import numpy as np
from sklearn.metrics import mean_squared_error

def get_model_params(rating_df):
    """Transform rating data into (sparse) matrix and gather data necessary for item-based CF.

        Arguments:
            rating_df -- DataFrame storing rating data. cols - 'userID', 'movieID', 'rating'
            replace_mean -- (optional) boolean deciding whether to replace all missing ratings with the average rating
                of the user.

        Returns:
            model_params -- dictionary containing the following
                A - 2D numpy array in which each row represents the vector of ratings for a movie and each column
                    represents a vector of ratings from a user (rows are movies and columns are users). Hence, the
                    matrix has # movies rows and # users columns.
                userID_hash - dictionary (hash table) mapping userID to column index in A.
                movieID_hash - dictionary (hash table) mapping movieID to row index in A.
                user_rated_dict - dictionary mapping hashed values of userID (column index) the list of movies they
                    rated (list of hashed values of movieIDs (row index)).
                avg_user_rating_arr - np array containing the average rating of each user. Index i corresponds to column
                    index of a user.
                movie_rated_by_dict -- dict mapping movie_row index to list of user_cols that have rated movie_row.
                avg_movie_rating_arr -- np array of average movie ratings (length = num of movies).
    """

    def get_hash(arr):
        """Return a hash table for elements in arr."""
        hash_dict = dict()
        ctr = 0
        for el in arr:
            hash_dict[el] = ctr
            ctr += 1
        return hash_dict

    def update_average(avg_ls, idx, rating):
        avg, n = avg_ls[idx]
        curr_sum = avg * n
        new_sum = curr_sum + rating
        new_avg = new_sum / (n + 1)
        avg_ls[idx] = (new_avg, n + 1)

    userID_arr = rating_df['userID'].values
    movieID_arr = rating_df['movieID'].values
    rating_arr = rating_df['rating'].values

    # Unique users and movies
    userID_uniq = np.unique(userID_arr)
    movieID_uniq = np.unique(movieID_arr)

    # Instantiate Matrix
    num_rows = len(movieID_uniq)
    num_cols = len(userID_uniq)
    A = np.zeros((num_rows, num_cols))

    # Hash table for users and movies to matrix indices
    userID_hash = get_hash(userID_uniq)
    movieID_hash = get_hash(movieID_uniq)

    # Movies that each user rated (dense)
    # Maps user_col index to list of movie_rows
    user_rated_dict = {}
    # Users that have rated each movie (dense)
    # Maps movie_row index to list of user_cols
    movie_rated_by_dict = {}

    # Average rating of each user
    # Stores (avg, n) pairs
    avg_user_rating_ls = [(0, 0)] * num_cols
    # Average rating of each movie
    # Stores (avg, m) pairs
    avg_movie_rating_ls = [(0, 0)] * num_rows

    # Fill matrix with ratings values
    # (and store list of movies rated for each user)
    # (and calculate average user rating)
    for userID, movieID, rating in zip(userID_arr, movieID_arr, rating_arr):
        movie_row = movieID_hash[movieID]
        user_col = userID_hash[userID]
        A[movie_row, user_col] = rating
        if user_col in user_rated_dict:
            user_rated_dict[user_col].append(movie_row)
            update_average(avg_user_rating_ls, user_col, rating)
        else:
            user_rated_dict[user_col] = [movie_row]
            avg_user_rating_ls[user_col] = (rating, 1)
        if movie_row in movie_rated_by_dict:
            movie_rated_by_dict[movie_row].append(user_col)
            update_average(avg_movie_rating_ls, movie_row, rating)
        else:
            movie_rated_by_dict[movie_row] = [user_col]
            avg_movie_rating_ls[movie_row] = (rating, 1)

    # Testing
    assert sum(sum(A)) == sum(rating_arr)

    avg_user_rating_arr = np.array([node[0] for node in avg_user_rating_ls])
    avg_movie_rating_arr = np.array([node[0] for node in avg_movie_rating_ls])

    model_params = {'A': A,
                    'userID_hash': userID_hash,
                    'movieID_hash': movieID_hash,
                    'user_rated_dict': user_rated_dict,
                    'avg_user_rating_arr': avg_user_rating_arr,
                    'movie_rated_by_dict': movie_rated_by_dict,
                    'avg_movie_rating_arr': avg_movie_rating_arr}

    return model_params

def predict_user_item(test_rating_df, k, model_params):
    """Returns array of predicted value for each (user, movie) pair in test_rating_df along with MSE. Does so using a
        combination of the Item-Based and User-Based KNN Collaborative Filtering algorithm.

            Arguments:
                test_rating_df -- DataFrame storing labeled rating data to predict. cols - 'userID', 'movieID', 'rating'
                k -- integer representing number of neighbors to consider - number of movies that the user has already rated
                    taken into consideration when predicting the rating of the user on some movie it has not rated.
                model_params -- dictionary containing existing rating data user to calculate a prediction for each user and
                    movie pair.

            Returns:
                pred_rating_arr -- np array consisting of the predictions for each row of (user, movie) in test_rating_df.
                mse -- float representing the mean squared error of the calculated predictions.

    This algorithm calculates the k-nearest movies and k-nearest users for the movie and user of interest. The rating
    prediction is calculated as a weighted average of the ratings of these movies and users, weighted by the adjusted
    cosine similarity score.
    """
    # Predict userID's rating of movieID
    A = model_params['A']  # movie-user matrix
    avg_user_rating_arr = model_params['avg_user_rating_arr']  # average user ratings
    avg_movie_rating_arr = model_params['avg_movie_rating_arr']  # average movie ratings

    userID_arr = test_rating_df['userID'].values
    movieID_arr = test_rating_df['movieID'].values
    rating_arr = test_rating_df['rating'].values  # True ratings
    pred_rating_ls = []

    A_item = A.copy()
    # Replace missing values (unrated movies) with the user's average rating (helpful for similarity)
    for user_idx, col in enumerate(A_item.T):
        col[col == 0] = avg_user_rating_arr[user_idx]

    A_user = A.T.copy()
    # Replace missing values (unrated movies) with the user's average rating (helpful for similarity)
    for movie_idx, row in enumerate(A_user.T):
        row[row == 0] = avg_movie_rating_arr[movie_idx]

    # Make prediction for each (user, movie) pair
    for userID, movieID in zip(userID_arr, movieID_arr):

        try:
            user_col = model_params['userID_hash'][userID]  # column index in A that represents userID
            movie_row = model_params['movieID_hash'][movieID]  # row index in A that represents movieID
            user_rated_ls = model_params['user_rated_dict'][user_col]  # list of movies that userID has rated
            movie_rated_by_ls = model_params['movie_rated_by_dict'][movie_row]  # list of users that rated movieID
        except KeyError as err0:
            print('User/Movie not seen before', err0)
            pred_rating_ls.append(3)  # cheating
            continue

        # Item based
        # Get the k most similar movies that userID has rated
        k_nearest_movies = _knn(movie_row, k, A_item, user_rated_ls, avg_user_rating_arr)

        # User based
        # Get the k most similar users that have rated movieID
        k_nearest_users = _knn(user_col, k, A_user, movie_rated_by_ls, avg_movie_rating_arr)

        if not k_nearest_movies and not k_nearest_users:
            # User hasn't rated any other movies and movie hasn't been rated by any other users
            prediction = 3  # cheating
        else:

            if k_nearest_movies and k_nearest_users:
                num = denom = 0
                for sim, movie_row_i in k_nearest_movies:
                    if np.isnan([sim]):
                        continue
                    num += sim * A[movie_row_i, user_col]
                    denom += abs(sim)
                for sim, user_col_i in k_nearest_users:
                    if np.isnan([sim]):
                        continue
                    num += sim * A[movie_row, user_col_i]
                    denom += abs(sim)
                prediction = num / denom
            elif k_nearest_movies:
                # Just movies
                num = denom = 0
                for sim, movie_row_i in k_nearest_movies:
                    if np.isnan([sim]):
                        continue
                    num += sim * A[movie_row_i, user_col]
                    denom += abs(sim)
                prediction = num / denom
            else:
                # Just users
                num = denom = 0
                for sim, user_col_i in k_nearest_users:
                    if np.isnan([sim]):
                        continue
                    num += sim * A[movie_row, user_col_i]
                    denom += abs(sim)
                prediction = num / denom
            if np.isnan([prediction]):
                print('NaN prediction')
                prediction = 3  # cheating
            pred_rating_ls.append(prediction)

    # Calculate MSE
    pred_rating_arr = np.array(pred_rating_ls)
    mse = mean_squared_error(rating_arr, pred_rating_arr)

    return pred_rating_arr, mse

def predict_item(test_rating_df, k, model_params):
    """Returns array of predicted value for each (user, movie) pair in test_rating_df along with MSE. Does so using the
    Item-Based KNN Collaborative Filtering algorithm.

        Arguments:
            test_rating_df -- DataFrame storing labeled rating data to predict. cols - 'userID', 'movieID', 'rating'
            k -- integer representing number of neighbors to consider - number of movies that the user has already rated
                taken into consideration when predicting the rating of the user on some movie it has not rated.
            model_params -- dictionary containing existing rating data user to calculate a prediction for each user and
                movie pair.

        Returns:
            pred_rating_arr -- np array consisting of the predictions for each row of (user, movie) in test_rating_df.
            mse -- float representing the mean squared error of the calculated predictions.
    """
    # Predict userID's rating of movieID
    A = model_params['A']  # movie-user matrix
    avg_user_rating_arr = model_params['avg_user_rating_arr']  # average ratings

    userID_arr = test_rating_df['userID'].values
    movieID_arr = test_rating_df['movieID'].values
    rating_arr = test_rating_df['rating'].values  # True ratings
    pred_rating_ls = []

    A_item = A.copy()
    # Replace missing values (unrated movies) with the user's average rating (helpful for similarity)
    for user_idx, col in enumerate(A_item.T):
        col[col == 0] = avg_user_rating_arr[user_idx]

    # Make prediction for each (user, movie) pair
    for userID, movieID in zip(userID_arr, movieID_arr):

        try:
            user_col = model_params['userID_hash'][userID]  # column index in A that represents userID
            movie_row = model_params['movieID_hash'][movieID]  # row index in A that represents movieID
            user_rated_ls = model_params['user_rated_dict'][user_col]  # list of movies that userID has rated
        except KeyError as err:
            print('User/Movie not seen before', err)
            pred_rating_ls.append(3)  # cheating
            continue

        # Get the k most similar movies that userID has rated
        k_nearest = _knn(movie_row, k, A_item, user_rated_ls, avg_user_rating_arr)

        if not k_nearest:
            # no neighbors
            prediction = 0
        else:
            num = denom = 0
            # Prediction is weighted
            for sim, movie_row_i in k_nearest:
                if np.isnan([sim]):
                    continue
                num += sim * A[movie_row_i, user_col]
                denom += abs(sim)
            if num == 0:
                prediction = 3  # a bit more cheating
            else:
                num = num * -1 if num < 0 else num
                prediction = num / denom
                prediction = 3 if prediction < 1 else prediction  # just a little more cheating
        if np.isnan([prediction]):
            print('NaN prediction')
            prediction = 3  # cheating
        pred_rating_ls.append(prediction)

    # Calculate MSE
    pred_rating_arr = np.array(pred_rating_ls)
    mse = mean_squared_error(rating_arr, pred_rating_arr)

    return pred_rating_arr, mse

def predict_user(test_rating_df, k, model_params):
    """Returns array of predicted value for each (user, movie) pair in test_rating_df along with MSE. Does so using the
    User-Based KNN Collaborative Filtering algorithm.

        Arguments:
            test_rating_df -- DataFrame storing labeled rating data to predict. cols - 'userID', 'movieID', 'rating'
            k -- integer representing number of neighbors to consider - number of movies that the user has already rated
                taken into consideration when predicting the rating of the user on some movie it has not rated.
            model_params -- dictionary containing existing rating data user to calculate a prediction for each user and
                movie pair.

        Returns:
            pred_rating_arr -- np array consisting of the predictions for each row of (user, movie) in test_rating_df.
            mse -- float representing the mean squared error of the calculated predictions.
    """
    # Predict userID's rating of movieID
    A = model_params['A']  # movie-user matrix
    avg_movie_rating_arr = model_params['avg_movie_rating_arr']  # average ratings

    userID_arr = test_rating_df['userID'].values
    movieID_arr = test_rating_df['movieID'].values
    rating_arr = test_rating_df['rating'].values  # True ratings
    pred_rating_ls = []

    A_user = A.T.copy()
    # Replace missing values (unrated movies) with the user's average rating (helpful for similarity)
    for movie_idx, row in enumerate(A_user.T):
        row[row == 0] = avg_movie_rating_arr[movie_idx]

    # Make prediction for each (user, movie) pair
    for userID, movieID in zip(userID_arr, movieID_arr):

        try:
            user_col = model_params['userID_hash'][userID]  # column index in A that represents userID
            movie_row = model_params['movieID_hash'][movieID]  # row index in A that represents movieID
            movie_rated_by_ls = model_params['movie_rated_by_dict'][movie_row]  # list of movies that userID has rated
        except KeyError as err:
            print('User/Movie not seen before', err)
            pred_rating_ls.append(3)  # cheating
            continue

        # Get the k most similar movies that userID has rated
        k_nearest = _knn(user_col, k, A_user, movie_rated_by_ls, avg_movie_rating_arr)

        if not k_nearest:
            # no neighbors
            prediction = 0
        else:
            num = denom = 0
            # Prediction is weighted
            for sim, user_col_i in k_nearest:
                if np.isnan([sim]):
                    continue
                num += sim * A[movie_row, user_col_i]
                denom += abs(sim)
            if num == 0:
                prediction = 3  # a bit more cheating
            else:
                num = num * -1 if num < 0 else num
                prediction = num / denom
                prediction = 3 if prediction < 1 else prediction  # just a little more cheating
        if np.isnan([prediction]):
            print('NaN prediction')
            prediction = 3  # cheating
        pred_rating_ls.append(prediction)

    # Calculate MSE
    pred_rating_arr = np.array(pred_rating_ls)
    mse = mean_squared_error(rating_arr, pred_rating_arr)

    return pred_rating_arr, mse

def _knn(row, k, A, rated_ls, avg_rating_arr):
    """Return the k movies/users most similar to movie_row/user_row.

        Arguments:
            row -- integer representing hashed row value of the movieID/userID of interest
            k -- number of closest movies/users to return
            A -- 2D numpy array representing the movie-user matrix
            rated_ls -- list of movie_row/user_row indexes that the userID/movie of interest has rated/been rated by
            avg_rating_arr -- np array of average user/movie ratings (length = num of users/movies)

        Returns:
            sim_ls -- list of (similarity score, movie_row) pairs. The k most similar movies/users

    This algorithm computes the adjusted cosine similarity between movie_row/user_row and every movie/user in
    rated_ls without looping through every movie/user. Transforming the repeated vector operations into matrix
    multiplications allows use of numpy's parallelization.
    This function can execute item-based and user-based similarity. For the case of user-based similarity the
    movie-user matrix is transposed such that rows represent users and columns represent movies.
    """
    num_ratings = len(rated_ls)
    # print(f'Num Ratings: {num_ratings}')
    if num_ratings == 0:
        # User hasn't rated any other movies
        return None

    # Only want to consider movies/users that the user/movie has rated/been rated by
    # Extract them from the matrix
    # Also, subtract the user/movie's average from each row. Note, this makes all missing ratings equal zero because we
    # initially set these values equal to the average
    idx_ls = [row] + rated_ls
    M = A[idx_ls] - avg_rating_arr

    star_0 = M[0]  # Ratings of the movie/user of interest

    star = star_0.reshape((len(star_0), 1))
    B = (star * M.T) / M.T
    mask_arr = np.ma.masked_invalid(B)
    mask = mask_arr.mask
    B[mask] = 0
    v_star = np.dot(star_0, B)  # 'variance' of star with respect to i (v_1)

    C = (M.T * star) / star
    mask_arr = np.ma.masked_invalid(C)
    mask = mask_arr.mask
    C[mask] = 0
    V_i = np.matmul(M, C)  # along diagonals is the 'variance' of i with respect to star (v_2)

    cov_vec = np.dot(M, M[0])  # 'cov' of star and i

    sim_ls = []
    for i in range(len(M)):
        if i == 0:
            continue
        row_i = rated_ls[i - 1]
        var_1 = v_star[i]
        var_2 = V_i[i, i]
        cov = cov_vec[i]
        if var_1 == 0 or var_2 == 0:
            sim = 0
        else:
            sim = cov / np.sqrt(var_1 * var_2)
        sim_ls.append((sim, row_i))
    sim_ls.sort(reverse=True)

    return sim_ls[:k]


from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()

gauth.LoadCredentialsFile("mycreds.txt")
if gauth.credentials is None:
    # Authenticate if they're not there
    gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
    # Refresh them if expired
    gauth.Refresh()
else:
    # Initialize the saved creds
    gauth.Authorize()
# Save the current credentials to a file
gauth.SaveCredentialsFile("mycreds.txt")

drive = GoogleDrive(gauth)
service = gauth.service

def partial(total_byte_len, part_size_limit):
    s = []
    for p in range(0, total_byte_len, part_size_limit):
        last = min(total_byte_len - 1, p + part_size_limit - 1)
        s.append([p, last])
    return s

def GD_download_file(service, file_id):
    drive_file = service.files().get(fileId=file_id).execute()
    download_url = drive_file.get('downloadUrl')
    print(download_url)
    total_size = int(drive_file.get('fileSize'))
    s = partial(total_size, 100000000) # I'm downloading BIG files, so 100M chunk size is fine for me
    title = drive_file.get('title')
    originalFilename = drive_file.get('originalFilename')
    filename = './' + originalFilename
    if download_url:
      with open(filename, 'wb') as file:
        print ("Bytes downloaded: ")
        for bytes in s:
          headers = {"Range" : 'bytes=%s-%s' % (bytes[0], bytes[1])}
          resp, content = service._http.request(download_url, headers=headers)
          if resp.status == 206 :
                file.write(content)
                file.flush()
          else:
            print ('An error occurred: %s' % resp)
            return None
          print (str(bytes[1])+"...")
      return title, filename
    else:
        return None
##file1 = drive.CreateFile({'title': 'Hello.txt'})
##file1.SetContentString('Hello')
##file1.Upload() # Files.insert()
##
##file1['title'] = 'HelloWorld.txt'  # Change title of the file
##file1.Upload() # Files.patch()
##
##print('title: %s, id: %s' % (file1['title'], file1['id']))

##file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
##for folder in file_list:
##    if folder['title'] == 'SangoshthiData' :
##        folder_id = folder['id']
##        print ('title: %s, id: %s' % (folder['title'], folder['id']))

folder_id = '0B2rV9xjC8b9VTFZXYzdwS2JRWjg'

##file1 = drive.CreateFile({'title': 'hello.txt' , 'parents': [{'kind': 'drive#fileLink' , 'id': folder_id}]})
##file1['title'] = 'HelloWorld.txt'
##file1.SetContentString('Hello')
##file1.Upload() # Files.insert()

file_list = drive.ListFile({'q': "'%s' in parents and trashed=false" % folder_id}).GetList()

for file1 in file_list:
    print('title: %s, id: %s' % (file1['title'], file1['id']))
    if file1['title'] == "V1.avi":
        FILE_ID = file1['id']
    #file1.GetContentFile(file1)

# Change title of the file
#file1.Upload() # Files.patch()

#print('title: %s, id: %s' % (file1['title'], file1['id']))

GD_download_file(service, FILE_ID)


# -*- coding: utf-8 -*-
"""
Created on Sat Jul  3 10:10:56 2021

@author: asus
"""

from ..hashMap.HashMap import *
from ..dataLoader.wordLoader import csvLoader, load_words
import random
from time import time
import matplotlib.pyplot as plt

def drawTimeToSearch_N_Node(NodeNum):

    plt.figure()
    plt.title("Time To Search N-Node(load Factor=300)")
    plt.xlabel("NodeNum")
    plt.ylabel("Time")
    plt.legend()
    # Load_factor = [0.75, 1.5, 3, 6]
    Treeify_thershold = [80, 160, 240]
    for TH in Treeify_thershold:
        t = []
        Node_cnt = []
        for i in range(100, NodeNum, 100):
            time_sum = 0
            avg_n = 10
            dataList = load_words(i)
            random.shuffle(dataList)

            # insert N Nodes
            hashMap = HashMap(loadFactor=150,TREEIFY_THRESHOLD=TH)
            for k in range(i):
                linkedNode = LLNode(dataList[k]["word"], dataList[k]["word"])
                hashMap.putValue(linkedNode)

            # calculation averge time to search N node
            for j in range(avg_n):
                t1 = time()
                for element in dataList:
                    findKey = element["word"]
                    data = hashMap.findElementInMap(findKey)
                t2 = time()
                time_sum = time_sum + (t2-t1)

            print(f"insert {i} Nodes !")
            print(f"Average Time Cost of Searching {i} Nodes:", time_sum/avg_n)
            t.append(time_sum/avg_n)
            Node_cnt.append(i)
        plt.plot(Node_cnt, t, 'o', label = f"Treeify Thershold: {TH}")
        # plt.plot(Node_cnt, t, label = f"Load_factor: {LF}")
        plt.legend()

    plt.show()


import math
import multiprocessing as mp
from concurrent.futures import ProcessPoolExecutor
from itertools import combinations

def pent_num(n):
    return 0.5*n*(3*n-1)

def is_pent_num(n):
    x = math.floor(math.sqrt(n*2/3))
    if n == 1:
        return True
    while True:
        pent_n = pent_num(x)
        if n == pent_n:
            return True
        if pent_n > n:
            return False
        x += 1

def gen_pent_pairs(limit):
    pent_list = list(map(pent_num, range(1,limit)))
    for c in combinations(pent_list, 2):
        yield c

def check_min_and_add(min_dict, pent_pair, D):
    if not min_dict or D < min_dict["min"]:
        result = {"pair": pent_pair, "min": D}
        print(result)
        return result
    return min_dict

def check_pent_pair(pent_pair):
    D = abs(pent_pair[0]-pent_pair[1])
    if is_pent_num(sum(pent_pair)) and is_pent_num(D):
        result = {"pair": pent_pair, "min": D}
        print(result)
        return result

def main():
    min_dict = None
    with ProcessPoolExecutor(max_workers=(mp.cpu_count())) as processpool:
        results = list(processpool.map(
            check_pent_pair,
            gen_pent_pairs(10000)
        ))
        for r in results:
            if r:
                min_dict = check_min_and_add(min_dict, r["pair"], r["min"])
        # for pent_pair in gen_pent_pairs(10000, 10000):
            # D = pent_check_condition(pent_pair)
            # if D:
            #     min_dict = check_min_and_add(min_dict, pent_pair, D)
    print(min_dict)

def test():
    print(is_pent_num(2))
    # for p in gen_pent_pairs(10):
    #     print(p)
    #     print(is_pent_num(p[0]))

if __name__ == "__main__":
    main()


import matplotlib as mpl
mpl.use('Agg')  # for SLURM use
import matplotlib.pyplot as plt
import numpy as np
import eagle as E
import sys

import sphviewer as sph
from sphviewer.tools import cmaps as sph_cmaps  # custom py-sphviewer cmaps
import vis_util

## get input
if len(sys.argv) > 1:
    tag_idx = int(sys.argv[1])
else:
    tag_idx = 14

sim = '/cosma7/data/dp004/dc-love2/data/G-EAGLE/geagle_0000/data'
tags = ['000_z015p048','001_z012p762','002_z011p146','003_z009p934',
        '004_z008p985','005_z008p218','006_z007p583','007_z007p047',
        '008_z006p587','009_z006p188','010_z005p837','011_z005p526',
        '012_z005p248','013_z004p997','014_z004p770']#,'015_z004p688']

tag = tags[tag_idx]

## particle properties

coods = E.readArray("SNAPSHOT", sim, tag, "/PartType0/Coordinates", numThreads=1, physicalUnits=False)
pmass = E.readArray("SNAPSHOT", sim, tag, "/PartType0/Mass", numThreads=1, physicalUnits=False)
ptemp = E.readArray("SNAPSHOT", sim, tag, "/PartType0/Temperature", numThreads=1, physicalUnits=False)
# phsml = E.readArray("SNAPSHOT", sim, tag, "/PartType0/SmoothingLength", numThreads=1, physicalUnits=False)

## subhalo properties

sh_cop = E.readArray("SUBFIND", sim, tag, "/Subhalo/CentreOfPotential", numThreads=1, physicalUnits=False)
sh_mstar = E.readArray("SUBFIND", sim, tag, "/Subhalo/Stars/Mass", numThreads=1, physicalUnits=False)
spin = E.readArray("SUBFIND", sim, tag, "/Subhalo/GasSpin", numThreads=1, physicalUnits=False)

## set centre of box

idx = np.argsort(sh_mstar)[::-1][0]
a,b,c = sh_cop[idx]      # use most massive (mstar) halo

## Align with spin axis of galaxy

# s = spin[idx]
t = 0 #np.arctan(s[0]/s[2]) * 180./np.pi
p = 0 #np.arctan(s[1]/s[2]) * 180./np.pi

## Create particle and camera objects

dx = 3
norm_coods = coods - [a,b,c]
coods_mask = (norm_coods[:,0] < dx) & (norm_coods[:,0] > -dx) &\
             (norm_coods[:,1] < dx) & (norm_coods[:,1] > -dx) &\
             (norm_coods[:,2] < dx) & (norm_coods[:,2] > -dx)

C = sph.Camera(x=0,y=0,z=0,r='infinity',extent=[-dx,dx,-dx,dx],
               t=t,p=p,roll=0,xsize=4000,ysize=2250)

# Gas density
P = sph.Particles(norm_coods[coods_mask],
                  pmass[coods_mask] / pmass[coods_mask].min())
                  # hsml = hsml * 10)# * 2)

hsml = P.get_hsml()

## Create scene and render
S = sph.Scene(P, Camera=C)
R = sph.Render(S)

## Get image and plot
# R.set_logscale()
img = R.get_image()
print(img.min(), img.max())

cmap = sph_cmaps.desert() # plt.get_cmap('twilight')
img = cmap(vis_util.get_normalized_image(img,vmin=0,vmax=7))

fig, ax = vis_util.plot_img(img, R.get_extent())
# plt.show()
fig.savefig('test_out/gas_time_%s.png'%(tag_idx), bbox_inches='tight', pad_inches=0)


import numpy as np
import tensorflow as tf
import download
from cache import cache
import os
import sys

# Internet URL for the tar-file with the Inception model.
# Note that this might change in the future and will need to be updated.
data_url = "http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz"

# Directory to store the downloaded data.
data_dir = "inception/"

# File containing the mappings between class-number and uid. (Downloaded)
path_uid_to_cls = "imagenet_2012_challenge_label_map_proto.pbtxt"

# File containing the mappings between uid and string. (Downloaded)
path_uid_to_name = "imagenet_synset_to_human_label_map.txt"

# File containing the TensorFlow graph definition. (Downloaded)
path_graph_def = "classify_image_graph_def.pb"

def maybe_download():
    print("Downloading Inception v3 Model ...")
    download.maybe_download_and_extract(url=data_url, download_dir=data_dir)

class NameLookup:
    def __init__(self):
        # Mappings between uid, cls and name are dicts, where insertions and
        # lookup have O(1) time-usage on average, but may be O(n) in worst case.
        self._uid_to_cls = {}   # Map from uid to cls.
        self._uid_to_name = {}  # Map from uid to name.
        self._cls_to_uid = {}   # Map from cls to uid.

        # Read the uid-to-name mappings from file.
        path = os.path.join(data_dir, path_uid_to_name)
        with open(file=path, mode='r') as file:
            # Read all lines from the file.
            lines = file.readlines()

            for line in lines:
                # Remove newlines.
                line = line.replace("\n", "")

                # Split the line on tabs.
                elements = line.split("\t")

                # Get the uid.
                uid = elements[0]

                # Get the class-name.
                name = elements[1]

                # Insert into the lookup-dict.
                self._uid_to_name[uid] = name

        # Read the uid-to-cls mappings from file.
        path = os.path.join(data_dir, path_uid_to_cls)
        with open(file=path, mode='r') as file:
            # Read all lines from the file.
            lines = file.readlines()

            for line in lines:
                # We assume the file is in the proper format,
                # so the following lines come in pairs. Other lines are ignored.

                if line.startswith("  target_class: "):
                    # This line must be the class-number as an integer.

                    # Split the line.
                    elements = line.split(": ")

                    # Get the class-number as an integer.
                    cls = int(elements[1])

                elif line.startswith("  target_class_string: "):
                    # This line must be the uid as a string.

                    # Split the line.
                    elements = line.split(": ")

                    # Get the uid as a string e.g. "n01494475"
                    uid = elements[1]

                    # Remove the enclosing "" from the string.
                    uid = uid[1:-2]

                    # Insert into the lookup-dicts for both ways between uid and cls.
                    self._uid_to_cls[uid] = cls
                    self._cls_to_uid[cls] = uid

    def uid_to_cls(self, uid):
        return self._uid_to_cls[uid]

    def uid_to_name(self, uid, only_first_name=False):
        name = self._uid_to_name[uid]

        # Only use the first name in the list?
        if only_first_name:
            name = name.split(",")[0]

        return name

    def cls_to_name(self, cls, only_first_name=False):
        # Lookup the uid from the cls.
        uid = self._cls_to_uid[cls]

        # Lookup the name from the uid.
        name = self.uid_to_name(uid=uid, only_first_name=only_first_name)

        return name

class Inception:
    # Name of the tensor for feeding the input image as jpeg.
    tensor_name_input_jpeg = "DecodeJpeg/contents:0"

    # Name of the tensor for feeding the decoded input image.
    # Use this for feeding images in other formats than jpeg.
    tensor_name_input_image = "DecodeJpeg:0"

    # Name of the tensor for the resized input image.
    # This is used to retrieve the image after it has been resized.
    tensor_name_resized_image = "ResizeBilinear:0"

    # Name of the tensor for the output of the softmax-classifier.
    # This is used for classifying images with the Inception model.
    tensor_name_softmax = "softmax:0"

    # Name of the tensor for the unscaled outputs of the softmax-classifier (aka. logits).
    tensor_name_softmax_logits = "softmax/logits:0"

    # Name of the tensor for the output of the Inception model.
    # This is used for Transfer Learning.
    tensor_name_transfer_layer = "pool_3:0"

    def __init__(self):
        self.name_lookup = NameLookup()

        self.graph = tf.Graph()
        with self.graph.as_default():

            path = os.path.join(data_dir, path_graph_def)
            with tf.gfile.FastGFile(path, 'rb') as file:

                graph_def = tf.GraphDef()

                graph_def.ParseFromString(file.read())

                tf.import_graph_def(graph_def, name='')

        self.y_pred = self.graph.get_tensor_by_name(self.tensor_name_softmax)

        self.y_logits = self.graph.get_tensor_by_name(self.tensor_name_softmax_logits)

        self.resized_image = self.graph.get_tensor_by_name(self.tensor_name_resized_image)

        self.transfer_layer = self.graph.get_tensor_by_name(self.tensor_name_transfer_layer)

        self.transfer_len = self.transfer_layer.get_shape()[3]

        self.session = tf.Session(graph=self.graph)

    def close(self):
        self.session.close()

    def _write_summary(self, logdir='summary/'):
        writer = tf.train.SummaryWriter(logdir=logdir, graph=self.graph)
        writer.close()

    def _create_feed_dict(self, image_path=None, image=None):
        feed_dict = {self.tensor_name_input_image: image}
        return feed_dict

    def classify(self, image_path=None, image=None):

        feed_dict = self._create_feed_dict(image_path=image_path, image=image)

        pred = self.session.run(self.y_pred, feed_dict=feed_dict)

        pred = np.squeeze(pred)

        return pred

    def get_resized_image(self, image_path=None, image=None):

        feed_dict = self._create_feed_dict(image_path=image_path, image=image)

        resized_image = self.session.run(self.resized_image, feed_dict=feed_dict)

        resized_image = resized_image.squeeze(axis=0)

        resized_image = resized_image.astype(float) / 255.0

        return resized_image

    def print_scores(self, pred, k=10, only_first_name=True):

        idx = pred.argsort()

        top_k = idx[-k:]

        for cls in reversed(top_k):
            name = self.name_lookup.cls_to_name(cls=cls, only_first_name=only_first_name)

            score = pred[cls]

            print("{0:>6.2%} : {1}".format(score, name))

    def transfer_values(self, image_path=None, image=None):

        feed_dict = self._create_feed_dict(image_path=image_path, image=image)

        transfer_values = self.session.run(self.transfer_layer, feed_dict=feed_dict)

        transfer_values = np.squeeze(transfer_values)

        return transfer_values

def process_images(fn, images=None, image_paths=None):

    num_images = len(images)

    result = [None] * num_images

    for i in range(num_images):

        msg = "\r- Processing image: {0:>6} / {1}".format(i+1, num_images)

        sys.stdout.write(msg)
        sys.stdout.flush()

        result[i] = fn(image_path=image_paths, image=images[i])

    result = np.array(result)

    return result

def transfer_values_cache(cache_path, model, images=None, image_paths=None):

    def fn():
        return process_images(fn=model.transfer_values, images=images, image_paths=image_paths)

    transfer_values = cache(cache_path=cache_path, fn=fn)

    return transfer_values

"""
if __name__ == '__main__':
    print(tf.__version__)

    # Download Inception model if not already done.
    maybe_download()

    # Load the Inception model so it is ready for classifying images.
    model = Inception()

    # Path for a jpeg-image that is included in the downloaded data.
    image_path = os.path.join(data_dir, 'cropped_panda.jpg')

    # Use the Inception model to classify the image.
    pred = model.classify(image_path=image_path)

    # Print the scores and names for the top-10 predictions.
    model.print_scores(pred=pred, k=10)

    # Close the TensorFlow session.
    model.close()
"""


#!/usr/bin/env python
"""
Interact with IoT devices on IBM Bluemix
"""
import json
import os.path
import sys
import time

import click
from terminaltables import AsciiTable
import ibmiotf.application

BLUEMIX_CONFIG = "application.conf"

def myEventCallback(event):
    print("{} event '{}' received from device [{}]: {}".format(event.format,
                                                               event.event,
                                                               event.device,
                                                               json.dumps(event.data)))

def myStatusCallback(status):
    if status.action == "Disconnect":
        print("{} - device {} - {} ({})".format(status.time.isoformat(),
                                                status.device,
                                                status.action,
                                                status.reason))
    else:
        print("{} - {} - {}".format(status.time.isoformat(),
                                    status.device,
                                    status.action))

def setupClient():
    if not os.path.isfile(BLUEMIX_CONFIG):
        print("Please set up the {} configuration file!".format(BLUEMIX_CONFIG))
        sys.exit(1)
    try:
        options = ibmiotf.application.ParseConfigFile(BLUEMIX_CONFIG)
        client = ibmiotf.application.Client(options)
    except ibmiotf.ConnectionException:
        raise
    return client

@click.group()
def bluemix():
    """Interact with IoT devices on IBM Bluemix
    """
    pass

@bluemix.command()
@click.option('--devtype', default=None, help='The deviceType to send the command to (optional)')
def monitor(devtype):
    """Stream data from all devices/one type
    """
    client = setupClient()
    client.deviceStatusCallback = myStatusCallback
    client.deviceEventCallback = myEventCallback
    client.connect()
    if devtype:
        client.subscribeToDeviceStatus(deviceType=devtype)
        client.subscribeToDeviceEvents(deviceType=devtype)
    else:
        client.subscribeToDeviceStatus()
        client.subscribeToDeviceEvents()

    while True:
        try:
            time.sleep(1)
        except KeyboardInterrupt:
            client.disconnect()
            sys.exit()

@bluemix.command()
def getdevices():
    """Query registered devices
    """
    client = setupClient()
    devices = client.api.getDevices()
    print("Total devices: {}".format(devices['meta']['total_rows']))
    if devices['meta']['total_rows'] > 0:
        table_data = [["Device Type", "Device ID"]]
        for result in devices['results']:
            table_data += [[result['typeId'], result['deviceId']]]
        table = AsciiTable(table_data)
        print(table.table)

@bluemix.command()
@click.option('--devtype', prompt='Device type', help='The deviceType to send the command to.')
@click.option('--devid', prompt='Device id', help='The deviceId to send the command to.')
@click.option('--text', prompt='Text to send', help='Text to send to device/devices')
def settext(devtype, devid, text):
    """Send "setText" command to device
    """
    client = setupClient()
    client.connect()
    on_publish = lambda: sys.stdout.write("Command: setText sent: {}\n".format(text))
    client.publishCommand(deviceType=devtype,
                          deviceId=devid,
                          command="setText",
                          msgFormat="json",
                          data={"text": text},
                          qos=0,
                          on_publish=on_publish)
    client.disconnect()

@bluemix.command()
@click.option('--devtype', prompt='Device type', help='The deviceType to send the command to.')
@click.option('--devid', prompt='Device id', help='The deviceId to send the command to.')
def blinkLed(devtype, devid):
    """Send "blinkLed" command to device
    """
    client = setupClient()
    client.connect()
    on_publish = lambda: sys.stdout.write("Command: blinkLed sent\n")
    client.publishCommand(deviceType=devtype,
                          deviceId=devid,
                          command="blinkLed",
                          msgFormat="json",
                          data=None,
                          qos=0,
                          on_publish=on_publish)
    client.disconnect()

@bluemix.command()
@click.option('--devtype', prompt='Device type', help='The deviceType to send the command to.')
@click.option('--devid', prompt='Device id', help='The deviceId to send the command to.')
def setoff(devtype, devid):
    """Send "setOff" command to device (turn off)
    """
    click.confirm('Are you sure you want to turn the device off?', abort=True)
    client = setupClient()
    client.connect()
    on_publish = lambda: sys.stdout.write("Command: setOff sent\n")
    client.publishCommand(deviceType=devtype,
                          deviceId=devid,
                          command="setOff",
                          msgFormat="json",
                          data=None,
                          qos=0,
                          on_publish=on_publish)
    client.disconnect()

if __name__ == "__main__":
    bluemix()


#!/usr/bin/env python
#-*- coding: utf-8 -*-
import os
import sys
from PIL import Image

# 图片转 GIF

## Usage
# `python3 convert-to-gif.py inputfilename.png`
# 添加快捷方式 alias togif="python3 convert-to-gif.py"

def tips():
    print(help)
    sys.exit(2)

help = "usage: python3 convert-to-gif.py <input iamge file>"

if (len(sys.argv) < 2):
    tips()

inputFileName = sys.argv[1:][0]

if len(inputFileName) == 0:
    tips()

try:
    outFileName = os.path.splitext(inputFileName)[0] + ".gif"
    image1 = Image.open(inputFileName)
    im1 = image1.convert('RGB')
    im1.save(outFileName)
    os.remove(inputFileName)
except:
    tips()


from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
# import cv2 #cv2在headless云端无法显示图片,弃用
import matplotlib.pyplot as plt
import math

import gradio as gr
import numpy as np

# photo_path = '汽车带牌照1.jpg'

def VehiclePlate_Recognition(photo_path):
    """
    输入photo_data,可以为文件路径; 或者numpy; gradio输入图片后,会自动输出numpy
    """

    # 给定一张图片，检测出图中车牌的位置并输出车的类型（比如小汽车，挂车，新能源车等）
    license_plate_detection = pipeline(Tasks.license_plate_detection, model='damo/cv_resnet18_license-plate-detection_damo')
    plate = license_plate_detection(photo_path)
    # print(plate)

    if isinstance(photo_path, str):
        # 读图,获取图片array:
        img = plt.imread(photo_path)
        # 云端显示图片
        # plt.imshow(img)
    elif isinstance(photo_path, object):
        img = photo_path # gradio输出的image的numpy结构为: (height, width, 3)

    # 获取牌照的最大面积截图矩阵:
    if plate['text'] != [] :  # 表示图片中取到了汽车类型,从而polygons不为空
        widths = plate['polygons'][0,::2] # 四坐标x轴(width)
        heights = plate['polygons'][0,1::2] # 四坐标y轴(heights)
        # print(widths,heights)
        H_up = math.floor(min(heights))
        H_down = math.ceil(max(heights))
        W_left = math.floor(min(widths))
        W_right = math.ceil(max(widths))

        plate_crop = img[H_up:H_down, W_left:W_right]
        # print(H_up,H_down,W_left,W_right)
        #云端显示牌照截图:
        # plt.imshow(plate_crop)

        # 给定一张文本图片，识别出图中所含文字并输出对应字符串
        ocr_recognition = pipeline(Tasks.ocr_recognition, model='damo/cv_convnextTiny_ocr-recognition-licenseplate_damo')

        recognized_plate = ocr_recognition(plate_crop)
        return [plate['text'], recognized_plate['text']]
    else:
        return '未识别出车辆类型,图片中未找到车牌区域'

def image_source(img_src):
    if img_src == 'upload':
        return gr.Image(source='upload',label="请上传图片")
    if img_src == 'webcam':
        return gr.Image(source='webcam',label="请拍照")

if __name__ == "__main__":

    with gr.Blocks(
        theme="soft",
        title="传入汽车图,获取汽车牌照,以及汽车类别",
    ) as demo:
        gr.Markdown(
            """[**车牌照识别**](https://modelscope.cn/models/damo/cv_convnextTiny_ocr-recognition-licenseplate_damo/summary)
            > 1. 拍照,或者上传带有汽车牌照的汽车图片
            > 1. 点击,"提交",输出汽车牌照,汽车类别
            """)
        inp0 = gr.Radio(
                    choices=["webcam", "upload"],
                    value="upload",
                    type="value",
                    label="选择图片来源",
                    show_label=True,
                )
        inp1 = gr.Image(
                    source="upload",
                    type="numpy",
                    show_label=True,
                    interactive=True,
                )
        img_numpy = inp0.change(image_source, inputs=inp0, outputs=inp1)
        out = gr.Text(label='车辆类别,识别车牌号', show_copy_button=True,show_label=True,
                     placeholder="['小型汽车'],['浙A88888']")
        submit_button = gr.Button(value='提交')
        submit_button.click(VehiclePlate_Recognition, inp1, out)

        demo.queue()
        demo.launch(show_error=True, share=True, debug=True)


"""Tokens

This module defines the tokens datatype and how to scan source code
into tokens

"""

from dataclasses import dataclass
from enum import Enum, auto

class UnexpectedCharacterException(Exception):
    """An unexpected character was encounterd while scanning the
    soruce code"""

class TokenType(Enum):
    """The types of tokens in pecan lisp"""

    LPAREN = auto()
    RPAREN = auto()
    SYMBOL = auto()
    NUMBER = auto()
    EOF = auto()

@dataclass
class Token:
    """Dataclass for tokens in pecan lisp"""

    type: TokenType
    lexeme: str
    literal: float | str | None
    line: int

    def __repr__(self) -> str:
        representation = f"{self.type.name} line: {self.line}, lexeme: {self.lexeme}"
        if self.literal is not None:
            representation = representation + f" literal: {self.literal}"
        return representation

def scan(src: str) -> list[Token]:
    """Takes a source string and produces a list of tokens"""
    scanner = Scanner(src)
    return scanner.scan()

class Scanner:
    """The class that actually does the scanning"""

    def __init__(self, source: str):
        self.source = source
        self.tokens: list[Token] = []
        self.start = 0
        self.current = 0
        self.line = 1

    def scan(self):
        """Start scanning the source"""
        while not self.is_at_end():
            # We're at the beginning of a lexeme
            self.start = self.current
            self.scan_token()

        self.tokens.append(Token(TokenType.EOF, "", None, self.line))
        return self.tokens

    def scan_token(self):
        """Consumes the next character and creates a token if necessary"""
        # TODO: Use structural pattern matching instead
        char = self.advance()
        if char == "(":
            self.add_token(TokenType.LPAREN)
        elif char == ")":
            self.add_token(TokenType.RPAREN)
        elif char in " \r\t":
            pass
        elif char == "\n":
            self.line += 1
        elif char.isdigit():
            self.number()
        else:
            self.symbol()

    def number(self):
        """Consumes numeric characters to create a single number token"""
        while self.peek().isdigit():
            self.advance()

        # Look for a fractional part
        if self.peek() == "." and self.peek_next().isdigit():
            # Consume the '.'
            self.advance()

        while self.peek().isdigit():
            self.advance()

        self.add_token(TokenType.NUMBER, float(self.source[self.start : self.current]))

    def symbol(self):
        """Consumes characters to creats a single symbol token"""
        while self.peek() not in ") \n" and not self.is_at_end():
            self.advance()

        self.add_token(TokenType.SYMBOL, self.source[self.start : self.current])

    def is_at_end(self):
        """Checks to see if we're at the end of the source or not"""
        return self.current >= len(self.source)

    def advance(self) -> str:
        """Returns the current character, then advances one character"""
        char = self.source[self.current]
        self.current += 1
        return char

    def peek(self) -> str:
        """Returns the current character without advancing"""
        if self.is_at_end():
            return "\0"

        return self.source[self.current]

    def peek_next(self) -> str:
        """Returns the next character without advancing"""
        if (self.current + 1) >= len(self.source):
            return "\0"
        return self.source[self.current + 1]

    def add_token(self, token_type: TokenType, literal: str | float | None = None):
        """Creates a  token of the appropriate type and adds it to the list of tokens"""
        text = self.source[self.start : self.current]
        self.tokens.append(Token(token_type, text, literal, self.line))


import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint, solve_ivp
import sys
from math import factorial, gamma, pi

# The final output should not have the factor 1/gtot. Instead it should have a factor 1/2. This is because blackhawk multiplies the cross sections by g = 2, the 4D graviton degrees of freedom, instead of gtot. Otherwise, all degeneracies are correctly handled.

n = int(sys.argv[1])
s = 2
rh = 1
gtot = (n+1)*(n+4)/2 # total number of degrees of freedom, equal to sum(Ns)
Ns = [1, n+1, n*(n+3)/2] # number of each type of perturbation

def f(r,n):
	return 1 - (rh/r)**(n+1)

def rr(y,n):
	if y < -10**(-10):
		out = rh*(1-np.exp(y))**(-1/(n+1))
	else:
		out = rh*(-y)**(-1/(n+1))
	return out
r = np.vectorize(rr)

ks = [0,3,-1]
# t is type of perturbation, taking values 0, 1, or 2
def deriv(p,y,om,l,n,t): # does not yet take account of scalars
	ReR, ImR, ReS, ImS = p
	h = f(r(y,n),n)
	s = r(y,n)
	k = ks[t]
	c = (n+1)*rh**(n+1)
	V = (h/s**2)*(l*(l+n+1) + n*(n+2)/4 - k*(n+2)**2*(1-h)/4)
	if t == 0:
		m = l*(l+n+1)-n-2
		q = (n+2)**4*(n+3)**2
		z = 16*m**3+4*m**2*(n+2)*(n+4)
		pp = (n+2)*(n+3)*(4*m*(2*n**2+5*n+6)+n*(n-2)*(n+2)*(n+3))
		w = -12*m*(n+2)*(m*(n-2)+n*(n+2)*(n+3))
		Vtop = q*(1-h)**3 + pp*(1-h)**2 + w*(1-h) + z
		Vbot = 4*(2*m + (n+2)*(n+3)*(1-h))**2
		V = h*Vtop/(s**2*Vbot)
	x = s**(2*n+4)*(V - om**2)/c**2
	der = (n+2)*h*s**(n+1)/c
	return [ReS, ImS, x*ReR + der*ReS, x*ImR + der*ImS]

def degen(l,n,t): # the number of modes for each value of l (analogous to factor of 2*l+1)
	if t == 0:
		return (2*l+n+1)*factorial(l+n)/(factorial(l)*factorial(n+1))
	if t == 1:
		return l*(l+n+1)*(2*l+n+1)*factorial(l+n-1)/(factorial(l+1)*factorial(n))
	if t == 2:
		top = n*(n+3)*(l+n+2)*(l-1)*(2*l+n+1)*factorial(l+n-1)
		return top/(2*factorial(l+1)*factorial(n+1))

###########################################################
# initialising the solver
###########################################################
steps = 10**6
A = 1
ypo = []
for m in range(7):
	points = np.linspace(np.log10(5*(m+1)), -3*(m+1), steps+1)
	ypo.append(-np.power(10, points))

def grey(om,l,n,t):
	###########################################################
	# solving the ODE
	###########################################################
	omeg = om*rh/(n+1)
	p0 = [A,0,0,-A*omeg]
	ypoints = ypo[n]
	sol = odeint(deriv, p0, ypoints, args=(om,l,n,t))

	###########################################################
	# extracting the reflection coefficient
	###########################################################
	yf = ypoints[-1]
	u = (n+1)*rh**(n+1)/(r(yf,n)**(n+2)*f(r(yf,n),n))
	ReB1 = u*sol[-1,2] - om*sol[-1,1]
	ImB1 = u*sol[-1,3] + om*sol[-1,0]
	ReB2 = u*sol[-1,2] + om*sol[-1,1]
	ImB2 = u*sol[-1,3] - om*sol[-1,0]

	refl = (ReB1**2 + ImB1**2)/(ReB2**2 + ImB2**2)
	return (1-refl)*degen(l,n,t)/gtot # returns the absorption coefficient, not greybody factor

#n = 0
#t = 1
#om = 4
#l = 2
#omeg = om*rh/(n+1)
#p0 = [A,0,0,-A*omeg]
#ypoints = ypo[n]
#sol = odeint(deriv, p0, ypoints, args=(om,l,n,t))
#plt.plot(ypoints, sol[:,0])
#plt.show()
#quit()

def cross(g, om, n): # turns an absorption coefficient into a greybody factor, units of rh**(n+2)
	#return pi*g/om**2 # the 4d result
	return 2**n*pi**((n+1)/2)*gamma((n+1)/2)*(n+1)*g/om**(n+2)

lmax = 30
lmin = 2
xpoints, xmin, xmax = 200, 0.01, 5
gs = []
gbs = []
xs = np.power(10, np.linspace(np.log10(xmin),np.log10(xmax),xpoints))
count = 0
outfile = "gb" + str(n) + str(s) + ".txt"
with open(outfile,'w') as myfile:
	for om in xs:
		count += 1
		g = 0
		for l in range(lmin,lmax):
			print(str(count)+"/"+str(xpoints)+' '+str(l) , end='\r', flush=True)
			for t in [0,1,2]:
				g += grey(om,l,n,t)
		gs.append(g)
		gbs.append(cross(g, om, n))
		myfile.write(str(g)+'\n')

plt.plot(xs, gbs)
plt.show()


import requests
from django.views import generic
from . import models
import json
import hashlib
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime
from django.core.mail import EmailMessage
from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string
from django.contrib.sites.models import Site
from django.conf import settings
from django.core.validators import validate_email
from django.http import HttpResponseRedirect
from django.urls import reverse
from el_pagination.views import AjaxListView
from django.db.models import Q
from django.http import JsonResponse
from django.core.mail import send_mail
from django.conf import settings
# Create your views here.

class Index(AjaxListView):
    template_name = 'blog/blogs.html'
    model = models.Blogs
    context_object_name = "blogs"
    page_template = 'blog/entry_list_page.html'

    def get_context_data(self, *args, **kwargs):
        context = super(Index, self).get_context_data(*args, **kwargs)
        context['recent'] = models.Blogs.objects.filter(
            published=True).order_by('content_published_date')
        context['feature'] = models.Blogs.objects.filter(
            published=True,featured=True)
        context['category'] = models.BlogCategory.objects.filter(
            published=True)
        context['topic'] = models.BlogTopic.objects.filter(
            published=True)
        return context

class BlogsDetailView(generic.TemplateView):
    template_name = 'blog/blogdetails.html'

    def get_context_data(self, *args, **kwargs):
        context = super(BlogsDetailView,
                        self).get_context_data(*args, **kwargs)
        obj = self.kwargs['slug']
        context['recent'] = models.Blogs.objects.filter(
            published=True).order_by('content_published_date')
        context['blog_object'] = models.Blogs.objects.get(slug=obj)
        return context

def SubscriptionCreate(request):
    if request.method == 'POST':
        email = request.POST.get('email_id')
        notification = request.POST.get('notification')
        if email == '':
            message = 'Email cannot be empty'
            return HttpResponse(json.dumps({'message': message}), content_type='application/json')
        else:
            try:
                validate_email(email)
            except:
                message = 'Please enter a valid email address'
                return HttpResponse(json.dumps({'message': message}), content_type='application/json')

            if models.Subscription.objects.filter(email_id=email).exists():
                models.Subscription.objects.filter(
                    email_id=email).update(notification=notification)
                message = 'You are already subscribed to our Newsletter and your notification choice updated'
            else:
                try:
                    m = models.Subscription.objects.create(email_id=email, hash=hash,
                                                               notification=notification,
                                                               )
                except Exception as e:
                    print(e)
                    pass
                m.save()
                # subject2 = "A New Subscription"
                # from_email = "covid19@embassyofficeparks.com"
                # admin_email = "covid19@embassyofficeparks.com"
                #
                # template_object_admin = render_to_string(
                #     'subscribe_admin.html', {"email":email, 'last_name':last_name, "notification": notification})
                # send_mail(subject=subject2, template_object=template_object_admin,
                #   from_email=from_email, to=[admin_email], resume=None,
                #   fail_silently=False)

                message = "Thank you for Subscribing to our Newsletter"

            ctx = {'message': message}
        return HttpResponse(json.dumps(ctx), content_type='application/json')

def Confirm(request, email, hash):
    return render(request, "confirm.html")

def Unsubscribe(request, email, hash):
    for row in models.Subscription.objects.all():
        if models.Subscription.objects.filter(id=row.id).filter(email_id__icontains=email).filter(hash__icontains=hash):
            row.unsubscribe(email)
    return render(request, "unsubcribe.html")

def autocompleteModel(request):
    if request.is_ajax():
        q = request.GET.get('term', '').capitalize()
        search_qs = models.Blogs.objects.filter(
            search_friendly__icontains=q)
        results = []
        # print(q)
        # print(search_qs)
        for r in search_qs:
            results.append(r.blog_title)
        data = json.dumps(results)
    else:
        data = 'fail'
    mimetype = 'application/json'
    return HttpResponse(data, mimetype)

def Blog_search(request, slug=None):
    if request.method == 'GET':
        q = request.GET.get('txtSearch')
        print(q)
        if q:
            try:
                results = models.Blogs.objects.get(
                        blog_title=q, published=1)
                recent = models.Blogs.objects.filter(
                    published=True).order_by('content_published_date')
                # social_feeds_obj = models.SocialFeeds.objects.filter(
                #         published=True)
                return render(request, 'blog/blogdetails.html', {'blog_object': results,'recent':recent})
            except Exception as e:
                results = models.Blogs.objects.filter(
                        Q(search_friendly__icontains=q)
                        | Q(blog_title__icontains=q), published=1)
                return render(request, 'blog/search_results.html', {'blog_object': results})

def FilterView(request):
    response_data = {}
    id = request.GET.get('id')
    response = models.BlogTopic.objects.filter(
                published=True, blog_category__category=id)
    print(response)
    topic_name = [i.topic for i in response]
    return HttpResponse(json.dumps({'topic_name': topic_name}), content_type='application/json')


from pyvisionproductsearch import ProductSearch, ProductCategories
from google.cloud import storage, vision
from google.cloud.vision import types

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

import pandas as pd
from utils import detectLabels, detectObjects
import io
from tqdm import tqdm # Not using jupyter notebook so I removed the .notebook (and it was causing an error)

import os
from dotenv import load_dotenv

load_dotenv()

ps = ProductSearch(os.getenv("PROJECTID"), os.getenv("CREDS"), os.getenv("BUCKET"))
productSet = ps.getProductSet(os.getenv("PRODUCT_SET"))

# For each fashion inspiration pic, check to make sure that it's
# a "fashion" picture. Ignore all other pics
storage_client = storage.Client()
blobs = list(storage_client.list_blobs(os.getenv("INSPO_BUCKET"), prefix=os.getenv("INSPO_SUBFOLDER")))
uris = ["gs://" + blobs[0].bucket.name + "/" + x.name
        for x in blobs if ('.jpg' in x.name or '.png' in x.name)]

# This format of "[... for ... in ... if ...]" is called a Python list comprehension. It is the same thing as saying:
# for (x in blobs):
#     if ('.jpg' in x.name or '.png' in x.name):
#         uri.append("gs://" + blobs[0].bucket.name + "/" + x.name)
urls = [x.public_url for x in blobs if ('.jpg' in x.name or '.png' in x.name)]

fashionPics = []
fashionWords = ["Fashion", "Shoe", "High Heel", "Boot", "Outerwear", "T-shirt", "Footwear", "Jeans", "Pants", "Shorts", "Clothing", "Clothes", "Dress", "Jewelry", "Earrings", "Earring", "Rings", "Ring", "Necklace", "Necklaces", "Style", "Outfit"]
for uri, url in tqdm(list(zip(uris, urls))):
    # Such a simple way to pull labels from an image with Google Vision!
    labels = detectLabels(image_uri=uri)
    # We don't want any bad data. If the AI can't even tell that the inspiration pic is fashion then we don't want to include it in the set
    if any([x.description in fashionWords for x in labels]):
        fashionPics.append((uri, url))
# Select a cell using: fashion_pics['column label'].iloc[row index]
fashion_pics = pd.DataFrame(fashionPics, columns=["uri", "url"])

# We want to recommend items that are similar and of the same type as in the inspiration picture.
# For example, the Product Search API might return a dress as a match for a shirt.
# getBestMatch sorts through the results returned by the API and makes sure that
    # 1. the match with the highest confidence is returned.
    # 2. the item types match (the match in our closet and the match in the inspiration should have the same type)

# The API sometimes uses different names for similar items, so this
# function tells you whether two labels are roughly equivalent
def isTypeMatch(label1, label2):
    # everything in a single match group are more or less synonymous
    matchGroups = [
        ("skirt", "miniskirt"),
        ("jeans", "pants"),
        ("shorts"),
        ("jacket", "vest", "outerwear", "coat", "suit"),
        ("top", "shirt"),
        ("dress"),
        ("swimwear", "underpants"),
        ("footwear", "sandal", "boot", "high heels"),
        ("handbag", "suitcase", "satchel", "backpack", "briefcase"),
        ("sunglasses", "glasses"),
        ("bracelet"),
        ("scarf", "bowtie", "tie"),
        ("earrings"),
        ("necklace"),
        ("sock"),
        ("hat", "cowboy hat", "straw hat", "fedora", "sun hat", "sombrero")]
    for group in matchGroups:
        if label1.lower() in group and label2.lower() in group:
            return True
    return False

# This returns a set of matches for each item identified in the inspiration photo (selected with .iloc[0]).
# For each item, a bounding box is returned that indicates where the item is in the picture.
    # RETURN: For each matched item in your closet, a Product object is returned along with its image id and a confidence score.
    # INPUT: Takes in one match of the response (not the response itself, just one of matches at a time)
def getBestMatch(searchResponse):
    label = searchResponse['label']
    matches = searchResponse['matches']
    viableMatches = [match for match in matches if any([isTypeMatch(label, match['product'].labels['type'])])]
    # If there are any viable matches return them. Otherwise return None
    return max(viableMatches, key= lambda x: x['score']) if len(viableMatches) else None

# Test the functions by seeing fetching the first matched outfit
# fashion_pics['uri'].iloc[0] selects the cell in row 0 in the column 'uri' from the fashion_pics dataframe.
response = productSet.search("apparel", image_uri = fashion_pics['uri'].iloc[0])
# print(fashion_pics) # Prints the dataframe as a table so you can see what inspo pics made it through the purge

def canAddItem(existingArray, newType):
    bottoms = {"pants", "skirt", "shorts", "dress"}
    newType = newType.lower()
    # Don't add the same item type twice
    if newType in existingArray:
        return False
    if newType == "shoe":
        return True
    # Only add one type of bottom (pants, skirt, etc)
    # I want to modify this so leggings can be their own category and worn with skirts/dresses.
    if newType in bottoms and len(bottoms.intersection(existingArray)):
        return False
    # You can't wear both a top and a dress
    if newType == "top" and "dress" in existingArray:
        return False
    return True

# A couple of options for deciding which of the matches give the best outfit

# Option 1: sum up the confidence scores for each closet item matched to the inspo photo
def scoreOutfit1(matches):
    if not matches:
        return 0
    return sum([match['score'] for match in matches]) / len(matches)

# Option 2: Sum up the confidence scores only of items that matched with the inspo photo
# with confidence > 0.3. Also, because shoes will match most images _twice_
# (because people have two feet), only count the shoe confidence score once
# I can't get the second algorithm to work because x["label"] does not exist. It should be going to x["product"]["label"] however that is not possible because x["product"] isn't an interactive object :(
# Deal with this in the future
# OH I wonder if you have to import Product from pyvisionproductsearch. Definitely come back to try that, it would be good to know if that's the issue
# def scoreOutfit2(matches):
#     if not len(matches):
#         return 0
#     for x in matches:
#         print("See if label is here: ", x["product"])
#     noShoeSum = sum([x['score'] for x in matches if (x['score'] > 0.3 and not isTypeMatch("shoe", x["product"]["label"]))])
#     shoeScore = 0
#     try:
#         shoeScore = max([x['score'] for x in matches if isTypeMatch("shoe", x["product"]["label"])])
#     except:
#         pass
#     return noShoeSum + shoeScore * 0.5 # half the weight for shoes

# Final function to put all the helpers together. This is the main one we will interface with.
def getOutfit(imgUri, verbose=False):
    # 1. Search for matching items
    response = productSet.search("apparel", image_uri=imgUri)
    if verbose:
        print("Found matching " + ", ".join([x['label'] for x in response]) + " in closet.")

    clothes = []
    # 2. For each item in the inspo pic, find the best match in our closet and add it to the outfit array
    for item in response:
        bestMatch = getBestMatch(item)
        if not bestMatch:
            if verbose:
                print(f"No good match found for {item['label']}")
            continue
        if verbose:
            print(f"Best match for {item['label']} was {bestMatch['product'].displayName}")
        clothes.append(bestMatch)

    # 3. Sort the items by highest confidence score first
    clothes.sort(key=lambda x: x['score'], reverse=True)

    # 4. Add as many items as possible to the outfit while still
    # maintaining a logical outfit
    outfit = []
    addedTypes = []
    for item in clothes:
        itemType = item['product'].labels['type'] # i.e. shorts, top, etc
        if canAddItem(addedTypes, itemType):
            addedTypes.append(itemType)
            outfit.append(item)
            if verbose:
                print(f"Added a {itemType} to the outfit")

    # 5. Now that we have a whole outfit, compute its score!
    score = scoreOutfit1(outfit)
    if verbose:
        print("Algorithm score: %0.3f" % score)
    return (outfit, score)

# print(getOutfit(fashion_pics.iloc[0]['uri'], verbose=True))

app = firebase_admin.initialize_app(credentials.Certificate(os.getenv("CREDS")))
db = firestore.client()
userid = os.getenv("userid")

doc_ref = db.collection('users').document(userid)
doc = doc_ref.get()
if doc.exists:
    print("User Found")
else:
    print("User Not found, creating document")
    doc_ref.set({"first": "Ada", "last": "Lovelace", "born": 1815})

thisUser = db.collection('users').document(userid)

outfits = thisUser.collection('outfitsDEMO')
# outfits = outfitsRef.get()

# if (outfits.exists):
#     print("OutfitsDEMO Exists")

# Go through all of the inspo pics and compute matches.
for row in fashion_pics.iterrows():
    srcUrl = row[1]['url']
    srcUri = row[1]['uri']
    (outfit, score1) = getOutfit(srcUri, verbose=False)

    # Construct a name for the source image--a key we can use to store it in the database
    srcId = srcUri[len("gs://"):].replace("/","-")

    # Firestore writes json to the database, so let's construct an object and fill it with data
    fsMatch = {
        "srcUrl": srcUrl,
        "srcUri": srcUri,
        "score1": score1,
    }
    # Go through all of the outfit matches and put them into json that can be
    # written to firestore
    theseMatches = []
    for match in outfit:
        image = match['image']
        imgName = match['image'].split('/')[-1]
        name = match['image'].split('/')[-3]
        # The storage api makes these images publicly accessible through url
        imageUrl = f"https://storage.googleapis.com/{os.getenv('BUCKET')}/" + imgName
        label = match['product'].labels['type']
        score = match['score']

        theseMatches.append({
            "score": score,
            "image": image,
            "imageUrl": imageUrl,
            "label": label
        })
    fsMatch["matches"] = theseMatches
    # Add the outfit to firestore!
    outfits.document(srcId).set(fsMatch)


import json
import logging.config
import sys

import os

from pushbullet import PushBullet

logger_configured = False

config = None

pushbullet = None

def set_working_directory():
    os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

def configure_logger(debug_file):
    global logger_configured
    if logger_configured:
        return
    else:
        logger_configured = True
    logging.config.dictConfig({
        "version": 1,
        "formatters": {
            "brief": {
                "format": "[%(asctime)s][%(levelname)s] %(message)s",
                "datefmt": "%H:%M:%S"
            },
            "full": {
                "format": "[%(asctime)s][%(levelname)s] %(message)s",
                "datefmt": "%Y-%m-%d][%H:%M:%S"
            }
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "brief",
                "level": "WARNING",
                "stream": "ext://sys.stderr"
            },
            "file": {
                "class": "logging.FileHandler",
                "formatter": "full",
                "level": "DEBUG",
                "filename": debug_file
            }
        },
        "root": {
            "level": "DEBUG",
            "handlers": ["console", "file"]
        }
    })

def get_config():
    global config
    if config is None:
        config_path = os.path.abspath("config.json")
        if os.path.isfile(config_path):
            with open(config_path) as config_file:
                config = json.load(config_file)
        else:
            logging.warning("Config not found! Please copy config.default.json to config.json")
            sys.exit()
    return config

def get_pushbullet():
    global pushbullet
    if pushbullet is None:
        config = get_config()

        pushbullet = PushBullet(config["pushbullet"]["api-key"])

    return pushbullet


from src.recipe import Recipe

import json

class Recipes:
    """
    Recipes is used to contain multiple Recipe objects
    """

    def __init__(self):
        self.dict_of_recipes = {}

    def len(self):
        return len(self.dict_of_recipes)

    def add_name_item(self, name, recipe):
        self.dict_of_recipes[name] = recipe

    def list_of_recipes_names(self):
        return sorted(self.dict_of_recipes.keys())

    def set_recipes_from_json_file(self, json_file):
        with open(json_file, 'r') as file:
            json_dict = json.load(file)

        for name, jdv in json_dict.items():
            jd_item_dict = {
                name: jdv
            }
            recipe = Recipe()
            json_str = json.dumps(jd_item_dict, indent=4)
            recipe.set_recipe_from_json_str(json_str)
            self.add_name_item(name, recipe)

    def get_recipe_from_recipes_by_name(self, name):
        return self.dict_of_recipes[name]

    def write_recipes_to_json_file(self, json_file):
        expanded_dict_of_recipes = {}
        for name, recipe in self.dict_of_recipes.items():
            fixed_recipe_dict = {}
            for k, v in recipe.dict_of_recipe.items():
                spaced_key = k
                if k not in ['min_servings', 'max_servings']:
                    spaced_key = k.replace('_', ' ')
                fixed_recipe_dict[spaced_key] = v
            expanded_dict_of_recipes[name] = fixed_recipe_dict

        with open(json_file, 'w') as file:
            json.dump(expanded_dict_of_recipes, file, sort_keys=True, indent=4)


import Chemins
from Utils import UTILS_Adaptations
from Utils.UTILS_Traduction import _
import wx
from Ctrl import CTRL_Bouton_image
import GestionDB
from Utils import UTILS_Dates
from Utils import UTILS_Titulaires

from Utils import UTILS_Interface
from Ctrl.CTRL_ObjectListView import FastObjectListView, ColumnDefn, Filter, CTRL_Outils

class Track(object):
    def __init__(self, donnees, dictTitulaires):
        self.IDpiece = donnees[0]
        self.date_debut = UTILS_Dates.DateEngEnDateDD(donnees[1])
        self.date_fin = UTILS_Dates.DateEngEnDateDD(donnees[2])
        self.public = donnees[3]
        self.nomPiece = donnees[4]
        self.IDindividu = donnees[5]
        self.IDfamille = donnees[6]
        self.individu_nom = donnees[7]
        self.individu_prenom = donnees[8]

        # Nom Individu si pièce individuelle
        if self.individu_prenom == None :
            self.individu_nom_complet = self.individu_nom
        else :
            self.individu_nom_complet = u"%s %s" % (self.individu_nom, self.individu_prenom)

        # Nom Famille si pièce familiale
        if self.IDfamille != None :
            self.nom_titulaires = dictTitulaires[self.IDfamille]["titulairesSansCivilite"]
        else :
            self.nom_titulaires = ""

        # Type de pièce
        if self.public == "famille" :
            self.nomPublic = _(u"Familiale")
        else :
            self.nomPublic = _(u"Individuelle")

class ListView(FastObjectListView):
    def __init__(self, *args, **kwds):
        # Récupération des paramètres perso
        self.IDtype_piece = None
        self.date_reference = None
        self.selectionID = None
        self.selectionTrack = None
        self.criteres = ""
        self.itemSelected = False
        self.popupIndex = -1
        self.listeFiltres = []
        # Initialisation du listCtrl
        self.nom_fichier_liste = __file__
        FastObjectListView.__init__(self, *args, **kwds)
        # Binds perso
        self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)

    def InitModel(self):
        self.donnees = self.GetTracks()

    def GetTracks(self):
        """ Récupération des données """
        if self.IDtype_piece == None :
            return []

        if self.date_reference != None :
            conditionDate = "AND pieces.date_debut <= '%s' AND pieces.date_fin >= '%s'" % (self.date_reference, self.date_reference)
        else :
            conditionDate = ""

        listeID = None
        db = GestionDB.DB()
        req = """SELECT pieces.IDpiece, pieces.date_debut, pieces.date_fin,
        types_pieces.public, types_pieces.nom,
        individus.IDindividu, pieces.IDfamille, individus.nom, individus.prenom
        FROM pieces
        LEFT JOIN types_pieces ON types_pieces.IDtype_piece = pieces.IDtype_piece
        LEFT JOIN individus ON individus.IDindividu = pieces.IDindividu
        WHERE pieces.IDtype_piece = %d %s
        ORDER BY individus.nom; """ % (self.IDtype_piece, conditionDate)
        db.ExecuterReq(req)
        listeDonnees = db.ResultatReq()
        db.Close()

        dictTitulaires = UTILS_Titulaires.GetTitulaires()

        listeListeView = []
        for item in listeDonnees :
            valide = True
            if listeID != None :
                if item[0] not in listeID :
                    valide = False
            if valide == True :
                track = Track(item, dictTitulaires)
                listeListeView.append(track)
                if self.selectionID == item[0] :
                    self.selectionTrack = track
        return listeListeView

    def InitObjectListView(self):
        # Couleur en alternance des lignes
        self.oddRowsBackColor = UTILS_Interface.GetValeur("couleur_tres_claire", wx.Colour(240, 251, 237))
        self.evenRowsBackColor = wx.Colour(255, 255, 255)
        self.useExpansionColumn = True

        def FormateDateCourt(dateDD):
            if dateDD == None :
                return ""
            if dateDD == "2999-01-01" :
                return _(u"Illimitée")
            else:
                return UTILS_Dates.DateDDEnFr(dateDD)

        liste_Colonnes = [
            ColumnDefn(_(u"IDPiece"), "left", 0, "IDpiece", typeDonnee="entier"),
            ColumnDefn(_(u"Individu"), 'left', 170, "individu_nom_complet", typeDonnee="texte"),
            ColumnDefn(_(u"Famille"), 'left', 220, "nom_titulaires", typeDonnee="texte"),
            ColumnDefn(u"Du", "left", 80, "date_debut", typeDonnee="date", stringConverter=FormateDateCourt),
            ColumnDefn(_(u"Au"), "left", 80, "date_fin", typeDonnee="date", stringConverter=FormateDateCourt),
            ColumnDefn(_(u"Type de pièce"), "left", 100, "nomPublic", typeDonnee="texte"),
            ]

        # Intégration le filtre inscrits/Présents
        if len(self.donnees) > 0 :
            if self.donnees[0].public == "famille" :
                liste_Colonnes.append(ColumnDefn(_(u"IDfamille"), "left", 40, "IDfamille", typeDonnee="entier"))
            else :
                liste_Colonnes.append(ColumnDefn(_(u"IDindividu"), "left", 40, "IDindividu", typeDonnee="entier"))

        self.SetColumns(liste_Colonnes)
        self.SetEmptyListMsg(_(u"Aucune pièce"))
        self.SetEmptyListMsgFont(wx.FFont(11, wx.DEFAULT, False, "Tekton"))
        self.SetSortColumn(self.columns[1])
        if len(self.donnees) > 0 :
            if self.donnees[0].public == "famille" :
                self.SetSortColumn(self.columns[2])
        self.SetObjects(self.donnees)

    def MAJ(self, ID=None, IDtype_piece=None, date_reference=None):
        self.IDtype_piece = IDtype_piece
        self.date_reference = date_reference
        if ID != None :
            self.selectionID = ID
            self.selectionTrack = None
        else:
            self.selectionID = None
            self.selectionTrack = None
        self.InitModel()
        self.InitObjectListView()
        # Sélection d'un item
        if self.selectionTrack != None :
            self.SelectObject(self.selectionTrack, deselectOthers=True, ensureVisible=True)
        self.selectionID = None
        self.selectionTrack = None

    def Selection(self):
        return self.GetSelectedObjects()

    def OnContextMenu(self, event):
        """Ouverture du menu contextuel """
        if len(self.Selection()) == 0:
            noSelection = True
        else:
            noSelection = False
            ID = self.Selection()[0].IDpiece

        # Création du menu contextuel
        menuPop = UTILS_Adaptations.Menu()

        # Génération automatique des fonctions standards
        self.GenerationContextMenu(menuPop, dictParametres=self.GetParametresImpression())

        self.PopupMenu(menuPop)
        menuPop.Destroy()

    def GetParametresImpression(self):
        if len(self.donnees) > 0 :
            intro = _(u"Pièce sélectionnée : %s") % self.donnees[0].nomPiece
        else :
            intro = ""
        total = _(u"Un total de %d pièces") % len(self.donnees)

        dictParametres = {
            "titre" : _(u"Liste des pièces fournies"),
            "intro" : intro,
            "total" : total,
            "orientation" : wx.PORTRAIT,
            }
        return dictParametres

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

class BarreRecherche(wx.SearchCtrl):
    def __init__(self, parent):
        wx.SearchCtrl.__init__(self, parent, size=(-1, -1), style=wx.TE_PROCESS_ENTER)
        self.parent = parent
        self.rechercheEnCours = False

        self.SetDescriptiveText(_(u"Rechercher une pièce..."))
        self.ShowSearchButton(True)

        self.listView = self.parent.ctrl_donnees
        nbreColonnes = self.listView.GetColumnCount()
        self.listView.SetFilter(Filter.TextSearch(self.listView, self.listView.columns[0:nbreColonnes]))

        self.SetCancelBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Interdit.png"), wx.BITMAP_TYPE_PNG))
        self.SetSearchBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Loupe.png"), wx.BITMAP_TYPE_PNG))

        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.OnSearch)
        self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancel)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnDoSearch)
        self.Bind(wx.EVT_TEXT, self.OnDoSearch)

    def OnSearch(self, evt):
        self.Recherche()

    def OnCancel(self, evt):
        self.SetValue("")
        self.Recherche()

    def OnDoSearch(self, evt):
        self.Recherche()

    def Recherche(self):
        txtSearch = self.GetValue()
        self.ShowCancelButton(len(txtSearch))
        self.listView.GetFilter().SetText(txtSearch)
        self.listView.RepopulateList()
        self.Refresh()

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

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        wx.Frame.__init__(self, *args, **kwds)
        panel = wx.Panel(self, -1, name="test1")
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(panel, 1, wx.ALL|wx.EXPAND)
        self.SetSizer(sizer_1)
        self.myOlv = ListView(panel, id=-1, name="OL_test", style=wx.LC_REPORT|wx.SUNKEN_BORDER|wx.LC_SINGLE_SEL|wx.LC_HRULES|wx.LC_VRULES)
        self.myOlv.MAJ()
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
        sizer_2.Add(self.myOlv, 1, wx.ALL|wx.EXPAND, 4)
        panel.SetSizer(sizer_2)
        self.Layout()

if __name__ == '__main__':
    app = wx.App(0)
    #wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "OL TEST")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()


import pytest
import unittest
from pages.courses.register_courses_page import RegisterCoursesPage
from utilities.teststatus import TestStatus

@pytest.mark.usefixtures('oneTimeSetUp', 'setUp')
class RegisterCoursesTests(unittest.TestCase):

    @pytest.fixture(autouse=True)
    def objectSetup(self, oneTimeSetUp):
        self.courses = RegisterCoursesPage(self.driver)
        self.ts = TestStatus(self.driver)

    @pytest.mark.run(order=1)
    def test_invalid_enrollment(self):
        self.courses.enter_course_name('Python 3')
        # self.courses.click_on_search_button()
        self.courses.select_course_to_enroll('Learn Python 3 from scratch')
        self.courses.enroll_course(num='4567 1234 7890 1010', exp='1023', cvv='455', postal_code='452312')
        result = self.courses.verify_enroll_failed()
        self.ts.mark_final('test_invalid_enrollment', result, 'Enrolment Failed Verification')
        self.courses.logout()


import torch

class TransformerDataset(torch.utils.data.Dataset):
    def __init__(self, texts, labels, tokenizer, max_length):
        self.texts = texts
        self.labels = labels
        self.tokenizer = tokenizer
        self.max_length = max_length

    def __getitem__(self, idx):
        text = str(self.texts[idx])
        text = " ".join(text.split())
        inputs = self.tokenizer(
            text,
            None,
            add_special_tokens=True,
            max_length=self.max_length,
            truncation=True,
            padding="max_length",
            return_tensors="pt",
        )
        inputs = {k: v.type(torch.long).squeeze(0) for k, v in inputs.items()}

        labels_pt = torch.tensor(self.labels[idx], dtype=torch.float)
        return inputs, labels_pt

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


import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models as models

from config import Config

cfg = Config()

def get_model(backbone):
    Model = {
        'resnet18': resnet18,
        'resnet50': resnet50,
        'swin_t': swin_t
    }

    return Model[backbone](cfg)

class resnet18(nn.Module):
    def __init__(self, cfg):
        super(resnet18, self).__init__()
        self.model = models.resnet18(weights='ResNet18_Weights.DEFAULT')
        # self.model.avgpool.output_size = (1, cfg.samples)
        self.model.fc = nn.Sequential(
            # nn.Flatten(),
            nn.BatchNorm1d(self.model.fc.in_features),
            nn.Dropout(p=0.5, inplace=True),
            nn.ReLU(inplace=True),
            nn.Linear(in_features=self.model.fc.in_features, out_features=1, bias=True),
            nn.Sigmoid()
        )

    def forward(self, x):
        out = self.model(x)

        return out

class resnet50(nn.Module):
    def __init__(self, cfg):
        super(resnet50, self).__init__()
        self.model = models.resnet50(weights='ResNet50_Weights.DEFAULT')
        self.model.fc = nn.Sequential(
            nn.BatchNorm1d(self.model.fc.in_features),
            nn.Dropout(p=0.5, inplace=True),
            nn.ReLU(inplace=True),
            nn.Linear(in_features=self.model.fc.in_features, out_features=1, bias=True),
            nn.Sigmoid()
        )

    def forward(self, x):
        out = self.model(x)

        return out

class swin_t(nn.Module):
    def __init__(self, cfg):
        super(swin_t, self).__init__()
        self.model = models.swin_t(weights='Swin_T_Weights.IMAGENET1K_V1')
        # self.model.head = nn.Sequential(
        #     self.model.head,
        #     nn.Linear(self.model.head.out_features, 1),
        #     nn.Sigmoid()
        # )
        # print(self.model.head)
        # exit()
        self.model.head = nn.Sequential(
            nn.BatchNorm1d(768),
            nn.Dropout(p=0.5, inplace=True),
            nn.ReLU(inplace=True),
            nn.Linear(in_features=768, out_features=1, bias=True),
            nn.Sigmoid()
        )

    def forward(self, x):
        out = self.model(x)

        return out


import requests
import yaml

from google.oauth2 import id_token
from google.auth.transport import requests as grequests

from exceptions import InvalidTokenException

with open("secrets.yaml") as f:
    secrets = yaml.load(f, Loader=yaml.FullLoader)
client_id = secrets["Google client ID"]
client_secret = secrets["Google client secret"]

def auth_1():
    response = requests.post("https://oauth2.googleapis.com/device/code", params={
        "client_id": client_id,
        "scope": "email profile", })
    return response.json()

def auth_2(device_code):
    response = requests.post("https://oauth2.googleapis.com/token", params={
        "client_id": client_id,
        "client_secret": client_secret,
        "code": device_code,
        "grant_type": "http://oauth.net/grant_type/device/1.0"
    })
    try:
        return {"access_token": response.json()["id_token"]}
    except:
        return {"error": "Not authorized."}, 403

def token_to_account_id(token):
    try:
        idinfo = id_token.verify_oauth2_token(token, grequests.Request(), client_id)
        return idinfo["sub"]
    except Exception as e:
        print(e)
        raise InvalidTokenException


"""Decoder portion of the model."""

import torch
import torch.nn.functional as F
from torch import nn

def _build_base_decoder():
    """Builds the base decoder shared by all three decoder types."""
    return nn.Sequential(nn.Conv2d(in_channels=1280, out_channels=256, kernel_size=(3, 3), stride=1, padding=1),
                         nn.BatchNorm2d(num_features=256), nn.ReLU())

class Decoders(nn.Module):
    """Module which contains all three decoders."""

    def __init__(self, num_classes: int, enabled_tasks: (bool, bool, bool), output_size=(128, 256)):
        super().__init__()
        self._output_size = output_size
        self._num_classes = num_classes
        self._enabled_tasks = enabled_tasks

        self._base_semseg = _build_base_decoder()
        self._base_insseg = _build_base_decoder()
        self._base_depth = _build_base_decoder()

        kernel_size = (1, 1)
        self._semsegcls = nn.Conv2d(256, self._num_classes, kernel_size)
        self._inssegcls = nn.Conv2d(256, 2, kernel_size)
        self._depthcls = nn.Conv2d(256, 1, kernel_size)

    def set_output_size(self, size):
        self._output_size = size

    def forward(self, x):
        """Returns (sem seg, instance seg, depth)."""
        # x: [batch x 1280 x H/8 x W/8]

        sem_seg_enabled, inst_seg_enabled, depth_enabled = self._enabled_tasks

        if sem_seg_enabled:
            x1 = self._base_semseg(x)
            x1 = self._semsegcls(x1)
            x1 = F.interpolate(x1, size=self._output_size, mode='bilinear', align_corners=True)
        else:
            x1 = None

        if inst_seg_enabled:
            x2 = self._base_insseg(x)
            x2 = self._inssegcls(x2)
            x2 = F.interpolate(x2, size=self._output_size, mode='bilinear', align_corners=True)
        else:
            x2 = None

        if depth_enabled:
            x3 = self._base_depth(x)
            x3 = self._depthcls(x3)
            x3 = F.interpolate(x3, size=self._output_size, mode='bilinear', align_corners=True)
        else:
            x3 = None

        return x1, x2, x3

if __name__ == '__main__':
    # ### Shape test
    output_size = (123, 432)
    model = Decoders(num_classes=20, output_size=output_size)
    test = torch.zeros(size=(2, 1280, 256, 256))
    result = model.forward(test)
    assert result[0].shape == (2, 20, *output_size), "output shape is {}".format(result[0].shape)


# %% IMPORTS
# Built-in imports
import abc
import logging as log

# Package imports
import numpy as np

# IMAGINE imports
from imagine.tools import BaseClass, req_attr

# All declaration
__all__ = ['Field']

# %% CLASS DEFINITIONS
# Define abstract base class for creating fields in IMAGINE
class Field(BaseClass, metaclass=abc.ABCMeta):
    """
    This is the base class which can be used to include a completely new field
    in the IMAGINE pipeline. Base classes for specific physical quantites
    (e.g. magnetic fields) are already available in the module
    :mod:`imagine.fields.basic_fields`.
    Thus, before subclassing `GeneralField`, check whether a more specialized
    subclass is not available.

    For more details check the :ref:`components:Fields` section in the
    documentation.

    Parameters
    ----------
    grid : imagine.fields.grid.BaseGrid
        Instance of :py:class:`imagine.fields.grid.BaseGrid` containing a
        3D grid where the field is evaluated
    parameters : dict
        Dictionary of full parameter set {name: value}
    ensemble_size : int
        Number of realisations in field ensemble
    ensemble_seeds : list
        Random seeds for generating random field realisations
    """

    def __init__(self, grid, *, parameters={}, ensemble_size=None,
                 ensemble_seeds=None, dependencies={}):
        log.debug('@ field::__init__')

        # Call super constructor
        super().__init__()

        self.grid = grid
        self._parameters = {}
        self.parameters = parameters
        # For convenience, when ensemble info is not available,
        # assumes an ensemble of 1
        if ensemble_size is None and ensemble_seeds is None:
            ensemble_size = 1
        self.ensemble_size = ensemble_size
        self.ensemble_seeds = ensemble_seeds
        # Placeholders
        self._deterministic_data = None
        self.dependencies = dependencies

        assert self.type not in self.dependencies_list, 'Field cannot depend on its own field type'

    @property
    @req_attr
    def type(self):
        """Type of the field"""
        return(self.TYPE)

    @property
    @req_attr
    def parameter_names(self):
        """Parameters of the field"""
        return self.PARAMETER_NAMES

    @property
    def dependencies_list(self):
        """Dependencies on other fields"""
        return(getattr(self, 'DEPENDENCIES_LIST', []))

    @property
    @req_attr
    def name(self):
        """
        Name of the field
        """
        return(self.NAME)

    @property
    def stochastic_field(self):
        """
        *True* if the field is stochastic or *False* if the field is
        deterministic (i.e. the output depends only on the parameter values and
        not on the seed value).
        Default value is *False* if subclass does not override
        :attr:`~STOCHASTIC_FIELD`.

        """
        return(getattr(self, 'STOCHASTIC_FIELD', False))

    @property
    @req_attr
    def units(self):
        """Physical units of the field"""
        return(self.UNITS)

    @abc.abstractproperty
    def data_description(self):
        """Summary of what is in each axis of the data array"""
        raise NotImplementedError

    @abc.abstractproperty
    def data_shape(self):
        """Shape of the field data array"""
        raise NotImplementedError

    @abc.abstractmethod
    def compute_field(self, seed):
        """
        This should be overridden with a derived class. It must return an array
        with dimensions compatible with the associated `field_type`.
        See :doc:`documentation <components>`.

        Should not be used directly (use :py:meth:`get_data` instead).

        Parameters
        ----------
        seed : int
            If the field is stochastic, this argument allows setting the random
            number generator seed accordingly.
        """
        raise NotImplementedError

    def get_data(self, i_realization=0, dependencies={}):
        """
        Evaluates the physical field defined by this class.

        Parameters
        ----------
        i_realization : int
            If the field is stochastic, this indexes the realization generated.
            Default value: 0 (i.e. the first realization).
        dependencies : dict
            If the :py:data:`dependencies_list` is non-empty, a dictionary containing
            the requested dependencies must be provided.

        Returns
        -------
        field : astropy.units.quantity.Quantity
            Array of shape :py:data:`data_shape` whose contents are described by
            :py:data:`data_description` in units :py:data:`field_units`.
        """
        if self.stochastic_field:
            assert i_realization < self.ensemble_size
            # Checks and updates dependencies
            self._update_dependencies(dependencies)
            # Computes stochastic field
            seed = self.ensemble_seeds[i_realization]
            field = self.compute_field(seed)
            self._check_realisation(field)
        elif self._deterministic_data is None:
            # Checks and updates dependencies
            self._update_dependencies(dependencies)
            # Computes and caches deterministic field
            field = self.compute_field(None)
            self._check_realisation(field)
            self._deterministic_data = field
        else:
            # Uses the cache of deterministic field
            field = self._deterministic_data

        return field

    def _update_dependencies(self, dependencies):
        for dep in self.dependencies_list:
            if dep not in dependencies:
                raise KeyError('Missing field dependency {}'.format(dep))
        self.dependencies = dependencies

    def _check_realisation(self, field):
        # Checks the units
        assert self.units.is_equivalent(field.unit), 'Field units should be '+self.units
        # Checks the shape
        try:
            assert field.shape == self.data_shape
        except AssertionError:
            print('Incorrect shape, it should be:', self.data_shape)
            print('It is instead:', field.shape)
            print('Description:', self.data_description)
            raise

    @property
    def ensemble_seeds(self):
        return self._ensemble_seeds

    @ensemble_seeds.setter
    def ensemble_seeds(self, ensemble_seeds):
        if ensemble_seeds is None:  # in case no seeds given, choose something
            self._ensemble_seeds = np.random.randint(0, 2**31-1,
                                                     self.ensemble_size)
        else:
            if self.ensemble_size is None:
                self.ensemble_size = len(ensemble_seeds)
            assert len(ensemble_seeds) == self.ensemble_size
            self._ensemble_seeds = ensemble_seeds

    @property
    def parameters(self):
        """
        Dictionary containing parameters used for this field."""
        return self._parameters

    @parameters.setter
    def parameters(self, parameters):
        for k in parameters:
            assert (k in self.parameter_names)
        self._parameters.update(parameters)
        log.debug('update full-set parameters %s' % (parameters))