# -*- coding: utf-8 -*-
"""
This module containes a set of thin wrappers to
hook the methods in postprocess package to X-ray
absorption tomography data object.
"""

# Import main TomoPy object.
from syncpy.tomopy.xtomo.xtomo_dataset import XTomoDataset

# Import available functons in the package.
from syncpy.tomopy.algorithms.postprocess.adaptive_segment import _adaptive_segment
from syncpy.tomopy.algorithms.postprocess.remove_background import _remove_background
from syncpy.tomopy.algorithms.postprocess.region_segment import _region_segment
from syncpy.tomopy.algorithms.postprocess.threshold_segment import _threshold_segment

# Import multiprocessing module.
from syncpy.tomopy.tools.multiprocess import distribute_jobs

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

def adaptive_segment(xtomo, block_size=256, offset=0,
                     num_cores=None, chunk_size=None,
                     overwrite=True):

    # Normalize data first.
    data = xtomo.data_recon - xtomo.data_recon.min()
    data /= data.max()

    # Distribute jobs.
    _func = _adaptive_segment
    _args = (block_size, offset)
    _axis = 0 # Slice axis
    data_recon = distribute_jobs(data, _func, _args, _axis,
                                 num_cores, chunk_size)

    # Update log.
    xtomo.logger.debug("adaptive_segment: block_size: " + str(block_size))
    xtomo.logger.debug("adaptive_segment: offset: " + str(offset))
    xtomo.logger.info("adaptive_segment [ok]")

    # Update returned values.
    if overwrite: xtomo.data_recon = data_recon
    else: return data_recon

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

def region_segment(xtomo, low=None, high=None,
                   num_cores=None, chunk_size=None,
                   overwrite=True):

    # Normalize data first.
    data = xtomo.data_recon - xtomo.data_recon.min()
    data /= data.max()

    # Distribute jobs.
    _func = _region_segment
    _args = (low, high)
    _axis = 0 # Slice axis
    data_recon = distribute_jobs(data, _func, _args, _axis,
                                 num_cores, chunk_size)

    # Update provenance.
    xtomo.logger.debug("region_segment: low: " + str(low))
    xtomo.logger.debug("region_segment: high: " + str(high))
    xtomo.logger.info("region_segment [ok]")

    # Update returned values.
    if overwrite: xtomo.data_recon = data_recon
    else: return data_recon

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

def remove_background(xtomo,
                      num_cores=None, chunk_size=None,
                      overwrite=True):

    # Distribute jobs.
    _func = _remove_background
    _args = ()
    _axis = 0 # Slice axis
    data_recon = distribute_jobs(xtomo.data_recon, _func, _args, _axis,
                                 num_cores, chunk_size)

    # Update provenance.
    xtomo.logger.info("remove_background [ok]")

    # Update returned values.
    if overwrite: xtomo.data_recon = data_recon
    else: return data_recon

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

def threshold_segment(xtomo, cutoff=None,
                      num_cores=None, chunk_size=None,
                      overwrite=True):

    # Normalize data first.
    data = xtomo.data_recon - xtomo.data_recon.min()
    data /= data.max()

    # Distribute jobs.
    _func = _threshold_segment
    _args = ()
    _axis = 0 # Slice axis
    data_recon = distribute_jobs(data, _func, _args, _axis,
                                 num_cores, chunk_size)

    # Update provenance.
    xtomo.logger.debug("threshold_segment: cutoff: " + str(cutoff))
    xtomo.logger.info("threshold_segment [ok]")

    # Update returned values.
    if overwrite: xtomo.data_recon = data_recon
    else: return data_recon

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

# Hook all these methods to TomoPy.
setattr(XTomoDataset, 'adaptive_segment', adaptive_segment)
setattr(XTomoDataset, 'remove_background', remove_background)
setattr(XTomoDataset, 'region_segment', threshold_segment)
setattr(XTomoDataset, 'threshold_segment', threshold_segment)

# Use original function docstrings for the wrappers.
adaptive_segment.__doc__ = _adaptive_segment.__doc__
remove_background.__doc__ = _remove_background.__doc__
region_segment.__doc__ = _region_segment.__doc__
threshold_segment.__doc__ = _threshold_segment.__doc__


class Solution:
    def validPalindrome(self, s: str) -> bool:
        i = 0
        j = len(s)-1
        while i<j:
            if s[i]!=s[j]:
                leftPointer=s[i+1:j+1]
                rightPointer=s[i:j]
                return leftPointer == leftPointer[-1::-1] or rightPointer == rightPointer[-1::-1]
            else:
                i+=1
                j-=1
        return True


import unittest
from ..app.player import Player
from ..app.board import Board

class TestPlayer(unittest.TestCase):

    """docstring for TestPlayer."""

    def test_player_name_on_object_creation(self):
        self.player = Player("Tester Testersen")
        player_name = self.player.get_name()
        self.assertEqual("Tester Testersen", player_name)

    def test_two_players_name(self):
        self.player1 = Player("Player1")
        self.player2 = Player("Player2")
        self.assertEqual("Player1", self.player1.get_name())
        self.assertEqual("Player2", self.player2.get_name())

    def test_that_player_have_two_boards(self):
        self.player = Player("Player")
        self.assertIs(self.player.get_tracking_board().__class__, Board)
        self.assertIs(self.player.get_primary_board().__class__, Board)

if __name__ == '__main__':
    unittest.main()


import logging
from tvm import topi, te
from tvm.target import Target
from .. import tag

def schedule_pool(outs, layout):
    """Create schedule for avgpool/maxpool"""

    if layout != "NHWC":
        logger = logging.getLogger("topi")
        logger.warning(
            """We currently only support NHWC target specific pools on arm_cpu,
               falling back on generic pool scheduling"""
        )
        return topi.generic.schedule_pool(outs, layout)

    return schedule_pool_2d(outs)

def schedule_pool_2d(outs):
    """Create arm_cpu specific 2D schedule for avgpool/maxpool"""

    outs = [outs] if isinstance(outs, te.tensor.Tensor) else outs
    schedule_ops = [x.op for x in outs]
    schedule = te.create_schedule(schedule_ops)
    scheduled_ops = []

    def traverse(op):
        # Recursively inline any injective operation that isn't the pooling
        # operation or hasn't already been scheduled.
        if tag.is_injective(op.tag):
            if op not in schedule.outputs:
                schedule[op].compute_inline()
            for tensor in op.input_tensors:
                if isinstance(tensor.op, te.tensor.ComputeOp) and tensor.op not in scheduled_ops:
                    traverse(tensor.op)
        # schedule the actual pooling operation
        elif op.tag.startswith("pool"):
            n, height, width, channel = schedule[op].op.axis
            # Average pool consists of two parts; a sum then a division.
            # We can schedule the division loop to parallelize across height and
            # vectorize across width.
            enable_explicit_vectorization = not Target.current(allow_none=False).features.has_sve
            if op != outs[0].op:
                output = outs[0]
                output_fused = schedule[output].fuse(output.op.axis[1], output.op.axis[2])
                schedule[output].parallel(output_fused)
                vectorization_factor = (
                    8 if enable_explicit_vectorization else output.op.axis[3].dom.extent
                )
                _, inner = schedule[output].split(output.op.axis[3], vectorization_factor)
                schedule[output].vectorize(inner)

            padded_input = op.input_tensors[0]
            if isinstance(padded_input.op, te.tensor.ComputeOp):
                schedule[padded_input].compute_inline()

            # For targets without SVE try explicitly vectorizing the channel
            # loop, For SVE targets leave the loop in place for LLVM to convert
            # into a scalable vector loop.
            vectorization_factor = 8 if enable_explicit_vectorization else channel.dom.extent
            channel_outer, channel_inner = schedule[op].split(channel, vectorization_factor)
            schedule[op].vectorize(channel_inner)
            schedule[op].parallel(height)
            if len(schedule[op].op.reduce_axis) > 0:
                filter_height, filter_width = schedule[op].op.reduce_axis
                # We consider any filter of area < 10 to be small enough to
                # unroll; 3x3 filters have shown better performance when
                # unrolled.
                if filter_height.dom.extent * filter_width.dom.extent <= 9:
                    # For small filters, unrolling the filter loops allows us to
                    # vectorize over channels without reordering anything.
                    schedule[op].unroll(filter_width)
                    schedule[op].unroll(filter_height)
                else:
                    # Reordering so that channels is the fastest moving axis allows
                    # LLVM to vectorize across contiguous memory in the NHWC
                    # ordering.
                    schedule[op].reorder(
                        n, height, width, filter_height, filter_width, channel_outer, channel_inner
                    )
            else:
                schedule[op].reorder(n, height, width, channel_outer, channel_inner)
        else:
            raise RuntimeError("Unsupported operator: %s" % op.tag)

        scheduled_ops.append(op)

    traverse(outs[0].op)
    return schedule


def get_inputs(filename: str):
    with open(filename, "r") as file:
        lines = file.read().splitlines()

    first = lines[0].split(" ")
    N = int(first[0])
    M = int(first[1])

    n = lines[1].split(" ")

    numbers = []

    for v in n:
        numbers.append(int(v))

    return (N, M, numbers)

for i in range(1, 6):
    N, M, numbers = get_inputs("input2/input"+str(i))

    waiting = 0
    parking = 0

    max_waiting = 0
    max_parking = 0

    for number in numbers:
        if number > 0:
            if parking < N:
                parking += 1
            else:
                waiting += 1
        else:
            if waiting > 0:
                waiting -= 1
            else:
                parking -= 1

        if parking > max_parking:
            max_parking = parking
        if waiting > max_waiting:
            max_waiting = waiting

    print(max_parking, max_waiting)


import random

from astral import Astral
from datetime import datetime, timedelta, time
from timedevent import TimedEvent
from scenes import VACATION_SCENES

import logging
logger = logging.getLogger(__name__)

#
#   This event builds the script of events for vacation mode for a single day.  Once it executes, it will rescue
#
class VacationBuildEvent(TimedEvent):
    def __init__(self, event_time, parent):
        TimedEvent.__init__(self, event_time)
        self.parent = parent

    def execute(self):
        date = datetime.now().date()
        events = self.parent.create_scene_script(date)
        for event in events:
            if event.event_time >= datetime.now():
                self.parent.home.timed_event_queue.add_event(event)
        date += timedelta(days=1)
        next_build_time = datetime.combine(date, time(10))      # Build the next day's script at 10am
        self.parent.home.timed_event_queue.add_event(VacationBuildEvent(next_build_time, self.parent))

class VacationLightEvent(TimedEvent):
    def __init__(self, event_time, home, scene_off, scene_on):
        TimedEvent.__init__(self, event_time)
        self.home = home
        self.scene_off = scene_off
        self.scene_on = scene_on

    def execute(self):
        if self.scene_off is not None:
            logger.info("Vacation turning off {0}".format(self.scene_off.names[0]))
            self.scene_off.off(self.home.lights)
        if self.scene_on is not None:
            logger.info("Vacation turning on {0}".format(self.scene_on.names[0]))
            self.scene_on.on(self.home.lights)

class VacationMode:
    def __init__(self, home, start=timedelta(minutes=-30), end_time=time(23, 0, 0), interval=timedelta(minutes=30)):
        self.start = start          # Can be either a timedelta or a datetime.time
        self.end_time = end_time
        self.interval = interval
        self.home = home
        self.enabled = False

    # After all the services have been started this method is called.  If the persistent store shows that we are
    # in vacation mode then we probably just had a power failure.
    def init_from_persistent_store(self):
        if self.home.persistent_store.get_value('vacation_mode', default=False):
            logger.info("Enabling vacation mode because enabled in persistent store")
            self.enable()

    def enable(self, delay=timedelta(minutes=5)):
        if not self.enabled:
            logger.info("Enabling vacation mode")
            self.enabled = True
            self.home.persistent_store['vacation_mode'] = True
            self.home.timed_event_queue.add_event(VacationBuildEvent(datetime.now() + delay, self))

    def disable(self):
        if self.enabled:
            logger.info("Disabling vacation mode")
            self.enabled = False
            self.home.persistent_store['vacation_mode'] = False
            self.home.timed_event_queue.remove_events(VacationBuildEvent)
            self.home.timed_event_queue.remove_events(VacationLightEvent)

    def create_scene_script(self, date):
        if isinstance(self.start, timedelta):
            a = Astral()
            start_time = (a['seattle'].sun(date=date, local=True)['sunset'] + self.start).time()
        else:
            start_time = self.start
        last_on = None
        events = []
        start_datetime = datetime.combine(date, start_time)
        end_datetime = datetime.combine(date, self.end_time)
        while start_datetime < end_datetime:
            next_on = random.choice(VACATION_SCENES.all_scenes)
            if next_on == last_on:
                next_on = None      # If we randomly choose the same scene twice in a row, don't turn anything on
            events.append(VacationLightEvent(start_datetime, self.home, last_on, next_on))
            last_on = next_on
            start_datetime += self.interval
        # always turn off the last_on light at the end of the script
        events.append(VacationLightEvent(start_datetime, self.home, last_on, None))
        return events


import torch

def eval_model(model, loader, device):
    with torch.no_grad():
        test_accuracy = []
        for input, target in loader:
            input, target = input.to(device), target.to(device)

            output = model(input)
            batch_accuracy = (output.argmax(dim=1) == target).float()

            test_accuracy.append(batch_accuracy)

        return torch.cat(test_accuracy, 0).mean().item()


"""
PCBA dataset loader.
"""
import os
import logging
import deepchem
import gzip

logger = logging.getLogger(__name__)

DEFAULT_DIR = deepchem.utils.data_utils.get_data_dir()

def load_pcba(featurizer='ECFP',
              split='random',
              reload=True,
              data_dir=None,
              save_dir=None,
              **kwargs):
  return load_pcba_dataset(
      featurizer=featurizer,
      split=split,
      reload=reload,
      assay_file_name="pcba.csv.gz",
      data_dir=data_dir,
      save_dir=save_dir,
      **kwargs)

def load_pcba_146(featurizer='ECFP',
                  split='random',
                  reload=True,
                  data_dir=None,
                  save_dir=None,
                  **kwargs):
  return load_pcba_dataset(
      featurizer=featurizer,
      split=split,
      reload=reload,
      assay_file_name="pcba_146.csv.gz",
      data_dir=data_dir,
      save_dir=save_dir,
      **kwargs)

def load_pcba_2475(featurizer='ECFP',
                   split='random',
                   reload=True,
                   data_dir=None,
                   save_dir=None,
                   **kwargs):
  return load_pcba_dataset(
      featurizer=featurizer,
      split=split,
      reload=reload,
      assay_file_name="pcba_2475.csv.gz",
      data_dir=data_dir,
      save_dir=save_dir,
      **kwargs)

def load_pcba_dataset(featurizer='ECFP',
                      split='random',
                      reload=True,
                      assay_file_name="pcba.csv.gz",
                      data_dir=None,
                      save_dir=None,
                      **kwargs):
  """Load PCBA dataset

  PubChem BioAssay (PCBA) is a database consisting of biological activities of
  small molecules generated by high-throughput screening. We use a subset of
  PCBA, containing 128 bioassays measured over 400 thousand compounds,
  used by previous work to benchmark machine learning methods.

  Random splitting is recommended for this dataset.

  The raw data csv file contains columns below:

  - "mol_id" - PubChem CID of the compound
  - "smiles" - SMILES representation of the molecular structure
  - "PCBA-XXX" - Measured results (Active/Inactive) for bioassays:
        search for the assay ID at
        https://pubchem.ncbi.nlm.nih.gov/search/#collection=bioassays
        for details

  References
  ----------
  .. [1] Wang, Yanli, et al. "PubChem's BioAssay database."
     Nucleic acids research 40.D1 (2011): D400-D412.
  """
  if data_dir is None:
    data_dir = DEFAULT_DIR
  if save_dir is None:
    save_dir = DEFAULT_DIR

  if reload:
    save_folder = os.path.join(save_dir,
                               assay_file_name.split(".")[0] + "-featurized",
                               featurizer)
    if featurizer == "smiles2img":
      img_spec = kwargs.get("img_spec", "std")
      save_folder = os.path.join(save_folder, img_spec)
    save_folder = os.path.join(save_folder, str(split))

  dataset_file = os.path.join(data_dir, assay_file_name)

  if not os.path.exists(dataset_file):
    deepchem.utils.data_utils.download_url(
        url="https://deepchemdata.s3-us-west-1.amazonaws.com/datasets/{0}".
        format(assay_file_name),
        dest_dir=data_dir)

  # Featurize PCBA dataset
  logger.info("About to featurize PCBA dataset.")
  if featurizer == 'ECFP':
    featurizer = deepchem.feat.CircularFingerprint(size=1024)
  elif featurizer == 'GraphConv':
    featurizer = deepchem.feat.ConvMolFeaturizer()
  elif featurizer == 'Weave':
    featurizer = deepchem.feat.WeaveFeaturizer()
  elif featurizer == 'Raw':
    featurizer = deepchem.feat.RawFeaturizer()
  elif featurizer == "smiles2img":
    img_spec = kwargs.get("img_spec", "std")
    img_size = kwargs.get("img_size", 80)
    featurizer = deepchem.feat.SmilesToImage(
        img_size=img_size, img_spec=img_spec)

  with gzip.GzipFile(dataset_file, "r") as fin:
    header = fin.readline().rstrip().decode("utf-8")
    columns = header.split(",")
    columns.remove("mol_id")
    columns.remove("smiles")
    PCBA_tasks = columns

  if reload:
    loaded, all_dataset, transformers = deepchem.utils.data_utils.load_dataset_from_disk(
        save_folder)
    if loaded:
      return PCBA_tasks, all_dataset, transformers

  loader = deepchem.data.CSVLoader(
      tasks=PCBA_tasks, smiles_field="smiles", featurizer=featurizer)

  dataset = loader.featurize(dataset_file)

  if split == None:
    transformers = [deepchem.trans.BalancingTransformer(dataset=dataset)]

    logger.info("Split is None, about to transform data")
    for transformer in transformers:
      dataset = transformer.transform(dataset)

    return PCBA_tasks, (dataset, None, None), transformers

  splitters = {
      'index': deepchem.splits.IndexSplitter(),
      'random': deepchem.splits.RandomSplitter(),
      'scaffold': deepchem.splits.ScaffoldSplitter(),
      'stratified': deepchem.splits.SingletaskStratifiedSplitter()
  }
  splitter = splitters[split]
  logger.info("About to split dataset using {} splitter.".format(split))
  frac_train = kwargs.get("frac_train", 0.8)
  frac_valid = kwargs.get('frac_valid', 0.1)
  frac_test = kwargs.get('frac_test', 0.1)

  train, valid, test = splitter.train_valid_test_split(
      dataset,
      frac_train=frac_train,
      frac_valid=frac_valid,
      frac_test=frac_test)

  transformers = [deepchem.trans.BalancingTransformer(dataset=train)]

  logger.info("About to transform dataset.")
  for transformer in transformers:
    train = transformer.transform(train)
    valid = transformer.transform(valid)
    test = transformer.transform(test)

  if reload:
    deepchem.utils.data_utils.save_dataset_to_disk(save_folder, train, valid,
                                                   test, transformers)

  return PCBA_tasks, (train, valid, test), transformers


import tensorflow as tf

# Our warm-up example turned into single-process "cluster".
server = tf.train.Server.create_local_server()

greeting = tf.constant('Hello, distributed Prague!')
with tf.Session(server.target) as sess:
    result = sess.run(greeting)
    print(result)

# We can also use the same cluster configuration with other sessions.
a = tf.placeholder(tf.int16)
b = tf.placeholder(tf.int16)
add = tf.add(a, b)
with tf.Session(server.target) as sess:
    first_result = sess.run(add, feed_dict={a: 1, b: 2})
    print(f'1 + 2 = {first_result}')
    second_result = sess.run(add, feed_dict={a: 3, b: 4})
    print(f'3 + 4 = {second_result}')


'''This module contains the collaborative filtering algorithms based on user similarity.

'''

import math
from operator import itemgetter

def user_sim_matrix(train):
    '''user_sim_matrix(dict) -> dict

    This will return the user similarity matrix. Use it when the train set is not very large.
    '''
    sim_matrix = dict()
    for p1 in train.iterkeys():
        for p2 in train.iterkeys():
            if p1 == p2:
                continue
            else:
                result = len(train[p1] & train[p2])
                sim_matrix[p1][p2] = result / math.sqrt((len(train[p1]) * len(train[p2]) * 1.0))

    return sim_matrix

def user_similarity(train):
    '''user_similarity(dict) -> dict

    This will return the user similarity matrix.
    It uses the item-users inverse table to make the computing process fast.
    '''
    sim_matrix = dict()
    item_users = dict()

    # build the item-users inverse table
    for user, prefs in train.iteritems():
        for item in prefs.iterkeys():
            if item not in item_users:
                item_users[item] = set()
            item_users[item].add(user)
    # compute the co-rated items between the users
    C = dict()
    N = dict()
    for item, users in item_users.iteritems():
        for u in users:
            N.setdefault(u, 0)
            N[u] += 1
            for v in users:
                if u == v:
                    continue
                else:
                    C.setdefault(u, {})
                    C[u].setdefault(v, 0)
                    C[u][v] += 1

    # get the sim_matrix
    for user, co_users in C.iteritems():
        sim_matrix.setdefault(user, {})
        for v, cuv in co_users.iteritems():
            sim_matrix.setdefault(v, {})
            #sim_matrix[user].setdefault(v, 0.0)
            if user not in sim_matrix[v]:
                sim_matrix[v][user] = sim_matrix[user][v] = cuv / math.sqrt(N[user] * N[v] * 1.0)

    return sim_matrix

# another implementation of the user similarity based on the popularity of the item
def user_similarity_iif(train):
    '''user_similarity_iif(dict) -> dict

    This function will return the user similarity matrix based on the popularity of the item
    which is preferd by one user and another.
    It first uses the inverse table of the item-users to make the computing process fast.
    '''
    sim_matrix = dict()
    item_users = dict()
    # build the item-users inverse table
    for user, prefs in train.iteritems():
        for item in prefs.iterkeys():
            if item not in item_users:
                item_users[item] = set()
            item_users[item].add(user)

    C = dict() # this matrix contains the intersection of every two users
    N = dict() # this matrix contains the num of items each user' preference

    for item, users in item_users.iteritems():
        # The popularity of the item
        pop = 1 / math.log(1+len(users))
        for u in users:
            C.setdefault(u, {})
            N.setdefault(u, 0)
            N[u] += 1
            for v in users:
                if u == v:
                    continue
                else:
                    C[u].setdefault(v, 0.0)
                    C[u][v] += pop

    for user, co_users in C.iteritems():
        sim_matrix.setdefault(user, {})
        for v, cuv in co_users.iteritems():
            sim_matrix.setdefault(v, {})
            if user not in sim_matrix[v]:
                sim_matrix[v][user] = sim_matrix[user][v] = cuv / math.sqrt((N[user] * N[v]*1.0))

    return sim_matrix

# recommend to user
def recommend(user, train, sim_matrix, K=30):
    '''recommend(int, dict, dict, int) -> dict

    This will return the recommendation to the user based the user's k neighbors.
    '''
    rank = dict()
    user_prefs = train[user]

    neighbors = sorted(sim_matrix[user].iteritems(), key = itemgetter(1), reverse = True)[0:K]
    for v, sim_uv in neighbors:
        for item, score in train[v].iteritems():
            if item in user_prefs:
                continue
            else:
                rank.setdefault(item, 0.0)
                rank[item] += sim_uv * score

    return rank


import os
import glob
import shutil

def main():
    with open("files.txt") as f:
        lines = f.read().splitlines()
        lines = [l.strip() for l in lines]

        for l in lines:
            print(l)

            for fl in glob.glob(os.path.expanduser(l)):
                if not os.path.isfile(fl):
                    listOfFiles = []
                    for (dirpath, dirnames, filenames) in os.walk(fl):
                        listOfFiles += [os.path.join(dirpath, fx) for fx in filenames]
                else:
                    listOfFiles = [fl]

                for n in listOfFiles:
                    copy(n)

def copy(l):
    original_file = l

    if l.startswith(os.path.expanduser('~') + "/"):
        l = "./" + l.removeprefix(os.path.expanduser('~') + "/")
    else:
        l = "fakeroot/" + l.removeprefix("/")

    l = l.strip()
    directory = os.path.dirname(l)

    if directory != ".":
        os.makedirs(directory, exist_ok=True)

    shutil.copy(original_file, directory)

main()


sentence = "I am the very model of a modern major general. something something"

fixed = ""

for index in range(len(sentence)):
    if index >= 2 \
            and fixed[index-2] == '.' \
            and fixed[index-1] == " ":
        fixed += sentence[index].upper()
    else:
        fixed += sentence[index]

print(fixed)


import numpy as np

def constructAdjM(input_file):
    '''
    Constructs adjacency matrix
    '''
    with open(input_file, "r") as inFile:
        S = inFile.readline().split()
        V, E = int(S[0]), int(S[1])

        adjM = []

        for i in range(V):
            adjM.append(V * [0])

        for _ in range(E):
            S = inFile.readline().split()
            u, v = int(S[0]) - 1, int(S[1]) - 1
            adjM[u][v] = 1

        inFile.close()

    return V, E, adjM

def constructProbTransMatrix(V, adjM, random_teleport=True, alpha=0.9):
    '''
    Constructs probability transition matrix using adjacency matrix
    '''
    P = []
    for _ in range(V):
        P.append(V * [0])

    if random_teleport:
        for i in range(V):
            connections = sum(adjM[i][:])
            if (connections == 0):
                for j in range(V):
                    P[i][j] = 1 / float(V)
            else:
                for j in range(V):
                    if adjM[i][j] == 1:
                        P[i][j] = 1 / float(connections)

        P = np.array(P)
        P = (1 - alpha) * P
        P = P + (alpha / float(V))

    else:
        for i in range(V):
            connections = sum(adjM[i][:])
            for j in range(V):
                if adjM[i][j] == 1:
                    P[i][j] = 1 / float(connections)

        P = np.array(P)

    return P

def compute_principle_left_eigen_vector(P):
    '''
    Computes principle left eigen vector using np
    Takes P matrix as input
    '''
    eigVals, eigVecs = np.linalg.eig(P)

    pi = eigVecs[:, eigVals.argmax()] # Compute with eigenvalue = 1
    norm_pi = pi / pi.sum()
    return norm_pi

def get_ranks(pi):
    """
        Prints pages in rank order
    """

    ranks = np.argsort(pi)

    for i in range(len(ranks)):
        print(f"Rank {i + 1}:= Page {ranks[len(ranks) - i - 1] + 1}")

def power_iteration(V, P, threshold=1e-9):
    """
        Computes steady state probability distribution with power iteration method
    """

    x = np.array([1.0] + (V - 1) * [0.0]).reshape(1, -1)  # (1, V)

    t = 1
    while True:
        x = np.dot(x, P)     # x(t)
        y = np.dot(x, P)     # x(t + 1)
        delta = y - x

        if delta.all() < threshold:
            break

        t += 1

    return x, t


import os
import numpy as np
import rasterio as rio
import rasterio.features
import geopandas as gpd
import rasterstats

def find_underlying_vector_value(starting_objects, starting_objects_identifying_column, objects_to_select,
                                 objects_to_select_attribute_column):
    """
    Find the value of a specified attribute of a vector layer underlying another vector layer.

    - Spatial join between input GeoDataFrames
    - Create DataFrame with only desired results columns
    - Aggregate underlying vector attribute values based on overlying vector identifying values
    - Merge aggregated results column back onto original input starting GeoDataFrame

    Parameters
    ----------
    starting_objects : GeoDataFrame
        Input object(s)
    starting_objects_identifying_column : column label
        Column name that uniquely identifies starting objects
    objects_to_select : GeoDataFrame
        Selecting objects
    objects_to_select_attribute_column : column label
        Desired attribute to find

    Returns
    -------
    GeoDataFrame
        Updated GeoDataFrame
    """
    # create a new GeoDataFrame using gpd.sjoin()
    joined = gpd.sjoin(starting_objects, objects_to_select, how='inner', lsuffix='left', rsuffix='right')
    # the joined GeoDataFrame contains all columns from both input GeoDataFrames so create a new DataFrame with only
    # the columns required for the output (the two identifying columns)
    results = joined[[starting_objects_identifying_column, objects_to_select_attribute_column]].copy()
    # aggregate the results DataFrame based on the starting objects identifying column value combining the vector
    # attribute column values with a semicolon separating them
    aggregated = results.groupby(starting_objects_identifying_column).agg(
                                                        {objects_to_select_attribute_column: '; ' .join}).reset_index()
    # merge the aggregated results columns back onto the starting objects GeoDataFrame based on the shared starting
    # object identifying column
    updated = starting_objects.merge(aggregated, on=[starting_objects_identifying_column])
    return updated  # an updated version of the input GeoDataFrame

def calculate_percentage_underlying_raster_categories_for_polygons(starting_polygons,
                                                                   starting_polygons_identifying_column,
                                                                   raster, raster_category_map, desired_column_names,
                                                                   affine, nodata=0):
    """
    Calculate percentage cover values based on underlying raster values for each polygon in a GeoDataFrame.

    - Calculate zonal statistics using rasterstats function giving pixel counts for each raster value
    - Create dictionary of results assigning zonal statistics to each polygon in polygon GeoDataFrame
    - Create dictionary of raster values and desired column names
    - Assign zonal stats results to new columns in GeoDataFrame using try...except block giving a 0 value for no cover
    - Convert pixel count values to percentages

    Parameters
    ----------
    starting_polygons : GeoDataFrame
        Input polygon(s)
    starting_polygons_identifying_column : column label
        Column name that uniquely identifies starting polygons
    raster : ndarray
        Input raster - must be categorical
    raster_category_map : dict
        Input raster category map dictionary
    desired_column_names : list of str
        Desired output column names
    affine : Affine instance
        The input raster geotransform
    nodata : int, default 0
        The nodata value for the input raster

    Returns
    -------
    GeoDataFrame
        Updated GeoDataFrame
    """
    # calculate zonal statistics using rasterstats.zonal_stats() function
    zonal_stats = rasterstats.zonal_stats(starting_polygons,  # the shapefile to use
                                          raster,  # the raster to use
                                          affine=affine,  # the geotransform for the raster
                                          categorical=True,  # this function only runs on categorised data
                                          category_map=raster_category_map,  # the raster category map dictionary
                                          nodata=nodata  # the nodata value for the raster
                                          )

    # create a dictionary with the zonal results added to each polygon in the input GeoDataFrame
    polygons_dict = dict()
    for ind, row in starting_polygons.iterrows():
        polygons_dict[row[starting_polygons_identifying_column]] = zonal_stats[ind]

    # use dict and zip with the category names to create a dictionary of category names and the names for the results
    # columns
    column_dict = dict(zip(raster_category_map.values(), desired_column_names))

    # add rasterstats results to columns in GeoDataFrame
    for ind, row in starting_polygons.iterrows():  # use iterrows to iterate over each row in the GeoDataFrame
        results_data = polygons_dict[row[starting_polygons_identifying_column]]  # get the category data for row/polygon
        for category in raster_category_map.values():  # iterate over each of the category class names
            # try...except block giving a 0 value for no cover and assigning value if there is cover
            try:
                # add the category count to a new column
                starting_polygons.loc[ind, column_dict[category]] = results_data[category]
            except KeyError:
                # if category name is not present, value should be 0
                starting_polygons.loc[ind, column_dict[category]] = 0

    # convert the counts into percentages
    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # multiply the pixel count values by 100 and divide by the sum of all cover column values
        starting_polygons.loc[ind, desired_column_names] = 100 * row[desired_column_names] / row[
                                                                                desired_column_names].sum()
    return starting_polygons  # an updated version of the input GeoDataFrame

def calculate_stat_values_underlying_raster_for_polygons(starting_polygons,
                                                         starting_polygons_identifying_column_integer,
                                                         desired_column_names, raster, affine, fill_value=0,
                                                         starting_polygons_geometry_column='geometry'):
    """
    Calculate statistics values of underlying raster for each polygon in a GeoDataFrame.

    - Create list of geometry, value pairs for polygons in GeoDataFrame
    - Rasterize vector polygons using rasterio in order to create masks for each polygon extent
    - Calculate statistics of underlying raster using masks by iterating over each polygon in GeoDataFrame
    - Add values to input polygon GeoDataFrame by creating new columns with desired column names

    Parameters
    ----------
    starting_polygons : GeoDataFrame
        Input polygon(s)
    starting_polygons_identifying_column_integer : column label
        Column name that uniquely identifies starting polygons - values in column must be of type integer and must not
        contain values equal to the fill value used with the vector geometries below
    desired_column_names : dict
        Dictionary of desired output column names - dictionary must have keys as below
                    {'mean': 'desired column name',
                    'min': 'desired column name',
                    'max': 'desired column name',
                    'range': 'desired column name',
                    'median': 'desired column name',
                    'std': 'desired column name'}
    raster : ndarray
        Input raster
    affine : Affine instance
        The input raster geotransform
    fill_value : int, default 0
        The value to use for areas not covered by the polygon geometries
    starting_polygons_geometry_column : column label, default 'geometry'
        Column name of geometry column in polygon GeoDataFrame

    Returns
    -------
    GeoDataFrame
        Updated GeoDataFrame
    """
    # get a list of geometry, value pairs
    shapes = list(zip(starting_polygons[starting_polygons_geometry_column],
                      starting_polygons[starting_polygons_identifying_column_integer]))

    # create a raster based on the vector polygons
    site_mask = rio.features.rasterize(shapes=shapes,  # the list of geometry/value pairs
                                       fill=fill_value,  # the value to use for cells not covered by any geometry
                                       out_shape=raster.shape,  # the shape of the new raster
                                       transform=affine)  # the geotransform of the new raster

    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # calculate mean value using mask and assign to column using desired column name from column name dictionary
        starting_polygons.loc[ind, desired_column_names['mean']] = np.nanmean(
            raster[site_mask == row[starting_polygons_identifying_column_integer]])
    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # calculate min value using mask and assign to column using desired column name from column name dictionary
        starting_polygons.loc[ind, desired_column_names['min']] = np.nanmin(
            raster[site_mask == row[starting_polygons_identifying_column_integer]])
    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # calculate max value using mask and assign to column using desired column name from column name dictionary
        starting_polygons.loc[ind, desired_column_names['max']] = np.nanmax(
            raster[site_mask == row[starting_polygons_identifying_column_integer]])
    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # calculate range value by finding max and min values and subtracting them using mask and assign to column using
        # desired column name from column name dictionary
        starting_polygons.loc[ind, desired_column_names['range']] = (np.nanmax(
            raster[site_mask == row[starting_polygons_identifying_column_integer]]) - np.nanmin(
            raster[site_mask == row[starting_polygons_identifying_column_integer]]))
    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # calculate median value using mask and assign to column using desired column name from column name dictionary
        starting_polygons.loc[ind, desired_column_names['median']] = np.nanmedian(
            raster[site_mask == row[starting_polygons_identifying_column_integer]])
    for ind, row in starting_polygons.iterrows():  # iterate over each row in the GeoDataFrame
        # calculate standard deviation value using mask and assign to column using desired column name from column name
        # dictionary
        starting_polygons.loc[ind, desired_column_names['std']] = np.nanstd(
            raster[site_mask == row[starting_polygons_identifying_column_integer]])
    return starting_polygons  # an updated version of the input GeoDataFrame

# load the input shapefile datasets from the data_files folder using gpd.read_file(os.path.abspath())
sites = gpd.read_file(os.path.abspath('data_files/Site_Locations.shp'))
counties = gpd.read_file(os.path.abspath('data_files/Counties.shp'))
LGDs = gpd.read_file(os.path.abspath('data_files/Local_Government_Districts.shp'))

# transform data files to Northern Ireland (NI) Universal Transverse Mercator zone (UTM(29) which has an epsg of 32629)
# which will give measurements in metres using gdf.to_crs() - see here for a list of EPSG codes: https://epsg.io/
# transform all input data_files to ensure all data is on the same reference system using inplace=true as we want to
# transform the datasets here and not create new ones
sites.to_crs(epsg=32629, inplace=True)
counties.to_crs(epsg=32629, inplace=True)
LGDs.to_crs(epsg=32629, inplace=True)

# find the county each site is situated within
# we want to improve the display of the county names in the output by ensuring the names are no longer in all capitals
# and by adding the characters 'County ' to the start of each county name string
for ind, row in counties.iterrows():  # iterate over each row in the GeoDataFrame
    # assign the row's CountyName to a new column called County after converting the values out of uppercase and adding
    # the 'County ' characters to the start of the string
    counties.loc[ind, 'County'] = 'County '+row['CountyName'].title()
# find the underlying county using find_underlying_vector_value() function previously defined and assigning its name to
# a new column called County
sites = find_underlying_vector_value(sites, 'Name', counties, 'County')

# find the Local Government District (LGD) each site is situated within
# we want to improve the display of the LGD name column label in the output by renaming the LGDNAME column to LGD
LGDs = LGDs.rename(columns={'LGDNAME': 'LGD'})
# find the underlying LGD using find_underlying_vector_value() function previously defined and assigning its name to
# a new column called LGD
sites = find_underlying_vector_value(sites, 'Name', LGDs, 'LGD')

# calculate the areas of each site
for ind, row in sites.iterrows():  # iterate over each row in the GeoDataFrame
    # calculate the area of the polygon and assign it to a new column called Area(km2)
    sites.loc[ind, 'Area(km2)'] = row['geometry'].area
# divide the area by 1000000 to convert from metres squared to kilometres squared and round to 2 decimal places
sites['Area(km2)'] = (sites['Area(km2)']/1000000).round(2)

# calculate the perimeter of each site
for ind, row in sites.iterrows():  # iterate over each row in the GeoDataFrame
    # calculate the perimeter of the polygon and assign it to a new column called Perimeter(km)
    sites.loc[ind, 'Perimeter(km)'] = row['geometry'].length
# divide the length by 1000 to convert from metres to kilometres and round to 2 decimal places
sites['Perimeter(km)'] = (sites['Perimeter(km)']/1000).round(2)

# calculate the percentage landcover for each site using the
# calculate_percentage_underlying_raster_categories_for_polygons() function previously defined
# open the landcover raster and read the data - we will use with rio.open() here to read the data and ensure the file
# is then closed
with rio.open('data_files/Landcover.tif') as dataset:
    lc_crs = dataset.crs  # the raster crs
    landcover = dataset.read(1)  # the band the data values are stored in that we want to read (band 1)
    lc_affine_tfm = dataset.transform  # the raster geotransform

# we need to ensure the vector layer is in the same crs as the raster before performing the next step
sites.to_crs(lc_crs, inplace=True)

# to find the percentage landcover for each site we first need to define a landcover category map dictionary which
# maps the raster values to the landcover categories
landcover_names = {1: 'Broadleaf woodland',
                   2: 'Coniferous woodland',
                   3: 'Arable',
                   4: 'Improved grassland',
                   5: 'Semi-natural grassland',
                   6: 'Mountain, heath, bog',
                   7: 'Saltwater',
                   8: 'Freshwater',
                   9: 'Coastal',
                   10: 'Built-up areas and gardens'}

# we also need to define a desired column names list (in the same order as the above raster category map)
lc_short_names = ['%Broadleaf',
                  '%Coniferous',
                  '%Arable',
                  '%Imp_grass',
                  '%Nat_grass',
                  '%Mountain',
                  '%Saltwater',
                  '%Freshwater',
                  '%Coastal',
                  '%Built_up']

# calculate the percentage landcover using the calculate_percentage_underlying_raster_categories_for_polygons()
# function previously defined
calculate_percentage_underlying_raster_categories_for_polygons(sites, 'Name', landcover, landcover_names,
                                                               lc_short_names, lc_affine_tfm)

# calculate the percentage underlying superficial geology for each site using the
# calculate_percentage_underlying_raster_categories_for_polygons() function previously defined
# open the geology raster and read the data - we will use with rio.open() here to read the data and ensure the file
# is then closed
with rio.open('data_files/Superficial_Geology.tif') as dataset:
    geol_crs = dataset.crs  # the raster crs
    geology = dataset.read(1)  # the band the data values are stored in that we want to read (band 1)
    geol_affine_tfm = dataset.transform  # the raster geotransform

# we need to ensure the vector layer is in the same crs as the raster before performing the next step
sites.to_crs(geol_crs, inplace=True)

# to find the percentage underlying geology for each site we first need to define a geology category map dictionary
# which maps the raster values to the geology categories
geology_names = {1: 'Alluvium - Sand and Silt',
                 2: 'Glaciolacustrine Deposits - Silt and Clay',
                 3: 'Blown Sand',
                 4: 'Diatomite',
                 5: 'Glaciofluvial Sheet Deposits - Sand, Silt and Clay',
                 6: 'Glacial Sand and Gravel',
                 7: 'Lacustrine Alluvium - Clay, Silt and Sand',
                 8: 'Peat',
                 9: 'Raised Beach Deposits - Gravel, Sand and Silt',
                 10: 'Raised Marine Deposits - Clay, Silt and Sand',
                 11: 'Landslide Deposits - Unknown/Unclassified',
                 12: 'Till - Diamicton'}

# we also need to define a desired column names list (in the same order as the above raster category map)
geol_short_names = ['%Alluv_sand_silt',
                    '%Glaciolac_silt_clay',
                    '%Blown_sand',
                    '%Diatomite',
                    '%Glaciofulv_sand_silt_clay',
                    '%Glacial_sand_gravel',
                    '%Lac_alluv_clay_silt_sand',
                    '%Peat',
                    '%Raised_beach_gravel_sand_silt',
                    '%Raised_marine_clay_silt_sand',
                    '%Landslide_unknown',
                    '%Till_diamicton']

# calculate the percentage underlying geology using the calculate_percentage_underlying_raster_categories_for_polygons()
# function previously defined
calculate_percentage_underlying_raster_categories_for_polygons(sites, 'Name', geology, geology_names, geol_short_names,
                                                               geol_affine_tfm)

# before running the calculate_stat_values_underlying_raster_for_polygons() function previously defined we need to
# ensure we have an integer column that uniquely identifies each polygon in the GeoDataFrame that does not contain a
# value that is the same as the value we will use as our fill value (0)
# create an integer identifier column for the raster analysis called ID_RA which starts with 1 and increments by 1 for
# each row until the end of the sites GeoDataFrame
sites['ID_RA'] = range(1, 1+len(sites))

# calculate wind speeed statistics for each site
# open the wind speed raster and read the data - we will use with rio.open() here to read the data and ensure the file
# is then closed
with rio.open('data_files/Wind_Speed.tif') as dataset:
    ws_crs = dataset.crs  # the raster crs
    wind_speed = dataset.read(1)  # the band the data values are stored in that we want to read (band 1)
    ws_affine_tfm = dataset.transform  # the raster geotransform

# we need to ensure the vector layer is in the same crs as the raster before performing the next step
sites.to_crs(ws_crs, inplace=True)

# before running the function we need to create a dictionary of desired column names for the statistics
wind_speed_stat_columns_dict = {'mean': 'MeanWindSpeed(m/s)',
                                'min': 'MinWindSpeed(m/s)',
                                'max': 'MaxWindSpeed(m/s)',
                                'range': 'WindSpeedRange(m/s)',
                                'median': 'MedianWindSpeed(m/s)',
                                'std': 'WindSpeedStdDev'}

# calculate statistics for the wind speed raster for each site using
# calculate_stat_values_underlying_raster_for_polygons() function previously defined
calculate_stat_values_underlying_raster_for_polygons(sites, 'ID_RA', wind_speed_stat_columns_dict, wind_speed,
                                                     ws_affine_tfm, 0, 'geometry')

# calculate wind power density statistics for each site
# open the wind power density raster and read the data - we will use with rio.open() here to read the data and ensure
# the file is then closed
with rio.open('data_files/Wind_Power_Density.tif') as dataset:
    wpd_crs = dataset.crs  # the raster crs
    wind_power_density = dataset.read(1)  # the band the data values are stored in that we want to read (band 1)
    wpd_affine_tfm = dataset.transform  # the raster geotransform

# we need to ensure the vector layer is in the same crs as the raster before performing the next step
sites.to_crs(wpd_crs, inplace=True)

# before running the function we need to create a dictionary of desired column names for the statistics
wind_power_density_stat_columns_dict = {'mean': 'MeanWindPowerDensity(W/m2)',
                                        'min': 'MinWindPowerDensity(W/m2)',
                                        'max': 'MaxWindPowerDensity(W/m2)',
                                        'range': 'WindPowerDensityRange(W/m2)',
                                        'median': 'MedianWindPowerDensity(W/m2)',
                                        'std': 'WindPowerDensityStdDev'}

# calculate statistics for the wind power density raster for each site using
# calculate_stat_values_underlying_raster_for_polygons() function previously defined
calculate_stat_values_underlying_raster_for_polygons(sites, 'ID_RA', wind_power_density_stat_columns_dict,
                                                     wind_power_density, wpd_affine_tfm, 0, 'geometry')

# calculate elevation statistics for each site
# open the elevation raster and read the data - we will use with rio.open() here to read the data and ensure the file
# is then closed
with rio.open('data_files/DEM.tif') as dataset:
    elev_crs = dataset.crs  # the raster crs
    elevation = dataset.read(1)  # the band the data values are stored in that we want to read (band 1)
    elev_affine_tfm = dataset.transform  # the raster geotransform

# we need to ensure the vector layer is in the same crs as the raster before performing the next step
sites.to_crs(elev_crs, inplace=True)

# before running the function we need to create a dictionary of desired column names for the statistics
elevation_stat_columns_dict = {'mean': 'MeanElevation(m)',
                               'min': 'MinElevation(m)',
                               'max': 'MaxElevation(m)',
                               'range': 'ElevationRange(m)',
                               'median': 'MedianElevation(m)',
                               'std': 'ElevationStdDev'}

# calculate statistics for the elevation raster for each site using
# calculate_stat_values_underlying_raster_for_polygons() function previously defined
calculate_stat_values_underlying_raster_for_polygons(sites, 'ID_RA', elevation_stat_columns_dict, elevation,
                                                     elev_affine_tfm, 0, 'geometry')

# for clarity and so that we can join the site characteristics data with the proximity data we will rename the Name
# column for the sites to Site Name
sites = sites.rename(columns={'Name': 'Site Name'})

# now to save the results - firstly, create a DataFrame to export to CSV by copying only desired columns from
# GeoDataFrame that contains results by dropping unnecessary columns (the geometry column as this is not needed in the
# csv results and the ID_RA column as this was only created for functions in the script and is not needed in the CSV
# results)
site_results = sites.drop(columns=['geometry', 'ID_RA']).copy()

# now that the results are in a DataFrame as opposed to a GeoDataFrame we can round all results to 2 decimal places,
# this step could not be undertaken on the GeoDataFame as geometry cannot be rounded
site_results = site_results.round(2)

# save the results DataFrame as a CSV called Proximity_analysis.csv to the output_files folder with the index removed
site_results.to_csv('output_files/Site_characteristics.csv', index=False)


from __future__ import absolute_import, division, print_function

import os
import sys
import glob
import argparse
import numpy as np
import PIL.Image as pil
import PIL.ImageOps
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.pyplot as plt

from skimage.segmentation import mark_boundaries
from scipy.optimize import linear_sum_assignment

import torch
import torch.nn.functional as F
from torchvision import transforms, datasets

import networks
from layers import disp_to_depth
from utils import download_model_if_doesnt_exist
#from fullcrf import fullcrf

#labels = ['unlabeled','ego vehicle','rectification border','out of roi','static','dynamic','ground','road','sidewalk','parking','rail track',
#    'building','wall','fence','guard rail','bridge','tunnel','pole','polegroup','traffic light','traffic sign','vegetation','terrain',
#    'sky','person','rider','car','truck','bus','caravan','trailer','train','motorcycle','bicycle','license plate']

labels = ['road','sidewalk','building','wall','fence','pole','traffic light','traffic sign','vegetation','terrain',
    'sky','person','rider','car','truck','bus','train','motorcycle','bicycle']

eval_cls = [7,8,11,12,13,17,19,20,21,22,23,24,25,26,27,28,31,32,33]
void_cls = [0, 1, 2, 3, 4, 5, 6, 9, 10, 14, 15, 16, 18, 29, 30, -1]

class_map = dict(zip(eval_cls, range(len(eval_cls))))
seg_class_map = dict(zip(range(len(eval_cls)), range(len(eval_cls))))

color_seg = [[128, 64, 128],[244, 35, 232],[70, 70, 70],[102, 102, 156],[190, 153, 153],
        [153, 153, 153],[250, 170, 30],[220, 220, 0],[107, 142, 35],[152, 251, 152],
        [0, 130, 180],[220, 20, 60],[255, 0, 0],[0, 0, 142],[0, 0, 70],[0, 60, 100],
        [0, 80, 100],[0, 0, 230],[119, 11, 32]]
color_seg = np.array(color_seg).astype(np.uint8)

def load_data(config):

    inputs = []
    gts = []

    output_dirs = {"input":[],"seg":[],"depth":[]}

    input_paths = sorted(glob.glob(os.path.join(config.input_path, '*.png')))[1::2]
    if config.gt_path != None:
        gt_paths = sorted(glob.glob(os.path.join(config.gt_path, '*.png')))[1::2]
    else:
        gt_paths = []

    model_name = config.model_name
    output_dir_base = os.path.join(config.output_dir, model_name)
    if not os.path.exists(output_dir_base):
        os.makedirs(output_dir_base)

    print("-> Predicting on {:d} eval images".format(len(input_paths)))

    print("-> {:d} gt images".format(len(gt_paths)))

    for image_path in input_paths:
        image = pil.open(image_path).convert('RGB')
        inputs.append(image)

        output_name = os.path.splitext(os.path.basename(image_path))[0]
        output_dir_input = os.path.join(output_dir_base, "{}_input.png".format(output_name))
        output_dir_seg = os.path.join(output_dir_base, "{}_seg.png".format(output_name))
        output_dir_depth = os.path.join(output_dir_base, "{}_zepth.png".format(output_name))
        output_dirs["input"].append(output_dir_input)
        output_dirs["seg"].append(output_dir_seg)
        output_dirs["depth"].append(output_dir_depth)

    for image_path in gt_paths:
        image = pil.open(image_path)
        original_width, original_height = image.size
        gt = np.array(image,dtype=np.uint8)
        for c in void_cls:
            gt[gt==c] = 255
        for c in eval_cls:
            gt[gt==c] = class_map[c]
        gts.append(gt)

    return inputs, gts, output_dirs

def predict_seg(models, inputs, output_dirs, config):
    """Function to predict for a single image or folder of images
    """

    for key, model in models.items():
        model.eval()
        model.to('cuda')

    segs = []

    with torch.no_grad():

        for i, image in enumerate(inputs):

            original_width, original_height = image.size
            image.save(output_dirs["input"][i])
            # Load image and preprocess

            input_image = image.resize((config.width, config.height), pil.LANCZOS)
            input_image = transforms.ToTensor()(input_image).unsqueeze(0)

            # PREDICTION
            input_image = input_image.to('cuda')

            if config.architecture == "share":
                seg_features = models["encoder"](input_image)
                seg = models["seg"](seg_features)[("output", 0)]
                depth = models["depth"](seg_features)[("output", 0)]

            if config.architecture == "byol":
                features = models["encoder"](input_image)
                representation = models["decoder"](features)
                representation = F.normalize(representation, dim=1, p=2)
                seg = F.softmax(models["head"](representation.detach(), features)[("output", 0)],dim=1)
                depth = None

            seg = torch.nn.functional.interpolate(
                seg, (original_height, original_width), mode="bilinear", align_corners=False)

            seg = seg.squeeze()
            seg = torch.argmax(seg, dim=0).cpu().numpy()

            segs.append(seg)

            if depth != None:
                disp_resized = torch.nn.functional.interpolate(depth, (original_height, original_width), mode="bilinear", align_corners=False)
                disp_resized_np = disp_resized.squeeze().cpu().numpy()
                vmax = np.percentile(disp_resized_np, 95)
                normalizer = mpl.colors.Normalize(vmin=disp_resized_np.min(), vmax=vmax)
                mapper = cm.ScalarMappable(norm=normalizer, cmap='magma')
                colormapped_im = (mapper.to_rgba(disp_resized_np)[:, :, :3] * 255).astype(np.uint8)
                im = pil.fromarray(colormapped_im)
                im.save(output_dirs["depth"][i])

    return segs

def compute_metrics(segs, gts, output_dirs, h_match = False):
    num_cls = len(eval_cls)
    intersection = np.zeros((num_cls, num_cls))
    for seg, gt in zip(segs, gts):
        mask = (gt >= 0) & (gt < num_cls)
        hist = np.bincount(
            num_cls * seg[mask] + gt[mask], minlength=num_cls ** 2
        ).reshape(num_cls, num_cls)
        intersection += hist
    i = j = range(num_cls)
    if h_match:
        union = -intersection + intersection.sum(axis=1,keepdims=True) + intersection.sum(axis=0,keepdims=True)
        cost = -intersection/union
        cost[np.isnan(cost)] = -1
        i, j = linear_sum_assignment(cost)

    hist = intersection
    print(j)

    acc = hist[i,j].sum() / hist.sum()
    acc_cls = hist[i,j] / hist.sum(axis=0)[j]
    acc_cls = np.nanmean(acc_cls)
    iu = hist[i,j] / (hist.sum(axis=1) + hist.sum(axis=0)[j] - hist[i,j])
    mean_iu = np.nanmean(iu)
    freq = hist.sum(axis=0)[j] / hist.sum()
    fwavacc = (freq[freq > 0] * iu[freq > 0]).sum()
    gt_labels = [labels[index] for index in j]
    cls_iu = dict(zip(gt_labels, iu))

    metrics = {
            "Overall Acc": acc,
            "Mean Acc": acc_cls,
            "FreqW Acc": fwavacc,
            "Mean IoU": mean_iu
        }
    metrics.update(cls_iu)

    for s, seg in enumerate(segs):
        seg_img = color_seg[j][seg]
        seg_img = pil.fromarray(seg_img)
        seg_img.save(output_dirs["seg"][s])

    return metrics

def build_models(config):
    models = {}
    if config.architecture == "share":
        models["encoder"] = networks.ResnetEncoder(
            num_layers = config.ResX,
            pretrained = True)
        models["seg"] = networks.Decoder(
            out_channels = config.cls_num,
            scales = config.seg_scales,
            activate = 'softmax',
            in_channels = models["encoder"].num_ch_enc)
        models["depth"] = networks.Decoder(
            out_channels = 1,
            scales = config.seg_scales,
            activate = 'sigmoid',
            in_channels = models["encoder"].num_ch_enc)

        models_to_load = ["encoder","seg","depth"]

    if config.architecture == "byol":
        models["encoder"] = networks.ResnetEncoder(
            num_layers = config.ResX,
            pretrained = False)
        models["decoder"] = networks.Decoder_BYOL(
            in_channels = models["encoder"].num_ch_enc)
        models["head"] = networks.FullHead(
            out_channels=19,
            activate = 'softmax',
        in_channels=models["encoder"].num_ch_enc)
        models_to_load = ["encoder","decoder","head"]

    config.load_weights_folder = os.path.expanduser(config.load_weights_folder)
    assert os.path.isdir(config.load_weights_folder), \
        "Cannot find folder {}".format(config.load_weights_folder)
    print("loading model from folder {}".format(config.load_weights_folder))

    for n in models_to_load:
        print("Loading {} weights...".format(n))
        path = os.path.join(config.load_weights_folder, "{}.pth".format(n))
        model_dict = models[n].state_dict()
        pretrained_dict = torch.load(path)
        pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
        model_dict.update(pretrained_dict)
        models[n].load_state_dict(model_dict)

    return models

def model_eval(config, models = None):
    if models == None:
        models = build_models(config)
    inputs, gts, output_dirs = load_data(config)
    segs = predict_seg(models, inputs, output_dirs, config)
    metrics = compute_metrics(segs, gts, output_dirs, config.h_match)

    return metrics


import tkinter as tk
from tkinter import filedialog

from module.logger import write_log

def select_folder() -> str:
	"""エクスプローラー画面でフォルダ選択"""

	root = tk.Tk()
	root.withdraw()
	folder_path = filedialog.askdirectory()
	write_log('select_folder path:' + folder_path)
	return folder_path

def select_json_file() -> str:
	"""エクスプローラー画面でjsonファイル選択"""

	root = tk.Tk()
	root.withdraw()
	# ファイル選択ダイアログの表示
	file_path = filedialog.askopenfilename(initialdir="./", title="Select JSON file", filetypes=(("JSON files", "*.json"),))
	write_log('select_file path:' + file_path)
	return file_path


from Button import Button
from Globals import Steering

class AIButton(Button):
    isPlayingwithAI = False
    text1 = "AI"
    text2 = "1v1"

    def __init__(self,text,x,y,width,height, paddle):
        Button.__init__(self,text,x,y,width,height)
        self.paddle = paddle

    def AI(self):
        self.isPlayingwithAI = True
        self.text = self.text2
        self.paddle.steering = Steering.AI

    def onClick(self):
        if not self.isPlayingwithAI:
            self.AI()
        else:
            self.normal()

    def normal(self):
        self.isPlayingwithAI = False
        self.text = self.text1
        self.paddle.steering = Steering.Mouse


'''
Universidad del Valle de Guatemala
Redes - 2021
DVR.py

Roberto Figueroa 18306
Luis Quezada 18028
Esteban del Valle 18221
'''

from slixmpp.basexmpp import BaseXMPP
from node import Node

from asyncio import sleep
from aioconsole import aprint
from time import time
from xml.etree import ElementTree as ET
import json
import asyncio
import numpy as np
from scipy.sparse.csgraph import shortest_path

"""
---------
|   A   |
|  Sec. |
|  Age  |
---------
| B | 0.3 |
| E | 0.5 |
---------
"""

EXPIRATION = 5

class DVR(Node):

    def __init__(self, jid, password, entity, asoc_nodes = None, t_keys = None):
        super().__init__(jid, password)
        self.DVR_seqnum = 0
        self.DVR = {}
        self.entity = entity
        self.basexmpp = BaseXMPP()
        self.neighbors = asoc_nodes #should be a dict
        self.neighbors_niknames = self.neighbors.keys() if self.neighbors != None else []

        self.topo = []
        self.all_nodes = [self.entity]
        self.ady_matrix = []
        self.prev_matrix = []
        self.build_topo_package()

        # ---------
        self.topo_vector = t_keys.sort()

    def send_hello(self, hto, hfrom):
        """
        Function for neighbor discovery
        """
        self.send_message(hto,
            "<hello>",
            mfrom=hfrom)
        print("Sending hello to neighbor ...")

    def eco(self, eco_to, eco_from):
        """
        Function for measure cost between neighbors
        """
        # print("Sending eco to {}".format(eco_to))
        self.send_message(
            mto=eco_to,
            mbody="<eco time='%f' ></eco>" % time(),
            mfrom=eco_from
        )

    def build_topo_package(self):
        """
        Function for package build about the network
        destination | dist | next hop
        """
        for i in self.topo_keys:
            if i == self.entity:
                self.topo.append((i , 0, None))
            self.topo.append((i , float('inf'), None))

    def update_topo_package(self, node, weight):
        """
        Function for package weights update+
        """

        for i in self.topo:
            if i[0] == node:
                i[1] = weight

    def send_topo_package(self, to):
        """
        Send the topo package to neighbors
        """
        dvr_json = json.dumps(self.topo)
        self.send_message(to,
            "<pack dvr='%s' from='%s'></pack>" % (dvr_json, self.entity),
            mfrom=self.boundjid,
        )

    def recieve_topo_package(self, nfrom, topo_package):
        """
        Recieve topo package from a neighbor,
        this function must process the timestamp and
        the sequence number in order to drop or send
        package
        """
        return "This should be a message stanza"

    def shortest_path(self):
        """
        Must be a Bellman-Ford algorithm implementation
        """
        path = []
        return path.reverse()

    async def update_tables(self):
        while True:
            for router in self.neighbors_niknames:
                self.eco(self.neighbors[router], self.boundjid)

            await asyncio.sleep(5)
            # print("Sending packages to neighbors ... ")
            for router in self.neighbors_niknames:
                self.send_topo_package(self.neighbors[router])

    def get_nickname(self, jid):
        key_list = list(self.neighbors.keys())
        val_list = list(self.neighbors.values())

        return key_list[val_list.index(jid)]

    def init_listener(self):
        self.loop.create_task(self.update_tables())

    def flood(self, to, package):

        self.send_message(to,
            "<pack dvr='%s'></pack>" % package,
            mfrom=self.boundjid,
        )

    def save_prev_matrix(self):
    	self.prev_matrix = self.ady_matrix

    def update_ady_matrix(self):
        self.save_prev_matrix()
        length = len(self.all_nodes)
        self.ady_matrix = np.zeros((length, length),dtype=np.float16)
        for row_node in self.all_nodes:
            for col_node in self.topo[row_node]['weights'].keys():
                row = self.all_nodes.index(row_node)
                if col_node in self.all_nodes:
                    col = self.all_nodes.index(col_node)
                else:
                    return
                self.ady_matrix[row][col] = self.topo[row_node]['weights'][col_node]

        # compare tables, update if diff with Bellman Ford
        optimized_matrix = shortest_path(self.ady_matrix,directed=True,method='BF',return_predecessors=False)
        if np.allclose(self.ady_matrix,optimized_matrix) == False:
            self.ady_matrix = optimized_matrix

    def bellmanFord(self, destiny):
        D, Pr = shortest_path(self.ady_matrix,directed=True,method='BF',return_predecessors=True)
        _from = self.all_nodes.index(self.entity)
        path = [destiny]
        k = destiny

    def parse_path(self, path):
        return [self.all_nodes[i] for i in path]

    def get_shortest_path(self, destiny): #should be a character
        _from = self.all_nodes.index(self.entity)
        destiny = self.all_nodes.index(destiny)
        path = [destiny]
        k = destiny
        while self.ady_matrix[_from, k] != -9999:
            path.append(self.ady_matrix[_from, k])
            k = self.ady_matrix[_from, k]
        return self.parse_path(path[::-1])

    def send_msg(self, to, msg): # to should be a character
        path = self.get_shortest_path(to)
        print("%s: my best path: %s" %(self.entity,path))
        if len(path) > 1:
            self.send_message(
                mto=self.neighbors[path[1]],
                mbody="<msg chat='%s' to='%s' ></msg>" %(msg, to),
                mfrom=self.boundjid
            )

    async def message(self, msg):
        if msg['type'] in ('normal', 'chat'):
            if msg['body'][:7] in ("<hello>"):
                msg.reply(self.boundjid).send()
                print("Recieved hello from neighbor, sending answer ...")
            elif msg['body'][1:4] == "eco":
                xml_parse = ET.fromstring(msg['body'])
                timestamp = xml_parse.attrib['time']
                msg.reply("<a_eco time='%s'></a_eco>" % timestamp).send()
            elif msg['body'][1:6] == "a_eco":
                pack_from = msg['from'].bare
                node_entity = self.get_nickname(pack_from)
                end_time = time()
                msg_parse = ET.fromstring(msg['body'])
                start_time = float(msg_parse.attrib['time'])
                delta_time = (end_time - start_time) / 2
                delta_time = round(delta_time, 1)
                self.update_topo_package(node_entity, delta_time)
            elif msg['body'][1:5] == "pack":
                # p_from = msg['from'].bare
                # n_entity = self.get_nickname(p_from)
                parse = ET.fromstring(msg['body'])
                pack_json = parse.attrib['dvr']
                dvr = json.loads(pack_json)
                n_entity = parse.attrib['from']

            elif msg['body'][1:4] == "msg":
                msg_parse = ET.fromstring(msg['body'])
                bare_msg = msg_parse.attrib['chat']
                msg_to = msg_parse.attrib['to']
                if msg_to != self.entity:
                    self.send_msg(msg_to, bare_msg)
                else:
                    print("Incoming message: %s" % bare_msg)
            else:
                pass


import pickle
from constants import Constants
from quotes import fetch_quotes, get_the_quote
from music import music_classify, get_songs
from movies import movies_classify, get_movies
from images import ImageDatasetProcessing, get_images
from books import books_classify, get_books

class Recommendations:
        def __init__(self):

                self.const = Constants()
                self.recs_path = self.const.recs_path

        def initialise_recommendations(self):
                """
                Drives the classification of all the datasets being used
                """
                print ()
                print ('Initialising recommendations...')
                music_classify()
                movies_classify()
                books_classify()
                fetch_quotes()
                ImageDatasetProcessing()
                print ('Initialised recommendations.')
                print ()

        def get_recommendations(self, emotion, choice):
                """
                Retrieves recommendations for the user based on their emotion

                Args:

                emotion: the user's emotion/mood
                choice: whether the user wants calming(0) or relatable(1) recommendations
                """
                print ()
                print ('Getting recommendations...')
                rec_dict = {}
                rec_dict[self.const.quote_key] = get_the_quote(self.const.quotes_emotions_mapping[emotion])
                if choice==1:
                        rec_dict[self.const.song_key] = get_songs(self.const.music_emotion_mapping['relatable'][emotion])
                        rec_dict[self.const.movie_key] = get_movies(self.const.movie_emotion_mapping['relatable'][emotion])
                        rec_dict[self.const.image_key] = get_images(self.const.image_emotion_mapping['relatable'][emotion])
                        rec_dict[self.const.book_key] = get_books(self.const.book_emotion_mapping['relatable'][emotion])
                else:
                        rec_dict[self.const.song_key] = get_songs(self.const.music_emotion_mapping['soothe'][emotion])
                        rec_dict[self.const.movie_key] = get_movies(self.const.movie_emotion_mapping['soothe'][emotion])
                        rec_dict[self.const.image_key] = get_images(self.const.image_emotion_mapping['soothe'][emotion])
                        rec_dict[self.const.book_key] = get_books(self.const.book_emotion_mapping['soothe'][emotion])

                print (rec_dict[self.const.song_key])
                print (rec_dict[self.const.book_key])
                print (rec_dict[self.const.movie_key])
                print (rec_dict[self.const.image_key])
                print (rec_dict[self.const.quote_key])

                with open(self.const.recs_path, 'wb') as handle:
                        pickle.dump(rec_dict, handle, protocol=pickle.HIGHEST_PROTOCOL)


import pysam, sys, getopt

argv = sys.argv[1:]
opts, args = getopt.getopt(argv, 'i:o:t:f:')
input_file = None
output_directory = None
tag = None
names = None
for opt, arg in opts:
    if opt == '-i':
        input_file = arg
    elif opt == '-o':
        output_directory = arg
    elif opt == '-t':
        tag = arg
    elif opt == '-f':
        names = arg
if input_file is None or output_directory is None or tag is None:
    print('arguments wrong')
    sys.exit(2)

pure_bam = pysam.AlignmentFile(input_file)
memory_read_arrays = {}
uniq_names = None
if names is not None:
    uniq_names = set()
    names = open(names, mode='r')
    for line in names.readlines():
        uniq_names.add(line[0:len(line)-1])

for read in pure_bam:
    try:
        key = read.get_tag(tag)
    except:
        continue
    if uniq_names is not None:
        if key not in uniq_names:
            continue
    if memory_read_arrays.get(key) is None:
        read_array = list()
    else:
        read_array = memory_read_arrays.get(key)
    read_array.append(read)
    memory_read_arrays[key] = read_array

for key in memory_read_arrays:
    f = pysam.AlignmentFile(output_directory + key + '.bam', 'wb', template=pure_bam)
    for read in memory_read_arrays.get(key):
        f.write(read)
    f.close()
pure_bam.close()


from PyQt5 import QtWidgets
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize, Qt
from .widgets import ControlButton, ScrollableButton, Seekbar, PlaybackModeControlButton
from .uilib.util import mask_image_circ, shadowify, setElide

class PlayerInfoFrame(QtWidgets.QFrame):
    def __init__(self, p):
        super(PlayerInfoFrame, self).__init__(p)
        self.hlay = QtWidgets.QHBoxLayout(self)
        self.hlay.setContentsMargins(4, 0, 16, 0)
        self.vlay = QtWidgets.QVBoxLayout()
        self.setFixedSize(208, 64)
        self.setObjectName("player-info-frame")

        self.coverArt = QtWidgets.QLabel(self)
        self.coverArt.setObjectName("player-info-cover-art")
        self.coverArt.setFixedSize(58, 58)
        self.coverArt.setPixmap(mask_image_circ("res/icons/cd.png", imgtype="png", size=58))

        self.trackTitle = QtWidgets.QLabel("----", self)
        self.trackTitle.setObjectName("player-info-track-title")

        self.trackArtist = QtWidgets.QLabel("--", self)
        self.trackArtist.setObjectName("player-info-track-artist")

        self.vlay.addWidget(self.trackTitle)
        self.vlay.addSpacing(-35)
        self.vlay.addWidget(self.trackArtist)

        self.hlay.addWidget(self.coverArt)
        self.hlay.addLayout(self.vlay)

        shadowify(self)

    def setCoverArt(self, coverPath):
        if coverPath is None:
            self.coverArt.setPixmap(mask_image_circ("res/icons/cd.png", imgtype="png", size=58))
        else:
            self.coverArt.setPixmap(mask_image_circ(coverPath, imgtype="jpg", size=58))

    def setTitle(self, trackTitle):
        setElide(self.trackTitle, trackTitle)

    def setArtist(self, trackArtist):
        setElide(self.trackArtist, trackArtist)

class PlayerControllerFrame(QtWidgets.QFrame):
    def __init__(self, p):
        super(PlayerControllerFrame, self).__init__(p)
        self.hlay = QtWidgets.QHBoxLayout(self)
        self.hlay.setContentsMargins(8, 0, 8, 0)
        self.hlay.setSpacing(0)
        self.hlay.setAlignment(Qt.AlignCenter)
        self.setFixedSize(168, 34)
        self.setObjectName("player-controller-frame")

        self.playPause = ControlButton(24, QIcon("res/icons/play.svg"), "", self)
        self.previousButton = ControlButton(16, QIcon("res/icons/skipback.svg"), "", self)
        self.nextButton = ControlButton(16, QIcon("res/icons/skipforward.svg"), "", self)
        self.rewind = ControlButton(16, QIcon("res/icons/rewind.svg"), "", self)
        self.fastForward = ControlButton(16, QIcon("res/icons/forward.svg"), "", self)

        self.rewind.setAutoRepeat(True)
        self.rewind.setAutoRepeatDelay(500)
        self.rewind.setAutoRepeatInterval(100)

        self.fastForward.setAutoRepeat(True)
        self.fastForward.setAutoRepeatDelay(500)
        self.fastForward.setAutoRepeatInterval(100)

        for button in self.findChildren(QtWidgets.QPushButton):
            button.setFixedSize(30, 30)

        self.hlay.addWidget(self.rewind)
        self.hlay.addWidget(self.previousButton)
        self.hlay.addWidget(self.playPause)
        self.hlay.addWidget(self.nextButton)
        self.hlay.addWidget(self.fastForward)

        shadowify(self)

class PlaybackControllerFrame(QtWidgets.QFrame):
    def __init__(self, p):
        super(PlaybackControllerFrame, self).__init__(p)
        self.hlay = QtWidgets.QHBoxLayout(self)
        self.hlay.setContentsMargins(0, 0, 0, 0)
        self.hlay.setSpacing(0)
        self.hlay.setAlignment(Qt.AlignCenter)
        self.setFixedSize(97, 34)
        self.setObjectName("playback-controller-frame")

        self.volumeButton = ScrollableButton(16, QIcon("res/icons/volume.svg"), "", self)
        self.playbackModeButton = PlaybackModeControlButton(16, QIcon("res/icons/repeatoff.svg"), "", self)
        self.playbackModeButton.set_state(0)
        self.equalizerButton = ControlButton(16, QIcon("res/icons/equalizer.svg"), "", self)

        for button in self.findChildren(QtWidgets.QPushButton):
            button.setIconSize(QSize(16, 16))
            button.setFixedSize(30, 30)
            self.hlay.addWidget(button)

        shadowify(self)

class SeekbarFrame(QtWidgets.QFrame):
    def __init__(self, p):
        super(SeekbarFrame, self).__init__(p)
        self.setObjectName("seekbar-frame")
        self.setFixedHeight(25)
        self.hlay = QtWidgets.QHBoxLayout(self)
        self.hlay.setContentsMargins(8, 0, 8, 0)
        self.seekbar = Seekbar(self)
        self.seekbar.setOrientation(Qt.Horizontal)
        self.hlay.addWidget(self.seekbar)

        shadowify(self)

class FavouriteFrame(QtWidgets.QFrame):
    def __init__(self, p):
        super(FavouriteFrame, self).__init__(p)
        self.setObjectName("favourite-frame")
        self.setFixedSize(34, 34)
        self.hlay = QtWidgets.QHBoxLayout(self)
        self.hlay.setContentsMargins(0, 0, 0, 0)
        self.favouriteButton = QtWidgets.QPushButton(QIcon("res/icons/fav-untoggled.svg"), "", self)
        self.favouriteButton.setIconSize(QSize(16, 16))
        self.favouriteButton.setFixedSize(30, 30)
        self.hlay.addWidget(self.favouriteButton)

        shadowify(self)

class TimeFrame(QtWidgets.QFrame):
    def __init__(self, p):
        super(TimeFrame, self).__init__(p)
        self.setObjectName("time-frame")
        self.setFixedHeight(34)
        self.hlay = QtWidgets.QHBoxLayout(self)
        self.time = QtWidgets.QLabel("--:--/--:--", self)
        self.hlay.addWidget(self.time, alignment=Qt.AlignCenter)

        shadowify(self)

class PlayerPanelLayout(QtWidgets.QHBoxLayout):
    def __init__(self):
        super(PlayerPanelLayout, self).__init__()
        self.setSpacing(10)
        self.bottom_hlay = QtWidgets.QHBoxLayout()
        self.vlay = QtWidgets.QVBoxLayout()

        self.playerInfoFrame = PlayerInfoFrame(self.parent())
        self.playerControllerFrame = PlayerControllerFrame(self.parent())
        self.playbackControllerFrame = PlaybackControllerFrame(self.parent())
        self.seekbarFrame = SeekbarFrame(self.parent())
        self.favouriteFrame = FavouriteFrame(self.parent())
        self.timeFrame = TimeFrame(self.parent())

        self.bottom_hlay.addWidget(self.playerControllerFrame)
        self.bottom_hlay.addWidget(self.playbackControllerFrame)
        self.bottom_hlay.addStretch()
        self.bottom_hlay.addWidget(self.favouriteFrame)
        self.bottom_hlay.addWidget(self.timeFrame)
        self.vlay.addWidget(self.seekbarFrame)
        self.vlay.addLayout(self.bottom_hlay)
        self.addWidget(self.playerInfoFrame)
        self.addLayout(self.vlay)


from flask import Flask, request, jsonify
import json

# 将当前程序作为web app应用
# 配置static模式
# static_folder静态文件的路径
app = Flask(__name__,static_folder='static',static_url_path='/')

@app.route(rule='/sales', methods=['GET'])
def post_test():
    # 附加题: 从excel表中读取这些数据
    sales_data = [20, 20, 30, 10, 10, 15]
    r = jsonify(sales_data)
    return r

if __name__ == '__main__':
    app.run(port=80, debug=True)


import training.dataset
import unittest
import model.rigid_body_model as rbm
import model.param as model_param
import numpy as np
from scipy.spatial.transform import Rotation as R

class TestDexGraspDataset(unittest.TestCase):
    def setUp(self) -> None:
        self.hand_plant = rbm.AllegroHandPlantDrake(meshcat_open_brower=False,
                                           num_viz_spheres=0)

    def test_make_dataset_from_same_point_cloud(self):
        rs = np.random.RandomState(0)
        copies = 3
        dut = training.dataset.make_dataset_from_same_point_cloud('003_cracker_box',
                                                                make_datset=False, random_xy=False,
                                                                random_yaw=False,
                                                                copies=copies,
                                                                data_idx_start=0, data_idx_end=1,
                                                                random_state=rs)
        # Theres should be exactly 10 data points
        self.assertEqual(len(dut), copies)
        # construct with random orientation
        dut_orn = training.dataset.make_dataset_from_same_point_cloud('003_cracker_box',
                                                                make_datset=False, random_xy=False,
                                                                random_yaw=True,
                                                                copies=copies,
                                                                data_idx_start=0, data_idx_end=1,
                                                                random_state=rs)

        def test_dataset_consistency(d):
            # Check that fingertip_normals is consistent with the fingertip positions
            # computed from (base_position, base_quaternion, finger_q)
            diagram_context, plant_context = self.hand_plant.create_context()
            gt_fingertip_angles_dict = {}
            gt_fingertip_angles_dict = model_param.finger_q_to_finger_angles_dict(d.finger_q)
            gt_fingertip_angles_dict[model_param.AllegroHandFinger.RING] = np.zeros(4)
            # Compute the corresponding fingeritp locations
            gt_drake_q = self.hand_plant.convert_hand_configuration_to_q(d.base_position,
                d.base_quaternion, gt_fingertip_angles_dict
            )
            gt_p_WF = self.hand_plant.compute_p_WF(gt_drake_q, plant_context)
            gt_fingertip_normals = d.fingertip_normals
            for fi, finger in enumerate(model_param.ActiveAllegroHandFingers):
                np.testing.assert_allclose(gt_fingertip_normals[fi,:3],
                np.squeeze(gt_p_WF[finger]),
                atol=1e-2 # Allow large tolerance as gt_p_WF is from IK solution
            )

        for idx in range(len(dut)):
            # Retrieve the random orientation
            original_entry = dut[idx]
            rotated_entry = dut_orn[idx]
            original_base_quaternion = R.from_quat(original_entry.base_quaternion[[1,2,3,0]])
            rotated_base_quaternion = R.from_quat(rotated_entry.base_quaternion[[1,2,3,0]])
            rot_diff = rotated_base_quaternion*original_base_quaternion.inv()
            # Rotate everything else back
            rot_diff_matrix = rot_diff.as_matrix()
            # Compare point clouds
            pc_original = original_entry.point_cloud
            pc_rot = rotated_entry.point_cloud
            np.testing.assert_allclose(pc_rot,
                                        (rot_diff_matrix @ (pc_original.T)).T)
            # Compare normals
            fingertip_normals_original = original_entry.fingertip_normals
            fingertip_normals_rot = rotated_entry.fingertip_normals
            # Check fingertip positions
            np.testing.assert_allclose(fingertip_normals_rot[:,:3],
                                        (rot_diff_matrix @ (fingertip_normals_original[:,:3].T)).T)
            # Check fingertip normal vectors
            np.testing.assert_allclose(fingertip_normals_rot[:,3:],
                            (rot_diff_matrix @ (fingertip_normals_original[:,3:].T)).T)
            # Check finger q
            np.testing.assert_allclose(original_entry.finger_q, rotated_entry.finger_q)

            # Check base position
            np.testing.assert_allclose(rotated_entry.base_position, rot_diff_matrix @ original_entry.base_position)

            # Test consistency
            test_dataset_consistency(original_entry)
            test_dataset_consistency(rotated_entry)

        # construct with random translation
        dut_trans = training.dataset.make_dataset_from_same_point_cloud('003_cracker_box',
                                                                make_datset=False, random_xy=True,
                                                                random_yaw=False,
                                                                copies=copies,
                                                                data_idx_start=0, data_idx_end=1,
                                                                random_state=rs)
        for idx in range(len(dut)):
            # Retrieve the random translation
            original_entry = dut[idx]
            translated_entry = dut_trans[idx]
            trans = translated_entry.base_position-original_entry.base_position
            # Compare point clouds
            pc_original = original_entry.point_cloud
            pc_trans = translated_entry.point_cloud
            pc_diff = pc_trans-pc_original
            self.assertTrue(np.allclose(pc_diff, trans))
            # Compare normals
            fingertip_normals_original = original_entry.fingertip_normals
            fingertip_normals_trans = translated_entry.fingertip_normals
            # Check fingertip positions
            self.assertTrue(np.allclose((fingertip_normals_trans-fingertip_normals_original)[:,:3],
                                        trans))
            # Check fingertip normal vectors
            np.testing.assert_allclose(fingertip_normals_trans[:,3:], fingertip_normals_original[:,3:])
            # Check finger q
            np.testing.assert_allclose(original_entry.finger_q, translated_entry.finger_q)
            np.testing.assert_allclose(original_entry.base_quaternion, translated_entry.base_quaternion)
            test_dataset_consistency(original_entry)
            test_dataset_consistency(translated_entry)

if __name__ == '__main__':
    unittest.main()


import requests
from bs4 import BeautifulSoup

def music_Leaderboard(input_country):
    country = {"西洋": "3",
               "日韓": "2",
               "華語": "1"}
    req = requests.get(
        'https://www.kiss.com.tw/music/billboard.php?a=%s' % (country[input_country]))
    soup = BeautifulSoup(req.text, 'html.parser')
    music_list = soup.find('tbody')
    music_info = music_list.find_all('td')
    music_name = []
    for music in music_info:
        music_name.append(music.get_text())
    show = ''
    for i in range(8, len(music_name)+8, 8):
        show += "名次:%s\n歌名:%s\n歌手:%s\n專輯名稱:%s\n發行公司:%s\n\n" % (
            music_name[i-8], music_name[i-7], music_name[i-6], music_name[i-5], music_name[i-4])
    return show