import ujson
import api
import numpy
import itertools
import math
keyset = set()
fields_to_write = ['NS', 'A', 'SOA', 'MX', 'TXT', "total_a_records", "num_asn_peers", "total_unique_peers", "median_peers_per_asn", "mean_peers_per_asn mean_ttl", "median_ttl", "total_unique_ttls", "num_contacts subdomains", "asn_ip_ratio", "asn_peer_ip_ratio", 'domain_length', 'num_record_types', 'raw_whois_len', 'total_a_records', 'pdns_a_records', 'total_urls', 'num_url_scores', 'num_detected_communicating_scores', 'num_detected_downloaded_scores', 'mean_url_scores', 'mean_detected_communicating_scores', 'mean_detected_downloaded_scores', 'median_url_scores', 'median_detected_communicating_scores', 'median_detected_downloaded_scores']
def emit(result, fields):
    output = []
    asn_peers = result.get('asn_peers', [])
    result['num_asn_peers'] = len(list(itertools.chain.from_iterable(asn_peers)))
    result['total_unique_peers'] = len(set(itertools.chain.from_iterable(asn_peers)))
    result['median_peers_per_asn'] = numpy.median([len(item) for item in asn_peers])
    if math.isnan(result['median_peers_per_asn']):
        result['median_peers_per_asn'] = 0
    result['mean_peers_per_asn'] = numpy.mean([len(item) for item in asn_peers])
    if math.isnan(result['mean_peers_per_asn']):
        result['mean_peers_per_asn'] = 0
    ttls = result.get("a_ttls", [])
    result['mean_ttl'] = numpy.mean(numpy.array(ttls))
    if math.isnan(result['mean_ttl']):
        result['mean_ttl'] = -1
    result['median_ttl'] = numpy.median(numpy.array(ttls))
    if math.isnan(result['median_ttl']):
        result['median_ttl'] = -1

    result['total_unique_ttls'] = len(set(ttls))

    result['num_contacts'] = len(result.get("contacts", []))
    result['subdomains'] = len(result.get('domain', '').strip('.').split())

    try:
        result['asn_ip_ratio'] = len(result.get('a_asns', [])) / float(result.get('total_a_records', 0))
    except ZeroDivisionError:
        result['asn_ip_ratio'] = -1
    try:
        result['asn_peer_ip_ratio'] = result['num_asn_peers'] / float(result.get('total_a_records', 0))
    except ZeroDivisionError:
        result['asn_peer_ip_ratio'] = -1
    #for field in fields:
    for field in fields:
        dat = result.get(field, -1)
        if math.isnan(dat):
            dat = field+"NAN"
        output.append(dat)
    return output, result['domain']

if __name__ == '__main__':
    for line in open('joint_vt_chompy').readlines():
        js = ujson.loads(line)
        result = {}
# domains have a list of source, in the JS files, find beningin ... on the first call when removing, segregate by source

# We might need to change this to do a look up on the TLO (Domain) and then pull the chompy and VT analysis_results
# This way we can limit my the Domains Source. For example we have benign, maltrieve droppers, and then novetta which
# should be call out Domains

#
# I am going to update the chompy_analytics.py file to limit my source.
#
        for e in js:
            if e['service_name'] == 'chompy':
                for element in e['results']:
                    if element['subtype'] == "DNS Summary":
                        result['domain'] = element['result']
                        result['domain_length'] = len(element['result'])

                        record_types = element.get('Record Contains', "").split(',')
                        print(record_types)
                        result['num_record_types'] = len(record_types)
                        for ty in record_types:
                            result[ty.strip()] = 1

                    if element['result'] == 'Raw':
                        # We'll do a flatten() on this, as manually extracting the data will be painful.
                        result['parsed_whois'] = api.parse_whois(element.get('Value', {}))
                        result['raw_whois_len'] = len(element.get('Value', {}))
                        """
                        for contact_type in result.get('parsed_whois', {}).get('contacts', []):
                            key = '%s_address_verification' % (contact_type)
                            v = api.verify_address(result['parsed_whois']['contacts'][contact_type])
                            if "error" not in v:
                                result[key] = v

                            email_key = '%s_freemail_verification' % (contact_type)
                            contact = result.get('parsed_whois', {}).get('contacts', {}).get(contact_type, {})
                            if contact is not None:
                                result[email_key] = api.verify_freemail(contact.get('email', ''))
                        """
                    if element['subtype'] == 'A':
                        result['total_a_records'] = result.get('total_a_records', 0) + 1
                        dns = element.get('DNS', {})
                        asn = element.get('ASN', {})

                        a_ttls = result.get('a_ttls', [])
                        a_ttls.append(dns.get('ttl', -1))
                        result['a_ttls'] = a_ttls
                        a_asns = result.get('a_asns', [])

                        if isinstance(asn, list):
                            asn = {}

                        a_asns.append(asn.get('asn', None))
                        result['a_asns'] = a_asns
                        asn_peers = result.get('asn_peers', [])
                        asn_peers.append(asn.get('as_peers', []))
                        result['asn_peers'] = asn_peers

            if e['service_name'] == "virustotal_lookup":
                pdns_a_records = 0
                total_urls = 0
                url_scores = numpy.array([])
                detected_downloaded_scores = numpy.array([])
                detected_communicating_scores = numpy.array([])
                for item in e['results']:
                    if item['subtype'] == "A Records":
                        pdns_a_records += 1
                    if item['subtype'] == "URLs":
                        total_urls += 1
                        if item['total'] != 0:
                            numpy.append(url_scores, float(item["positives"])/float(item['total']))
                        else:
                            numpy.append(url_scores, float(item["positives"])/float(55))

                    if item['subtype'] == "Detected Downloaded Samples":
                        if item['total'] != 0:
                            detected_downloaded_scores = numpy.append(detected_downloaded_scores, float(item["positives"])/float(item['total']))
                        else:
                            detected_downloaded_scores = numpy.append(detected_downloaded_scores, float(item["positives"])/float(55))

                    if item['subtype'] == "Detected Communicating Samples":
                        if item['total'] != 0:
                            detected_communicating_scores = numpy.append(detected_communicating_scores, float(item["positives"])/float(item['total']))
                        else:
                            detected_communicating_scores = numpy.append(detected_communicating_scores, float(item["positives"])/float(55))
                #Need a NAN conversion function. -1 for NAN?
                result['pdns_a_records'] = pdns_a_records
                result['total_urls'] = total_urls
                result['num_url_scores'] = len(url_scores)
                result['num_detected_communicating_scores'] = len(detected_communicating_scores)
                result['num_detected_downloaded_scores'] = len(detected_downloaded_scores)
                result['mean_url_scores'] = numpy.mean(url_scores)
                result['mean_detected_communicating_scores'] = numpy.mean(detected_communicating_scores)
                result['mean_detected_downloaded_scores'] = numpy.mean(detected_downloaded_scores)
                result['median_url_scores'] = numpy.median(url_scores)
                result['median_detected_communicating_scores'] = numpy.median(detected_communicating_scores)
                result['median_detected_downloaded_scores'] = numpy.median(detected_downloaded_scores)
        print(emit(result, fields_to_write))


import json
import os
import sys
sys.path.append('source')
from preset import Preset

currObj = ""

presetsRaw =  [
    Preset("Preset1", "Description of Preset1", "C:\\Users\\Bence\\Desktop\\preset1.reg",[]),
    Preset("Preset2", "Description of Preset2", "C:\\Users\\Bence\\Desktop\\preset2.reg",[]),
    Preset("Preset3", "Description of Preset3", "C:\\Users\\Bence\\Desktop\\preset3.reg",[])
]

# build a list of dicts from your objects:
presets = [obj.to_dict() for obj in presetsRaw]

presets.sort(key=lambda obj: obj["name"])

presetsJSON = json.dumps({"presets": presets})
print("\n-> jsdata: " + presetsJSON)

### HOW TO WRITE FILE ###

# Set the directory where the files are located
filename = "C:\\Users\\" + os.getenv("username") + "\\AppData\\Local\\DLO\\Presets\\presetlist.json"

print("\n-> writing to... " + filename)

# Writing to the given filename
with open(f"{filename}", "w") as outfile:
   outfile.write(presetsJSON)

### HOW TO READ FILE ###

f = open(f"{filename}", "r")
fileRead = json.loads(f.read())

print("\n-> printing file output...")
for a in fileRead['presets']:
    print(a['name'])

### WORKING WITH OBJECTS ###

currObj = fileRead['presets'][1]
print("\n-> currObj: " + currObj['name'])

### TO_PRESET TEST ###
p1 = Preset.to_Preset(fileRead['presets'][0])

print(p1.name)


import tempfile
from tvm import meta_schedule as ms
import pytest
import tvm.meta_schedule.testing.te_workload as te_workload
import tvm
from tvm import te, tir
from tvm.script import tir as T
import tvm.testing
import numpy as np
from tvm.contrib import nvcc

@T.prim_func
def mma_sync_desc(a: T.handle, b: T.handle, c: T.handle) -> None:
    A = T.match_buffer(a, [32, 4], dtype="float16", scope="warp")
    B = T.match_buffer(b, [32, 2], dtype="float16", scope="warp")
    C = T.match_buffer(c, [32, 4], dtype="float32", scope="warp")
    with T.block("root"):
        T.reads(C[0 : 32, 0 : 4], A[0 : 32, 0 : 4], B[0 : 32, 0 : 2])
        T.writes(C[0 : 32, 0 : 4])
        for i0, i1, i2 in T.grid(16, 8, 8):
            with T.block("C"):
                i, j, k = T.axis.remap("SSR", [i0, i1, i2])
                T.reads(C[i % 8 * 4 + j % 8 // 2, i % 16 // 8 * 2 + j % 2], A[i % 8 * 4 + k % 8 // 2, i % 16 // 8 * 2 + k % 2], B[j % 8 * 4 + k % 8 // 2, k % 2])
                T.writes(C[i % 8 * 4 + j % 8 // 2, i % 16 // 8 * 2 + j % 2])
                C[i % 8 * 4 + j % 8 // 2, i % 16 // 8 * 2 + j % 2] = C[i % 8 * 4 + j % 8 // 2, i % 16 // 8 * 2 + j % 2] + T.cast(A[i % 8 * 4 + k % 8 // 2, i % 16 // 8 * 2 + k % 2], "float32") * T.cast(B[j % 8 * 4 + k % 8 // 2, k % 2], "float32")

                # T.reads(C[i % 8 * 4 + j // 2, i // 8 * 2 + j % 2], A[i % 8 * 4 + k // 2, i // 8 * 2 + k % 2], B[j * 4 + k // 2, k % 2])
                # T.writes(C[i % 8 * 4 + j // 2, i // 8 * 2 + j % 2])
                # C[i % 8 * 4 + j // 2, i // 8 * 2 + j % 2] = C[i % 8 * 4 + j // 2, i // 8 * 2 + j % 2] + T.cast(A[i % 8 * 4 + k // 2, i // 8 * 2 + k % 2], "float32") * T.cast(B[j * 4 + k // 2, k % 2], "float32")

@T.prim_func
def mma_sync_impl(a: T.handle, b: T.handle, c: T.handle) -> None:
    A = T.match_buffer(a, (32, 4), "float16", align=128, offset_factor=1, scope="warp")
    B = T.match_buffer(b, (32, 2), "float16", align=128, offset_factor=1, scope="warp")
    C = T.match_buffer(c, (32, 4), "float32", align=128, offset_factor=1, scope="warp")

    with T.block("root"):
        T.reads(C[0 : 32, 0 : 4], A[0 : 32, 0 : 4], B[0 : 32, 0 : 2])
        T.writes(C[0 : 32, 0 : 4])
        tx = T.env_thread("threadIdx.x")
        T.launch_thread(tx, 32)
        T.evaluate(
            T.ptx_mma(
                "m16n8k8",
                "row",
                "col",
                "fp16",
                "fp16",
                "fp32",
                A.data,
                A.elem_offset + tx * 4,
                B.data,
                B.elem_offset + tx * 2,
                C.data,
                C.elem_offset + tx * 4,
                False,
                dtype="float32",
            ))

MMA_SYNC = tir.TensorIntrin.register(
    "mma_sync",
    mma_sync_desc,
    mma_sync_impl,
)

def test_integration_matmul():
    N = 4096
    M = 4096
    K = 4096
    workload = te_workload.matmul_fp16(n=N, m=M, k=K)
    workload = te.create_prim_func(workload)

    # a = mk b = nk / kk c = nn
    # scope = local
    def schedule(sch: tir.Schedule):
        block = sch.get_block("C")
        i, j, k = sch.get_loops(block)
        # Step 1. Rule-Auto-Tensorize
        # pylint: disable=invalid-name
        i, i_tc = sch.split(i, factors=[None, 16])
        j, j_tc = sch.split(j, factors=[None, 8])
        k, k_tc = sch.split(k, factors=[None, 8])
        sch.reorder(
            # fmt: off
            i, j, k,
            # tensor core
            i_tc, j_tc, k_tc,
            # fmt: on
        )
        block_inner = sch.blockize(i_tc)
        block_outer, block_inner = block_inner, block
        del block
        # Step 2. Rule-Multi-Level-Tiling

        # i_factors = sch.sample_perfect_tile(i, n=5)
        # j_factors = sch.sample_perfect_tile(j, n=5)
        # k_factors = sch.sample_perfect_tile(k, n=3)
        # num_ty = sch.get(i_factors[2]) * sch.get(j_factors[2])

        # i_factors = [64, 1, 2, 1, 2]
        # j_factors = [2, 32, 2, 1, 4]
        # k_factors = [256, 2, 1]
        i_factors = [1, 64, 1, 1, 4]
        j_factors = [16, 4, 4, 2, 1]
        k_factors = [64, 4, 2]

        num_ty = i_factors[2] * j_factors[2]

        i0, i1, i2, i3, i4 = sch.split(i, factors=i_factors)
        j0, j1, j2, j3, j4 = sch.split(j, factors=j_factors)
        k0, k1, k2 = sch.split(k, k_factors)
        # pylint: enable=invalid-name
        sch.reorder(
            # fmt: off
            i0, j0,   # S => blockIdx.x
            i1, j1,   # S => blockIdx.y
            j2, i2,   # S => threadIdx.y
            # cache_write here
            k0,       # R
            # vectorized cooperative fetching here
            k1,       # R
            i3, j3,   # S
            k2,       # R
            i4, j4,
            # S
            # fmt: on
        )
        block_idx = sch.fuse(i0, j0, i1, j1)
        thread_idy = sch.fuse(j2, i2)  # threadidx.y is actually number of warps here
        sch.bind(block_idx, "blockIdx.x")
        sch.bind(thread_idy, "threadIdx.y")

        def fetch_to_shared(block, idx, ndim):
            # shared [128 x 32]
            block_read = sch.cache_read(block, idx, "shared")
            # block_read_local = sch.cache_read(block_read, 0, "local")
            sch.compute_at(block_read, k0)
            vector_size = 8
            warp_size = 32
            fused = sch.fuse(*sch.get_loops(block_read)[-ndim:])
            f_0, f_1, f_2, f_3 = sch.split(fused, factors=[None, num_ty, warp_size, vector_size])
            sch.bind(f_2, "threadIdx.x")
            sch.bind(f_1, "threadIdx.y")
            sch.vectorize(f_3)

            #sch.storage_align(block_read, 0, axis=-2, factor=32, offset=8)

        fetch_to_shared(block_outer, 0, 2)
        fetch_to_shared(block_outer, 1, 2)

        # fetch to warp - A 4096 * 4096 -> 256 * 512 * 16 * 8 -> 256 * 512 * 32 * 4
        A_warp = sch.cache_read(block_outer, 0, "warp")
        sch.compute_at(A_warp, k1)
        def lambda_a(i, j):
            i_0 = i // 16
            j_0 = j // 8
            k_0 = i % 16
            l_0 = j % 8
            k_1 = (k_0 % 8) * 4 + l_0 // 2
            l_1 = (k_0 // 8) * 2 + l_0 % 2
            return i_0, j_0, k_1, l_1

        sch.transform_layout(
            A_warp,
            0,
            "write",
            index_map=lambda_a,
        )
        warp_loop1, warp_loop2 = sch.get_loops(A_warp)[-2:]
        # 32 * 8 -> 2 * 1 * 32 * 4
        i_0, k_0 = sch.split(warp_loop1, factors=[None, 16])
        j_0, l_0 = sch.split(warp_loop2, factors=[None, 8])
        k_0_0, k_0_1 = sch.split(k_0, [None, 8])
        l_0_0, l_0_1 = sch.split(l_0, [None, 2])
        sch.reorder(i_0, j_0, k_0_1, l_0_0, k_0_0, l_0_1)
        k_1 = sch.fuse(k_0_1, l_0_0)
        sch.bind(k_1, "threadIdx.x")
        #l_1 = sch.fuse(k_0_0, l_0_1)
        # sch.vectorize(l_0_1) # this will cause correctness issue

        # fetch to warp - B 4096 * 4096 -> 512 * 512 * 8 * 8 -> 512 * 512 * 32 * 2
        B_warp = sch.cache_read(block_outer, 1, "warp")
        sch.compute_at(B_warp, k1)

        def lambda_b(i, j):
            i_0 = i // 8
            j_0 = j // 8
            k_0 = i % 8
            l_0 = j % 8
            k_1 = k_0 // 2 + l_0 * 4
            l_1 = k_0 % 2
            return i_0, j_0, k_1, l_1

        sch.transform_layout(
            B_warp,
            0,
            "write",
            index_map=lambda_b,
        )
        warp_loop1, warp_loop2 = sch.get_loops(B_warp)[-2:]
        # 8 * 32 -> 4 * 32 * 2
        i_0, k_0 = sch.split(warp_loop1, factors=[None, 8]) # 1 * 8
        j_0, l_0 = sch.split(warp_loop2, factors=[None, 8]) # 4 * 8
        k_0_1, l_0_1 = sch.split(k_0, [None, 2]) # 4 * 2
        sch.reorder(i_0, j_0, l_0, k_0_1, l_0_1)
        k_1 = sch.fuse(l_0, k_0_1)
        sch.bind(k_1, "threadIdx.x")
        # sch.vectorize(l_0_1) # this will cause correctness issue

        # fetch to C 4096 * 4096 -> 256 * 512 * 16 * 8 -> 256 * 512 * 32 * 4
        C_warp = sch.cache_write(block_outer, 0, "warp")
        sch.reverse_compute_at(C_warp, sch.get_loops(block_outer)[2])
        # need to do a reverse_compute_at to place it under blockidx.x
        def lambda_c(i, j):
            i_0 = i // 16
            j_0 = j // 8
            k_0 = i % 16
            l_0 = j % 8
            k_1 = (k_0 % 8) * 4 + l_0 // 2
            l_1 = (k_0 // 8) * 2 + l_0 % 2
            return i_0, j_0, k_1, l_1

        sch.transform_layout(
            C_warp,
            0,
            "read",
            index_map=lambda_c,
        )
        warp_loop1, warp_loop2 = sch.get_loops(C_warp)[-2:]
        # 32 * 32 -> 2 * 4 * 32 * 4
        i_0, k_0 = sch.split(warp_loop1, factors=[None, 16])
        j_0, l_0 = sch.split(warp_loop2, factors=[None, 8])
        k_0_0, k_0_1 = sch.split(k_0, [None, 8])
        l_0_0, l_0_1 = sch.split(l_0, [None, 2])
        sch.reorder(i_0, j_0, k_0_1, l_0_0, k_0_0, l_0_1)
        k_1 = sch.fuse(k_0_1, l_0_0)
        sch.bind(k_1, "threadIdx.x")
        #l_1 = sch.fuse(k_0_0, l_0_1)
        sch.vectorize(l_0_1)

        # Step 3.3. Decompose -> this may be needed
        loop = sch.get_loops(block_outer)[2]
        block_init_c = sch.decompose_reduction(block_outer, loop)

        # C_init() 16 * 8 -> 32 * 4
        # as binding is already transformed by previous step
        # only split/reorder/fuse is needed here
        C_init = sch.get_block("C_init")
        init_loop1, init_loop2 = sch.get_loops(C_init)[-2:]
        f_0, f_1 = sch.split(init_loop1, factors=[None, 8])
        f_2, f_3 = sch.split(init_loop2, factors=[None, 2])
        sch.reorder(f_1, f_2, f_0, f_3)
        fused_1 = sch.fuse(f_1, f_2)
        fused_2 = sch.fuse(f_0, f_3)
        sch.bind(fused_1, "threadIdx.x")
        sch.vectorize(fused_2)

        # tensorize
        loop1, loop2, loop3 = sch.get_loops(block_inner)

        print(sch.mod.script())
        # assert False

        sch.tensorize(loop1, "mma_sync")

    sch = tir.Schedule(workload)
    schedule(sch)

    if False:
        with tempfile.TemporaryDirectory() as work_dir:
            sch = ms.tune_tir(
                mod=workload,
                target=tvm.target.Target("nvidia/geforce-rtx-3070"),
                # use replay or evolutionary search
                # config = ms.TuneConfig(
                #     strategy="evolutionary",
                #     num_trials_per_iter=8,
                #     max_trials_per_task=8,
                #     max_trials_global=8,
                # ),
                config=ms.ReplayTraceConfig(
                    num_trials_per_iter=8,
                    num_trials_total=8,
                ),
                work_dir=work_dir,
                space=ms.space_generator.ScheduleFn(schedule)
                )

    if sch is None:
        print("No valid schedule found")
    else:
        print(sch.mod["main"].script())
        print(tvm.lower(sch.mod["main"], None, simple_mode=True))

    dev = tvm.device("cuda", 0)
    a_np = np.random.uniform(size=(N, K)).astype("float16")
    b_np = np.random.uniform(size=(K, M)).astype("float16")
    c_np = np.dot(a_np.astype("float32"), b_np.astype("float32"))
    a = tvm.nd.array(a_np, dev)
    b = tvm.nd.array(b_np, dev)
    c = tvm.nd.array(np.zeros((N, M), dtype="float32"), dev)
    # sys.exit(0)
    f = tvm.build(sch.mod["main"], target="cuda", name="dense")
    f(a, b, c)
    print(f.imported_modules[0].get_source())
    tvm.testing.assert_allclose(c.numpy(), c_np, rtol=1e-3, atol=1e-3)
    print("ok")

    evaluator = f.time_evaluator(f.entry_name, dev, number=100)
    gflops = (N * M * K) * 2 / 1e9
    time_ms = evaluator(a, b, c).mean * 1e3
    print("matmul with tensor core: %f ms, %f GFLOPS" % (time_ms, gflops / (time_ms / 1e3)))

if __name__ == "__main__":
    test_integration_matmul()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 25 13:39:05 2019

@author: saikats
"""

import cv2
import numpy as np
import matplotlib.pyplot as plt

def set_bit(num, pos):
  mask = 1 << pos
  num &= ~mask
  return num

if __name__ == "__main__":

    img1 = cv2.imread('image/image.jpg',0)

    img = np.zeros(img1.shape, img1.dtype)

    rows, cols = img1.shape

    fig = plt.figure(figsize=(20,10))

    for i in range(rows):
            for j in range(cols):
                img[i][j] = img1[i][j]

    fig.add_subplot(2,9,1)
    plt.title("Orignal Image")
    plt.axis('off')
    plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')

    p = 2
    pp = 2
    b = 7
    while(b>=1):
        img = np.zeros(img1.shape, img1.dtype)
        for i in range(rows):
            for j in range(cols):
                pixel = img1[i][j]
                c = 7 - b + 1
                cc = 7
                while(c>0):
                    pixel = set_bit(pixel,cc)
                    cc = cc-1
                    c = c - 1
                img[i][j] = pixel

        fig.add_subplot(pp,9,p)
        plt.title('bit plane = {}'.format(b))
        plt.axis('off')
        plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
        p = p + 1

        if(p>4):
            p = 1
            pp = 1

        b = b-1


"""
360. Sort Transformed Array
Medium

435

126

Add to List

Share
Given a sorted integer array nums and three integers a, b and c, apply a quadratic function of the form f(x) = ax2 + bx + c to each element nums[i] in the array, and return the array in a sorted order.

Example 1:

Input: nums = [-4,-2,2,4], a = 1, b = 3, c = 5
Output: [3,9,15,33]
Example 2:

Input: nums = [-4,-2,2,4], a = -1, b = 3, c = 5
Output: [-23,-5,1,7]

Constraints:

1 <= nums.length <= 200
-100 <= nums[i], a, b, c <= 100
nums is sorted in ascending order.

Follow up: Could you solve it in O(n) time?
"""
from typing import List

"""
Array

use map and lambda and sort
time O(N*log(N))
"""

class Solution0:
    def sortTransformedArray(self, nums: List[int], a: int, b: int, c: int) -> List[int]:
        return sorted(map(lambda x: a * x * x + b * x + c, nums))

"""
Array

since nums is already sorted, a*x^2+b*x+c is a parabola
if a>0 it is concave, means two ends are larger
if a<0 it is convex, means two ends are smaller
so we need to calculate two sides separately and do merge sort O(N)

nums = [-4,-2,2,4], a = 1, b = 3, c = 5

time O(N)
"""

class Solution:
    def sortTransformedArray(self, nums: List[int], a: int, b: int, c: int) -> List[int]:
        n = len(nums)
        ans = []
        i, j = 0, n - 1
        while i <= j:
            xi = a * nums[i] * nums[i] + b * nums[i] + c
            xj = a * nums[j] * nums[j] + b * nums[j] + c
            if a > 0:  # concave, add big ones (from ends) first, reverse at output
                if xi <= xj:
                    ans.append(xj)
                    j -= 1
                else:
                    ans.append(xi)
                    i += 1
            else:  # a<0 # convex, add smaller ones (from ends) first
                if xi <= xj:
                    ans.append(xi)
                    i += 1
                else:
                    ans.append(xj)
                    j -= 1

        return ans[::-1] if a > 0 else ans

def main():
    sol = Solution()
    assert sol.sortTransformedArray(nums = [-4,-2,2,4], a = 1, b = 3, c = 5) == [3,9,15,33], 'fails'

    assert sol.sortTransformedArray(nums = [-4,-2,2,4], a = -1, b = 3, c = 5) == [-23,-5,1,7], 'fails'

if __name__ == '__main__':
   main()


import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style

# Giving a style to the graph
style.use("ggplot")

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)

def animate(i):
    # Reading and splitting the log per lines
    pullData = open("twitter_log.txt", "r").read()
    lines = pullData.split('\n')

    # Creating the x and y array lists that will be used to make the graph dynamic
    xar = []
    yar = []

    # Starting positions for x and y
    x = 0
    y = 0

    # Each line has the classification of that tweet "pos" or "neg"
    for line in lines:
        x += 1 # x will be incrementing per number of tweets
        if "pos" in line:
            y += 1 # function increases per positive tweet
        elif "neg" in line:
            y -= 1 # function decreases per negative tweet

        # Populating the array lists for x and y
        xar.append(x)
        yar.append(y)

    ax1.clear()
    ax1.plot(xar, yar)

# Running the dynamic graph up to 1,000 tweets
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()


import torch
import torch.nn.functional as F

from libs.GANet.modules.GANet import MyLoss2
from modeling.base_model import BaseModel
from utils import Odict
from .GANet_deep import GANet as GANet_deep

class GaLoss:
    def __init__(self, is_kitti=False):
        super(GaLoss, self).__init__()
        self.is_kitti = is_kitti
        self.criterion = MyLoss2(thresh=3, alpha=2)

    def __call__(self, training_output):
        training_disp = training_output['disp']
        pred_disp = training_disp['disp_ests']
        disp_gt = training_disp['disp_gt']
        mask = training_disp['mask']
        disp0, disp1, disp2 = pred_disp
        if self.is_kitti:
            loss = 0.2 * F.smooth_l1_loss(disp0[mask], disp_gt[mask], reduction='mean') \
                   + 0.6 * F.smooth_l1_loss(disp1[mask], disp_gt[mask], reduction='mean') \
                   + self.criterion(disp2[mask], disp_gt[mask])
        else:
            loss = 0.2 * F.smooth_l1_loss(disp0[mask], disp_gt[mask], reduction='mean') \
                   + 0.6 * F.smooth_l1_loss(disp1[mask], disp_gt[mask], reduction='mean') \
                   + F.smooth_l1_loss(disp2[mask], disp_gt[mask], reduction='mean')

        loss_info = Odict()
        loss_info['scalar/train/loss_disp'] = loss
        loss_info['scalar/train/loss_sum'] = loss
        return loss, loss_info

class GANet(BaseModel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def build_loss_fn(self):
        """Build the loss."""
        loss_cfg = self.cfg['loss_cfg']
        is_kitti = loss_cfg.get("is_kitti", False)
        self.loss_fn = GaLoss(is_kitti)

    def build_network(self):
        """Build the network."""
        self.net = GANet_deep(maxdisp=self.max_disp)

    def init_parameters(self):
        return

    def forward(self, inputs):
        """Forward the network."""
        ref_img = inputs["ref_img"]
        tgt_img = inputs["tgt_img"]
        res = self.net(ref_img, tgt_img)

        if self.training:
            [disp0, disp1, disp2] = res
            output = {
                "training_disp": {
                    "disp": {
                        "disp_ests": [disp0, disp1, disp2],
                        "disp_gt": inputs['disp_gt'],
                        "mask": inputs['mask']
                    },
                },
                "visual_summary": {
                    'image/train/image_c': torch.cat([ref_img[0], tgt_img[0]], dim=1),
                    'image/train/disp_c': torch.cat([inputs['disp_gt'][0], res[-1][0]], dim=0),
                },
            }
        else:
            output = {
                "inference_disp": {
                    "disp_est": res
                },
                "visual_summary": {
                    'image/test/image_c': torch.cat([ref_img[0], tgt_img[0]], dim=1),
                    'image/test/disp_c': res[0],
                }
            }
            if 'disp_gt' in inputs:
                output['visual_summary'] = {
                    'image/val/disp_c': torch.cat([inputs['disp_gt'][0], res[0]], dim=0),
                    'image/val/image_c': torch.cat([ref_img[0], tgt_img[0]], dim=1),
                }

        return output


import pygame
import random

pygame.init()

from city_scroll import Scroller

WHITE = (255, 255, 255)
RED = (255, 0, 0)

screen_width=(800)
screen_height=(600)
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Runner Game")

done = False

clock = pygame.time.Clock()

#classes

class RunnerSprite(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load("bird.png")
		self.rect = self.image.get_rect()
		self.image = pygame.transform.scale(self.image,(60,60))

	def draw(self,pos):
		global screen
		screen.blit(self.image,pos)
		self.rect.move(pos)
	def update(self):
		g

#player sprite stuff
bird = RunnerSprite()
all_sprites_list = pygame.sprite.Group()
good_sprites = pygame.sprite.Group()
all_sprites_list.add(bird)
bird.draw((screen_width-100,100))

#scroller stuff

FRONT_SCROLLER_COLOR = (0,0,30)
MIDDLE_SCROLLER_COLOR = (30,30,100)
BACK_SCROLLER_COLOR = (50,50,150)
BACKGROUND_COLOR = (17, 9, 89)

back_scroller = Scroller(screen, screen_width, 100, screen_height-100, BACK_SCROLLER_COLOR, 1)
middle_scroller = Scroller(screen, screen_width, 300, screen_height-70, MIDDLE_SCROLLER_COLOR, 2)
front_scroller = Scroller(screen, screen_width, 500, screen_height-20, FRONT_SCROLLER_COLOR, 3)

back_scroller.add_buildings()
middle_scroller.add_buildings()
front_scroller.add_buildings()
a=0

# -------- Main Program Loop -----------
while not done:
	# --- Main event loop
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			done = True

	# --- Game logic should go here
	if a%30==0:
		back_scroller.add_building(-100)
	if a%20==0:
		middle_scroller.add_building(-100)
	if a%10==0:
		front_scroller.add_building(-100)
	a+=1

	# If you want a background image, replace this clear with blit'ing the
	# background image.
	screen.fill(WHITE)

	# --- Drawing code should go here
	back_scroller.draw_buildings()
	back_scroller.move_buildings()
	middle_scroller.draw_buildings()
	middle_scroller.move_buildings()
	front_scroller.draw_buildings()
	front_scroller.move_buildings()

	eagle.draw((pygame.mouse.get_pos()[0]-30,pygame.mouse.get_pos()[1]-30))

	# --- Go ahead and update the screen with what we've drawn.
	pygame.display.flip()

	# --- Limit to 60 frames per second
	clock.tick(60)

# Close the window and quit.
pygame.quit()
exit() # Needed when using IDLE


#!/usr/bin/env python3
#
# Checks for incorrect whitespace in source files

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import subprocess
import sys
import argparse

from whitespace import Whitespace

source_directory = os.path.join(sys.path[0], '..')

extensions_to_check = [
    'java',
    'py',
    'js',
    'json',
    'html',
    'css',
    'txt',
    'gitignore',
    'yml',
    'md',
    'xml',
    'yaml',
    'conf',
    'sh'
]

config_ignore = [
    '.idea/'
]

extensions_no_tabs = [
    'html',
    'py',
    'yml',
    'sh'
]

def ignore_filename(filename):
    for pattern in config_ignore:
        if filename.startswith(pattern):
            return True
    return False

parser = argparse.ArgumentParser()
parser.add_argument("--fix", help="automatically fix errors", action="store_true")
parser.add_argument("--verbose", help="show verbose output", action="store_true")
args = parser.parse_args()

# only check files known to git - this neatly avoids us processing git ignored files, generated files, etc
command = ['git', 'ls-files']
files = subprocess.check_output(command).decode('utf8')
fixed = False
errors = False
for f in files.split('\n'):
    if len(f) == 0:
        continue
    path, extension = os.path.splitext(f)
    extension = extension[1:]

    if extension not in extensions_to_check:
        if args.verbose:
            print("Skipping '{}': not in extensions_to_check".format(f))
        continue

    if ignore_filename(f):
        if args.verbose:
            print("Skipping '{}': listed in config_ignore".format(f))
        continue

    if args.verbose:
        print("Checking "+f)

    with open(f) as fh:
        lines = fh.read()

    # print("File " + f + " contents:\n" + lines)
    whitespace = Whitespace(lines, fix=args.fix)
    if whitespace.dos_line_endings():
        print('{} has DOS line endings'.format(f))
        errors = True

    if whitespace.has_trailing():
        print('{} contains trailing whitespace'.format(f))
        errors = True

    if whitespace.missing_final_newline():
        print('{} is missing final newline'.format(f))
        errors = True

    if whitespace.blank_lines_at_end():
        print('{} has blank lines at end'.format(f))
        errors = True

    if extension in extensions_no_tabs and whitespace.has_tabs():
        print('{} has tabs'.format(f))
        errors = True

    if whitespace.fixed:
        fixed = True
        with open(f, 'w') as fh:
            fh.write(whitespace.lines)
        print('{} has been fixed'.format(f))

if fixed:
    print('All errors fixed')

if errors:
    sys.exit(1)


from flask import Flask
from flask import render_template,request,make_response
from utils.func_clustering import clustering
from utils.StatisticFunction import statistics
from utils.func_cleanexcel import cleanDataframe
# from utils.decisiontree import DecisionTree
from utils.decisiontree import getanswer
from utils.func_grouping import grouping
from utils.assocrule import association
from werkzeug.utils import secure_filename
import os
import pandas as pd
from flask_cors import CORS
import json
import gunicorn
import xlrd
import openpyxl
import psutil
from operator import xor
import math
import requests

app = Flask(__name__,static_folder = "static")
CORS(app)
app.config['UPLOAD_EXTENSION'] = ['.xls','.xlsx','.csv']
app.config['UPLOAD_PATH'] = 'Files'
app.config['STATIC_PATH'] = 'static'
MYDIR = os.path.dirname(__file__)
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

file_to_be_analyze = ''

@app.route('/')
def hello():

    files_dir = app.config['UPLOAD_PATH']
    for root, dirs, files in os.walk(files_dir):
        for name in files:
            # if (name == file_to_be_analyze):
            os.remove(os.path.join(root,name))
            print('We gonna remove' + os.path.join(root,name))

    files_dir_2 = app.config['STATIC_PATH']
    for root,dirs,files in os.walk(files_dir_2):
        for name in files:
            if ('.png' in name):
                os.remove(os.path.join(root,name))
                print('We gonna remove' + os.path.join(root,name))

    return render_template('index.html')

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

@app.route('/submit', methods=['POST'])
def submitFile():

    uploaded_file = request.files['file']
    filename = secure_filename(uploaded_file.filename)
    if filename != '':
        file_ext = os.path.splitext(filename)[1]
        if file_ext not in app.config['UPLOAD_EXTENSION']:
            return
        uploaded_file.save(os.path.join(MYDIR + '/' + app.config['UPLOAD_PATH'],filename))
        global file_to_be_analyze
        file_to_be_analyze = filename
    msg = "Your file is uploaded , the file is" + file_to_be_analyze
    print(msg)
    return render_template('submit.html', msg=msg)

@app.route('/analyze', methods=['GET','POST'])
def analyze():

    file = app.config['UPLOAD_PATH']+'/'+ file_to_be_analyze
    df = pd.read_excel(file)
    df.fillna(0,inplace=True)
    qa_clustering = clustering(df)
    qa_statistic = statistics(df)
    qa_assoocrule = association(df)
    qa_grouping = grouping(df)
    qa={**qa_clustering,**qa_assoocrule,**qa_statistic,**qa_grouping}
    number_of_item = len(qa)
    list_number_of_item = list(range(0,number_of_item))
    i = 0
    qx = {}

    for question in qa:
        question_answer = [question]
        for answer in qa[question]:
            question_answer.append(answer)
            # question_answer.append(answer[1])
        qx[list_number_of_item[i]] = question_answer
        # print(question_answer[1:])
        i=i+1

    msg = 'This page will analyze data from your uploaded file '+ app.config['UPLOAD_PATH']+'/' + file_to_be_analyze
    print(msg)
    if (request.method == 'POST'):
        response = make_response(render_template('analyze.html',  msg=msg, qa=qx, zip=zip))
        response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
        response.headers['Pragma'] = 'no-cache'
        # print(qx)
        return response
    # else:
    #     return render_template('answers.html',  msg=msg, qa=qa)

@app.route('/predict' , methods=['POST'])
def predict():
    file = app.config['UPLOAD_PATH']+'/' + file_to_be_analyze
    df_before_clean = pd.read_excel(file)
    df_after_clean = cleanDataframe(df_before_clean)

    columns = list(df_after_clean)
    columns_values = {}
    for col in columns:
        value_of_col = (list(set(df_after_clean[col])))
        # print(col)
        # print(value_of_col)
        columns_values[col] = value_of_col
    # print(columns_values)

    print('We gonna predict '+app.config['UPLOAD_PATH']+'/' + file_to_be_analyze)

    msg = 'This page will predict data from your uploaded file'
    return render_template('predict.html',  msg=msg, columns_values=columns_values,columns=columns)

@app.route('/showoutput', methods=['POST'])
def showOutput():

    # test = request.form.get("selector")
    # print(test)

    file = app.config['UPLOAD_PATH']+'/'+ file_to_be_analyze
    df_before_clean = pd.read_excel(file)
    df_after_clean = cleanDataframe(df_before_clean)
    # print('------')
    # print(df_before_clean)
    # print('------')
    # print(df_after_clean)
    # print('------')
    copy_df_after_clean = df_after_clean.copy(deep=True)
    columns = list(df_after_clean)
    #col_val_selector is the user's inputs
    col_val_selector = {}
    #target_column will be the last column of dataframe
    target_column = request.form.get("target_column")
    # print(target_column)
    for col in columns:
        if col != target_column:
            col_val_selector[col] = request.form.get("selector-for-"+col)
    # print(col_val_selector)
    # x = DecisionTree()
    answerList = getanswer(df_after_clean,col_val_selector)
    answer = answerList[0]
    score = answerList[1]
    # print(type(df_after_clean))
    # print(columns)
    print('We gonna show output for  '+app.config['UPLOAD_PATH']+'/' + file_to_be_analyze)
    # print(target_column)
    # print(col_val_selector)
    # print(answer)

    return render_template('predict-answer.html', target_column=target_column, answer=answer, score=score,col_val_selector=col_val_selector)

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(host="0.0.0.0", port=port,debug=True)
    # app.run(host="0.0.0.0",debug=True)


from django.test import TestCase

from database.models import (
    Description,
    OldnameNewnameTableLeft,
    OldnameNewnameTableRight,
    PesticidalProteinDatabase,
    PesticidalProteinPrivateDatabase,
    ProteinDetail,
    StructureDatabase,
    UserUploadData,
)

class PesticidalProteinDatabaseModelTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        PesticidalProteinDatabase.objects.create(name="Cry1001Aa1", oldname="R1")

    def test_name_label(self):
        protein = PesticidalProteinDatabase.objects.get(id=1)
        field_label = PesticidalProteinDatabase._meta.get_field("name").verbose_name
        self.assertEquals(field_label, "Protein Name")

    def test_name_max_length(self):
        protein = PesticidalProteinDatabase.objects.get(id=1)
        max_length = PesticidalProteinDatabase._meta.get_field("name").max_length
        self.assertEquals(max_length, 15)

    def setUp(self):
        self.database = PesticidalProteinDatabase.objects.create(
            submittersname="Suresh",
            submittersemail="admin@bpprc.org",
            name="Rpp1001Aa1",
            oldname="",
            othernames="",
            accession="M7829DHR",
            year="2023",
            sequence="MEKYMLLAQFPAEKTLNETDIPSATLQLLTGKQAGVARPGGIFTKEDLINIKLYV",
            bacterium="True",
            bacterium_textbox="Photorhabdus khanii",
            taxonid="1004151",
            partnerprotein="False",
            partnerprotein_textbox="",
            toxicto="",
            nontoxic="",
            dnasequence="",
            publication="",
        )

    def test_post_model(self):
        data = self.database
        self.assertTrue(isinstance(data, PesticidalProteinDatabase))

    def test_PesticidalProteinDatabase_name(self):
        database = self.database
        self.assertEqual(database.__str__(), "Rpp1001Aa1")

    def test_category_name(self):
        database = str(self.database.name)
        print(database[:3])
        category_name = database[:3]
        self.assertEqual(category_name, "Rpp")


import oauth
import urllib

from django.conf import settings

signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()

SERVER = getattr(settings, 'OAUTH_SERVER', 'twitter.com')
REQUEST_TOKEN_URL = getattr(settings, 'OAUTH_REQUEST_TOKEN_URL', 'https://%s/oauth/request_token' % SERVER)
ACCESS_TOKEN_URL = getattr(settings, 'OAUTH_ACCESS_TOKEN_URL', 'https://%s/oauth/access_token' % SERVER)
AUTHORIZATION_URL = getattr(settings, 'OAUTH_AUTHORIZATION_URL', 'http://%s/oauth/authorize' % SERVER)

CONSUMER_KEY = getattr(settings, 'CONSUMER_KEY', 'YOUR_KEY')
CONSUMER_SECRET = getattr(settings, 'CONSUMER_SECRET', 'YOUR_SECRET')

# We use this URL to check if Twitters oAuth worked
TWITTER_CHECK_AUTH = 'https://twitter.com/account/verify_credentials.json'
TWITTER_FRIENDS = 'https://twitter.com/statuses/friends.json'

def request_oauth_resource(consumer, url, access_token, parameters=None, signature_method=signature_method, http_method="GET"):
    """
    usage: request_oauth_resource( consumer, '/url/', your_access_token, parameters=dict() )
    Returns a OAuthRequest object
    """
    oauth_request = oauth.OAuthRequest.from_consumer_and_token(
        consumer, token=access_token, http_method=http_method, http_url=url, parameters=parameters,
    )
    oauth_request.sign_request(signature_method, consumer, access_token)
    return oauth_request

def fetch_response(oauth_request, connection):
    url = oauth_request.to_url()
    connection.request(oauth_request.http_method, url)
    response = connection.getresponse()
    s = response.read()
    return s

def get_unauthorised_request_token(consumer, connection, signature_method=signature_method):
    oauth_request = oauth.OAuthRequest.from_consumer_and_token(
        consumer, http_url=REQUEST_TOKEN_URL
    )
    oauth_request.sign_request(signature_method, consumer, None)
    resp = fetch_response(oauth_request, connection)
    token = oauth.OAuthToken.from_string(resp)
    return token

def get_authorisation_url(consumer, token, signature_method=signature_method):
    oauth_request = oauth.OAuthRequest.from_consumer_and_token(
        consumer, token=token, http_url=AUTHORIZATION_URL
    )
    oauth_request.sign_request(signature_method, consumer, token)
    return oauth_request.to_url()

def get_oauth_url(oauth_request):
    url = oauth_request.to_url()
    package = urllib.urlopen(url)
    return package.read()

def exchange_request_token_for_access_token(consumer, request_token, signature_method=signature_method, params={}):
    oauth_request = oauth.OAuthRequest.from_consumer_and_token(
        consumer, token=request_token, http_url=ACCESS_TOKEN_URL, parameters=params
    )
    oauth_request.sign_request(signature_method, consumer, request_token)
    resp = get_oauth_url(oauth_request)
    return oauth.OAuthToken.from_string(resp)

def is_authenticated(consumer, connection, access_token):
    oauth_request = request_oauth_resource(consumer, TWITTER_CHECK_AUTH, access_token)
    json = fetch_response(oauth_request, connection)
    if 'screen_name' in json:
        return json
    return False

def get_friends(consumer, connection, access_token, page=0):
    """Get friends on Twitter"""
    oauth_request = request_oauth_resource(consumer, TWITTER_FRIENDS, access_token, {'page': page})
    json = fetch_response(oauth_request, connection)
    return json

def update_status(consumer, connection, access_token, status):
    """Update twitter status, i.e., post a tweet"""
    oauth_request = request_oauth_resource(consumer,
                                           TWITTER_UPDATE_STATUS,
                                           access_token,
                                           {'status': status},
                                           http_method='POST')
    json = fetch_response(oauth_request, connection)
    return json


import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

import torch
from torch.fft import fftn, fftshift
from torch.linalg import vector_norm

def azimuthalAverage(image, center=None):
    """
    Calculate the azimuthally averaged radial profile.

    :param image: Input image (can be 2D or 3D)
    :param center: The pixel coordinates used as the center. The default is
                None, which then uses the center of the image (including
                fractional pixels).
    :return: The azimuthally averaged radial profile.

    """
    dim = len(image.shape)

    # Calculate the indices from the image
    if dim == 2:
        y, x = torch.meshgrid(torch.arange(image.shape[0]),
                              torch.arange(image.shape[1]),
                              indexing='ij')
        if not center:
            center = torch.tensor([(x.max() - x.min()) / 2.0,
                                   (y.max() - y.min()) / 2.0])
        r = vector_norm(
            torch.stack(
                [x - center[0], y - center[1]]
            ),
            ord=2,
            dim=0
        )

    elif dim == 3:
        z, y, x = torch.meshgrid(torch.arange(image.shape[0]),
                                 torch.arange(image.shape[1]),
                                 torch.arange(image.shape[2]),
                                 indexing='ij')
        if not center:
            center = torch.tensor([(x.max() - x.min()) / 2.0,
                                   (y.max() - y.min()) / 2.0,
                                   (z.max() - z.min()) / 2.0])
        r = vector_norm(
            torch.stack(
                [x - center[0], y - center[1], z - center[2]]
            ),
            ord=2,
            dim=0
        )
    else:
        raise ValueError(f'Expecting input to be 2D or 3D. Got {dim}D instead.')

    # Get sorted radii
    r_flat = torch.flatten(r)
    ind = torch.argsort(r_flat)
    r_sorted = r_flat[ind]
    image_flat = torch.flatten(image)
    i_sorted = image_flat[ind]

    # Get the integer part of the radii (bin size = 1)
    r_int = r_sorted.long()

    # Find all pixels that fall within each radial bin.
    deltar = r_int[1:] - r_int[:-1]  # Assumes all radii represented
    rind = torch.where(deltar)[0]  # location of changed radius
    nr = rind[1:] - rind[:-1]  # number of radius bin

    # Cumulative sum to figure out sums for each radius bin
    csim = torch.cumsum(i_sorted, dim=-1, dtype=torch.float64)
    tbin = csim[rind[1:]] - csim[rind[:-1]]

    radial_prof = tbin / nr

    return radial_prof

def get_spectrum(img, epsilon=1e-8):
    f = fftn(img)
    f = fftshift(f)
    f += epsilon

    magnitude_spectrum = 20 * torch.log(torch.abs(f))

    # Calculate the azimuthally averaged 1D power spectrum
    psd1D = azimuthalAverage(magnitude_spectrum)
    print(psd1D.shape)

    return psd1D

if __name__ == '__main__':
    img = Image.open("./cat.jpg").convert('L')
    arr = np.array(img.getdata(), dtype=np.float32)
    arr = arr.reshape(img.size[1], img.size[0])
    arr = arr / 255.0
    arr = torch.tensor(arr)

    psd1D = get_spectrum(arr)

    plt.plot(psd1D)
    plt.xlabel('Spatial Frequency')
    plt.ylabel('Log Power Spectral Density')
    plt.title('1D Power Spectrum')
    plt.savefig('./psd1D.png', dpi=300, bbox_inches='tight')
    plt.show()


import csv
from hashtable import HashTable
from datetime import datetime

class Package:
    status_dict = {0: 'DELAYED', 1: 'AT THE HUB', 2: 'EN ROUTE', 3: 'DELIVERED', }

    def __init__(self, id, address, city, state, zip, deadline, mass, special_note):
        self.id = id
        self.address = address
        self.city = city
        self.state = state
        self.zip = zip
        self.deadline = deadline
        self.mass = mass
        self.special_note = special_note

        self.status = 1
        self.valid = True
        self.truck_dependency = None
        self.at_hub_time = str2time("8:00 AM")
        self.en_route_time = str2time("11:59 PM")
        self.delivered_time = str2time("11:59 PM")
        self.location = None
        self.address_hash = None

    # Update address information of package in invalid
    # Time Complexity for update address -> O(1)
    def update_address(self, address, city, state, zip):
        if self.valid is False:
            self.address = address
            self.city = city
            self.state = state
            self.zip = zip
            self.location = self.address_hash.search(address)
            self.valid = True
        else:
            return False

    # Display single line package status information for full report
    # Time Complexity for get brief information -> O(1)
    def get_brief_inf(self, time):
        set_time = str2time(time)

        # Determine if package was delivered at or after given time
        if self.delivered_time < set_time:
            delivery_status = Package.status_dict.get(3) + " at " + self.delivered_time.strftime('%I:%M %p')
        # Determine if package was en route at or after given time
        elif self.en_route_time < set_time:
            delivery_status = Package.status_dict.get(2)
        # Determine if package was at hub at or after given time
        else:
            delivery_status = Package.status_dict.get(1)

        print(
            f'Package ID: {self.id}, '
            f'Status: {delivery_status}'
        )

    # Display full package information and status
    # Time Complexity for get full information -> O(1)
    def get_full_inf(self, time):
        set_time = str2time(time)

        # Determine if package was delivered at or after given time
        if self.delivered_time < set_time:
            delivery_status = Package.status_dict.get(3) + " at " + self.delivered_time.strftime('%I:%M %p')
        # Determine if package was en route at or after given time
        elif self.en_route_time < set_time:
            delivery_status = Package.status_dict.get(2)
        # Determine if package was at hub at or after given time
        else:
            delivery_status = Package.status_dict.get(1)
        print('---------------------------------------------------')
        print('ID:       ', self.id)
        print('Address:  ', self.address)
        print('Deadline: ', self.deadline)
        print('City:     ', self.city)
        print('Zip:      ', self.zip)
        print(f'Weight:    {self.mass}kg')
        print('Status:   ', delivery_status)
        print('---------------------------------------------------')

# Time Complexity for import package list -> O(n)
# Space Complexity for import package list -> O(n)
def import_package_list(filename, address_hash):
    with open(filename) as csvfile:
        read_csv = csv.reader(csvfile, delimiter=',')
        # Skip first header row of CSV file
        next(read_csv)
        # Create variable for HashTable calling out capacity based on package list size
        hash_table = HashTable(41)
        package_list = []
        for row in read_csv:
            id = int(row[0])
            address = row[1]
            city = row[2]
            state = row[3]
            zip = row[4]
            deadline = str2time(row[5])
            mass = row[6]
            special_note = row[7].upper()  # Handles case sensitivity
            package = Package(id, address, city, state, zip, deadline, mass, special_note)
            package.location = address_hash.search(address)
            hash_table.add(id, package)
            # Adding address hash to each package to validate addresses for updates
            package.address_hash = address_hash
            # Check specialty comment for delayed packages update at hub to delay time
            if 'WILL NOT ARRIVE TO DEPOT UNTIL' in special_note:
                split_string = special_note.split('WILL NOT ARRIVE TO DEPOT UNTIL ')
                arrival_time = split_string[len(split_string) - 1]
                package.at_hub_time = str2time(arrival_time)

            # Check specialty comment indicating wrong information listed, set valid status to false
            elif 'WRONG ADDRESS LISTED' in special_note:
                package.valid = False
            # Check specialty comment for truck dependency and add truck as attribute
            elif 'CAN ONLY BE ON' in special_note:
                split_string = special_note.split('CAN ONLY BE ON ')
                truck_dependency = split_string[len(split_string) - 1]
                package.truck_dependency = str2time(truck_dependency)
            package_list.append(package)
    return hash_table, package_list

# Converts string to time variable
# Time Complexity for string to time -> O(1)
def str2time(string):
    try:
        return datetime.strptime(string, '%I:%M %p')
    except ValueError:
        return string


import os
import cv2
import random
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
from pathlib import Path

import torch
from torch_geometric.loader import DataLoader

import deep_hand_eye.pose_utils as p_utils
from deep_hand_eye.utils import AttrDict
from deep_hand_eye.dataset import MVSDataset
from deep_hand_eye.viz_utils import vizualize_poses

MODEL_PATH = 'models/2022-10-17--19-11-31/model.pt'
DATA_PATH = "data/DTU_MVS_2014/Rectified/test/"
MAX_SAMPLES = 20
LOG_DIR = "eval"
LOG_IMAGES = True

config = AttrDict()
config.seed = 0
config.device = "cuda"
config.num_workers = 8
config.batch_size = 2

def seed_everything(seed: int):
    """From https://pytorch-lightning.readthedocs.io/en/latest/_modules/pytorch_lightning/utilities/seed.html#seed_everything"""
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)

@torch.no_grad()
def run_eval():
    seed_everything(config.seed)
    log_dir = Path(LOG_DIR)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    model = torch.load(MODEL_PATH)
    model.eval()

    test_dataset = MVSDataset(image_folder=DATA_PATH, get_raw_images=True)
    test_dataloader = DataLoader(
        dataset=test_dataset,
        batch_size=config.batch_size,
        shuffle=True,
        num_workers=config.num_workers
    )

    # loss functions
    t_criterion = lambda t_pred, t_gt: np.linalg.norm(t_pred - t_gt, axis=-1)
    q_criterion = p_utils.quaternion_angular_error

    t_loss_he = []
    q_loss_he = []
    t_loss_R = []
    q_loss_R = []
    count = 0

    # inference loop
    for data in tqdm(test_dataloader, total=MAX_SAMPLES // config.batch_size):
        data = data.to(config.device)
        output_he, output_R, _ = model(data)

        output_he = output_he.cpu().numpy()
        target_he = data.y.cpu().numpy()
        output_R = output_R.cpu().numpy()
        target_R = data.y_edge.cpu().numpy()

        # Generate poses from predictions and label for hand-eye pose
        q = [p_utils.qexp(p[3:]) for p in output_he]
        output_he = np.hstack((output_he[:, :3], np.asarray(q)))
        q = [p_utils.qexp(p[3:]) for p in target_he]
        target_he = np.hstack((target_he[:, :3], np.asarray(q)))

        # Calculate hand-eye losses
        t_loss_he_batch = t_criterion(output_he[:, :3], target_he[:, :3])
        q_loss_he_batch = q_criterion(output_he[:, 3:], target_he[:, 3:])

        # Generate poses from predictions and label for relative poses
        q = [p_utils.qexp(p[3:]) for p in output_R]
        output_R = np.hstack((output_R[:, :3], np.asarray(q)))
        q = [p_utils.qexp(p[3:]) for p in target_R]
        target_R = np.hstack((target_R[:, :3], np.asarray(q)))

        t_loss_R_batch = t_criterion(output_R[:, :3], target_R[:, :3])
        q_loss_R_batch = q_criterion(output_R[:, 3:], target_R[:, 3:])

        t_loss_he.append(t_loss_he_batch)
        q_loss_he.append(q_loss_he_batch)
        t_loss_R.append(t_loss_R_batch)
        q_loss_R.append(q_loss_R_batch)

        edge_batch_idx = data.batch[data.edge_index[0]].cpu().numpy()
        edge_first_nodes = data.edge_index[0].cpu().numpy()

        # Visualization of Results
        for graph_id in range(data.num_graphs):
            img_list = data.raw_images[graph_id]
            count += 1

            axis, angle = p_utils.quaternion_to_axis_angle(target_he[graph_id, 3:], in_degrees=True)
            edge_mask = edge_batch_idx == graph_id
            rel_pos_error = t_loss_R_batch[edge_mask].mean(axis=0) * 1000
            rel_rot_error = q_loss_R_batch[edge_mask].mean(axis=0)

            row1 = cv2.hconcat([cv2.resize(img_list[0], (600, 450)), cv2.resize(img_list[1], (600, 450)), cv2.resize(img_list[2], (600, 450))])
            row2 = cv2.hconcat([cv2.resize(img_list[3], (600, 450)), cv2.resize(img_list[4], (600, 450)), np.zeros_like(cv2.resize(img_list[3], (600, 450)))])
            combined = cv2.vconcat([row1, row2])

            pos_str = "  ".join([f"{1000 * item: 0.2f}" for item in target_he[graph_id, :3]])
            he_pos_str = "HE Translation (mm):  " + pos_str + f"  Total: {1000 * np.linalg.norm(target_he[graph_id, :3]): 0.2f}"
            axis_str = "  ".join([f"{item: 0.4f}" for item in axis])
            he_rot_str = f"HE Angle {angle: 0.2f} degrees   Axis: " + axis_str

            cv2.putText(combined, he_pos_str, (1200, 550), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 0, 0), 1)
            cv2.putText(combined, he_rot_str, (1200, 600), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 0, 0), 1)
            cv2.putText(combined, f"HE Translation Error: {t_loss_he_batch[graph_id]*1000:3.2f} mm", (1200, 650), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 0, 0), 1)
            cv2.putText(combined, f"HE Rotation Error: {q_loss_he_batch[graph_id]:3.2f} degrees", (1200, 700), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 0, 0), 1)
            cv2.putText(combined, f"Relative Translation Error: {rel_pos_error:3.2f} mm", (1200, 750), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 0, 0), 1)
            cv2.putText(combined, f"Relative Rotation Error: {rel_rot_error:3.2f} degrees", (1200, 800), cv2.FONT_HERSHEY_SIMPLEX, .5, (255, 0, 0), 1)
            if LOG_IMAGES:
                plt.imsave(str(log_dir / f"data_{count}.jpg"), combined)
            plt.imshow(combined)
            plt.show()

            graph_first_node = min(edge_first_nodes[edge_mask])
            reqd_edges = edge_first_nodes == graph_first_node

            R_poses = target_R[reqd_edges]
            R_poses = np.vstack((np.array([[0, 0, 0, 1, 0, 0, 0]], dtype=float), R_poses))
            vizualize_poses(R_poses)

        if count > MAX_SAMPLES:
            break

    t_loss_he = np.concatenate(t_loss_he, axis=0)
    q_loss_he = np.concatenate(q_loss_he, axis=0)
    t_loss_R = np.concatenate(t_loss_R, axis=0).reshape(-1)
    q_loss_R = np.concatenate(q_loss_R, axis=0).reshape(-1)

    def get_stats(qty):
        return np.mean(qty, axis=0), np.median(qty, axis=0), np.max(qty, axis=0)

    mean_t_he, median_t_he, max_t_he = get_stats(t_loss_he)
    mean_q_he, median_q_he, max_q_he = get_stats(q_loss_he)

    mean_t_R, median_t_R, max_t_R = get_stats(t_loss_R)
    mean_q_R, median_q_R, max_q_R = get_stats(q_loss_R)

    fig, axs = plt.subplots(2, 2, tight_layout=True)
    axs[0, 0].hist(1000*np.array(t_loss_he), bins=125)
    axs[0, 0].set_title('Hand-eye Translational Error')
    axs[0, 0].set_xlabel('Error [mm]')
    axs[0, 0].set_ylabel('Number of Instances')
    axs[0, 0].minorticks_on()
    axs[0, 1].hist(q_loss_he, bins=125)
    axs[0, 1].set_title('Hand-eye Rotational Error')
    axs[0, 1].set_xlabel('Error [deg]')
    axs[0, 1].set_ylabel('Number of Instances')
    axs[0, 1].minorticks_on()
    axs[1, 0].hist(1000*np.array(t_loss_R), bins=125)
    axs[1, 0].set_title('Relative Translational Error')
    axs[1, 0].set_xlabel('Error [mm]')
    axs[1, 0].set_ylabel('Number of Instances')
    axs[1, 0].minorticks_on()
    axs[1, 1].hist(q_loss_R, bins=125)
    axs[1, 1].set_title('Relative Rotational Error')
    axs[1, 1].set_xlabel('Error [deg]')
    axs[1, 1].set_ylabel('Number of Instances')
    axs[1, 1].minorticks_on()
    plt.show()

    print(f'Error in translation: \n'
            f'\t median {median_t_he:3.2f} m \n'
            f'\t mean {mean_t_he:3.2f} m \n'
            f'\t max {max_t_he:3.2f} m \n'
            f'Error in rotation: \n'
            f'\t median {median_q_he:3.2f} degrees \n'
            f'\t mean {mean_q_he:3.2f} degrees \n'
            f'\t max {max_q_he:3.2f} degrees \n'
            f'Error in relative translation: \n'
            f'\t median {median_t_R:3.2f} m \n'
            f'\t mean {median_q_R:3.2f} m \n'
            f'\t max {mean_t_R:3.2f} m \n'
            f'Error in relative rotation: \n'
            f'\t median {mean_q_R:3.2f} degrees \n'
            f'\t mean {max_t_R:3.2f} degrees \n'
            f'\t max {max_q_R:3.2f} degrees \n')

if __name__ == "__main__":
    run_eval()