from config.configs import *
import tensorflow as tf
import numpy as np

class DataLoader(object):
    """
    Load train and test dataset
    """

    def __init__(self, params):
        """
        Constructor of DataLoader
        :param params: all input parameters
        """
        self.params = params

        self.path_train_data = training_path.format(self.params.dataset)
        self.path_validation_data = None
        if self.params.validation:
            self.path_validation_data = validation_path.format(self.params.dataset)
        self.path_test_data = test_path.format(self.params.dataset)

        self.num_users, self.num_items = self.get_length()

        # train
        self.training_list = []
        self.load_list('train')

        # validation
        self.validation_list = []
        if self.params.validation:
            self.load_list('val')

        # test
        self.test_list = []
        self.load_list('test')

    def get_length(self):
        with open(dataset_info.format(self.params.dataset), 'r') as f:
            lines = f.readlines()
            for i, line in enumerate(lines):
                if i == 2:
                    us = int(line.split(': ')[1])
                if i == 3:
                    it = int(line.split(': ')[1])
                    break
        return us, it

    def load_list(self, train_val_test):
        # Get number of users and items
        u_ = 0
        items = []
        read_path = self.path_train_data if train_val_test == 'train' else self.path_validation_data if train_val_test == 'val' else self.path_test_data
        with open(read_path, "r") as f:
            line = f.readline()
            index = 0
            while line is not None and line != "":
                arr = line.split("\t")
                u, i = int(arr[0]), int(arr[1])
                if u_ < u:
                    index = 0
                    if train_val_test == 'train':
                        self.training_list.append(items)
                    elif train_val_test == 'val':
                        self.validation_list.append(items)
                    else:
                        self.test_list.append(items)
                    items = []
                    u_ += 1
                index += 1
                items.append(i)
                line = f.readline()
        if train_val_test == 'train':
            self.training_list.append(items)
        elif train_val_test == 'val':
            self.validation_list.append(items)
        else:
            self.test_list.append(items)

    def all_triple_batches(self):
        r_int = np.random.randint
        actual_used_samples = (self.num_users // self.params.batch_size) * self.params.batch_size
        user_input, pos_input, neg_input = [], [], []

        for ep in range(self.params.epochs):
            for ab in range(actual_used_samples):
                u = r_int(self.num_users)
                ui = set(self.training_list[u])
                lui = len(ui)
                if lui == self.num_items:
                    continue
                i = list(ui)[r_int(lui)]

                j = r_int(self.num_items)
                while j in ui:
                    j = r_int(self.num_items)
                user_input.append(np.array(u))
                pos_input.append(np.array(i))
                neg_input.append(np.array(j))

        return user_input, pos_input, neg_input,

    def next_triple_batch(self):
        all_triples = self.all_triple_batches()
        data = tf.data.Dataset.from_tensor_slices(all_triples)
        data = data.batch(batch_size=self.params.batch_size)
        data = data.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)

        return data

    def next_triple_batch_pipeline(self):
        def load_func(u, p, n):
            b = tf.py_function(
                self.read_triple,
                (u, p, n,),
                (np.int32, np.int32, np.int32)
            )
            return b

        all_triples = self.all_triple_batches()
        data = tf.data.Dataset.from_tensor_slices(all_triples)
        data = data.map(load_func, num_parallel_calls=tf.data.experimental.AUTOTUNE)
        data = data.batch(batch_size=self.params.batch_size)
        data = data.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)

        return data

    def read_triple(self, user, pos, neg):
        return user.numpy(), pos.numpy(), neg.numpy()


import sys
from PyQt5.QtWidgets import QDialog, QApplication
import DataCollectTool.RecToolUI as RecToolUI
import DataCollectTool.CommandRecord as rec
import _thread

FILE_PATH = ""
count = 1

class MyForm(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = RecToolUI.Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.record_button.clicked.connect(self.start_record)
        self.ui.reset_button.clicked.connect(self.reset)
        self.show()

    def start_record(self):
        global count, FILE_PATH
        path = self.ui.path_edit.text()
        if path != rec.PATH:
            rec.PATH = path
            FILE_PATH = rec.PATH + "/Names.txt"
            with open(FILE_PATH, 'r') as f:
                for line in f:
                    count += 1

        namefile = open(FILE_PATH, "a")
        name = self.ui.name_lineEdit.text()
        if name != rec.NAME:
            rec.NAME = name
            namefile.write(str(count) + ". " + name + "\n")
            count += 1
            # self.reset()

        rec.TIMES_NEEDED = self.ui.times_needed_spinbox.value()
        if rec.end:
            rec.end = False
            self.ui.record_button.setText("Dừng")
            rec.record()
            self.ui.record_button.setText("Ghi âm")
        else:
            rec.end = True
            self.ui.record_button.setText("Ghi âm")

    def reset(self):
        rec.TIMES_RECORDED = 0
        rec.CUR_COMMAND = 0
        rec.CUR_DIRECTORY = 0
        print("Reset")
        # self.ui.cur_command_label.setText("")
        # self.ui.cur_remain_label.setText(0)

    def show_command(self):
        self.ui.cur_command_label.setText(rec.COMMAND[rec.CUR_COMMAND])
        self.ui.cur_remain_label.setText(str(15 - rec.TIMES_RECORDED))

# if __name__ == "__main__":
#     app = QApplication(sys.argv)
#     w = MyForm()
#     w.show()
#     sys.exit(app.exec_())


#!/usr/bin/env python
#-------------------------------------------------------------------------------
# Name:
# Purpose:
# Version:      1.0
# Licence:      MIT Licence
# Author:       Jack Simpson
# Email:        jack.simpson@jacksimpson.co
# Created:      2015-02-24
#-------------------------------------------------------------------------------
# These modules are available in the Standard Library of Python
import os
# These modules come from third party libraries
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

import data_processing

def plot_num_frames_bees_tracked(df, output_directory):
    bees_frames = df[['BeeID', 'Frame']]
    split_by_id = bees_frames.groupby('BeeID',  sort=True)
    frames_bees_present = split_by_id.last() - split_by_id.first()

    plt.figure()
    plot_of_frames = frames_bees_present['Frame'].plot(kind='hist', alpha=0.5, bins=50)
    plt.xlabel("Number of frames")
    plt.ylabel("Number of bees")
    plt.title("Number of frames tracked: all bees")
    plt.savefig(output_directory + "1_number_frames_bees_tracked_all.png")
    plt.clf()
    plt.close()
    return plot_of_frames

def plot_num_bees_on_frame(df, output_directory):
    bees_frames = df[['BeeID', 'Frame']]
    number_of_bees_on_frame = bees_frames.groupby('Frame', sort=False).BeeID.nunique()

    plt.figure()
    plot_num_bees = number_of_bees_on_frame.plot(kind='hist', alpha=0.5)
    plt.xlabel("Number of bees")
    plt.ylabel("Number of frames")
    plt.title("Number of bees on a frame: all tags")
    plt.savefig(output_directory + "5_number_of_bees_on_frame_all.png")
    plt.clf()
    plt.close()
    return plot_num_bees

def num_bees_on_frame_split_by_tag(data, output_directory):
    num_bees_on_frame_by_type = { 0: [], 1: [], 2: [], 3: [] };

    grouped_bees_by_frame_tag = data.groupby(['Frame', 'Tag'])
    for group_id, df in grouped_bees_by_frame_tag:
        num_bees_on_frame_by_type[group_id[1]].append(len(df['BeeID']))

    plt.figure()
    plt.hist(num_bees_on_frame_by_type[0], range=(0,50), bins=50)
    plt.xlabel("Number of bees")
    plt.ylabel("Number of frames")
    plt.title("Number of bees on tag: tag 0")
    plt.savefig(output_directory + "6_number_of_bees_tag0_on_frame.png")
    plt.clf()
    plt.close()

    plt.figure()
    plt.hist(num_bees_on_frame_by_type[1], range=(0,50), bins=50)
    plt.xlabel("Number of bees")
    plt.ylabel("Number of frames")
    plt.title("Number of bees on tag: tag 1")
    plt.savefig(output_directory + "7_number_of_bees_tag1_on_frame.png")
    plt.clf()
    plt.close()

    plt.figure()
    plt.hist(num_bees_on_frame_by_type[2], range=(0,50), bins=50)
    plt.xlabel("Number of bees")
    plt.ylabel("Number of frames")
    plt.title("Number of bees on tag: tag 2")
    plt.savefig(output_directory + "8_number_of_bees_tag2_on_frame.png")
    plt.clf()
    plt.close()

    plt.figure()
    if len(num_bees_on_frame_by_type[3]):
        plt.hist(num_bees_on_frame_by_type[3], range=(0,50), bins=50)
    else:
        plt.hist([0,0,0], range=(0,50), bins=50)
    plt.xlabel("Number of bees")
    plt.ylabel("Number of frames")
    plt.title("Number of bees on tag: tag 3")
    plt.savefig(output_directory + "9_number_of_bees_tag3_on_frame.png")
    plt.clf()
    plt.close()

def frames_and_path_length_tracked_by_tag(bee_paths, output_directory):
    frames_bee_tracked = { 1: [], 2: [], 3: [] };
    path_length_tracked = { 1: [], 2: [], 3: [] };

    #print(len(bee_paths))

    for each_bee in bee_paths:
        frames_bee_tracked[each_bee.tag].append(len(each_bee.coords[0]))
        for each_path in each_bee.path_begin_end_frames:
            path_len = each_path[1] + 1 - each_path[0]
            path_length_tracked[each_bee.tag].append(path_len)

    #print(path_length_tracked)
    #print(frames_bee_tracked)

    p1 = np.percentile(path_length_tracked[1], 90)
    p2 = np.percentile(path_length_tracked[2], 90)
    #p3 = np.percentile(path_length_tracked[3], 90)

    plt.figure()
    plt.hist([x for x in path_length_tracked[1] if x < p1], bins=50)
    plt.xlabel("Number of frames")
    plt.ylabel("Number of bees")
    plt.title("Length of unbroken paths: tag 1")
    plt.savefig(output_directory + "10_length_tag1_path.png")
    plt.clf()
    plt.close()

    plt.figure()
    plt.hist([x for x in path_length_tracked[2] if x < p2], bins=50)
    plt.xlabel("Number of frames")
    plt.ylabel("Number of bees")
    plt.title("Length of unbroken paths: tag 2")
    plt.savefig(output_directory + "11_length_tag2_path.png")
    plt.clf()
    plt.close()

    try:
        plt.figure()
        plt.hist(path_length_tracked[3], bins=50, range=(0, 100000))
        plt.xlabel("Number of frames")
        plt.ylabel("Number of bees")
        plt.title("Length of unbroken paths: tag 3")
        plt.savefig(output_directory + "12_length_tag3_path.png")
        plt.clf()
        plt.close()
    except ValueError:
        plt.figure()
        plt.hist([0, 0, 0], bins=50, range=(0, 100000))
        plt.xlabel("Number of frames")
        plt.ylabel("Number of bees")
        plt.title("Length of unbroken paths: tag 3")
        plt.savefig(output_directory + "12_length_tag3_path.png")
        plt.clf()
        plt.close()

    p1 = np.percentile(frames_bee_tracked[1], 95)
    p2 = np.percentile(frames_bee_tracked[2], 95)
    #p3 = np.percentile(frames_bee_tracked[3], 95)

    with open(output_directory + "dumped.txt", "a") as myfile:
        myfile.write("\nBee Frame number for treatment: " + str(sum(frames_bee_tracked[1])))
        myfile.write("\nBee frame number for control: " + str(sum(frames_bee_tracked[2])))
        myfile.write("\nBee Frame number for queen: " + str(sum(frames_bee_tracked[3])))

    plt.figure()
    plt.hist(frames_bee_tracked[1], bins=36)
    #plt.hist([x for x in frames_bee_tracked[1] if x < 18000], range=(0, 18000), bins=36)
    plt.xlabel("Number of frames")
    plt.ylabel("Number of bees")
    plt.title("Frames bee tracked for: tag 1")
    plt.savefig(output_directory + "2_frames_tag1_tracked.png")
    plt.clf()
    plt.close()

    plt.figure()
    plt.hist(frames_bee_tracked[2], bins=36)
    plt.xlabel("Number of frames")
    plt.ylabel("Number of bees")
    plt.title("Frames bee tracked for: tag 2")
    plt.savefig(output_directory + "3_frames_tag2_tracked.png")
    plt.clf()
    plt.close()

    try:
        plt.figure()
        plt.hist(frames_bee_tracked[3], bins=36, range=(0, 100000))
        plt.xlabel("Number of frames")
        plt.ylabel("Number of bees")
        plt.title("Frames bee tracked for: tag 3")
        plt.savefig(output_directory + "4_frames_tag3_tracked.png")
        plt.clf()
        plt.close()
    except ValueError:
        plt.figure()
        plt.hist([0,0,0], bins=36, range=(0, 100000))
        plt.xlabel("Number of frames")
        plt.ylabel("Number of bees")
        plt.title("Frames bee tracked for: tag 3")
        plt.savefig(output_directory + "4_frames_tag3_tracked.png")
        plt.clf()
        plt.close()

    return 'done'

def tag_classify_confidence(data, output_directory):
    tag_classification_confidence = { 1: [], 2: [], 3: [] };
    tag_classification_time_tracked = { 1: [], 2: [], 3: [] };

    #min_frames_bee_visible = 100
    grouped_bees_by_id = data.groupby('BeeID',  sort=True)
    for group_id, df in grouped_bees_by_id:
        #if len(df['Frame']) < min_frames_bee_visible:
            #continue
        remove_zeroes = df[df.Tag > 0]
        if len(remove_zeroes['Tag']) < 10:
            continue
        tag_percentage = remove_zeroes['Tag'].value_counts().max() / len(remove_zeroes['Tag'])
        tag_identity = remove_zeroes['Tag'].value_counts().idxmax()
        tag_classification_confidence[tag_identity].append(tag_percentage)
        tag_classification_time_tracked[tag_identity].append(len(remove_zeroes['Tag']))

    plt.figure()
    plt.hist(tag_classification_confidence[1])
    plt.xlabel("Percent confidedence")
    plt.ylabel("Number of bees")
    plt.title("Classification confidence for: tag 1")
    plt.savefig(output_directory + "13_classified_confid_tag1.png")
    plt.clf()
    plt.close()

    plt.figure()
    plt.hist(tag_classification_confidence[2])
    plt.xlabel("Percent confidedence")
    plt.ylabel("Number of bees")
    plt.title("Classification confidence for: tag 2")
    plt.savefig(output_directory + "14_classified_confid_tag2.png")
    plt.clf()
    plt.close()

    try:
        plt.figure()
        plt.hist(tag_classification_confidence[3])
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence for: tag 3")
        plt.savefig(output_directory + "15_classified_confid_tag3.png")
        plt.clf()
        plt.close()
    except:
        plt.figure()
        plt.hist([0,0,0])
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence for: tag 3")
        plt.savefig(output_directory + "15_classified_confid_tag3.png")
        plt.clf()
        plt.close()

    return "done"

def tag_classify_confidence_with0(data, output_directory):
    tag_classification_confidence_with0 = { 0: [], 1: [], 2: [], 3: [] };
    tag_classification_time_tracked_with0 = { 0: [], 1: [], 2: [], 3: [] };

    grouped_bees_by_id_with0 = data.groupby('BeeID',  sort=True)
    for group_id, df in grouped_bees_by_id_with0:
        tag_percentage = df['Tag'].value_counts().max() / len(df['Tag'])
        #print (tag_percentage)
        #print(tag_identity)
        if len(df['Tag']) < 25:
            continue
        tag_identity = df['Tag'].value_counts().idxmax()
        tag_classification_confidence_with0[tag_identity].append(tag_percentage)
        tag_classification_time_tracked_with0[tag_identity].append(len(df['Tag']))

    #p0 = np.percentile(tag_classification_confidence_with0[0], 90)
    #p1 = np.percentile(tag_classification_confidence_with0[1], 90)
    #p2 = np.percentile(tag_classification_confidence_with0[2], 90)
    #p3 = np.percentile(tag_classification_confidence_with0[3], 90)

    plt.figure()
    plt.hist(tag_classification_confidence_with0[0], bins=50)
    #plt.hist([x for x in tag_classification_confidence_with0[0] if x < p0], bins=50)
    plt.xlabel("Percent confidedence")
    plt.ylabel("Number of bees")
    plt.title("Classification confidence including unknowns for: tag 0")
    plt.savefig(output_directory + "16_classified_confid_tag0_with0.png")
    plt.clf()
    plt.close()

    try:
        plt.figure()
        plt.hist(tag_classification_confidence_with0[1], bins=50)
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence including unknowns for: tag 1")
        plt.savefig(output_directory + "17_classified_confid_tag1_with0.png")
        plt.clf()
        plt.close()
    except:
        plt.figure()
        plt.hist([0,0,0], bins=50)
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence including unknowns for: tag 1")
        plt.savefig(output_directory + "17_classified_confid_tag1_with0.png")
        plt.clf()
        plt.close()

    try:
        plt.figure()
        plt.hist([x for x in tag_classification_confidence_with0[2] if x < p2], bins=50)
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence including unknowns for: tag 2")
        plt.savefig(output_directory + "18_classified_confid_tag2_with0.png")
        plt.clf()
        plt.close()
    except:
        plt.figure()
        plt.hist([0,0,0], bins=50)
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence including unknowns for: tag 2")
        plt.savefig(output_directory + "18_classified_confid_tag2_with0.png")
        plt.clf()
        plt.close()

    try:
        plt.figure()
        plt.hist(tag_classification_confidence_with0[3], bins=50)
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence including unknowns for: tag 3")
        plt.savefig(output_directory + "19_classified_confid_tag3_with0.png")
        plt.clf()
        plt.close()
    except:
        plt.figure()
        plt.hist([0,0,0], bins=50)
        plt.xlabel("Percent confidedence")
        plt.ylabel("Number of bees")
        plt.title("Classification confidence including unknowns for: tag 3")
        plt.savefig(output_directory + "19_classified_confid_tag3_with0.png")
        plt.clf()
        plt.close()

    return 'done'

def main():
    csv_directory = '/Users/u5305887/Desktop/drive_9_csv/'
    ordered_csv_files = data_processing.list_all_files(csv_directory)
    ordered_csv_files = ordered_csv_files
    for each_csv in ordered_csv_files:
        data = pd.read_csv(each_csv, comment='#', header = 0)
        filename = each_csv.split('/')[-1]
        base_file = os.path.splitext(filename)[0]
        print(base_file)
        output_dir = '/Users/u5305887/Desktop/output/qc2/' + base_file + '/'
        os.mkdir(output_dir)

        list_bees_current_csv = data_processing.analyse_bees_per_csv(data, output_dir, base_file)
        plot_num_frames_bees_tracked(data, output_dir)
        plot_num_bees_on_frame(data, output_dir)
        num_bees_on_frame_split_by_tag(data, output_dir)
        frames_and_path_length_tracked_by_tag(list_bees_current_csv, output_dir)
        tag_classify_confidence(data, output_dir)
        tag_classify_confidence_with0(data, output_dir)

if __name__ == "__main__":
    main()


#-*- coding: utf-8 -*-
"""myapp URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path, re_path

from django.views.generic import TemplateView

from . import views

urlpatterns = [
    path('', views.index, ),
    path('admin/', admin.site.urls),

    path('connection/', views.connection ),

    path('login/', views.login),

    # path('login/', TemplateView.as_view(template_name='login.html')),

    #http://localhost:8000/books/11299
    path('books/<int:number>/', views.books),

    #http://localhost:8000/art/2020/
    re_path(r'^art/(?P<year>[0-9]{4})/$', views.art),

    #http://localhost:8000/comment/page-1984/
    re_path(r'^comment/(?:page-(?P<id>\d+)/)?$', views.comment),

    path('test/', views.test, name='test'),

    path('hello/', views.hello, name='hello'),
]


from django.urls import path, include, re_path

# from .views import LoginView, LogoutView

from . import views

# this is the urls, with api prefix before
urlpatterns = [
    path('order/create/', views.ProductView.as_view(), name="home"),
    path('combo/create/', views.ComboCreateView.as_view()),
    path('combo/update/<int:number>', views.ComboUpdateView.as_view()),
    path('combo/delete/<int:number>', views.ComboDeleteView.as_view()),
    re_path(r'^combo/list/((?P<number>\d*)/?)$', views.ComboListView.as_view()),
]


from functools import partial
import numpy as np
from copy import deepcopy
import cv2
from utils_mudSlap import *
from utils_naturalPerturbations import addFog, addRain

'''
HELPER Functions
'''
def makeObservations(imgList, mode='multi', farScale = 0.5, obliquePercentage = 10, obliqueDirection = 'left'):
    """
    Changes all the images in the provided list according to the given parameters.
        imgList: [ndarray]
            List of all images to be altered; All images must be of same dimensions
        mode: string ('single' or 'multi')
            If 'multi': ignores other parameters and generate 28 new observations for
                        each image. 7 different oblique patterns each at 4 different
                        distances (including original image too)
            If 'single': create 1 observation for each image in the list according to
                         the specified parameters
        farScale: scalar (float) (0-1]
            Parameter defining the closeness of the new image (1=same, ~0=farthest)
        obliquePercentage: scalar (int) (0-45)
            Defines how much the image is to be tilted
        obliqueDirection: string ('left' or 'right')
            Specifies the direction of tilt
    """
    if (len(imgList.shape)==3): #Only one image is provided
        numImgs = 1
        imgRows = imgList.shape[0]
        imgCols = imgList.shape[1]
        nChannels = imgList.shape[2]
        imgList = [imgList]
    else:
        numImgs = imgList.shape[0]
        imgRows = imgList.shape[1]
        imgCols = imgList.shape[2]
        nChannels = imgList.shape[3]
    if mode=='multi':
        obliquePercentages = [20, 30]
        farScales = [1, 0.25]
        increaseFactor = ((2*len(obliquePercentages))+1)*len(farScales)
        newImgList = np.zeros((numImgs*increaseFactor, imgRows, imgCols, nChannels))
        i = 0
        for img in imgList:
            for fS in farScales:
                img1 = cv2.resize(img, (int(imgRows*fS), int(imgCols*fS)))
                img1 = cv2.resize(img1, (imgRows, imgCols))
                img1 = cv2.GaussianBlur(img1, (5,5), 0)
                newImgList[i, ...] = img1
                i+=1
            for oP in obliquePercentages:
                for fS in farScales:
                    #For Left Oblique
                    XobliquePixels = oP*imgRows/100
                    YobliquePixels = 0.75*XobliquePixels
                    src = np.array([
                            [0, 0],
                            [imgRows - 1, 0],
                            [imgRows - 1, imgCols - 1],
                            [0, imgCols - 1]
                            ], dtype = "float32")
                    dst = np.array([
                            [XobliquePixels, YobliquePixels],
                            [imgRows - XobliquePixels - 1, 0],
                            [imgRows - XobliquePixels - 1, imgCols - 1],
                            [XobliquePixels, imgCols - YobliquePixels - 1]
                            ], dtype = "float32")
                    # compute the perspective transform matrix and then apply it
                    M = cv2.getPerspectiveTransform(src, dst)
                    warped = cv2.warpPerspective(img, M, (imgRows, imgCols))
                    #warped = warped[:, int(XobliquePixels):int(imgRows - XobliquePixels - 1)]
                    warped = warped[int(oP*YobliquePixels/100):int(imgCols - (oP*YobliquePixels/100) - 1),
                                int(XobliquePixels):int(imgRows - XobliquePixels - 1)]
                    warped = cv2.resize(warped, (imgRows, imgCols))
                    img1 = cv2.resize(warped, (int(imgRows*fS), int(imgCols*fS)))
                    img1 = cv2.resize(img1, (imgRows, imgCols))
                    img1 = cv2.GaussianBlur(img1, (5,5), 0)
                    newImgList[i, ...] = img1
                    i+=1
                    #For Right Oblique
                    XobliquePixels = oP*imgRows/100
                    YobliquePixels = 0.75*XobliquePixels
                    src = np.array([
                            [0, 0],
                            [imgRows - 1, 0],
                            [imgRows - 1, imgCols - 1],
                            [0, imgCols - 1]
                            ], dtype = "float32")
                    dst = np.array([
                            [XobliquePixels, 0],
                            [imgRows - XobliquePixels - 1, YobliquePixels],
                            [imgRows - XobliquePixels - 1, imgCols - YobliquePixels - 1],
                            [XobliquePixels, imgCols - 1]
                            ], dtype = "float32")
                    # compute the perspective transform matrix and then apply it
                    M = cv2.getPerspectiveTransform(src, dst)
                    warped = cv2.warpPerspective(img, M, (imgRows, imgCols))
                    warped = warped[int(oP*YobliquePixels/100):int(imgCols - (oP*YobliquePixels/100) - 1),
                                int(XobliquePixels):int(imgRows - XobliquePixels - 1)]
                    warped = cv2.resize(warped, (imgRows, imgCols))
                    img1 = cv2.resize(warped, (int(imgRows*fS), int(imgCols*fS)))
                    img1 = cv2.resize(img1, (imgRows, imgCols))
                    img1 = cv2.GaussianBlur(img1, (5,5), 0)
                    newImgList[i, ...] = img1
                    i+=1
    else:
        newImgList = np.zeros((numImgs, imgRows, imgCols, nChannels))
        increaseFactor = 1
        i = 0
        for img in imgList:
            XobliquePixels = obliquePercentage*imgRows/100
            YobliquePixels = 0.75*XobliquePixels
            if obliqueDirection=='left' or obliqueDirection == 'Left':
                src = np.array([
                    [0, 0],
                    [imgRows - 1, 0],
                    [imgRows - 1, imgCols - 1],
                    [0, imgCols - 1]
                    ], dtype = "float32")
                dst = np.array([
                    [XobliquePixels, YobliquePixels],
                    [imgRows - XobliquePixels - 1, 0],
                    [imgRows - XobliquePixels - 1, imgCols - 1],
                    [XobliquePixels, imgCols - YobliquePixels - 1]
                    ], dtype = "float32")
            else:
                src = np.array([
                    [0, 0],
                    [imgRows - 1, 0],
                    [imgRows - 1, imgCols - 1],
                    [0, imgCols - 1]
                    ], dtype = "float32")
                dst = np.array([
                    [XobliquePixels, 0],
                    [imgRows - XobliquePixels - 1, YobliquePixels],
                    [imgRows - XobliquePixels - 1, imgCols - YobliquePixels - 1],
                    [XobliquePixels, imgCols - 1]
                    ], dtype = "float32")
            # compute the perspective transform matrix and then apply it
            M = cv2.getPerspectiveTransform(src, dst)
            warped = cv2.warpPerspective(img, M, (imgRows, imgCols))
            warped = warped[int(obliquePercentage*YobliquePixels/100):int(imgCols - (obliquePercentage*YobliquePixels/100) - 1),
                        int(XobliquePixels):int(imgRows - XobliquePixels - 1)]
            warped = cv2.resize(warped, (imgRows, imgCols))
            img1 = cv2.resize(warped, (int(imgRows*farScale), int(imgCols*farScale)))
            img1 = cv2.resize(img1, (imgRows, imgCols))
            img1 = cv2.GaussianBlur(img1, (5,5), 0)
            newImgList[i, ...] = img1
            i+=1
    return newImgList, increaseFactor

def alterImages(imageList, alterFeatures = None, withRain = True):
    """
    Given a feature vector of alterations (as described below), alters a set of
    images accordingly

    Arguments:
    -----------
        imageList: np.ndarray (numImages, Width, Height, numChannels)
            List of images on which alterations are required to be added
        alterFeatures: List [<mudSplat1>, <mudSplat2>, <mudSplat3>, <rain>, <fog>]
            List of features to explain modifications in the order as defined above.
            Further explanations of each component as follows:
                <mudSplat1> : [mudSpaltObject]
                <mudSplat2> : [mudSpaltObject]
                <mudSplat3> : [mudSpaltObject]
                <rain>      : [randomSeed, rainy]
                <fog>       : [fogIntensity, randomSeed]
        withRain: boolean
            If False, will ignore the rain features
    Returns:
    -----------
        outImgs: np.ndarray (numImages, Width, Height, numChannels)
            The list of transformed output images with 'alterFeatures' effects
    """
    if len(imageList.shape)==3:
        imageList = np.expand_dims(imageList, axis=0)
    numImgs = imageList.shape[0]
    W = imageList.shape[1]
    H = imageList.shape[2]
    nCh = imageList.shape[3]
    if alterFeatures is not None:
        mudObj1  = alterFeatures[0]
        mudObj2  = alterFeatures[1]
        mudObj3  = alterFeatures[2]
        rainSeed = alterFeatures[3]
        rainExt  = alterFeatures[4]
        fogInten = alterFeatures[5]
        fogSeed  = alterFeatures[6]

        if mudObj1.scale>0 and mudObj2.scale>0 and mudObj3.scale>0:
            allSplatImg = combineSplats([mudObj1]+[mudObj2]+[mudObj3], W, H).astype('uint8')
            allSplatImg[:,:,:-1][allSplatImg[:,:,:-1]==0] = 255
            splatImgs = np.zeros(imageList.shape)
            for i, image in enumerate(imageList):
                splatImgs[i, ...] = addMudSplat(image, allSplatImg)
        elif mudObj1.scale>0 and mudObj2.scale>0:
            allSplatImg = combineSplats([mudObj1]+[mudObj2], W, H).astype('uint8')
            allSplatImg[:,:,:-1][allSplatImg[:,:,:-1]==0] = 255
            splatImgs = np.zeros(imageList.shape)
            for i, image in enumerate(imageList):
                splatImgs[i, ...] = addMudSplat(image, allSplatImg)
        elif mudObj1.scale>0:
            allSplatImg = combineSplats([mudObj1], W, H).astype('uint8')
            allSplatImg[:,:,:-1][allSplatImg[:,:,:-1]==0] = 255
            splatImgs = np.zeros(imageList.shape)
            for i, image in enumerate(imageList):
                splatImgs[i, ...] = addMudSplat(image, allSplatImg)
        else:
            splatImgs = deepcopy(imageList).astype("float64")
        if np.ceil(rainExt)>0 and withRain and np.ceil(fogInten)>0:
            outImgs = addRain(addFog(splatImgs, fogInten, int(fogSeed)), int(rainSeed))
        elif np.ceil(rainExt)>0 and withRain:
            outImgs = addRain(splatImgs, int(rainSeed))
        elif np.ceil(fogInten)>0:
            outImgs = addFog(splatImgs, fogInten, int(fogSeed))
        else:
            outImgs = splatImgs
    else:
        outImgs = imageList
    return outImgs

def predictModel_Nparticles(originalImages, originalClass, targetClass,
                         model, alterFeatures = None):
    """
    Adds a mud splat on the original image according to the specified feature
    vector and then predict its class using the trained model.

    Arguments:
    -----------
        originalImages: np.ndarray (numImages, Width, Height, numChannels)
            List of original images (without any perturbations)
        originalClass: scalar (int) {0,1,2}
            Original Class label specified as follows:
                turnLeft: 0
                turnRight: 1
                goStraight: 2
        targetClass: scalar (int) {0,1,2}
            Target Class (aiming to misclassify) label specified as follows:
                turnLeft: 0
                turnRight: 1
                goStraight: 2
        trainedModelWeightsPath: Keras Model Object
            Previously Trained Model Object
        alterFeatures: List [[<mudSplat1>, <mudSplat2>, <mudSplat3>, <rain>, <fog>]]
            List of list of features to explain modifications in the order as defined above.
            **Must be either of length 1 or equal to the number of originalImages or None.
            Further explanations of each component as follows:
                <mudSplat1> : [mudSpaltObject]
                <mudSplat2> : [mudSpaltObject]
                <mudSplat3> : [mudSpaltObject]
                <rain>      : [randomSeed]
                <fog>       : [fogIntensity, randomSeed]
    Returns:
    -----------
        predScore: Classify predictions w.r.t. original and target classes and
            give score according to the following scheme:
                2   : if predicted class == original class (correct prediction)
                0   : if predicted class == target class (incorrect prediction -
                                                          target matched)
                1   : if predicted class == any other class (incorrect prediction -
                                                             target mismatched)
            The scores for all images are then added to produce final score
        predOutput: list of predictions
            The transformed output image with mud-splat on it
    """
    print("Starting to alter images...")
    if len(originalImages.shape)==3:
        originalImages = np.expand_dims(originalImages, axis=0)
    numImgs = originalImages.shape[0]
    W = originalImages.shape[1]
    H = originalImages.shape[2]
    nCh = originalImages.shape[3]

    if alterFeatures is None:
        raise Exception('alterFeatures not provided for any particle')
    else:
        numFinImages = numImgs*len(alterFeatures)
        finImages = np.zeros((numFinImages, W, H, nCh))
        for n, feature in enumerate(alterFeatures):
            finImages[n*numImgs:(n+1)*numImgs, ...] = alterImages(originalImages, feature, False)
        print("Alteration process is success. Proceeding to making observations.")
        finImages, increaseFactor = makeObservations(finImages)
        numImgs = numImgs*increaseFactor
        for n, feature in enumerate(alterFeatures):
            if np.ceil(feature[4])>0:
                finImages[n*numImgs:(n+1)*numImgs, ...] = addRain(finImages[n*numImgs:(n+1)*numImgs, ...].astype("float64"), int(feature[3]))
        finImages = np.uint8(finImages)
        print("Made observations successfully. Proceeding to model predictions.")
        predOutput = model.predict(finImages)

    predScore = np.zeros(len(alterFeatures))
    for n in range(len(alterFeatures)):
        for outputs in predOutput[n*numImgs:(n+1)*numImgs]:
            if np.any(np.argmax(outputs) == originalClass):
                predScore[n] += 2
            elif np.any(np.argmax(outputs) == targetClass):
                predScore[n] += 0
            else:
                predScore[n] += 1
    print("Predictions made and scores calculated. Returning handle back to PSO.")
    print("For reference, scores are:")
    print(predScore)
    return predScore, predOutput
'''
def  predictModelMudSplat_Nparticles(originalImages, originalClass, targetClass,
                         model, mudSplatObjects = None):
    """
    Adds a mud splat on the original image according to the specified feature
    vector and then predict its class using the trained model.

    Arguments:
    -----------
        originalImages: np.ndarray
            Original Image (without any perturbations)
        originalClass: scalar (int) {0,1,2}
            Original Class label specified as follows:
                turnLeft: 0
                turnRight: 1
                goStraight: 2
        targetClass: scalar (int) {0,1,2}
            Target Class (aiming to misclassify) label specified as follows:
                turnLeft: 0
                turnRight: 1
                goStraight: 2
        trainedModelWeightsPath: Keras Model Object
            Previously Trained Model Object
        mudSplatObjects: Array of mud-splat objects
            Explains the features of all mud-splats.
            (If None: Predict the class and correctness of original image.)
    Returns:
    -----------
        predScore: Classify predictions w.r.t. original and target classes and
            give score according to the following scheme:
                2   : if predicted class == original class (correct prediction)
                0   : if predicted class == target class (incorrect prediction -
                                                          target matched)
                1   : if predicted class == any other class (incorrect prediction -
                                                             target mismatched)
            The scores for all images are then added to produce final score
        predOutput: list of predictions
            The transformed output image with mud-splat on it
    """
    print("Here")
    newImages = deepcopy(originalImages)
    if len(newImages.shape) == 3:   # Only 1 image is provided
        newImages = np.expand_dims(newImages, axis=0)
    if mudSplatObjects is not None:
        numSplattedImages = newImages.shape[0]*len(mudSplatObjects)
        splattedImages = np.zeros(np.append(numSplattedImages,newImages.shape[1:]))
        print(len(mudSplatObjects))
        print(len(newImages))
        for n, mudSplatObj in enumerate(mudSplatObjects):
            mudSplat = cv2.imread(mudSplatObj.imgPath, cv2.IMREAD_UNCHANGED)
            for i, img in enumerate(newImages):
                splattedImages[n*len(newImages)+i,...] = addMudSplat(img, mudSplat, mudSplatObj.xOffset,
                                                                    mudSplatObj.yOffset, mudSplatObj.scale,
                                                                    mudSplatObj.rotate)
        predOutput = model.predict(splattedImages)
    else:
        predOutput = model.predict(newImages)
    print("Here Again!")
    predScore = np.zeros(len(mudSplatObjects))
    for n in range(len(mudSplatObjects)):
        for outputs in predOutput[n*len(newImages):(n+1)*len(newImages)]:
            if np.any(np.argmax(outputs) == originalClass):
                predScore[n] += 2
            elif np.any(np.argmax(outputs) == targetClass):
                predScore[n] += 0
            else:
                predScore[n] += 1
    print("Here Too")
    print(predScore)
    return predScore, predOutput
'''
def _obj_wrapper(func, args, kwargs, x):
    return func(x, *args, **kwargs)

def _is_feasible_wrapper(func, x):
    return np.all(func(x)>=0)

def _cons_none_wrapper(x):
    return np.array([0])

def _cons_ieqcons_wrapper(ieqcons, args, kwargs, x):
    return np.array([y(x, *args, **kwargs) for y in ieqcons])

def _cons_f_ieqcons_wrapper(f_ieqcons, args, kwargs, x):
    return np.array(f_ieqcons(x, *args, **kwargs))

def pso(func, lb, ub, ieqcons=[], f_ieqcons=None, args=(), kwargs={},
        swarmsize=100, omega=0.5, phip=0.5, phig=0.5, maxiter=100,
        minstep=1e-8, minfunc=1e-8, debug=False, processes=1,
        particle_output=False, abs_min=None):
    """
    Perform a particle swarm optimization (PSO)

    Parameters
    ==========
    func : function
        The function to be minimized
    lb : array
        The lower bounds of the design variable(s)
    ub : array
        The upper bounds of the design variable(s)

    Optional
    ========
    ieqcons : list
        A list of functions of length n such that ieqcons[j](x,*args) >= 0.0 in
        a successfully optimized problem (Default: [])
    f_ieqcons : function
        Returns a 1-D array in which each element must be greater or equal
        to 0.0 in a successfully optimized problem. If f_ieqcons is specified,
        ieqcons is ignored (Default: None)
    args : tuple
        Additional arguments passed to objective and constraint functions
        (Default: empty tuple)
    kwargs : dict
        Additional keyword arguments passed to objective and constraint
        functions (Default: empty dict)
    swarmsize : int
        The number of particles in the swarm (Default: 100)
    omega : scalar
        Particle velocity scaling factor (Default: 0.5)
    phip : scalar
        Scaling factor to search away from the particle's best known position
        (Default: 0.5)
    phig : scalar
        Scaling factor to search away from the swarm's best known position
        (Default: 0.5)
    maxiter : int
        The maximum number of iterations for the swarm to search (Default: 100)
    minstep : scalar
        The minimum stepsize of swarm's best position before the search
        terminates (Default: 1e-8)
    minfunc : scalar
        The minimum change of swarm's best objective value before the search
        terminates (Default: 1e-8)
    debug : boolean
        If True, progress statements will be displayed every iteration
        (Default: False)
    processes : int
        The number of processes to use to evaluate objective function and
        constraints (default: 1)
    particle_output : boolean
        Whether to include the best per-particle position and the objective
        values at those.
    abs_min : int
        If 'abs_min' is given, iterations will terminate if the value of PSO
        objective function falls below or equal to this number

    Returns
    =======
    g : array
        The swarm's best known position (optimal design)
    f : scalar
        The objective value at ``g``
    p : array
        The best known position per particle
    pf: arrray
        The objective values at each position in p

    """

    assert len(lb)==len(ub), 'Lower- and upper-bounds must be the same length'
    assert hasattr(func, '__call__'), 'Invalid function handle'
    lb = np.array(lb)
    ub = np.array(ub)
    assert np.all(ub>=lb), 'All upper-bound values must be greater than or equal to lower-bound values'

    vhigh = np.abs(ub - lb)
    vlow = -vhigh

    # Initialize objective function
    obj = partial(_obj_wrapper, func, args, kwargs)

    # Check for constraint function(s) #########################################
    if f_ieqcons is None:
        if not len(ieqcons):
            if debug:
                print('No constraints given.')
            cons = _cons_none_wrapper
        else:
            if debug:
                print('Converting ieqcons to a single constraint function')
            cons = partial(_cons_ieqcons_wrapper, ieqcons, args, kwargs)
    else:
        if debug:
            print('Single constraint function given in f_ieqcons')
        cons = partial(_cons_f_ieqcons_wrapper, f_ieqcons, args, kwargs)
    is_feasible = partial(_is_feasible_wrapper, cons)

    # Initialize the multiprocessing module if necessary
    if processes > 1:
        import multiprocessing
        mp_pool = multiprocessing.Pool(processes)

    # Initialize the particle swarm ############################################
    S = swarmsize
    D = len(lb)  # the number of dimensions each particle has
    x = np.random.rand(S, D)  # particle positions
    v = np.zeros_like(x)  # particle velocities
    p = np.zeros_like(x)  # best particle positions
    fx = np.zeros(S)  # current particle function values
    fs = np.zeros(S, dtype=bool)  # feasibility of each particle
    fp = np.ones(S)*np.inf  # best particle function values
    g = []  # best swarm position
    fg = np.inf  # best swarm position starting value

    # Initialize the particle's position
    x = lb + x*(ub - lb)
    #x[-1,:] = [25, 50, 40, 220, 55, 20, 30, 150, 60, 40, 20, 90, 0, 0, 0, 0]
    x[:,2] = ub[2]
    x[:,6] = ub[6]
    x[:,10]= ub[10]
    x[-1,14]= ub[14]

    # Calculate objective and constraints for each particle
    if processes > 1:
        fx = np.array(mp_pool.map(obj, x))
        fs = np.array(mp_pool.map(is_feasible, x))
    else:
        imgData, oriClass, tarClass, mudImgPath, model = args
        allFeatures = []
        for i in range(S):
            mudSplatObject1 = mudSplat(mudImgPath, int(x[i,0]), int(x[i,1]), x[i,2], x[i,3])
            mudSplatObject2 = mudSplat(mudImgPath, int(x[i,4]), int(x[i,5]), x[i,6], x[i,7])
            mudSplatObject3 = mudSplat(mudImgPath, int(x[i,8]), int(x[i,9]), x[i,10], x[i,11])
            rainFeatures    = [int(x[i,12]), np.ceil(x[i,13])]
            fogFeatures     = [x[i,14], int(x[i,15])]
            allFeatures.append([mudSplatObject1] + [mudSplatObject2] + [mudSplatObject3] + rainFeatures + fogFeatures)
        fx = predictModel_Nparticles(imgData, oriClass, tarClass, model, allFeatures)[0]

        for i in range(S):
            #fx[i] = obj(x[i, :])
            fs[i] = is_feasible(x[i, :])

    # Store particle's best position (if constraints are satisfied)
    i_update = np.logical_and((fx < fp), fs)
    p[i_update, :] = x[i_update, :].copy()
    fp[i_update] = fx[i_update]

    # Update swarm's best position
    i_min = np.argmin(fp)
    if fp[i_min] < fg:
        fg = fp[i_min]
        g = p[i_min, :].copy()
    else:
        # At the start, there may not be any feasible starting point, so just
        # give it a temporary "best" point since it's likely to change
        g = x[0, :].copy()

    # Initialize the particle's velocity
    v = vlow + np.random.rand(S, D)*(vhigh - vlow)

    # Iterate until termination criterion met ##################################
    fg_history = []
    fg_history.append(fg)
    it = 1
    while it <= maxiter:
        rp = np.random.uniform(size=(S, D))
        rg = np.random.uniform(size=(S, D))

        # Update the particles velocities
        v = omega*v + phip*rp*(p - x) + phig*rg*(g - x)

        # Update the particles' positions
        x = x + v

        # Correct for bound violations
        maskl = x < lb
        masku = x > ub
        x = x*(~np.logical_or(maskl, masku)) + lb*maskl + ub*masku

        # Update objectives and constraints
        if processes > 1:
            fx = np.array(mp_pool.map(obj, x))
            fs = np.array(mp_pool.map(is_feasible, x))
        else:
            imgData, oriClass, tarClass, mudImgPath, model = args
            allFeatures = []
            for i in range(S):
                X = deepcopy(x[i,:])
                mudSplatObject1 = mudSplat(mudImgPath, int(X[0]), int(X[1]), X[2], X[3])
                mudSplatObject2 = mudSplat(mudImgPath, int(X[4]), int(X[5]), X[6], X[7])
                mudSplatObject3 = mudSplat(mudImgPath, int(X[8]), int(X[9]), X[10], X[11])
                rainFeatures    = [int(X[12]), np.ceil(X[13])]
                fogFeatures     = [X[14], int(X[15])]
                allFeatures.append([mudSplatObject1] + [mudSplatObject2] + [mudSplatObject3] + rainFeatures + fogFeatures)
            fx = predictModel_Nparticles(imgData, oriClass, tarClass, model, allFeatures)[0]

            for i in range(S):
                #fx[i] = obj(x[i, :])
                fs[i] = is_feasible(x[i, :])

        # Store particle's best position (if constraints are satisfied)
        i_update = np.logical_and((fx < fp), fs)
        p[i_update, :] = x[i_update, :].copy()
        fp[i_update] = fx[i_update]

        # Compare swarm's best position with global best position
        i_min = np.argmin(fp)
        if fp[i_min] < fg:
            if debug:
                print('New best for swarm at iteration {:}: {:} {:}'\
                    .format(it, p[i_min, :], fp[i_min]))

            p_min = p[i_min, :].copy()
            stepsize = np.sqrt(np.sum((g - p_min)**2))

            if np.abs(fg - fp[i_min]) <= minfunc:
                print('Stopping search: Swarm best objective change less than {:}'\
                    .format(minfunc))
                if particle_output:
                    return p_min, fp[i_min], fg_history, p, fp
                else:
                    return p_min, fp[i_min], fg_history
            elif stepsize <= minstep:
                print('Stopping search: Swarm best position change less than {:}'\
                    .format(minstep))
                if particle_output:
                    return p_min, fp[i_min], fg_history, p, fp
                else:
                    return p_min, fp[i_min], fg_history
            else:
                g = p_min.copy()
                fg = fp[i_min]

        if fg<=abs_min:
            print('Stopping search: Swarm best position change less than or equal to given absolute minima{:}'\
                .format(abs_min))
            if debug:
                print('Best after iteration {:}: {:} {:}'.format(it, g, fg))
            if particle_output:
                return g, fg, fg_history, p, fp
            else:
                return g, fg, fg_history
        if debug:
            print('Best after iteration {:}: {:} {:}'.format(it, g, fg))
        fg_history.append(fg)
        it += 1

    print('Stopping search: maximum iterations reached --> {:}'.format(maxiter))

    if not is_feasible(g):
        print("However, the optimization couldn't find a feasible design. Sorry")
    if particle_output:
        return g, fg, fg_history, p, fp
    else:
        return g, fg, fg_history


# coding: utf-8

# https://gist.github.com/lukaskollmer/962625208f872c242706

# Load Twitter profile pictures and set them as image to your iOS contacts

# https://forum.omz-software.com/topic/2736/share-code-update-ios-contact-images-with-twitter-profile-pictures

import twitter
import json
import urllib
import contacts
import console
from objc_util import *
import ui
import os
from PIL import Image
import webbrowser

console.clear()

CNContactStore = ObjCClass('CNContactStore')
CNContact = ObjCClass('CNContact')
CNSaveRequest = ObjCClass('CNSaveRequest')
UIActivityIndicatorView = ObjCClass('UIActivityIndicatorView')

activity_indicator = None
twitter_contacts = []
current_contact_index = -1
did_present = False
store = CNContactStore.alloc().init()

view = ui.load_view()
all_view_element_names = [
	'contact_name_label',
	'old_image_title_label',
	'new_image_title_label',
	'left_image_view',
	'right_image_view',
	'keep_image_button',
	'use_new_image_button',
	'progress_view_container'
]

def setup_view():
	view['left_image_view'].content_mode = ui.CONTENT_SCALE_ASPECT_FIT
	view['right_image_view'].content_mode = ui.CONTENT_SCALE_ASPECT_FIT

	view['keep_image_button'].action = keep_current_image
	view['use_new_image_button'].action = use_twitter_image
class NoTwitterAccountSetUpError(Exception):
	pass

class LoadTwitterProfilePictureError(Exception):
	def __init__(self, status_code):
		self.status_code = status_code

		def __str__():
			return 'Could not retrieve profile image (status: %i)' % (self.status_code,)

class Contact(object):
	def __init__(self, name, twitter_username, has_image, current_image, twitter_image):
		self.name = name
		self.twitter_username = twitter_username
		self.has_image = has_image
		self.current_image = current_image
		self.twitter_image = twitter_image

	def __str__(self):
		return 'Contact {} (@{})'.format(self.name, self.twitter_username)

def show_message_in_image_view(message, image_view):
	if len(image_view.subviews) > 0: # already a message subview
		for subview in image_view.subviews:
			if type(subview) is ui.Label:
				subview.text = message
	else:
		label = ui.Label()
		label.frame = image_view.frame
		label.text = message
		label.text_color = 0.4
		label.center = ((image_view.width / 2), (image_view.height / 2))
		label.alignment = ui.ALIGN_CENTER
		image_view.add_subview(label)

def profile_picture_for_account(username):
	all_accounts = twitter.get_all_accounts()
	if len(all_accounts) >= 1:
		account = all_accounts[0]
		parameters = {'screen_name': username}
		status, data = twitter.request(account, 'https://api.twitter.com/1.1/users/show.json', 'GET', parameters)
		if status == 200:
			user_info = json.loads(data)
			avatar_url = user_info['profile_image_url']
			# Get the URL for the original size:
			avatar_url = avatar_url.replace('_normal', '')
			filename, headers = urllib.urlretrieve(avatar_url)
			img = Image.open(filename)
			format = img.format.lower()
			path = os.path.expanduser('~/Documents/{}.{}'.format(username, format))
			img.save(path, format=format)
			image = ui.Image.named(path)
			os.remove(path)
			return image
		else:
			raise LoadTwitterProfilePictureError(status)
	else:
		raise NoTwitterAccountSetUpError('You don\'t have any Twitter accounts (or haven\'t given permission to access them).')

def addressBook_account_with_name(name):
	predicate = CNContact.predicateForContactsMatchingName_(name)
	keys_to_fetch = ['identifier', 'givenName', 'familyName', 'imageDataAvailable', 'imageData']

	result = store.unifiedContactsMatchingPredicate_keysToFetch_error_(predicate, keys_to_fetch, None)[0]

	return result

def load_contacts_with_twitter():
	contacts_with_twitter = []
	all_people = contacts.get_all_people()
	for person in all_people:
		view['currently_loading_info_label'].text = 'Loading image for {}'.format(person.full_name)
		social = person.social_profile
		if social:
			for service in social:
				if service[1]['service'] == 'twitter':
					twitter_username = service[1]['username']
					should_dismiss_view_because_no_account_error = False
					try:
						twitter_image = profile_picture_for_account(twitter_username)
					except LoadTwitterProfilePictureError as error:
						twitter_image = None
					except NoTwitterAccountSetUpError as error:
						twitter_image = None
						should_dismiss_view_because_no_account_error = True
						if console.alert(error.message, button1='open settings') == 1:
							webbrowser.open('app-settings://')
						view.close()
					finally:
						if should_dismiss_view_because_no_account_error == True:
							view.close()
					image = None
					result = addressBook_account_with_name(person.full_name)
					has_image = result.imageDataAvailable()
					if has_image == True:
						data = NSData.dataWithData_(result.imageData())
						image = UIImage.imageWithData_(data)
					contacts_with_twitter.append(Contact(person.full_name, twitter_username, has_image, image, twitter_image))
	return contacts_with_twitter

def update_contact_with_name_set_new_image(name, image):
	contact = addressBook_account_with_name(name).mutableCopy()
	image_data = bytearray(image.to_png())
	contact.imageData = image_data
	save_resuest = CNSaveRequest.new()
	save_resuest.updateContact_(contact)
	store.executeSaveRequest_error_(save_resuest, None)

def current_contact():
	if current_contact_index <= len(twitter_contacts):
		return twitter_contacts[current_contact_index]
	else:
		return None

def show_next_contact():
	global current_contact_index
	current_contact_index = current_contact_index + 1
	if current_contact_index >= len(twitter_contacts):
		view.close()
		return
	contact = current_contact()
	view['contact_name_label'].text = contact.name
	if contact.current_image is None:
		left_message = 'No image set'
	else:
		left_message = ''
	show_message_in_image_view(left_message, view['left_image_view'])
	ObjCInstance(view['left_image_view']).image = contact.current_image
	if contact.twitter_image is None:
		right_message = 'Unable to load image'
	else:
		right_message = ''
	show_message_in_image_view(right_message, view['right_image_view'])
	view['right_image_view'].image = contact.twitter_image
	view['use_new_image_button'].enabled = not contact.twitter_image == None

def keep_current_image(sender):
	show_next_contact()

def use_twitter_image(sender):
	contact = current_contact()
	name = contact.name
	new_image = view['right_image_view'].image
	update_contact_with_name_set_new_image(name, new_image)
	show_next_contact()

def set_all_views_hidden(hidden):
	for element in all_view_element_names:
		view[element].hidden = hidden

@on_main_thread
def show_ui(loading):
	global did_present
	global activity_indicator
	if did_present == False:
		try:
			view.present('sheet')
			did_present = True
		except:
			pass
	set_all_views_hidden(loading)
	if loading:
		activity_indicator = UIActivityIndicatorView.alloc().initWithActivityIndicatorStyle_(2) #2= grey style
		activity_indicator.startAnimating()
		activity_indicator_container = ObjCInstance(view['progress_view_container'])
		activity_indicator.center = activity_indicator_container.convertPoint_fromView_(activity_indicator_container.center(), activity_indicator_container.superview())
		activity_indicator_container.addSubview_(activity_indicator)
	else:
		activity_indicator.stopAnimating()
		show_next_contact()
	view['progress_view_container'].hidden = not loading
	view['currently_loading_info_label'].hidden = not loading

if __name__ == '__main__':
	setup_view()
	show_ui(loading=True)
	twitter_contacts = load_contacts_with_twitter()
	show_ui(loading=False)

contacts/Add Twitter Profile Picture to iOS Contacts.py


import numpy as np
import pygame

class Board:
    def __init__(self):
        # colors
        self.white = (255, 255, 255)
        self.black = (0, 0, 0)
        self.gray = (50, 50, 50)
        self.red = (255, 0, 0)
        self.yellow = (255, 255, 0)

        # self
        self.rows = 6
        self.columns = 7

        # create empty self
        self.board = self.create_board()

        # square size of the screen
        self.square_size = 100
        # piece radius of the screen
        self.radius = int(self.square_size / 2 - 5)

        # height and width of the screen
        self.width = self.columns * self.square_size
        self.height = (self.rows + 1) * self.square_size

        # size of the screen
        self.size = (self.width, self.height)

        # set screen for the game
        self.screen = pygame.display.set_mode(self.size)

    # create board with zeros
    def create_board(self):
        board = np.zeros((self.rows, self.columns))
        return board

    # place the piece on board
    def place_piece(self, row, column, piece):
        self.board[row][column] = piece

    # check if the place for piece empty
    def is_empty(self, column):
        if self.board[self.rows - 1][column] == 0:
            return True
        else:
            return False

    def get_next_row(self, column):
        for row in range(self.rows):
            if self.board[row][column] == 0:
                return row

    def print_board(self):
        print('--- STATE ---')
        printer = np.flip(self.board.copy(), 0)
        for i in range(self.rows):
            for j in range(self.columns):
                if int(printer[i][j]) == 1:
                    print('R ', end='')
                elif int(printer[i][j]) == 2:
                    print('Y ', end='')
                else:
                    print('0 ', end='')
            print()
        print()

    def get_valid_locations(self):
        valid_locations = []
        for column in range(self.columns):
            if self.board[self.rows - 1][column] == 0:
                valid_locations.append(column)
        return valid_locations

    def check_win(self, piece):
        # Check horizontal locations for win
        for column in range(self.columns - 3):
            for row in range(self.rows):
                if (self.board[row][column] == piece
                        and self.board[row][column + 1] == piece
                        and self.board[row][column + 2] == piece
                        and self.board[row][column + 3] == piece):
                    return True

        # Check vertical locations for win
        for column in range(self.columns):
            for row in range(self.rows - 3):
                if (self.board[row][column] == piece
                        and self.board[row + 1][column] == piece
                        and self.board[row + 2][column] == piece
                        and self.board[row + 3][column] == piece):
                    return True

        # Check positively sloped diagonals
        for column in range(self.columns - 3):
            for row in range(self.rows - 3):
                if (self.board[row][column] == piece
                        and self.board[row + 1][column + 1] == piece
                        and self.board[row + 2][column + 2] == piece
                        and self.board[row + 3][column + 3] == piece):
                    return True

        # Check negatively sloped diagonals
        for column in range(self.columns - 3):
            for row in range(3, self.rows):
                if (self.board[row][column] == piece
                        and self.board[row - 1][column + 1] == piece
                        and self.board[row - 2][column + 2] == piece
                        and self.board[row - 3][column + 3] == piece):
                    return True
        #return False

    def draw_board(self, player_1, player_2):
        for column in range(self.columns):
            for row in range(self.rows):
                pygame.draw.rect(self.screen, self.white, (
                    column * self.square_size, row * self.square_size + self.square_size, self.square_size,
                    self.square_size))
                pygame.draw.circle(self.screen, self.gray, (
                    int(column * self.square_size + self.square_size / 2),
                    int(row * self.square_size + self.square_size + self.square_size / 2)), self.radius)

        for column in range(self.columns):
            for row in range(self.rows):
                if self.board[row][column] == player_1:
                    pygame.draw.circle(
                        self.screen,
                        self.red,
                        (
                            int(column * self.square_size + self.square_size / 2),
                            self.height - int(row * self.square_size + self.square_size / 2)
                        ),
                        self.radius
                    )
                elif self.board[row][column] == player_2:
                    pygame.draw.circle(
                        self.screen,
                        self.yellow,
                        (
                            int(column * self.square_size + self.square_size / 2),
                            self.height - int(row * self.square_size + self.square_size / 2)
                        ),
                        self.radius
                    )
        pygame.display.update()


#!/usr/bin/env python3
import json
from itertools import groupby

from brushfire.client import brushfire
from churchsuite.client import churchsuite

def cs_to_brushfire_form_value(bf_field, cs_attendee_data):
    """
    Return the correct Value for Brushfire from Churchsuite
    1. I need to match the key in cs_attendee_data with something in the bf_field
    2. This depends on the type of the field.
    3. Based on the Type I need to know 2 things - how to match, how to set the value
    """
    field_type_match = {
        "Email": lambda a, bf: a["email"],
        "Name": lambda a, bf: a["last_name"]
        if "Last" in bf["Label"]
        else a["first_name"],
        "Phone": lambda a, bf: a["mobile"],
        "Dropdown": lambda a, bf: [
            o for o in bf["Options"] if o["Label"] == a["church"]
        ],
        "Text": lambda a, bf: a["other"],
    }
    return field_type_match[bf_field["Type"]](cs_attendee_data, bf_field)

def checkout_on_brushfire(event_id, attendees):
    cart_id = brushfire.cart_id()
    cart_data = brushfire.add_attendee_to_cart(
        cart_id, event_id, attendees["cart_input"]
    )
    # print(brushfire.get_event_signups(event_id))
    for idx, attendee in enumerate(cart_data["EventCart"]["Items"]):
        form = brushfire.get_attendee_form(cart_id, event_id, attendee["AttendeeId"])
        fields = form.get("Fields")
        form_values = []
        cs_attendee = attendees["attendee_input"][idx]
        for field in fields:
            form_values.append(
                {
                    "Id": field["Id"],
                    "Value": cs_to_brushfire_form_value(field, cs_attendee),
                }
            )
        brushfire.add_attendee_form(
            cart_id, event_id, attendee["AttendeeId"], form_values
        )

    data = brushfire.create_order_from_cart(
        {
            "CartId": cart_id,
            "BillingFirstName": "The C3",
            "BillingLastName": "Church",
            "BillingStreet1": "C3 Centre, Coldhams Lane",
            "BillingCity": "Cambridge",
            "BillingRegion": "Cambridgeshire",
            "BillingCountry": "GB",
            "BillingPostalCode": "CB1 3HR",
            "ContactPhone": "01223 844415",
            "ShippingBillingSame": True,
            "PaidInFull": True,
            "SendEmail": False,
            "PaymentMethodId": "00000000-0000-0000-0000-000000000004",
        }
    )
    # return data

def get_orders_from_churchsuite(event_id):
    return churchsuite.get_event_signups(event_id)

def translate_order(orders, event_id, type_id):

    for _order_id, order in groupby(orders, lambda o: o["batch_id"]):
        order_list = list(order)
        yield {
            "cart_input": {
                "EventId": event_id,
                "TypeId": type_id,
                "Amount": 0 * len(order_list),
                "SelectedAmount": 0 * len(order_list),
                "Quantity": len(order_list),
                "IsPreRegistered": True,
            },
            "attendee_input": [
                {
                    "email": attendee["person"]["email"],
                    "first_name": attendee["person"]["first_name"],
                    "last_name": attendee["person"]["last_name"],
                    "mobile": attendee["person"]["mobile"],
                    "church": attendee["question_responses"]["104"]["value"],
                    "other": attendee["question_responses"]["102"]["value"],
                }
                for attendee in order_list
            ],
        }

def main():
    churchsuite_event_id = "384"
    brushfire_event_id = "466168"
    brushfire_attentee_type_id = "5d220886-e25a-4b36-8f96-8bee2f9f7671"
    orders = get_orders_from_churchsuite(churchsuite_event_id)

    for order in translate_order(
        orders, brushfire_event_id, brushfire_attentee_type_id
    ):
        checkout_on_brushfire(brushfire_event_id, order)
    print(brushfire.get_event_signups(brushfire_event_id))

if __name__ == "__main__":
    main()


from __future__ import print_function

import argparse
import sys

from s3pypi import __prog__
from s3pypi.exceptions import S3PyPiError
from s3pypi.package import Package
from s3pypi.storage import S3Storage

__author__ = 'Matteo De Wint'
__copyright__ = 'Copyright 2016, November Five'
__license__ = 'MIT'

def create_and_upload_package(args):
    package = Package.create(args.wheel, args.sdist)
    storage = S3Storage(args.bucket, args.secret, args.region, args.bare, args.private, args.profile)

    index = storage.get_index(package)
    index.add_package(package, args.force)

    storage.put_package(package)
    storage.put_index(package, index)

def parse_args(raw_args):
    p = argparse.ArgumentParser(prog=__prog__)
    p.add_argument('--bucket', required=True, help='S3 bucket')
    p.add_argument('--secret', help='S3 secret')
    p.add_argument('--region', help='AWS region')
    p.add_argument('--profile', help='AWS profile')
    p.add_argument('--force', action='store_true', help='Overwrite existing packages')
    p.add_argument('--no-wheel', dest='wheel', action='store_false', help='Skip wheel distribution')
    p.add_argument('--no-sdist', dest='sdist', action='store_false', help='Skip sdist distribution')
    p.add_argument('--bare', action='store_true', help='Store index as bare package name')
    p.add_argument('--private', action='store_true', help='Store S3 Keys as private objects')
    return p.parse_args(raw_args)

def main():
    args = parse_args(sys.argv[1:])

    try:
        create_and_upload_package(args)
    except S3PyPiError as e:
        print('error: %s' % e)
        sys.exit(1)

if __name__ == '__main__':
    main()


import random

grid = {
    'tl': ' ', 'tm': ' ', 'tr': ' ',
    'ml': ' ', 'mm': ' ', 'mr': ' ',
    'll': ' ', 'lm': ' ', 'lr': ' '
}

presentation_grid = {
    'tl': 'tl', 'tm': 'tm', 'tr': 'tr',
    'ml': 'ml', 'mm': 'mm', 'mr': 'mr',
    'll': 'll', 'lm': 'lm', 'lr': 'lr'
}

# picked_arr_items = list(range(len(grid)))

def get_grid(grid):
    print(grid['tl'] + '|' + grid['tm'] + '|' + grid['tr'])
    print('-+-+-')
    print(grid['ml'] + '|' + grid['mm'] + '|' + grid['mr'])
    print('-+-+-')
    print(grid['ll'] + '|' + grid['lm'] + '|' + grid['lr'])
    print('#' * 7)

get_grid(presentation_grid)

def random_add(grid):
    points = ['tl', 'tm', 'tr', 'ml', 'mm', 'mr', 'll', 'lm', 'lr']
    while True:
        rand_index = random.randint(0, len(points) - 1)
        if grid[points[rand_index]] == 'X':
            continue
        else:
            grid[points[random.randint(0, len(points))]] = '0'
            break
    get_grid(grid)

for trial in range(5):
    user_coord = input('Add to: ')
    if user_coord == 'e':
        break
    user_item = input('Add to: ')
    if user_item != 'X':
        print('X only!')
        exit()
    try:
        if grid[user_coord] == ' ':
            grid[user_coord] = user_item[0]
        else:
            print('I need \'X\'value')
            continue
    except KeyError:
        print('I need something like: tm, tr, mr...')
        continue
    get_grid(grid)
    random_add(grid)


from flask import Flask, Blueprint, jsonify, redirect
from flask_restx import Api as RestX_Api
from os import getenv
from ecom.commands import ecom_cli
import pymysql
from ecom import extensions
from ecom.ping.v1 import ping_api_v1
from ecom.category.v1 import category_api_v1
from ecom.product.v1 import product_api_v1
from ecom.design.models import Category, Product, CategoryToProductMap

api_blueprint = Blueprint("api", __name__, url_prefix="/api")

authorizations = {
    "JWT Token Authentication": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "key": "Bearer xxxx",
    }
}

rest_api = RestX_Api(
    api_blueprint,
    title="ECOM",
    version="1.0.0",
    description="Swagger UI / API specs for ECOM application",
    authorizations=authorizations,
)

rest_api.add_namespace(ping_api_v1, path="/v1")
rest_api.add_namespace(category_api_v1, path="/v1")
rest_api.add_namespace(product_api_v1, path="/v1")

# mysql driver required for sqlalchemy
pymysql.install_as_MySQLdb()

def create_app():
    """Create the flask app and intialize all the extensions"""

    # flask app
    app = Flask(__name__)

    print("App Created..")

    # register blueprint with application
    app.register_blueprint(api_blueprint)

    # load env specific configs
    app.config.from_object(get_config_object_path())
    print(app.config["SQLALCHEMY_DATABASE_URI"])

    # initialize all extensions
    extensions.init_extensions(app)

    app.cli.add_command(ecom_cli)

    # 404 route handler
    @app.errorhandler(404)
    def route_not_present(err):
        return (
            jsonify(
                {
                    "success": False,
                    "error": {"errorCode": err.code, "message": err.description},
                }
            ),
            404,
        )

    # redirect the root to /api for easy access of swagger docs for devs
    @app.route("/")
    def redirect_to_swagger_spec():
        return redirect("/api")

    @app.shell_context_processor
    def shell_context():  # pylint: disable=unused-variable # pragma: no cover
        """The app.shell_context_processor decorator registers the function as a shell context function.
        When the `flask shell` command runs, it will invoke this function
        and register the items returned by it in the shell session.
        """
        return {"db": extensions.db}

    return app

def get_config_object_path() -> str:
    """reads `FLASK_ENV` from OS and returns string that can be used with app.config.from_object.
    If `FLASK_ENV` not set in OS, returns `ipdo.config.DevelopmentConfig`

    Returns:
        str: one of 'ipdo.config.DevelopmentConfig', 'ipdo.config.TestingConfig', 'ipdo.config.ProductionConfig'
    """
    try:
        dev_config = "ecom.config.DevelopmentConfig"
        test_config = "ecom.config.TestingConfig"
        prod_config = "ecom.config.ProductionConfig"

        env = getenv("FLASK_ENV")
        environment_configuration = dev_config

        if env in ["development", "extdev", "dev", "demo"]:
            environment_configuration = dev_config
        elif env == "testing":
            environment_configuration = test_config
        elif env in ["production", "prod", "stage"]:
            environment_configuration = prod_config
    except Exception:
        # logging.error(
        #     "Failed to load FLASK_ENV in application factory. Loading Dev environment configs."
        # )
        environment_configuration = dev_config

    return environment_configuration


import pytest
import numpy as np
import astropy.units as u
from ..ionization_states import IonizationState
from plasmapy.utils import AtomicError, RunTestError, InvalidIsotopeError, run_test
from plasmapy.atomic import (
    atomic_number,
    mass_number,
    atomic_symbol,
    isotope_symbol,
    Particle,
)
import collections
import warnings

test_cases = {
    'Li': {
        'particle': 'Li',
        'ionic_fractions': np.array([0.4, 0.3, 0.2, 0.1]),
        'tol': 1e-15,
    },

    'Li ground state': {
        'particle': 'Li',
        'ionic_fractions': np.array([1, 0, 0, 0], dtype=np.int64),
        'tol': 1e-15,
    },

    'H': {
        'particle': 'H',
        'ionic_fractions': [0.6, 0.4],
        'tol': 1e-8,
    },

    'H acceptable error': {
        'particle': 'H',
        'ionic_fractions': [0.6, 0.400_000_001],
        'tol': 1e-8,
    },

    'D': {
        'particle': 'deuterium',
        'ionic_fractions': [0.7, 0.3],
        'tol': 1e-15,
        'n_e': 3e14 * u.m ** -3,
    },

    'He': {
        'particle': 'He',
        'ionic_fractions': [0.5, 0.3, 0.2],
        'n_elem': 1e20 * u.m ** -3,
    },

    'number densities': {
        'particle': 'T',
        'ionic_fractions': np.array([1e4, 1]) * u.cm ** -3,
    }

}

test_names = test_cases.keys()

class Test_IonizationState:
    """Test instances of IonizationState."""

    @classmethod
    def setup_class(cls):
        cls.instances = {}

    @pytest.mark.parametrize('test_name', test_names)
    def test_instantiation(self, test_name):
        try:
            self.instances[test_name] = IonizationState(**test_cases[test_name])
        except Exception as exc:
            raise RunTestError(
                f"Unable to create IonizationState instance for "
                f"test case {test_name}.")

    @pytest.mark.parametrize(
        'test_name',
        [name for name in test_names if 'ionic_fractions' in test_cases[name].keys()],
    )
    def test_ionic_fractions(self, test_name):
        instance = self.instances[test_name]

        inputted_fractions = test_cases[test_name]['ionic_fractions']
        if isinstance(inputted_fractions, u.Quantity):
            inputted_fractions = inputted_fractions.to(u.m ** -3)
            inputted_fractions = (inputted_fractions / inputted_fractions.sum()).value

        try:
            assert np.allclose(instance.ionic_fractions, inputted_fractions)
        except:
            raise RunTestError(f"Mismatch in ionic fractions for test {test_name}")

    def test_equality1(self):
        assert self.instances['Li'] == self.instances['Li'], \
            "Identical IonizationState instances are not equal."

    def test_equality2(self):
        assert self.instances['H'] == self.instances['H acceptable error'], \
            ("Two IonizationState instances that are approximately the "
             "same to within the tolerance are not testing as equal.")

    def test_inequality(self):
        """
        Test that instances with different ionic fractions are not equal
        to each other.
        """
        assert self.instances['Li ground state'] != self.instances['Li'], \
            "Different IonizationState instances are equal."

    def test_equality_error(self):
        """
        Test that comparisons of IonizationState instances for
        different elements fail.
        """
        with pytest.raises(AtomicError):
            self.instances['Li'] == self.instances['H']

    @pytest.mark.parametrize('test_name', test_names)
    def test_iteration(self, test_name: str):
        """Test that IonizationState instances iterate impeccably."""
        try:
            states = [state for state in self.instances[test_name]]
        except Exception:
            raise AtomicError(
                f"Unable to perform iteration for {test_name}.")

        try:
            integer_charges = [state.integer_charge for state in states]
            ionic_fractions = np.array([state.ionic_fraction for state in states])
            ionic_symbols = [state.ionic_symbol for state in states]
        except Exception:
            raise AtomicError("An attribute may be misnamed or missing.")

        try:
            base_symbol = isotope_symbol(ionic_symbols[0])
        except InvalidIsotopeError:
            base_symbol = atomic_symbol(ionic_symbols[0])
        finally:
            atomic_numb = atomic_number(ionic_symbols[1])

        errors = []

        expected_charges = np.arange(atomic_numb + 1)
        if not np.all(integer_charges == expected_charges):
            errors.append(
                f"The resulting integer charges are {integer_charges}, "
                f"which are not equal to the expected integer charges, "
                f"which are {expected_charges}.")

        expected_fracs = test_cases[test_name]['ionic_fractions']
        if isinstance(expected_fracs, u.Quantity):
            expected_fracs = (expected_fracs / expected_fracs.sum()).value

        if not np.allclose(ionic_fractions, expected_fracs):
            errors.append(
                f"The resulting ionic fractions are {ionic_fractions}, "
                f"which are not equal to the expected ionic fractions "
                f"of {expected_fracs}.")

        expected_particles = [Particle(base_symbol, Z=charge) for charge in integer_charges]
        expected_symbols = [particle.ionic_symbol for particle in expected_particles]
        if not ionic_symbols == expected_symbols:
            errors.append(
                f"The resulting ionic symbols are {ionic_symbols}, "
                f"which are not equal to the expected ionic symbols of "
                f"{expected_symbols}.")

        if errors:
            errors.insert(0, (
                f"The test of IonizationState named '{test_name}' has "
                f"resulted in the following errors when attempting to "
                f"iterate."))
            errmsg = " ".join(errors)
            raise AtomicError(errmsg)

    def test_slicing_error(self):
        with pytest.raises(TypeError):
            self.instances['Li'][1:3]

    @pytest.mark.parametrize('index', [-1, 4, 'Li'])
    def test_indexing_error(self, index):
        with pytest.raises(AtomicError):
            self.instances['Li'][index]

    def test_normalization(self):
        H = self.instances['H acceptable error']
        assert not H.is_normalized(tol=1e-15)
        H.normalize()
        assert H.is_normalized(tol=1e-15)

    @pytest.mark.parametrize('test_name', test_names)
    def test_identifications(self, test_name):
        """
        Test that the identification attributes for test IonizationState
        instances match the expected values from the Particle instance.
        """

        Identifications = collections.namedtuple(
            "Identifications",
            ["element", "isotope", "base_particle", "atomic_number"],
        )

        expected_identifications = Identifications(
            self.instances[test_name].element,
            self.instances[test_name].isotope,
            self.instances[test_name].base_particle,
            self.instances[test_name].atomic_number,
        )

        expected_element = self.instances[test_name]._particle.element
        expected_isotope = self.instances[test_name]._particle.isotope
        expected_atomic_number = self.instances[test_name]._particle.atomic_number

        resulting_identifications = Identifications(
            expected_element,
            expected_isotope,
            expected_isotope if expected_isotope else expected_element,
            expected_atomic_number,
        )

        assert resulting_identifications == expected_identifications, (
            f"For IonizationState test {test_name}, the resulting "
            f"identifications of {resulting_identifications} differ "
            f"from the expected identifications of "
            f"{expected_identifications}."
        )

    @pytest.mark.parametrize('tol', [-1e-16, 1.0000001])
    def test_invalid_tolerances(self, tol):
        """Test that invalid tolerances raise appropriate errors."""
        test_name = "Li"
        instance = self.instances[test_name]
        with pytest.raises(ValueError):
            instance.tol = tol

    @pytest.mark.parametrize('test_name', test_cases.keys())
    def test_particles(self, test_name):
        """
        Test that IonizationState returns the correct Particle
        instances.
        """
        instance = self.instances[test_name]
        base_particle = instance.base_particle
        nstates = instance.atomic_number + 1
        expected_particles = [Particle(base_particle, Z=Z) for Z in range(nstates)]
        assert expected_particles == instance.particles, (
            f"The expected Particle instances of {expected_particles} "
            f"are not all equal to the IonizationState particles of "
            f"{instance.particles} for test {test_name}."
        )

    def test_electron_density_from_n_elem_ionic_fractions(self):
        test_name = 'He'
        instance = self.instances[test_name]
        n_elem = test_cases[test_name]['n_elem']
        ionic_fractions = test_cases[test_name]['ionic_fractions']
        assert instance.n_elem == n_elem, \
            f"n_elem is not being stored correctly for test {test_name}"
        assert np.isclose(
            instance.n_e,
            np.sum(n_elem * ionic_fractions * np.array([0, 1, 2])),
            rtol=1e-12, atol=0 * u.m ** -3), \
            "n_e is not the expected value."

IE = collections.namedtuple("IE", ["inputs", "expected_exception"])

tests_for_exceptions = {
    'too few nstates': IE({'particle': 'H', 'ionic_fractions': [1.0]}, AtomicError),
    'too many nstates': IE({'particle': 'H', 'ionic_fractions': [1, 0, 0, 0]}, AtomicError),

    'redundant ndens 1': IE({
        'particle': 'H', 'ionic_fractions': np.array([3, 4]) * u.m ** -3, 'n_e': 4 * u.m ** -3,
    }, AtomicError),

    'redundant ndens 2': IE({
        'particle': 'H', 'ionic_fractions': np.array([3, 4]) * u.m ** -3, 'n_elem': 7 * u.m ** -3,
    }, AtomicError),
}

@pytest.mark.parametrize('test', tests_for_exceptions.keys())
def test_execeptions(test):
    """
    Test that appropriate exceptions are raised for inappropriate inputs
    to IonizationStates.
    """
    run_test(
        IonizationState,
        kwargs=tests_for_exceptions[test].inputs,
        expected_outcome=tests_for_exceptions[test].expected_exception,
    )


import logging
from pydblite.pydblite import Base

logger = logging.getLogger()

class ZipcodeDB(object):
    PYDBLITE_DB_FILE = './zipcode.db'

    def __init__(self,pydblite_db_file=None):
        if pydblite_db_file is None:
            pydblite_db_file = ZipcodeDB.PYDBLITE_DB_FILE
        try:
            self._db = Base(pydblite_db_file)
            self._db.open()
        except Exception:
            self._db = None

    def query_by_zip_code(self, zip_cd):
        logger.debug("**************** entering ZipcodeDB.query_zipcode_db_by_zip_code")
        record = {} # Empty dict if not found
        if self._db is not None:
            records = self._db(zip_cd=zip_cd)
            if len(records)==1:
                record = records[0]
        return record

    def get_timezone_for_zip_code(self, zip_code):
        logger.debug("**************** entering ZipcodeDB.get_timezone")

        ret_val = 'NoTZ/'+zip_code
        data = self.query_by_zip_code(zip_code)
        if data:
            # timezone is really just an offset
            timezone = data['data']['timezone']
            dst = data['data']['dst']
            tz_dic = {'-5+1':'US/Eastern', '-5+0':'US/East-Indiana', '-6+1':'US/Central', '-7+1':'US/Mountain',
                      '-7+0':'US/Arizona', '-8+1':'US/Pacific', '-9+1':'US/Alaska', '-10+0':'US/Hawaii',
                      '-10+1':'US/Aleutian'}
            key=timezone+'+'+dst
            if key in tz_dic:
                ret_val = tz_dic[key]

        return ret_val


#!/usr/bin/python
# encoding: utf-8

"""
@author: 大圣
@contact: excelchart@sina.cn
@file: knnclassfier.py
@time: 2016/1/19 0019 下午 2:46
"""

from dataminer.baseClassifier.baseClassifier import BaseClassifier
from dataminer.mltools.stats.distance import Distance
import operator
class KNNClassifier(BaseClassifier):
    def __init__(self,traingfilesname,fieldsrols,delimiter,k=10):
        super(KNNClassifier,self).__init__(traingfilesname,fieldsrols,delimiter)
        self.k=k

    def _findNearestNeighbor(self,item):
        neighbors=[]
        for idx,onerecord in enumerate(self._data['prop']):
            distance=Distance.computeManhattanDistance(onerecord,item)
            neighbors.append([idx,distance,self._data['class'][idx]])

        neighbors.sort(key=lambda x:x[1])

        nearestk={}
        for i in range(self.k):
            nearestk.setdefault(neighbors[i][2],0)
            nearestk[neighbors[i][2]]+=1

        return nearestk

    def predicate(self,item):
        nearestk=self._findNearestNeighbor(item)
        ps=sorted(nearestk.items(),key=lambda x:x[1],reverse=True)
        return ps[0][0]


from agent_dir.agent import Agent
from agent_dir.model import Net, CNN2

import scipy.misc
import numpy as np
import matplotlib.pyplot as plt

import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
from torch.distributions import Bernoulli, Categorical

import time
import random
from itertools import count

torch.manual_seed(22)
USE_CUDA = torch.cuda.is_available()
# USE_CUDA = False

def prepro(o,image_size=[80,80]):
    """
    Call this function to preprocess RGB image to grayscale image if necessary
    This preprocessing code is from
        https://github.com/hiwonjoon/tf-a3c-gpu/blob/master/async_agent.py

    Input:
    RGB image: np.array
        RGB screen of game, shape: (210, 160, 3)
    Default return: np.array
        Grayscale image, shape: (80, 80, 1)

    """
    #############
    # toast add #
    #############
    o = o[35:190, :, :]     # remove the score board
    y = 0.2126 * o[:, :, 0] + 0.7152 * o[:, :, 1] + 0.0722 * o[:, :, 2]

    #############
    # toast end #
    #############
    y = y.astype(np.uint8)
    resized = scipy.misc.imresize(y, image_size)
    return np.expand_dims(resized.astype(np.float32),axis=2)/255.

class Agent_PG(Agent):
    def __init__(self, env, args):
        """
        Initialize every things you need here.
        For example: building your model
        """

        super(Agent_PG,self).__init__(env)

        ##################
        # YOUR CODE HERE #
        ##################

        # environment
        self.env = env.env

        # args
        self.gamma = args.gamma
        self.episode = args.episode
        self.batch_size = args.batch_size
        self.render = args.render
        self.save_state = None
        # initialize model
        self.model = CNN2()
        if USE_CUDA:
            self.model = self.model.cuda()

        # optimizer
        self.optimizer = optim.RMSprop(params=self.model.parameters(), lr=args.learning_rate)

        if args.test_pg or args.pretrain:
            #you can load your model here
            print('loading trained model -- cnn2')
            self.model.load_state_dict(torch.load('model/pg_model.pth'))
            # self.model.eval()

    def init_game_setting(self):
        """

        Testing function will call this function at the begining of new game
        Put anything you want to initialize if necessary

        """
        ##################
        # YOUR CODE HERE #
        ##################
        torch.manual_seed(1)

    def train(self):
        """
        Implement your training algorithm here
        """
        ##################
        # YOUR CODE HERE #
        ##################

        self.model.train()

        # memory
        state_pool = []
        action_pool = []
        reward_pool = []
        prob_pool = []
        log_prob_pool = []
        # for observation
        # frame_pool = []

        for episode in range(self.episode):
            # print('episode: ', episode)
            # setup
            state = self.env.reset()
            state = prepro(state)
            state = torch.FloatTensor(state)
            state = Variable(state).cuda() if USE_CUDA else Variable(state)

            new_state = state
            save_state = state

            # start playing
            while True:
                if self.render:
                    self.env.render()

                dif_state = new_state - save_state
                # plt.imshow(dif_state.cpu().data.numpy()[:, :, 0], cmap='gray')
                # plt.colorbar()
                # plt.show()
                save_state = new_state
                prob = self.model(dif_state)
                # if len(frame_pool) <= 150:
                #     frame_pool.append(dif_state.cpu().data.numpy())
                prob_pool.append(prob.cpu().data.numpy())
                m = Categorical(prob)

                # memorize!
                state_pool.append(dif_state)

                # take action
                # 1-> do nothing, 2->up, 3->down
                # action = int(prob.topk(1)[1]) + 1

                # print('episode: ', episode)
                # print(prob)
                action = m.sample() + 1

                ######
                # test
                ######
                log_prob_pool.append(m.log_prob(action-1))
                ######
                # test
                ######
                action_pool.append(action)

                if USE_CUDA:
                    action = action.cpu().data.numpy().astype(int)[0]
                else:
                    action = action.data.numpy().astype(int)[0]

                # action = random.sample([1, 2, 3], 1)

                state, reward, done, info = self.env.step(action)
                state = prepro(state)
                state = torch.FloatTensor(state)
                state = Variable(state).cuda() if USE_CUDA else Variable(state)
                new_state = state
                # memorize!
                reward_pool.append(reward)

                # if terminated
                if done:
                    break

            if episode > 0 and episode % self.batch_size == 0:
                # print('update policy..')
                # update network (policy)
                # Discount reward
                running_add = 0.
                # print(reward_pool[-5:])

                avg_reward = np.sum(reward_pool)/self.batch_size
                print("episode: %d | average reward: %.2f" % (episode, avg_reward))
                with open('reward_log_cnn2.csv', 'a+') as log:
                    log.write('%d,%f\n' % (episode, avg_reward))

                for i in reversed(range(len(state_pool))):
                    if reward_pool[i] == 1 or reward_pool[i] == -1:
                        running_add = reward_pool[i]
                    else:
                        running_add = running_add * self.gamma + reward_pool[i]
                        reward_pool[i] = running_add
                        # print(running_add)

                # Normalize reward
                # reward_mean = np.mean(reward_pool)
                # reward_std = np.std(reward_pool)

                # for i in range(len(state_pool)):
                #     reward_pool[i] = (reward_pool[i] - reward_mean) / reward_std

                # print(reward_pool[-5:])
                # plt.plot(np.arange(len(reward_pool)), reward_pool)
                # plt.xlabel('frame')
                # plt.ylabel('reward')
                # plt.title('moving average reward')
                # plt.show()
                # assert False
                # optimize!
                self.optimizer.zero_grad()
                # loss = 0
                for i in range(len(state_pool)):
                    state = state_pool[i]
                    # action = action_pool[i]
                    # action = int(action)

                    # action = Variable(torch.FloatTensor([action_pool[i]]))
                    # action = action.cuda() if USE_CUDA else action

                    reward = reward_pool[i]

                    # prob = self.model(state)
                    # m = Bernoulli(prob[action_pool[i] - 1])
                    # m = Categorical(prob)
                    # loss += -m.log_prob(action) * reward
                    # loss += -torch.log(prob[action-1]) * (reward - reward_mean) # substract baseline (arbitrary)
                    # loss = -torch.log(prob[action-1]) * reward # substract baseline (arbitrary)

                    loss = -log_prob_pool[i] * reward
                    loss.backward()

                # loss /= len(state_pool)
                # loss.backward()
                self.optimizer.step()

                ###############
                # observe the std of probability of each action
                # (does the network really react to different frame?)
                #
                # print("the std of each action over an episode:")
                # print(np.asarray(prob_pool).std(0))
                # plt.plot(np.arange(len(prob_pool)), np.asarray(prob_pool).T[0], label='none')
                # plt.plot(np.arange(len(prob_pool)), np.asarray(prob_pool).T[1], label='up')
                # plt.plot(np.arange(len(prob_pool)), np.asarray(prob_pool).T[2], label='down')
                plt.plot(np.arange(150), np.asarray(prob_pool[:150]).T[0], label='none')
                plt.plot(np.arange(150), np.asarray(prob_pool[:150]).T[1], label='up')
                plt.plot(np.arange(150), np.asarray(prob_pool[:150]).T[2], label='down')
                plt.xlabel('t')
                plt.ylabel('probability')
                plt.title('std of none: %.4f, up: %.4f, down: %.4f' % (np.asarray(prob_pool).std(0)[0], np.asarray(prob_pool).std(0)[1], np.asarray(prob_pool).std(0)[2]))
                plt.legend()
                plt.savefig('plot/std_cnn2.png')
                plt.close()

                ###########
                # observe
                ###########
                # for idx, frame in enumerate(frame_pool):
                #     plt.imshow(frame[:, :, 0])
                #     plt.savefig('plot/frames/frame%d.png' % idx)
                #     plt.close()

                # clear memory!
                state_pool = []
                action_pool = []
                reward_pool = []
                prob_pool = []
                log_prob_pool = []
                # frame_pool = []
                # assert False

                torch.save(self.model.state_dict(), 'model/pg_model_cnn2.pth')

    def make_action(self, observation, test=True):
        """
        Return predicted action of your agent

        Input:
            observation: np.array
                current RGB screen of game, shape: (210, 160, 3)

        Return:
            action: int
                the predicted action from trained model
        """
        ##################
        # YOUR CODE HERE #
        ##################
        observation = prepro(observation)
        observation = torch.FloatTensor(observation)
        observation = Variable(observation).cuda() if USE_CUDA else Variable(observation)

        if self.save_state is None:
            self.save_state = observation
        dif_state = observation - self.save_state
        self.save_state = observation

        prob = self.model(dif_state)
        # action = int(action.topk(1)[1]) + 1
        m = Categorical(prob)

        action =  m.sample() + 1
        if USE_CUDA:
            action = action.cpu().data.numpy().astype(int)[0]
        else:
            action = action.data.numpy().astype(int)[0]

        return action
        # return self.env.get_random_action()