# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:

    # Input: root = [4,2,5,1,3], target = 3.714286, and k = 2

    #     4
    #    / \
    #   2   5
    #  / \
    # 1   3
    #    / \
    #  2.5 3.5
    # 2.2 2.7
    # small_stack = [2, 3, 3.5]
    # large_stack = [4]
    # 3.5, not left node
    # 4,  put 5 in stack [5]
    # 3, less than target, means all its right node has been handled,
    # so put 3 in res, put its left node 2.5 in small stack, and loop its all right node
    # to small stack [2, 2.5, 2.7]
    # so idea is using two stacks, one for larger, one for smaller
    # first find the closest node, in the same time, put the node on the path to two stacks
    # then from two stacks, move the closest value one to result
    # if the node come from small stack, put its left node, and its left node's all right nodes
    # to small stack
    # if the node come from large stack, put its right node, and its right node's all left nodes
    # to large stack
    # time is O(n), space is O(n)
    def closestKValues(self, root, target, k):
        """
        :type root: TreeNode
        :type target: float
        :type k: int
        :rtype: List[int]
        """
        def find_closest(node):
            if node == None:
                return
            if node.val > target:
                large_stack.append(node)
                find_closest(node.left)
            elif node.val < target:
                small_stack.append(node)
                find_closest(node.right)
            else:
                large_stack.append(node)
        def put_all_right(node):
            while node:
                small_stack.append(node)
                node = node.right
        def put_all_left(node):
            while node:
                large_stack.append(node)
                node = node.left
        if k <= 0: return []
        large_stack, small_stack = [], []
        find_closest(root)
        res = []
        while len(res) < k:
            if len(large_stack) > 0 and (len(small_stack) == 0 or large_stack[-1].val - target <= target - small_stack[-1].val):
                node = large_stack.pop()
                res.append(node.val)
                if node.val == target:
                    put_all_right(node.left)
                put_all_left(node.right)
            else:
                node = small_stack.pop()
                res.append(node.val)
                put_all_right(node.left)
        return res

    def closestKValues(self, root, target, k):
        """
        :type root: TreeNode
        :type target: float
        :type k: int
        :rtype: List[int]
        """
        if not root: return []
        cur = root
        largers, smallers, larger_values, smaller_values, res = [], [], [], [], []
        while cur:
            if cur.val < target:
                smallers += cur,
                print("smallers",cur.val)
                cur = cur.right
            elif cur.val > target:
                largers += cur,
                print("largers",cur.val)
                cur = cur.left
        # print(smallers, largers)
        def small_first(node):
            if node.left:
                if small_first(node.left):
                    return True
            larger_values.append(node.val)
            if len(larger_values) >= k:
                return True
            if node.right: small_first(node.right)
        def large_first(node):
            if node.right:
                if large_first(node.right):
                    return True
            smaller_values.append(node.val)
            if len(smaller_values) >= k:
                return True
            if node.left: large_first(node.left)
        for cur in largers[::-1]:
            temp_left, cur.left = cur.left, None
            small_first(cur)
            cur.left = temp_left
        for cur in smallers[::-1]:
            temp_right, cur.right = cur.right, None
            large_first(cur)
            cur.right = temp_right
        print(smaller_values, larger_values)
        while len(res)<k:
            small_v = smaller_values[0] if smaller_values else float("inf")
            large_v = larger_values[0] if larger_values else float("inf")
            if target - small_v <= large_v - target:
                val = smaller_values.pop(0)
            else:
                val = larger_values.pop(0)
            res += val,
        return res


num = 3

name = "John"
countries = ["Egypt", "Morocco", "Tunis"]
langs = ["En", "Ar", "Sp", "Gr"]
colors = ["red", "green", "blue", "black", "white"]
books = ["clean code", "python expert", "django for backend", "flask micro framework"]
fruits = ["Apple", "Orange", "Banana"]
players = ["Messi", "Ronaldo", "Mo Salah"]
apps = ["FB", "Instgram", "Youtube", "Twitter", "WhatsApp"]

print(books)
print(books[0])  # position/ index is actually an offset(look at the pic

print(books[1])  # "python expert" index 1 , means shitted by 1,
# means there is 1 item before it, mean "python expert" it is the second item
print(books[2])

print(books[-1])  # the last item


#online_consumer.py
import numpy as np
from sklearn.linear_model import SGDClassifier
from kafka import KafkaConsumer
import json
import plotly
import plotly.tools
import plotly.graph_objs as go
from scipy import stats

#############################################
# Create a plotly plot
#############################################

with open('/home/ventum/Syn-Repo-DataScience/Python/KAFKA_Streaming/config2.json') as config_file:
    plotly_user_config = json.load(config_file)

username = plotly_user_config['plotly_username']
api_key = plotly_user_config['plotly_api_key']
stream_token1 = plotly_user_config['plotly_streaming_tokens'][1]
stream_token2 = plotly_user_config['plotly_streaming_tokens'][2]
#stream_token = dict(token=stream_token, maxpoints=60)

print("Starting Streaming")

#############################################
# Initialize your plotly object
#############################################

p = plotly.plotly.sign_in(username, api_key)

x_data          = []
y_data_fit      = []
target      = []
prediction  = []
line  = []
line_history  = []
n_features = 1
count = 0
correct = 0

trace0 = go.Scatter(
    x = [],
    y = [],
    mode = 'markers',
    name = 'train data points'

)
trace1 = go.Scatter(
    x = [],
    y = [],
    mode = 'markers',
    name = 'trend line'
)
data = [trace0,trace1]
plotly.plotly.iplot(data,filename='Support-Vector-Machine-Kafka', fileopt='overwrite')

#plotly.plotly.iplot([{'x': [], 'y': [], 'type': 'scatter', 'mode': 'markers','stream': {'token': stream_token1, 'maxpoints': 100}},
#                     {'x': [], 'y': [], 'type': 'scatter', 'mode': 'line','stream': {'token': stream_token2, 'maxpoints': 100}}],
#                     filename='Support-Vector-Machine-Kafka', fileopt='overwrite')

#############################################
# Open plotly stream
#############################################

s1 = plotly.plotly.Stream(stream_token1)
s1.open()

s2 = plotly.plotly.Stream(stream_token2)
s2.open()

#############################################
# Open Kafka connection and do incremental SVM fit
#############################################

clf = SGDClassifier(loss="hinge", alpha=0.01, n_iter=20, fit_intercept=True)

consumer = KafkaConsumer('simple-test2',
    bootstrap_servers="localhost:9091,localhost:9092")

for binary_message in consumer:

    #############################################
    # encode binary value back to the message
    #############################################
    msg=binary_message.value.decode('utf-8')

    #############################################
    # create a json file
    #############################################

    data = json.loads(msg)
    vec = np.zeros(len(data))
    for key,value in data.items():
        vec[int(key)]=value

    #############################################
    # create a feature vector
    #############################################

    features = vec[:n_features].reshape(1,n_features)

    #############################################
    # Create a target vector
    #############################################

    target = [vec[n_features]]

    # if the stream is initiated we need to create an initial value count
    if count > 1:
        prediction = clf.predict(features)
        prediction =  np.array(prediction)
        correct += int(prediction[0]==int(target[0]))
    if count > 2:
        x_data.extend(features[0])
        y_data_fit.extend(prediction)

        #############################################
        # Generated linear fit
        #############################################

        slope, intercept, r_value, p_value, std_err = stats.linregress(x_data,y_data_fit)
        line = slope*float(x_data[0])+intercept
        line_history.append(float(line))
        print("Score           :   " + str(correct/float(count-1)))
        print("Line of best fit:   " + str(line_history))
        print("xdata[0]        :   " + str(float(x_data[0])))
        print("xdata           :   " + str(x_data))
        print("prediction      :   " + str(prediction))
        print("features        :   " + str(features))
    #############################################
    # Fit the Support vector machine model (Stochastic Gradient Descent)
    #############################################

    clf.partial_fit(features, target,classes=[0,1])

    #############################################
    # Write the data to the plotly stream
    #############################################

    s1.write({'x': x_data, 'y': target[0]})
    s2.write({'x': x_data, 'y': line_history})

    # increment the count
    count += 1


import logging
import os
import subprocess

import boto3
import click
from retrying import retry

from ..utils.io import IngestStatus
from ..models import Scene
from ..ingest.models import Ingest
from ..ingest import (
    create_landsat8_ingest,
    create_sentinel2_ingest,
    create_ingest_definition
)
from ..uploads.landsat8.settings import datasource_id as landsat_id
from ..utils.exception_reporting import wrap_rollbar
from ..utils.emr import get_cluster_id, wait_for_emr_success

logger = logging.getLogger(__name__)

BATCH_JAR_PATH = os.getenv('BATCH_JAR_PATH', 'rf-batch-761c316.jar')
SENTINEL2_DATASOURCE_IDS = ['4a50cb75-815d-4fe5-8bc1-144729ce5b42', 'c33db82d-afdb-43cb-a6ac-ba899e48638d']

@click.command(name='ingest-scene')
@click.argument('scene_id')
@click.option('--ignore-previous', is_flag=True,
              help='Boolean to ignore scene status for ingestion')
@click.option('--local', is_flag=True,
              help='Boolean to run using a spark local cluster rather than EMR job')
@wrap_rollbar
def ingest_scene(scene_id, ignore_previous, local):
    """Ingest a scene into Raster Foundry

    Args:
        scene_id (str): ID of scene to ingest
        ignore_previous (bool): whether to ignore ingest_status when processing ingest
    """
    logger.info("Ingesting Scene: %s", scene_id)
    s3_uri, ingest_definition_id = save_ingest_def_to_s3(scene_id, ignore_previous)
    launch_spark_ingest_job(s3_uri, ingest_definition_id, scene_id, local)
    wait_for_status(ingest_definition_id)

def save_ingest_def_to_s3(scene_id, ignore_previous=False):
    """Create ingest definition and upload to S3

    Args:
        ignore_previous (bool): boolean to ignore previous ingest status
        scene_id (str): ID of scene to create ingest definition for
    """
    scene = Scene.from_id(scene_id)

    logger.info('Beginning to create ingest definition for scene %s for user %s...',
                scene_id, scene.owner)
    if scene.ingestStatus not in [IngestStatus.TOBEINGESTED, IngestStatus.FAILED] and not ignore_previous:
        raise Exception('Scene is no longer waiting to be ingested, error error')

    scene.ingestStatus = IngestStatus.INGESTING
    logger.info('Updating scene (%s) status to ingesting', scene_id)
    scene.update()
    logger.info('Successfully updated scene (%s) status', scene_id)

    logger.info('Creating ingest definition')
    if scene.datasource == landsat_id:
        ingest_definition = create_landsat8_ingest(scene)
    elif scene.datasource in SENTINEL2_DATASOURCE_IDS:
        ingest_definition = create_sentinel2_ingest(scene)
    else:
        ingest_definition = create_ingest_definition(scene)
    ingest_definition.put_in_s3()
    logger.info('Successfully created and pushed ingest definition for scene %s', scene)

    Ingest.delete_status_from_s3(ingest_definition.id)
    return ingest_definition.s3_uri, ingest_definition.id

def launch_spark_ingest_job(ingest_def_uri, ingest_def_id, scene_id, local=False):
    """Launch ingest job and wait for success/failure

    Args:
        ingest_def_uri (str): S3 URI for location of ingest definition
        ingest_def_id (str): ID for ingest definition
        scene_id (str): ID for scene to be ingested
        local (bool): whether to execute ingest as a spark local job

    Returns:
        bool
    """

    logger.info('Launching Spark ingest job with ingest definition %s for scene %s',
                ingest_def_uri, scene_id)
    if local:
        return execute_local_ingest_job(scene_id, ingest_def_uri)
    else:
        cluster_id = get_cluster_id()
        emr_response = execute_ingest_emr_job(scene_id, ingest_def_uri, ingest_def_id, cluster_id)
        logger.info('Launched Spark ingest job for %s with ingest ID %s. Waiting for status changes.',
                    scene_id, ingest_def_id)
        step_id = emr_response['StepIds'][0]
        is_success = wait_for_emr_success(step_id, cluster_id)
        return is_success

def execute_local_ingest_job(scene_id, ingest_s3_uri):
    """Execute ingest job locally with a spark local cluster

    Args:
        scene_id (str): ID of scene to ingest
        ingest_s3_uri (str): S3 location for ingest definition
    """

    ingest_cores = os.getenv('LOCAL_INGEST_CORES', 32)
    ingest_memory = os.getenv('LOCAL_INGEST_MEM_GB', 48)
    command = ['spark-submit',
               '--master', 'local[{}]'.format(ingest_cores),
               '--driver-memory', '{}g'.format(ingest_memory),
               '--class', 'com.azavea.rf.batch.ingest.spark.Ingest',
               '/opt/raster-foundry/jars/rf-batch.jar',
               '-t', '--overwrite', '-s', scene_id, '-j', ingest_s3_uri
    ]
    subprocess.check_call(command)
    logger.info('Finished Ingesting %s in spark local', scene_id)
    return True

@retry(wait_exponential_multiplier=2000, wait_exponential_max=30000, stop_max_attempt_number=5)
def execute_ingest_emr_job(scene_id, ingest_s3_uri, ingest_def_id, cluster_id):
    """Kick off ingest in AWS EMR

    Args:
        scene_id (str): id of the scene to ingest
        ingest_s3_uri (str): URI for ingest definition
        ingest_def_id (str): ID to namespace ingest job
        cluster_id (str): ID of the cluster to submit work to

    Returns:
        dict
    """
    logger.info('Constructing ingest step request for %s for cluster %s for ingest id %s',
                scene_id, cluster_id, ingest_def_id)
    step = {
        'ActionOnFailure': 'CONTINUE',
        'Name': 'ingest-{}'.format(ingest_def_id),
        'HadoopJarStep': {
            'Args': ['/usr/bin/spark-submit',
                     '--master',
                     'yarn',
                     '--deploy-mode',
                     'cluster',
                     '--conf',
                     'spark.yarn.submit.waitAppCompletion=false',
                     '--class',
                     'com.azavea.rf.batch.ingest.spark.Ingest',
                     's3://rasterfoundry-global-artifacts-us-east-1/batch/{}'.format(BATCH_JAR_PATH),
                     '-t',
                     '--overwrite',
                     '-s',
                     scene_id,
                     '-j',
                     ingest_s3_uri],
            'Jar': 's3://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar'
        }
    }
    logger.info('Submitting step to EMR (%s)', step)
    emr = boto3.client('emr')
    response = emr.add_job_flow_steps(
        JobFlowId=cluster_id,
        Steps=[step]
    )
    logger.info('Received response from EMR API: %s', response)
    return response

@retry(wait_exponential_multiplier=2000, wait_exponential_max=30000, stop_max_attempt_number=2)
def wait_for_status(ingest_def_id):
    """Wait for a result from the Spark job

    Args:
        ingest_def_id (str): ID of ingest definition to check on results for
    """
    ingest_status_dict = Ingest.get_status_from_s3(ingest_def_id)
    scene_id = ingest_status_dict['sceneId']
    status = ingest_status_dict['ingestStatus']

    layer_s3_bucket = os.getenv('TILE_SERVER_BUCKET')
    s3_output_location = 's3://{}/layers'.format(layer_s3_bucket)

    logger.info('Waiting for scene status at %s for scene %s with ingest defintion %s',
                s3_output_location, scene_id, ingest_def_id)

    scene = Scene.from_id(scene_id)
    scene.ingestLocation = s3_output_location
    scene.ingestStatus = status

    if scene.ingestStatus != IngestStatus.FAILED:
        logger.info('Writing scene metadata into postgres.')
        metadata_to_postgres(s3_output_location, scene_id)

    logger.info('Setting scene %s ingest status to %s', scene.id, scene.ingestStatus)
    scene.update()
    logger.info('Successfully updated scene %s\'s ingest status', scene.id)

    notify_for_scene_ingest_status(scene.id)

    if scene.ingestStatus == IngestStatus.FAILED:
        raise Exception('Failed to ingest {} for user {}'.format(scene_id, scene.owner))

def metadata_to_postgres(uri, scene_id):
    """Save metadata of Layer at URI and Scene to Database

    Args:
        uri (str): remote location of layer
        scene_id (str): ID of scene to save metadata for
    """
    bash_cmd = [
        'java', '-cp',
        '/opt/raster-foundry/jars/rf-batch.jar',
        'com.azavea.rf.batch.Main',
        'migration_s3_postgres',
        uri,
        'layer_attributes',
        scene_id
    ]
    logger.debug('Bash command to store metadata: %s', ' '.join(bash_cmd))
    running_cmd = subprocess.Popen(bash_cmd)
    running_cmd.communicate()
    logger.info('Successfully completed metadata postgres write for scene %s', scene_id)
    return True

def notify_for_scene_ingest_status(scene_id):
    """Notify users that are using this scene as well as the scene owner that
    the ingest status of this scene has changed

    Args:
        scene_id (Scene): the scene which has an updated status
    """

    bash_cmd = [
        'java', '-cp',
        '/opt/raster-foundry/jars/rf-batch.jar',
        'com.azavea.rf.batch.Main',
        'notify_ingest_status',
        scene_id
    ]
    running_process = subprocess.Popen(bash_cmd)
    running_process.communicate()
    return True


import asyncio
import collections
import contextlib
import functools
import itertools
import re

import discord
from discord.ext import commands
from more_itertools import chunked, consume, iter_except, unique_everseen

from .misc import maybe_awaitable
from .queue import SimpleQueue

_Trigger = collections.namedtuple('_Trigger', 'emoji pattern blocking fallback')

def trigger(emoji, pattern=None, *, block=False, fallback=None):
    """Add a function that will be called with a certain reaction.

    If pattern is a string, it will be used as a regex pattern for
    messages to trigger that function.

    If fallback is a string, it will be used as a regex pattern like
    pattern. However, it will only be used if the bot can't add
    reactions.

    If block is True, reactions will be ignored for the duration of the
    execution.
    """
    def decorator(func):
        func.__trigger__ = _Trigger(emoji=emoji, pattern=pattern, blocking=block, fallback=fallback)
        return func
    return decorator

paginated = functools.partial(
    commands.bot_has_permissions,
    embed_links=True,
)

# Extract the predicate from the check...
_validate_context = paginated()(lambda: 0).__commands_checks__[0]

class _TriggerCooldown(commands.CooldownMapping):
    def __init__(self):
        super().__init__(commands.Cooldown(rate=5, per=2, type=commands.BucketType.user))

    def _bucket_key(self, tup):
        return tup

    def is_rate_limited(self, message_id, user_id):
        bucket = self.get_bucket((message_id, user_id))
        return bucket.update_rate_limit() is not None

_trigger_cooldown = _TriggerCooldown()

class _Callback(collections.namedtuple('_Callback', 'func blocking')):
    """Wrapper class to store both the resolved descriptor and blocking
    attribute."""

    __slots__ = ()

    # InteractiveSession.reaction_help relies on the wrapped function's __doc__
    @property
    def __doc__(self):
        return self.func.__doc__

class InteractiveSession:
    r"""Base class for all interactive sessions.

    Subclasses must implement 'default' method. If necessary, they can
    override 'start'.

    Example:
        class Thing(InteractiveSession):
            @reaction('\N{HEAVY BLACK HEART}')
            def default(self):
                return discord.Embed(description='hi myst \N{HEAVY BLACK HEART}')

            @reaction('\N{THINKING FACE}')
            def think(self):
                return discord.Embed(description='\N{THINKING FACE}')

    A page should either return a discord.Embed, or None if to indicate
    the page was invalid somehow. e.g. The page number given was out of
    bounds, or there were side effects associated with it.
    """

    # TODO: Context-less __init__
    def __init__(self, ctx):
        self.context = ctx
        self._bot = ctx.bot
        self._channel = ctx.channel
        self._users = {ctx.author.id}
        self._message = None
        self._blocking = False

        # XXX: Remove self._current
        self._current = None

        # Queue is used to avoid having reactions being ignored if they're
        # spammed or if a callback unexpectedly takes a long time.
        self._queue = SimpleQueue()

        # Simple flag variable to see if reactions are being used
        # Might be refactored out later, but this is the simplest solution.
        self._using_reactions = False

    def __init_subclass__(cls, *, stop_emoji='\N{BLACK SQUARE FOR STOP}', stop_pattern=None, stop_fallback='exit', **kwargs):
        super().__init_subclass__(**kwargs)
        cls._reaction_map = callbacks = collections.OrderedDict()

        # These are lists as opposed to dicts because we need to iterate
        # through it to find a match, rather than looking it up in a table.
        cls._message_callbacks = message_callbacks = []
        cls._message_fallbacks = message_fallbacks = []
        seen_patterns = set()

        def trigger_iterator():
            # Can't use inspect.getmembers for two reasons:
            # 1. It sorts the members lexographically, which is not what
            #    we want. We want them in definition order.
            # 2. It resolves descriptors too early. This causes things like
            #    x = page('emoji')(partialmethod(meth, ...)) to not be registered.
            #
            name_members = itertools.chain.from_iterable(b.__dict__.items() for b in cls.__mro__)
            for name, member in unique_everseen(name_members, key=lambda p: p[0]):
                trigger = getattr(member, '__trigger__', None)
                if trigger is None:
                    continue

                # Resolve any descriptors ahead of time so we can do _reaction_map[emoji](self)
                resolved = getattr(cls, name)
                callback = _Callback(resolved, trigger.blocking)
                yield trigger.emoji, trigger.pattern, trigger.fallback, callback

            if stop_emoji or stop_pattern or stop_fallback:
                yield stop_emoji, stop_pattern, stop_fallback, _Callback(cls.stop, False)

        for emoji, pattern, fallback, callback in trigger_iterator():
            if emoji not in callbacks:
                callbacks[emoji] = callback

            if pattern and pattern not in seen_patterns:
                seen_patterns.add(pattern)
                message_callbacks.append((pattern, callback))

            if fallback and fallback not in seen_patterns:
                seen_patterns.add(fallback)
                message_fallbacks.append((fallback, callback))

    def using_reactions(self):
        """Return True if reactions are being used for the current
        session, False otherwise.

        This can return False if the session is not running.
        """
        return self._using_reactions

    def check(self, reaction, _):
        """Extra checks for reactions"""
        return reaction.emoji in self._reaction_map

    async def add_reactions(self):
        """Add the reactions to the message"""
        for emoji in self._reaction_map:
            await self._message.add_reaction(emoji)

    def default(self):
        """Return the first embed to start the controller"""
        raise NotImplementedError

    async def start(self):
        """First thing that gets called"""
        self._current = embed = await maybe_awaitable(self.default)
        self._message = await self._channel.send(embed=embed)

    async def stop(self):
        """Stop running the controller"""
        await self._queue.put(None)

    async def cleanup(self, *, delete_after):
        """Clean up anything else after stopping"""
        msg = self._message
        method = msg.delete if delete_after else msg.clear_reactions
        with contextlib.suppress(Exception):
            await method()

    # XXX: Remove release_connection
    async def run(self, *, timeout=120, delete_after=True, release_connection=True):
        """Run the interactive loop"""
        _validate_context(self.context)
        if release_connection:
            with contextlib.suppress(AttributeError):
                await self.context.release()

        # XXX: Can we accomplish without context???
        self._using_reactions = self._channel.permissions_for(self.context.me).add_reactions
        using_reactions = self._using_reactions

        await self.start()
        if self._message is None:
            # start() was overridden but no message was set
            raise RuntimeError('start() must set self._message')

        message = self._message
        triggers = self._message_callbacks.copy()
        task = None
        listeners = []

        def listen(func):
            listeners.append(func)
            return self._bot.listen()(func)

        if using_reactions:
            task = self._bot.loop.create_task(self.add_reactions())

            @listen
            async def on_reaction_add(reaction, user):
                if (
                    not self._blocking
                    and reaction.message.id == message.id
                    and user.id in self._users
                    and self.check(reaction, user)
                    and not _trigger_cooldown .is_rate_limited(message.id, user.id)
                ):
                    callback, self._blocking = self._reaction_map[reaction.emoji]
                    cleanup = functools.partial(message.remove_reaction, reaction.emoji, user)
                    await self._queue.put((callback, cleanup))
        else:
            triggers.extend(self._message_fallbacks)

        if triggers:
            @listen
            async def on_message(msg):
                if (
                    self._blocking
                    or msg.channel != self._channel
                    or msg.author.id not in self._users
                ):
                    return

                patterns, callbacks = zip(*triggers)
                selectors = map(re.fullmatch, patterns, itertools.repeat(msg.content))
                callback = next(itertools.compress(callbacks, selectors), None)
                if callback is None:
                    return

                if _trigger_cooldown.is_rate_limited(message.id, msg.author.id):
                    return

                callback, self._blocking = callback
                await self._queue.put((callback, msg.delete))

        try:
            while True:
                # TODO: Would async_timeout be better here?
                try:
                    job = await asyncio.wait_for(self._queue.get(), timeout=timeout)
                except asyncio.TimeoutError:
                    break

                if job is None:
                    break

                callback, after = job

                result = await maybe_awaitable(callback, self)

                with contextlib.suppress(discord.HTTPException):
                    await after()

                self._blocking = False

                if result is None:
                    continue
                self._current = result  # backwards compat...

                try:
                    await message.edit(embed=result)
                except discord.NotFound:  # Message was deleted
                    break

        finally:
            self._using_reactions = False

            for listener in listeners:
                self._bot.remove_listener(listener)

            if not (task is None or task.done()):
                task.cancel()

            consume(iter_except(self._queue.get_nowait, asyncio.QueueEmpty))
            await self.cleanup(delete_after=delete_after)

    interact = run  # backwards compat

    @property
    def reaction_help(self):
        return '\n'.join(itertools.starmap('{0} => {1.__doc__}'.format, self._reaction_map.items()))

# ------------- Paginator --------------

class Paginator(InteractiveSession):
    """Class that takes an iterable of entries and paginates them.

    This is what often comes to mind when people talk about 'paginators'
    """
    def __init__(self, ctx, entries, *, per_page=15, title=discord.Embed.Empty, colour=None, **kwargs):
        super().__init__(ctx, **kwargs)
        self._pages = tuple(chunked(entries, per_page))
        self._index = 0

        if colour is None:
            colour = ctx.bot.colour

        # These should probably be removed at some point in the future.
        self.title = title
        self.colour = colour

    def single_page(self):
        """Return True if there is only one page, False otherwise"""
        return len(self._pages) == 1

    def small(self):
        """Return True if there are five pages or less, False otherwise"""
        return len(self._pages) <= 5

    async def start(self):
        await super().start()
        if self.single_page():
            # Don't even start paginating if there is only one page.
            await self.stop()

    async def cleanup(self, *, delete_after):
        if not self.single_page():
            await super().cleanup(delete_after=delete_after)

    async def add_reactions(self):
        if self.single_page():
            return

        fast_forwards = {'\U000023ed', '\U000023ee'}
        small = self.small()

        for emoji in self._reaction_map:
            if not (small and emoji in fast_forwards):
                await self._message.add_reaction(emoji)

    # Main methods
    def create_embed(self, page):
        """Create an embed given a slice of entries"""

        return (discord.Embed(title=self.title, colour=self.colour, description='\n'.join(page))
                .set_footer(text=f'Page: {self._index + 1} / {len(self._pages)} ({self.total} total)')
                )

    def page_at(self, idx):
        """Return the embed that would be created at a certain point.

        None if the index is out of bounds.
        """
        if not 0 <= idx < len(self._pages):
            return None

        self._index = idx
        return self.create_embed(self._pages[idx])

    @trigger('\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}', fallback=r'\<\<')
    def default(self):
        """First page"""
        return self.page_at(0)

    @trigger('\N{BLACK LEFT-POINTING TRIANGLE}', fallback=r'\<')
    def previous(self):
        """Previous page"""
        return self.page_at(self._index - 1)

    @trigger('\N{BLACK RIGHT-POINTING TRIANGLE}', fallback=r'\>')
    def next(self):
        """Next page"""
        return self.page_at(self._index + 1)

    @trigger('\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}', fallback=r'\>\>')
    def last(self):
        """Last page"""
        return self.page_at(len(self._pages) - 1)

    # --------- Go-to page ------------

    def _goto_embed(self):
        ctx = self.context
        description = (
            f'Please enter a number from 1 to {len(self._pages)}.\n\n'
            'To cancel, click \N{INPUT SYMBOL FOR NUMBERS} again.'
        )
        return (discord.Embed(colour=self.colour, description=description)
                .set_author(name=f'What page do you want to go to, {ctx.author.display_name}?')
                )

    def _goto_parse_input(self, content):
        try:
            index = int(content)
        except ValueError:
            return None

        return self.page_at(index - 1)

    # XXX: This needs to be fully refactored for the reaction-less paginator
    #      or possibly not used at all.
    # XXX: This needs to use the user who actually added the reaction, NOT ctx.author
    @trigger('\N{INPUT SYMBOL FOR NUMBERS}', block=True)
    async def goto(self):
        """Go to page"""
        ctx = self.context
        return_result = None
        user_message = None

        def check(m):
            nonlocal return_result, user_message
            if not (m.channel.id == self._channel.id and m.author.id == ctx.author.id):
                return False

            result = self._goto_parse_input(m.content)
            if result is None:
                return False

            return_result = result
            user_message = m
            return True

        def remove_check(reaction, user):
            return (reaction.message.id == self._message.id
                    and user.id == ctx.author.id
                    and reaction.emoji == '\N{INPUT SYMBOL FOR NUMBERS}')

        # The two futures are such that so the user doesn't get "stuck" in the
        # number page. If they click on the number page by accident, then they
        # should have an easy way out.
        #
        # Thus we have to wait for one of two things:
        # 1. The actual number of the page they want to go to
        # 2. The removal of the numbered reaction if the user wants to go back

        to_wait = [
            self._bot.wait_for('message', check=check),
            self._bot.wait_for('reaction_remove', check=remove_check),
        ]

        try:
            embed = self._goto_embed()
            delete_always = await self._channel.send(embed=embed)

            done, pending = await asyncio.wait(
                to_wait,
                timeout=60,
                return_when=asyncio.FIRST_COMPLETED
            )
            for fut in pending:
                fut.cancel()

            if not done:
                # Effectively a timeout.
                return None

            result = done.pop().result()

            if isinstance(result, discord.Message):
                return return_result
            # The user probably removed a reaction.
            return None
        finally:
            for m in [delete_always, user_message]:
                with contextlib.suppress(Exception):
                    await m.delete()

    # ------------- End go-to page -----------

    @property
    def total(self):
        """Return the total number of entries in the list"""
        return sum(map(len, self._pages))

# -------------- Field Pages ----------------------

class FieldPaginator(Paginator):
    """Similar to Paginator, but uses the fields instead of the description"""
    def __init__(self, context, entries, *, inline=True, **kwargs):
        super().__init__(context, entries, **kwargs)

        self.inline = inline
        if len(self._pages) > 25:
            raise ValueError("too many fields per page (maximum 25)")

    def create_embed(self, page):
        embed = (discord.Embed(title=self.title, colour=self.colour)
                 .set_footer(text=f'Page: {self._index + 1} / {len(self._pages)} ({self.total} total)')
                 )

        add_field = functools.partial(embed.add_field, inline=self.inline)
        for name, value in page:
            add_field(name=name, value=value)
        return embed

EmbedFieldPages = FieldPaginator  # backwards compat


# -*- coding: utf-8 -*-
# getMKMPrice.py

from shared import *

baseURL = "https://magiccards.info/"

def  getTCGTrendValue (cardName, cache=None):
    nullTrend = True;
    cardURL = baseURL + "query?q=" + urllib2.quote (cardName.encode ("utf8"), safe='')

    html = download (cardURL, cache=cache)
    if not html  and  'ae' in cardName.lower()  and not "æ" in cardName.lower():
        cardName = cardName.lower().replace("ae", "æ").encode ("utf8")
        cardURL = baseURL + singlesURL + cardName
        html = download (cardURL, cache=cache)
    elif not html  and not  'ae' in cardName.lower()  and  "æ" in cardName.lower():
        cardName = cardName.lower().replace("ae", "æ").encode ("utf8")
        cardURL = baseURL + singlesURL + cardName
        html = download (cardURL, cache=cache)

    if not html:
        logger.exception ("Couldn't download Magic Cards Info web", exc_info=True)
    else:
        soup = BeautifulSoup (html, 'html.parser')
        value = getTCGValue (soup, cardName)

        # Find the editions block
        editionsBlock = re.search(r'<u.*?<b.*?Editions.*?<u.*?<b.*?Languages', html, re.DOTALL)
        start = editionsBlock.start()
        end = editionsBlock.end()
        editions_html = html[start:end]
        editions_soup = BeautifulSoup (editions_html, 'html.parser')
        editions_url = editions_soup.findAll ('a')

        # Look the trend value for each set and select the lowest
        for  a  in  editions_url:
            cardsetURL = baseURL + a["href"]
            editionSoup = BeautifulSoup (download(cardsetURL, cache=cache), 'html.parser')
            if  nullTrend:
                nullTrend = False
                trend = value
            value = getTCGValue(soup, cardName)
            if  value is not None  and  value < trend:
                trend = value

    if  nullTrend:
        trend = None
    else:
        logger.info ("'" + cardName + "' value Trend: " + str(trend) + "\n")

    return trend

# Scrapes MKM to return card value for a given set.
# Returns 0 if card isn't available
def  getTCGValue (soup, cardName):
    value = None

    try:
        # Scrape for the trend value which is in a block like this:
        value = float (soup.find ('td', {'class':'TCGPHiLoMid'}).find ('a').text.strip(u' \t\n\r\xa0\u20ac').replace(' ', '').replace(',', '.'))
        logger.info ("Value: " + str(value))
    except: # The card may not have a value
        logger.warning ("Couldn't get value for '%s'", cardName, exc_info=True)

    return  value

def  main ():
    if  len (sys.argv) == 2:
        cardName = sys.argv[1]
        cache = diskCache.DiskCache ()
        getTCGTrendValue (cardName, cache=cache)

if __name__ == "__main__":
    main ()


"""
****************************************************************************************************
:copyright (c) 2019-2020 URBANopt, Alliance for Sustainable Energy, LLC, and other contributors.

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the
distribution.

Neither the name of the copyright holder nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
****************************************************************************************************
"""

import os
import shutil
import unittest
from pathlib import Path

from geojson_modelica_translator.geojson_modelica_translator import (
    GeoJsonModelicaTranslator
)
from geojson_modelica_translator.model_connectors.spawn import SpawnConnector
from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner
from geojson_modelica_translator.system_parameters.system_parameters import (
    SystemParameters
)

class SpawnModelConnectorSingleBuildingTest(unittest.TestCase):
    def setUp(self):
        root_dir, project_name = "tests/model_connectors/output", "spawn_single"

        if os.path.exists(os.path.join(root_dir, project_name)):
            shutil.rmtree(os.path.join(root_dir, project_name))

        # load in the example geojson with a single offie building
        filename = os.path.abspath("tests/model_connectors/data/spawn_geojson_ex1.json")
        self.gj = GeoJsonModelicaTranslator.from_geojson(filename)
        self.gj.scaffold_directory(root_dir, project_name)  # use the GeoJson translator to scaffold out the directory

        # load system parameter data
        filename = os.path.abspath("tests/model_connectors/data/spawn_system_params_ex1.json")
        sys_params = SystemParameters(filename)

        # now test the spawn connector (independent of the larger geojson translator
        self.spawn = SpawnConnector(sys_params)

        for b in self.gj.buildings:
            self.spawn.add_building(b)

    def test_spawn_init(self):
        self.assertIsNotNone(self.spawn)
        self.assertEqual(self.spawn.system_parameters.get_param("buildings.custom")[0]["load_model"], "Spawn", )

    def test_spawn_to_modelica(self):
        self.spawn.to_modelica(self.gj.scaffold)

    def test_spawn_to_modelica_and_run(self):
        self.spawn.to_modelica(self.gj.scaffold)

        # make sure the model can run using the ModelicaRunner class
        mr = ModelicaRunner()
        file_to_run = os.path.abspath(
            os.path.join(self.gj.scaffold.loads_path.files_dir, 'B5a6b99ec37f4de7f94020090', 'coupling.mo'),
        )
        run_path = Path(os.path.abspath(self.gj.scaffold.project_path)).parent
        exitcode = mr.run_in_docker(file_to_run, run_path=run_path)
        self.assertEqual(0, exitcode)

class SpawnModelConnectorTwoBuildingTest(unittest.TestCase):
    def setUp(self):
        root_dir, project_name = "tests/model_connectors/output", "spawn_two_building"

        if os.path.exists(os.path.join(root_dir, project_name)):
            shutil.rmtree(os.path.join(root_dir, project_name))

        # load in the example geojson with a single offie building
        filename = os.path.abspath("tests/model_connectors/data/spawn_geojson_ex2.json")
        self.gj = GeoJsonModelicaTranslator.from_geojson(filename)
        self.gj.scaffold_directory(root_dir, project_name)  # use the GeoJson translator to scaffold out the directory

        # load system parameter data
        filename = os.path.abspath("tests/model_connectors/data/spawn_system_params_ex2.json")
        sys_params = SystemParameters(filename)

        # now test the spawn connector (independent of the larger geojson translator
        self.spawn = SpawnConnector(sys_params)

        for b in self.gj.buildings:
            self.spawn.add_building(b)

    def test_spawn_to_modelica_and_run(self):
        self.spawn.to_modelica(self.gj.scaffold)

        # make sure the model can run using the ModelicaRunner class
        mr = ModelicaRunner()
        file_to_run = os.path.abspath(
            os.path.join(self.gj.scaffold.loads_path.files_dir, 'B5a6b99ec37f4de7f94021950', 'coupling.mo')
        )
        run_path = Path(os.path.abspath(self.gj.scaffold.project_path)).parent
        exitcode = mr.run_in_docker(file_to_run,  run_path=run_path)
        self.assertEqual(0, exitcode)


import os
import torch, cv2
import random
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage
import appro_dahu_3chanels as dahu
import math
from skimage.util import img_as_float
import skimage
import scipy.spatial.distance
from skimage.color import rgb2lab
from sklearn import mixture
import MBD

def tens2image(im):
    if im.size()[0] == 1:
        tmp = np.squeeze(im.numpy(), axis=0)
    else:
        tmp = im.numpy()
    if tmp.ndim == 2:
        return tmp
    else:
        return tmp.transpose((1, 2, 0))

def crop2fullmask(crop_mask, bbox, im=None, im_size=None, zero_pad=False, relax=0, mask_relax=True,
                  interpolation=cv2.INTER_CUBIC, scikit=False):
    if scikit:
        from skimage.transform import resize as sk_resize
    assert(not(im is None and im_size is None)), 'You have to provide an image or the image size  True'
    if im is None:
        im_si = im_size
    else:
        im_si = im.shape
    # Borers of image
    bounds = (0, 0, im_si[1] - 1, im_si[0] - 1)

    # Valid bounding box locations as (x_min, y_min, x_max, y_max)
    bbox_valid = (max(bbox[0], bounds[0]),
                  max(bbox[1], bounds[1]),
                  min(bbox[2], bounds[2]),
                  min(bbox[3], bounds[3]))

    # Bounding box of initial mask
    bbox_init = (bbox[0] + relax,
                 bbox[1] + relax,
                 bbox[2] - relax,
                 bbox[3] - relax)

    if zero_pad:
        # Offsets for x and y
        offsets = (-bbox[0], -bbox[1])
    else:
#        assert((bbox == bbox_valid).all())
        offsets = (-bbox_valid[0], -bbox_valid[1])

    # Simple per element addition in the tuple
    inds = tuple(map(sum, zip(bbox_valid, offsets + offsets)))

    if scikit:
        crop_mask = sk_resize(crop_mask, (bbox[3] - bbox[1] + 1, bbox[2] - bbox[0] + 1), order=0, mode='constant').astype(crop_mask.dtype)
    else:
        crop_mask = cv2.resize(crop_mask, (bbox[2] - bbox[0] + 1, bbox[3] - bbox[1] + 1), interpolation=interpolation)
    result_ = np.zeros(im_si)
    result_[bbox_valid[1]:bbox_valid[3] + 1, bbox_valid[0]:bbox_valid[2] + 1] = \
        crop_mask[inds[1]:inds[3] + 1, inds[0]:inds[2] + 1]

    result = np.zeros(im_si)
    if mask_relax:
        result[bbox_init[1]:bbox_init[3]+1, bbox_init[0]:bbox_init[2]+1] = \
            result_[bbox_init[1]:bbox_init[3]+1, bbox_init[0]:bbox_init[2]+1]
    else:
        result = result_

    return result

def overlay_mask(im, ma, colors=None, alpha=0.5):
    assert np.max(im) <= 1.0
    if colors is None:
        colors = np.load(os.path.join(os.path.dirname(__file__), 'pascal_map.npy'))/255.
    else:
        colors = np.append([[0.,0.,0.]], colors, axis=0);

    if ma.ndim == 3:
        assert len(colors) >= ma.shape[0], 'Not enough colors'
    ma = ma.astype(np.bool)
    im = im.astype(np.float32)

    if ma.ndim == 2:
        fg = im * alpha+np.ones(im.shape) * (1 - alpha) * colors[1, :3]   # np.array([0,0,255])/255.0
    else:
        fg = []
        for n in range(ma.ndim):
            fg.append(im * alpha + np.ones(im.shape) * (1 - alpha) * colors[1+n, :3])
    # Whiten background
    bg = im.copy()
    if ma.ndim == 2:
        bg[ma == 0] = im[ma == 0]
        bg[ma == 1] = fg[ma == 1]
        total_ma = ma
    else:
        total_ma = np.zeros([ma.shape[1], ma.shape[2]])
        for n in range(ma.shape[0]):
            tmp_ma = ma[n, :, :]
            total_ma = np.logical_or(tmp_ma, total_ma)
            tmp_fg = fg[n]
            bg[tmp_ma == 1] = tmp_fg[tmp_ma == 1]
        bg[total_ma == 0] = im[total_ma == 0]

    # [-2:] is s trick to be compatible both with opencv 2 and 3
    contours = cv2.findContours(total_ma.copy().astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
    cv2.drawContours(bg, contours[0], -1, (0.0, 0.0, 0.0), 1)

    return bg
import PIL
def overlay_masks(im, masks, alpha=0.5):
    colors = np.load(os.path.join(os.path.dirname(__file__), 'pascal_map.npy'))/255.

    if isinstance(masks, np.ndarray):
        masks = [masks]

    assert len(colors) >= len(masks), 'Not enough colors'

    ov = im.copy()
    ov_black = im.copy()*0

    imgZero = np.zeros(np.array(masks, dtype = np.uint8).shape,np.uint8)
    im = im.astype(np.float32)
    total_ma = np.zeros([im.shape[0], im.shape[1]])
    i = 1
    for ma in masks:
        ma = ma.astype(np.bool)
        fg = im * alpha+np.ones(im.shape) * (1 - alpha) * colors[i, :3]   # np.array([0,0,255])/255.0
        i = i + 1
        ov[ma == 1] = fg[ma == 1]
        total_ma += ma

        # [-2:] is s trick to be compatible both with opencv 2 and 3
        contours = cv2.findContours(ma.copy().astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
        cv2.drawContours(ov, contours[0], -1, (0.0, 0.0, 0.0), 1)
        cv2.drawContours(ov_black, contours[0], -1, (255, 255, 255), -1)#only draw a round
    ov[total_ma == 0] = im[total_ma == 0]

    return ov_black

from scipy import ndimage
def getPositon(distance_transform):
    a = np.mat(distance_transform)
    raw, column = a.shape# get the matrix of a raw and column
    _positon = np.argmax(a)# get the index of max in the a
    m, n = divmod(_positon, column)
    raw=m
    column=n
#    print "The raw is " ,m
#    print "The column is ",  n
#    print "The max of the a is ", a[m , n]
#    print(raw,column,a[m , n])
    return  raw,column

def iog_points(mask, pad_pixel=10):
    def find_point(id_x, id_y, ids):
        sel_id = ids[0][random.randint(0, len(ids[0]) - 1)]
        return [id_x[sel_id], id_y[sel_id]]

    inds_y, inds_x = np.where(mask > 0.5)
    [h,w]=mask.shape
    left = find_point(inds_x, inds_y, np.where(inds_x <= np.min(inds_x)))
    right = find_point(inds_x, inds_y, np.where(inds_x >= np.max(inds_x)))
    top = find_point(inds_x, inds_y, np.where(inds_y <= np.min(inds_y)))
    bottom = find_point(inds_x, inds_y, np.where(inds_y >= np.max(inds_y)))

    x_min=left[0]
    x_max=right[0]
    y_min=top[1]
    y_max=bottom[1]

    map_xor = (mask > 0.5)
    h,w = map_xor.shape
    map_xor_new = np.zeros((h+2,w+2))
    map_xor_new[1:(h+1),1:(w+1)] = map_xor[:,:]
    distance_transform=ndimage.distance_transform_edt(map_xor_new)
    distance_transform_back = distance_transform[1:(h+1),1:(w+1)]
    raw,column=getPositon(distance_transform_back)
    center_point = [column,raw]

    left_top=[max(x_min-pad_pixel,0),  max(y_min-pad_pixel,0)]
    left_bottom=[max(x_min-pad_pixel ,0),     min(y_max+pad_pixel,h)]
    right_top=[min(x_max+pad_pixel,w),          max(y_min-pad_pixel,0)]
    righr_bottom=[min(x_max+pad_pixel ,w),    min(y_max+pad_pixel,h)]
    a=[center_point,left_top,left_bottom,right_top,righr_bottom]

    return np.array(a)

def get_bbox(mask, points=None, pad=0, zero_pad=False):
    if points is not None:
        inds = np.flip(points.transpose(), axis=0)
    else:
        inds = np.where(mask > 0)

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

    if zero_pad:
        x_min_bound = -np.inf
        y_min_bound = -np.inf
        x_max_bound = np.inf
        y_max_bound = np.inf
    else:
        x_min_bound = 0
        y_min_bound = 0
        x_max_bound = mask.shape[1] - 1
        y_max_bound = mask.shape[0] - 1

    x_min = max(inds[1].min() - pad, x_min_bound)
    y_min = max(inds[0].min() - pad, y_min_bound)
    x_max = min(inds[1].max() + pad, x_max_bound)
    y_max = min(inds[0].max() + pad, y_max_bound)

    return x_min, y_min, x_max, y_max

def crop_from_bbox(img, bbox, zero_pad=False):
    # Borders of image
    bounds = (0, 0, img.shape[1] - 1, img.shape[0] - 1)

    # Valid bounding box locations as (x_min, y_min, x_max, y_max)
    bbox_valid = (max(bbox[0], bounds[0]),
                  max(bbox[1], bounds[1]),
                  min(bbox[2], bounds[2]),
                  min(bbox[3], bounds[3]))

    if zero_pad:
        # Initialize crop size (first 2 dimensions)
        crop = np.zeros((bbox[3] - bbox[1] + 1, bbox[2] - bbox[0] + 1), dtype=img.dtype)

        # Offsets for x and y
        offsets = (-bbox[0], -bbox[1])

    else:
        assert(bbox == bbox_valid)
        crop = np.zeros((bbox_valid[3] - bbox_valid[1] + 1, bbox_valid[2] - bbox_valid[0] + 1), dtype=img.dtype)
        offsets = (-bbox_valid[0], -bbox_valid[1])

    # Simple per element addition in the tuple
    inds = tuple(map(sum, zip(bbox_valid, offsets + offsets)))

    img = np.squeeze(img)
    if img.ndim == 2:
        crop[inds[1]:inds[3] + 1, inds[0]:inds[2] + 1] = \
            img[bbox_valid[1]:bbox_valid[3] + 1, bbox_valid[0]:bbox_valid[2] + 1]
    else:
        crop = np.tile(crop[:, :, np.newaxis], [1, 1, 3])  # Add 3 RGB Channels
        crop[inds[1]:inds[3] + 1, inds[0]:inds[2] + 1, :] = \
            img[bbox_valid[1]:bbox_valid[3] + 1, bbox_valid[0]:bbox_valid[2] + 1, :]

    return crop

def fixed_resize(sample, resolution, flagval=None):

    if flagval is None:
        if ((sample == 0) | (sample == 1)).all():
            flagval = cv2.INTER_NEAREST
        else:
            flagval = cv2.INTER_CUBIC

    if isinstance(resolution, int):
        tmp = [resolution, resolution]
        tmp[np.argmax(sample.shape[:2])] = int(round(float(resolution)/np.min(sample.shape[:2])*np.max(sample.shape[:2])))
        resolution = tuple(tmp)

    if sample.ndim == 2 or (sample.ndim == 3 and sample.shape[2] == 3):
        sample = cv2.resize(sample, resolution[::-1], interpolation=flagval)
    else:
        tmp = sample
        sample = np.zeros(np.append(resolution, tmp.shape[2]), dtype=np.float32)
        for ii in range(sample.shape[2]):
            sample[:, :, ii] = cv2.resize(tmp[:, :, ii], resolution[::-1], interpolation=flagval)
    return sample

def crop_from_mask(img, mask, relax=0, zero_pad=False):
    if mask.shape[:2] != img.shape[:2]:
        mask = cv2.resize(mask, dsize=tuple(reversed(img.shape[:2])), interpolation=cv2.INTER_NEAREST)

    assert(mask.shape[:2] == img.shape[:2])
    bbox = get_bbox(mask, pad=relax, zero_pad=zero_pad)

    if bbox is None:
        return None

    crop = crop_from_bbox(img, bbox, zero_pad)

    return crop

def make_gaussian(size, sigma=10, center=None, d_type=np.float64):
    """ Make a square gaussian kernel.
    size: is the dimensions of the output gaussian
    sigma: is full-width-half-maximum, which
    can be thought of as an effective radius.
    """

    x = np.arange(0, size[1], 1, float)
    y = np.arange(0, size[0], 1, float)
    y = y[:, np.newaxis]

    if center is None:
        x0 = y0 = size[0] // 2
    else:
        x0 = center[0]
        y0 = center[1]

    return np.exp(-4 * np.log(2) * ((x - x0) ** 2 + (y - y0) ** 2) / sigma ** 2).astype(d_type)

def make_gt(image, img, labels, sigma=10, one_mask_per_point=False):
    """ Make the ground-truth for  landmark.
    img: the original color image
    labels: label with the Gaussian center(s) [[x0, y0],[x1, y1],...]
    sigma: sigma of the Gaussian.
    one_mask_per_point: masks for each point in different channels?
    """

    h, w = img.shape[:2]
    if labels is None:
        gt = make_gaussian((h, w), center=(h//2, w//2), sigma=sigma)
        gt_0 = np.zeros(shape=(h, w), dtype=np.float64)
        gt_0 = gt
        gt_1 = np.zeros(shape=(h, w), dtype=np.float64)
        gt_2 = np.zeros(shape=(h, w), dtype=np.float64)

        gtout = np.zeros(shape=(h, w, 3))
        gtout[:, :, 0]=gt_0
        gtout[:, :, 1]=gt_1
        gtout[:, :, 2]=gt_2

        gtout = gtout.astype(dtype=img.dtype) #(0~1)
        return gtout
    else:
        labels = np.array(labels)
        if labels.ndim == 1:
            labels = labels[np.newaxis]
            gt_0 = np.zeros(shape=(h, w), dtype=np.float64)
            gt_1 = np.zeros(shape=(h, w), dtype=np.float64)
            gt_2 = np.zeros(shape=(h, w), dtype=np.float64)

            gt_0 = np.maximum(gt_0, make_gaussian((h, w), center=labels[0, :], sigma=sigma))

        else:
            gt_0 = np.zeros(shape=(h, w), dtype=np.float64)
            gt_1 = np.zeros(shape=(h, w), dtype=np.float64)
            gt_2 = np.zeros(shape=(h, w), dtype=np.float64)

            # for ii in range(1,labels.shape[0]):
            #     gt_1 = np.maximum(gt_1, make_gaussian((h, w), center=labels[ii, :], sigma=sigma))

            gt_0 = np.maximum(gt_0, make_gaussian((h, w), center=labels[0, :], sigma=sigma))

            # Euclidean distance map

            ### compute the Dahu distance map

            fg =  np.ones(shape=(h, w), dtype=np.uint8)
            fg[labels[1, :][1], :]  = 0
            fg[:, labels[1, :][0]]  = 0
            fg[labels[4, :][1], :]  = 0
            fg[:, labels[4, :][0]]  = 0
            dmap_fg = ndimage.distance_transform_edt(fg)

            dmap = np.exp(-4 * np.log(2) * (dmap_fg** 2) / sigma ** 2)
            gt_1 = np.maximum(gt_1, dmap)

            ### compute the Dahu distance map

            bg =  np.zeros(shape=(h, w), dtype=np.uint8)
            bg[labels[1, :][1], :]  = 255
            bg[:, labels[1, :][0]]  = 255
            bg[labels[4, :][1], :]  = 255
            bg[:, labels[4, :][0]]  = 255

            bg[0, :]  = 255
            bg[:, 0]  = 255
            bg[0, :]  = 255
            bg[:, 0]  = 255

            # height = h * 2 - 1
            # width = w * 2 - 1
            # F_bg = cv2.resize(bg, (width, height))
            # F_bg = np.array(F_bg, dtype="uint8")  # convert to uint8

            # dmap_scalar_bg = dahu.appro_dahu_scribble(image, F_bg)
            dmap_scalar_bg = MBD.MBD_waterflow(image, bg)

            dmap_scalar_bg[0:labels[1, :][1], :]  = 0
            dmap_scalar_bg[:, 0:labels[1, :][0]]  = 0
            dmap_scalar_bg[labels[4, :][1]:, :]  = 0
            dmap_scalar_bg[:, labels[4, :][0]:]  = 0

            dmap = dmap_scalar_bg/ (np.max(dmap_scalar_bg) + 0.001) * 255

            ############BIC

            (n_rows, n_cols, n_channels) = image.shape
            img_size = math.sqrt(n_rows * n_cols)
            border_thickness = int(math.floor(0.02 * img_size))

            img_lab = img_as_float(rgb2lab(image))
            # img_lab = img_as_float(img)

            # A = np.sum(img_lab, axis=2)
            # A[labels[1, :][1]:labels[4, :][1], labels[1, :][0]:labels[4, :][0]]  = 0
            #
            # nonzero = np.nonzero(A)
            # nonzero_row = nonzero[0]
            # nonzero_col = nonzero[1]
            # color = []
            # for row, col in zip(nonzero_row, nonzero_col):
            #     color.append(img_lab[row,col])
            #
            # u = np.zeros((h, w))
            # if color:
            #     h, w, nchannel = img_lab.shape
            #     n_comp = 5
            #
            #     gmm_bg = mixture.BayesianGaussianMixture(n_comp, covariance_type='full', tol=0.001, random_state=0)
            #     gmm_bg.fit(color)
            #     print("bg:", gmm_bg.weights_)
            #
            #     u = gmm_bg.score_samples(img_lab.reshape((w * h, nchannel)))
            #     u = u.reshape((h, w))

            #################### 4 borders

            px_left = img_lab[0:border_thickness, :, :]
            px_right = img_lab[n_rows - border_thickness - 1:-1, :, :]
            px_top = img_lab[:, 0:border_thickness, :]
            px_bottom = img_lab[:, n_cols - border_thickness - 1:-1, :]

            px_mean_left = np.mean(px_left, axis=(0, 1))
            px_mean_right = np.mean(px_right, axis=(0, 1))
            px_mean_top = np.mean(px_top, axis=(0, 1))
            px_mean_bottom = np.mean(px_bottom, axis=(0, 1))

            px_left = px_left.reshape((n_cols * border_thickness, 3))
            px_right = px_right.reshape((n_cols * border_thickness, 3))
            px_top = px_top.reshape((n_rows * border_thickness, 3))
            px_bottom = px_bottom.reshape((n_rows * border_thickness, 3))

            cov_left = np.cov(px_left.T)
            cov_right = np.cov(px_right.T)

            cov_top = np.cov(px_top.T)
            cov_bottom = np.cov(px_bottom.T)

            cov_left = np.linalg.pinv(cov_left)
            cov_right = np.linalg.pinv(cov_right)

            cov_top = np.linalg.pinv(cov_top)
            cov_bottom = np.linalg.pinv(cov_bottom)

            u_left = np.zeros((h,w))
            u_right = np.zeros((h,w))
            u_top = np.zeros((h,w))
            u_bottom = np.zeros((h,w))

            u_final = np.zeros((h,w))
            img_lab_unrolled = img_lab.reshape(img_lab.shape[0] * img_lab.shape[1], 3)

            if np.sum(px_mean_left) > 0:
                px_mean_left_2 = np.zeros((1, 3))
                px_mean_left_2[0, :] = px_mean_left
                u_left = scipy.spatial.distance.cdist(img_lab_unrolled, px_mean_left_2, 'mahalanobis', VI=cov_left)
                u_left = u_left.reshape((img_lab.shape[0], img_lab.shape[1]))
            else:
                u_left = np.zeros((h, w))

            if np.sum(px_mean_right) > 0:
                px_mean_right_2 = np.zeros((1, 3))
                px_mean_right_2[0, :] = px_mean_right
                u_right = scipy.spatial.distance.cdist(img_lab_unrolled, px_mean_right_2, 'mahalanobis', VI=cov_right)
                u_right = u_right.reshape((img_lab.shape[0], img_lab.shape[1]))
            else:
                u_right = np.zeros((h, w))

            if np.sum(px_mean_top) > 0:
                px_mean_top_2 = np.zeros((1, 3))
                px_mean_top_2[0, :] = px_mean_top
                u_top = scipy.spatial.distance.cdist(img_lab_unrolled, px_mean_top_2, 'mahalanobis', VI=cov_top)
                u_top = u_top.reshape((img_lab.shape[0], img_lab.shape[1]))
            else:
                u_top = np.zeros((h, w))

            if np.sum(px_mean_bottom) > 0:
                px_mean_bottom_2 = np.zeros((1, 3))
                px_mean_bottom_2[0, :] = px_mean_bottom
                u_bottom = scipy.spatial.distance.cdist(img_lab_unrolled, px_mean_bottom_2, 'mahalanobis', VI=cov_bottom)
                u_bottom = u_bottom.reshape((img_lab.shape[0], img_lab.shape[1]))
            else:
                u_bottom = np.zeros((h, w))

            max_u_left = np.max(u_left)
            max_u_right = np.max(u_right)
            max_u_top = np.max(u_top)
            max_u_bottom = np.max(u_bottom)

            u_left = u_left / (max_u_left + 0.001)
            u_right = u_right / (max_u_right + 0.001)
            u_top = u_top / (max_u_top + 0.001)
            u_bottom = u_bottom / (max_u_bottom + 0.001)

            u_max = np.maximum(np.maximum(np.maximum(u_left, u_right), u_top), u_bottom)
            u_min = np.minimum(np.minimum(np.minimum(u_left, u_right), u_top), u_bottom)

            u_final = (u_left + u_right + u_top + u_bottom) - u_max
            u_final = u_final/ (np.max(u_final) + 0.001) * 255
            u_final = np.asarray(u_final, dtype=np.uint8)
            u_final = cv2.medianBlur(u_final, 3)

            u_final[0:labels[1, :][1], :]  = 0
            u_final[:, 0:labels[1, :][0]]  = 0
            u_final[labels[4, :][1]:, :]  = 0
            u_final[:, labels[4, :][0]:]  = 0

            u_final = u_final/ (np.max(u_final) + 0.001) * 255

            ### sum

            sal = u_final/ (np.max(u_final) + 0.001) +    dmap/ (np.max(dmap) + 0.001)

            xv, yv = np.meshgrid(np.arange(dmap_scalar_bg.shape[1]), np.arange(dmap_scalar_bg.shape[0]))
            w2 = labels[0, 0]
            h2 = labels[0, 1]

            C = 1 - np.sqrt(np.power(xv - w2, 2) + np.power(yv - h2, 2)) / math.sqrt(np.power(w2, 2) + np.power(h2, 2))

            sal = sal * C

            sal = sal/ (np.max(sal) + 0.001) * 255

            gt_2 = np.maximum(gt_2, sal)

    gt = np.zeros(shape=(h, w, 3))
    gt[:, :, 0]=gt_0
    gt[:, :, 1]=gt_1
    gt[:, :, 2]=gt_2

    # gt = gt.astype(dtype=img.dtype) #(0~1)
    return gt

def cstm_normalize(im, max_value):
    """
    Normalize image to range 0 - max_value
    """
    imn = max_value*(im - im.min()) / max((im.max() - im.min()), 1e-8)
    return imn

def generate_param_report(logfile, param):
    log_file = open(logfile, 'w')
    for key, val in param.items():
        log_file.write(key+':'+str(val)+'\n')
    log_file.close()


import sys
import numpy as np
import pyqtgraph as pg
from PySide import QtCore, QtGui
from ventana_MP_conversion import Ui_Form
import matplotlib as mpl

mpl.use('Qt4Agg')
mpl.rcParams['backend.qt4']='PySide'
import matplotlib.pyplot as plt
from show_cursor import SnaptoCursor, Cursor

class Reactor_mp_conversion(QtGui.QWidget, Ui_Form):

    def __init__(self):

        QtGui.QWidget.__init__(self)
        self.setupUi(self)
        self.le_molA.setText('1')
        self.le_molB.setText('1')
        self.cb_orden.setCurrentIndex(2)
        self.le_temp_fin.setText('393')
        self.le_concentracion_ini.setText('6.65')
        self.le_ener_act.setText('83680')
        self.le_k.setText('55000000')
        self.le_volumen_2.setText('912')
        self.le_caudal.setText('1.26')

        self.deltaT = 0.5
        self.R = 8.3143
        self.plot.setLabel('left', 'Conversión')
        self.plot.setLabel('bottom', 'Volumen', units='L')

        self.btn_mostrar_resultados.setDisabled(True)

        self.btn_ejecutar.clicked.connect(self.ejecutar)
        self.btn_mostrar_resultados.clicked.connect(self.mostrar_resultado)
        self.btn_reset.clicked.connect(self.resetear)
        self.btn_cerrar.clicked.connect(self.close)

    def leerDatos(self):

        self.molA = float(self.le_molA.text())
        self.molB = float(self.le_molB.text())
        self.orden = int(self.cb_orden.currentText()[0].strip())
        self.temp_fin = float(self.le_temp_fin.text())
        self.cao = float(self.le_concentracion_ini.text())
        self.ener_act = float(self.le_ener_act.text())
        self.k = float(self.le_k.text())
        self.volumen = float(self.le_volumen_2.text())
        self.caudal = float(self.le_caudal.text())

    def calcularK(self):

        self.K = self.k * np.exp(-self.ener_act / (self.R * self.temp_fin))

    def f0(self, vol):
        return vol * self.K / self.caudal / self.cao

    def f1(self, vol):
        return vol * self.K / (self.caudal + self.molA * vol * self.K)

    def f2(self, vol):

        a = 1
        b = -((2 / self.molA) + (self.caudal / vol / self.K / self.cao))
        c = 1 / (self.molA ** 2)

        xf1 = (-b + ((b ** 2 - 4 * a * c)) ** 0.5) / (2 * a)
        xf2 = (-b - ((b ** 2 - 4 * a * c)) ** 0.5) / (2 * a)

        if xf1 <= 1:
            return xf1
        else:
            return xf2

    def plotear(self):

        self.x = np.arange(0.5, self.volumen+self.deltaT, self.deltaT)

        if self.orden == 0:
            f = np.vectorize(self.f0)

        elif self.orden == 1:
            f = np.vectorize(self.f1)

        else:
            f = np.vectorize(self.f2)

        self.y = f(self.x)

        self.plot.clear()
        curve = self.plot.plot(self.x, self.y, pen=None)  ## setting pen=None disables line drawing
        curve.curve.setClickable(True)
        curve.setPen('w')  ## white pen

        curve.setShadowPen(pg.mkPen((70, 70, 30), width=6, cosmetic=True))

    def resetear(self):

        self.le_molA.clear()
        self.le_molB.clear()
        self.cb_orden.setCurrentIndex(0)
        self.le_temp_fin.clear()
        self.le_concentracion_ini.clear()
        self.le_ener_act.clear()
        self.le_k.clear()
        self.le_caudal.clear()
        self.le_volumen.clear()
        self.le_volumen_2.clear()
        self.le_xa.clear()
        self.plot.clear()

        self.btn_mostrar_resultados.setDisabled(True)

    def ejecutar(self):

        if self.le_molA.text() == "" or self.le_molB.text() == "" or self.le_temp_fin.text() == "" or self.le_concentracion_ini.text() == "" or self.le_ener_act.text() == "" or self.le_k.text() == "" or self.le_caudal.text() == "" or self.le_volumen_2.text() == "":
            QtGui.QMessageBox.warning(self, "Error en la ejecución", "Alguna/s de las celdas de datos está/n vacía/s. Por favor, revise que ha introducido correctamente todos los datos.", QtGui.QMessageBox.Cancel, QtGui.QMessageBox.NoButton)
        else:
            self.leerDatos()
            self.calcularK()
            self.plotear()

            self.le_volumen.setText(str(self.volumen))

            if self.orden == 0:
                self.le_xa.setText(str(float("{0:.2f}".format(self.f0(self.volumen)))))

            elif self.orden == 1:
                self.le_xa.setText(str(float("{0:.2f}".format(self.f1(self.volumen)))))

            else:
                self.le_xa.setText(str(float("{0:.2f}".format(self.f2(self.volumen)))))

            self.btn_mostrar_resultados.setEnabled(True)

    def mostrar_resultado(self):

        self.fig, self.conv = plt.subplots()

        self.conv.set_title('RESULTADO')

        self.conv.set_xlim([min(self.x), max(self.x)])
        self.conv.set_ylim([min(self.y), max(self.y)])

        self.conv.set_xlabel('Volumen (L)')
        self.conv.set_ylabel('Conversión')

        # cursor = Cursor(ax)
        self.cursor = SnaptoCursor(self.conv, self.x, self.y)
        plt.connect('motion_notify_event', self.cursor.mouse_move)

        self.conv.plot(self.x, self.y, linewidth = 2)

        # Hace que matlplolib controle todas las figuras con sus propios hilos de forma independiente a la gui principal
        # sustituye a la funcion plt.show()
        plt.ion()
        plt.show()

if __name__ == '__main__':

    try:
        app = QtGui.QApplication(sys.argv)
    except RuntimeError:
        pass

    # MainWindow = QtGui.QWidget()
    ui = Reactor_mp_conversion()
    # ui.setupUi(MainWindow)
    ui.show()
    app.exec_()


"""5 Train Contrastive.

Train or fine-tune InceptionV3 architecture to fit van-Gogh data set.

Author: Lucas David -- <lucasolivdavid@gmail.com>
Licence: MIT License 2016 (c)

"""

import os

import tensorflow as tf
from keras import backend as K, callbacks, optimizers
from sacred import Experiment
from sacred.utils import apply_backspaces_and_linefeeds

from connoisseur.models import build_siamese_model
from connoisseur.utils.image import BalancedDirectoryPairsSequence, ImageDataGenerator

from base import contrastive_loss

ex = Experiment('5-train-contrastive')

ex.captured_out_filter = apply_backspaces_and_linefeeds

@ex.config
def config():
    image_shape = [299, 299, 3]
    batch_size = 150
    device = '/gpu:0'
    data_dir = '/datasets/vangogh'
    train_dir = '/datasets/vangogh/vgdb_2016/extracted_patches_256/train'
    valid_dir = '/datasets/vangogh/vgdb_2016/extracted_patches_256/valid'
    balanced_classes = True

    train_augmentations = []
    train_shuffle = True
    train_dataset_seed = 14
    valid_augmentations = []
    valid_shuffle = True
    valid_dataset_seed = 9

    arch = 'inejc'
    network_weights = None
    pre_trained_weights = None

    opt_params = {'lr': 0.005}
    ckpt_file = '/work/vangogh/5-train-contrastive/ckpt/optimal.hdf5'
    nb_epoch = 10000
    train_samples_per_epoch = 13350
    nb_val_samples = 2048
    nb_worker = 1
    early_stop_patience = 300
    reduce_lr_on_plateau_patience = 100
    tensorboard_file = './logs/loss:contrastive'

    initial_epoch = 0

@ex.automain
def run(batch_size, data_dir, train_dir, valid_dir, balanced_classes,
        image_shape,
        train_augmentations, train_shuffle, train_dataset_seed,
        valid_augmentations, valid_shuffle, valid_dataset_seed,
        device, opt_params, ckpt_file, pre_trained_weights,
        arch, network_weights,
        train_samples_per_epoch, nb_epoch, nb_val_samples, nb_worker,
        early_stop_patience, reduce_lr_on_plateau_patience, tensorboard_file,
        initial_epoch):
    os.makedirs(os.path.dirname(ckpt_file), exist_ok=True)

    tf_config = tf.ConfigProto(allow_soft_placement=True)
    tf_config.gpu_options.allow_growth = True
    sess = tf.Session(config=tf_config)
    K.set_session(sess)

    g = ImageDataGenerator(
        featurewise_center=True,
        horizontal_flip=True,
        vertical_flip=True,
        rotation_range=30,
        height_shift_range=.2,
        width_shift_range=.2,
        rescale=2. / 255.,
        fill_mode='reflect')
    g.mean = 1.
    train_data = BalancedDirectoryPairsSequence(
        train_dir,
        image_data_generator=g, target_size=image_shape[:2],
        augmentations=train_augmentations, batch_size=batch_size,
        balanced_classes=balanced_classes, shuffle=train_shuffle,
        seed=train_dataset_seed)
    valid_data = BalancedDirectoryPairsSequence(
        valid_dir,
        image_data_generator=g, target_size=image_shape[:2],
        augmentations=valid_augmentations, batch_size=batch_size,
        balanced_classes=balanced_classes, shuffle=valid_shuffle,
        seed=valid_dataset_seed)

    with tf.device(device):
        model = build_siamese_model(x_shape=image_shape, arch=arch, weights=network_weights)
        opt = optimizers.Adam(**opt_params)
        model.compile(optimizer=opt, loss=contrastive_loss)

        if pre_trained_weights:
            model.load_weights(pre_trained_weights)
        elif initial_epoch > 0:
            print('re-loading weights...')
            model.load_weights(ckpt_file)

        print('training network...')
        try:
            model.fit_generator(
                train_data, samples_per_epoch=train_samples_per_epoch,
                nb_epoch=nb_epoch,
                validation_data=valid_data, nb_val_samples=nb_val_samples,
                nb_worker=nb_worker,
                callbacks=[
                    callbacks.ReduceLROnPlateau(min_lr=1e-10, patience=reduce_lr_on_plateau_patience),
                    callbacks.EarlyStopping(patience=early_stop_patience),
                    callbacks.TensorBoard(tensorboard_file, histogram_freq=5),
                    callbacks.ModelCheckpoint(ckpt_file, verbose=1, save_best_only=True),
                ],
                initial_epoch=initial_epoch)
        except KeyboardInterrupt:
            print('training interrupted by user.')
        else:
            print('done.')


from Token import *
from Lexer import *
class Wrapper:
    def __init__(self,value,myType="Main"):
        self.type=myType
        if myType=="Main":
            self.value=Lex(value)
        else:
            self.value=value
        self.nestGroups()
        if myType in ["Main","Group"]:
            self.nestCommands()
        if myType in ["Command","Expression","List"]:
            self.nestLists()
            self.nestExpressions()
    def nestLists(self):
        firstIndex=-1
        secondIndex=-1
        nestingLevel=0
        for i in range(len(self.value)):
            if(self.value[i].value=="["):
                nestingLevel+=1
                if(nestingLevel==1):
                    firstIndex=i
            elif(self.value[i].value=="]"):
                nestingLevel-=1
                if(nestingLevel==0):
                    secondIndex=i
                    newBracket=[]
                    for j in range(firstIndex+1,secondIndex):
                        newBracket.append(self.value[j])
                    self.value[firstIndex]=Wrapper(newBracket,"List")
                    for j in range(secondIndex-firstIndex):
                        del self.value[firstIndex+1]
                    self.nestLists()
                    break
        if self.type=="List":
            for i in range(len(self.value)-1,-1,-1):
                if self.value[i].type=="Symbol":
                    del self.value[i]
    def nestGroups(self):
        firstIndex=-1
        secondIndex=-1
        nestingLevel=0
        for i in range(len(self.value)):
            if(self.value[i].value=="{"):
                nestingLevel+=1
                if(nestingLevel==1):
                    firstIndex=i
            elif(self.value[i].value=="}"):
                nestingLevel-=1
                if(nestingLevel==0):
                    secondIndex=i
                    newBracket=[]
                    for j in range(firstIndex+1,secondIndex):
                        newBracket.append(self.value[j])
                    self.value[firstIndex]=Wrapper(newBracket,"Group")
                    for j in range(secondIndex-firstIndex):
                        del self.value[firstIndex+1]
                    self.nestGroups()
                    break
    def nestCommands(self):
        command=[]
        newValue=[]
        for i in self.value:
            if(i.value==";"):
                newValue.append(Wrapper(command,"Command"))
                command=[]
            else:
                command.append(i)
        if(not len(command)==0):
            raise Exception("The last command does not have a semi colon")
        self.value=newValue
    def nestExpressions(self):
        firstIndex=-1
        secondIndex=-1
        nestingLevel=0
        for i in range(len(self.value)):
            if(self.value[i].value=="("):
                nestingLevel+=1
                if(nestingLevel==1):
                    firstIndex=i
            elif(self.value[i].value==")"):
                nestingLevel-=1
                if(nestingLevel==0):
                    secondIndex=i
                    newBracket=[]
                    for j in range(firstIndex+1,secondIndex):
                        newBracket.append(self.value[j])
                    self.value[firstIndex]=Wrapper(newBracket,"Expression")
                    for j in range(secondIndex-firstIndex):
                        del self.value[firstIndex+1]
                    self.nestExpressions()
                    break
        operators=["+","-","*","/","%","&","|","^","<",">","&&","||","==","<=",">="]
        for i in range(len(self.value)):
            if(not i<len(self.value)-2):
                break
            if(self.value[i].type in ["Identifier","Expression"] or (self.value[i].__class__.__name__=="Token" and not self.value[i].type=="Symbol")):
                if(self.value[i+1].type=="Symbol"):
                    if(self.value[i+2].type=="Symbol" and (self.value[i+1].value+self.value[i+2].value) in operators):
                        if(not i+3<len(self.value)):
                            raise Exception("Ill Formatted Expression")
                        else:
                            if(self.value[i+3].type in ["Identifier","Expression"] or self.value[i+3].__class__.__name__=="Token"):
                                if(len(self.value)>4):
                                    newValue=[]
                                    for o in range(4):
                                        newValue.append(self.value[i+o])
                                    newValue[1]=Token("Symbol",newValue[1].value+newValue[2].value)
                                    del newValue[2]
                                    self.value[i]=Wrapper(newValue,"Expression")
                                    for o in range(3):
                                        del self.value[i+1]
                                    self.nestExpressions()
                                    break
                                else:
                                    self.value[1]=Token("Symbol",self.value[1].value+self.value[2].value)
                                    del self.value[2]
                    elif(self.value[i+1].value in operators):
                        if(self.value[i+2].type in ["Identifier","Expression"] or self.value[i+2].__class__.__name__=="Token"):
                            if(len(self.value)>3):
                                    newValue=[]
                                    for o in range(3):
                                        newValue.append(self.value[i+o])
                                    self.value[i]=Wrapper(newValue,"Expression")
                                    for o in range(2):
                                        del self.value[i+1]
                                    self.nestExpressions()
                                    break
    def printMe(self,layer=0):
        for i in self.value:
            if(not i.__class__.__name__=="Token"):
                print("\t"*layer+i.type)
                i.printMe(layer+1)
            elif(i.__class__.__name__=="Token"):
                i.printMe(layer)