import numpy as np

from sklearn.preprocessing import LabelEncoder
import torch
import torch.nn.utils.rnn as rnn_utils
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from torch.utils.data.sampler import SubsetRandomSampler
import copy
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split

class PadSequence:
    def __call__(self, batch):
        x = [ix[0] for ix in batch]
        y = [iy[1] for iy in batch]
        y = torch.LongTensor(y)

        padded = rnn_utils.pad_sequence(x, batch_first=True)
        sorted_batch_lengths = [len(p) for p in padded]
        packed = rnn_utils.pack_padded_sequence(padded, sorted_batch_lengths, batch_first=True, enforce_sorted=False)
        return packed, y

def load_dataset(dataset_path, batch_size, shuffle_dataset=True, random_seed=42):
    data_list = np.load(dataset_path, allow_pickle=True)
    x = data_list[:, 0]
    x = [torch.Tensor(arr) for arr in x]

    y = data_list[:, 1]
    le = LabelEncoder()
    le.fit(y)
    y = le.transform(y)
    dataset = list(zip(x, y))

    indices = list(range(len(dataset)))
    if shuffle_dataset:
        np.random.seed(random_seed)
        np.random.shuffle(indices)

    train_indices, val_indices, test_indices = indices[:round(len(indices)*0.7143)], indices[round(len(indices)*0.7143):round(len(indices)*0.7858)], indices[round(len(indices)*0.7858):]

    train_sampler = SubsetRandomSampler(train_indices)
    valid_sampler = SubsetRandomSampler(val_indices)
    test_sampler = SubsetRandomSampler(test_indices)

    train_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                               sampler=train_sampler, collate_fn=PadSequence())
    valid_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                               sampler=valid_sampler, collate_fn=PadSequence())
    test_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                              sampler=test_sampler, collate_fn=PadSequence())

    feature_num = x[0].shape[1]

    print(f'Dataset loaded - train: {len(train_indices)}, val: {len(val_indices)}, test: {len(test_indices)}')
    print(f'\tfeature_num: {feature_num}, classes_num: {len(le.classes_)}')
    return train_loader, valid_loader, test_loader, feature_num, le

def load_augmented_dataset(train_dataset_paths, test_dataset_path, batch_size, shuffle_dataset=True, random_seed=42):
    test_data_list = np.load(test_dataset_path, allow_pickle=True)
    x = []
    ys = []
    data_list_size = None
    for path in train_dataset_paths:
        data_list = np.load(path, allow_pickle=True)
        x += [torch.Tensor(arr) for arr in data_list[:, 0]]
        ys.append(data_list[:, 1])

        if data_list_size is None:
            data_list_size = data_list.shape[0]
        elif data_list_size != data_list.shape[0]:
            raise Exception(f'Datasets are of different sizes: {data_list_size} and {data_list.shape[0]}')

    y = np.concatenate(ys)

    test_x = [torch.Tensor(arr) for arr in test_data_list[:, 0]]
    test_y = test_data_list[:, 1]

    le = LabelEncoder()
    le.fit(test_y)
    y = le.transform(y)
    test_y = le.transform(test_y)
    dataset = list(zip(x, y))
    # test_dataset = list(zip(test_x, test_y))

    indices = list(range(len(test_x)))
    if shuffle_dataset:
        np.random.seed(random_seed)
        np.random.shuffle(indices)

    train_end_index = round(len(indices)*0.7143)
    test_start_index = round(len(indices)*0.7858)
    train_indices, val_indices, test_indices = indices[:train_end_index], indices[train_end_index:test_start_index], indices[test_start_index:]

    train_ds = np.random.randint(0, len(train_dataset_paths) - 1, len(train_indices))
    train_indices = [index + ds * data_list_size for index, ds in zip(train_indices, train_ds)]
    val_ds = np.random.randint(0, len(train_dataset_paths) - 1, len(val_indices))
    val_indices = [index + ds * data_list_size for index, ds in zip(val_indices, val_ds)]
    test_ds = np.random.randint(0, len(train_dataset_paths) - 1, len(test_indices))
    test_indices = [index + ds * data_list_size for index, ds in zip(test_indices, test_ds)]

    print('data_list_size', data_list_size)
    print('np.min(train_ds)', np.min(train_ds), 'np.max(train_ds)', np.max(train_ds))
    print('np.min(val_ds)', np.min(val_ds), 'np.max(val_ds)', np.max(val_ds))
    print('np.min(test_ds)', np.min(test_ds), 'np.max(test_ds)', np.max(test_ds))

    print('np.max(train_indices)', np.max(train_indices))
    print('np.max(val_indices)', np.max(val_indices))
    print('np.max(test_indices)', np.max(test_indices))

    train_sampler = SubsetRandomSampler(train_indices)
    valid_sampler = SubsetRandomSampler(val_indices)
    test_sampler = SubsetRandomSampler(test_indices)

    train_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                               sampler=train_sampler, collate_fn=PadSequence())
    valid_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                               sampler=valid_sampler, collate_fn=PadSequence())
    test_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                              sampler=test_sampler, collate_fn=PadSequence())

    feature_num = x[0].shape[1]

    print(f'Augmented dataset loaded - train: {len(train_indices)}, val: {len(val_indices)}, test: {len(test_indices)}')
    print(f'\tfeature_num: {feature_num}, classes_num: {len(le.classes_)}')
    return train_loader, valid_loader, test_loader, feature_num, le

def train_model(model, num_epochs, loss, optimizer, train_loader, valid_loader, device, patience, verbose=1):
    stopping = 0
    max_val_acc = 0
    model = model.to(device)

    for epoch in range(num_epochs):
        model.train()
        total, correct = 0, 0
        for batch in train_loader:
            x_train = batch[0].to(device)
            y_train = batch[1].to(device)

            optimizer.zero_grad()
            y_train_pred = model(x_train)

            train_loss = loss(y_train_pred, y_train)
            train_loss.backward()
            optimizer.step()
            if verbose >= 2:
                print('Epoch {}:  Train loss: {}'.format(epoch, train_loss.item()))

            _, y_train_pred = torch.max(y_train_pred.data, 1)
            total += y_train_pred.size(0)
            correct += (y_train_pred == y_train).sum().item()
        if verbose >= 1:
            accuracy = 100 * correct / total
            print('Epoch {}:  Train Accuracy: {}%'.format(epoch, '%.4f' % accuracy))

        """
        Validation part:
        """
        model.eval()
        total, correct = 0, 0
        for batch in valid_loader:
            x_valid = batch[0].to(device)
            y_valid = batch[1].to(device)
            y_valid_pred = model(x_valid)
            _, y_valid_pred = torch.max(y_valid_pred.data, 1)

            total += y_valid_pred.size(0)
            correct += (y_valid_pred == y_valid).sum().item()
        if verbose >= 1:
            accuracy = 100 * correct / total
            print('Epoch {}:  Validation Accuracy: {}%\n'.format(epoch, '%.4f' % accuracy))

        """
        Early stopping:
        """
        if max_val_acc < accuracy:
            max_val_acc = accuracy
            weights = copy.deepcopy(model.state_dict())
            stopping = 0
        else:
            stopping = stopping + 1

        if stopping == patience:
            print('Early stopping...')
            print('Restoring best weights')
            model.load_state_dict(weights)
            break

def plot_conf_matrix(y_pred, y_test, le, title=None):
    if title is None:
        title = 'Confusion matrix'

    cm = confusion_matrix(y_test, y_pred)
    ax = plt.subplot()
    sns.heatmap(cm, annot=True, fmt="d")
    plt.title(title)
    plt.xlabel('Predicted label')
    plt.ylabel('Actual label')
    ax.set_xticklabels([''] + le.classes_, rotation=90)
    ax.set_yticklabels([''] + le.classes_, rotation=0)
    plt.show()

def test_model(model, test_loader, classes, le, device, confusion_matrix_title=None, verbose=1):
    model = model.to(device)

    class_correct = [0] * classes
    class_total = [0] * classes
    all_test_pred = []
    all_labels = []
    with torch.no_grad():
        model.eval()
        for batch in test_loader:
            x_test = batch[0].to(device)
            y_test = batch[1].to(device)
            y_test_pred = model(x_test)
            _, y_test_pred = torch.max(y_test_pred.data, 1)

            tp = (y_test_pred == y_test).squeeze()
            all_test_pred.extend(y_test_pred.cpu().numpy())
            all_labels.extend(y_test.cpu().numpy())

            for i in range(y_test_pred.size(0)):
                label = y_test[i].item()
                class_correct[label] += tp[i].item()
                class_total[label] += 1

        classes_accuracies = []
        for i in range(classes):
            class_accuracy = class_correct[i] / class_total[i]
            classes_accuracies.append(class_accuracy)
            if verbose >= 2:
                print('Test Accuracy of {} {}: {}'.format(i, le.inverse_transform([i])[0], 100 * class_accuracy))

        accuracy = sum(class_correct) / sum(class_total)
        if verbose >= 1:
            print('Test Accuracy: {}%'.format('%.4f' % (100 * accuracy)))
            plot_conf_matrix(np.array(all_test_pred), np.array(all_labels), le, confusion_matrix_title)

    return accuracy, classes_accuracies

def test_hyper_parameters(num_runs, dataset_path, batch_size,
                          num_epochs, learning_rate, weight_decay,
                          model_cls, model_args, device, patience, verbose=1):
    train_loader, valid_loader, test_loader, feature_num, le = load_dataset(dataset_path, batch_size)
    classes = len(list(le.classes_))

    model_args['feature_num'] = feature_num
    model_args['classes'] = classes

    loss = torch.nn.CrossEntropyLoss()
    bestAcc = 0
    accuracies = []
    class_accuracies = []
    for run in range(num_runs):
        model = model_cls(**model_args)
        optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay)

        train_model(model, num_epochs, loss, optimizer, train_loader, valid_loader, device, patience, verbose=verbose)
        accuracy, class_acc = test_model(model, test_loader, classes, le, device, verbose=verbose)
        accuracies.append(accuracy)
        class_accuracies.append(class_acc)

        if accuracy > bestAcc:
            bestAcc = accuracy
            bestModel = copy.deepcopy(model)

    if verbose >= 1:
        print(
            'Test Accuracy	0-Accuracy	1-Accuracy	2-Accuracy	3-Accuracy	4-Accuracy	5-Accuracy	6-Accuracy')
        for run in range(num_runs):
            print_string = f'{accuracies[run]}'
            class_acc = class_accuracies[run]
            for acc in class_acc:
                print_string += f'	{acc}'

            print(print_string)

    return np.mean(accuracies), accuracies, class_accuracies, bestModel

def test_hyper_parameters_augmented(num_runs, clean_dataset_path, train_dataset_paths, test_dataset_path, batch_size,
                                    num_epochs, learning_rate, weight_decay,
                                    model_cls, model_args, device, patience, verbose=1):
    clean_train_loader, clan_valid_loader, clean_test_loader, clean_feature_num, clean_le = load_dataset(
        clean_dataset_path, batch_size)
    train_loader, valid_loader, test_loader, feature_num, le = load_augmented_dataset(train_dataset_paths,
                                                                                test_dataset_path, batch_size)
    clean_classes = len(list(clean_le.classes_))
    classes = len(list(le.classes_))

    model_args['feature_num'] = feature_num
    model_args['classes'] = classes

    loss = torch.nn.CrossEntropyLoss()

    noise_accuracies = []
    noise_class_accuracies = []
    clean_accuracies = []
    clean_class_accuracies = []
    for run in range(num_runs):
        model = model_cls(**model_args)
        optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=weight_decay)

        train_model(model, num_epochs, loss, optimizer, train_loader, valid_loader, device, patience, verbose=verbose)
        noise_accuracy, noise_class_acc = test_model(model, test_loader, classes, le, device,
                                                     confusion_matrix_title='Confusion Matrix Augmented',
                                                     verbose=verbose)
        clean_accuracy, clean_class_acc = test_model(model, clean_test_loader, clean_classes, clean_le, device,
                                                     confusion_matrix_title='Confusion Matrix Clean', verbose=verbose)
        noise_accuracies.append(noise_accuracy)
        noise_class_accuracies.append(noise_class_acc)
        clean_accuracies.append(clean_accuracy)
        clean_class_accuracies.append(clean_class_acc)

    if verbose >= 1:
        print('Noise test results:')
        print_test_results(noise_accuracies, noise_class_accuracies)
        print('Clean test results:')
        print_test_results(clean_accuracies, clean_class_accuracies)

    return (np.mean(clean_accuracies), clean_accuracies, clean_class_accuracies,
            np.mean(noise_accuracies), noise_accuracies, noise_class_accuracies,
            model)

def print_test_results(accuracies, class_accuracies):
    print(
        'Test Accuracy	0-Accuracy	1-Accuracy	2-Accuracy	3-Accuracy	4-Accuracy	5-Accuracy	6-Accuracy')
    for run in range(len(accuracies)):
        print_string = f'{accuracies[run]}'
        class_acc = class_accuracies[run]
        for acc in class_acc:
            print_string += f'	{acc}'

        print(print_string)

if __name__ == '__main__':
    import os
    from training import load_dataset
    from training import train_model
    from training import test_hyper_parameters
    from models import LSTM, GRU, VanillaRNN

    if torch.cuda.is_available():
        device = torch.cuda.current_device()
        print('Current device:', torch.cuda.get_device_name(device))
    else:
        print('Failed to find GPU. Will use CPU.')
        device = 'cpu'

    dataset_path = os.path.join('big_data_list.npy')
    train_dataset_paths = [
        dataset_path,
        os.path.join('big_data_list_engine-0.3.npy'),
        os.path.join('big_data_list_piano-0.4.npy'),
        os.path.join('big_data_list_l_noise-0.3.npy'),
    ]
    test_dataset_path = os.path.join('big_data_list_talking-0.4.npy')

    ## Parameters:
    num_runs = 2
    patience = 20
    batch_size = 64
    num_epochs = 1
    learning_rate = 0.001
    weight_decay = 0.01
    model_args = {
        'num_layers': 1,
        'hidden_size': 256,
        'linear_size': 128,
        'bidirectional': True,
    }

    results = test_hyper_parameters_augmented(num_runs=num_runs,
                                              clean_dataset_path=dataset_path,
                                              train_dataset_paths=train_dataset_paths,
                                              test_dataset_path=test_dataset_path,
                                              batch_size=batch_size,
                                              num_epochs=num_epochs,
                                              learning_rate=learning_rate,
                                              weight_decay=weight_decay,
                                              model_cls=LSTM,
                                              model_args=model_args,
                                              device=device, patience=patience,
                                              verbose=1)

    print(results[0])
    print(results[3])


## author@Wenhui Yu  2021.02.16
## read train/test/validation data
## transform data into wanted structures
## return user and item number, and padding train data
## read (hyper-) graph embeddings, propoagation embeddings, and pre-trained embeddings
## construct sparse graph

import json
import numpy as np
import random as rd
from dense2sparse import propagation_matrix

def read_data(path):
    with open(path) as f:
        line = f.readline()
        data = json.loads(line)
    f.close()
    user_num = len(data)
    item_num = 0
    interactions = []
    for user in range(user_num):
        for item in data[user]:
            interactions.append((user, item))
            item_num = max(item, item_num)
    item_num += 1
    rd.shuffle(interactions)
    return(data, interactions, user_num, item_num)

def read_bases(path, fre_u, fre_v):
    with open(path) as f:
        line = f.readline()
        bases = json.loads(line)
    f.close()
    [feat_u, feat_v] = bases
    feat_u = np.array(feat_u)[:, 0: fre_u].astype(np.float32)
    feat_v = np.array(feat_v)[:, 0: fre_v].astype(np.float32)
    return [feat_u, feat_v]

def read_bases1(path, fre, _if_norm = False):
    with open(path) as f:
        line = f.readline()
        bases = json.loads(line)
    f.close()
    if _if_norm:
        for i in range(len(bases)):
            bases[i] = bases[i]/np.sqrt(np.dot(bases[i], bases[i]))
    return np.array(bases)[:, 0: fre].astype(np.float32)

def read_all_data(all_para):
    [_, DATASET, MODEL, _, _, _, EMB_DIM, _, _, _, IF_PRETRAIN, TEST_VALIDATION, _, FREQUENCY_USER, FREQUENCY_ITEM, FREQUENCY, _, _, GRAPH_CONV, _, _, _, _, _, _, _, PROP_DIM, PROP_EMB, IF_NORM] = all_para
    [hypergraph_embeddings, graph_embeddings, propagation_embeddings, sparse_propagation_matrix] = [0, 0, 0, 0]

    ## Paths of data
    DIR = 'dataset/' + DATASET + '/'
    train_path = DIR + 'train_data.json'
    test_path = DIR + 'test_data.json'
    validation_path = DIR + 'validation_data.json'
    hypergraph_embeddings_path = DIR + 'hypergraph_embeddings.json'                     # hypergraph embeddings
    graph_embeddings_1d_path = DIR + 'graph_embeddings_1d.json'                         # 1d graph embeddings
    graph_embeddings_2d_path = DIR + 'graph_embeddings_2d.json'                         # 2d graph embeddings
    pre_train_feature_path = DIR + 'pre_train_feature' + str(EMB_DIM) + '.json'         # pretrained latent factors
    if MODEL == 'SGNN': propagation_embeddings_path = DIR + 'pre_train_feature' + str(PROP_DIM) + '.json'   # pretrained latent factors

    ## Load data
    ## load training data
    print('Reading data...')
    [train_data, train_data_interaction, user_num, item_num] = read_data(train_path)
    ## load test data
    teat_vali_path = validation_path if TEST_VALIDATION == 'Validation' else test_path
    test_data = read_data(teat_vali_path)[0]
    ## load pre-trained embeddings for all deep models
    if IF_PRETRAIN:
        try: pre_train_feature = read_bases(pre_train_feature_path, EMB_DIM, EMB_DIM)
        except:
            print('There is no pre-trained embeddings found!!')
            pre_train_feature = [0, 0]
            IF_PRETRAIN = False

    ## load pre-trained transform bases for LCFN and SGNN
    if MODEL == 'LCFN': hypergraph_embeddings = read_bases(hypergraph_embeddings_path, FREQUENCY_USER, FREQUENCY_ITEM)
    if MODEL == 'LGCN':
        if GRAPH_CONV == '1D': graph_embeddings = read_bases1(graph_embeddings_1d_path, FREQUENCY)
        if GRAPH_CONV == '2D_graph': graph_embeddings = read_bases(graph_embeddings_2d_path, FREQUENCY_USER, FREQUENCY_ITEM)
        if GRAPH_CONV == '2D_hyper_graph': graph_embeddings = read_bases(hypergraph_embeddings_path, FREQUENCY_USER, FREQUENCY_ITEM)
    if MODEL == 'SGNN':
        if PROP_EMB == 'RM': propagation_embeddings = read_bases(propagation_embeddings_path, PROP_DIM, PROP_DIM)
        if PROP_EMB == 'SF': propagation_embeddings = read_bases1(graph_embeddings_1d_path, PROP_DIM, IF_NORM)
        if PROP_EMB == 'PE': propagation_embeddings = 0

    ## convert dense graph to sparse graph
    if MODEL in ['GCMC', 'SCF', 'CGMC']: sparse_propagation_matrix = propagation_matrix(train_data_interaction, user_num, item_num, 'left_norm')
    elif MODEL in ['NGCF', 'LightGCN']: sparse_propagation_matrix = propagation_matrix(train_data_interaction, user_num, item_num, 'sym_norm')

    return train_data, train_data_interaction, user_num, item_num, test_data, pre_train_feature, hypergraph_embeddings, graph_embeddings, propagation_embeddings, sparse_propagation_matrix, IF_PRETRAIN


# -*- coding: utf-8 -*-
import json
import os
import more_itertools
import math
import argparse

from jinja2 import Environment, FileSystemLoader
from livereload import Server

def rebuild(json_file_path):
    with open(json_file_path, 'r', encoding='utf-8') as json_file:
        books = json.load(json_file)
    total_books = len(books)
    books_per_page = 20
    book_pages = list(more_itertools.chunked(books, books_per_page))
    total_pages = math.ceil(total_books / books_per_page)
    for page_num, page_books in enumerate(book_pages, start=1):
        env = Environment(loader=FileSystemLoader('.'))
        template = env.get_template('template.html')
        render_html = template.render(
            books=page_books,
            current_page=page_num,
            total_pages=total_pages,
        )
        page_filename = f'pages/index{page_num}.html'
        with open(page_filename, 'w', encoding='utf-8') as html_file:
            html_file.write(render_html)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--json',
        default='media/book_parse.json',
        help='Путь к файлу book_parse.json'
    )
    args = parser.parse_args()

    if not os.path.exists('pages'):
        os.makedirs('pages')

    rebuild(args.json)
    server = Server()
    server.watch('template.html', lambda: rebuild(args.json))
    server.serve(root='.')


import json
import os

import geopandas as gpd
import matplotlib.pyplot as plt
import pandas as pd

import osmnx as ox

# configure script
cities = ["olomouc", "belfast", "hong_kong"]
edge_buffer_dists = [10, 50]
indicators_filepath = "./indicators.csv"
figure_filepath = "./fig/street-comparison-{city}.png"

if not os.path.exists("./fig/"):
    os.makedirs("./fig/")

def load_data(osm_graphml_path, osm_buffer_gpkg_path, official_streets_gpkg_path):
    """
    Load the street network edges and study boundary.

    Parameters
    ----------
    osm_graphml_path : str
        path to the OSM graphml file
    osm_buffer_gpkg_path : str
        path to the buffered study area geopackage
    official_streets_gpkg_path : str
        path to the official streets shapefile

    Returns
    -------
    gdf_osm_streets_clipped, gdf_official_streets_clipped, study_area : tuple
        the osm streets (clipped to the study area), the official streets
        (clipped to the study area), and the study area polygon
    """

    # load the study area boundary as a shapely (multi)polygon
    gdf_study_area = gpd.read_file(osm_buffer_gpkg_path, layer="urban_study_region")
    study_area = gdf_study_area["geometry"].iloc[0]
    print(ox.ts(), "loaded study area boundary")

    # load the official streets shapefile
    gdf_official_streets = gpd.read_file(official_streets_gpkg_path)
    print(ox.ts(), "loaded official streets shapefile")

    # load the graph, make it undirected, then get edges GeoDataFrame
    gdf_osm_streets = ox.graph_to_gdfs(ox.get_undirected(ox.load_graphml(osm_graphml_path)), nodes=False)
    print(ox.ts(), "loaded osm edges and made undirected streets")

    # Project the data to a common crs
    crs = gdf_study_area.crs
    if gdf_osm_streets.crs != crs:
        gdf_osm_streets = gdf_osm_streets.to_crs(crs)
        print(ox.ts(), "projected osm streets")
    if gdf_official_streets.crs != crs:
        gdf_official_streets = gdf_official_streets.to_crs(crs)
        print(ox.ts(), "projected official streets")

    # spatially clip the streets to the study area boundary
    import warnings

    warnings.filterwarnings("ignore", "GeoSeries.notna", UserWarning)  # temp warning suppression
    gdf_osm_streets_clipped = gpd.clip(gdf_osm_streets, study_area)
    gdf_official_streets_clipped = gpd.clip(gdf_official_streets, study_area)
    print(ox.ts(), "clipped osm/official streets to study area boundary")

    # double-check everything has same CRS, then return
    assert gdf_osm_streets_clipped.crs == gdf_official_streets_clipped.crs == gdf_study_area.crs
    return gdf_osm_streets_clipped, gdf_official_streets_clipped, study_area

def plot_data(gdf_osm, gdf_official, study_area, filepath, figsize=(10, 10), bgcolor="#333333", projected=True):
    """
    Plot the OSM vs official streets and save to disk.

    Parameters
    ----------
    gdf_osm : geopandas.GeoDataFrame
        the osm streets
    gdf_official : geopandas.GeoDataFrame
        the official streets
    study_area : shapely.Polygon or shapely.MultiPolygon
        the study area boundary
    filepath : str
        path to save figure as file
    figsize : tuple
        size of plotting figure
    bgcolor : str
        background color of plot
    projected : bool
        True if gdfs are projected rather than lat-lng

    Returns
    -------
    fig, ax : tuple
    """

    fig, ax = plt.subplots(figsize=figsize, facecolor=bgcolor)
    ax.set_facecolor(bgcolor)

    # turn study_area polygon into gdf with correct CRS
    gdf_boundary = gpd.GeoDataFrame(geometry=[study_area], crs=gdf_osm.crs)

    # plot study area, then official streets, then osm streets as layers
    _ = gdf_boundary.plot(ax=ax, facecolor="k", label="Study Area")
    _ = gdf_official.plot(ax=ax, color="r", lw=1, label="Official Data")
    _ = gdf_osm.plot(ax=ax, color="y", lw=1, label="OSM Data")

    ax.axis("off")
    if projected:
        # only make x/y equal-aspect if data are projected
        ax.set_aspect("equal")

    # create legend
    ax.legend()

    # save to disk
    fig.savefig(filepath, dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor())
    print(ox.ts(), f'figure saved to disk at "{filepath}"')

    plt.close()
    return fig, ax

def total_edge_length_count(gdf_streets):
    """
    Calculate the total length and count of streets in gdf.

    Parameters
    ----------
    gdf_streets : geopandas.GeoDataFrame
        the osm or official streets

    Returns
    -------
    streets_total_length, streets_count : tuple
    """
    streets_total_length = gdf_streets.length.sum()
    streets_count = len(gdf_streets)
    return streets_total_length, streets_count

def calculate_overlap(a, b, dist):
    """
    Calculate the % overlap of a and b's lines and buffered lines' areas
    given different buffering distances.

    Parameters
    ----------
    a : geopandas.GeoDataFrame
        the osm streets
    b : geopandas.GeoDataFrame
        the osm streets
    dist : int
        buffer distance in meters

    Returns
    -------
    a_area_pct, b_area_pct, a_length_pct, b_length_pct : tuple
    """

    # buffer each by the current distance
    a_buff = a.buffer(dist)
    b_buff = b.buffer(dist)

    # take the unary union of each's buffered geometry
    a_buff_unary = a_buff.unary_union
    b_buff_unary = b_buff.unary_union

    # find the portion of each's buffered geometry that intersects with the other's buffered geometry
    a_buff_overlap = a_buff_unary.intersection(b_buff_unary)
    b_buff_overlap = b_buff_unary.intersection(a_buff_unary)

    # what % of each's buffered area does that intersecting portion comprise?
    a_area_pct = a_buff_overlap.area / a_buff_unary.area
    b_area_pct = b_buff_overlap.area / b_buff_unary.area

    # take the unary union of each's original unbuffered lines
    a_unary = a.unary_union
    b_unary = b.unary_union

    # find each's lines that intersect the intersecting buffered portion
    a_overlap = a_unary.intersection(a_buff_overlap)
    b_overlap = b_unary.intersection(b_buff_overlap)

    # what % of each's lines length does that intersecting portion comprise?
    a_length_pct = a_overlap.length / a_unary.length
    b_length_pct = b_overlap.length / b_unary.length

    return a_area_pct, b_area_pct, a_length_pct, b_length_pct

# RUN THE SCRIPT
indicators = {}
for city in cities:

    print(ox.ts(), f"begin processing {city}")
    indicators[city] = {}

    # load this city's configs
    with open(f"../configuration/{city}.json") as f:
        config = json.load(f)

    # load street gdfs from osm graph and official shapefile, then clip to study area boundary polygon
    gdf_osm_streets, gdf_official_streets, study_area = load_data(
        config["osm_graphml_path"], config["osm_buffer_gpkg_path"], config["official_streets_gpkg_path"]
    )

    # plot map of study area + osm and official streets, save to disk
    fp = figure_filepath.format(city=city)
    fig, ax = plot_data(gdf_osm_streets, gdf_official_streets, study_area, fp)

    # calculate total street length and edge count in each dataset, then add to indicators
    osm_total_length, osm_edge_count = total_edge_length_count(gdf_osm_streets)
    official_total_length, official_edge_count = total_edge_length_count(gdf_official_streets)
    indicators[city]["osm_total_length"] = osm_total_length
    indicators[city]["osm_edge_count"] = osm_edge_count
    indicators[city]["official_total_length"] = official_total_length
    indicators[city]["official_edge_count"] = official_edge_count
    print(ox.ts(), "calculated edge lengths and counts")

    # calculate the % overlaps of areas and lengths between osm and official streets with different buffer distances
    for dist in edge_buffer_dists:
        osm_area_pct, official_area_pct, osm_length_pct, official_length_pct = calculate_overlap(
            gdf_osm_streets, gdf_official_streets, dist
        )
        indicators[city][f"osm_area_pct_{dist}"] = osm_area_pct
        indicators[city][f"official_area_pct_{dist}"] = official_area_pct
        indicators[city][f"osm_length_pct_{dist}"] = osm_length_pct
        indicators[city][f"official_length_pct_{dist}"] = official_length_pct
        print(ox.ts(), f"calculated area/length of overlaps for buffer {dist}")

# turn indicators into a dataframe and save to disk
df_ind = pd.DataFrame(indicators).T
df_ind.to_csv(indicators_filepath, index=True, encoding="utf-8")
print(ox.ts(), f'all done, saved indicators to disk at "{indicators_filepath}"')


from dataclasses import asdict, dataclass

from apibara import Info
from apibara.model import BlockHeader, StarkNetEvent

from dao import utils
from dao.indexer import storage
from dao.indexer.base_event import BaseEvent
from dao.indexer.deserializer import BlockNumber

@dataclass
class VoteSubmitted(BaseEvent):
    callerAddress: bytes
    proposalId: int
    vote: bool
    onBehalfAddress: bytes

    async def _handle(
        self, info: Info, block: BlockHeader, starknet_event: StarkNetEvent
    ):
        # TODO: store both callerAddress and onBehalfAddress, we'll need to know
        # who voted at some point
        if self.vote:
            update_proposal_vote = {"$push": {"yesVoters": self.onBehalfAddress}}
        else:
            update_proposal_vote = {"$push": {"noVoters": self.onBehalfAddress}}

        await storage.update_proposal(
            proposal_id=self.proposalId,
            update=update_proposal_vote,
            info=info,
        )

        if self.vote:
            update_member_vote = {"$push": {"yesVotes": self.proposalId}}
        else:
            update_member_vote = {"$push": {"noVotes": self.proposalId}}

        await storage.update_member(
            member_address=self.onBehalfAddress,
            update=update_member_vote,
            info=info,
        )

@dataclass
class MemberAdded(BaseEvent):
    memberAddress: bytes
    shares: int
    loot: int
    onboardedAt: BlockNumber

    async def _handle(
        self, info: Info, block: BlockHeader, starknet_event: StarkNetEvent
    ):
        member_dict = {
            **asdict(self),
            "jailedAt": None,
            "exitedAt": None,
        }
        await info.storage.insert_one("members", member_dict)

@dataclass
class MemberUpdated(BaseEvent):
    memberAddress: bytes
    delegateAddress: bytes
    shares: int
    loot: int
    jailed: bool
    lastProposalYesVote: int
    onboardedAt: BlockNumber

    async def _handle(
        self, info: Info, block: BlockHeader, starknet_event: StarkNetEvent
    ):
        update_member_dict = asdict(self)

        block_datetime = utils.get_block_datetime_utc(block)

        # TODO: keep history of jailed and exited
        update_member_dict["jailedAt"] = block_datetime if self.jailed else None
        update_member_dict["exitedAt"] = block_datetime if not self.shares else None

        return await storage.update_member(
            member_address=self.memberAddress,
            update={"$set": update_member_dict},
            info=info,
        )

@dataclass
class RoleGranted(BaseEvent):
    account: bytes
    role: str
    sender: bytes

    async def _handle(
        self, info: Info, block: BlockHeader, starknet_event: StarkNetEvent
    ):
        # TODO: add roles history
        return await storage.update_member(
            member_address=self.account,
            update={"$push": {"roles": self.role}},
            info=info,
        )

@dataclass
class RoleRevoked(BaseEvent):
    account: bytes
    role: str
    sender: bytes

    async def _handle(
        self, info: Info, block: BlockHeader, starknet_event: StarkNetEvent
    ):
        # TODO: add roles history
        return await storage.update_member(
            member_address=self.account,
            update={"$pull": {"roles": self.role}},
            info=info,
        )


# import the necessary packages
from PIL import Image
import os
from imutils import paths
import argparse
import cv2
from pathlib import Path
import numpy as np
import sys
from sightengine.client import SightengineClient

def get_image_sharpness2(path):
    im = Image.open(path).convert('L')  # to grayscale
    array = np.asarray(im, dtype=np.int32)

    gy, gx = np.gradient(array)
    gnorm = np.sqrt(gx ** 2 + gy ** 2)
    sharpness = np.average(gnorm)
    return sharpness

def get_image_dimensions(imagePath):

    # Inline import for PIL because it is not a common library
    with Image.open(imagePath) as img:
        # Calculate the width and hight of an image
        width, height = img.size
    # calculat ethe size in bytes
    size_bytes = os.path.getsize(imagePath)
    a =  str(height) + ", " + str(width) + ", " + str((size_bytes)/1000)
    return a
    # return dict(width=width, height=height, size_bytes=size_bytes)

for i in range(0,4290):

    path = r'C:\Users\training.CSSCORP\Desktop\Video\Vid1\1080\frame'+str(i)+'.png'
    print(path)

    # image = cv2.imread(path)
    # image = cv2.resize(image, (1600, 1600))
    # image = cv2.GaussianBlur(image, (3, 3), 0)
    # image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    fm = get_image_sharpness2(path)
    info = get_image_dimensions(path)
    # text = imagePath + " - " + str(fm)
    # print(imagePath + " -  Blurriness:" + str(fm) + " - " + info)

    f = open(r'C:\Users\training.CSSCORP\Desktop\Notes\Week 4\14.06.19\miniproj\sharp_1080_v1.csv','a')
    f.write("  \n" + path + ", " + info + ", " + str(fm))
    f.close()


import sympy
print(sympy.__file__)
from sympy import Abs
import numpy as np
import argparse

from examples.seismic import Model
from examples.seismic import TimeAxis
from examples.seismic import RickerSource
from examples.seismic import Receiver
from devito import Eq, solve
from devito import Operator
from examples.seismic import plot_shotrecord

parser = argparse.ArgumentParser()
parser.add_argument('--velocity_setup', action="store", dest="vsetup", type=str, default=None, required=True,
                    help=" expects a npz file with shape, spacing, origin and velocity model")
parser.add_argument('--src_loc', action="store", dest="src_loc", type=str, default=None, required=True)
parser.add_argument('--rec_loc_setup', action="store", dest="rec_loc_setup", type=str, default=None, required=True,
                    help=" expects a npz file with receiver locations n_point x 3 matrix")
parser.add_argument('--time', action="store", dest="time", type=float, default=1.0)

# Argument loading
res = parser.parse_args()
REC_LOC_SETUP = res.rec_loc_setup
rsetup = np.load(REC_LOC_SETUP)
REC_LOC = rsetup["rec_loc"]
SRC_LOC = res.src_loc
SRC_LOC_X, SRC_LOC_Y, SRC_LOC_Z = [float(a) for a in SRC_LOC.split(',')]
VSETUP = res.vsetup
setup = np.load(VSETUP)
shape = setup["shape"]
spacing = setup["spacing"]
origin = setup["origin"]
v = setup["velocity_model"]
TIME = res.time

model = Model(vp=v, origin=origin, shape=shape, spacing=spacing,
              space_order=2, nbl=10, bcs="damp")

#### SOURCE SETTING ####
t0 = 0.  # Simulation starts a t=0
tn = np.ceil(TIME * 1000)  # Simulation last 1 second (1000 ms)
dt = model.critical_dt  # Time step from model grid spacing
time_range = TimeAxis(start=t0, stop=tn, step=dt)
f0 = 0.010  # Source peak frequency is 10Hz (0.010 kHz)
src = RickerSource(name='src', grid=model.grid, f0=f0,
                   npoint=1, time_range=time_range)

src.coordinates.data[0, :] = np.array([SRC_LOC_X, SRC_LOC_Y, SRC_LOC_Z])
#src.show()

#### RECEIVER SETTING ####
rec = Receiver(name='rec', grid=model.grid, npoint=REC_LOC.shape[0], time_range=time_range)
rec.coordinates.data[:,:] = REC_LOC

# ACOUSTIC MODEL

from devito import TimeFunction
u = TimeFunction(name="u", grid=model.grid, time_order=2, space_order=2)
pde = model.m * u.dt2 - u.laplace + model.damp * u.dt

stencil = Eq(u.forward, solve(pde, u.forward))
src_term = src.inject(field=u.forward, expr=src * dt**2 / model.m)
rec_term = rec.interpolate(expr=u.forward)
op = Operator([stencil] + src_term + rec_term, subs=model.spacing_map)
op(time=time_range.num-1, dt=model.critical_dt)
plot_shotrecord(rec.data, model, t0, tn)


# -*- coding: utf-8 -*-
"""
Created on Tue Jan 26 14:32:59 2016

@author: Jee-Bee for jBae (c) 2016
"""

import sys
if sys.version_info.major <3:
    from __future__ import division
import numpy as np
from src.signal import chirp
from src import Transform, Window, DefaultFigures
import matplotlib.pyplot as plt
# from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# from matplotlib.ticker import LinearLocator, FormatStrFormatter

"""transfer function test
Signal out is signal for speaker.
Signal in1 is recorded by mic.
Signal in2 is recorded + filter
transfer function is:
    in signal     in1    in2
H = ---------- --> --- or ---
    out signal     out    out
"""

# http://www.mathworks.com/matlabcentral/answers/33500-2nd-order-digital-butterworth-filter
# Filtering acc:
# [B, A] = sig.butter(2, ff[0] / fs, 'bandstop')
# in3 = np.transpose(sig.filtfilt(B, A, np.transpose(in3)))
# [B, A] = sig.butter(4, (ff[1] * 2)/fs, 'bandstop')
# in3 = np.transpose(sig.filtfilt(B, A, np.transpose(in3)))
# [B, A] = sig.butter(2, 19000 * 2 / fs, 'lowpass')
# in3 = np.transpose(sig.filtfilt(B, A, np.transpose(in3)))

#
#N = 64
#t = np.arange(0, 1, 1 / N)
#x = chirp(t, 1, 1, 8, phi=90)
#y = 2 * np.sin(2 * np.pi * 4 * t) + 0.707 * np.sin(2 * np.pi * 6 * t)
#
#X = fft(x)
#Y = fft(y)
#F = np.arange(-N/2+1, N/2+1)
#
#Xr = np.real(X)
#Xi = np.imag(X)
#Yr = np.real(Y)
#Yi = np.imag(Y)
#
## From here test\
## for now just real and imag or complex.
## next step also Magnitude and phase
#
## Most Needed Function is not finished...
#
## X_in = x, X_out = complex
#H0_1_val = Transform.Transfer(x, Y, N)
#
## X_in = tuple, X_out = complex
#H0_2_val = Transform.Transfer((Xr, Xi), Y, N)
#
## X_in = complex, X_out = tuple
#H0_3_val = Transform.Transfer(X, (Yr, Yi), N)
## Fix Odd symmetry check
#
#plt.plot(F,abs(X))
#
#plt.figure()
#plt.plot(t,x,t,y)
#plt.figure()
#plt.plot(F,abs(X))
#plt.plot(F,np.real(X),F,np.imag(X))
#plt.figure()
#plt.plot(F, H0_1_val, F, H0_2_val, F, H0_3_val)
#
#

#
# ----- Part 2 of test
#

# signal generation
# allready exist
N = 2 ** 16
fs = 2 ** 12
overlap = 50  # [%]
t = np.arange(0, N / fs, 1 / fs)
x = chirp(t, 20, N / fs - 1 / fs, 2000, phi=90)
x = np.append(x, np.zeros(fs))  # silece for tail of real live sound

y = sd.playrec(x, samplerate=fs, channels=1)
sd.wait()
y = np.reshape(y, len(y))
# averaging multiple signals
# pass  # for later on

# window + multi fft
Nw = fs
hannw = Window.Window(Nw)
(dummy, hann) = hannw.hanwind()

S_1 = np.sum(hann)
S_2 = np.sum(hann ** 2)
NENBW = Nw * S_2 / (S_1 ** 2)
ENBW = fs * S_2 / (S_1 ** 2)  # = NENBW * fs/N

print(NENBW, ENBW)

overlap = overlap/100 *Nw
idxl = 0
idxu = Nw
Y = []
while idxu <= len(y):
    (F, Yd) = Transform.FFT(y[idxl:idxu] * hann, fs)
    #np.concatenate([a[None,:],b[None,:]])
#    http://stackoverflow.com/questions/21887754/numpy-concatenate-two-arrays-vertically?rq=1
    if Y == []:
        Y = np.append(Y,  Yd)
    else:
        Y = np.vstack((Y, Yd))
    #(F, Y) = np.append(Y, Transform.FFT(y[idxl:idxu] * hann,fs), axis=1)
    idxl += (Nw - overlap)
    idxu += (Nw - overlap)
Y /= S_1
#Y = np.reshape(Y,(Nw,len(Y)/Nw))
twind = np.arange(0,16.5,0.5)
twind, F = np.meshgrid(twind, F)
if np.shape(F) != np.shape(Y):
    Y = Y.T

## Later on fix
## now not volt_rms so PS, PSD, LS and LSD are just V and not V_rms
## PS_rms = 2 * np.abs(y_m)/S1 equation 23
#PS_rms = 2 * np.abs(WIND_nf)/S_1
#
## PSD_rms = PS_rms/ENBW equation 24
#PSD_rms = 2 * np.abs(WIND_nf)**2/(fs*S_2)

# spectogram
#DefaultFigures.Default3D(Y, F, twind)

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(twind, F, abs(Y), rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
#ax.set_zlim(-1.01, 1.01)

#ax.zaxis.set_major_locator(LinearLocator(10))
#ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

#spectfig = DefaultFigures.default3D(twind, F, Y)
#spectfig.Spect()

#
# ---TEST-----------TEST------------TEST----------TEST----
#

#H4 = OUT / fftshift(IN1)
#plt.figure()
#plt.plot(t, ifft(H4))  # hold all;
#
#SIH3 = fftshift(ifft(H3))
#ISH3 = ifft(fftshift(H3))
#
#plt.figure()
## plt.plot(t, SIH3)# hold all;
#plt.plot(t, ISH3)


import os
import time
import argparse
from tqdm import tqdm

# Command-line arguement parsing code.
parser = argparse.ArgumentParser()
parser.add_argument("--basepath", "-b", type=str, help="Enter the location of all the .tar files.")
parser.add_argument("--destination", "-d", type=str, help="Enter the destination to extract all files.")
args = parser.parse_args()

errorFiles = []

# Creating the destination folder if does not exist already.
if not os.path.exists(args.destination):
    os.makedirs(args.destination)

# Loop to go through every .tar file and extract it in the destination folder.
for file in tqdm(os.listdir(args.basepath)):
    if file.endswith('.tar') and 'mai' in file and 'pDSSAT' in file:
        try:
            #print("[INFO]. Extracting {}".format(os.path.join(args.basepath, file)))
            os.system("tar -xf {} --directory={}".format(os.path.join(args.basepath, file), args.destination))
        except:
            print("[ERROR]. Cannot extract {} file properly.".format(os.path.join(args.basepath, file)))
            errorFiles.append(os.path.join(args.basepath, file))
            print("[INFO]. Process will continue shortly.")
            time.sleep(5)

# Checking if encountered error in any .tar file.
if len(errorFiles) == 0:
    print("[FINISH]. Successfully extracted all the files.")
else:
    print("[INCOMPLETE][ERROR]. Some Files are not extracted properly.")
    print("[INCOMPLETE][ERROR]. List : ", errorFiles)


import pytest
from life_grid import LifeGrid

steps_cases = [("""
........
....*...
...**...
........
""",
"""
........
...**...
...**...
........
"""),
("""
*.......
....*...
...**...
........
""",
"""
........
...**...
...**...
........
"""),
]

class TestGridEvolution:

    @pytest.mark.parametrize("in_grid, out_grid", steps_cases)
    def test_evolution(self, in_grid, out_grid):
        g1 = LifeGrid.from_string( in_grid )
        g2 = LifeGrid.from_string( out_grid )
        assert g2 == g1.step()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Views directly related to individual courses and course sub-objects.

.. $Id$
"""

from __future__ import print_function, absolute_import, division
__docformat__ = "restructuredtext en"

logger = __import__('logging').getLogger(__name__)

from requests.structures import CaseInsensitiveDict

from zope import component

from zope.event import notify

from zope.i18n import translate

from pyramid import httpexceptions as hexc

from nti.app.base.abstract_views import AbstractAuthenticatedView

from nti.app.externalization.error import raise_json_error

from nti.app.externalization.view_mixins import BatchingUtilsMixin
from nti.app.externalization.view_mixins import ModeledContentUploadRequestUtilsMixin

from nti.app.products.courseware.views import MessageFactory as _

from nti.app.publishing import TRX_TYPE_PUBLISH
from nti.app.publishing import TRX_TYPE_UNPUBLISH

from nti.contenttypes.presentation.interfaces import IConcreteAsset
from nti.contenttypes.presentation.interfaces import INTILessonOverview

from nti.externalization.interfaces import LocatedExternalDict
from nti.externalization.interfaces import StandardExternalFields

from nti.ntiids.ntiids import is_valid_ntiid_string
from nti.ntiids.ntiids import find_object_with_ntiid

from nti.recorder.record import get_transactions

ITEMS = StandardExternalFields.ITEMS
ITEM_COUNT = StandardExternalFields.ITEM_COUNT
LAST_MODIFIED = StandardExternalFields.LAST_MODIFIED

class AbstractRecursiveTransactionHistoryView(AbstractAuthenticatedView,
                                              BatchingUtilsMixin):

    """
    An abstract helper class to gather transaction history from course
    outline components, including nodes, lessons, etc. The result is a
    batched set of sorted transactions.

    Params:

    sortOrder - Either 'descending' or 'ascending'; defaults to ascending.
    """

    _DEFAULT_BATCH_SIZE = 20
    _DEFAULT_BATCH_START = 0
    _FILTER_NODE_TYPES = (TRX_TYPE_PUBLISH, TRX_TYPE_UNPUBLISH)

    def _get_items(self):
        """
        Subclasses should define this.
        """
        raise NotImplementedError()

    def _get_transactions(self, obj):
        result = ()
        if obj is not None:
            result = get_transactions(obj, sort=False)
        return result

    def __get_number_items_needed(self, total_item_count):
        number_items_needed = total_item_count
        batch_size, batch_start = self._get_batch_size_start()
        if batch_size is not None and batch_start is not None:
            number_items_needed = min(batch_size + batch_start + 2,
                                      total_item_count)
        return number_items_needed

    def _accum_lesson_transactions(self, lesson_overview, accum):
        accum.extend(self._get_transactions(lesson_overview))
        for overview_group in lesson_overview or ():
            accum.extend(self._get_transactions(overview_group))
            for item in overview_group or ():
                item = IConcreteAsset(item, item)
                accum.extend(self._get_transactions(item))

    def _filter_node_transactions(self, transactions):
        # Exclude publish/unpublish node events, since these are essential
        # dupes of lesson publish/unpublish.
        for transaction in transactions:
            if transaction.type not in self._FILTER_NODE_TYPES:
                yield transaction

    def _get_node_items(self, origin_node):
        accum = list()

        def handle_node(node):
            traxs = self._get_transactions(node)
            node_transactions = self._filter_node_transactions(traxs)
            accum.extend(node_transactions)
            for child in node.values() or ():
                handle_node(child)
            lesson_ntiid = node.LessonOverviewNTIID
            if lesson_ntiid:
                lesson_overview = component.queryUtility(INTILessonOverview,
                                                         name=lesson_ntiid)
                if lesson_overview is not None:
                    self._accum_lesson_transactions(lesson_overview, accum)

        handle_node(origin_node)
        return accum

    @property
    def _sort_desc(self):
        sort_order_param = self.request.params.get('sortOrder', 'ascending')
        return sort_order_param.lower() == 'descending'

    def __call__(self):
        result = LocatedExternalDict()
        result.__name__ = self.request.view_name
        result.__parent__ = self.request.context

        items = self._get_items()
        if items:
            result[LAST_MODIFIED] = max(x.createdTime for x in items)
            items.sort(key=lambda t: t.createdTime, reverse=self._sort_desc)
        result['TotalItemCount'] = item_count = len(items)

        # Supply this number to batching to prevent batch-ext links from showing
        # up if we've exhausted our supply.
        number_items_needed = self.__get_number_items_needed(item_count)
        self._batch_items_iterable(result, items,
                                   number_items_needed=number_items_needed)
        result[ITEM_COUNT] = len(result.get(ITEMS) or ())
        return result

class AbstractChildMoveView(AbstractAuthenticatedView,
                            ModeledContentUploadRequestUtilsMixin):
    """
    Move a given object between two parents in a course. The source
    and target NTIIDs must exist beneath the given context (no
    nodes are allowed to move between roots).

    Body elements:

    ObjectNTIID
            The NTIID of the object being moved.

    ParentNTIID
            The NTIID of the new parent node of the object being moved.

    Index
            (Optional) The index at which to insert the node in our parent.

    OldParentNTIID
            (Optional) The NTIID of the old parent of our moved
            node.

    :raises HTTPUnprocessableEntity if the parents do not exist, if the item
            does not exist in the old parent, or if moving between roots.
    """

    # The notify event on move.
    notify_type = None

    def _get_children_ntiids(self, parent_ntiid=None):
        """
        Subclasses should implement this to allow
        validation of movements within this context.
        """
        return ()

    def _get_context_ntiid(self):
        """
        Subclasses should implement this to define the contextual ntiid.
        Can return null.
        """
        return getattr(self.context, 'ntiid', None)

    def _remove_from_parent(self, parent, obj):
        """
        Define how to remove an item from a parent.
        """
        raise NotImplementedError()

    def _get_object_to_move(self, ntiid, old_parent=None):
        obj = find_object_with_ntiid(ntiid)
        if obj is None:
            raise_json_error(self.request,
                             hexc.HTTPUnprocessableEntity,
                             {
                                 'message': _(u"Object no longer exists."),
                             },
                             None)
        return obj

    def _get_old_parent(self, old_parent_ntiid):
        result = None
        if old_parent_ntiid:
            result = find_object_with_ntiid(old_parent_ntiid)
            if result is None:
                raise_json_error(self.request,
                                 hexc.HTTPUnprocessableEntity,
                                 {
                                     'message': _(u"Old item parent no longer exists."),
                                 },
                                 None)
        return result

    def _get_new_parent(self, context_ntiid, new_parent_ntiid):
        if new_parent_ntiid == context_ntiid:
            new_parent = self.context
        else:
            new_parent = find_object_with_ntiid(new_parent_ntiid)

        if new_parent is None:
            # Really shouldn't happen if we validate this object is in our
            # outline.
            raise_json_error(self.request,
                             hexc.HTTPUnprocessableEntity,
                             {
                                 'message': _(u"New parent does not exist."),
                             },
                             None)
        return new_parent

    def _validate_parents(self, old_parent_ntiid=None, new_parent_ntiid=None,
                          context_ntiid=None, *unused_args, **unused_kwargs):
        children_ntiids = self._get_children_ntiids(context_ntiid)
        if      new_parent_ntiid not in children_ntiids \
            or (old_parent_ntiid
                and old_parent_ntiid not in children_ntiids):
            raise_json_error(self.request,
                             hexc.HTTPUnprocessableEntity,
                             {
                                 'message': _(u"Cannot move between root objects."),
                             },
                             None)

    def __call__(self):
        values = CaseInsensitiveDict(self.readInput())
        index = values.get('Index')
        ntiid = values.get('ObjectNTIID')
        new_parent_ntiid = values.get('ParentNTIID')
        old_parent_ntiid = values.get('OldParentNTIID')
        context_ntiid = self._get_context_ntiid()

        new_parent = self._get_new_parent(context_ntiid, new_parent_ntiid)
        old_parent = self._get_old_parent(old_parent_ntiid)
        if old_parent is None:
            old_parent = new_parent
        self._validate_parents(old_parent=old_parent,
                               new_parent=new_parent,
                               old_parent_ntiid=old_parent_ntiid,
                               new_parent_ntiid=new_parent_ntiid,
                               context_ntiid=context_ntiid)

        if index is not None and index < 0:
            raise_json_error(self.request,
                             hexc.HTTPBadRequest,
                             {
                                 'message': _(u"Invalid index."),
                             },
                             None)
        obj = self._get_object_to_move(ntiid, old_parent)
        new_parent.insert(index, obj)

        # Make sure they don't move the object within the same node and
        # attempt to delete from that node.
        if old_parent_ntiid and old_parent_ntiid != new_parent_ntiid:
            did_remove = self._remove_from_parent(old_parent, obj)
            if not did_remove:
                raise_json_error(self.request,
                                 hexc.HTTPUnprocessableEntity,
                                 {
                                     'message': _(u"Moved item does not exist in old parent."),
                                 },
                                 None)
            old_parent.childOrderLock()

        if self.notify_type:
            notify(self.notify_type(obj, self.remoteUser.username,
                                    index, old_parent_ntiid=old_parent_ntiid))
        logger.info('Moved item (%s) at index (%s) (to=%s) (from=%s)',
                    ntiid, index, new_parent_ntiid, old_parent_ntiid)
        new_parent.childOrderLock()
        return self.context

class IndexedRequestMixin(object):

    def _get_index(self):
        """
        If the user supplies an index, we expect it to exist on the
        path: '.../index/<index_number>'
        """
        index = None
        if self.request.subpath and self.request.subpath[0] == 'index':
            try:
                index = self.request.subpath[1]
                index = int(index)
            except (TypeError, IndexError):
                msg = translate(_(u"Invalid index ${index}.",
                                  mapping={'index': index})),
                raise_json_error(self.request,
                                 hexc.HTTPUnprocessableEntity,
                                 {
                                     'message': msg,
                                 },
                                 None)
        index = index if index is None else max(index, 0)
        return index

class NTIIDPathMixin(object):

    def _get_ntiid(self):
        """
        Looks for a user supplied ntiid in the context path: '.../ntiid/<ntiid>'.
        """
        result = None
        if self.request.subpath and self.request.subpath[0] == 'ntiid':
            try:
                result = self.request.subpath[1]
            except (TypeError, IndexError):
                pass
        if result is None or not is_valid_ntiid_string(result):
            msg = translate(_(u"Invalid ntiid ${ntiid}.",
                              mapping={'ntiid': result})),
            raise_json_error(self.request,
                             hexc.HTTPUnprocessableEntity,
                             {
                                 'message': msg,
                             },
                             None)
        return result

class DeleteChildViewMixin(NTIIDPathMixin):
    """
    A view to delete a child underneath the given context.

    index
            This param will be used to indicate which object should be
            deleted. If the object described by `ntiid` is no longer at
            this index, the object will still be deleted, as long as it
            is unambiguous.

    :raises HTTPConflict if state has changed out from underneath user
    """

    def _get_children(self):
        return self.context

    def _is_target(self, obj, ntiid):
        return ntiid == getattr(obj, 'ntiid', '')

    def _validate(self):
        pass

    def _remove(self, item=None, index=None):
        """
        Subclasses should override to implement removal.
        """
        raise NotImplementedError()

    def _get_item(self, ntiid, index):
        """
        Find the item or index to delete for the given ntiid and index.
        """

        # If the index param is an empty string, we should treat
        # it the same as if it was not included at all. We should
        # only raise a 422 if the index is a non-numeric string.
        if index:
            try:
                index = int(index)
            except ValueError:
                raise_json_error(self.request,
                                 hexc.HTTPUnprocessableEntity,
                                 {
                                     'message': _(u"Index must be an int."),
                                 },
                                 None)
        found = []
        for idx, child in enumerate(self._get_children()):
            if self._is_target(child, ntiid):
                if idx == index:
                    # We have an exact ref hit.
                    return None, idx
                else:
                    found.append(child)

        if len(found) == 1:
            # Inconsistent match, but it's unambiguous.
            return found[0], None

        if found:
            # Multiple matches, none at index
            msg = _(u'Ambiguous item ref no longer exists at this index.')
            raise_json_error(self.request,
                             hexc.HTTPConflict,
                             {
                                 'message': msg,
                             },
                             None)

    def __call__(self):
        self._validate()
        values = CaseInsensitiveDict(self.request.params)
        index = values.get('index')
        ntiid = self._get_ntiid()
        found = self._get_item(ntiid, index)
        if found:
            to_delete, index = found
            self._remove(to_delete, index)
            self.context.childOrderLock()
        return hexc.HTTPOk()


# 作业1 : 分页获取豆瓣的数据（json数据）， 把电影图片存入本地，且图片名取电影名
# url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start="+ str(i * 20)+"&limit=20"
import json
import urllib.request
import os

path = r'/home/misaka/PycharmProjects/PaChong/day02/img'

headers = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'
}

x = 0
for i in range(1, 3):
    url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=" + str(i * 20) + "&limit=20"

    req = urllib.request.Request(url,headers=headers)
    response = urllib.request.urlopen(req)
    context = response.read().decode()

    json_list = json.loads(context)
    # print(json_list)

    # print(cover_url)
    for item in json_list:
        cover_url = item['cover_url']
        file_name = item['title']
        x += 1
        urllib.request.urlretrieve(cover_url,'/home/misaka/PycharmProjects/PaChong/day02/img/'+file_name+'.jpg')
        print(x,'下载中')


import os
import sys
import pygame as pg

from . import tools

SCREEN_SIZE = (1000, 600)
ORIGINAL_CAPTION = 'Puzzle'

pg.mixer.pre_init(44100, -16, 1, 512)
pg.init()
os.environ['SDL_VIDEO_CENTERED'] = 'TRUE'
SCREEN = pg.display.set_mode(SCREEN_SIZE)
SCREEN_RECT = SCREEN.get_rect()

PICS_AMOUNT = 10
DIFFICULTY_SIZE = (9, 16, 25)
TURN_TIME = [(5000, 10000), (4000, 8000), (3000, 6000)]
TRANSITION_TIME = 700

def graphics_from_directories(directories):
    """
    Calls the tools.load_all_graphics() function for all directories passed.
    """
    base_path = os.path.join("resources", "graphics")
    GFX = {}
    for directory in directories:
        if getattr(sys, 'frozen', False):
            path = os.path.join(os.path.dirname(sys.executable), 'graphics',
                                directory)
        else:
            path = os.path.join(base_path, directory)
        GFX[directory] = tools.load_all_gfx(path)
    return GFX

_SUB_DIRECTORIES = ['gui']
GFX = graphics_from_directories(_SUB_DIRECTORIES)

fonts_path = os.path.join('resources', 'fonts')
FONTS = tools.load_all_fonts(fonts_path)

sfx_path = os.path.join('resources', 'sounds')
SFX = tools.load_all_sfx(sfx_path)

music_path = os.path.join('resources', 'music')
MUSIC = tools.load_all_music(music_path)

tools.music_station.create_playlist(MUSIC.values())

def transparent_surface(width, height, alpha=0):
    surface = pg.Surface((width, height)).convert()
    surface.set_alpha(alpha)
    return surface.convert_alpha()

def make_transition(state, name, alpha_transition=False, duration=None):
    image = pg.Surface(SCREEN_RECT.size).convert()
    state.draw(image)
    state.persist['next_state'] = name
    state.persist['next_image'] = image
    if alpha_transition:
        state.persist['alpha_transition'] = True
    if duration:
        state.persist['duration'] = duration
    state.next = 'TRANSITION'
    state.done = True


from setuptools import setup

from pathlib import Path
this_directory = Path(__file__).parent
long_description = (this_directory / "README.md").read_text()

setup(
    name="dort",
    version="1.4.1",
    description="dort solver/email api wrapper for python",
    url="https://github.com/chaarlottte/dortsolver-python-api",
    author="chaarlottte",
    packages=[
        "dort",
        "dort.captcha",
        "dort.mail"
    ],
    install_requires=[
        "imap-tools",
        "requests"
    ],
    long_description=long_description,
    long_description_content_type="text/markdown"
)


import pandas as pd
import os
import datetime
from mailcleaner import MailCleaner
from fileordering import *

### Driver code ###
if __name__ == "__main__":
    #Link to directory of files to clean
    file_path =  input("What's the absolute file path where you are storing the files?: ")
    directory = r'{}'.format(file_path)

    #convert xls files to csv
    print('Converting excel files to csv...')
    for file_name in os.listdir(directory):
        print(file_name)
        if file_name[-3:] != 'xls':
            continue

        convert_to_csv(file_name)

    #Create empty dataframes
    manhattan_df = pd.DataFrame(columns = ['Address 2', 'Name', 'Address', 'City',
    'State', 'Zip Code', 'Building Year'])

    brooklyn_df = pd.DataFrame(columns = ['Address 2', 'Name', 'Address', 'City',
    'State', 'Zip Code', 'Building Year'])

    unknown_df = pd.DataFrame(columns = ['Address 2', 'Name', 'Address', 'City',
    'State', 'Zip Code', 'Building Year'])

    #Loop over the directory and apply a cleaner to each
    for file_name in os.listdir(directory):
        #Skip the non-csv version of the file
        if file_name[-3:] != 'csv':
            continue

        #Read in the dataframe and the cleaner file
        df = pd.read_csv(file_path + '/' + file_name)
        print('\n')
        print('original data for ' + file_name[28:-4] + ' has ' + str(df.shape[0]) + ' rows')

        #Create cleaner
        cleaner = MailCleaner()

        #Clean data
        df = cleaner.filter_names(df)
        df = cleaner.format_names(df)
        df = cleaner.remove_duplicates(df)
        df = cleaner.remove_special_units(df)
        df = cleaner.filter_multi_units(df)
        df = cleaner.delete_cols(df)
        df = cleaner.delete_prev_unit(df=df, file_name=file_name)
        df = cleaner.populate_address(df, file_name)
        df = cleaner.populate_year(df=df, file_name=file_name)

        #Rename columns to match sheets
        df.rename(columns={"Unit/Tax lot": "Address 2", "Owner": "Name"}, inplace=True)

        print('cleaned data for ' + file_name[28:-4] + ' has ' + str(df.shape[0]) + ' rows')

        print('appending data ...')
        #Switch over the address to find proper df (Brooklyn, Manhattan or Unkonwn')
        if 'Brooklyn' in df['City'].values.tolist():
            brooklyn_df = brooklyn_df.append(df)
        elif 'New York' in df['City'].values.tolist():
            manhattan_df = manhattan_df.append(df)
        else:
            unknown_df = unknown_df.append(df)

        print('---------------------------------------------')

    #Get time to create a unique file each time
    time = str(datetime.datetime.now())[0:19].replace(':', '-')

    #Print and Download data based on time stamp
    #Manhattan
    print('Manhattan Data: ')
    print(manhattan_df)
    manhattan_df.to_csv('manhattan_data - ' + time + '.csv')
    print('\n')

    #Brooklyn
    print('Brooklyn Data: ')
    print(brooklyn_df)
    brooklyn_df.to_csv('brooklyn_data - ' + time + '.csv')
    print('\n')

    #Unknown
    print('Uncategorized Data: ')
    print(unknown_df)
    unknown_df.to_csv('unknown_data - ' + time + '.csv')


from utils.dspp_hidden import DSPPHHiddenLayer
from gpytorch.models.deep_gps.dspp import DSPP
from gpytorch.mlls import DeepPredictiveLogLikelihood

from gpytorch.models.deep_gps import DeepGP
from utils.deep_gp_hidden import DeepGPHiddenLayer
from gpytorch.mlls import DeepApproximateMLL, VariationalELBO

def deep_gp_ll(model, x_batch, y_batch):
    return model.likelihood.log_marginal(y_batch, model(x_batch)).cpu()

def dspp_ll(model, x_batch, y_batch):
    base_batch_ll = model.likelihood.log_marginal(y_batch, model(x_batch))
    deep_batch_ll = model.quad_weights.unsqueeze(-1) + base_batch_ll
    batch_log_prob = deep_batch_ll.logsumexp(dim=0)
    return batch_log_prob.cpu()

def create_deep_gp_config(num_inducing):
    return {
        "class_type": DeepGP,
        "hidden_layer_type": DeepGPHiddenLayer,
        "objective": lambda likelihood, model, num_data : DeepApproximateMLL(
            VariationalELBO(likelihood, model, num_data)
        ),
        "hidden_info": {"num_inducing": num_inducing},
        "class_init_info": {},
        "log_likelihood_cal": deep_gp_ll,
    }

def create_dspp_config(num_inducing, num_quad_site):
    return {
        "class_type": DSPP,
        "hidden_layer_type": DSPPHHiddenLayer,
        "objective": lambda likelihood, model, num_data : DeepPredictiveLogLikelihood(
            likelihood, model, num_data, beta=0.5
        ),
        "hidden_info": {"num_inducing": num_inducing, "num_quad_sites": num_quad_site},
        "class_init_info": {"num_quad_sites": num_quad_site},
        "log_likelihood_cal": dspp_ll,
    }


import numpy as np
import os
import constants
from numpy.linalg import inv
from dataloader import indoor_scenes
import torch
from collections import OrderedDict, Counter
from tqdm import tqdm

def project_image_to_world(x, y, depth, cam2world, depth_intrinsic):
    I = torch.zeros(4, depth.shape[0]).type(torch.cuda.FloatTensor)
    I[0, :] = x * depth
    I[1, :] = y * depth
    I[2, :] = depth
    I[3, :] = 1.0
    world_coordinates = torch.mm(torch.from_numpy(cam2world).type(torch.cuda.FloatTensor), torch.mm(
        torch.from_numpy(inv(depth_intrinsic)).type(torch.cuda.FloatTensor), I))

    del I, x, y, depth
    torch.cuda.empty_cache()

    return world_coordinates

def project_images_to_world(depths, cam2worlds, depth_intrinsic, superpixels, frames):
    x = np.linspace(0, constants.DEPTH_WIDTH - 1, constants.DEPTH_WIDTH)
    y = np.linspace(0, constants.DEPTH_HEIGHT - 1, constants.DEPTH_HEIGHT)
    x_mesh, y_mesh = np.meshgrid(x, y)

    world_coordinates = torch.zeros(4, len(depths) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.FloatTensor)
    frame_origins = torch.zeros(len(depths) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.IntTensor)
    superpixel_origins = torch.zeros(len(depths) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.IntTensor)

    for im_idx in range(len(depths)):
        world_coordinates[:, im_idx * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT: (im_idx + 1) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT] = project_image_to_world(torch.from_numpy(x_mesh).type(torch.cuda.FloatTensor).flatten(),
                                                                                torch.from_numpy(y_mesh).type(torch.cuda.FloatTensor).flatten(), torch.from_numpy(depths[im_idx][:]).type(torch.cuda.FloatTensor).flatten(), cam2worlds[im_idx], depth_intrinsic)
        frame_origins[im_idx * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT: (im_idx + 1) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT] = torch.ones(
            constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT).type(torch.cuda.IntTensor) * frames[im_idx]

        superpixel_origins[im_idx * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT: (im_idx + 1) * constants.DEPTH_WIDTH * constants.DEPTH_HEIGHT] = torch.from_numpy(superpixels[im_idx].astype(np.int).flatten()).type(torch.cuda.IntTensor)

    # visualize_point_cloud(world_coordinates)

    return world_coordinates, frame_origins, superpixel_origins

def project_world_to_image(depth, superpixel_map, cam2world, depth_intrinsic, world_coordinates, frame_origins, superpixel_origins):
    world_coordinates_copy = world_coordinates.transpose(0, 1)[:, :3]
    projected_points = torch.mm(torch.mm(torch.from_numpy(depth_intrinsic).type(torch.cuda.FloatTensor),
                                         torch.from_numpy(inv(cam2world)).type(torch.cuda.FloatTensor)), world_coordinates)
    projected_points = projected_points.transpose(0, 1)[:, :3]
    projected_points[:, 0] /= projected_points[:, 2]
    projected_points[:, 1] /= projected_points[:, 2]
    projected_points[:, 2] /= projected_points[:, 2]
    selection_mask = ~torch.isnan(projected_points[:, 2])

    projected_points = torch.round(projected_points[selection_mask])
    frame_origins = frame_origins[selection_mask]
    superpixel_origins = superpixel_origins[selection_mask]
    world_coordinates_copy = world_coordinates_copy[selection_mask]

    # remove out of frame bounds
    selection_mask = (projected_points[:, 0] >= 0) & (projected_points[:, 0] < constants.DEPTH_WIDTH) & (
        projected_points[:, 1] >= 0) & (projected_points[:, 1] < constants.DEPTH_HEIGHT)

    projected_points = projected_points[selection_mask][:, :2]
    frame_origins = frame_origins[selection_mask]
    superpixel_origins = superpixel_origins[selection_mask]
    world_coordinates_copy = world_coordinates_copy[selection_mask]

    depth = torch.from_numpy(depth).type(torch.cuda.FloatTensor)
    depth = depth[projected_points[:, 1].type(torch.cuda.LongTensor), projected_points[:, 0].type(torch.cuda.LongTensor)].flatten()
    backprojected_points = project_image_to_world(projected_points[:, 0], projected_points[
        :, 1], depth, cam2world, depth_intrinsic).transpose(0, 1)[:, :3]

    selection_mask = (torch.norm(world_coordinates_copy - backprojected_points, dim=1) < constants.WORLD_DISTANCE_THRESHOLD)

    projected_points = projected_points[selection_mask]

    if projected_points.shape[0] == 0:
        return None

    frame_origins = frame_origins[selection_mask]
    superpixel_origins = superpixel_origins[selection_mask]
    superpixel_targets = superpixel_map[projected_points[:, 1].type(torch.cuda.LongTensor).cpu().numpy(), projected_points[:, 0].type(torch.cuda.LongTensor).cpu().numpy()].flatten()
    t1, t2 = np.unique(superpixel_map, return_counts=True)
    target_superpixel_sizes = dict(zip(t1, t2))

    frame_spx = torch.zeros((frame_origins.shape[0], 3)).type(torch.cuda.IntTensor)
    frame_spx[:, 0] = torch.from_numpy(superpixel_targets.astype(np.int)).type(torch.cuda.IntTensor)
    frame_spx[:, 1] = frame_origins
    frame_spx[:, 2] = superpixel_origins

    uniques, counts = torch.unique(frame_spx, dim=0, return_counts=True)
    frame_spx_counts = {}
    for idx, u in enumerate(uniques.tolist()):
        frame_spx_counts[tuple(u)] = float(counts[idx].cpu().item())

    coverage_dict = {}
    for i in frame_spx_counts:
        coverage = frame_spx_counts[i] / target_superpixel_sizes[i[0]]
        coverage_dict[(i[0], i[1], i[2])] = coverage

    return coverage_dict  # , projected_points

def find_superpixel_coverage(dataset_name, lmdb_handle, superpixel_dir, base_size, images):
    dataset = indoor_scenes.IndoorScenesWithAllInfo(dataset_name, lmdb_handle, superpixel_dir, base_size, images)
    scene_id_to_index = dataset.scene_id_to_index

    image_paths = []

    for scene_id in tqdm(scene_id_to_index, desc='Scene[Coverage]'):
        all_frame_coverages = OrderedDict()
        depths = []
        poses = []
        superpixels = []
        intrinsic = None

        for frame_id in scene_id_to_index[scene_id]:
            sample = dataset[frame_id]
            depths.append(sample['depth'])
            poses.append(sample['pose'])
            superpixels.append(sample['superpixel'])
            intrinsic = sample['intrinsic']

        world_coordinates, frame_origins, superpixel_origins = project_images_to_world(depths, poses, intrinsic, superpixels, scene_id_to_index[scene_id])

        for frame_id in tqdm(scene_id_to_index[scene_id], desc='Scene[Project]'):
            sample = dataset[frame_id]
            frame_coverages = project_world_to_image(sample['depth'], sample['superpixel'], sample['pose'], sample['intrinsic'], world_coordinates, frame_origins, superpixel_origins)
            if not frame_coverages is None:
                all_frame_coverages[frame_id] = frame_coverages
                image_paths.append(images[frame_id])
        #from pprint import pprint
        #pprint(all_frame_coverages)
        np.save(os.path.join(constants.SSD_DATASET_ROOT, dataset_name, "raw", "selections", "coverage_"+superpixel_dir, f'{scene_id}.npy'), all_frame_coverages)

        del world_coordinates, frame_origins, superpixel_origins
        del depths, poses, superpixels, all_frame_coverages
        torch.cuda.empty_cache()

    with open(os.path.join(constants.SSD_DATASET_ROOT, dataset_name, "raw", "selections", "coverage_"+superpixel_dir, "coverage_paths.txt"), "w") as fptr:
        for p in image_paths:
            fptr.write(p.decode() + "\n")

def test_coverage_scannet_sample():
    import constants
    import os
    from dataloader import dataset_base
    from dataloader.indoor_scenes import IndoorScenes
    lmdb_handle = dataset_base.LMDBHandle(os.path.join(constants.HDD_DATASET_ROOT, "scannet-sample", "dataset.lmdb"), False)
    train_set = IndoorScenes('scannet-sample', lmdb_handle, (240, 320), 'train')
    find_superpixel_coverage('scannet-sample', lmdb_handle, (240, 320), train_set.image_path_subset)

if __name__=='__main__':
    test_coverage_scannet_sample()


import copy
import pickle
from modules.hpe.utils.misc import postprocess_yolo_output, homography, get_augmentations, is_within_fov, \
    reconstruct_absolute
import einops
import numpy as np
from utils.tensorrt_runner import Runner
from utils.params import MetrabsTRTConfig, RealSenseIntrinsics, MainConfig
from tqdm import tqdm
import cv2
from utils.matplotlib_visualizer import MPLPosePrinter

class HumanPoseEstimator:
    def __init__(self, model_config, cam_config, just_box=None):

        if just_box is None:
            self.just_box = model_config.just_box
        else:
            self.just_box = just_box

        self.yolo_thresh = model_config.yolo_thresh
        self.nms_thresh = model_config.nms_thresh
        self.num_aug = model_config.num_aug
        self.n_test = 1 if self.num_aug < 1 else self.num_aug

        # Intrinsics and K matrix of RealSense
        self.K = np.zeros((3, 3), np.float32)
        self.K[0][0] = cam_config.fx
        self.K[0][2] = cam_config.ppx
        self.K[1][1] = cam_config.fy
        self.K[1][2] = cam_config.ppy
        self.K[2][2] = 1

        # Load conversions
        self.skeleton = model_config.skeleton
        self.expand_joints = np.load(model_config.expand_joints_path)
        with open(model_config.skeleton_types_path, "rb") as input_file:
            self.skeleton_types = pickle.load(input_file)

        # Load modules
        self.yolo = Runner(model_config.yolo_engine_path)  # model_config.yolo_engine_path
        if not self.just_box:
            self.image_transformation = Runner(model_config.image_transformation_path)
            self.bbone = Runner(model_config.bbone_engine_path)
            self.heads = Runner(model_config.heads_engine_path)

    def estimate(self, frame):

        # Preprocess for yolo
        square_img = cv2.resize(frame, (256, 256), fx=1.0, fy=1.0, interpolation=cv2.INTER_AREA)
        yolo_in = copy.deepcopy(square_img)
        yolo_in = cv2.cvtColor(yolo_in, cv2.COLOR_BGR2RGB)
        yolo_in = np.transpose(yolo_in, (2, 0, 1)).astype(np.float32)
        yolo_in = np.expand_dims(yolo_in, axis=0)
        yolo_in = yolo_in / 255.0

        # Yolo
        outputs = self.yolo(yolo_in)
        boxes, confidences = outputs[0].reshape(1, 4032, 1, 4), outputs[1].reshape(1, 4032, 80)
        bboxes_batch = postprocess_yolo_output(boxes, confidences, self.yolo_thresh, self.nms_thresh)

        # Get only the bounding box with the human with highest probability
        box = bboxes_batch[0]  # Remove batch dimension
        humans = []
        for e in box:  # For each object in the image
            if e[5] == 0:  # If it is a human
                humans.append(e)
        if len(humans) > 0:
            humans.sort(key=lambda x: x[4], reverse=True)  # Sort with decreasing probability
            human = humans[0]
        else:
            return None

        # Preprocess for BackBone
        x1 = int(human[0] * frame.shape[1]) if int(human[0] * frame.shape[1]) > 0 else 0
        y1 = int(human[1] * frame.shape[0]) if int(human[1] * frame.shape[0]) > 0 else 0
        x2 = int(human[2] * frame.shape[1]) if int(human[2] * frame.shape[1]) > 0 else 0
        y2 = int(human[3] * frame.shape[0]) if int(human[3] * frame.shape[0]) > 0 else 0

        # If we are doing rgb inference, we need just the box
        if self.just_box:
            return {"bbox": (x1, y1, x2, y2)}

        new_K, homo_inv = homography(x1, x2, y1, y2, self.K, 256)

        # Test time augmentation (What is Gamma Decoding?)
        if self.num_aug > 0:
            aug_should_flip, aug_rotflipmat, aug_gammas, aug_scales = get_augmentations(self.num_aug)
            new_K = np.tile(new_K, (self.num_aug, 1, 1))
            for k in range(self.num_aug):
                new_K[k, :2, :2] *= aug_scales[k]
            homo_inv = aug_rotflipmat @ np.tile(homo_inv[0], (self.num_aug, 1, 1))

        # Apply homography
        H = self.K @ np.linalg.inv(new_K @ homo_inv)
        bbone_in = self.image_transformation(frame.astype(int), H.astype(np.float32))

        bbone_in = bbone_in[0].reshape(self.n_test, 256, 256, 3)  # [..., ::-1]
        bbone_in_ = (bbone_in / 255.0).astype(np.float32)

        # BackBone
        outputs = self.bbone(bbone_in_)

        # Heads
        logits = self.heads(outputs[0])

        # Get logits 3d  TODO DO THE SAME WITH 2D
        logits = logits[0].reshape(1, 8, 8, 288)
        _, logits2d, logits3d = np.split(logits, [0, 32], axis=3)
        current_format = 'b h w (d j)'
        logits3d = einops.rearrange(logits3d, f'{current_format} -> b h w d j', j=32)  # 5, 8, 8, 9, 32

        # 3D Softmax
        heatmap_axes = (2, 1, 3)
        max_along_axis = logits3d.max(axis=heatmap_axes, keepdims=True)
        exponential = np.exp(logits3d - max_along_axis)
        denominator = np.sum(exponential, axis=heatmap_axes, keepdims=True)
        res = exponential / denominator

        # 3D Decode Heatmap
        result = []
        for ax in heatmap_axes:
            other_heatmap_axes = tuple(other_ax for other_ax in heatmap_axes if other_ax != ax)
            summed_over_other_heatmap_axes = np.sum(res, axis=other_heatmap_axes, keepdims=True)
            coords = np.linspace(0.0, 1.0, res.shape[ax])
            decoded = np.tensordot(summed_over_other_heatmap_axes, coords, axes=[[ax], [0]])
            result.append(np.squeeze(np.expand_dims(decoded, ax), axis=heatmap_axes))
        pred3d = np.stack(result, axis=-1)

        # 2D Softmax
        heatmap_axes = (2, 1)
        max_along_axis = logits2d.max(axis=heatmap_axes, keepdims=True)
        exponential = np.exp(logits2d - max_along_axis)
        denominator = np.sum(exponential, axis=heatmap_axes, keepdims=True)
        res = exponential / denominator

        # Decode heatmap
        result = []
        for ax in heatmap_axes:
            other_heatmap_axes = tuple(other_ax for other_ax in heatmap_axes if other_ax != ax)
            summed_over_other_heatmap_axes = np.sum(res, axis=other_heatmap_axes, keepdims=True)
            coords = np.linspace(0.0, 1.0, res.shape[ax])
            decoded = np.tensordot(summed_over_other_heatmap_axes, coords, axes=[[ax], [0]])
            result.append(np.squeeze(np.expand_dims(decoded, ax), axis=heatmap_axes))
        pred2d = np.stack(result, axis=-1) * 255

        # Get absolute position (if desired)
        is_predicted_to_be_in_fov = is_within_fov(pred2d)

        # If less than 1/3 of the joints is visible, then the resulting pose will be weird
        if is_predicted_to_be_in_fov.sum() < is_predicted_to_be_in_fov.size/4:
            return None

        # Move the skeleton into estimated absolute position if necessary
        pred3d = reconstruct_absolute(pred2d, pred3d, new_K[None, ...], is_predicted_to_be_in_fov, weak_perspective=False)

        # Go back in original space (without augmentation and homography)
        pred3d = pred3d @ homo_inv

        # Get correct skeleton
        pred3d = (pred3d.swapaxes(1, 2) @ self.expand_joints).swapaxes(1, 2)
        if self.skeleton is not None:
            pred3d = pred3d[:, self.skeleton_types[self.skeleton]['indices']]
            edges = self.skeleton_types[self.skeleton]['edges']
        else:
            edges = None

        pred3d = pred3d[0]  # Remove batch dimension

        return {"pose": pred3d,
                "edges": edges,
                "bbox": (x1, x2, y1, y2)}

if __name__ == "__main__":
    import pycuda.autoinit  # IMPORTANT leave this here! It creates the context for CUDA
    args = MainConfig()
    vis = MPLPosePrinter()

    h = HumanPoseEstimator(MetrabsTRTConfig(), RealSenseIntrinsics())

    # from utils.input import RealSense
    # cap = RealSense(width=args.cam_width, height=args.cam_height)  # RealSense
    cap = cv2.VideoCapture(0)  # Webcam

    for _ in tqdm(range(10000)):
        ret, img = cap.read()
        r = h.estimate(img)

        if r is not None:

            p = r["pose"]
            e = r["edges"]
            b = r["bbox"]

            if p is not None:
                p = p - p[0]
                vis.clear()
                vis.print_pose(p, e)
                vis.sleep(0.001)

            if b is not None:
                x1_, x2_, y1_, y2_ = b
                xm = int((x1_ + x2_) / 2)
                ym = int((y1_ + y2_) / 2)
                l = max(xm - x1_, ym - y1_)
                img = img[(ym - l if ym - l > 0 else 0):(ym + l), (xm - l if xm - l > 0 else 0):(xm + l)]
                img = cv2.resize(img, (224, 224))

        cv2.imshow("", img)
        cv2.waitKey(1)


from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
import re

path = 'C:/Projects/OrgBuilder/Codes/DataServices/DataServices/outputs/'
# filename = path+"US Bank.xlsx"
filename = path+"BOA Full Org - 8.29.17 Project Baseline.xlsx"
colname = "Job Title"
# colname = "Job Family Desc"
Ngrams = 3
NumRecurrences = 3
output_path = path
output_tag = "BOA_0305"
dict_path = path + 'Short_Forms_Dictionary_KA.xlsx'

replace_dict = pd.read_excel(dict_path)
df = pd.read_excel(filename, encoding='latin-1')
replace_dict = {s: a for s, a in zip(replace_dict['Short'], replace_dict['Actual'])}

def clean_text(text, use_dict=1):
    """
    function to clean text of symbols, spaces, capitals etc.

    Parameters
    ----------
    text: a string

    Returns
    ----------
    text: modified initial string
    """
    # Cleaning
    REPLACE_BY_SPACE_RE = re.compile('[/(){}\[\]\|@,;&-]')
    BAD_SYMBOLS_RE = re.compile('[^0-9a-z #+_]')

    text = re.sub(r'([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))', r'\1 ', text)

    text = text.lower()  # lowercase text
    text = REPLACE_BY_SPACE_RE.sub(' ',
                                   text)
    # replace REPLACE_BY_SPACE_RE symbols by space in text. substitute the matched string in REPLACE_BY_SPACE_RE with space.
    text = BAD_SYMBOLS_RE.sub('',
                              text)  # remove symbols which are in BAD_SYMBOLS_RE from text. substitute the matched string in BAD_SYMBOLS_RE with nothing.
    # text = text.replace('x', '')

    # if use_dict == 1:
    #     keys = list(self.replace_dict.keys())
    #     values = list(self.replace_dict.values())
    #     for n in range(len(self.replace_dict)):
    #         text = re.sub(r"\b%s\b" % keys[n], values[n], text)

    if use_dict == 1:
        keys = list(replace_dict.keys())
        values = list(replace_dict.values())
        # for n in range(len(self.replace_dict)):
        #     text = re.sub(r"\b%s\b" % keys[n], values[n], text)
        for key_term in set(text.split(" ")).intersection(keys):
            n = keys.index(key_term)
            text = re.sub(r"\b%s\b" % keys[n], values[n], text)

    return text

def clean_column(df, col, use_dict=1):
    """
    Clean the column - remove caps, stop words etc.

    Parameters
    ----------
    df: pandas, Data frame with column to be cleaned
    col: str, Name of the column

    Returns
    --------
    df: pandas, data frame with column cleaned
    """
    df[col] = df[col].str.replace("-", ' ')
    df[col] = df[col].apply(clean_text, use_dict=use_dict)
    df[col] = df[col].str.replace('\d+', '')
    return df

def prepare_col(df, sourcecol, col, replace_spaces=1):
    # Drop duplicates
    df.drop_duplicates(subset=sourcecol, inplace=True)
    df[col] = df[sourcecol].str.strip()

    print('Cleaning column')
    df = clean_column(df, col)

    if replace_spaces:
        print('Replacing spaces')
        df[col] = ['_'.join(x.split()) for x in df[col]]

    return df

print('Clean the column')
df = df[[colname]]
df[colname] = df[colname].astype('str')
df = prepare_col(df, colname, colname + '_Cleaned', replace_spaces=1)
colname = colname + '_Cleaned'

print('Replace Underscores to spaces (if any).')
df[colname] = df[colname].str.replace("_", " ")

N = Ngrams  # N grams
n = NumRecurrences  # least number of recurrences

print('Get word vectorizer')
word_vectorizer = CountVectorizer(ngram_range=(1, N), analyzer='word')
sparse_matrix = word_vectorizer.fit_transform(df[colname])

print('Get frequencies')
frequencies = sum(sparse_matrix).toarray()[0]

print('Get Ngrams df')
ngrams_df = pd.DataFrame(frequencies, index=word_vectorizer.get_feature_names(), columns=['frequency'])

print('Sort on frequency and reset index')
ngrams_df.sort_values('frequency', ascending=False, inplace=True)
ngrams_df.reset_index(inplace=True)
ngrams_df.rename(columns={'index': colname}, inplace=True)

print('Add Ngram column')
ngrams_df['ngram'] = ngrams_df[colname].str.split().str.len()

print('Filter for recurrences >= {}'.format(str(n)))
ngrams_df = ngrams_df[ngrams_df['frequency'] >= n]

Ngram_path = '/Ngrams_1-{}_minCount_{}_{}.csv'.format(N, n, output_tag)
ngrams_df.to_csv(output_path + Ngram_path, index=False)


import argparse
from time import time

import pandas as pd

from src.analyze import analyze_utils as au

def get_parser():
    parser = argparse.ArgumentParser(description='Netwrok analysis on the models architecture.')
    parser.add_argument('--input-results', default='./reports/dfresults.pkl')
    parser.add_argument('--net-dir', dest='net_dir',
                        help='The directory with the network model definitions (default: ./graphs)',
                        default='./graphs', type=str)
    parser.add_argument('--output',
                        help='The directory used to save features (default: ./reports/dffeaturestotal.pk)',
                        default='./reports/dffeaturestotal.pkl', type=str)
    return parser

def make_features(results_path, output_path):
    """
    Computes the features for all graphs, which are present in the results dataframe.
    :param results_path: The results dataframe.
    :param output_path: The output path.
    :return:
    """
    results = pd.read_pickle(results_path)
    graphs = results.index.to_list()
    ngraphs = len(graphs)

    df = None
    t0 = time()

    for i, g in enumerate(graphs):
        print('{}/{} {}'.format(i + 1, ngraphs, g))
        info = au.graphinfo(g, net_dir=args.net_dir)
        features0 = au.features_part0(info)
        features1 = au.features_part1(info)
        features2 = au.features_part2(info)
        features = {**features0, **features1, **features2}
        columns = features.keys()
        if df is None:
            df = pd.DataFrame(index=graphs, columns=columns)
        df.loc[g] = features
        print(features)
        print()
    print('finished in', time() - t0)
    df.to_pickle(output_path)

def main():
    parser = get_parser()
    args = parser.parse_args()
    make_features(args.input_results, args.output)

if __name__ == "__main__":
    main()


import torch
from torch import nn
from torch.utils.checkpoint import checkpoint
from models.batch_norm import get_bn_cache_size, MectaNorm2d
from utils.utils import dtype_memory_size_dict

class CheckpointSeq(nn.Module):
    def __init__(self, sequential_mod: nn.Sequential, segment=1, record_bn_cache=False) -> None:
        super().__init__()
        assert 1 <= segment <= len(sequential_mod), \
            f"Invalid segment. Should in range [1, {len(sequential_mod)}] but got {segment}"

        self.sequential_mod = sequential_mod
        self.checkpoint_sequential = checkpoint_sequential(record_bn_cache)
        self.segment = segment
        self.cache_size = 0  # TODo need to reset.
        self.max_bn_cache_size = 0

    def forward(self, x):
        if self.segment > 1:
            out, cache_size, max_bn_cache_size = self.checkpoint_sequential(self.sequential_mod, self.segment, x)
            self.cache_size = cache_size
            self.max_bn_cache_size = max_bn_cache_size
            return out
        else:
            return self.sequential_mod(x)

    def get_split_num(self):
        return len(self.sequential_mod) // self.segment

def print_chkpt_seg(model):
    n_gc = 0
    total_parts = 0
    for nm, mod in model.named_modules():
        if isinstance(mod, CheckpointSeq):
            split = mod.get_split_num()
            total_parts += split
            print(f" Segment stage {nm} into {split} parts.")
            n_gc += 1
    if n_gc > 0:
        print(f"Total segments: {total_parts}")

def compute_input_cache(input):
    # if isinstance(input, tuple):
    #     return sum([torch.prod(torch.tensor(inp.shape)).item() for inp in input if torch.is_tensor(inp)])
    # else:
    return torch.prod(torch.tensor(input.shape)).item()

class checkpoint_sequential:
    def __init__(self, record_bn_cache):
        self.record_bn_cache = record_bn_cache

    def __call__(self, functions, segments, input, **kwargs):
        r"""Modified from torch.utils.checkpoint.checkpoint_sequential

        Returns:
            Output of running :attr:`functions` sequentially on :attr:`*inputs`

        Example:
            >>> model = nn.Sequential(...)
            >>> input_var = checkpoint_sequential(model, chunks, input_var)
        """
        # Hack for keyword-only parameter in a python 2.7-compliant way
        preserve = kwargs.pop('preserve_rng_state', True)
        if kwargs:
            raise ValueError("Unexpected keyword arguments: " +
                            ",".join(arg for arg in kwargs))

        def run_function(start, end, functions):
            def forward(input):
                for j in range(start, end + 1):
                    input = functions[j](input)
                return input
            return forward

        if isinstance(functions, torch.nn.Sequential):
            functions = list(functions.children())

        segment_size = len(functions) // segments
        # the last chunk has to be non-volatile
        end = -1
        cache_size = 0
        max_bn_cache_size = 0
        for start in range(0, segment_size * (segments - 1), segment_size):
            end = start + segment_size - 1
            cache_size += compute_input_cache(input)
            input = checkpoint(run_function(start, end, functions), input,
                            preserve_rng_state=preserve)

            if self.record_bn_cache:
                _, bn_cache_size = get_bn_cache_size(
                    torch.nn.Sequential(*[functions[i] for i in range(start, end+1)]))
                if bn_cache_size > max_bn_cache_size:
                    max_bn_cache_size = bn_cache_size
                    # print(f">> bn_cache_size: {bn_cache_size/1e6:.2f} Mb")
        cache_size += compute_input_cache(input)
        start = end + 1
        end = len(functions) - 1
        out = run_function(start, end, functions)(input)
        if self.record_bn_cache:
            _, bn_cache_size = get_bn_cache_size(
                torch.nn.Sequential(*[functions[i] for i in range(start, end+1)]))
            if bn_cache_size > max_bn_cache_size:
                max_bn_cache_size = bn_cache_size
                # print(f">> bn_cache_size: {bn_cache_size/1e6:.2f} Mb")

            if max_bn_cache_size == 0 and not input.requires_grad: # This layer does not need cache.
                cache_size = 0.
        else:
            max_bn_cache_size = 0.
        return out, cache_size * dtype_memory_size_dict[torch.float], max_bn_cache_size


#!/bin/python

import numpy as np
import pyautogui,cv2,time

def pointsToRectangle(x0,y0,x1,y1):
    w=int(x1-x0)
    h=int(y1-y0)
    rec={'x0':int(x0),'x1':int(x1),'y0':int(y0),'y1':int(y1),'w':int(w),'h':int(h)}
    return rec

def setup():
    def draw_rect(event,x,y,flags,param):
        nonlocal x0,y0,x1,y1,drawing,screen_bkp,screen,selected_square,thickness,color
        if event==cv2.EVENT_LBUTTONDOWN:
            drawing=True
            x0,y0=x,y
            # screen_bkp=screen.copy()
        elif event==cv2.EVENT_MOUSEMOVE:
            if drawing==True:
                if screen_bkp is not None:
                    screen=screen_bkp.copy()
                cv2.rectangle(screen,(x0,y0),(x,y),color,thickness)
        elif event==cv2.EVENT_LBUTTONUP:
            if drawing==True:
                drawing=False
                selected_square=True
                x1,y1=x,y
                cv2.rectangle(screen,(x0,y0),(x,y),color,thickness)
    thickness=2
    color=(0,255,0)
    x0,y0,x1,y1=-1,-1,-1,-1
    drawing=False
    selected_square=False
    delay=3
    print('Taking screenshot in {} seconds'.format(delay))
    time.sleep(delay)
    screen=cv2.cvtColor(np.array(pyautogui.screenshot()), cv2.COLOR_RGB2BGR)
    screen_bkp=screen.copy()
    cv2.namedWindow('screen', cv2.WND_PROP_FULLSCREEN)
    cv2.setWindowProperty('screen', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
    while not selected_square:
        cv2.setMouseCallback('screen',draw_rect)
        cv2.imshow('screen',screen)
        cv2.waitKey(1)
    if x1<x0:
        tmp=x0
        x0=x1
        x1=tmp
    if y1<y0:
        tmp=y0
        y0=y1
        y1=tmp
    print('Found game screen ({}, {}), ({}, {})'.format(x0,y0,x1,y1))
    screen=screen_bkp.copy()
    cv2.rectangle(screen,(x0,y0),(x1,y1),(0,255,0),2)
    cv2.imshow('screen',screen)
    time.sleep(1)
    cv2.destroyWindow('screen')
    cv2.waitKey(1)
    return pointsToRectangle(x0,y0,x1,y1)

def captureScreen(area_rec,grey=False):
    screen=np.array(pyautogui.screenshot())
    screen=screen[area_rec['y0']:area_rec['y1'],area_rec['x0']:area_rec['x1']]
    if grey:
        screen=cv2.cvtColor(screen, cv2.COLOR_RGB2GRAY)
    else:
        screen=cv2.cvtColor(screen, cv2.COLOR_RGB2BGR)
    return screen

def isRelativeltyEqual(a,b,confidance):
    confidance=1-confidance
    return a*(1-confidance)<=b and a*(1+confidance)>=b

def matchMaskedSprite(image,sprite,confidance,mask=None): # too slow
    if len(image.shape)==2:
        image=np.reshape(image,image.shape+(1,))
    if len(sprite.shape)==2:
        sprite=np.reshape(sprite,sprite.shape+(1,))
    image_h,image_w,image_c=image.shape
    sprite_h,sprite_w,sprite_c=sprite.shape
    if mask is not None:
        if len(mask.shape)==2:
            mask=np.reshape(mask,mask.shape+(1,))
        mask_h,mask_w,mask_c=mask.shape
        if mask_h!=sprite_h or mask_w!=sprite_w:
            raise 'Wrong mask size'
    if image_c!=sprite_c:
        raise 'Wrong channels size'
    match_points=[]
    # output=np.zeros((image_h,image_w))
    for i in range(image_h-sprite_h):
        for j in range(image_w-sprite_w):
            have_match=True
            for c in range(sprite_h):
                for t in range(sprite_w):
                    if mask is None or mask[c][t][0]==255:
                        for k in range(image_c):
                            if not isRelativeltyEqual(image[i+c][j+t][k],sprite[c][t][k],confidance):
                                have_match=False
                                break
                        if not have_match:
                            break
                    if not have_match:
                        break
                if not have_match:
                    break
            if have_match:
                print('we have a match')
                match_points.append((i,j))
            # output[i][j]=0
    # return output
    return match_points