import pygame
import time

from app.config.settings import *
from app.states.menu.title_screen import TitleMenu

DEFAULT_ACTIONS = {
    "left": False,
    "right": False,
    "up": False,
    "down": False,
    "crouch": False,
    "attack": False,
    "cast": False,
    "switch_weapon": False,
    "switch_magic": False,
    "pause": False,
    "action2": False,
    "start": False,
    "yes": False,
    "time_trigger": False,
}

class Game:
    def __init__(self):
        pygame.init()
        pygame.display.set_caption('Wraith Of The Worldbreaker')
        self.clock = pygame.time.Clock()

        # window variables
        self.GAME_W, self.GAME_H = WIDTH, HEIGHT  # 480, 270
        self.SCREEN_WIDTH, self.SCREEN_HEIGHT, self.GMID_W, self.GMID_H = WIDTH, HEIGHT, self.GAME_W / 2, self.GAME_H / 2
        self.game_canvas = pygame.Surface((self.GAME_W, self.GAME_H))
        self.screen = pygame.display.set_mode((self.SCREEN_WIDTH, self.SCREEN_HEIGHT))

        # event variables
        self.running, self.playing, self.paused = True, True, False
        self.actions = DEFAULT_ACTIONS
        self.dt, self.prev_time = 0, 0

        # main state stack
        self.state_stack = []

        # font variables
        self.default_fontsize = 20
        self.default_font = pygame.font.Font('font/PressStart2P-vaV7.ttf', 20)

        # run init methods
        self.init_states()

        self.timer_event = pygame.USEREVENT + 1
        pygame.time.set_timer(self.timer_event, 10000)

    def game_loop(self):
        while self.playing:
            self.get_dt()
            self.get_events()
            self.update()
            self.render()
            self.clock.tick(FPS)

    def get_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.playing = False
                self.running = False
            elif event.type == self.timer_event:
                self.actions['time_trigger'] = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.playing = False
                    self.running = False
                if event.key == pygame.K_a:
                    self.actions['left'] = True
                if event.key == pygame.K_d:
                    self.actions['right'] = True
                if event.key == pygame.K_w:
                    self.actions['up'] = True
                if event.key == pygame.K_s:
                    self.actions['down'] = True
                if event.key == pygame.K_p:
                    self.actions['pause'] = True
                if event.key == pygame.K_o:
                    self.actions['action2'] = True
                if event.key == pygame.K_y:
                    self.actions['yes'] = True
                if event.key == pygame.K_q:
                    self.actions['cast'] = True
                if event.key == pygame.K_x:
                    self.actions['switch_weapon'] = True
                if event.key == pygame.K_c:
                    self.actions['switch_magic'] = True
                if event.key == pygame.K_RETURN:
                    self.actions['start'] = True
                if event.key == pygame.K_SPACE:
                    self.actions['attack'] = True

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_a:
                    self.actions['left'] = False
                if event.key == pygame.K_d:
                    self.actions['right'] = False
                if event.key == pygame.K_w:
                    self.actions['up'] = False
                if event.key == pygame.K_s:
                    self.actions['down'] = False
                if event.key == pygame.K_p:
                    self.actions['pause'] = False
                if event.key == pygame.K_o:
                    self.actions['action2'] = False
                if event.key == pygame.K_y:
                    self.actions['yes'] = False
                if event.key == pygame.K_q:
                    self.actions['cast'] = False
                if event.key == pygame.K_x:
                    self.actions['switch_weapon'] = False
                if event.key == pygame.K_c:
                    self.actions['switch_magic'] = False
                if event.key == pygame.K_RETURN:
                    self.actions['start'] = False
                if event.key == pygame.K_SPACE:
                    self.actions['attack'] = False

    def update(self):
        self.state_stack[-1].update(self.dt, self.actions)

    def render(self):
        # Render current state to the canvas
        self.state_stack[-1].render(self.game_canvas)
        # Render canvas to screen
        self.screen.blit(pygame.transform.scale(self.game_canvas, (self.SCREEN_WIDTH, self.SCREEN_HEIGHT)), (0, 0))
        pygame.display.flip()

    def get_dt(self):
        now = time.time()
        self.dt = now - self.prev_time
        self.prev_time = now

    def draw_text(self, surface, text='', color='black', x=0, y=0, font='default', size='default'):
        if (font == 'default') and (size == 'default'):
            font = self.default_font
        elif (font == 'default') and (not size == 'default'):
            font = pygame.font.Font(pygame.font.get_default_font(), size)
        elif size == 'default':
            font = pygame.font.Font('font/' + font, self.default_fontsize)
        # font = pygame.font.Font(os.path.join(self.font_dir, "PressStart2P-vaV7.ttf"), 20)
        else:
            font = pygame.font.Font(font, size)

        text_surface = font.render(text, True, color)
        # text_surface.set_colorkey((0,0,0))
        text_rect = text_surface.get_rect()
        text_rect.center = (x, y)
        text_rect.left = x
        surface.blit(text_surface, text_rect)

    def init_states(self):
        # change here
        self.title_screen = TitleMenu(self)
        self.state_stack.append(self.title_screen)

    def reset_keys(self):
        for action in self.actions:
            self.actions[action] = False


# AC 76ms

class Solution:
    # @param {string} s
    # @param {string} t
    # @return {boolean}
    def alphas(self, s):
        d = {}
        for (i, a) in enumerate(s):
            if a in d:
                d[a].append(i)
            else:
                d[a] = [i]
        # print d
        nums = {}
        for a in d:
            l = len(d[a])
            if l in nums:
                nums[l].append([a, d[a]])
            else:
                nums[l] = [[a, d[a]]]
        return nums

    def find(self, locs, als):
        # print locs
        for [b, ls] in als:
            # print ls
            if len(ls) != len(locs):
                continue
            for i in range(len(ls)):
                if locs[i] != ls[i]:
                    break
            else:
                return b
        return False

    def isIsomorphic(self, s, t):
        d1 = self.alphas(s)
        d2 = self.alphas(t)
        keys1 = d1.keys()
        keys2 = d2.keys()
        if len(keys1) != len(keys2):
            return False
        for key in keys1:
            if key not in d2:
                return False
            alphas1 = d1[key]
            alphas2 = d2[key]
            if len(alphas1) != len(alphas2):
                return False
            for [a, locs] in alphas1:
                b = self.find(locs, alphas2)
                # print a, b
                if b:
                    alphas2.remove([b, locs])
                else:
                    return False
        return True

# sol = Solution()
# s1 = "ab"
# s2 = "ca"
# print sol.alphas(s1)
# print sol.alphas(s2)
# print sol.isIsomorphic(s1, s2)


""" HJ75 - 公共子串计算（暴力枚举法） """
if __name__ == "__main__":
    a, b = input(), input()
    if len(a) > len(b):
        a, b = b, a
    result = 0

    for i in range(len(a)):
        for j in range(i, len(a)):
            if a[i:j + 1] in b and j + 1 - i > result:
                result = j + 1 - i

    print(result)


# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# **************************************************************************/

"""
:info:
    Wrapper class for enabling and resetting robot state.

"""

import rospy
from threading import Lock

from franka_msgs.msg import ErrorRecoveryActionGoal
from franka_core_msgs.msg import RobotState

import franka_dataflow
from .robot_params import RobotParams

class RobotEnable(object):
    """
    Class RobotEnable - simple control/status wrapper around robot state

    enable()  - enable all joints
    disable() - disable all joints
    reset()   - reset all joints, reset all jrcp faults, disable the robot
    stop()    - stop the robot, similar to hitting the e-stop button

    :param robot_params: A RobotParams instance (optional)
    :type robot_params: RobotParams
    """

    param_lock = Lock()

    def __init__(self, robot_params = None):
        """

        """

        if robot_params:
            self._params = robot_params
        else:
            self._params = RobotParams()

        self._ns = self._params.get_base_namespace()

        self._enabled = None

        state_topic = '{}/custom_franka_state_controller/robot_state'.format(self._ns)
        self._state_sub = rospy.Subscriber(state_topic,
                                           RobotState,
                                           self._state_callback
                                           )

        franka_dataflow.wait_for(
            lambda: not self._enabled is None,
            timeout=5.0,
            timeout_msg=("Failed to get robot state on %s" %
            (state_topic,)),
        )

    def _state_callback(self, msg):
        self._enabled = (msg.robot_mode != 4)

    def is_enabled(self):
        """
        Return status of robot

        :return: True if enabled, False otherwise
        :rtype: bool
        """
        return self._enabled

    def _toggle_enabled(self, status):

        pub = rospy.Publisher('{}/franka_control/error_recovery/goal'.format(self._ns), ErrorRecoveryActionGoal,
                              queue_size=10)

        if self._enabled == status:
            rospy.loginfo("Robot is already %s"%self.state())

        franka_dataflow.wait_for(
            test=lambda: self._enabled == status,
            timeout=5.0,
            timeout_msg=("Failed to %sable robot" %
                         ('en' if status else 'dis',)),
            body=lambda: pub.publish(ErrorRecoveryActionGoal()),
        )
        rospy.loginfo("Robot %s", ('Enabled' if status else 'Disabled'))

    def state(self):
        """
        Returns the last known robot state.

        :rtype: str
        :return: "Enabled"/"Disabled"
        """
        return "%sabled"%('en' if self._enabled else 'dis',)

    def enable(self):
        """
        Enable all joints
        """
        if not self._enabled:
            rospy.loginfo("Robot Stopped: Attempting Reset...")
            self._toggle_enabled(True)

    def disable(self):
        """
        Disable all joints
        """
        self._toggle_enabled(False)


# -*- coding: utf-8 -*-
# @Time: 18-12-7 下午2:38
# @Author: gtw
import cv2

def black_process_one(image1):
    image = image1.copy()
    binary = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(binary, 100, 255, cv2.THRESH_BINARY)# | cv2.THRESH_OTSU)
    cv2.imshow('binary', binary)
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel1, iterations=3)
    image[binary == 0, :] = 0
    binary = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    image[binary >= 220, :] = 0
    binary = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cv2.imshow('binary1', binary)
    ret, binary = cv2.threshold(binary, 10, 255, cv2.THRESH_BINARY)# | cv2.THRESH_OTSU)
    kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel1, iterations=3)
    binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel1, iterations=4)
    # cv2.imshow('close', binary)
    kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
    binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel2, iterations=5)
    binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel2, iterations=5)
    binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel1, iterations=1)
    # cv2.imshow('reslut', binary)
    # binary = cv2.bitwise_not(binary)
    # kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7))
    # binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel3, iterations=5)
    # binary = cv2.morphologyEx(binary, cv2.MORPH_ERODE, kernel3, iterations=5)
    # cv2.imshow('mor', binary)
    image[binary == 0, :] = 0
    # cv2.imshow('final', image)

    return binary, image

if __name__ == '__main__':
    import random
    import glob
    random.seed(0)
    img_list = glob.glob('voc_80/*')
    img_path = random.choice(img_list)
    img = cv2.imread(img_path)
    binary, image = black_process_one(img)
    # _, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # image = cv2.drawContours(img, contours, 3, (0, 255, 0), -1)
    # for contour in contours:
    #     image = cv2.drawContours(img, [contour], 0, (0, 255, 0), 3)
        # x, y, w, h = cv2.boundingRect(contour)
        # cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 3)
    # x, y, w, h = cv2.boundingRect(binary)
    # cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0))
    # cv2.imshow('binary', binary)
    # cv2.imshow('image', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


import os
import re
import pipes
import logging
import urllib
import json
import subprocess
import requests
import click
from .shell import cast, call
from . import auth
from . import api_exception
from . import presenter
from . import ssh_key
from . import git
from contextlib import closing
from six.moves.urllib.parse import quote

def get(host):
    r = requests.get('%s/api/apps' % host, headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def info(host, app_name):
    r = requests.get('%s/api/apps/%s' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def set_git_remote(host, app_name):
    git.check_for_git()

    remotes = call('git remote').splitlines()
    if 'gigalixir' in remotes:
        cast('git remote rm gigalixir')
    cast('git remote add gigalixir https://git.gigalixir.com/%s.git/' % app_name)
    logging.getLogger("gigalixir-cli").info("Set git remote: gigalixir.")

def create(host, unique_name, cloud, region, stack):
    git.check_for_git()

    body = {}
    if unique_name != None:
        body["unique_name"] = unique_name.lower()
    if cloud != None:
        body["cloud"] = cloud
    if region != None:
        body["region"] = region
    if stack != None:
        body["stack"] = stack
    r = requests.post('%s/api/apps' % host, headers = {
        'Content-Type': 'application/json',
    }, json = body)
    if r.status_code != 201:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        unique_name = data["unique_name"]
        logging.getLogger("gigalixir-cli").info("Created app: %s." % unique_name)

        set_git_remote(host, unique_name)
        click.echo(unique_name)

def status(host, app_name):
    r = requests.get('%s/api/apps/%s/status' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise api_exception.ApiException(r)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def scale(host, app_name, replicas, size):
    body = {}
    if replicas != None:
        body["replicas"] = replicas
    if size != None:
        body["size"] = size
    r = requests.put('%s/api/apps/%s/scale' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    }, json = body)
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def customer_app_name(host, app_name):
    r = requests.get('%s/api/apps/%s/releases/latest' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        return data["customer_app_name"]

def distillery_eval(host, app_name, ssh_opts, ssh_cmd, expression):
    # capture_output == True as this isn't interactive
    # and we want to return the result as a string rather than
    # print it out to the screen
    return ssh_helper(host, app_name, ssh_opts, ssh_cmd, True, "gigalixir_run", "distillery_eval", "--", expression)

def distillery_command(host, app_name, ssh_opts, ssh_cmd, *args):
    ssh(host, app_name, ssh_opts, ssh_cmd, "gigalixir_run", "shell", "--", "bin/%s" % customer_app_name(host, app_name), *args)

def ssh(host, app_name, ssh_opts, ssh_cmd, *args):
    # capture_output == False for interactive mode which is
    # used by ssh, remote_console, distillery_command
    ssh_helper(host, app_name, ssh_opts, ssh_cmd, False, *args)

def ssh_add_identity_option(ssh_opts):
    # use the identity file specified by environment variable
    id_file = os.environ.get("GIGALIXIR_IDENTITY_FILE")
    if id_file and not re.match(r'(^|[\s])-i', ssh_opts):
        return (ssh_opts + " -i " + id_file).strip()

    return ssh_opts

# if using this from a script, and you want the return
# value in a variable, use capture_output=True
# capture_output needs to be False for remote_console
# and regular ssh to work.
def ssh_helper(host, app_name, ssh_opts, ssh_cmd, capture_output, *args):
    # verify SSH keys exist
    keys = ssh_key.ssh_keys(host)
    if len(keys) == 0:
        raise Exception("You don't have any ssh keys yet. See `gigalixir account:ssh_keys:add --help`")

    # use the identity file specified by environment variable
    ssh_opts = ssh_add_identity_option(ssh_opts)

    # if -T and -t are not specified, add the -t option
    if not re.match(r'(^|[\s])-[Tt]', ssh_opts):
        ssh_opts = (ssh_opts + " -t")

    r = requests.get('%s/api/apps/%s/ssh_ip' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        ssh_ip = data["ssh_ip"]
        if len(args) > 0:
            escaped_args = [pipes.quote(arg) for arg in args]
            command = " ".join(escaped_args)
            if capture_output:
                return call("%s %s root@%s %s" % (ssh_cmd, ssh_opts, ssh_ip, command))
            else:
                cast("%s %s root@%s %s" % (ssh_cmd, ssh_opts, ssh_ip, command))
        else:
            cast("%s %s root@%s" % (ssh_cmd, ssh_opts, ssh_ip))

def restart(host, app_name):
    r = requests.put('%s/api/apps/%s/restart' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def rollback(host, app_name, version):
    if version == None:
        version = second_most_recent_version(host, app_name)
    r = requests.post('%s/api/apps/%s/releases/%s/rollback' % (host, quote(app_name.encode('utf-8')), quote(str(version).encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def second_most_recent_version(host, app_name):
    r = requests.get('%s/api/apps/%s/releases' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        if len(data) < 2:
            raise Exception("No release available to rollback to.")
        else:
            return data[1]["version"]

def run(host, app_name, command):
    # runs command in a new container
    r = requests.post('%s/api/apps/%s/run' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    }, json = {
        "command": command,
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        click.echo("Starting new container to run: `%s`." % ' '.join(command))
        click.echo("See `gigalixir logs` for any output.")
        click.echo("See `gigalixir ps` for job info.")

def ps_run(host, app_name, ssh_opts, ssh_cmd, *command):
    # runs command in same container app is running
    ssh(host, app_name, ssh_opts, ssh_cmd, "gigalixir_run", "shell", "--", *command)

def remote_console(host, app_name, ssh_opts, ssh_cmd):
    ssh(host, app_name, ssh_opts, ssh_cmd, "gigalixir_run", "remote_console")

def migrate(host, app_name, migration_app_name, ssh_opts, ssh_cmd):
    if migration_app_name is None:
        ssh(host, app_name, ssh_opts, ssh_cmd, "gigalixir_run", "migrate")
    else:
        ssh(host, app_name, ssh_opts, ssh_cmd, "gigalixir_run", "migrate", "-m", migration_app_name)

def logs(host, app_name, num, no_tail):
    payload = {
        "num_lines": num,
        "follow": not no_tail
    }
    with closing(requests.get('%s/api/apps/%s/logs' % (host, quote(app_name.encode('utf-8'))), stream=True, params=payload)) as r:
        if r.status_code != 200:
            if r.status_code == 401:
                raise auth.AuthException()
            raise Exception(r.text)
        else:
            for chunk in r.iter_content(chunk_size=None):
                if chunk:
                    click.echo(chunk, nl=False)

def delete(host, app_name):
    r = requests.delete('%s/api/apps/%s' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    })
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)

def set_stack(host, app_name, stack):
    body = {}
    if stack != None:
        body["stack"] = stack
    r = requests.put('%s/api/apps/%s/stack' % (host, quote(app_name.encode('utf-8'))), headers = {
        'Content-Type': 'application/json',
    }, json = body)
    if r.status_code != 200:
        if r.status_code == 401:
            raise auth.AuthException()
        raise Exception(r.text)
    else:
        data = json.loads(r.text)["data"]
        presenter.echo_json(data)


import numpy as np
import networkx as nx

class NetworkWorld:

    '''
    a world for traversal on a network structure
    '''

    def __init__(self,
                 nodes,
                 edges,
                 action_dim,
                 permute_node_labels=False):
        self.nodes = nodes # an array of nodes
        self.edges = edges # a dict of (node - list of nodes) paring
        self.current = None # for traversal
        self.action_dim = action_dim
        self.node_mapping = None
        if permute_node_labels:
            self.permute_node_labels()
        self.build_graph()

    def permute_node_labels(self):
        new_labels = np.copy(self.nodes)
        np.random.shuffle(new_labels)
        old_new_lookup = {}
        for i, old in enumerate(self.nodes):
            old_new_lookup[old] = new_labels[i]
        self.node_mapping = old_new_lookup
        # modify self.edges using the new nodes
        new_edges = {}
        for i, old in enumerate(self.nodes):
            new = old_new_lookup[old]
            old_successors = self.edges[old]
            new_successors = [old_new_lookup[o] for o in old_successors]
            new_edges[new] = new_successors
        self.edges = new_edges
        self.nodes = new_labels

    def build_graph(self):
        self.graph = nx.DiGraph()
        for i in self.nodes:
            self.graph.add_node(i)
            for j in self.edges[i]:
                self.graph.add_edge(i, j, weight=1)

    def get_neighbors(self, node, lookup='a'):
        '''
        returs the neighbors for the given node
        :param lookup: if a, get all neighbors
                       if p, get predecessors nodes
                       if s, get successors nodes
        '''
        if lookup=='a': # all neighbors
            return list(self.graph.predecessors(node)) + list(self.graph.successors(node))
        if lookup=='p': # predecessors
            return list(self.graph.predecessors(node))
        if lookup=='s': # successors
            return list(self.graph.successors(node))

    def reset(self, start=None):
        self.current = start if start is not None else np.random.choice(self.nodes)
        return self.current

    def step(self, action):
        next_node = self.edges[self.current][action]
        self.current = next_node
        return self.current

    def shortest_path(self, s1, s2):
        shortest_path = nx.shortest_path(self.graph, s1, s2)
        actions = [self.edges[shortest_path[i-1]].index(shortest_path[i])
                   for i in np.arange(len(shortest_path))[1:]]
        n = len(actions)
        return {'n_step':n, 'path':shortest_path, 'actions':actions}


from utils import bytes_to_bits

# Mining rules
MINING_REWARD = 50
MIN_ZEROS = 20
MINER_WAIT_TIMEOUT = 5
MAX_TXN_COUNT = 20

def valid_block_hash(h):
    bits = bytes_to_bits(h)
    return all(map(lambda b: b == 0, bits[:MIN_ZEROS]))

# chain rules
MAX_BLOCKS_BEHIND = 10


from collections import deque

n, k = map(int, input().split())
L = set([int(input()) for _ in range(n)])
dp = [-1] * (k+1)
queue = deque()
queue.append([0, 0])

while queue:
    num, cnt = queue.popleft()
    for i in L:
        if num+i > k:
            continue

        if dp[num+i] == -1:
            dp[num+i] = cnt+1
            queue.append([num+i, cnt+1])

print(dp[-1])


#Mia Katz
#Group Homework Problems
#Sources: renegadecoder.com, for the list adding in the third problem

#Shuffle numbers 1 to 100
import random
import sys
x = [i for i in range(100)]
random.shuffle(x)
print("100 shuffled numbers:",x)

#Print 10 random numbers, order them descending, remove multiples of 3
t=[]
for i in range(10):
	r = (random.randrange(100))
	t.append(r)
	if r%3 == 0:
		t.remove(r)
t.sort(reverse = True)

print("10 numbers, minus those divisible by 3:",t)

#take ten arguments, print them in order, in reverse order, and the sum
l = []
m = []
for i in range(1,11):
	p = int(sys.argv[i])
	l.append(p)
	m.append(p)
l.sort()
print(l)
m.sort(reverse = True)
print(m)
al = [sum(pair) for pair in zip(l, m)]
print("Sum of both lists:",al)


#!/usr/bin/python

import sys
import os
import pandas as pd
import itertools
import csv
import re
import subprocess
import glob
import shutil
import pysam
import collections
from collections import Counter
import time
import argparse
import logging
import psutil
import re

from argparse import ArgumentParser, RawTextHelpFormatter

# Debugging, if we don't have any candidates i think we should still create the empty file about the pseudogene candidates?

def parseArgs():
    parser = argparse.ArgumentParser(description='Detects processed pseudogenes by looking at DNA data that splits across the splice junctions',formatter_class=RawTextHelpFormatter)
    choices_helper = { "Fastq": "Input is Fastq, The pipeline will run STAR for you, method specific parameters are [-R1 Path to Read1, -R2, Path to Read2, -STARindex Path to human reference genome]",
                       "Bam": "Input is Bam which means that you have already aligned your fastq files towards the reference genome in the required way (Read more about how to align using the method description), method specific parameter is [-I, Path to the bam input]"}
    parser.add_argument('--Method',dest="method", choices=choices_helper,help='\n'.join("{}: {}".format(key, value) for key, value in choices_helper.items()), required=True)
    parser.add_argument('-S', dest='Sample', help='Sample name, descides the prefix of your outputs together with the output folder (required)', required=True)
    parser.add_argument('--pseudoCandidateDepth', dest='Psdepth', help='The minimum depth that supports the splice junctions, these are the resulting processed pseudogene candidates (default 5)', default=5 ,type=int)
    parser.add_argument('--InsertDistance', dest='insdistance', help='What is the distance from the parent gene where we can have an pseudogene, low distance might increase the amount of detected pseudogenes but will also increase the amount of false positives. A low distance and you might hit inserted pseudogenes in the parent gene itself which is not very likely (default 200 000)', default=200000,type=int)
    parser.add_argument('--ChimericPairDepthTreshold', dest='ChimPairDepthTresh', help='The minimum amount of reads to suppport the chimeric pairs in the left anchor, (min 5), (default 10)', default=10,type=int)
    parser.add_argument('--ChimericPairBinningTreshold', dest='ChimPairBinningTresh', help='When the chimeric pairs are binned into the anchors the binning distance defines the distance for the read to belong to same bin, (default 500)', default=500,type=int)
    parser.add_argument('--ChimericReadDepthTreshold', dest='ChimReadDepthTresh', help='The minimum amount of reads to support the chimeric reads in the fusion site, (min 5) (default 10)', default=10,type=int)
    parser.add_argument('--ChimericReadBinningTreshold', dest='ChimReadBinningTresh', help='When the chimeric reads are binned into the anchors the binning distance defines the distance for the read to belong to same bin', default=10,type=int)
    parser.add_argument('--MergeChimReadWithChimpairTresh', dest='chimreadpairdistance', help='When we are combining the results from the chimeric pairs and the chimeric reads we combine them if the chimeric read are withing the chimeric pair anchors or the chimeric read are in a user defined distance from the left anchor (default 100)', default=100,type=int)
    opts, rem_args = parser.parse_known_args()
    if opts.method == "Bam":
        parser.add_argument('-I', dest='baminput',help='Bamfile containing alignment performed by a splice aware aligner, need index in the same folder (required)',required=True)
    else:
        parser.add_argument('-R1', dest='Fastq1',help='R1 from a Fastq file (required)',required=True)
        parser.add_argument('-R2', dest='Fastq2',help='R2 from a Fastq file (required)',required=True)
        parser.add_argument('-STARindex', dest='STARindex',help='Path to the star index of the reference genome',required=True)
    arguments=parser.parse_args(sys.argv[1:])
    return arguments

def CheckingPaths():
    """
    This is the part which checks so you have all the correct paths to the tools that you are using
    """
    # Testing Bedtools
    command = "which bedtools"
    a = subprocess.Popen(command, stdout=subprocess.PIPE,stderr = subprocess.PIPE, shell=True)
    stdout, stderr = a.communicate()
    if not stdout:
        print("Error, there is no bedtools in your path, Please install! Exiting!")
        sys.exit()
    # Testing Samtools, Impportant that you are not using two old version of samtools
    command = "which samtools"
    a = subprocess.Popen(command, stdout=subprocess.PIPE,stderr = subprocess.PIPE, shell=True)
    stdout, stderr = a.communicate()
    if not stdout:
        print("Error, there is no samtools in your path, Please install! Exiting!")
        sys.exit()
    # Testing R
    #command = "which R"
    #a = subprocess.Popen(command, stdout=subprocess.PIPE,stderr = subprocess.PIPE, shell=True)
    #stdout, stderr = a.communicate()
    #if not stdout:
     #   print "Error, there is no R in your path, Please install! Exiting!"
     #   sys.exit()
    # Test required R packages
    #command = "Rscript -e 'library(\"Gviz\")'"
    #a = subprocess.Popen(command, stdout=subprocess.PIPE,stderr = subprocess.PIPE, shell=True)
    #stdout, stderr = a.communicate()
    #if not stdout:
    #    print "Error, there GVIZ is not installed in your R version, Please install! Exiting!"
    #    sys.exit()
    # Testing convert
    command = "which convert"
    a = subprocess.Popen(command, stdout=subprocess.PIPE,stderr = subprocess.PIPE, shell=True)
    stdout, stderr = a.communicate()
    if not stdout:
        print("Error, there is no convert in your path, Please install! Exiting!")
        sys.exit()
    # Testing awk
    command = "which awk"
    a = subprocess.Popen(command, stdout=subprocess.PIPE,stderr = subprocess.PIPE, shell=True)
    stdout, stderr = a.communicate()
    if not stdout:
        print("Error, there is no awk in your path, Please install! Exiting!")
        sys.exit()

def database():
    """
    This part reads the databases that is used for input
    """
    # Check database after installation
    logging.info('%s\tCollecting the paths to the HG19 databases', time.ctime().split(" ")[-2])
    genecoords = os.path.abspath(__file__).split("bin/Ppsy.py")[0] + "HG19_databases/Gene_coord_hg19_refgene.bed"
    exoncoords = os.path.abspath(__file__).split("bin/Ppsy.py")[0] + "HG19_databases/Exon_coord_hg19_refgene.bed"
    #genecoords = "/home/xabras/.conda/envs/Ppsy/HG19_databases/Gene_coord_hg19_refgene.bed"
    #exoncoords = "/home/xabras/.conda/envs/Ppsy/HG19_databases/Exon_coord_hg19_refgene.bed"
    pseudogenecoords = os.path.abspath(__file__).split("bin/Ppsy.py")[0] + "HG19_databases/KnownProcessedPseudogenes_Homo_sapiens.GRCh37.75_CHR.bed"
    #pseudogenecoords="/home/xabras/.conda/envs/Ppsy/HG19_databases/KnownProcessedPseudogenes_Homo_sapiens.GRCh37.75_CHR.bed"
    return(genecoords,pseudogenecoords,exoncoords)

def CreatingOutputDir(Sample):
    """
    This Part creates the output folder together with the cleaning lists
    """
    logging.info('%s\tSetting Up Outputdir', time.ctime().split(" ")[-2])
    Outputfolder=Sample + "_PPsyOut"
    command = "mkdir -p %s" % Outputfolder
    os.system(command)
    # List for cleaning and moving files
    Cleaninglist=[]
    MovingList = []
    return(Cleaninglist, MovingList,Outputfolder)

def AlignmentWithSTAR(Fastq1,Fastq2,STARindex,Sample,Outputfolder):
    """
    This function is only run if you dont have the alignment file so this part runs STAR, the Issue here is that we cannot run this in multicore while the other is single core, this is why it is preferable to have the Alignmentfile with star already done
    """
    # You need to have STAR in your path for this
    logging.info('%s\tAlignment using STAR... This step might be very slow', time.ctime().split(" ")[-2])
    baminput = Outputfolder +"/"+ Sample + "Aligned.sortedByCoord.out.bam"
    if Fastq1.endswith(".gz"):
        command = "STAR --runThreadN 1 --genomeDir %s --chimOutType WithinBAM --outSAMunmapped Within --outFilterMultimapNmax 20 --chimSegmentMin 20 --readFilesCommand zcat --readFilesIn %s %s --outSAMtype BAM SortedByCoordinate --outFileNamePrefix %s/%s" %(STARindex,Fastq1,Fastq2,Outputfolder,Sample)
        os.system(command)
    else:
        command = "STAR --runThreadN 1 --genomeDir %s --chimOutType WithinBAM --outSAMunmapped Within --outFilterMultimapNmax 20 --chimSegmentMin 20 --readFilesIn %s %s --outSAMtype BAM SortedByCoordinate --outFileNamePrefix %s/%s" %(STARindex,Fastq1,Fastq2,Outputfolder,Sample)
        os.system(command)
    command = "samtools index %s" %baminput
    os.system(command)
    return(baminput)

def CreateTheChromosomeInfoFile(baminput,Sample,Cleaninglist):
    """
    This extract the chromsome info file from the input
    """
    logging.info('%s\tCreating Chromsome Info File', time.ctime().split(" ")[-2])
    chrominfo = Sample + ".ChromInfo_SortingOrder.txt"
    command = "samtools view %s -H" % baminput
    a = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    with open(chrominfo, "w") as chromout:
        for line in a.stdout:
            line = line.strip().decode("utf-8")
            if line.split("\t")[0] == "@SQ":
                chrom  = line.split("\t")[1].split(":")[-1]
                size = line.split("\t")[2].split(":")[-1]
                print(chrom +"\t"+ str(size), file=chromout)
    Cleaninglist.append(chrominfo)
    return chrominfo

def extractingClipped(Sample,baminput, Cleaninglist,MovingList):
    '''
    Softclipped reads are extracted and saved to a new bamfile
    '''
    logging.info('%s\tExtracting Softclipped reads',time.ctime().split(" ")[-2])
    bamClipped = Sample + ".Clipped.bam"
    commandExtractingclipped = "samtools view -h %s | awk '$17 ~ /SA/ || $1 ~ /^@/' | samtools view -bS - > %s" % (baminput, bamClipped)
    os.system(commandExtractingclipped)
    command = "samtools index %s" % bamClipped
    os.system(command)
    MovingList.append(bamClipped)
    MovingList.append(bamClipped+".bai")
    return bamClipped

def extractingchimericReads(Sample, baminput, Cleaninglist, MovingList,insdistance):
    '''
    Extracting Reads with large insertsite Either if the mate maps in another chromosome or the insertsite is larger than a user defined treshold, the default is 200 000
    '''
    logging.info('%s\tExtracting chimeric reads, ins > %s or seperate chr mapping', time.ctime().split(" ")[-2], insdistance)

    bamChimericPairs = Sample + ".ChimericReadPairs.bam"
    MovingList.append(bamChimericPairs)
    MovingList.append(bamChimericPairs + ".bai")
    command = "samtools view %s -h | awk 'function abs(x){return ((x < 0.0) ? -x : x)} $7 != \"=\" || abs($4-$8) > %s {print $0}' | samtools view -bS - > %s" %(baminput, insdistance,bamChimericPairs)  # Obs i increased it to 200 000 as some of the candates are longer than 100 000 bp
    os.system(command)
    command = "samtools index %s" % bamChimericPairs
    os.system(command)
    return bamChimericPairs

def ChimericReadsOverlapwithPseudogeneCandidates(Sample, bamChimericPairs,Pseudogenecandidatesbed, Cleaninglist, MovingList,ChimPairDepthTresh,ChimPairBinningTresh):
    '''
    Here we look for intersect between pseudogene candidates and chimericreads overlap
    This will add evidence to the pseudogene candidates by looking at overlap between these coordinates and the softclip coordinates
    '''
    logging.info('%s\tLooking for an overlap between chimeric reads and Pseudogenes candidates',time.ctime().split(" ")[-2])
    PseudogeneCandidateChimbed = Sample + ".ChimericPairs_AmountOfReads.bed"
    Cleaninglist.append(PseudogeneCandidateChimbed)
    samchimpericPairs = pysam.AlignmentFile(bamChimericPairs, 'rb')
    with open(PseudogeneCandidateChimbed, "w") as out:
        with open(Pseudogenecandidatesbed, "r") as pseudogenecandidatesbedf:
            # For each line in the bedfile Create a new bedfile for the chimeric pseudogenes fusion sites
            for line in pseudogenecandidatesbedf:
                line = line.strip()
                chrom = line.split("\t")[0]
                start = line.split("\t")[1]
                end = line.split("\t")[2]
                pseudogenecandidate = line.split("\t")[3]
                PseudogeneCandidateChimbedtmp =Sample+"_" + pseudogenecandidate + ".ChimericPairs_AmountOfReads.bed.tmp"
                Cleaninglist.append(PseudogeneCandidateChimbedtmp)
                with open(PseudogeneCandidateChimbedtmp, "w") as tmpout:
                    for read in samchimpericPairs.fetch(chrom, int(start), int(end)):
                        if read.tostring(samchimpericPairs).split("\t")[6] == "=":
                            matechrom = chrom # The fusion is on the same chrom as the pseudogene
                        else:
                            matechrom = read.tostring(samchimpericPairs).split("\t")[6] # The fusion is in a sperate chrom
                        try:
                            matepositonslist = samchimpericPairs.mate(read).positions # This part might be super slow, maybe you need to read sort this? We extract the positions of the mate togehter with the positions of the reads
                            startMate = matepositonslist[0]
                            endMate = matepositonslist[-1]
                            startInGene = read.positions[0]
                            endInGene = read.positions[-1]
                            print(chrom + "\t" + str(startInGene) + "\t" + str(endInGene)+"\t"+matechrom + "\t" + str(startMate) + "\t" + str(endMate), file=tmpout)
                        except ValueError:
                            continue
                # Make sure that the output file is not empty,if it is continue with the next coord
                if not os.stat(PseudogeneCandidateChimbedtmp).st_size==0:
                    logging.info('%s\tOverlapping coord detected',time.ctime().split(" ")[-2])
                    logging.info('%s\tStart binning the left and right anchors, atleast %s i depth',time.ctime().split(" ")[-2],ChimPairDepthTresh)
                    # Binning using pandas df
                    data = pd.read_csv(PseudogeneCandidateChimbedtmp, sep = "\t", header=None)
                    sorted = data.sort_values([0, 3,1,4]).reset_index(drop=True)
                    if len(sorted) == 1: # If you only have 1 hit the loop will break,
                        continue
                    sorted[["diff1", "diff2"]] = sorted.groupby(3)[[1,4]].diff()
                    fusionchroms = []
                    groupedsorted = sorted.groupby(3)
                    for name, group in groupedsorted:
                        group = group.sort_values([3,4,1]).reset_index(drop=True)
                        PseudogeneanchorLeftstarts = []
                        PseudogeneanchorLeftends= []
                        FusionAnchorleftstarts = []
                        FusionAnchorleftends = []
                        PseudoanchorRightstarts = []
                        PseudoanchorRightends = []
                        FusionAnchorRightstarts = []
                        FusionAnchorRightends= []
                        if len(group) > 4: # We wont use groups with less than 5 items, this is not enough for the binning anyways, if only one hit it will crash
                            groupCounter = 0 # This is the counter that makes sure that the loop is not in the end, if we have a hit but the loop ends we will loose that hit
                            for i, row in group.iterrows():
                                groupCounter +=1
                                if groupCounter != len(group): # If we are not in the final hit
                                    if not name in fusionchroms:# This is the first hit in the group which set up the lists
                                        PseudogeneanchorLeftstarts.append(row.loc[1])
                                        PseudogeneanchorLeftends.append(row.loc[2])
                                        FusionAnchorleftstarts.append(row.loc[4])
                                        FusionAnchorleftends.append(row.loc[5])
                                        fusionchroms.append(name)
                                    else:
                                        if abs(PseudogeneanchorLeftstarts[0] - int(row.loc[1])) < ChimPairBinningTresh and abs(FusionAnchorleftstarts[0] - int(row.loc[4])) < ChimPairBinningTresh: # if the difference from the previous and the new coords is smaller than the user defined trehsolds for both start sites we save them to the binnning, 500 is default
                                            PseudogeneanchorLeftstarts.append(row.loc[1])
                                            PseudogeneanchorLeftends.append(row.loc[2])
                                            FusionAnchorleftstarts.append(row.loc[4])
                                            FusionAnchorleftends.append(row.loc[5])
                                        elif abs(PseudogeneanchorLeftstarts[0] - row.loc[1]) > 5000 and abs(FusionAnchorleftstarts[0] - int(row.loc[4])) < ChimPairBinningTresh: # If the range within the pseudogene is larger than 5000 you might have found the second anchor. We are further away for the pseudogene anchor then what we would expect, therefore we are have the right anchor if we are in the same range for the fusion still
                                            PseudoanchorRightstarts.append(row.loc[1])
                                            PseudoanchorRightends.append(row.loc[2])
                                            FusionAnchorRightstarts.append(row.loc[4]) # Fusion coord on the right side is the end coord of the read in the pair outside of the gene. Always think you want to have as much space as possible
                                            FusionAnchorRightends.append(row.loc[5])
                                        else:
                                            # Now we cannot continue as we are not within the range of anything. If we have enough for the range we count them. Otherwise we skip them and continue the loop
                                            if len(FusionAnchorleftstarts) > ChimPairDepthTresh:
                                                PseudogeneAnchorleftStart=PseudogeneanchorLeftstarts[0]
                                                PseudogeneAnchorleftend= PseudogeneanchorLeftends[-1]# important, the value is from the previous row. The current row is the faulty, when getting the previus value you need to use the group index
                                                FusionAnchorleftStart = FusionAnchorleftstarts[0]
                                                FusionAnchorleftEnd = FusionAnchorleftends[-1]
                                                leftstring = str(row.loc[3]) + "\t" + str(FusionAnchorleftStart) + "\t" + str(FusionAnchorleftEnd) + "\t"+str(len(FusionAnchorleftstarts))
                                                if len(PseudoanchorRightstarts) > ChimPairDepthTresh:
                                                    # This part tells us we have the right anchor as well
                                                    PseudogeneAnchorrightStart=PseudoanchorRightstarts[0]
                                                    PseudogeneAnchorrightEnd=PseudoanchorRightends[-1]
                                                    FusionAnchorrightStart=FusionAnchorRightstarts[0]
                                                    FusionAnchorrightEnd=FusionAnchorRightends[-1]
                                                    print(pseudogenecandidate+"\t"+ chrom + "\t" + str(start) + "\t" + str(end)+ "\t"+leftstring + "\t"+str(row.loc[3])+ "\t" + str(FusionAnchorrightStart)+"\t" + str(FusionAnchorrightEnd) + "\t" + str(len(PseudoanchorRightstarts)), file=out)

                                                else:
                                                    # We did not detect the second anchor
                                                    print(pseudogenecandidate+"\t"+ chrom + "\t" + str(start) + "\t" + str(end)+ "\t"+leftstring + "\tNA\tNA\tNA\tNA", file=out)
                                                    # We are done with all the
                                            # We did not find anything for this loop, or we did but we reached the end. Therefore we need to reset everything

                                            # Left sites are the ones we find first
                                            PseudogeneanchorLeftstarts=[row.loc[1]]
                                            PseudogeneanchorLeftends=[row.loc[2]]
                                            FusionAnchorleftstarts=[row.loc[4]]
                                            FusionAnchorleftends=[row.loc[5]]
                                            # Then we go to the right side, reset.
                                            PseudoanchorRightstarts=[]
                                            PseudoanchorRightends=[]
                                            FusionAnchorRightstarts=[]
                                            FusionAnchorRightends=[]
                                else: # We are in the end of the loop
                                    if len(FusionAnchorleftstarts) > ChimPairDepthTresh:
                                        PseudogeneAnchorleftStart=PseudogeneanchorLeftstarts[0]
                                        PseudogeneAnchorleftend= PseudogeneanchorLeftends[-1]# important, the value is from the previous row. The current row is the faulty, when getting the previus value you need to use the group index
                                        FusionAnchorleftStart = FusionAnchorleftstarts[0]
                                        FusionAnchorleftEnd = FusionAnchorleftends[-1]
                                        leftstring = str(row.loc[3]) + "\t" + str(FusionAnchorleftStart) + "\t" + str(FusionAnchorleftEnd) + "\t"+str(len(FusionAnchorleftstarts))
                                        if len(PseudoanchorRightstarts) > ChimPairDepthTresh:
                                            # This part tells us we have the right anchor as well
                                            PseudogeneAnchorrightStart=PseudoanchorRightstarts[0]
                                            PseudogeneAnchorrightEnd=PseudoanchorRightends[-1]
                                            FusionAnchorrightStart=FusionAnchorRightstarts[0]
                                            FusionAnchorrightEnd=FusionAnchorRightends[-1]
                                            print (pseudogenecandidate+"\t"+ chrom + "\t" + str(start) + "\t" + str(end)+ "\t"+leftstring + "\t"+str(row.loc[3])+ "\t" + str(FusionAnchorrightStart)+"\t" + str(FusionAnchorrightEnd) + "\t" + str(len(PseudoanchorRightstarts)), file=out)

                                        else:
                                            # We did not detect the second anchor
                                            print(pseudogenecandidate+"\t"+ chrom + "\t" + str(start) + "\t" + str(end)+ "\t"+leftstring + "\tNA\tNA\tNA\tNA", file=out)

    samchimpericPairs.close()        # Close the pysam
    return PseudogeneCandidateChimbed  #  return the name of the output where we have our fusion coords

def ClippedBamtoCoord(bamClipped,Cleaninglist, MovingList):
    '''
    Converting the chimeric ranges to coordinates
    '''
    logging.info('%s\tExtracting the Clipped read coordinates',time.ctime().split(" ")[-2])
    clippedtmp = bamClipped.split(".bam")[0] + ".sam"
    Cleaninglist.append(clippedtmp)
    clippedbed = bamClipped.split(".bam")[0] + ".bed"
    Cleaninglist.append(clippedbed)
    command = "samtools view %s > %s" %(bamClipped, clippedtmp)
    os.system(command)
    listofreads = [] # Making sure that if you extracted the coords from one read that you dont extract them again!
    with open(clippedtmp, "r") as chim:
        with open(clippedbed, "w") as out:
            for line in chim:
                line = line.strip()
                read = line.split("\t")[0]
                if read not in listofreads:
                    chrom = line.split("\t")[2]
                    chromchim = line.split("\t")[16].split(":")[2].split(",")[0]
                    Cigar = line.split("\t")[5]
                    #print(list(Cigar))
                    if not "D" in Cigar or not "I" in Cigar: # We are ignoring the reads containing a D or an I
                        #print(Cigar)
                        char= re.sub('\d+', ',', Cigar)
                        char=char.split(",")
                        char=list(filter(None, char))
                        Cigar=re.sub('\D', ',', Cigar)
                        Cigar=Cigar.split(",")
                        Cigar = list(filter(None, Cigar))
                        CigarList = [int(i) for i in Cigar]
                        startchimCigar= line.split("\t")[16].split(":")[2].split(",")[3]
                        charchim=re.sub('\d+', ',', startchimCigar)
                        charchim=charchim.split(",")
                        charchim=list(filter(None, charchim))
                        cigarchim=re.sub('\D', ',', startchimCigar)
                        cigarchim=cigarchim.split(",")
                        cigarchim=list(filter(None, cigarchim))
                        cigarchim=[int(i) for i in cigarchim]
                        #print(charchim)
                        #print(cigarchim)
                        if len(cigarchim)==3: # If we have longer then 2 remove the softclipped as you wont count it anyway
                            minval=cigarchim.index(min(cigarchim))
                            charchim.pop(minval)
                            cigarchim.pop(minval)
                        if len(CigarList)==3:
                            minval=CigarList.index(min(CigarList))
                            CigarList.pop(minval)
                            char.pop(minval)
                        if len(cigarchim) == 2 and len(CigarList)==2: # If both of them are 2 it is very straight forward!
                            startchim = line.split("\t")[16].split(":")[2].split(",")[1]
                            if "M" == charchim[0]:
                                startchim=str(int(startchim)+cigarchim[0])
                            else:
                                startchim=str(int(startchim))
                            if "M" == char[0]:
                                start=str(int(line.split("\t")[3])+int(CigarList[0]))
                                print(chrom+":"+start+"\t"+chromchim+":"+startchim, file=out)
                                #print(chrom+":"+start+"\t"+chromchim+":"+startchim)
                                listofreads.append(read)
                            else:
                                start=str(int(line.split("\t")[3]))
                                print(chrom+":"+start+"\t"+chromchim+":"+startchim, file=out)
                                #print(chrom+":"+start+"\t"+chromchim+":"+startchim)
                                listofreads.append(read)
    return clippedbed

def clippedreadbinning(clippedbed, Cleaninglist, MovingList,ChimReadDepthTresh,ChimReadBinningTresh):
    '''
    Making sure that we have enought depth  over the chimeric reads, userdefined treshold. Bin the first mapping coord using bedtools merge, then loop through the hits in the chimeric alignment to add them to the first coord
    '''
    clippedbedrange = clippedbed.split(".bed")[0] + ".clippedrange.bed"
    Cleaninglist.append(clippedbedrange)
    clippedmapping = clippedbed.split(".bed")[0] + ".clipped.bed.withcov.txt"
    Cleaninglist.append(clippedmapping)
    logging.info('%s\tBinning the clipped reads coords, depth %s',time.ctime().split(" ")[-2], ChimReadDepthTresh)
    command = "cut -f 1 %s | sed 's/:/\t/g' | sort -k1,1 -k2,2n | awk 'OFS=\"\t\" {print $1,$2,$2}' | mergeBed -c 1 -o count -d %s| awk '$4 > 4 {print $1\"\t\"$2\"\t\"$3}' > %s" %(clippedbed, ChimReadBinningTresh,clippedbedrange) # obs! Overlap is counted if they overlap a userdefined treshold away in nucleotides
    os.system(command)
    # Need to now how many lines you have so you start the counting before the for loop breaks below
    with open(clippedbed) as f:
        for nrLines, l in enumerate(f):
            pass
    with open(clippedmapping, "w") as clippedout:
        with open(clippedbedrange, "r") as clippedrange:
            counter = 0
            for line in clippedrange:
                line = line.strip()
                chrom = line.split("\t")[0]
                start = line.split("\t")[1]
                end = line.split("\t")[2]
                with open(clippedbed, "r") as chimeras:
                    counter += 1
                    d = {}
                    rownr = 0
                    for l in chimeras:
                        rownr += 1
                        l = l.strip()
                        chromfirst = l.split("\t")[0].split(":")[0]
                        startfirst = l.split("\t")[0].split(":")[1]
                        chromchim = l.split("\t")[1].split(":")[0]
                        startchim = l.split("\t")[1].split(":")[1]
                        if chromfirst == chrom and end > startfirst > start:
                            if chromchim in d.keys(): # if i have the chromosome for that range append
                                d[chromchim].append(startchim)
                            else:  # Else create as new chromosome
                                d[chromchim] = [startchim]
                    for key, value in d.items():
                        firstitem = 0
                        amount = 1
                        if len(value) > ChimReadDepthTresh: # If you have atleast 10 in depth by default
                            sortedlist = sorted(map(int,value))
                            for i in range(1,len(sortedlist)): # Remeber the indexes
                                if sortedlist[i] - sortedlist[i-1] < ChimReadBinningTresh: # If the previus item is atleast 20 away from the new one by default
                                    amount += 1
                                    if i+1 == len(value) and amount > ChimReadDepthTresh: # If you are reaching the end of the list and you have atleast 5
                                        print(line + "\t" + str(amount) + "\t" + key + "\t" + str(sortedlist[firstitem]) + "\t" + str(sortedlist[i]), file=clippedout)
                                        #print(line + "\t" + str(amount) + "\t" + key + "\t" + str(sortedlist[firstitem]) + "\t" + str(sortedlist[i]))
                                else:
                                    if amount > ChimReadDepthTresh: # not in the end of the list but you have 10 by default
                                        print(line + "\t" + str(amount) + "\t" + key + "\t" + str(sortedlist[firstitem]) + "\t" + str(sortedlist[i-1]),file=clippedout)
                                        #print(line + "\t" + str(amount) + "\t" + key + "\t" + str(sortedlist[firstitem]) + "\t" + str(sortedlist[i-1]))
                                    firstitem = i
                                    amount = 1
    return clippedmapping

def intersectClippedPseudogeneCandidates(Sample, clippedmapping, Pseudogenecandidatesbed, Cleaninglist, MovingList):
    clippedwithpseudogeneoverlap = Sample + ".Clipped_overlapPseudogenes.txt"
    Cleaninglist.append(clippedwithpseudogeneoverlap)
    logging.info('%s\tIntersect the clipped binned read coords with pseudogene candidates',time.ctime().split(" ")[-2])
    with open(clippedwithpseudogeneoverlap, "w") as out:
        with open(Pseudogenecandidatesbed, "r") as pseudocandidates:
            for line in pseudocandidates:
                line = line.strip()
                pseudochrom = line.split("\t")[0]
                pseudostart = int(line.split("\t")[1])
                pseudoend = int(line.split("\t")[2])
                pseudogene = line.split("\t")[3]
                with open(clippedmapping, "r") as clipped:
                    for cline in clipped:
                        cline = cline.strip()
                        #print(cline)
                        clipfirstchrom = cline.split("\t")[0]
                        clipsecondchrom = cline.split("\t")[4]
                        clipfirststart = int(cline.split("\t")[1] )
                        clipsecondstart = int(cline.split("\t")[5] )
                        clipdepth = cline.split("\t")[3]
                        clipfirstend = int(cline.split("\t")[2] )
                        clipsecondend = int(cline.split("\t")[6])
                        if pseudochrom == clipfirstchrom: # If first coordinates in the clip overlaps the pseudogene candidate
                            if pseudostart-10 < clipfirststart < pseudoend+10 or pseudostart-10 < clipfirstend < pseudoend+10:
                                print(pseudogene+"\t"+str(pseudochrom)+"\t"+str(pseudostart)+"\t"+str(pseudoend)+"\t"+str(clipsecondchrom)+"\t"+str(clipsecondstart)+"\t"+str(clipsecondend)+"\t"+str(clipdepth),file=out)
                        elif pseudochrom == clipsecondchrom:
                            if pseudostart-10 < clipsecondstart < pseudoend+10 or pseudostart-10 < clipsecondend < pseudoend+10:
                                print(pseudogene+"\t"+str(pseudochrom)+"\t"+str(pseudostart)+"\t"+str(pseudoend)+"\t"+str(clipfirstchrom)+"\t"+str(clipfirststart)+"\t"+str(clipfirstend)+"\t"+str(clipdepth), file=out)
    if not os.stat(clippedwithpseudogeneoverlap).st_size==0: # The clipped reads with the pseudogenes might be empty and this will break the loop. Therefore we are making sure that the file is not empty before the analysis
        pandasdf=pd.read_csv(clippedwithpseudogeneoverlap, sep = "\t", header=None) # If we have the same fusion in different positions in the pseudogene we merge them
        pandasdf2= pandasdf.groupby([0,1,2,3,4,5,6], as_index=False)[7].sum()
        #print(pandasdf2)
        pandasdf2.to_csv(clippedwithpseudogeneoverlap,sep="\t", header = False, index=False)
    else:
        logging.info('%s\tObs the Psedugene clipp overlap is emtpy',time.ctime().split(" ")[-2])
    return clippedwithpseudogeneoverlap

def CombiningClippWithChimericReads(Sample, clippedwithpseudogeneoverlap, PseudogeneCandidateChimbed, Cleaninglist, MovingList,chimreadpairdistance):
    '''
    Adding the evidence to the clipped reads from the chimeric reads
    '''
    clippedlist=[]
    chimlist=[]
    logging.info('%s\tMerging the overlapping coords from chimeric read pairs and chimeric clipped reads',time.ctime().split(" ")[-2])
    clipandchimevidence = Sample + ".Clipped_Chimeric_Evidence.txt"
    DetectedPseudogenesList = [] # List of Pseudogenes that is evident in both chim reads and pairs. We will use thes pseudogenes for the plots
    Cleaninglist.append(clipandchimevidence)
    with open(clipandchimevidence, "w") as out:
        print("Pseudogene\tP_chrom\tP_start\tP_end\tIS_chrom_left\tIS_start_left\tIS_end_left\tnChimPairs_left\tIS_chrom_right\tIS_start_right\tIS_end_right\tnChimPairs_right\tChimRead_chrom\tChimRead_Start\tChimRead_End\tnChimReads", file=out)
        with open(clippedwithpseudogeneoverlap, "r") as clippedCoord:
            for cline in clippedCoord:
                cline = cline.strip()
                pseudogene = cline.split("\t")[0]
                pseudogenechrom = cline.split("\t")[1]
                pseudogenestart = cline.split("\t")[2]
                pseudogeneend = cline.split("\t")[3]
                cfusionchrom= cline.split("\t")[4]
                cfusionstart = int(cline.split("\t")[5])
                cfusionend = int(cline.split("\t")[6])
                cfusiondepth = str(cline.split("\t")[7])
                with open(PseudogeneCandidateChimbed, "r") as chimcoord:
                    for chimline in chimcoord:
                        chimline = chimline.strip()
                        chimpseudogene = chimline.split("\t")[0]
                        chimpsudochrom = chimline.split("\t")[1]
                        chimpseudostart = int(chimline.split("\t")[2])  # Increase the range with 100 on both sides
                        chimpseudoend = int(chimline.split("\t")[3])
                        chimfuschrom = chimline.split("\t")[4]
                        chimfusstartleft = int(chimline.split("\t")[5])
                        chimfusendleft = int(chimline.split("\t")[6])
                        chimdepthleft = chimline.split("\t")[7]
                        chimfusstartright = chimline.split("\t")[9]
                        chimfusendright = chimline.split("\t")[10]
                        chimdepthrigth = chimline.split("\t")[11]
                        if pseudogene == chimpseudogene:
                            if chimfuschrom == cfusionchrom:
                                if chimfusstartright != "NA" and int(chimfusstartleft) <= cfusionstart <= int(chimfusendright): # If we have both anchors the fusion should be inbetween the start left and the end right.
                                    print(chimline +"\t"+ cfusionchrom + "\t" + str(cfusionstart) + "\t" + str(cfusionend)  + "\t" + cfusiondepth, file=out)
                                    clippedlist.append(repr(cline.rstrip())) # Append the entire row from both the chimread evidence and the clippedread evidence if we found them, if we did not detect them we can print them seperately as the final results
                                    chimlist.append(repr(chimline.rstrip()))
                                    DetectedPseudogenesList.append(pseudogene)
                                elif chimfusstartright == "NA" and (int(chimfusstartleft) - chimreadpairdistance) <= cfusionstart <= (int(chimfusendleft) + chimreadpairdistance): # We dont have the right anchor and the clipp is within the left anchor or 100 plus or minus from the left anchor by default
                                    print(chimline +"\t"+ cfusionchrom + "\t" + str(cfusionstart) + "\t" + str(cfusionend)  + "\t" + cfusiondepth, file=out)
                                    clippedlist.append(repr(cline.rstrip()))
                                    chimlist.append(repr(chimline.rstrip()))
                                    DetectedPseudogenesList.append(pseudogene)
        with open(PseudogeneCandidateChimbed, "r") as chimcoord:
            for chimline in chimcoord:
                #print repr(chimline.rstrip())
                #print chimlist
                rawstring = repr(chimline.rstrip())
                if not rawstring in chimlist: # In this case we have evidence from only a chimeric pair
                    print(chimline.rstrip() +"\tNA\tNA\tNA\tNA", file=out)
        with open(clippedwithpseudogeneoverlap, "r") as clippedCoord:
            for cline in clippedCoord:
                pseudogene = cline.split("\t")[0]
                pseudogenechrom = str(cline.split("\t")[1])
                pseudogenestart = str(cline.split("\t")[2])
                pseudogeneend = str(cline.split("\t")[3])
                cfusionchrom= str(cline.split("\t")[4])
                cfusionstart = str(cline.split("\t")[5])
                cfusionend = str(cline.split("\t")[6])
                cfusiondepth = str(cline.split("\t")[7])
                if not repr(cline.rstrip()) in clippedlist: # In this we have evidence from only clipped reads
                    print(pseudogene + "\t"+ pseudogenechrom + "\t" + pseudogenestart + "\t" + pseudogeneend + "\tNA\tNA\tNA\tNA\tNA\tNA\tNA\tNA\t" + cfusionchrom + "\t" + cfusionstart + "\t" + cfusionend + "\t" + cfusiondepth.rstrip(), file=out)
    return (clipandchimevidence, DetectedPseudogenesList)

def Pseuodogenecandidates(Sample,baminput,exoncoords, pseudogenecoords,chrominfo,genecoords,Cleaninglist, MovingList,Outputfolder,Psdepth):
    '''
    Extract reads that are split across exons, These are my pseudogene candidates
    '''
    # Files
    Cigarbam = Sample + ".extractedN.bam"
    MovingList.append(Cigarbam)
    Cigarbai = Sample + ".extractedN.bam.bai"
    MovingList.append(Cigarbai)
    Cigarbed = Sample + ".extractedN.bed"
    Cleaninglist.append(Cigarbed)
    Pseudogenecandidates = Sample + "_pseudogenecandidates.tmp"
    Cleaninglist.append(Pseudogenecandidates)
    Pseudogenecandidatesbed = Sample + ".PseudogeneCandidates.bed"
    command_extractNcigar = "samtools view -h %s | awk '$1 ~ \"@\" || $6 ~ \"N\" {print $0}' | samtools view -Sb - | samtools sort -o %s" %(baminput, Cigarbam)
    os.system(command_extractNcigar)
    command_index = "samtools index %s" % Cigarbam
    os.system(command_index)
    logging.info('%s\tLooking for pseudogene Candidates', time.ctime().split(" ")[-2])
    logging.info('%s\tCalculating coverage over spliced alignment, filt 5 depth', time.ctime().split(" ")[-2])
    # Create a bed file by using genomecov for having a treshold in mapped reads! For obtaining pseudogene candidates
    commandgenomecovforsplittranscriptreads = "genomeCoverageBed -ibam %s -g %s -bg -split | awk '($4>%s){print $1\"\t\"$2\"\t\"$3}' > %s" %(Cigarbam, chrominfo,Psdepth,Cigarbed) # Atleast 5 in coverage
    os.system(commandgenomecovforsplittranscriptreads)
    logging.info('%s\tExtracting pseudogene candidates', time.ctime().split(" ")[-2])
    commandoverlappwithknowngenes = "intersectBed -wb -a %s -b %s -split | cut -f 7 | sort -n | uniq | cut -f 2- -d \"-\" | sort -n | uniq -c | sed -e 's/^[ \t]*//' | awk '$1 > 2 {print $2}' > %s" % (Cigarbed,exoncoords, Pseudogenecandidates)
    os.system(commandoverlappwithknowngenes)
    if os.stat(Pseudogenecandidates).st_size==0: # If file is empty, no pseudogenes than you can end the script But first remove tmp files and then count the known processed pseudogenes
        # I will still add the output for the pseudogene report but i will keep it empty except for the header, then it will be included in the make ppsy report
        summaryOutAnnotatedBoth = Sample + ".ChimPairs_ChimReads.Ppsy.txt" # This is what the output is called
        MovingList.append(summaryOutAnnotatedBoth)
        with open(summaryOutAnnotatedBoth, "w") as copyexactcoord:
            print("Pseudogene\tP_chrom\tP_start\tP_end\tIS_chrom_left\tIS_start_left\tIS_end_left\tnChimPairs_left\tIS_chrom_right\tIS_start_right\tIS_end_right\tnChimPairs_right\tChimRead_chrom\tChimRead_Start\tChimRead_End\tnChimReads\tIS_Region\tIS_Gene", file=copyexactcoord)
        logging.info('%s\tCleaning...', time.ctime().split(" ")[-2])
        CountKnownPseudogenes(Sample,baminput,pseudogenecoords, MovingList)
        cleaning(Cleaninglist, MovingList,Outputfolder)
        sys.exit("No pseudogeneCandidates detected")
    else:
        Cleaninglist.append(Pseudogenecandidatesbed)
        logging.info('%s\tPseudogene candidates detected', time.ctime().split(" ")[-2])
        command = "grep -w -f %s %s > %s" %(Pseudogenecandidates, genecoords, Pseudogenecandidatesbed)
        os.system(command)
        return (Pseudogenecandidatesbed,Cigarbam)

def CountKnownPseudogenes(Sample,baminput,pseudogenecoords, MovingList):
    '''
    Here we annotate the known pseudogenes with bedtools
    '''
    logging.info('%s\tCounting known pseudogenes... reads overlapping with the pseudogene coords in Ensembl',time.ctime().split(" ")[-2])
    AmountOfreadsinKnownProcessedPseudogenes = Sample + ".KnownProcessedPseudogenes.txt"
    MovingList.append(AmountOfreadsinKnownProcessedPseudogenes)
    # Look at the intersect with known processed pseudogenes
    #print pseudogenecoords
    bedintersectcommand = "intersectBed -abam %s -b %s -bed -wb" %(baminput, pseudogenecoords)
    capture_overlap_knownProcessedPseudogenes = subprocess.Popen(bedintersectcommand,shell = True, stdout=subprocess.PIPE)
    KnownProcessedPseudogenesList = [] # Create empty list for storing the pseudogene candidates
    for line in capture_overlap_knownProcessedPseudogenes.stdout.readlines(): # Read each line of the standard out
        gene = line.strip().decode("utf-8").split("\t")[-1] # Save last item in the output from intersect, the gene names for the overlapping reads
        KnownProcessedPseudogenesList.append(gene) # Save to empty list
    counts = Counter(KnownProcessedPseudogenesList) # Count the amount of times each gene appears, save it in a count object that works as a dictionary

    min_treshold = 10 # Set treshold of how many reads the pseudogene most intersect with to be noted as there
    filteredCounts = {x : counts[x] for x in counts if counts[x] >= min_treshold } # Filter the counts based on a treshold, amounts of reads that intersect with a known processed pseudogene!
    # Get the positions of the pseudogene
    #filteredCountsSorted = sorted(filteredCounts, key=filteredCounts.get, reverse=True) # Sort the dictionary
    DictWithPostAndAmountsOfReads = {}
    with open(pseudogenecoords, "r") as knownpseudogenes: # Open the pseudogene bed file
        for line in knownpseudogenes:
            for key, value in filteredCounts.items(): # Go through the dictionary
                if line.strip().split("\t")[-1] == key:  # If gene name in known pseudogene file is the same as in the dictionary, append information about chr, start, end to the values
                    chrom = str(line.strip().split("\t")[0]) # append chromosome
                    Start = str(line.strip().split("\t")[1]) # append start
                    End = str(line.strip().split("\t")[2]) # append end
                    DictWithPostAndAmountsOfReads[key] = [chrom, Start, End, str(value)]
    with open(AmountOfreadsinKnownProcessedPseudogenes, "w") as out:
        for key, values in DictWithPostAndAmountsOfReads.items():
            out.write(key + "\t" + '\t'.join(values) + "\n")

def GvizPlottingForOutput(Sample,baminput,Cigarbam,summaryOutAnnotatedBoth,exoncoords,Cleaninglist,MovingList):
    """
    This part plots the outputs using the gviz package in R instead of circos
    """
    logging.info('%s\tPlotting The Detected PseudogeneCandidates using GVIZ',time.ctime().split(" ")[-2])
    with open(summaryOutAnnotatedBoth, "r") as finaloutputreport:
        h=next(finaloutputreport)
        exoncoordsdict = {}
        for line in finaloutputreport:
            estarts = []
            eends = []
            line = line.strip()
            parentgene = line.split("\t")[0]
            parentchrom = line.split("\t")[1]
            parentgenestart = line.split("\t")[2]
            parentgeneend = line.split("\t")[3]
            if not line.split("\t")[4] == "NA":
                fuschrom  = line.split("\t")[4]
            else: # We only have evidence in the clip therefore you need to extract it from column 12
                fuschrom  = line.split("\t")[12]
            fusstartleft = line.split("\t")[5]
            fusendleft = line.split("\t")[6]
            fusstartright = line.split("\t")[9]
            fusendright =  line.split("\t")[10]
            chimreadstart = line.split("\t")[13]
            chimreadend = line.split("\t")[14]
            Anno = line.split("\t")[16]+"_"+line.split("\t")[17]
            command = "grep -w %s %s" %(parentgene,exoncoords)
            a=subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
            for excord in a.stdout:
                excord=excord.strip().decode("utf-8")
                exonchrom = excord.split("\t")[0]
                exonstart = int(excord.split("\t")[1])
                exonend = int(excord.split("\t")[2])
                estarts.append(exonstart)
                eends.append(exonend)
            if not parentgene in exoncoordsdict.keys():
                exoncoordsdict[parentgene]=(estarts,eends)
            if not chimreadstart == "NA":
                outputname = "%s_%swithin%s-%s" %(Sample,parentgene,fuschrom,chimreadstart)
                fusionstartplot = chimreadstart # When you have the clipp coord use them for the plotting
                fusionwidth = int(chimreadend)-int(chimreadstart)
                fusionrangestart = int(chimreadstart)-100
                fusionrangeend = int(chimreadstart)+100
            else:
                outputname = "%s_%swithin%s-%s" %(Sample,parentgene,fuschrom,fusstartleft)
                if fusstartright == "NA": # You only have the left anchor, use those for the plotting
                    fusionstartplot = fusstartleft
                    fusionwidth = int(fusendleft) - int(fusstartleft)
                    fusionrangestart = int(fusstartleft)-100
                    fusionrangeend = int(fusendleft)+100
                else: # You have the entire anchor rang , use that for the plotting
                    fusionstartplot = fusstartleft
                    fusionwidth = int(fusendright)-int(fusstartleft)
                    fusionrangestart = int(fusstartleft)-100
                    fusionrangeend = int(fusendright)+100
            outputRscript = outputname + ".R"
            outputPicturepdf = outputname + ".pdf"
            outputPicturepng = outputname + ".png" # png for having in the ppsy reports, cannot create them at the nodes so you need to do it with a seperate command
            with open(outputRscript, "w") as R:
                startvector= "starts=c("+','.join(str(e) for e in exoncoordsdict[parentgene][0]) + ")"
                endvector= "ends=c("+','.join(str(e) for e in exoncoordsdict[parentgene][1]) + ")"
                print("""
#!/usr/bin/R
suppressMessages(library(Gviz))
options(ucscChromosomeNames=FALSE)
axisTrack <- GenomeAxisTrack()
%s
%s
widths=ends-starts
bamfile <- '%s'
cigarbamfile <- '%s'
# AlignmentTracks
alTrack <- DataTrack(range=bamfile, genome = "hg19", name = "Raw Coverage",  type="heatmap",chromosome="%s")
alTrack2 <- AlignmentsTrack(cigarbamfile,chromosome="%s",genome="hg19",name="Splice Coverage", isPaired=TRUE)
bamzoominsert<-DataTrack(range=bamfile, genome = "hg19", name = "Insert Coverage",  type="histogram", chromosome="%s")
# AnnotationTracks
aTrack.groups <- AnnotationTrack(start=c(starts), width=c(widths),chromosome="%s", strand=rep("*",length(starts)),group=rep("%s",length(starts)), genome = "hg19", name = "Anno")
AnnotationTrackinsert<-AnnotationTrack(start=%s, width = %s, strand="*",shape="box",id="%s",genome="hg19", chromosome="%s",name ="Insert", group = "%s")

TextTrack1 <- CustomTrack(plottingFunction = function(GdObject, prepare) {if(!prepare) grid.text("Coverage over the insert site") ; return(invisible(GdObject))}, name=NULL,displayPars=list(cex=1.5))

displayPars(aTrack.groups)<-list(fill="black", col=NULL)
displayPars(AnnotationTrackinsert)<-list(col=NULL)

pdf("%s")
grid.newpage()
pushViewport(viewport(layout=grid.layout(4, 6)))
pushViewport(viewport(layout.pos.col=c(1,2,3,4,5,6), layout.pos.row=c(1,2)))
plotTracks(list(axisTrack,alTrack,alTrack2,aTrack.groups), groupAnnotation="group", just.group=\"above\",from=%s,to=%s,type=c("heatmap","coverage"), sizes=c(1,2,3,0.5),fill.coverage=\"grey\",add=TRUE, main="Coverage over the Gene",background.title="white",col.title="black",col.axis="black", cex.main=1.5)
popViewport(1)
pushViewport(viewport(layout.pos.col=c(2.5,5.5), layout.pos.row=c(3,4)))
plotTracks(c(TextTrack1,bamzoominsert,AnnotationTrackinsert,axisTrack), from=%s,to=%s, fill="darkred", sizes =c(0.5,0.5,0.1,0.5), lwd = 1, add=TRUE, background.title="white",col.title="black",col.axis="black", groupAnnotation = "id", fill.histogram="darkgrey",col.histogram="darkgrey")
                      shhh<-dev.off()""" %(str(startvector),str(endvector), str(baminput),str(Cigarbam) ,str(parentchrom), str(parentchrom),str(fuschrom),str(parentchrom),str(parentgene),str(fusionstartplot),str(fusionwidth),str(Anno),str(fuschrom),str(Anno) ,str(outputPicturepdf),str(parentgenestart),str(parentgeneend),str(fusionrangestart),str(fusionrangeend)), file=R)
            command = "Rscript %s" %outputRscript # This part plots using the Gviz plotting
            os.system(command)
            # Cleaning up the outputs
            MovingList.append(outputPicturepdf)
            # Creating png does not work on the nodes, use the command convert instead for those ...
            command = "convert %s %s" %(outputPicturepdf, outputPicturepng)
            os.system(command)
            MovingList.append(outputPicturepng)
            MovingList.append(outputRscript)

def AnnotateFusionPoint(Sample,clipandchimevidence,exoncoords,genecoords,Cleaninglist,MovingList):
    '''
    Here we annotate the fusion point with annovar, using the absolute start position for the fusion range.
    '''
    #filestoremove = []
    logging.info('%s\tAnnotating the fusion points',time.ctime().split(" ")[-2])
    summaryOutAnnotatedBoth = Sample + ".ChimPairs_ChimReads.Ppsy.txt"
    MovingList.append(summaryOutAnnotatedBoth)
    # Calculate the insert within a gene for the fusion
    with open(summaryOutAnnotatedBoth, "w") as copyexactcoord:
        print("Pseudogene\tP_chrom\tP_start\tP_end\tIS_chrom_left\tIS_start_left\tIS_end_left\tnChimPairs_left\tIS_chrom_right\tIS_start_right\tIS_end_right\tnChimPairs_right\tChimRead_chrom\tChimRead_Start\tChimRead_End\tnChimReads\tIS_Region\tIS_Genes", file=copyexactcoord)
        with open(clipandchimevidence, 'r') as exactcoord: # Loop through a copy of the input file.
            next(exactcoord)
            for line in exactcoord:
                stripped=line.strip()
                if not stripped.split("\t")[13] == "NA": # If we have the clipped fusion point that one sets the coords, otherwise uer use the start coord on the right anchor
                    fuschr = stripped.split("\t")[12]
                    fusstart = stripped.split("\t")[13]
                    fusend = stripped.split("\t")[14]
                else:
                    fuschr = stripped.split("\t")[4]
                    fusstart = stripped.split("\t")[5]
                    fusend = stripped.split("\t")[6]
                with open(genecoords, "r") as genecoordforinsertanno: # Here we use the gene coord first, if on gene coord is detected grep the exons with the same gene coord from the alignment
                    for l in genecoordforinsertanno:
                        l = l.strip()
                        genechrom = l.split("\t")[0]
                        genestart = l.split("\t")[1]
                        geneend = l.split("\t")[2]
                        genename = l.split("\t")[3]
                        if fuschr == genechrom and int(fusstart) >= int(genestart) and int(fusend) <= int(geneend):
                            geneofinsert = genename
                            command = "grep %s %s" % (genename,exoncoords)
                            pipe = subprocess.Popen(command, shell=True, stdout = subprocess.PIPE)
                            for exoncoordline in pipe.stdout: # If we have an insert in a gene we grep the exon coordinates
                                exoncoordline = exoncoordline.strip().decode("utf-8")
                                exonchrom = exoncoordline.split("\t")[0] # I need to ad the exon chrom as an overlapp importance as well as i cannot grep exactly as the Gene coord is not exactly the same as the exon coords which have an id onto it.
                                exonstart = exoncoordline.split("\t")[1]
                                exonend = exoncoordline.split("\t")[2]
                                if fuschr == exonchrom and int(fusstart) >= int(exonstart) and int(fusend) <= int(exonend):
                                    geneinsertanno = "exonic"
                                    break
                                else:
                                    geneinsertanno = "intronic"
                            break
                        else: # No hit within the genecoord therefore it is intergenic
                            geneofinsert = "NA"
                            geneinsertanno = "intergenic"
                    print(stripped + "\t" + geneinsertanno + "\t" + geneofinsert,  file=copyexactcoord)
    return summaryOutAnnotatedBoth

def cleaning(Cleaninglist, MovingList,Outputfolder):
    # Itererating for files to be removed
    logging.info('%s\tCleaning',time.ctime().split(" ")[-2])
    if Cleaninglist:
        for item in list(set(Cleaninglist)):
            os.remove(item)
    # move all the files to this folder, then create the subfolders and move the files to that one.
    # If there is duplicates in the list, set to unique, it is ugly but some are added within a for loop
    if MovingList:
        for item in list(set(MovingList)):
            os.rename(item, Outputfolder+"/"+item)
    # Now create the subdirectories
    alignmentout = "%s/Alignments" %Outputfolder
    if os.path.exists(alignmentout):
        shutil.rmtree(alignmentout)
    os.makedirs(alignmentout)
    # Alignments
    alignmentfiles = [f for f in os.listdir(Outputfolder) if f.endswith((".bam",".bai"))]
    if alignmentfiles:
        for f in alignmentfiles:
            try:
                os.rename(Outputfolder+"/"+f, alignmentout+"/"+f)
            except OSError:
                pass
    # Gviz
    GvizOut  = "%s/Plotting" %Outputfolder
    if os.path.exists(GvizOut):
        shutil.rmtree(GvizOut)
    os.makedirs(GvizOut)
    Rscriptout = GvizOut + "/Scripts"
    if os.path.exists(Rscriptout):
        shutil.rmtree(Rscriptout)
    os.makedirs(Rscriptout)
    covplots =  [f for f in os.listdir(Outputfolder) if f.endswith((".png", ".pdf"))]
    if covplots:
        for f in covplots:
            try:
                os.rename(Outputfolder+"/"+f, GvizOut+"/"+f)
            except OSError:
                pass
    Rscripts =  [f for f in os.listdir(Outputfolder) if f.endswith(".R")]
    if Rscripts:
        for f in Rscripts:
            try:
                os.rename(Outputfolder+"/"+f, Rscriptout+"/"+f)
            except OSError:
                pass
    # OutPut Results
    Logout = "%s/PpsyReports" %Outputfolder
    if os.path.exists(Logout):
        shutil.rmtree(Logout)
    os.makedirs(Logout)
    logfiles = [f for f in os.listdir(Outputfolder) if f.endswith((".ChimPairs_ChimReads.Ppsy.txt", "_PsudogenewithFusUnfiltered.txt","BinnedPseudoFusExonOverlap.txt",".KnownProcessedPseudogenes.txt"))]
    if logfiles: # If you have something in the list
        for f in logfiles:
            try:
                os.rename(Outputfolder+"/"+f, Logout+"/"+f)
            except OSError:
                pass

def mainBam(baminput,Sample,Psdepth,insdistance,ChimPairDepthTresh,ChimPairBinningTresh,ChimReadDepthTresh, ChimReadBinningTresh,chimreadpairdistance):
    # Create the logger
    process = psutil.Process(os.getpid())
    logging.basicConfig(level=logging.INFO)
    start = time.time()
    logging.info('%s\tStarting Ppsyfinder', time.ctime())
    CommandLine  = "%s --Method Bam --pseudoCandidateDepth %s --InsertDistance %s --ChimericPairDepthTreshold %s --ChimericPairBinningTreshold %s --ChimericReadDepthTreshold %s --ChimericReadBinningTreshold %s --MergeChimReadWithChimpairTresh %s -S %s -I %s" %(sys.argv[0], arguments.Psdepth,arguments.insdistance, arguments.ChimPairDepthTresh, arguments.ChimPairBinningTresh, arguments.ChimReadDepthTresh, arguments.ChimReadBinningTresh, arguments.chimreadpairdistance, arguments.Sample, arguments.baminput)
    logging.info('%s\tCommandline\t%s', time.ctime().split(" ")[-2],CommandLine)
    CheckingPaths()
    (genecoords,pseudogenecoords,exoncoords)=database()
    (Cleaninglist, MovingList,Outputfolder)=CreatingOutputDir(Sample)
    chrominfo=CreateTheChromosomeInfoFile(baminput,Sample,Cleaninglist)
    (Pseudogenecandidatesbed,Cigarbam)=Pseuodogenecandidates(Sample,baminput,exoncoords,pseudogenecoords,chrominfo,genecoords,Cleaninglist, MovingList,Outputfolder,Psdepth)
    bamChimericPairs=extractingchimericReads(Sample, baminput, Cleaninglist, MovingList,insdistance)
    PseudogeneCandidateChimbed=ChimericReadsOverlapwithPseudogeneCandidates(Sample, bamChimericPairs,Pseudogenecandidatesbed, Cleaninglist, MovingList,ChimPairDepthTresh,ChimPairBinningTresh)
    bamClipped=extractingClipped(Sample,baminput, Cleaninglist,MovingList)
    clippedbed=ClippedBamtoCoord(bamClipped,Cleaninglist, MovingList)
    clippedmapping=clippedreadbinning(clippedbed,Cleaninglist, MovingList,ChimReadDepthTresh,ChimReadBinningTresh)
    clippedwithpseudogeneoverlap=intersectClippedPseudogeneCandidates(Sample, clippedmapping, Pseudogenecandidatesbed, Cleaninglist, MovingList)
    (clipandchimevidence, DetectedPseudogenesList)=CombiningClippWithChimericReads(Sample, clippedwithpseudogeneoverlap, PseudogeneCandidateChimbed, Cleaninglist, MovingList,chimreadpairdistance)
    CountKnownPseudogenes(Sample,baminput,pseudogenecoords, MovingList)
    summaryOutAnnotatedBoth=AnnotateFusionPoint(Sample,clipandchimevidence,exoncoords,genecoords,Cleaninglist,MovingList)
    GvizPlottingForOutput(Sample,baminput,Cigarbam,summaryOutAnnotatedBoth,exoncoords,Cleaninglist,MovingList)
    #makeCircosGraph(Sample,baminput,Cigarbam,clipandchimevidence,exoncoords,chrominfo,DetectedPseudogenesList, Cleaninglist, MovingList)
    cleaning(Cleaninglist, MovingList,Outputfolder)
    logging.info('%s\tPpsy Finished, results in output folder',time.ctime().split(" ")[-2])
    logging.info('Total memory Consumed in Bytes:\t%s',(process.memory_info()[0]))
    print(process.memory_info())
    logging.info('RunTime in Sec:\t%s', int(time.time()-start))

def mainFastq(Fastq1,Fastq2,STARindex,Sample,Psdepth,insdistance,ChimPairDepthTresh,ChimPairBinningTresh,ChimReadDepthTresh, ChimReadBinningTresh,chimreadpairdistance):
    """
    This is the Main function to run when you have a Fastq as input and need to run STAR on your data... One small issue here is the multicores, i should multithread but the rest of the script cannot be threaded... If you use nextflow this would have worked but i dont want to add another tool
    """
    # Create the logger
    process = psutil.Process(os.getpid())
    logging.basicConfig(level=logging.INFO)
    start = time.time()
    logging.info('%s\tStarting Ppsyfinder, including The Alignment', time.ctime())
    CommandLine  = "%s --Method Fastq --pseudoCandidateDepth %s --InsertDistance %s --ChimericPairDepthTreshold %s --ChimericPairBinningTreshold %s --ChimericReadDepthTreshold %s --ChimericReadBinningTreshold %s --MergeChimReadWithChimpairTresh %s -STARindex %s -S %s -R1 %s -R2 %s" %(sys.argv[0], arguments.Psdepth,arguments.insdistance, arguments.ChimPairDepthTresh, arguments.ChimPairBinningTresh, arguments.ChimReadDepthTresh, arguments.ChimReadBinningTresh, arguments.chimreadpairdistance, arguments.STARindex,arguments.Sample,arguments.Fastq1, arguments.Fastq2)
    CheckingPaths()
    (genecoords,pseudogenecoords,exoncoords)=database()
    (Cleaninglist, MovingList,Outputfolder)=CreatingOutputDir(Sample)
    baminput=AlignmentWithSTAR(Fastq1,Fastq2,STARindex,Sample,Outputfolder)
    chrominfo=CreateTheChromosomeInfoFile(baminput,Sample,Cleaninglist)
    (Pseudogenecandidatesbed,Cigarbam)=Pseuodogenecandidates(Sample,baminput,exoncoords,pseudogenecoords,chrominfo,genecoords,Cleaninglist, MovingList,Outputfolder,Psdepth)
    bamChimericPairs=extractingchimericReads(Sample, baminput, Cleaninglist, MovingList,insdistance)
    PseudogeneCandidateChimbed=ChimericReadsOverlapwithPseudogeneCandidates(Sample, bamChimericPairs,Pseudogenecandidatesbed, Cleaninglist, MovingList,ChimPairDepthTresh,ChimPairBinningTresh)
    bamClipped=extractingClipped(Sample,baminput, Cleaninglist,MovingList)
    clippedbed=ClippedBamtoCoord(bamClipped,Cleaninglist, MovingList)
    clippedmapping=clippedreadbinning(clippedbed,Cleaninglist, MovingList,ChimReadDepthTresh,ChimReadBinningTresh)
    clippedwithpseudogeneoverlap=intersectClippedPseudogeneCandidates(Sample, clippedmapping, Pseudogenecandidatesbed, Cleaninglist, MovingList)
    (clipandchimevidence, DetectedPseudogenesList)=CombiningClippWithChimericReads(Sample, clippedwithpseudogeneoverlap, PseudogeneCandidateChimbed, Cleaninglist, MovingList,chimreadpairdistance)
    CountKnownPseudogenes(Sample,baminput,pseudogenecoords, MovingList)
    summaryOutAnnotatedBoth=AnnotateFusionPoint(Sample,clipandchimevidence,exoncoords,genecoords,Cleaninglist,MovingList)
    GvizPlottingForOutput(Sample,baminput,Cigarbam,summaryOutAnnotatedBoth,exoncoords,Cleaninglist,MovingList)
    cleaning(Cleaninglist, MovingList,Outputfolder)
    logging.info('%s\tPpsy Finished, results in output folder',time.ctime().split(" ")[-2])
    logging.info('Memory Consumed in Bytes:\t%s',(process.memory_info()[0]))
    logging.info('RunTime in Sec:\t%s', int(time.time()-start))

if __name__=='__main__':
  arguments=parseArgs()
  if arguments.method == "Bam":
      mainBam(arguments.baminput, arguments.Sample,arguments.Psdepth, arguments.insdistance,arguments.ChimPairDepthTresh,arguments.ChimPairBinningTresh,arguments.ChimReadDepthTresh,arguments.ChimReadBinningTresh, arguments.chimreadpairdistance)

  else: # The input is the Fastq method so you run star within the pipeline
      mainFastq(arguments.Fastq1,arguments.Fastq2,arguments.STARindex, arguments.Sample,arguments.Psdepth, arguments.insdistance,arguments.ChimPairDepthTresh,arguments.ChimPairBinningTresh,arguments.ChimReadDepthTresh,arguments.ChimReadBinningTresh, arguments.chimreadpairdistance)


import requests
import os

# If this didn't exist ~2000 wouldn't download
def number(u):
    if u < 10:
        return '000' + f'{u}'
    elif u < 100:
        return '00' + f'{u}'
    elif u < 1000:
        return '0' + f'{u}'
    else:
        return u

# get os for clear function
if os.name == 'nt':
    clear = 'cls'
else:
    clear = 'clear'

def main():
    i = 0
    for x in range(10000):
        a = number(i)
        url = f'https://www.larvalabs.com/public/images/cryptopunks/punk{a}.png'
        r = requests.get(url=url)
        if r.status_code == 200:
            with open(f'punks/punk{a}.png', 'wb') as f:
                f.write(r.content)
            os.system(clear)
            print(f'Saved punk {i}')
        else:
            print(r.status_code)
        i += 1

if __name__ == '__main__':
    main()
else:
    print('this cannot be imported')


import sys
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

def load_train_test_data():
    samples, labels = load_data()

    # Split dataset into training set and test set (80%/20%)
    train_data, test_data, train_label, test_label = train_test_split(samples, labels, test_size=0.2, random_state=1)
    return train_data.T, train_label, test_data.T, test_label

def normalize(keypoints):

    # origin keypoint
    palmBase = np.array(keypoints[-1])
    for k in range(len(keypoints) - 1):
        scaled_keypoint = np.subtract(keypoints[k], palmBase)

    nom = (keypoints - keypoints.min(axis=0)) * 2
    denom = keypoints.max(axis=0) - keypoints.min(axis=0)
    denom[denom==0] = 1

    return -1 + nom/denom

def load_data():

    # read from keypoints.txt
    data_file = open('./keypoints/keypoints_KS.txt', 'r')
    lines = data_file.readlines()
    lines = lines[1:]

    n = len(lines)

    # gesture dictionary
    gesture_labels = {'s1':1, 's2':2, 's3':3, 's4':5, 's5':0, 's6':2, 's7':1, 's8':4, 's9':3, 's10':1, 's11':1, 'k1':0, 'k2':1, 'k3':1, 'k4':2, 'k5':2, 'k6':3, 'k7':2, 'k8':3, 'k9':5, 'k10':3}
    samples = []
    labels = []

    for l in range(n):
        coordinates = lines[l].split(',')

        # remove newline
        coordinates[-1] = coordinates[-1].rstrip()

        # ground truth
        first_string = coordinates[0].split('_')
        # decide what you want to do with the classifier labels, for now label them all '1'
        labels.append(gesture_labels[first_string[0]])
        coordinates[0] = first_string[2]

        # split coordinates into respective keypoints
        k = 3 # 3 values per keypoint
        keypoints = [coordinates[i * k:(i + 1) * k] for i in range((len(coordinates) + k - 1) // k)]

        keypoints = np.asfarray(keypoints)
        # keypoints = normalize(keypoints)
        keypoints = np.reshape(keypoints, (1, 3, 21))
        samples.append(keypoints)

    samples = np.asfarray(samples)
    labels = np.asfarray(labels)
    print("Data shape:", samples.shape)
    print("Labels shape:", labels.shape)

    return samples, labels

if __name__ == '__main__':
    load_train_test_data()


#采样偏差影响对总体的预测，可以减小采样误差，但是避免不了采样误差，
#标准差，用来表征数据的分散程度   样本-均值的平方和的均值的开方

#置信区间：用总体统计量的估计区间话标准差，用于表征数据的波动范围
#抽样方法   1）蒙特卡洛模拟
import seaborn
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
#boostrap采样的实现
def boostrap_sample():
    data = seaborn.load_dataset('iris')
    # seaborn.distplot(data['sepal_length'],color='gray')

    boost_sample = []
    for i in range(1000):
        boost_sample.append([])
    boost_mean = []
    for i in range(1000):
        boost_sample[i].append(pd.Series.sample(data['sepal_length'],replace=True))
        sample_data = pd.Series.sample(data['sepal_length'],replace=True)
        boost_mean.append(np.mean(sample_data))
    seaborn.distplot(boost_mean,color='gray')
    #求置信区间
    print(boost_mean)
    start_percentile = np.percentile(boost_mean,2.5)
    end_percentile = np.percentile(boost_mean,97.5)
    print([start_percentile,end_percentile])
    plt.show()

if __name__ == '__main__':
    boostrap_sample()