from grid_world import *
from numpy.random import choice
import numpy as np
import random
from matplotlib import pyplot as plt

class DiscreteSoftmaxPolicy(object):
    def __init__(self, num_states, num_actions, temperature):
        self.num_states = num_states
        self.num_actions = num_actions
        self.temperature = temperature
        self.init_temperature = temperature
        self.terminal_temperature = 0.8

        # here are the weights for the policy
        self.weights = np.random.randn(num_states, num_actions) * np.sqrt(2/num_actions)

    # TODO: fill this function in
    # it should take in an environment state
    # return the action that follows the policy's distribution
    def act(self, state):
        probs = self._action_probs(state)
        return choice(range(self.num_actions), p=probs)

    def _sigmoid(self):
        return 1 / (1 + np.exp(-self.weights))

    def _action_probs(self, state):
        prob_actions = np.zeros((self.num_actions, ))
        total = 0
        for a in range(self.num_actions):
            prob_actions[a] = np.exp( self.weights[state][a] / self.temperature )
            total += prob_actions[a]

        return prob_actions / total

    def _custom_softmax(self, weights, state):
        prob_actions = np.zeros((self.num_actions, ))
        total = 0
        for a in range(self.num_actions):
            prob_actions[a] = np.exp( weights[state][a] / self.temperature )
            total += prob_actions[a]

        return prob_actions / total

    # TODO: fill this function in
    # computes the gradient of the discounted return
    # at a specific state and action
    # return the gradient, a (self.num_states, self.num_actions) numpy array
    def compute_gradient(self, state, action, discounted_return):
        grad = np.zeros((self.num_states, self.num_actions))
        probs = self._action_probs(state)

        for a in range(self.num_actions):
            if a == action:
                grad[state][a] = ( self.weights[state][action] / self.temperature ) * ( 1 - probs[a] ) * discounted_return

            else:
                grad[state][a] = ( self.weights[state][action] / self.temperature ) * (- probs[a] ) * discounted_return

        return grad

    # TODO: fill this function in
    # takes a step of gradient ascent given a gradient (from compute_gradient())
    # and a step size. adjust self.weights
    def gradient_step(self, grad, step_size):
        self.weights = self.weights + grad * step_size

# TODO: fill this function in
# takes in a list of rewards from an episode
# and returns a list of discounted rewards
# Ex. get_discounted_returns([1, 1, 1], 0.5)
# should return [1.75, 1.5, 1]
def get_discounted_returns(rewards, gamma):
    cumulative_returns = np.zeros((len(rewards), ))
    future_returns = 0
    for i in range(len(rewards) - 1, -1, -1):
        cumulative_returns[i] = rewards[i] + gamma * future_returns
        future_returns = cumulative_returns[i]
    return cumulative_returns

# TODO: fill this function in
# this will take in an environment, GridWorld
# a policy (DiscreteSoftmaxPolicy)
# a discount rate, gamma
# and the number of episodes you want to run the algorithm for
def reinforce(env, policy, gamma, num_episodes, learning_rate):
    total_rewards = []
    state = env.reset() # initial state
    for ep in range(num_episodes):
        # Decrease temperature overtime
        policy.temperature -= ((policy.init_temperature - policy.terminal_temperature) / num_episodes)
        rewards = []
        states = []
        actions = []

        done = False

        # Generate a full episode folowing the policy
        while not done:
            states.append(state)

            action = policy.act(state)
            actions.append(action)

            state, reward, done = env.step(action)
            rewards.append(reward)
        state = env.reset()

        G = get_discounted_returns(rewards, gamma)

        # loop through each episode
        for i in range(len(states)):
            grad = policy.compute_gradient(states[i], actions[i], G[i])
            policy.gradient_step(grad, learning_rate)
        total_rewards.append(np.mean(rewards))
    total_rewards = np.convolve(total_rewards, np.ones((300,)) / 300, mode='valid')
    return list(range(len(total_rewards))), total_rewards

def print_policy(policy: DiscreteSoftmaxPolicy, env: GridWorld, i):
        result = np.chararray((env.n_rows, env.n_cols), unicode=True)
        act_arrow_map = {
            0: u"\u2191",
            1: u"\u2192",
            2: u"\u2193",
            3: u"\u2190"
        }
        for r in range(env.n_rows):
            for c in range(env.n_cols):
                result[r][c] = act_arrow_map[policy.act(env.map[r][c])]

        print('Iteration: [{}]\nPolicy:\n{}\n\n'.format(i, result))

if __name__ == "__main__":
    gamma = 0.9
    num_episodes = 20000
    learning_rate = 1e-4

    fig = plt.figure()
    for i in range(1, 21):
        env = GridWorld(MAP2)
        policy = DiscreteSoftmaxPolicy(env.get_num_states(), env.get_num_actions(), temperature=1.4)
        iteration, total_mean_return = reinforce(env, policy, gamma, num_episodes, learning_rate)

        print_policy(policy, env, i)

        ax = fig.add_subplot(4,5,i)
        ax.plot(iteration, total_mean_return)
        ax.set_title(i)
        print('{} | Reached goal: {} times\n\n'.format(i, env.goals_reached))

    plt.tight_layout()
    plt.show()

    # gives a sample of what the final policy looks like
    print("Rolling out final policy")
    state = env.reset()
    env.print()
    done = False
    while not done:
        input("press enter to continue:")
        action = policy.act(state)
        state, reward, done = env.step(action)
        env.print()


# Объедините функции из прошлых задач.
# Функцию угадайку задекорируйте:
# ○ декораторами для сохранения параметров,
# ○ декоратором контроля значений и
# ○ декоратором для многократного запуска.
# Выберите верный порядок декораторов.

from typing import Callable
from random import randint
import os
import json

def check_parametr(func: Callable):
    MIN_NUM = 1
    MAX_NUM = 100
    MIN_COUNT = 1
    MAX_COUNT =10
    def wrapper(num: int, count: int, *args, **kwargs):
        if num > MAX_NUM or num < MIN_NUM:
            num = randint(MIN_NUM, MAX_NUM)
        if count > MAX_COUNT or count < MIN_COUNT:
            count = randint(MIN_COUNT, MAX_COUNT)
        # print(num, count)
        result = func(num, count, *args, **kwargs)

        return result

    return wrapper

def logger(func: Callable):
    file_name = f'{func.__name__}.json'
    if os.path.exists(file_name):
        with open(file_name, 'r', encoding='utf-8') as f:
            data = json.load(f)
    else:
        data = []

    def wrapper(*args, **kwargs):
        json_dict = {'args': args, **kwargs}
        result = func(*args, **kwargs)
        json_dict['result'] = result
        data.append(json_dict)

        with open(file_name, 'w', encoding='utf-8') as f1:
            json.dump(data, f1)

        return result

    return wrapper

def count_f(num: int = 1):
    def deco(func: Callable):
        results = []
        def wrapper(*args, **kwargs):
            for i in range(num):
                results.append(func(*args, **kwargs))
            return results
        return wrapper
    return deco

@count_f(2)
@check_parametr
@logger
def gess_number(num: int, count: int) -> Callable[[], None]:

    for i in range(1, count + 1):
        num_input = int(input(f'Угадайте число от 1 до 100, у Вас {count + 1 - i} попыток: '))
        print(f'Попытка № {i}')
        if num_input == num:
            return 'Вы угадали!'
        elif num_input < num:
            print('Загаданное число больше')
        else:
            print('Загаданное число меньше')

    return 'Вы не угадали!'

if __name__ == '__main__':
    game = gess_number(25, 5)
    print(game)


from __future__ import print_function
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
import pandas as pd
from IPython.display import HTML

import logging
import boto3
import boto3.session
from botocore.exceptions import ClientError

#ELO Weights
WIN = 1
TIE = 0.5
LOSS = 0

class CatanStats():

    def __init__(self):
        # If modifying these scopes, delete the file token.json.
        self.SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']

        # The ID and range of a sample spreadsheet.
        self.SAMPLE_SPREADSHEET_ID = '1MG7jhiarGpRunEILVbkEfD3mLRUBpIMI4au7cMID_EM'
        self.SAMPLE_RANGE_NAME = 'Games'

        # Dataframe containing Games and All Player Data from Google Sheets
        self.games, self.player_scores = self.get_games()

        # Initialize Elo Dict
        self.elo = self.elo_init()

        for index, row in self.games.iterrows():
            self.new_ratings(row)

    # Fetches data from Google Sheets
    def get_games(self):
        creds = None
        # The file token.json stores the user's access and refresh tokens, and is
        # created automatically when the authorization flow completes for the first
        # time.
        if os.path.exists('token.json'):
            creds = Credentials.from_authorized_user_file('token.json', self.SCOPES)
        # If there are no (valid) credentials available, let the user log in.
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    'credentials.json', self.SCOPES)
                creds = flow.run_local_server(port=0)
            # Save the credentials for the next run
            with open('token.json', 'w') as token:
                token.write(creds.to_json())

        service = build('sheets', 'v4', credentials=creds)

        sheet = service.spreadsheets()
        result = sheet.values().get(spreadsheetId=self.SAMPLE_SPREADSHEET_ID,
                                    range=self.SAMPLE_RANGE_NAME).execute()
        values = result.get('values', [])

        df = pd.DataFrame(values[1:], columns=values[0])

        p1 = df[['Player 1', 'Starting Production 1', 'Ending VP 1']].rename(columns={"Player 1": "Player", "Starting Production 1": "Starting Production",  "Ending VP 1": "Ending VP"})
        p2 = df[['Player 2', 'Starting Production 2', 'Ending VP 2']].rename(columns={"Player 2": "Player", "Starting Production 2": "Starting Production",  "Ending VP 2": "Ending VP"})
        p3 = df[['Player 3', 'Starting Production 3', 'Ending VP 3']].rename(columns={"Player 3": "Player", "Starting Production 3": "Starting Production",  "Ending VP 3": "Ending VP"})
        p4 = df[['Player 4', 'Starting Production 4', 'Ending VP 4']].rename(columns={"Player 4": "Player", "Starting Production 4": "Starting Production",  "Ending VP 4": "Ending VP"})

        players = pd.concat([p1, p2, p3, p4])

        nan_value = float("NaN")
        players.replace("", nan_value, inplace=True)
        players = players.dropna()

        players = players.reset_index()
        players_scores = players.apply(pd.to_numeric, errors='ignore')

        return df, players_scores

    # Initializes Elo Dict
    def elo_init(self):
        elo = {}
        for player in self.player_scores['Player'].unique():
            elo[player] = 1000
        return elo

    # Individual elo calculation based on outcome
    def elo_calc(self, eloA, eloB, actual_outcome):
        K_VAL = 15
        expected_outcome = 1 / (1 + 10**((eloB - eloA)/400) )
        elo_adjustment_a = K_VAL * (actual_outcome - expected_outcome)
        return elo_adjustment_a

    # Calculates new elo ratings for game
    def new_ratings(self, game):

        # Check if Variant Game
        if(game["Variant"] == "TRUE"):
            variant = True
        else:
            variant = False

        # Check if 3 or 4 player
        if(game["Player 4"] == ''):
            four_player_game = False
        else:
            four_player_game = True

        # Pairwise elo_calc
        player_elo_adj = []

        if(not variant):
            if(four_player_game):

                # Iterate over pairwise player matchups
                for i in range(1,5):

                    player_cummulative = 0

                    for j in range(1,5):

                        if(int(game["Ending VP {}".format(i)]) > int(game["Ending VP {}".format(j)])):
                            outcome = WIN
                        elif(int(game["Ending VP {}".format(i)]) == int(game["Ending VP {}".format(j)])):
                            outcome = TIE
                        else:
                            outcome = LOSS

                        match_up = self.elo_calc(self.elo[game['Player {}'.format(i)]], self.elo[game['Player {}'.format(j)]], outcome)

                        player_cummulative += match_up

                    player_elo_adj.append(player_cummulative)

                # Elo adjustments after calculations
                for i in range(0,4):
                    self.elo[game['Player {}'.format(i + 1)]] += round(player_elo_adj[i])

            else:
                # Iterate over pairwise player matchups
                for i in range(1,4):

                    player_cummulative = 0

                    for j in range(1,4):
                        try:
                            if(int(game["Ending VP {}".format(i)]) > int(game["Ending VP {}".format(j)])):
                                outcome = WIN
                            elif(int(game["Ending VP {}".format(i)]) == int(game["Ending VP {}".format(j)])):
                                outcome = TIE
                            else:
                                outcome = LOSS
                        except ValueError:
                            print(game["Game #"],i, " ", j, " ", game["Ending VP {}".format(i)], " " , game["Ending VP {}".format(j)] )

                        match_up = self.elo_calc(self.elo[game['Player {}'.format(i)]], self.elo[game['Player {}'.format(j)]], outcome)

                        player_cummulative += match_up

                    player_elo_adj.append(player_cummulative)

                # Elo adjustments after calculations
                for i in range(0,3):
                    self.elo[game['Player {}'.format(i + 1)]] += round(player_elo_adj[i])

        return None

    # Aggregate Stats on Players
    def player_info(self):

        # Add Elo scores to Player_Scores
        self.player_scores['Elo'] = self.player_scores.apply(lambda row: int(self.elo[row['Player']]), axis = 1)

        # Add aggregate data to player_stats df
        player_stats = self.player_scores.groupby('Player').agg({'Starting Production': ['mean', 'std'], 'Ending VP': ['mean', 'std'], 'Elo': ['mean']})
        player_stats["Games Played"] = self.player_scores.groupby('Player').size()
        player_stats["Wins"] = self.player_scores.loc[self.player_scores['Ending VP'] >= 10].groupby('Player').size()
        player_stats["Win Percentage"] = player_stats["Wins"] / player_stats["Games Played"]

        # Rounds data to 2 decimal spots
        player_stats[('Starting Production','mean')] = player_stats[('Starting Production','mean')].round(2)
        player_stats[('Starting Production','std')] = player_stats[('Starting Production','std')].round(2)
        player_stats[('Ending VP','mean')] = player_stats[('Ending VP','mean')].round(2)
        player_stats[('Ending VP','std')] = player_stats[('Ending VP','std')].round(2)
        player_stats['Win Percentage'] = (player_stats['Win Percentage'] * 100).round(2)

        # Filter players who have played more than 1 game
        player_stats = player_stats[player_stats['Games Played'] > 1]

        # return player_stats.sort_values([('Ending VP', 'mean'),('Elo', 'mean'),"Win Percentage"], ascending=False)
        # return player_stats.sort_values(["Games Played", ('Ending VP', 'mean'),('Elo', 'mean'),"Win Percentage"], ascending=False)
        # return player_stats.sort_values([('Starting Production', 'mean'),"Win Percentage",('Ending VP', 'mean')], ascending=False)
        # return player_stats.sort_values(["Win Percentage",('Elo', 'mean'),('Ending VP', 'mean')], ascending=False)
        return player_stats.sort_values([('Elo', 'mean'),"Win Percentage",('Ending VP', 'mean')], ascending=False)

    # Aggregate Stats on Dice
    def dice_info(self):
        df = get_data()

    # Creates HTML File from player_info
    def create_player_table(self):

        html = self.player_info().to_html(classes=["table", "table-striped"])

        # write html to file
        text_file = open("index.html", "w")
        text_file.write('<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">\n')
        text_file.write(html)
        text_file.close()

def upload_s3(file):

    session = boto3.session.Session(profile_name='default')
    s3_client = session.client('s3')

    try:
        s3_client.upload_file(Filename=file, Bucket="adamlenning.com", Key=file,  ExtraArgs={'ContentType': "text/html"})
    except ClientError as e:
        logging.error(e)
        return False
    return True

if __name__ == '__main__':
    c1 = CatanStats()
    c1.create_player_table()
    upload_s3('index.html')


r"""CLIP ImageNet zero-shot evaluation.

"""
# pylint: enable=line-too-long

import ml_collections

from configs import clip_common  # local file import from experimental.multimodal

def get_config():
  """Config for zero-shot evaluation of CLIP on ImageNet."""
  config = ml_collections.ConfigDict()

  config.model_name = 'vit_b16'
  config.only_eval = True

  # Fine-tuning dataset
  config.dataset = 'coco_captions'
  config.train_split = 'train'
  config.val_split = 'val'

  BATCH_SIZE = 512  # pylint: disable=invalid-name
  config.batch_size = BATCH_SIZE
  config.batch_size_eval = BATCH_SIZE
  config.val_cache = False

  config.total_steps = 20_000

  config.tokenizer_max_len = 77

  # PP modified from
  # third_party/py/big_vision/configs/proj/image_text/lit_coco.py
  INPUT_RES = clip_common.IMAGE_RESOLUTION[config.model_name]  # pylint: disable=invalid-name
  coco_pp = 'get_coco_captions("text")'
  image_pp = f'|decode|resize({INPUT_RES})|flip_lr|randaug(2,10)|value_range(-1,1)'
  text_pp = f'|clip_tokenize({config.tokenizer_max_len}, key="text", key_result="text")'
  final_pp = '|keep(["image", "text"])'
  config.pp_train = config.pp_eval = coco_pp + image_pp + text_pp + final_pp

  config.shuffle_buffer_size = 50_000  # Per host, so small-ish is ok.

  config.log_training_steps = 100
  config.log_eval_steps = 1000
  config.checkpoint_steps = 4000
  config.checkpoint_timeout = 1

  config.prefetch_to_device = 2
  config.trial = 0

  # Model section
  config.model_init = clip_common.CHECKPOINTS[config.model_name]
  config.convert_pytorch = True
  config.model = ml_collections.config_dict.create(
      **clip_common.CONFIGS[config.model_name])

  # Optimizer section
  config.optim_name = 'Momentum'
  config.optim = ml_collections.ConfigDict()
  config.grad_clip_norm = 1.0
  config.weight_decay = None  # No explicit weight decay

  config.lr = ml_collections.ConfigDict()
  config.lr.base = 0.06
  config.lr.warmup_steps = 500
  config.lr.decay_type = 'cosine'

  # zeroshot section
  def zeroshot_pp(num_classes, resize_method='area'):
    zeroshot_pp = f'decode|resize_small({INPUT_RES}, method="{resize_method}")|central_crop({INPUT_RES})'
    # zeroshot_pp += '|value_range(-1, 1)'
    zeroshot_pp += f'|value_range(0, 1)|normalize({clip_common.CLIP_IMAGE_MEAN}, {clip_common.CLIP_IMAGE_STD})'
    zeroshot_pp += f'|onehot({num_classes}, key="label", key_result="text")'
    zeroshot_pp += '|keep(["image", "text"])'
    return zeroshot_pp

  config.zeroshot_eval_datasets = {
      'imagenet': {
          'dataset': 'imagenet2012',
          'split': 'validation',
          'classnames_key': 'imagenet',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(1000)
      },
      'cars196': {
          'dataset': 'cars196',
          'split': 'train',
          'classnames_key': 'cars196',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(196)
      },
      'caltech101': {
          'dataset': 'caltech101',
          'split': 'train',
          'classnames_key': 'caltech101',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(102)
      },
      'cifar10': {
          'dataset': 'cifar10',
          'split': 'train',
          'classnames_key': 'cifar10',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(10, 'bicubic')
      },
      'cifar100': {
          'dataset': 'cifar100',
          'split': 'train',
          'classnames_key': 'cifar100',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(100, 'bicubic')
      },
      'dtd': {
          'dataset': 'dtd',
          'split': 'test',
          'classnames_key': 'dtd',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(47)
      },
      'eurosat': {
          'dataset': 'eurosat',
          'split': 'train',
          'classnames_key': 'eurosat',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(10, 'bicubic')
      },
      'resisc45': {
          'dataset': 'resisc45',
          'split': 'train',
          'classnames_key': 'resisc45',
          'prompts_key': 'none',
          'pp_spec': zeroshot_pp(45, 'bicubic')
      },
      'imagenet_prompt': {
          'dataset': 'imagenet2012',
          'split': 'validation',
          'classnames_key': 'imagenet',
          'prompts_key': 'imagenet',
          'pp_spec': zeroshot_pp(1000)
      },
      'cars196_prompt': {
          'dataset': 'cars196',
          'split': 'train',
          'classnames_key': 'cars196',
          'prompts_key': 'cars196',
          'pp_spec': zeroshot_pp(196)
      },
      'caltech101_prompt': {
          'dataset': 'caltech101',
          'split': 'train',
          'classnames_key': 'caltech101',
          'prompts_key': 'caltech101',
          'pp_spec': zeroshot_pp(102)
      },
      'cifar10_prompt': {
          'dataset': 'cifar10',
          'split': 'train',
          'classnames_key': 'cifar10',
          'prompts_key': 'cifar10',
          'pp_spec': zeroshot_pp(10, 'bicubic')
      },
      'cifar100_prompt': {
          'dataset': 'cifar100',
          'split': 'train',
          'classnames_key': 'cifar100',
          'prompts_key': 'cifar100',
          'pp_spec': zeroshot_pp(100, 'bicubic')
      },
      'dtd_prompt': {
          'dataset': 'dtd',
          'split': 'test',
          'classnames_key': 'dtd',
          'prompts_key': 'dtd',
          'pp_spec': zeroshot_pp(47)
      },
      'eurosat_prompt': {
          'dataset': 'eurosat',
          'split': 'train',
          'classnames_key': 'eurosat',
          'prompts_key': 'eurosat',
          'pp_spec': zeroshot_pp(10, 'bicubic')
      },
      'resisc45_prompt': {
          'dataset': 'resisc45',
          'split': 'train',
          'classnames_key': 'resisc45',
          'prompts_key': 'resisc45',
          'pp_spec': zeroshot_pp(45, 'bicubic')
      },
      'imagenet_best': {
          'dataset': 'imagenet2012',
          'split': 'validation',
          'classnames_key': 'imagenet',
          'prompts_key': 'imagenet_best',
          'pp_spec': zeroshot_pp(1000)
      },
  }

  return config

def get_sweep(hyper):
  return hyper.product([
  ])


import re
import functools

class InputError(Exception):
    """Exception to be raised for invalid inputs.
    """

    def __init__(self, char, message="Input is invalid."):
        """
        Parameters
        ----------

        char : str
            Invalidad character raising this exception.
        message: str
            Message to be shown when this exception is raised.
        """
        self.char = char
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return "{0} - > {1}".format(self.char,self.message)

class PlugboardError(Exception):
    """Exception to be raised when there's an error with the PlugBoard.
    """

    def __init__(self, char, message):
        """
        Parameters
        ----------

        char : str
            Invalidad character raising this exception.
        message: str
            Message to be shown when this exception is raised.
        """
        self.char = char
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return "{0} - > {1}".format(self.char,self.message)

def inputValidator(component, element):
    """Decorator for validating the input for several
    functions across the programme.

    Parameters
    ----------
    component : Str
        Part of the enigma machine or action to be performed.
        For example: 'encodingElement' or 'ringSettting'.
    element : Str
        String to be included within the error message.
        Makes reference to the type of component.add()
        For example: 'Ring Settings' or 'Initial Position'.
    """
    def function_decorator(function):
        def cleaning_function(selfObject, currentInput, *args, **kwargs):

            if component in ['inputElement','encodingElement']:

                lettersClean = "".join(re.findall("[a-zA-Z]+", currentInput))
                amountLettersInput = len(currentInput)
                amountLettersClean = len(lettersClean)

                if amountLettersInput > amountLettersClean:
                    raise InputError(currentInput, message="[{0}] Input can only take letters [a-zA-Z].".format(element))

                if component in 'inputElement':

                    if amountLettersClean != 2:
                        raise InputError(currentInput, message="[{0}] Input must cointain TWO letters.".format(element))

                    elif lettersClean[0] == lettersClean[1]:
                        raise InputError(currentInput, message="[{0}] Input letters must be different.".format(element))

                elif component == 'encodingElement':

                    if amountLettersClean != 1:
                        raise InputError(currentInput, message="[{0}] Input must cointain ONE letter.".format(element))

                return function(selfObject,lettersClean.lower(), *args, **kwargs)

            elif component in ['ringSetting']:
                inputClean = int("0"+"".join(re.findall("[0-9]+", str(currentInput))))
                amountCharsInput = len(str(currentInput))
                amountCharsClean = len(str(inputClean))

                if inputClean < 1 or inputClean > 26 or amountCharsInput > amountCharsClean:
                    raise InputError(currentInput, message="[{0}] Input can only take numbers between 1-26.".format(element))

                return function(selfObject,inputClean, *args, **kwargs)

            else:

                print('tu vieja')

        r = functools.update_wrapper(cleaning_function, function)
        return r

    return function_decorator


"""
Random test stuff
"""

from pysynth.seq import Sequencer
from pysynth.utils import *
from pysynth.osc import *
from pysynth.synth import *
from pysynth.filters import *
from pysynth.output.base import OutputHandler
from pysynth.output.modules import *
from pysynth.wrappers import querty, mml
from pysynth.wrappers.midi import midi
from pysynth.envelope.amp import *

import time
import pyaudio
import threading
import struct
import wave
import math
import os
import copy

from tkinter import Tk, Frame

BITRATE = 16000
#MAX_AMPLITUDE = 32767.0
#MAX_AMPLITUDE = 127.0

paudio = pyaudio.PyAudio()
stream = paudio.open(format=pyaudio.paFloat32,
                     channels=1,
                     output=True,
                     rate=44100)

def type_test():

    # Tests the audio type test

    audio = AudioValue(0.5, 0, 1000)
    #audio.add_event(ExponentialRamp, 800.0, get_time()+10000000000)
    #audio.add_event(LinearRamp, 500.0, get_time()+20000000000)

    #audio.add_event(ExponentialRamp, 800.0, get_time()+10)
    #audio.add_event(LinearRamp, 500.0, get_time()+20)

    #audio.exponential_ramp(0, get_time() + 2000000000)

    audio.linear_ramp(1, get_time() + 1000000000)

    audio.cancel_all_events()

    audio.linear_ramp(0, get_time() + 2000000000)

    while True:

        thing = audio.value

        print(thing)

        if thing == 0:

            break

        time.sleep(0.01)

def start_stream(osc):

    """
    Starts the audio thread and starts streaming data
    """

    thread = threading.Thread(target=stream_data, args=[osc])
    thread.daemon = True
    thread.start()

    return thread

def stream_data(data, time=None):

    """
    Streams data to PyAudio.
    Data is a oscillator we iterate over

    :param data: Data to stream
    """

    for num, i in enumerate(data):

        #print(i)

        stream.write(struct.pack('f', i))

        if time and num > time:

            # We are done

            return

def write_wave(data, seconds):

    """
    Writes a specified amount of wave data:
    :param data: Data to write
    :param seconds: Seconds to write
    """

    # Open the wave file:

    wav = wave.open('blorck.wav', 'wb')

    wav.setnchannels(1)
    wav.setsampwidth(4)
    wav.setframerate(44100.0)

    iter(data)

    for i in range(44100*seconds):

        value = next(data)

        wav.writeframesraw(struct.pack('<f', value))

    wav.close()

class KeyboardHandler:

    """
    Handles keyboard input, removing and adding
    oscillators to an AudioCollection as necessary.
    """

    def __init__(self, aud, keys):

        self.aud = aud  # Audio collection to maintain
        self.keys = keys  # Mapping keys to oscillators.

        # Mapping keys to oscillators to generate

        self.osc_keys = {'z': SineOscillator, 'x': SquareOscillator, 'c': SawToothOscillator, 'v': TriangleOscillator}

    def remove_key(self, key):

        """
        Removes an oscillator from the AudioCollection.

        :param key: Oscillator to remove
        """

        print("Removed key: {}".format(key.keysym))

        if key.keysym in self.osc_keys:

            # DO nothing,

            return

        if self.keys[key.keysym] not in self.aud._objs:

            # Nothing, return

            return

        self.aud.remove_module(self.keys[key.keysym])

    def add_key(self, key):

        """
        Adds an oscillator from the AudioCollection.

        :param key: Oscillator to add
        """

        print("Added Key: {}".format(key.char))

        if key.char in self.osc_keys:

            # Generate a new oscillator mp

            self.keys = gen_oscs(self.osc_keys[key.char])

            return

        if self.keys[key.char] in self.aud._objs:

            # Nothing, return

            return

        self.aud.add_module(self.keys[key.char])

def gen_oscs(osc):

    """
    Generates a list of oscillators
    :param osc: Oscillator to use to generate our list
    :return: List of keys mapped to oscillators
    """

    oscs = {}
    keys = ['q', 'a', 'w', 's', 'e', 'd', 'r', 'f', 't', 'g', 'y', 'h', 'u', 'j', 'i', 'k', 'o', 'l', 'p']

    # Generating oscillators and mapping them to keys:

    for note in range(-17, 2):

        oscs[keys[note+17]] = osc()
        oscs[keys[note + 17]].freq = 440 * (2 ** (1 / 12)) ** note
        iter(oscs[keys[note + 17]])

    return oscs

def old_keyboard_input():

    """
    Maps certain keys to a keyboard,
    and adding the notes as we press/release keys.
    """

    oscs = gen_oscs(SineOscillator)

    print(oscs)

    # Create AudioCollection for output

    collec = AudioCollection()
    collec.add_module(ZeroOscillator())

    # Create KeyBoardHandler:

    hand = KeyboardHandler(collec, oscs)

    # Start streaming the AudioCollection:

    start_stream(collec)

    # Disabling continuous keypresses:

    os.system("xset r off")

    # Creating TKinter data:

    root = Tk()
    f = Frame(root, width=100, height=100)
    f.bind("<KeyPress>", hand.add_key)
    f.bind("<KeyRelease>", hand.remove_key)
    f.pack()
    f.focus_set()
    root.mainloop()

    os.system("xset r on")

def pitch_comp(osc):

    """
    Tests the pitch of the incoming oscillator.
    :param osc:
    """

    sine = SineOscillator(freq=osc.freq.value)

    print("Pitch One:")

    stream_data(sine, time=220500)

    print("Pitch Two:")

    stream_data(osc, time=220500)

def chord_test():

    """
    Tests if the additive synthesis is producing valid chords
    """

    osc1 = TriangleOscillator(freq=440.0)
    osc2 = TriangleOscillator(freq=880.0)
    osc3 = TriangleOscillator(freq=1320.0)
    osc4 = TriangleOscillator(freq=1760.0)

    thing = AudioCollection()

    thing.add_module(osc1, start=True)

    start_stream(thing)

    time.sleep(1)
    thing.add_module(osc2, start=True)
    time.sleep(1.5)
    thing.add_module(osc3, start=True)
    time.sleep(1.76)
    thing.add_module(osc4, start=True)

def avgfilt_test():

    """
    Tests Moving Average Filter
    """

    # Set up a sine wave:

    sine = SineOscillator()

    # Set up a filter:

    filter = MovingAverage(101)

    filter.bind(sine)

    sine.freq = 1234.0

    print(sine.freq.value)
    print(filter.freq.value)

    # Start the stream:

    start_stream(filter)

def fm_test():

    """
    Tests FM Synthesis
    """

    osc1 = SineOscillator(freq=440)
    osc2 = SineOscillator(freq=6160)

    oscmain = SineOscillator(freq=440)

    collec = AudioCollection()

    twomain = FMSynth(oscmain, osc2, 1)

    oneandtwo = FMSynth(twomain, osc1, 5)

    collec.add_node(oneandtwo)

    start_stream(twomain)

def keyboard_input():

    # Tests the QUERTY sequencer, and the QUERTYKeyboard input module.

    # Create the QWERTY wrapper

    sequencer = querty.QWERTYWrapper()

    # Create the output handler:

    out = OutputHandler()
    pyaudo = PyAudioModule()
    pyaudo.special = True
    out.add_output(pyaudo)

    #out.add_output(WaveModule("test_seq.wav"))

    # Configure for keyboard:

    sequencer.load_keyboard()

    attack = 1000000000
    decay = 1000000000
    sustain = 0.2
    release = 1000000000

    env1 = ADSREnvelope(attack, decay, sustain, release)
    env2 = ADSREnvelope(attack, decay, sustain, release)
    env3 = ADSREnvelope(attack, decay, sustain, release)
    env4 = ADSREnvelope(attack, decay, sustain, release)

    env1.bind(SineOscillator(440.0))
    env2.bind(SquareOscillator(440.0))
    env3.bind(SawToothOscillator(440.0))
    env4.bind(TriangleOscillator(440.0))

    # Get controller for sine wave oscillator:

    sine = out.bind_synth(env1)
    square = out.bind_synth(env2)
    saw = out.bind_synth(env3)
    tri = out.bind_synth(env4)

    # Add sine oscillator for default instrument:

    sequencer.add_synth(sine, name=0)
    sequencer.add_synth(square, name=1)
    sequencer.add_synth(saw, name=2)
    sequencer.add_synth(tri, name=3)

    # Start the output handler:

    out.start()

    # Start the sequencer:

    sequencer.start()
    sequencer.join()
    sequencer.stop()
    out.stop()

def freq_conv(num, middle_pitch=440.0):

    # Calculate and return the frequency of the note:

    return middle_pitch * pow(2, (((num) / 12)))

def mixing_test():

    # Tests mixing operations:

    pass

def mml_test():

    # Tests the MML wrapper

    #song = '$ t120 o4 l4 e f+ b > c+ d < f+ e > c+  d c+ <e f+ b > c+ d < f+ e > c+  d c+'
    #song = '$o4 c r e r g r b r;$o4 r d r f r a r <c'
    #song = 'o4 c d e f g a b <c d'

    #song = "o4 l1 ca"

    #song = "t60 l4 o4 /: [ceg] [fac]1 :/4"

    #song = "t92 l8 o4 [>cg<cea]2. [>cg<ceg]4 [>>a<a<c+fa+]2. [>>a<a<c+ea]4 " \
    #       "[>>f<fg+<cg]2. [>>f<fg+<cf]4 [>>g<gg+b<g+]2." \
    #       "[>>g<g<g]4 o3 l32 v6 cdef ga b<c de fg"

    #song = "t92 l4 o4 [>>a<a<c+fa+]"
    #song = 'o3 l32 v6 cdefgab<cdefg'
    #song = 't30 a'
    #song = "t92 [>>f<fg+<cg]2. [>>f<fg+<cf]4 [>>g<gg+b<g+]2. [>>g<g<g]4 o3 t92 l32 v6 cdef ga b<c de fg"
    #song = 't60 [>>g<g<g]4'

    #song = 't60 o3 l4 cdefgab<c> l8 cdefgab<c> l16 cdefgab l32 cdefgab'

    song1 = "t92 l8 o4 $ [>cg<cea]2. [>cg<ceg]4 [>>a<a<c+fa+]2. [>>a<a<c+ea]4 " \
           "[>>f<fg+<cg]2. [>>f<fg+<cf]4 [>>g<gg+b<g+]2. r4; " \
           "t92 $ l1 o3 v12 r r r r2 r8 l32 v6 cdef ga b<c de fg;"

    song = "t60 l4 o4 a+ r a+;" \
           "t60 l4 o4 r  r >a+"

    song = "t120$l8 o3 >g+2.. g+ a+4. a+ <c2 >a+ g+2.. a+4 a+4 <c4. >d+ a+ g+2. g+ a+4. a+ <c2 >a+ g+2.. a+4 a+4 <c2."

    song = "t120$l8 o3 >g+2.. g+ a+4. a+ <c2 >a+ g+2.. a+4 a+4 <c4. >d+ a+ g+2. g+ a+4. a+ <c2 >a+ g+2.. a+4 a+4 <c2."

    song = 't60 l1 a r8 a. r8 a.. r8 a...'

    song = "t105 l8 o5 q75 v100 " \
        "ab-> c4c4c4 c4.faf fedccc+dccdfdd c4. c4c4c4 c4.faf fedccc+dcccc< f>ccc< g>ccc< [e>c]2 [f>c]4 [b->d]2.^2 [b-]4 [ca]2[cb-]4 [fa]4 <f4>" \
        "r4 c4>c4r4< c4>c4r4< [cdf]4[cdf]4[cdf]4 [ce]4r4" \
        "r4 f>ccc< f>ccc< g>ccc< [e>c]2 [f>c]4 [b->d]2.^2 [b-]4 [ca]2[cb-]4 [fa]4 <f4>;" \

    song2 = "t120$l8 o4 v9rr g  g4  g+ a+4  d4  d4  d+2 d  c   g   g4 g+   a+4 d4 d4 d+2 rr g g4 g+ a+4 d4 d4 d+2 d c g g4 g+ a+4 d4 d4 d+2.;" \
           "t120$l8 o4 v9 rr d+ d+2 r  >a+4 a+4 <c2 >a+ g+ <d+ d+2 r  >a+4 a+4 a+2 rr d+ d+2 r >a+4 a+4 <c2 >a+ g+ <d+ d+2 r >a+4 a+4 a+2.;" \
           "t120$l8 o4 v9 rr c  c2  r  >f4  f4  g2  a+  g+ <c  c2 >f  f4   r   f g2< rr c c2 r >f4 f4 g2 a+ g+ <c c2 >f f4 r f g2.<;" \
           "t120$l8 o3 v8 >g+2.. g+ a+4. a+ <c2 >a+ g+2.. a+4 a+4 <c4. >d+ a+ g+2. g+ a+4. a+ <c2 >a+ g+2.. a+4 a+4 <r2." \

    #song = 't60 o3 l4 cdefgab<c> l8 cdefgab<c> l16 cdefgab l32 cdefgab'

    #song = '$ t120 o4 l4 e f+ b > c+ d < f+ e > c+  d c+ <e f+ b > c+ d < f+ e > c+  d c+'

    sec = mml.MMLWrapper()

    sec.load_string(song2)

    out = OutputHandler()

    pyaud = PyAudioModule()
    pyaud.special = True
    out.add_output(pyaud)

    # --== Instrument Selection: ==--
    # Uncomment the instrument you want to use!

    #osc = SineOscillator(freq=440.0)
    #osc = SquareOscillator(freq=440.0)
    osc = SawToothOscillator(freq=440.0)
    #osc = TriangleOscillator(freq=440.0)

    final = osc
    # --== End Instrument Selection! ==--

    # --== Other Output Options: ==--
    # Uncomment to write to a wav file:

    #wave = WaveModule('saw_test.wav')
    #out.add_output(wave)

    # --== End Other Output Options! ==--

    # --== ADSR Options: ==--
    # Configure the parameters for the ADSR envelope:

    attack = 10000000
    decay = 100000
    sustain = 0.2
    release = 5000000

    # Uncomment to enable the envelope:

    #env = ADSREnvelope(attack, decay, sustain, release)
    #env.bind(osc)
    #final = env

    # --== End ADSR Options! ==--

    amp = AmpScale()
    amp.bind(final)
    final = amp

    cont = out.bind_synth(final)

    sec.add_synth(cont)

    # Start output handler:

    out.start()

    # Start the sequencer:

    sec.start()
    sec.join()

    print("Done joining")

    print("Stopping sequencer...")

    sec.stop()

    print("Stopping output...")

    out.stop()

def delay():

    # Tests the delay function of OutputControl

    osc = TriangleOscillator(freq=440.0)

    out = OutputHandler()

    pyaud = PyAudioModule()
    pyaud.special = True
    out.add_output(pyaud)

    cont = out.bind_synth(osc)

    out.start()

    cont.start(time=3000000000 + get_time())

    cont.stop(time=5000000000 + get_time())

    time.sleep(8)

    out.stop()

def deepcopy():

    # Tests the deep copy of synths

    # OutputHandler:

    out = OutputHandler()

    # PyAudio module:

    pyaud = PyAudioModule()
    pyaud.special = True

    out.add_output(pyaud)

    osc = SineOscillator(freq=440.0)

    final = out.bind_synth(osc)

    # Make a deep copy:

    thing = copy.deepcopy(final)

def audio_param():

    # Tests the audio parameter as it alters the frequency of the pitch

    # Create a simple sine oscillator:

    osc = SineOscillator(freq=440)

    out = OutputHandler()

    pyaud = PyAudioModule()
    pyaud.special = True
    out.add_output(pyaud)

    sine = out.bind_synth(osc)

    out.start()

    # Start the oscillator:

    sine.start()

    # Have the frequency go up to 550 in 5 seconds:

    sine.info.freq.exponential_ramp(550.0, get_time()+5000000000)

    time.sleep(5)

    # Have the frequency go back down to 440 in 10 seconds:

    sine.info.freq.linear_ramp(440.0, get_time()+60000000000)

    sine.join()

    out.stop()

def test_output():

    # Creates and registers a oscillator. Used for testing output.

    osc1 = TriangleOscillator(freq=440.0)
    osc2 = TriangleOscillator(freq=880.0)
    osc3 = TriangleOscillator(freq=1320.0)
    osc4 = TriangleOscillator(freq=1760.0)

    out = OutputHandler()

    out.add_output(WaveModule("test.wav"))

    # Add the PyAudio module:

    pyaud = PyAudioModule()
    pyaud.special = True

    out.add_output(pyaud)

    # Add the WaveModule:

    # Bind the synth:

    final = out.bind_synth(osc1)
    final2 = out.bind_synth(osc2)
    final3 = out.bind_synth(osc3)
    final4 = out.bind_synth(osc4)

    # Start the OutputHandler:

    #out.start()

    # Start the synth:

    final.start()

    out.start()

    time.sleep(1)
    final2.start()

    time.sleep(1)
    final3.start()

    time.sleep(1)
    final4.start()

    time.sleep(1)

    final4.stop()
    time.sleep(1)
    final3.stop()
    time.sleep(1)
    final2.stop()
    time.sleep(3)
    final.stop()

    out.stop()

def module_connection():

    # Tests the connectivity features of modules

    mod1 = SineOscillator(freq=640.0)
    mod2 = DummyModule()
    mod3 = DummyModule()
    mod4 = DummyModule()

    mod2.bind(mod1)
    mod3.bind(mod2)
    mod4.bind(mod3)

    print("Connected modules: {}".format(mod4.info.connected))
    print("Should be 4!")

    print("Chain frequency: {}".format(mod4.info.freq))
    print("Should be 640.0!")

class DummyWait(BaseModule):

    """
    Passes values from the inputs attached,
    but continues to play for 5 seconds after we are released.
    """

    def __init__(self):

        super().__init__()

        self.finishing = False
        self.wait = 5000000000
        self.start_time = 0

    def start(self):

        self.finishing = False
        self.wait = 5000000000
        self.start_time = 0

    def finish(self):

        print("Dummy module finishing...")

        self.finishing = True

        self.start_time = get_time()

        print("Starting time: {}".format(self.start_time))

    def get_next(self):

        # Check if we are finishing

        if self.finishing:

            if get_time() > self.start_time + self.wait:

                # We are done, lets say we are finished:

                print("Dummy module done!")
                print("Current time: {}".format(get_time()))
                print("Target time: {}".format(self.start_time + self.wait))

                self.done()

                return None

        # Otherwise, lets just return the input:

        return self.get_input()

def fade_test():

    # Tests the ability for synths to continue to play after they have been stopped

    out = OutputHandler()

    pyaud = PyAudioModule()
    pyaud.special = True
    out.add_output(pyaud)

    osc = TriangleOscillator(freq=440.0)

    dummy = DummyWait()

    dummy.bind(osc)

    cont = out.bind_synth(dummy)

    sec = Sequencer()
    sec.add_synth(cont)

    print(cont.info.connected)
    print(cont.info.done)

    out.start()

    print("Starting controller...")

    cont.start()

    print("Waiting...")

    time.sleep(5)

    print("Stopping controller...")

    cont.stop()

    time.sleep(5)

    print(("Waiting..."))

    time.sleep(5)

    print("Synth should be stopped!")

    print("Starting synth...")

    cont.start()

    print("Waiting...")

    time.sleep(5)

    print("Stopping cont...")

    cont.stop()

    print("Waiting three seconds to interrupt...")

    time.sleep(3)

    print("Interrupting!")

    cont.start()

    cont.stop()

    print("Finished!")

    #sec.start()

def adsr_test():

    # Tests the ADSR envelope

    attack = 1000000000
    decay = 1000000000
    sustain = 0.5
    release = 1000000000

    # Create the OutputHandler:

    out = OutputHandler()

    pyaud = PyAudioModule()
    pyaud.special = True
    out.add_output(pyaud)

    osc = SawToothOscillator(freq=440.0)

    env = ADSREnvelope(attack, decay, sustain, release)

    env.bind(osc)

    cont = out.bind_synth(env)

    out.start()

    print("Starting:")

    cont.start()

    time.sleep(5)

    print("Stopping:")

    cont.stop()

    time.sleep(5)

def MIDI_test():

    # Tests if we can get MIDI info from ALSA

    out = OutputHandler()

    pyaud = PyAudioModule()
    pyaud.special = True
    out.add_output(pyaud)

    osc = SineOscillator(freq=440.0)
    #osc = SquareOscillator(freq=440.0)
    #osc = SawToothOscillator(freq=440.0)
    #osc = TriangleOscillator(freq=440.0)

    attack = 1000000000
    decay = 1000000000
    sustain = 0.2
    release = 1000000000

    env = ADSREnvelope(attack, decay, sustain, release)
    env.bind(osc)

    cont = out.bind_synth(env)

    seq = midi.MIDIWrapper()
    seq.alsa_live()

    seq.add_synth(cont)

    out.start()
    seq.start()

    seq.join()

    seq.stop()
    out.stop()


class edge():
  def __init__(self,src, nbr, weigh):
    self.src = src
    self.nbr = nbr
    self.weigh = weigh

graph = {}
v = int(input())
e = int(input())

for i in range(v):
  graph[i]=[]

for i in range(e):
  a, b, c= map(int, input().split())
  graph[a].append(edge(a, b, c))
  graph[b].append(edge(b, a, c))

visited= [-1]*v

class forbfs():
  def __init__(self, data, level):
    self.data = data
    self.level = level

def isbipartite(graph, s, visited):
  l = []

  l.append(forbfs(s, 0))

  while(len(l)!=0):
    p = l.pop(0)

    if(visited[p.data]!=-1):

      if(p.level!=visited[p.data]):

        return False

    visited[p.data] = p.level

    for i in graph[p.data]:

      if(visited[i.nbr]==-1):

        lvl = p.level + 1
        l.append(forbfs(i.nbr,lvl))

  return True

finalans = True

for i in range(v):

  if(visited[i]==-1):

    ans = isbipartite(graph, i, visited)

    if(ans ==False):
      finalans = False
      break

print("true") if(finalans) else print("false")


from django.contrib.gis.geos import Point, Polygon, GEOSGeometry
import requests
import pytest
import json

API_URL = "http://127.0.0.1:8000/api/buildings/"

@pytest.fixture
def building_data():
    return  {
        "geom": {
            "type": "Polygon",
            "coordinates": [
                [
                    [
                        5.0,
                        5.0
                    ],
                    [
                        5.0,
                        10.0
                    ],
                    [
                        10.0,
                        10.0
                    ],
                    [
                        10.0,
                        5.0
                    ],
                    [
                        5.0,
                        5.0
                    ]
                ]
            ]
        },
        "address": "CreatedFromTest3"
    }

def test_list_buildings():
    res = requests.get(API_URL + '')
    assert res.status_code == 200
    data = res.json()
    return data

@pytest.fixture
def get_big_distance_and_point():
    return (100000000, Point(0, 0))

@pytest.fixture
def get_big_distance_filtered_list(get_big_distance_and_point):
    res = requests.get(API_URL + '?dist={0}&&point={1},{2}'.
                       format(get_big_distance_and_point[0],
                              get_big_distance_and_point[1].x, get_big_distance_and_point[1].y))
    assert res.status_code == 200
    data = res.json()
    return data

@pytest.fixture
def get_full_building_list():
    return test_list_buildings()

#Testing that for 100000 km (100000000m) it will return all values
def test_distance_filter_big(get_big_distance_filtered_list, get_full_building_list):
    assert get_big_distance_filtered_list == get_full_building_list

@pytest.fixture
def get_zero_distance_and_point():
    return (0, Point(-5, -5, srid=4326))

@pytest.fixture
def get_zero_distance_filtered_list(get_zero_distance_and_point):
    res = requests.get(API_URL + '?dist={0}&&point={1},{2}'.
                       format(get_zero_distance_and_point[0],
                              get_zero_distance_and_point[1].x, get_zero_distance_and_point[1].y))
    assert res.status_code == 200
    data = res.json()
    return (data, get_zero_distance_and_point[1])

def test_distance_filter_zero(get_zero_distance_filtered_list, get_full_building_list):
    filtered = get_zero_distance_filtered_list[0]["features"]
    full = get_full_building_list["features"]
    point = get_zero_distance_filtered_list[1]
    for feature in filtered:
        geom = GEOSGeometry(json.dumps(feature['geometry']))
        #For zero distance each filtered geometry should cover this point
        assert geom.covers(point)

    #We count here from full list how many objects covers point
    cnt_test = 0
    for feature in full:
        geom = GEOSGeometry(json.dumps(feature['geometry']))
        #For zero distance each geometry should contain this point
        if geom.covers(point):
            cnt_test += 1
    cnt_api = len(filtered)
    #Checking that cnts of filtered object in api and in test are equal
    assert cnt_api == cnt_test

@pytest.mark.skip(reason="no need to check now")
def test_distance_filter(get_full_building_list):
    for i in range(10):
        dist = 10
        x = 0.0
        y = 0.0
        for j in range(10):
            res = requests.get(API_URL + '?dist={0}&&point={1},{2}'.
                           format(dist, x, y))
            assert res.status_code == 200
            data = res.json()
            x += 2
            y += 2
        dist *= 10

def test_distance_filter(get_full_building_list):
    res = requests.get(API_URL + '?dist={0}&&point={1},{2}'.
                       format(5, 5, 5))

    assert res.status_code == 200
    # if filter args are incorrect, should return all
    res = requests.get(API_URL + '?&point={0},{1}'.
                       format(5, 5))
    assert res.status_code == 200
    data = res.json()
    data == get_full_building_list

    #if filter args are incorrect, should return all
    res = requests.get(API_URL + '??dist=&point={0},{1}'.
                       format(5, 5))
    assert res.status_code == 200
    data = res.json()
    data == get_full_building_list

@pytest.fixture
def post_new_polygon():
    x = 0
    y = 1
    d = {"geom": {"type": '', "coordinates": ''}}
    # area is 1/2 square degree or ~ 6160500000 square meters
    p = Polygon(((x, x), (y, y), (x, y), (x, x)), srid=4326)
    d["geom"]["type"] = p.geom_type
    d["geom"]["coordinates"] = p.coords
    res = requests.post(API_URL + '', json=d)
    assert res.status_code == 201
    newBuildingData = res.json()
    return newBuildingData

def test_distance_filtel_value(post_new_polygon):

    id = post_new_polygon["id"]

    #point is 1 degree distance or ~ 111000
    res = requests.get(API_URL + '?dist=100000&point=0,2.0')
    filteredData = res.json()
    assert res.status_code == 200
    assert post_new_polygon not in filteredData["features"]

    res = requests.get(API_URL + '?dist=200000&point=0,2.0')
    filteredData = res.json()
    assert res.status_code == 200
    assert post_new_polygon in filteredData["features"]

    res = requests.delete(API_URL + str(id))
    assert res.status_code == 204
    return

#print(Distance(Point(0,0,srid=27700),(Point(1,0,srid=27700))).


global state_machine
global state_machine_flag
global bck_to_login

global ch_b
global cont
global sh_pt
global sh_gpt
global s_t
global op_c
global p_s

global connector_y_n
global lk_y_n
global ch_y_n

global buzz_on_off
global ext_pt_on_off
global cut_on_off
global lbl_y_n
global no_of_lbl
global bar_y_n
global two_stage_y_n
global no_1
global no_2
global no_3
global gbl_set
global lrn_hrn
global lrn_2_hrn
global clr_table
global no_of_labels
global login_flag
global diag_page_flag
global cable_change_flag
global combo_click
global op_no
global user_1,user_1_pw
global user_2,user_2_pw
global username
global Global_Settings_File

user_1=''
user_1_pw=''
user_2=''
user_2_pw=''
username=''
combo_click=0
cable_change_flag=0
diag_page_flag=0
login_flag=0

no_of_labels=1
lrn_hrn=1
lrn_2_hrn=1
clr_table=1
gbl_set=1
no_1=1
no_2=1
no_3=1
buzz_on_off=1
cut_on_off=1
ext_pt_on_off=1
lbl_y_n=1
no_of_lbl=1
bar_y_n=1
two_stage_y_n=1

connector_y_n=1
lk_y_n=1
ch_y_n=1

ch_b=1
cont=1
sh_pt=1
sh_gpt=1
s_t=1
op_c=1
p_s=1

state_machine=1
state_machine_flag=1
bck_to_login=0


import sys

import cv2
import matplotlib.pyplot as plt
print(cv2.__version__)
path = '../main/big_data/lecture/week9/data/cat.bmp'
img = cv2.imread(path)
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.show()

if img is None:
    print('image load failed')
    sys.exit()

cv2.namedWindow('image')
cv2.imshow('image',img)
cv2.waitKey()
cv2.destroyAllWindows()
# cv2.destroyWindow('image')
# img write
cv2.imwrite('../main/big_data/lecture/week9/data/cat.png',img)

#
path = '../main/big_data/lecture/week9/data/cat.bmp'
img = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
plt.imshow(img)
plt.imshow(img,cmap='gray')
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.show()
img.shape

if img is None:
    print('image load failed')
    sys.exit()

# 확장자 변경
# img : bmp file
cv2.imwrite('../main/big_data/lecture/week9/data/cat_gray.png',img)

path = '../main/big_data/lecture/week9/data/cat_gray.png'
img = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
cv2.imshow('../main/big_data/lecture/week9/data/cat_gray.png',img)
cv2.waitKey()
cv2.destroyAllWindows()

#
path = '../main/big_data/lecture/week9/data/cat.bmp'
img = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
cv2.imshow('image',img)
cv2.waitKey()

# 키 할당
while True:
    if cv2.waitKey() == ord('q'):
        cv2.destroyAllWindows()
        print(1)
        break

imgBGR = cv2.imread(path)
imgRGB = cv2.cvtColor(imgBGR,cv2.COLOR_BGR2RGB)
plt.axis('off')
plt.imshow(imgRGB)
plt.imshow(imgBGR)

img_gray = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
plt.axis('off')
plt.imshow(img_gray,cmap='gray')

plt.subplot(121)
plt.axis('off')
plt.imshow(imgRGB)
plt.subplot(122)
plt.axis('off')
plt.imshow(img_gray,cmap='gray')


# "Eugene Morozov"<Eugene ~at~ HiEugene.com>

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from util import get_color
import time

def plotX(X, mu, M, N, K, r, ax):
  for i in range(M):
    if plotX.px[i]: plotX.px[i].remove()
    if N == 2:
      plotX.px[i] = ax.scatter(X[i,0], X[i,1], color=get_color(r[i]), marker="o")
    else:
      plotX.px[i] = ax.scatter(X[i,0], X[i,1], X[i,2], color=get_color(r[i]), marker="o")
  for i in range(K):
    if plotX.pmu[i]: plotX.pmu[i].remove()
    if N == 2:
      plotX.pmu[i] = ax.scatter(mu[i,0], mu[i,1], color=get_color(i+K), marker="*", linewidths=5)
    else:
      plotX.pmu[i] = ax.scatter(mu[i,0], mu[i,1], mu[i,2], color=get_color(i+K), marker="*", linewidths=5)

def calc_dist(x, y):
  d = ((x - y)**2).sum() # sqrt omitted
  return d

def K_means(X, K, v, title_str):
  M, N = X.shape # M samples of dimension N
  r = np.zeros(M, dtype="int") # cluster id for each point

  mu_new = np.empty([K,N])
  for i in range(K):
    mu_new[i,:] = X[i*M//K,:]
  mu = np.zeros([K,N])

  if v and (N==2 or N==3):
    plotX.px = [None]*M
    plotX.pmu = [None]*K
    fig = plt.figure()
    if N == 2:
      ax = fig.gca()
    else:
      ax = fig.gca(projection='3d')
    plt.ion()
    plt.grid(True)
    plt.show()

  # while np.abs(mu_new - mu).sum() > 1e-10: # or track when the assignments no longer change
  while calc_dist(mu_new, mu) > 1e-10: # or track when the assignments no longer change
    if v and (N==2 or N==3):
      plotX(X, mu_new, M, N, K, r, ax)
      # ax.set_title(f"diff = {np.abs(mu_new - mu).sum()}")
      ax.set_title(f"diff = {calc_dist(mu_new, mu)}")
      fig.canvas.flush_events(); time.sleep(0.5)
    mu = mu_new.copy()
    for i in range(M):
      min_dist = 1e10
      r[i] = 0
      for k in range(K):
        dist = calc_dist(X[i,:], mu[k,:])
        if dist < min_dist:
          min_dist = dist
          r[i] = k

    for k in range(K):
      mu_new[k] = X[r==k,:].sum(axis=0) / X[r==k,:].shape[0]
  if v and (N==2 or N==3):
    ax.set_title(title_str)
    fig.canvas.flush_events(); time.sleep(0.5)
  return r


from data_handler import DataHandler
from scanner import Scanner
from datetime import datetime
from queue import Queue
from threading import Thread
import sys

def printStats(devices_count, sensor_type):
    time = datetime.now().strftime("%H:%M:%S")
    print("%s | %d {:>4} devices found.".format(
        sensor_type) % (time, devices_count))

def queueScans(scanner):
    jobs = Queue()
    threads_list = list()

    t1 = Thread(target=lambda q: q.put(
        scanner.count_bt_devices()), args=(jobs,))
    t1.daemon = True  # Kill thread on exit
    t1.start()
    threads_list.append(t1)

    t2 = Thread(target=lambda q: q.put(
        scanner.count_wifi_devices()), args=(jobs,))
    t2.daemon = True  # Kill thread on exit
    t2.start()
    threads_list.append(t2)

    # Join threads
    for t in threads_list:
        t.join()
        # t.keepRunning = False

    scan_results = []

    # Get return values from threads
    while not jobs.empty():
        result = jobs.get()
        scan_results.append(result)
    return scan_results

def main():
    scanner = Scanner()
    data_handler = DataHandler()

    while True:
        try:
            data = queueScans(scanner)
            bt_devices_count = data[0]
            wifi_devices_count = data[1]

            sensor_type = "bt"
            printStats(bt_devices_count, sensor_type)
            # data_handler.send_data(bt_devices_count, sensor_type)
            data_handler.save_data(bt_devices_count, sensor_type)

            sensor_type = "wifi"
            printStats(wifi_devices_count, sensor_type)
            # data_handler.send_data(wifi_devices_count, sensor_type)
            data_handler.save_data(wifi_devices_count, sensor_type)

        except (KeyboardInterrupt, SystemExit):
            sys.exit()

if __name__ == "__main__":
    main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 26 11:46:50 2023
@author: BD

Evaluate and plot the effect of package color on the win rate
"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def draw_it(i):
    ax.errorbar(x[i], MC_mean[i], yerr=uncertainty[i], fmt='o', elinewidth=2,\
                ms=5, color='black', zorder=0)
    ax.plot(x[i]-0.1, MC_mean[i], marker='>', ms=5, color='black', zorder=0)
    ax.plot(x[i]+0.1, MC_mean[i], marker='<', ms=5, color='black', zorder=0)

    ax.errorbar(x[i], MC_mean[i], yerr=uncertainty[i]*0.99, fmt='o', elinewidth=1.5,\
                ms=1, color=color_codes[i], zorder=1)
    ax.plot(x[i], MC_mean[i], marker='o', ms=5, color='black', zorder=2)
    ax.plot(x[i], MC_mean[i], marker='o', ms=4, color=color_codes[i], zorder=3)
    ax.plot(x[i]-0.1, MC_mean[i], marker='>', ms=4, color=color_codes[i], zorder=2)
    ax.plot(x[i]+0.1, MC_mean[i], marker='<', ms=4, color=color_codes[i], zorder=2)

if __name__ == '__main__':
    path = ''
    # Read in the table
    tbl = pd.read_csv(path+'candy_data_extended.csv')

    # The list of all colors and their color codes (thank you chatGPT)
    # cyan is used when there are many colors or no colors (placebo)
    colors = np.unique(tbl['main color'])
    color_codes = ['#00FFFF', 'k', 'b', '#8B4513', 'y', 'gray', 'g', '#00FFFF',\
                  '#FFA500', '#FFC0CB', 'purple', 'r', 'w', '#FFD700']

    # Calculate the mean
    # Calculate the uncertainty of the mean as the rms/sqrt(N)
    MC_mean = []
    MC_std = []
    N = []
    for color in colors:
        MC_mean.append(np.mean(tbl['winpercent'][tbl['main color']==color]))
        MC_std.append(np.std(tbl['winpercent'][tbl['main color']==color]))
        N.append(len(tbl[tbl['main color']==color]))
    uncertainty = MC_std/np.sqrt(N)

    # Plot the results
    x = range(len(colors))

    plt.figure(figsize=(7,4))
    ax = plt.subplot(111)
    for i in range(len(N)):
        draw_it(i)
        ax.text(x[i]-0.1, 32, N[i])

    ax.text(-0.85, 32, 'N =')
    ax.set_xticks(range(len(colors)), colors, rotation=90)
    ax.set_ylabel('win [%]')
    ax.set_xlim([-1,len(colors)])

    plt.tight_layout()
    plt.savefig(path+'package_colors.pdf')


import array
import fcntl
import os
import re
import subprocess
import time
from multiprocessing import cpu_count
from tempfile import mkstemp
from termios import FIONREAD

from catkin_tools.common import log
from catkin_tools.common import version_tuple
from catkin_tools.terminal_color import ColorMapper

mapper = ColorMapper()
clr = mapper.clr

def memory_usage():
    """
    Get used and total memory usage.

    :returns: Used and total memory in bytes
    :rtype: tuple
    """

    # Handle optional psutil support
    try:
        import psutil

        psutil_version = version_tuple(psutil.__version__)
        if psutil_version < (0, 6, 0):
            usage = psutil.phymem_usage()
            used = usage.used
        else:
            usage = psutil.virtual_memory()
            used = usage.total - usage.available

        return used, usage.total

    except ImportError:
        pass

    return None, None

JOBSERVER_SUPPORT_MAKEFILE_OLD = b'''
all:
\techo $(MAKEFLAGS) | grep -- '--jobserver-fds'
'''

JOBSERVER_SUPPORT_MAKEFILE = b'''
all:
\techo $(MAKEFLAGS) | grep -- '--jobserver-auth'
'''

def test_gnu_make_support_common(makefile_content):
    """
    Test if "make -f MAKEFILE -j2" runs successfully when MAKEFILE
    contains makefile_content.
    """

    fd, makefile = mkstemp()
    os.write(fd, makefile_content)
    os.close(fd)

    ret = subprocess.call(['make', '-f', makefile, '-j2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    os.unlink(makefile)
    return ret == 0

def test_gnu_make_support_old():
    """
    Test if the system 'make' supports the job server implementation.

    This simply checks if the `--jobserver-fds` option is supported by the
    `make` command. It does not tests if the jobserver is actually working
    properly.
    """

    return test_gnu_make_support_common(JOBSERVER_SUPPORT_MAKEFILE_OLD)

def test_gnu_make_support():
    """
    Test if the system 'make' supports the job server implementation.

    This simply checks if the `--jobserver-auth` option is supported by the
    `make` command. It does not tests if the jobserver is actually working
    properly.
    """

    return test_gnu_make_support_common(JOBSERVER_SUPPORT_MAKEFILE)

class GnuMake(object):
    def __init__(self):
        if test_gnu_make_support():
            self.make_args = lambda job_pipe: ["--jobserver-auth=%d,%d" % JobServer._job_pipe]
        elif test_gnu_make_support_old():
            self.make_args = lambda job_pipe: ["--jobserver-fds=%d,%d" % JobServer._job_pipe, "-j"]
        else:
            self.make_args = None

    def is_supported(self):
        return not (self.make_args is None)

class JobServer(object):
    # Whether the job server has been initialized
    _initialized = False

    # Flag designating whether the `make` program supports the GNU Make
    # jobserver interface
    _gnu_make = None

    # Initialize variables
    _load_ok = True
    _mem_ok = True
    _internal_jobs = []
    _max_load = 0
    _max_jobs = 0
    _job_pipe = os.pipe()

    # Setting fd inheritance is required in Python > 3.4
    # This is set by default in Python 2.7
    # For more info see: https://docs.python.org/3.4/library/os.html#fd-inheritance
    if hasattr(os, 'set_inheritable'):
        for fd in _job_pipe:
            os.set_inheritable(fd, True)
            if not os.get_inheritable(fd):
                log(clr('@{yf}@!Warning: jobserver file descriptors are not inheritable.@|'))

    @classmethod
    def _set_max_jobs(cls, max_jobs):
        """Set the maximum number of jobs to be used with the jobserver.

        This will wait for all active jobs to be completed, then re-initialize the job pipe.
        """

        # Read all possible tokens from the pipe
        try:
            os.read(cls._job_pipe[0], cls._max_jobs)
        except (BlockingIOError, InterruptedError):
            pass

        # Update max jobs
        cls._max_jobs = max_jobs

        # Initialize the pipe with max_jobs tokens
        for i in range(cls._max_jobs):
            os.write(cls._job_pipe[1], b'+')

    @classmethod
    def _set_max_mem(cls, max_mem):
        """
        Set the maximum memory to keep instantiating jobs.

        :param max_mem: String describing the maximum memory that can be used
        on the system. It can either describe memory percentage or absolute
        amount.  Use 'P%' for percentage or 'N' for absolute value in bytes,
        'Nk' for kilobytes, 'Nm' for megabytes, and 'Ng' for gigabytes.
        :type max_mem: str
        """

        if max_mem is None:
            cls._max_mem = None
            return
        elif type(max_mem) is float or type(max_mem) is int:
            mem_percent = max_mem
        elif type(max_mem) is str:
            m_percent = re.search(r'([0-9]+)\%', max_mem)
            m_abs = re.search(r'([0-9]+)([kKmMgG]{0,1})', max_mem)

            if m_percent is None and m_abs is None:
                cls._max_mem = None
                return

            if m_percent:
                mem_percent = m_abs.group(1)
            elif m_abs:
                val = float(m_abs.group(1))
                mag_symbol = m_abs.group(2)

                _, total_mem = memory_usage()

                if mag_symbol == '':
                    mag = 1.0
                elif mag_symbol.lower() == 'k':
                    mag = 1024.0
                elif mag_symbol.lower() == 'm':
                    mag = pow(1024.0, 2)
                elif mag_symbol.lower() == 'g':
                    mag = pow(1024.0, 3)

                mem_percent = 100.0 * val * mag / total_mem

        cls._max_mem = max(0.0, min(100.0, float(mem_percent)))

    @classmethod
    def _check_load(cls):
        if cls._max_load is not None:
            try:
                load = os.getloadavg()
                if load[0] < cls._max_load:
                    cls._load_ok = True
                else:
                    cls._load_ok = False
            except NotImplementedError:
                cls._load_ok = True

        return cls._load_ok

    @classmethod
    def _check_mem(cls):
        if cls._max_mem is not None:
            mem_used, mem_total = memory_usage()
            mem_percent_used = 100.0 * float(mem_used) / float(mem_total)
            if mem_percent_used > cls._max_mem:
                cls._mem_ok = False
            else:
                cls._mem_ok = True

        return cls._mem_ok

    @classmethod
    def _check_conditions(cls):
        return (cls._check_load() and cls._check_mem()) or cls._running_jobs() == 0

    @classmethod
    def _acquire(cls):
        """
        Obtain a job server token. Be sure to call _release() to avoid
        deadlocks.
        """
        try:
            # read a token from the job pipe
            token = os.read(cls._job_pipe[0], 1)
            return token
        except (BlockingIOError, InterruptedError):
            pass

        return None

    @classmethod
    def _release(cls):
        """
        Write a token to the job pipe.
        """
        os.write(cls._job_pipe[1], b'+')

    @classmethod
    def _running_jobs(cls):

        try:
            buf = array.array('i', [0])
            if fcntl.ioctl(cls._job_pipe[0], FIONREAD, buf) == 0:
                return cls._max_jobs - buf[0]
        except (NotImplementedError, OSError):
            pass

        return cls._max_jobs

def initialized():
    """Return True if the job server has been initialized."""
    return JobServer._initialized

def initialize(max_jobs=None, max_load=None, max_mem=None, gnu_make_enabled=False):
    """
    Initialize the global GNU Make jobserver.

    :param max_jobs: the maximum number of jobs available
    :param max_load: do not dispatch additional jobs if this system load
    value is exceeded
    :param max_mem: do not dispatch additional jobs if system physical
    memory usage exceeds this value (see _set_max_mem for additional
    documentation)
    :param gnu_make_enabled: Set gnu make compatibility enabled
    """

    # Check initialization
    if JobServer._initialized is True:
        return

    # Check if the jobserver is supported
    if JobServer._gnu_make is None:
        JobServer._gnu_make = GnuMake()

    if not JobServer._gnu_make.is_supported():
        log(clr('@!@{yf}WARNING:@| Make job server not supported. The number of Make '
                'jobs may exceed the number of CPU cores.@|'))

    # Set gnu make compatibility enabled
    JobServer._gnu_make_enabled = gnu_make_enabled

    # Set the maximum number of jobs
    if max_jobs is None:
        try:
            max_jobs = cpu_count()
        except NotImplementedError:
            log('@{yf}WARNING: Failed to determine the cpu_count, falling back to 1 jobs as the default.@|')
            max_jobs = 1
    else:
        max_jobs = int(max_jobs)

    JobServer._set_max_jobs(max_jobs)
    JobServer._max_load = max_load
    JobServer._set_max_mem(max_mem)

    JobServer._initialized = True

def load_ok():
    return JobServer._load_ok

def mem_ok():
    return JobServer._mem_ok

def set_max_mem(max_mem):
    """
    Set the maximum memory to keep instantiating jobs.

    :param max_mem: String describing the maximum memory that can be used on
    the system. It can either describe memory percentage or absolute amount.
    Use 'P%' for percentage or 'N' for absolute value in bytes, 'Nk' for
    kilobytes, 'Nm' for megabytes, and 'Ng' for gigabytes.
    :type max_mem: str
    """

    JobServer._set_max_mem(max_mem)

def wait_acquire():
    """
    Block until a job server token is acquired, then return it.
    """

    token = None

    while token is None:
        # make sure we're observing load and memory maximums
        if not JobServer._check_conditions():
            time.sleep(0.01)
            continue

        # try to get a job token
        token = JobServer._acquire()

    return token

def acquire():
    """
    Block until a job server token is acquired, then return it.
    """

    token = None

    # make sure we're observing load and memory maximums
    if JobServer._check_conditions():
        # try to get a job token
        token = JobServer._acquire()

    return token

def add_label(label):
    JobServer._internal_jobs.append(label)

def del_label(label):
    JobServer._internal_jobs.remove(label)

def try_acquire_gen():
    """
    Yield None until a job server token is acquired, then yield it.
    """
    while True:
        # make sure we're observing load and memory maximums
        if JobServer._check_conditions() and running_jobs() < max_jobs():
            # try to get a job token
            token = JobServer._acquire()
            yield token
        else:
            yield None

def try_acquire():
    """
    Try to acquire a job token, return None if not available.
    """
    # make sure we're observing load and memory maximums
    if JobServer._check_conditions() and running_jobs() < max_jobs():
        # try to get a job token
        token = JobServer._acquire()
        return token

    return None

def release(label=None):
    """
    Release a job server token.
    """
    JobServer._release()
    if label is not None:
        del_label(label)

def gnu_make_enabled():
    return JobServer._gnu_make.is_supported() and JobServer._gnu_make_enabled

def gnu_make_args():
    """
    Get required arguments for spawning child gnu Make processes.
    """

    if JobServer._gnu_make_enabled:
        return JobServer._gnu_make.make_args(JobServer._job_pipe)
    else:
        return []

def max_jobs():
    """
    Get the maximum number of jobs.
    """

    return JobServer._max_jobs

def running_jobs():
    """
    Try to estimate the number of currently running jobs.
    """

    if not gnu_make_enabled():
        return 0

    return JobServer._running_jobs()

def internal_jobs():
    return JobServer._internal_jobs

class JobGuard:

    """
    Context manager representing a jobserver job.
    """

    def __enter__(self):
        wait_acquire()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        release()
        return False


import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

fig = plt.figure()
ax = fig.add_subplot()
x_data = np.linspace(-10, 10, 100)
sinx = np.sin(x_data)
cosx = np.cos(x_data)
ax.set_xlim(-10, 10)
ax.set_ylim(2, -2)
line1, = plt.plot(x_data, sinx)
line2, = plt.plot(x_data, cosx)
def next_frame(frame_number):
    i = frame_number/10
    line1.set_ydata(np.sin(x_data*i))
    line2.set_ydata(np.cos(x_data/np.sqrt(i)))

ani = FuncAnimation(fig, func=next_frame, interval=50)

plt.show()


import os

from expyriment import control, design, misc, io, stimuli
from expyriment.design.extras import StimulationProtocol

# SETTINGS
REPETITIONS = 25  # times 4 is total
TR = 2.0
SCAN_TRIGGER = misc.constants.K_5
SCAN_TRIGGER_LTP_ADDRESS = None  # None = USB (keyboard emulation)
BB_SERIAL_PORT_ADDRESS = None  # None = USB (keyboard emulation)
RESPONSE_LEFT = 49
RESPONSE_RIGHT = 50

# DESIGN
exp = design.Experiment("Stroop Task (Colour)")
exp.add_data_variable_names(["TrialID, Condition, Text, Colour, Key, RT, Correct"])
control.initialize(exp)

out_protocol = StimulationProtocol("time")
out_protocol.add_condition("congruent")
out_protocol.add_condition("incongruent")
out_protocol.add_condition("error")

fixcross = stimuli.FixCross()
fixcross.preload()

main = design.Block()
for r in range(REPETITIONS):
    for name in ("RED",
                 "GREEN"):
        for colour in (misc.constants.C_RED,
                       misc.constants.C_GREEN):
            trial = design.Trial()
            if (name == "RED" and colour == misc.constants.C_RED) or \
               (name == "GREEN" and colour == misc.constants.C_GREEN):
                trial.set_factor("Condition", "congruent")
            else:
                trial.set_factor("Condition", "incongruent")
            stim = stimuli.TextLine(name,
                                    text_size=70,
                                    text_font="monospace",
                                    text_colour=colour)
            stim.preload()
            trial.add_stimulus(stim)
            main.add_trial(trial)
main.shuffle_trials()
exp.add_block(main)

# IO
trigger = exp.keyboard  # For USB (keyboad emulation) trigger
#trigger = io.TriggerInput(io.ParallelPort(SCAN_TRIGGER_LTP_ADDRESS))  # For LTP trigger
bb = exp.keyboard  # For USB (keyboard emulation) responses
# bb = io.EventButtonBox(io.SerialPort(BB_SERIAL_PORT_ADDRESS))  # For serial port button box

# RUN
control.start()

in_protocol = StimulationProtocol("time")
in_protocol.import_from_brainvoyager(os.path.join(
    "timings",
    "S{0}.prt".format(str(exp.subject).zfill(2))))
exp.blocks[0] = in_protocol.get_as_experimental_block(block=exp.blocks[0])

stimuli.TextScreen(
    "Instructions",
    "Respond left for green colour, right for red colour.").present()
bb.wait()
stimuli.TextLine("Waiting for trigger...").present()
trigger.wait(SCAN_TRIGGER)  # Initial scanner sync
exp.clock.reset_stopwatch()
for trial in exp.blocks[0].trials:
    fixcross.present()
    trial.preload_stimuli()
    while exp.clock.stopwatch_time < trial.get_factor("begin") - (TR / 2) * 1000:
        pass
    trigger.wait(SCAN_TRIGGER)  # Sync scanner for each trial
    trial.stimuli[0].present()
    start = exp.clock.stopwatch_time
    key, rt = bb.wait([RESPONSE_LEFT, RESPONSE_RIGHT],
        duration=trial.get_factor("end") - trial.get_factor("begin"))
    fixcross.present()
    correct = True
    if rt is None:
        rt = 1500
        correct = False
    if (trial.stimuli[0].text_colour == misc.constants.C_GREEN and \
        key != RESPONSE_LEFT) or \
       (trial.stimuli[0].text_colour == misc.constants.C_RED and \
        key != RESPONSE_RIGHT):
        correct = False
    if correct:
        out_protocol.add_event(trial.get_factor("Condition"), start, start + rt)
    else:
        out_protocol.add_event("error", start, start + rt)
    exp.data.add([trial.id, trial.get_factor("Condition"),
        trial.stimuli[0].text, trial.stimuli[0].text_colour, key, rt, correct])
    trial.unload_stimuli()
fixcross.present()
exp.clock.wait(12500)

if not os.path.isdir("protocols"):
    os.mkdir("protocols")
out_protocol.export_to_brainvoyager(
        exp.name,
        "protocols"+os.path.sep+exp.name+"_"+"S"+repr(exp.subject).zfill(2))

control.end()


# 4
# 1 2 3 4
# 5 6 7 8
# 9 10 11 12
# 13 14 15 16

def solution(matrix, n):
    if n <= 1:
        return matrix
    i, j = 0, n - 1
    while i < j:
        #  如果转多了，可能又转回去了
        for k in range(j - i):
            tmp = matrix[i][i + k]
            matrix[i][i + k] = matrix[j - k][i]
            matrix[j - k][i] = matrix[j][j - k]
            matrix[j][j - k] = matrix[i + k][j]
            matrix[i + k][j] = tmp
        i += 1
        j -= 1
    return matrix

if __name__ == '__main__':
    matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

    ans = solution(matrix, 4)

    # print(ans)


#!/usr/bin/python

import numpy as np
import copy
import time
import itertools

from sim import *
from scenario import *
from AStarAlgo import aStar, clearcache

def parse_env(env):
    fires = []
    lakes = []
    #print(env)
    for value in env:
        x, y, z = value
        x = np.float(x)
        y = np.float(y)
        z = np.float(z)
        #print(x, y, z)
        if env[value] == "orange":
            fires.append(np.array([x, y + 2, z]))
        if env[value] == "blue":
            lakes.append(np.array([x, y + 1, z]))
        if env[value] == "drone":
            fires.insert(0, np.array([x, y, z]))

    graph = []
    for i, fire1 in enumerate(fires):
        vertex = []
        for j, fire2 in enumerate(fires):
            edge = {}
            edge['start'] = fire1
            edge['dist'] = np.inf
            edge['end'] = fire1
            edge['path'] = []
            edge['path'].append(fire2)
            if i == j:
                edge['lake'] = None
                vertex.append(edge)
                continue

            for k, lake in enumerate(lakes):
                #print(i, j, k)
                #dist1 = len(aStar(tuple(fire1), tuple(lake), env))
                #dist2 = len(aStar(tuple(lake), tuple(fire2), env))
                dist1 = np.linalg.norm(fire1 - lake)
                dist2 = 2 * np.linalg.norm(lake - fire2)
                #num_edges += 1
                if (dist1 + dist2) < edge['dist']:
                    edge['dist'] = dist1 + dist2
                    edge['lake'] = lake
                    edge['fire'] = fire2
            #print(vertex)
            vertex.append(edge)
        graph.append(vertex)
    #print(graph, fires, lakes)
    return (graph, fires, lakes)

def pick_neighbors(graph, start_vertex_id, max_dist, max_num_vertices):
    vertex = graph[start_vertex_id]
    short_list = []
    num_vertices = 1
    short_list.append(start_vertex_id)
    for i, edge in enumerate(vertex):
        if edge['dist'] > max_dist:
            continue
        short_list.append(i)
        num_vertices += 1
        if num_vertices >= max_num_vertices:
            break
    return short_list

def pick_farthest_neighbor(graph, cur_vertex_id):
    farthest_vertex_id = 0
    farthest_dist = 0
    vertex = graph[cur_vertex_id]
    for i, edge in enumerate(vertex):
        if edge['dist'] == np.inf:
            continue
        if edge['dist'] > farthest_dist:
            farthest_dist = edge['dist']
            farthest_vertex_id = i
    #print(farthest_vertex_id)
    return farthest_vertex_id

def mark_vertices_covered(graph, short_list):
    for vertex_id in short_list:
        #vertex = graph[vertex_id]
        #for edge in vertex:
        #    edge['dist'] = np.inf
        for vertex in graph:
            vertex[vertex_id]['dist'] = np.inf
    #print(graph)
    if len(short_list) == 1:
        return graph
    for vertex_id in short_list[1:]:
        graph[vertex_id][vertex_id]['path'] = None
    return graph

def find_shortest_path(graph, short_list):
    shortest_path = []
    shortest_dist = np.inf
    if (short_list[0] == 0):
        start_vertex_id = short_list[0]
        for path in itertools.permutations(short_list[1:]):
            prev_vertex_id = start_vertex_id
            cur_dist = 0
            for vertex_id in path:
                cur_dist += graph[prev_vertex_id][vertex_id]['dist']
                prev_vertex_id = vertex_id
            if cur_dist < shortest_dist:
                shortest_path = copy.deepcopy(list(path))
                shortest_dist = cur_dist
        shortest_path.insert(0, start_vertex_id)
    else:
        for path in itertools.permutations(short_list):
            prev_vertex_id = path[0]
            cur_dist = 0
            for vertex_id in path[1:]:
                cur_dist += graph[prev_vertex_id][vertex_id]['dist']
                prev_vertex_id = vertex_id
            if cur_dist < shortest_dist:
                shortest_path = copy.deepcopy(list(path))
                shortest_dist = cur_dist
    return shortest_path

def populate_path_with_lakes(graph, path):
    path_with_lakes = []
    #final_path.append(fires[0])
    prev_vertex_id = path[0]
    path_with_lakes.extend(graph[prev_vertex_id][prev_vertex_id]['path'])
    for vertex_id in path[1:]:
        path_with_lakes.append(graph[prev_vertex_id][vertex_id]['lake'])
        path_with_lakes.extend(graph[prev_vertex_id][vertex_id]['path'])
        #print(path_with_lakes)
        prev_vertex_id = vertex_id
    #print(final_path)
    return path_with_lakes

def reconstruct_graph(graph, lakes):
    new_graph = []
    for i, v1 in enumerate(graph):
        if v1[i]['path'] == None:
            continue
        vertex = []
        for j, v2 in enumerate(graph):
            if v2[j]['path'] == None:
                continue
            edge = {}
            edge['start'] = v1[i]['start']
            edge['dist'] = np.inf
            edge['end'] = v1[i]['path'][-1]
            edge['path'] = copy.deepcopy(v2[j]['path'])
            if i == j:
                edge['lake'] = None
                vertex.append(edge)
                continue

            for k, lake in enumerate(lakes):
                #print(i, j, k)
                #dist1 = len(aStar(tuple(fire1), tuple(lake), env))
                #dist2 = len(aStar(tuple(lake), tuple(fire2), env))
                dist1 = np.linalg.norm(v1[i]['path'][-1] - lake)
                dist2 = 2 * np.linalg.norm(lake - v2[j]['path'][0])
                #num_edges += 1
                if (dist1 + dist2) < edge['dist']:
                    edge['dist'] = dist1 + dist2
                    edge['lake'] = lake
                    edge['fire'] = v2[j]['path'][0]
            #print(vertex)
            vertex.append(edge)
        new_graph.append(vertex)
    #print(graph, fires, lakes)
    return new_graph

def form_clusters(graph, max_dist, max_num_vertices, lakes):
    num_nodes_covered = 0
    num_clusters = 0
    start_vertex_id = 0
    while num_nodes_covered < len(graph):
        short_list = pick_neighbors(graph, start_vertex_id, max_dist, max_num_vertices)
        if (len(short_list) > 1):
            shortest_path = find_shortest_path(graph, short_list)
            shortest_path_with_lakes = populate_path_with_lakes(graph, shortest_path)
            #if num_clusters % 2 == 0:
            graph[shortest_path[0]][shortest_path[0]]['path'] = copy.deepcopy(shortest_path_with_lakes)
            #print("Clustered Nodes", num_clusters)
            #print(shortest_path)
            #print(graph[shortest_path[0]][shortest_path[0]]['path'])
            graph = mark_vertices_covered(graph, shortest_path)
            start_vertex_id = pick_farthest_neighbor(graph, shortest_path[-1])
            #else:
            #    graph[shortest_path[-1]][shortest_path[-1]]['path'] = copy.deepcopy(list(reversed(shortest_path_with_lakes)))
            #    graph = mark_vertices_covered(graph, short_list)
            #    start_vertex_id = pick_farthest_neighbor(graph, shortest_path[0])
        else:
            graph = mark_vertices_covered(graph, short_list)
            start_vertex_id = pick_farthest_neighbor(graph, short_list[0])
            #print("Clustered Nodes", num_clusters)
            #print(short_list)
            #print(graph[short_list[0]][short_list[0]]['path'])
        num_nodes_covered += len(short_list)
        num_clusters += 1
        #print(num_nodes_covered, num_clusters)
        #print(start_vertex_id)
    #print("Number of Clusters", num_clusters)
    graph = reconstruct_graph(graph, lakes)
    return (graph, num_clusters)

def shortest(env):
    orig_graph, orig_fires, orig_lakes = parse_env(env)
    #print("Orig_Graph", orig_graph)
    #print("Orig_Lakes", orig_lakes)
    #print("Orig_Fires", orig_fires)
    graph = copy.deepcopy(orig_graph)
    max_dist = 64
    max_num_vertices = 10
    while True:
        #print("Max Dist", max_dist)
        (graph, num_clusters) = form_clusters(graph, max_dist, max_num_vertices, orig_lakes)
        if (num_clusters == 1):
            break
        max_dist = max_dist * 2
    #print(graph[0][0]['path'])
    #prev_coord = graph[0][0]['path'][0]
    #total_dist = 0
    #for i, coord in enumerate(graph[0][0]['path'][1:]):
    #    if i % 2 == 0:
    #        total_dist += np.linalg.norm(prev_coord - coord)
    #    else:
    #        total_dist += 2 * np.linalg.norm(prev_coord - coord)
    #    prev_coord = coord
    #print("Total Distance: ", total_dist)
    convertedPath=[]
    for path in graph[0][0]['path'][1:]:
        x, y, z = path
        convertedPath.append(tuple((x, y, z)))
    #print(convertedPath)
    return convertedPath
    #print(orig_graph)

if __name__ == "__main__":
    scene = scenario_cityfire()
    scene.generate_scenario()
    clearcache()
    env = scene.simul.state()
    start = time.time()
    p = shortest(env)
    elapsed = time.time() - start
    print("Elapsed Time")
    print(elapsed)


import rospy
import open3d as o3d
import sensor_msgs.point_cloud2 as pc2
from sensor_msgs.msg import PointCloud2
import numpy as np

class RealSensePointCloud:
    def __init__(self):
        # Initialize ROS node
        rospy.init_node('realsense_pointcloud_visualizer')

        # Create a subscriber to the RealSense point cloud ROS topic
        # Make sure to use the correct topic where your RealSense camera publishes the point cloud data
        self.pc_subscriber = rospy.Subscriber("/camera/depth/color/points", PointCloud2, self.pointcloud_callback, queue_size=1)

        # Initialize Open3D visualizer
        self.vis = o3d.visualization.Visualizer()
        self.vis.create_window(window_name='RealSense Point Cloud')

        # Initialize point cloud variable
        self.pcd = o3d.geometry.PointCloud()

        self.voxel_size = 0.01  # Adjust this value as needed

        # Variable to control the main loop
        self.is_running = True

    def pointcloud_callback(self, msg):
        try:
            # Convert ROS PointCloud2 message to array of xyz points
            pc_array = pc2.read_points(msg, field_names=("x", "y", "z"), skip_nans=True)
            points = np.array(list(pc_array))

            if points.size == 0:
                rospy.logwarn("Received an empty point cloud.")
                return

            # Update point cloud
            self.pcd.clear()
            self.pcd.points = o3d.utility.Vector3dVector(points)

            # Voxel downsample the point cloud
            self.pcd = self.pcd.voxel_down_sample(voxel_size=self.voxel_size)

            # Update the visualizer
            self.update_visualizer()
        except Exception as e:
            rospy.logerr("An error occurred in pointcloud_callback: %s", str(e))

    def update_visualizer(self):
        self.vis.clear_geometries()  # Clear old geometries
        self.vis.add_geometry(self.pcd)  # Add the current point cloud
        self.vis.poll_events()  # Update the visualizer events
        self.vis.update_renderer()  # Render the point cloud

    def run(self):
        # Main loop
        while not rospy.is_shutdown() and self.is_running:
            rospy.spin()

        # If ROS is shut down or the script is stopped, close the visualizer window
        self.vis.destroy_window()

# Main function
if __name__ == "__main__":
    try:
        pointcloud_visualizer = RealSensePointCloud()
        pointcloud_visualizer.run()
    except rospy.ROSInterruptException:
        pass


import streamlit as st
import pandas as pd
import numpy as np
import folium
import os
from folium.plugins import HeatMap
from streamlit_folium import st_folium, folium_static
# from gbq_functions.big_query_download import *
from gbq_functions.params import *
import matplotlib.pyplot as plt
import matplotlib as mpl
from google.cloud import bigquery
from google.oauth2 import service_account
import streamlit.components.v1 as components
from functions_for_website.load_outputs import *

st.set_page_config(page_title="LocA", layout="wide", initial_sidebar_state="auto", menu_items=None)

for key in st.session_state.keys():
        del st.session_state[key]

st.markdown("
LocA
", unsafe_allow_html=True)

st.markdown("
Alternative Mapping Technique
", unsafe_allow_html=True)

credentials = service_account.Credentials.from_service_account_info(st.secrets["gcp_service_account"])

@st.cache_data(persist=True)
def get_master_district_df():
    '''function that returns the full master district df.
    Dataframe contains district name (primary key), lat_lons for the center,
    lat_lons for the edges of rectangle around area, and the area of the
    rectangle in Hectares'''

    query = f"""
            SELECT {",".join(MASTER_COLUMN_NAMES_RAW)}
            FROM {GCP_PROJECT}.{BQ_DATASET}.{BQ_DISTRICT_TABLE}
            ORDER BY HECTARES DESC
        """

    client = bigquery.Client(project=GCP_PROJECT, credentials=credentials)
    query_job = client.query(query)
    result = query_job.result()
    master_districts_df = result.to_dataframe()
    return master_districts_df
master_df = get_master_district_df()
master_df['start'] = master_df['District_ID'].astype(str).str[0] #gets the letter at start of dist.
master_df = master_df[master_df['start'] == "E"]
master_df = master_df[~master_df['District'].str.contains("London",regex=False)]
master_df = master_df.sort_values(by="District", ascending=True) #sorts

# create drop down box
option = st.selectbox("Select District:",
                      list(master_df['District']))

# set up the website to show Dorset on initializing
if 'district' not in st.session_state:
    st.session_state['district'] = 'Adur District'

@st.cache_data
def create_map(district):
    @st.cache_data  # :point_left: Add the caching decorator
    def load_data(csv):
        df = pd.read_csv(csv)
        return df

    df_good = load_data(os.path.abspath("outputs/display_gd.csv"))
    df_bad = load_data(os.path.abspath("outputs/display_bad.csv"))
    df = pd.concat([df_good, df_bad],ignore_index=True)
    golden_df = df[df['district_name'] == district]
    golden_df = golden_df.drop_duplicates(['lat', 'lng'])
    golden_df['id'] = golden_df.index

    mapObj = folium.Map(location=[golden_df['lat'].mean(),golden_df['lng'].mean()], zoom_start=10, prefer_canvas=True)

    lats = np.array( golden_df['lat'] )
    longs = np.array( golden_df['lng'] )

    # set up the grid
    lat_step = max(n2 - n1 for n1, n2 in zip(sorted(set(lats)), sorted(set(lats))[1:]))
    long_step = max(n2 - n1 for n1, n2 in zip(sorted(set(longs)), sorted(set(longs))[1:]))

    my_geo_json = {
      "type": "FeatureCollection",
      "features": []}

    for i in range(len(lats)):
        my_geo_json['features'].append(
            {
            "type": "Feature",
            "properties": {},
            "geometry": {
                "type": "Polygon",
                "coordinates": [[
                    [longs[i] - long_step/2, lats[i] - lat_step/2],
                    [longs[i] - long_step/2, lats[i] + lat_step/2],
                    [longs[i] + long_step/2, lats[i] + lat_step/2],
                    [longs[i] + long_step/2, lats[i] - lat_step/2],
                    [longs[i] - long_step/2, lats[i] - lat_step/2],
                ]]},
            "id": int(golden_df['id'].values[i])
            }
        )

    folium.Choropleth(
        geo_data=my_geo_json,
        data=golden_df,
        columns = ['id','metric'],
        fill_color='RdYlGn',
        fill_opacity=0.6,
        line_opacity=0,
        key_on='feature.id',
        bins=5
    ).add_to(mapObj)

    folium_static(mapObj, width = 725)

if st.button('Submit!'):
    st.session_state['district'] = option
create_map(st.session_state['district'])


# to make a diagram
n = int(input('Enter the string'))
y = 0
for i in range(-n, 0):
    j = -i
    print(j*' ', end = '')
    y += 1
    for k in range(y, n-y):
        print(k, end='')
    print('\n', end='')


# -*- coding: utf-8 -*-
"""
Created on Fri Aug  2 11:57:41 2019
Updated 20220904 22:42WER

@authors: wrosing, mfitz
"""

import os
import pathlib
import sys
import socket

import glob

# This routine here removes all mention of previous configs from the path...
# for safety and local computer got clogged with all manner of configs in the path

path_removals = []
for q in range(len(sys.path)):
    if "ptr-observatory" in sys.path[q] and "configs" in sys.path[q]:
        print("Removing old config path: " + str(sys.path[q]))
        path_removals.append(sys.path[q])

for remover in path_removals:
    sys.path.remove(remover)

pathdone = 0

# First try to get the hostname from a file in the directory above (..) ptr-observatory
cwd = str(pathlib.Path().resolve())
hwd = cwd.replace("ptr-observatory", "")
hostname_file = glob.glob(hwd + "hostname*")

try:
    site_name = hostname_file[0].replace('.txt','').split("hostname")[1]
    sys.path.append(os.path.join(pathlib.Path().resolve(), "configs", site_name))
    pathdone = 1
except OSError:
    print(
        "Could not find a hostname* file in the directory above ptr-observatory \
        (e.g. hostnamesro).\n Trying another method..."
    )

if pathdone == 0:
    print("Attempting hostname approach to config file...")
    host_site = socket.gethostname()[:3].lower()
    sys.path.append(os.path.join(pathlib.Path().resolve(), "configs", host_site))

try:
    from obs_config import *

except ImportError:
    print(
        "Failed the hostname approach to config file.\n"
        + str(host_site)
        + " isn't a real place, or there isn't a config file \
                        that I can find!"
    )

    try:
        site_name = input("What site am I running at?\n")
        sys.path.append(os.path.join(pathlib.Path().resolve(), "configs", site_name))
        from site_config import *

    except ImportError:
        print(
            str(site_name)
            + " isn't a real place, or there isn't a config file \
                        that I can find! Make sure you supplied \
                        a correct site name. Exiting."
        )
        sys.exit()


# https://www.hackerrank.com/challenges/counting-valleys/
def counting_valleys(amount_steps, path_walked):
    count = 0
    valleys = 0
    for step in path_walked:
        if step == 'D':
            count -= 1
        else:
            count += 1

        if count == 0 and step == 'U':
            valleys += 1

    return valleys

if __name__ == '__main__':
    steps = int(input().strip())
    path = input()

    print(counting_valleys(steps, path))


class House:
    def __init__(self, location, house_type, deal_type, price, completion_year):
        self.location = location
        self.house_type = house_type
        self.deal_type = deal_type
        self.price = price
        self.completion_year = completion_year

    def show_detail(self):
        print(self.location, self.house_type, self.deal_type, self.price, self.completion_year)

houses = []
h1 = House("Gangnam", "apartment", "sell", "1 billion", 2010)
h2 = House("Mapo", "studio", "full rent", "500 million", 2007)
h3 = House("Songpa", "villa", "monthly rent", "500/50", 2000)
houses.append(h1)
houses.append(h2)
houses.append(h3)

print("There are {0} houses.".format(len(houses)))
for i in houses:
    i.show_detail()


#@UIService uiService
from ij import IJ, ImagePlus
from ij.gui import Overlay, Roi
from ij.plugin import ImagesToStack, Straightener

"""
This script straightens the pixels associated with Sholl sampling shells, so
that the signal sampled during Sholl Analysis can be measured in a more
straightforward way. For details, see https://forum.image.sc/t/51087/

The script assumes that the frontmost image is a 2D image analyzed by the Sholl
Analysis plugin (typically a "Sholl Mask image") containing "ROI shells" as
annotations in the image overlay. Further details:
https://forum.image.sc/t/measuring-distribution-of-object-diameters-in-different-stripes-using-sholl-plugin/51087
"""

def error():
  uiService.showDialog("No 'shell' ROIs found in frontmost image.\
  Make sure image has '2D Sholl Shells' in its overlay.")

shell_width = 10
imp = IJ.getImage()
overlay = imp.getOverlay()
raster_shells = []

if imp and overlay:
  for i in range(overlay.size()):
    roi = overlay.get(i)
    if roi.getName() and "Shell" in roi.getName():
      imp.setRoi(roi)
      IJ.run(imp, "Area to Line", "")
      raster = ImagePlus(roi.getName(), Straightener().straighten(imp, roi, shell_width))
      raster_shells.append(raster)
  if raster_shells:
    holding_imp = ImagesToStack.run(raster_shells)
    IJ.run(holding_imp, "Make Montage...", "columns=1 rows={} scale=1".format(holding_imp.getNSlices()))
    measurable_imp = IJ.getImage()
    measurable_imp.setTitle("Rasterized Shells")
    IJ.setAutoThreshold(measurable_imp, "Default dark")
    IJ.run(measurable_imp, "Analyze Particles...", "  show=[Overlay Masks] display clear overlay")
  else:
    error()
else:
  error()