import os,sys
import pandas as pd
import numpy as np
import subprocess
import pysam
import gzip

def read_sample_file(file):
	out = {}
	files = []
	dat = pd.read_csv(file,sep="\t",header=None)
	if np.sum(dat.count()) == dat.shape[0] * dat.shape[1]:
		with open(file) as f:
			for line in f:
				line = line.strip()
				tp = line.split("\t")
				group = tp[2]
				treat = tp[1]
				file  = tp[0]
				files.append(file)
				if group in out.keys():
					if treat in out[group].keys():
						out[group][treat].append(file)
					else:
						out[group][treat] =[]
						out[group][treat].append(file)
				else:
					out[group]={}
					if treat in out[group].keys():
						out[group][treat].append(file)
					else:
						out[group][treat] =[]
						out[group][treat].append(file)
		return(out, files,True)
	else:
		return(out,files,False)

def check_raw_files(path,samplefile,p1):
	p2 = []
	if p1 == True:
		print("checking input files ...")
		files = os.listdir(path)
		for i in files:
			if i in samplefile:
				p2.append(1)
			else:
				p2.append(0)
		if 0 in p2:
			return(False)
		else:
			return(True)
	else:
		print("Missing sample info ...")
		return(False)

def generate_output_folder(outpath,p1):
	# fastqcBefore: fastqc before trimming
	# trimming
	if p1 == True:
		print("file checked ...")
		print("mkdirs ...")
		checked_outpath = check_outpath(outpath)
		print("Output folders are creating in "+checked_outpath)
		if os.path.isdir(checked_outpath + "1_QCbeforeTrim/") is False:
			cmd1= "mkdir "+ checked_outpath + "1_QCbeforeTrim/"
			subprocess.run(cmd1,shell=True)
		if os.path.isdir(checked_outpath + "2_trimmedFastq/") is False:
			cmd2= "mkdir "+ checked_outpath + "2_trimmedFastq/"
			subprocess.run(cmd2,shell=True)
		if os.path.isdir(checked_outpath + "2_length_selection/") is False:
			cmd2s="mkdir "+ checked_outpath + "2_length_selection/"
			subprocess.run(cmd2s,shell=True)
		if os.path.isdir(checked_outpath + "3_QCafterTrim/") is False:
			cmd3= "mkdir "+ checked_outpath + "3_QCafterTrim/"
			subprocess.run(cmd3,shell=True)
		if os.path.isdir(checked_outpath + "4_Mapping/") is False:
			cmd4= "mkdir "+ checked_outpath + "4_Mapping/"
			subprocess.run(cmd4,shell=True)
		if os.path.isdir(checked_outpath + "5_Pepr/") is False:
			cmd5= "mkdir "+ checked_outpath + "5_Pepr/"
			subprocess.run(cmd5,shell=True)
		if os.path.isdir(checked_outpath + "6_piRNA/") is False:
			cmd6= "mkdir "+ checked_outpath + "6_piRNA/"
			subprocess.run(cmd6,shell=True)
		return(True)
	else:
		print("Not all fastq files existed in the data folder ...")
		return(False)

def check_outpath(outpath):
	newpath = ""
	if outpath.endswith("/"):
		newpath = outpath
	else:
		newpath = outpath+"/"
	return(newpath)

def qc_before_trim(datafd,outpath):
	checked_outpath = check_outpath(outpath)
	checked_datadf  = check_outpath(datafd)
	files = os.listdir(datafd)
	for i in files:
		cmd = "fastqc -o " + checked_outpath + "1_QCbeforeTrim/ -t 4 " + checked_datadf + i
		subprocess.run(cmd,shell=True)

def trimming_fastq_with_cutadapt(datafd,outpath):
	#
	checked_outpath = check_outpath(outpath)
	checked_datadf  = check_outpath(datafd)
	files = os.listdir(datafd)
	for i in files:
		outfile = i.rstrip("fastq.gz") + ".trimmed.fq.gz"
		cmd = "cutadapt -m 15 -u 3 -a AAAAAAAAAA -o " + checked_outpath + "2_trimmedFastq/" + outfile + " " + checked_datadf+i
		subprocess.run(cmd,shell=True)

def lengthe_selection(outpath,fd):
	checked_outpath = check_outpath(outpath)
	checked_fd      = check_outpath(checked_outpath+fd)
	files = os.listdir(checked_outpath+"2_trimmedFastq/")
	for i in files:
		if i.endswith(".trimmed.fq.gz"):
			inpfile = checked_outpath+"2_trimmedFastq/"+i
			outfile = gzip.open(checked_fd+i.rstrip("trimmed.fq.gz")+".filtered.fq.gz",'wb')
			with pysam.FastxFile(inpfile) as f:
				for entry in f:
					lens = len(entry.sequence)
					if lens <= 45 and lens >= 20:
						outfile.write((entry.name+"\n"+entry.sequence+"\n"+entry.comment+"\n"+entry.quality+"\n").encode())
			outfile.close()

def check_empty_folder(outpath,subs):
	checked_outpath = check_outpath(outpath)
	ipfd = checked_outpath + subs
	if os.path.exists(ipfd) and not os.path.isfile(ipfd):
		if not os.listdir(ipfd):
			return(False)
		else:
			return(True)
	else:
		return(False)

def qc_after_trim(outpath):
	checked_outpath = check_outpath(outpath)
	files = os.listdir(checked_outpath+"2_length_selection/")
	for i in files:
		cmd = "fastqc -o " + checked_outpath + "3_QCafterTrim/ -t 4 " + checked_outpath + "2_length_selection/" + i
		subprocess.run(cmd,shell=True)

def run_mapping(outpath,genome,gtf):
	checked_outpath = check_outpath(outpath)
	files = os.listdir(checked_outpath+"2_length_selection/")
	for i in files:
		tag = i.strip("fastq.gz")
		tag = tag.strip("fq.gz")
		cmd = "STAR --runThreadN 8 --outFilterMismatchNoverLmax 0.05 --outFilterMatchNmin 16 --outFilterScoreMinOverLread 0  --outFilterMatchNminOverLread 0 --alignIntronMax 1 --genomeDir " + genome + " --sjdbGTFfile " + gtf + " --readFilesIn " + checked_outpath + "2_trimmedFastq/" + i + " --readFilesCommand zcat  --outSAMtype BAM SortedByCoordinate --outFileNamePrefix " + checked_outpath + "4_Mapping/STAR_sortedByCoord_" + tag+"."
		subprocess.run(cmd,shell=True)

def generate_bai_file_for_pepr(outpath):
	checked_outpath = check_outpath(outpath)
	files = os.listdir(checked_outpath+"4_Mapping/")
	for i in files:
		if i.endswith("bam"):
			cmd = "samtools index " + checked_outpath + "4_Mapping/"+i
			subprocess.run(cmd,shell=True)

def run_pepr(sample,outpath):
	for group,values in sample.items():
		untrted = values['untreated']
		treated = values['treated']
		untrtedfiles = get_bam_files(untrted,outpath)
		treatedfiles = get_bam_files(treated,outpath)
		cmd = "PePr -c "+",".join(treatedfiles) + " -i " + ",".join(untrtedfiles) + " --file-format bam --shiftsize 0 --windowsize 20 --threshold 1e-3 --peaktype sharp --num-processors 1 --name "+str(group)+" --output "+ check_outpath(outpath)+"5_Pepr/"
		subprocess.run(cmd,shell=True)

def get_bam_files(files,outpath):
	out = []
	bamfiles = os.listdir(check_outpath(outpath)+"4_Mapping/")
	for i in files:
		tag = i.strip("fastq.gz")
		tag = tag.strip("fq.gz")
		for x in bamfiles:
			if tag in x and x.endswith("bam"):
				out.append(check_outpath(outpath)+"4_Mapping/"+x)
	return(out)

def generate_piRNA_from_Peaks(outpath,fasta):
	outpath_checked = check_outpath(outpath)
	files = os.listdir(outpath_checked+"5_Pepr/")
	for i in files:
		if i.endswith("bed"):
			generate_file_with_seq(outpath_checked,fasta,i)

def get_tag(file):
	return(file.split("__")[0])

def read_fasta(fp):
	name, seq = None, []
	for line in fp:
		line = line.rstrip()
		if line.startswith(">"):
			if name: yield (name, ''.join(seq))
			name, seq = line.split()[0].strip(">"), []
		else:
			seq.append(line)
	if name: yield (name, ''.join(seq))

def generate_file_with_seq(outpath,fasta,file):
	tag = get_tag(file)
	inputfile = outpath+"5_Pepr/"+file
	outptfile = open(outpath+"6_piRNA/"+tag+".piRNA.txt",'w')
	coord = get_coord(inputfile)
	for seqid,seq in read_fasta(open(fasta,"r")):
		for chrs,v in coord.items():
			if chrs == seqid:
				for z in v:
					targetseq = seq[int(z[0])-1:int(z[1])]
					rightflnk = seq[int(z[0])-1-3:int(z[0])-1]
					leftflnak = seq[int(z[1])-1:int(z[1])-1+3]
					outline = z[2] + "\t" + rightflnk.upper() + "\t" +targetseq.upper() + "\t" + leftflnak.upper() + "\n"
					outptfile.write(outline)
	outptfile.close()

def get_coord(file):
	out = {}
	with open(file) as f:
		for line in f:
			line = line.strip()
			chrs = line.split("\t")[0]
			strt = line.split("\t")[1]
			end  = line.split("\t")[2]
			if chrs in out.keys():
				out[chrs].append([strt,end,line])
			else:
				out[chrs]=[]
				out[chrs].append([strt,end,line])
	return(out)


class Node:
    """docstring for Node"""
    def __init__(self, value, l_son = None, r_son = None, visited = False):
        self._value = value
        self._l_son = l_son
        self._r_son = r_son
        self._visited = visited

    def get_value(self):
        return self._value

    def get_lson(self):
        return self._l_son

    def set_lson(self, son):
        self._l_son = son

    def get_rson(self):
        return self._r_son

    def set_rson(self, son):
        self._r_son = son

    def get_visited(self):
        return self._visited

    def set_visited(self, value):
        self._visited = value

def check_node(tree, value):

    if value > tree.get_value():
        rson = tree.get_rson()
        if rson and not rson.get_visited():
            rson.set_visited(True)
            if rson.get_value() == value:
                return True
            else:
                return False
        elif rson:
            return check_node(rson, value)
        else:
            return False

    elif value < tree.get_value():
        lson = tree.get_lson()
        if lson and not lson.get_visited():
            lson.set_visited(True)
            if lson.get_value() == value:
                return True
            else:
                return False
        elif lson:
            return check_node(lson, value)
        else:
            return False

def is_same_bt(proto, seq):
    if not seq:
        return False
    root = int(seq.pop(0))
    if root != proto.get_value():
        return False
    proto.set_visited(True)
    while seq:
        value = int(seq.pop(0))
        if not check_node(proto, value):
            return False

    return True

def insert_node(root, value):
    if value < root.get_value():
        lson = root.get_lson()
        if lson:
            insert_node(lson, value)
        else:
            root.set_lson(Node(value))
    elif value > root.get_value():
        rson = root.get_rson()
        if rson:
            insert_node(rson, value)
        else:
            root.set_rson(Node(value))

def build_binary_tree(seq):
    if not seq:
        return None

    root = Node(int(seq.pop(0)))

    while seq:
        value = int(seq.pop(0))
        insert_node(root, value)

    return root

def main():
    info = input()
    while info != "0":

        case_num = int(info.split()[1])

        proto = input().split()

        for dummy in range(case_num):
            pro_t = build_binary_tree(list(proto))
            tree = input().split()
            if is_same_bt(pro_t, tree):
                print("Yes")
            else:
                print("No")

        info = input()

main()


documents = [
    {"type": "passport", "number": "2207 876234", "name": "Василий Гупкин"},
    {"type": "invoice", "number": "11-2", "name": "Геннадий Покемонов"},
    {"type": "insurance", "number": "10006", "name": "Аристарх Павлов"},
    {"type": "insurance", "number": "5455 028765"}
]

directories = {
    '1': ['2207 876234', '11-2', '5455 028765'],
    '2': ['10006'],
    '3': []
}

def add(doc):
  number_shelf = input('Введите номер полки: ')
  if number_shelf in directories.keys():
    number_doc = input('Введите номер документа: ')
    type_doc = input('Введите тип документа: ')
    name = input('Ведите номер владельца: ')
    doc.append({"type": type_doc , "number": number_doc , "name": name})
    directories[number_shelf] += [number_doc]
    print(doc)
    print(directories)

  else:
    print('Такой полки не существует')

# add(documents)

def people_name(doc):
    for doc_name in doc:
        try:
            doc_name['name']
        except:
            print(f'У данного документа {doc_name["number"]} отсутствует имя name.')

# people_name(documents)

def main():
    while True:
        user_input = input(
            'Введите номер команды: a - команда, которая добавит новый документ, p - команда, которая выведет ошибку, q - выход из программы ')
        if user_input == 'a':
            add(documents)
        if user_input == 'p':
            people_name(documents)

        elif user_input == 'q':
            break

main()


def binary_search(array, elem):
	left = 0
	right = len(array) - 1
	while left < right:
		middle = left + (right - left) // 2
		if elem > array[middle]:
			left = middle + 1
		else:
			right = middle
	return elem == array[left]

n = int(input())
n_ls = list(map(int, input().split()))
m = int(input())
m_list = list(map(int, input().split()))

for elem in m_list:
	is_exist = binary_search(n_ls, elem)
	if is_exist:
		print('YES')
	else:
		print('NO')


import json
import logging
import os
import shutil
from curses.ascii import isascii
from pathlib import Path

import torchaudio
from hw_asr.base.base_dataset import BaseDataset
from hw_asr.utils import ROOT_PATH
from speechbrain.utils.data_utils import download_file
from tqdm import tqdm

logger = logging.getLogger(__name__)

URL_LINKS = {
    "dataset": "https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2",
}

class LJspeechDataset(BaseDataset):
    def __init__(self, part, data_dir=None, *args, **kwargs):
        if data_dir is None:
            data_dir = ROOT_PATH / "data" / "datasets" / "ljspeech"
            data_dir.mkdir(exist_ok=True, parents=True)
        self._data_dir = data_dir
        index = self._get_or_load_index(part)

        super().__init__(index, *args, **kwargs)

    def _load_dataset(self):
        arch_path = self._data_dir / "LJSpeech-1.1.tar.bz2"
        print(f"Loading LJSpeech")
        download_file(URL_LINKS["dataset"], arch_path)
        shutil.unpack_archive(arch_path, self._data_dir)
        for fpath in (self._data_dir / "LJSpeech-1.1").iterdir():
            shutil.move(str(fpath), str(self._data_dir / fpath.name))
        os.remove(str(arch_path))
        shutil.rmtree(str(self._data_dir / "LJSpeech-1.1"))

        files = [file_name for file_name in (self._data_dir / "wavs").iterdir()]
        train_length = int(0.85 * len(files)) # hand split, test ~ 15%
        (self._data_dir / "train").mkdir(exist_ok=True, parents=True)
        (self._data_dir / "test").mkdir(exist_ok=True, parents=True)
        for i, fpath in enumerate((self._data_dir / "wavs").iterdir()):
            if i < train_length:
                shutil.move(str(fpath), str(self._data_dir / "train" / fpath.name))
            else:
                shutil.move(str(fpath), str(self._data_dir / "test" / fpath.name))
        shutil.rmtree(str(self._data_dir / "wavs"))

    def _get_or_load_index(self, part):
        index_path = self._data_dir / f"{part}_index.json"
        if index_path.exists():
            with index_path.open() as f:
                index = json.load(f)
        else:
            index = self._create_index(part)
            with index_path.open("w") as f:
                json.dump(index, f, indent=2)
        return index

    def _create_index(self, part):
        index = []
        split_dir = self._data_dir / part
        if not split_dir.exists():
            self._load_dataset()

        wav_dirs = set()
        for dirpath, dirnames, filenames in os.walk(str(split_dir)):
            if any([f.endswith(".wav") for f in filenames]):
                wav_dirs.add(dirpath)
        for wav_dir in tqdm(
                list(wav_dirs), desc=f"Preparing ljspeech folders: {part}"
        ):
            wav_dir = Path(wav_dir)
            trans_path = list(self._data_dir.glob("*.csv"))[0]
            with trans_path.open() as f:
                for line in f:
                    w_id = line.split('|')[0]
                    w_text = " ".join(line.split('|')[1:]).strip()
                    wav_path = wav_dir / f"{w_id}.wav"
                    if not wav_path.exists(): # elem in another part
                        continue
                    t_info = torchaudio.info(str(wav_path))
                    length = t_info.num_frames / t_info.sample_rate
                    if w_text.isascii():
                        index.append(
                            {
                                "path": str(wav_path.absolute().resolve()),
                                "text": w_text.lower(),
                                "audio_len": length,
                            }
                        )
        return index


import logging
import requests
from django.core.cache import cache
from tracker_genius_geocoder.address import Address
from tracker_genius_geocoder.address_format import AddressFormat
from tracker_genius_geocoder.geocoder import Geocoder
from typing import Optional, Callable, Any, Dict

logger = logging.getLogger(__name__)

class JsonGeocoder(Geocoder):
    def __init__(self, url: str, address_format: Optional[AddressFormat] = None) -> None:
        self.url = url
        self.address_format = address_format
        self.statitics_manager = None

    def set_statitics_manager(self, statitics_manager: Callable):
        self.statitics_manager = statitics_manager

    def read_value(self, object: Dict[str, Any], key: str) -> Optional[Any]:
        if key in object and object[key] is not None:
            return object[key]
        return None

    def handle_response(self, latitude: float, longitude: float, json: Dict[str, Any], callback: Geocoder.ReverseGeocoderCallback = None):
        address: Optional[Address] = self.parse_address(json)
        if address is not None:
            formatted_address = self.address_format.format(
                address) if self.address_format else None
            if formatted_address is not None:
                if cache.get(f'{latitude}:{longitude}') is None:
                    cache.set(f'{latitude}:{longitude}', formatted_address)
                if callback is not None:
                    callback.on_success(formatted_address)
                return formatted_address
        else:
            msg = f'Empty address. Error: {self.parse_error(json)}'
            if callback is not None:
                callback.on_error(msg)
            else:
                logger.warning(msg)

        return None

    def get_address(self, latitude: float, longitude: float, callback: Geocoder.ReverseGeocoderCallback = None) -> Optional[str]:
        if cache.get(f'{latitude}:{longitude}') is not None:
            cached_address: str = cache.get(f'{latitude}:{longitude}')
            if callback:
                callback.on_success(cached_address)
            return cached_address

        if self.statitics_manager:
            self.statitics_manager.register_geocoder_request()

        url = self.url.format(latitude, longitude)
        response = requests.get(url)

        if response.status_code == 200:
            json = response.json()
            return self.handle_response(latitude, longitude, json, callback)
        else:
            logger.warning('Geocoder network error')

        return None

    def parse_address(self, json: Dict[str, Any]) -> Optional[Address]:
        return None

    def parse_error(self, json: Dict[str, Any]):
        return None


"""
ChromosomeStructure process

- Resolve collisions between molecules and replication forks on the chromosome.
- Remove and replicate promoters and motifs that are traversed by replisomes.
- Reset the boundaries and linking numbers of chromosomal segments.
"""

from __future__ import absolute_import, division, print_function

import numpy as np

import wholecell.processes.process
from wholecell.utils.polymerize import buildSequences
from wholecell.utils import units
from six.moves import zip

class ChromosomeStructure(wholecell.processes.process.Process):
	""" ChromosomeStructure """

	_name = "ChromosomeStructure"

	# Constructor
	def __init__(self):
		super(ChromosomeStructure, self).__init__()

	# Construct object graph
	def initialize(self, sim, sim_data):
		super(ChromosomeStructure, self).initialize(sim, sim_data)

		# Load parameters
		self.RNA_sequences = sim_data.process.transcription.transcription_sequences
		self.protein_sequences = sim_data.process.translation.translation_sequences
		self.n_TUs = len(sim_data.process.transcription.rna_data)
		self.n_TFs = len(sim_data.process.transcription_regulation.tf_ids)
		self.n_amino_acids = len(sim_data.molecule_groups.amino_acids)
		self.n_fragment_bases = len(sim_data.molecule_groups.polymerized_ntps)
		replichore_lengths = sim_data.process.replication.replichore_lengths
		self.min_coordinates = -replichore_lengths[1]
		self.max_coordinates = replichore_lengths[0]
		self.relaxed_DNA_base_pairs_per_turn = sim_data.process.chromosome_structure.relaxed_DNA_base_pairs_per_turn
		self.terC_index = sim_data.process.chromosome_structure.terC_dummy_molecule_index

		# Load sim options
		self.calculate_superhelical_densities = sim._superhelical_density

		# Get placeholder value for chromosome domains without children
		self.no_child_place_holder = sim_data.process.replication.no_child_place_holder

		# Load bulk molecule views
		self.inactive_RNAPs = self.bulkMoleculeView(sim_data.molecule_ids.full_RNAP)
		self.fragmentBases = self.bulkMoleculesView(sim_data.molecule_groups.polymerized_ntps)
		self.ppi = self.bulkMoleculeView(sim_data.molecule_ids.ppi)
		self.active_tfs = self.bulkMoleculesView(
			[x + "[c]" for x in sim_data.process.transcription_regulation.tf_ids])
		self.ribosome_30S_subunit = self.bulkMoleculeView(sim_data.molecule_ids.s30_full_complex)
		self.ribosome_50S_subunit = self.bulkMoleculeView(sim_data.molecule_ids.s50_full_complex)
		self.amino_acids = self.bulkMoleculesView(sim_data.molecule_groups.amino_acids)
		self.water = self.bulkMoleculeView(sim_data.molecule_ids.water)

		# Load unique molecule views
		self.active_replisomes = self.uniqueMoleculesView('active_replisome')
		self.chromosome_domains = self.uniqueMoleculesView('chromosome_domain')
		self.active_RNAPs = self.uniqueMoleculesView('active_RNAP')
		self.RNAs = self.uniqueMoleculesView('RNA')
		self.active_ribosomes = self.uniqueMoleculesView('active_ribosome')
		self.oriCs = self.uniqueMoleculesView('oriC')
		self.full_chromosomes = self.uniqueMoleculesView('full_chromosome')
		self.promoters = self.uniqueMoleculesView('promoter')
		self.genes = self.uniqueMoleculesView('gene')
		self.DnaA_boxes = self.uniqueMoleculesView('DnaA_box')

		if self.calculate_superhelical_densities:
			self.chromosomal_segments = self.uniqueMoleculesView(
				'chromosomal_segment')

		# Listener
		monomer_data = sim_data.process.translation.monomer_data
		self.ribosome_profiling_molecules = {
			'N-ACETYLTRANSFER-MONOMER[c]': 'argA',
			}
		self.ribosome_profiling_molecule_indexes = {}
		self.ribosome_profiling_listener_sizes = {}
		for molecule in self.ribosome_profiling_molecules.keys():
			molecule_index = np.where(monomer_data['id'] == molecule)[0][0]
			listener_size = int(1 + monomer_data['length'][molecule_index].asNumber(units.aa))
			self.ribosome_profiling_molecule_indexes[molecule] = molecule_index
			self.ribosome_profiling_listener_sizes[molecule] = listener_size

	def calculateRequest(self):
		# Request access to delete active RNAPs, RNAs, ribosomes, chromosomal
		# segments, and DNA motifs
		self.active_RNAPs.request_access(self.EDIT_DELETE_ACCESS)
		self.RNAs.request_access(self.EDIT_DELETE_ACCESS)
		self.active_ribosomes.request_access(self.EDIT_DELETE_ACCESS)
		self.promoters.request_access(self.EDIT_DELETE_ACCESS)
		self.genes.request_access(self.EDIT_DELETE_ACCESS)
		self.DnaA_boxes.request_access(self.EDIT_DELETE_ACCESS)

		if self.calculate_superhelical_densities:
			self.chromosomal_segments.request_access(self.EDIT_DELETE_ACCESS)

		# Request water to degrade polypeptides from removed ribosomes
		self.water.requestAll()

	def evolveState(self):
		# Read unique molecule attributes
		replisome_domain_indexes, replisome_coordinates, replisome_unique_indexes = self.active_replisomes.attrs(
			'domain_index', 'coordinates', 'unique_index')
		all_chromosome_domain_indexes, child_domains = self.chromosome_domains.attrs(
			'domain_index', 'child_domains')
		RNAP_domain_indexes, RNAP_coordinates, RNAP_is_forward, RNAP_unique_indexes = self.active_RNAPs.attrs(
			'domain_index', 'coordinates', 'is_forward', 'unique_index')

		origin_domain_indexes = self.oriCs.attr('domain_index')
		mother_domain_indexes = self.full_chromosomes.attr('domain_index')

		RNA_TU_indexes, transcript_lengths, RNA_RNAP_indexes, RNA_unique_indexes = self.RNAs.attrs(
			'TU_index', 'transcript_length', 'RNAP_index', 'unique_index')
		ribosome_protein_indexes, ribosome_peptide_lengths, ribosome_mRNA_indexes = self.active_ribosomes.attrs(
			'protein_index', 'peptide_length', 'mRNA_index')

		promoter_TU_indexes, promoter_domain_indexes, promoter_coordinates, promoter_bound_TFs = self.promoters.attrs(
			'TU_index', 'domain_index', 'coordinates', 'bound_TF')
		gene_cistron_indexes, gene_domain_indexes, gene_coordinates = self.genes.attrs(
			'cistron_index', 'domain_index', 'coordinates')
		DnaA_box_domain_indexes, DnaA_box_coordinates, DnaA_box_bound = self.DnaA_boxes.attrs(
			'domain_index', 'coordinates', 'DnaA_bound')

		# Build dictionary of replisome coordinates with domain indexes as keys
		replisome_coordinates_from_domains = {
			domain_index: replisome_coordinates[replisome_domain_indexes == domain_index]
			for domain_index in np.unique(replisome_domain_indexes)
			}

		def get_removed_molecules_mask(domain_indexes, coordinates):
			"""
			Computes the boolean mask of unique molecules that should be
			removed based on the progression of the replication forks.
			"""
			mask = np.zeros_like(domain_indexes, dtype=bool)

			# Loop through all domains
			for domain_index in np.unique(domain_indexes):
				# Domain has active replisomes
				if domain_index in replisome_coordinates_from_domains:
					domain_replisome_coordinates = replisome_coordinates_from_domains[
						domain_index]

					# Get mask for molecules on this domain that are out of range
					domain_mask = np.logical_and.reduce((
						domain_indexes == domain_index,
						coordinates > domain_replisome_coordinates.min(),
						coordinates < domain_replisome_coordinates.max()))

				# Domain has no active replisomes
				else:
					# Domain has child domains (has finished replicating)
					if (child_domains[all_chromosome_domain_indexes == domain_index, 0]
							!= self.no_child_place_holder):
						# Remove all molecules on this domain
						domain_mask = (domain_indexes == domain_index)
					# Domain has not started replication
					else:
						continue

				mask[domain_mask] = True

			return mask

		# Build mask for molecules that should be removed
		removed_RNAPs_mask = get_removed_molecules_mask(
			RNAP_domain_indexes, RNAP_coordinates)
		removed_promoters_mask = get_removed_molecules_mask(
			promoter_domain_indexes, promoter_coordinates)
		removed_genes_mask = get_removed_molecules_mask(
			gene_domain_indexes, gene_coordinates)
		removed_DnaA_boxes_mask = get_removed_molecules_mask(
			DnaA_box_domain_indexes, DnaA_box_coordinates)

		# Get attribute arrays of remaining RNAPs
		remaining_RNAPs_mask = np.logical_not(removed_RNAPs_mask)
		remaining_RNAP_domain_indexes = RNAP_domain_indexes[remaining_RNAPs_mask]
		remaining_RNAP_coordinates = RNAP_coordinates[remaining_RNAPs_mask]
		remaining_RNAP_unique_indexes = RNAP_unique_indexes[remaining_RNAPs_mask]

		# Build masks for head-on and co-directional collisions between RNAPs
		# and replication forks
		RNAP_headon_collision_mask = np.logical_and(
			removed_RNAPs_mask,
			np.logical_xor(RNAP_is_forward, RNAP_coordinates > 0))
		RNAP_codirectional_collision_mask = np.logical_and(
			removed_RNAPs_mask, np.logical_not(RNAP_headon_collision_mask))

		n_total_collisions = np.count_nonzero(removed_RNAPs_mask)
		n_headon_collisions = np.count_nonzero(RNAP_headon_collision_mask)
		n_codirectional_collisions = np.count_nonzero(
			RNAP_codirectional_collision_mask)

		# Write values to listeners
		self.writeToListener(
			'RnapData', 'n_total_collisions', n_total_collisions)
		self.writeToListener(
			'RnapData', 'n_headon_collisions', n_headon_collisions)
		self.writeToListener(
			'RnapData', 'n_codirectional_collisions', n_codirectional_collisions)
		self.writeToListener(
			'RnapData', 'headon_collision_coordinates',
			RNAP_coordinates[RNAP_headon_collision_mask])
		self.writeToListener(
			'RnapData', 'codirectional_collision_coordinates',
			RNAP_coordinates[RNAP_codirectional_collision_mask])

		if self.calculate_superhelical_densities:
			# Get attributes of existing segments
			boundary_molecule_indexes, boundary_coordinates, segment_domain_indexes, linking_numbers = self.chromosomal_segments.attrs(
				'boundary_molecule_indexes', 'boundary_coordinates',
				'domain_index', 'linking_number')

			# Initialize new attributes of chromosomal segments
			all_new_boundary_molecule_indexes = np.empty((0, 2), dtype=np.int64)
			all_new_boundary_coordinates = np.empty((0, 2), dtype=np.int64)
			all_new_segment_domain_indexes = np.array([], dtype=np.int32)
			all_new_linking_numbers = np.array([], dtype=np.float64)

			for domain_index in np.unique(all_chromosome_domain_indexes):
				# Skip domains that have completed replication
				if np.all(domain_index < mother_domain_indexes):
					continue

				domain_spans_oriC = (domain_index in origin_domain_indexes)
				domain_spans_terC = (domain_index in mother_domain_indexes)

				# Get masks for segments and RNAPs in this domain
				segments_domain_mask = (segment_domain_indexes == domain_index)
				RNAP_domain_mask = (remaining_RNAP_domain_indexes == domain_index)

				# Parse attributes of segments in this domain
				boundary_molecule_indexes_this_domain = boundary_molecule_indexes[segments_domain_mask, :]
				boundary_coordinates_this_domain = boundary_coordinates[segments_domain_mask, :]
				linking_numbers_this_domain = linking_numbers[segments_domain_mask]

				# Parse attributes of remaining RNAPs in this domain
				new_molecule_coordinates_this_domain = remaining_RNAP_coordinates[RNAP_domain_mask]
				new_molecule_indexes_this_domain = remaining_RNAP_unique_indexes[RNAP_domain_mask]

				# Append coordinates and indexes of replisomes on this domain, if any
				if not domain_spans_oriC:
					replisome_domain_mask = (replisome_domain_indexes == domain_index)

					new_molecule_coordinates_this_domain = np.concatenate((
						new_molecule_coordinates_this_domain,
						replisome_coordinates[replisome_domain_mask]
						))
					new_molecule_indexes_this_domain = np.concatenate((
						new_molecule_indexes_this_domain,
						replisome_unique_indexes[replisome_domain_mask]
						))

				# Append coordinates and indexes of parent domain replisomes, if any
				if not domain_spans_terC:
					parent_domain_index = all_chromosome_domain_indexes[
						np.where(child_domains == domain_index)[0][0]]
					replisome_parent_domain_mask = (replisome_domain_indexes == parent_domain_index)

					new_molecule_coordinates_this_domain = np.concatenate((
						new_molecule_coordinates_this_domain,
						replisome_coordinates[replisome_parent_domain_mask]
						))
					new_molecule_indexes_this_domain = np.concatenate((
						new_molecule_indexes_this_domain,
						replisome_unique_indexes[replisome_parent_domain_mask]
						))

				# If there are no molecules left on this domain, continue
				if len(new_molecule_indexes_this_domain) == 0:
					continue

				# Calculate attributes of new segments
				new_segment_attrs = self._compute_new_segment_attributes(
					boundary_molecule_indexes_this_domain,
					boundary_coordinates_this_domain,
					linking_numbers_this_domain,
					new_molecule_indexes_this_domain,
					new_molecule_coordinates_this_domain,
					domain_spans_oriC, domain_spans_terC
					)

				# Append to existing array of new segment attributes
				all_new_boundary_molecule_indexes = np.vstack((
					all_new_boundary_molecule_indexes,
					new_segment_attrs["boundary_molecule_indexes"]))
				all_new_boundary_coordinates = np.vstack((
					all_new_boundary_coordinates,
					new_segment_attrs["boundary_coordinates"]))
				all_new_segment_domain_indexes = np.concatenate((
					all_new_segment_domain_indexes,
					np.full(len(new_segment_attrs["linking_numbers"]), domain_index,
						dtype=np.int32)))
				all_new_linking_numbers = np.concatenate((
					all_new_linking_numbers, new_segment_attrs["linking_numbers"]))

			# Delete all existing chromosomal segments
			self.chromosomal_segments.delByIndexes(
				np.arange(self.chromosomal_segments.total_count()))

			# Add new chromosomal segments
			n_segments = len(all_new_linking_numbers)
			self.chromosomal_segments.moleculesNew(
				n_segments,
				boundary_molecule_indexes=all_new_boundary_molecule_indexes,
				boundary_coordinates=all_new_boundary_coordinates,
				domain_index=all_new_segment_domain_indexes,
				linking_number=all_new_linking_numbers,
				)

		# Get mask for RNAs that are transcribed from removed RNAPs
		removed_RNAs_mask = np.isin(
			RNA_RNAP_indexes, RNAP_unique_indexes[removed_RNAPs_mask])

		# Remove RNAPs and RNAs that have collided with replisomes
		if n_total_collisions > 0:
			self.active_RNAPs.delByIndexes(np.where(removed_RNAPs_mask)[0])
			self.RNAs.delByIndexes(np.where(removed_RNAs_mask)[0])

			# Increment counts of inactive RNAPs
			self.inactive_RNAPs.countInc(n_total_collisions)

			# Get sequences of incomplete transcripts
			incomplete_sequence_lengths = transcript_lengths[
				removed_RNAs_mask]
			n_initiated_sequences = np.count_nonzero(incomplete_sequence_lengths)

			if n_initiated_sequences > 0:
				incomplete_sequences = buildSequences(
					self.RNA_sequences,
					RNA_TU_indexes[removed_RNAs_mask],
					np.zeros(n_total_collisions, dtype=np.int64),
					np.full(n_total_collisions, incomplete_sequence_lengths.max()))

				base_counts = np.zeros(self.n_fragment_bases, dtype=np.int64)

				for sl, seq in zip(incomplete_sequence_lengths, incomplete_sequences):
					base_counts += np.bincount(seq[:sl], minlength=self.n_fragment_bases)

				# Increment counts of fragment NTPs and phosphates
				self.fragmentBases.countsInc(base_counts)
				self.ppi.countInc(n_initiated_sequences)

		# Get mask for ribosomes that are bound to nonexisting mRNAs
		remaining_RNA_unique_indexes = RNA_unique_indexes[
			np.logical_not(removed_RNAs_mask)]
		removed_ribosomes_mask = np.logical_not(np.isin(
			ribosome_mRNA_indexes, remaining_RNA_unique_indexes))
		n_removed_ribosomes = np.count_nonzero(removed_ribosomes_mask)

		# Remove ribosomes that are bound to removed mRNA molecules
		collision_removed_ribosomes = {}
		for molecule, gene in self.ribosome_profiling_molecules.items():
			listener_size = self.ribosome_profiling_listener_sizes[molecule]
			collision_removed_ribosomes[gene] = np.zeros(listener_size)

		if n_removed_ribosomes > 0:

			(protein_indexes, peptide_lengths,) = self.active_ribosomes.attrs(
				'protein_index', 'peptide_length')

			for molecule, gene in self.ribosome_profiling_molecules.items():
				molecule_index = self.ribosome_profiling_molecule_indexes[molecule]
				ribosomes_removed = np.logical_and(
					removed_ribosomes_mask,
					protein_indexes == molecule_index,
					)
				if np.any(ribosomes_removed):
					for position in peptide_lengths[np.where(ribosomes_removed)[0]]:
						collision_removed_ribosomes[gene][position] += 1

			self.active_ribosomes.delByIndexes(
				np.where(removed_ribosomes_mask)[0])

			# Increment counts of inactive ribosomal subunits
			self.ribosome_30S_subunit.countInc(n_removed_ribosomes)
			self.ribosome_50S_subunit.countInc(n_removed_ribosomes)

			# Get amino acid sequences of incomplete polypeptides
			incomplete_sequence_lengths = ribosome_peptide_lengths[
				removed_ribosomes_mask]
			n_initiated_sequences = np.count_nonzero(incomplete_sequence_lengths)

			if n_initiated_sequences > 0:
				incomplete_sequences = buildSequences(
					self.protein_sequences,
					ribosome_protein_indexes[removed_ribosomes_mask],
					np.zeros(n_removed_ribosomes, dtype=np.int64),
					np.full(n_removed_ribosomes, incomplete_sequence_lengths.max()))

				amino_acid_counts = np.zeros(
					self.n_amino_acids, dtype=np.int64)

				for sl, seq in zip(incomplete_sequence_lengths, incomplete_sequences):
					amino_acid_counts += np.bincount(
						seq[:sl], minlength=self.n_amino_acids)

				# Increment counts of free amino acids and decrease counts of
				# free water molecules
				self.amino_acids.countsInc(amino_acid_counts)
				self.water.countDec(
					incomplete_sequence_lengths.sum() - n_initiated_sequences)

		# Write to listener
		self.writeToListener(
			'RnapData', 'n_removed_ribosomes', n_removed_ribosomes)

		for molecule, gene in self.ribosome_profiling_molecules.items():
			self.writeToListener('TrnaCharging', f'collision_removed_ribosomes_{gene}',
				collision_removed_ribosomes[gene])

		def get_replicated_motif_attributes(old_coordinates, old_domain_indexes):
			"""
			Computes the attributes of replicated motifs on the chromosome,
			given the old coordinates and domain indexes of the original motifs.
			"""
			# Coordinates are simply repeated
			new_coordinates = np.repeat(old_coordinates, 2)

			# Domain indexes are set to the child indexes of the original index
			new_domain_indexes = child_domains[
				np.array([np.where(all_chromosome_domain_indexes == idx)[0][0]
					for idx in old_domain_indexes]),
				:].flatten()

			return new_coordinates, new_domain_indexes

		# Replicate promoters
		n_new_promoters = 2*np.count_nonzero(removed_promoters_mask)

		if n_new_promoters > 0:
			# Delete original promoters
			self.promoters.delByIndexes(np.where(removed_promoters_mask)[0])

			# Add freed active tfs
			self.active_tfs.countsInc(
				promoter_bound_TFs[removed_promoters_mask, :].sum(axis=0))

			# Set up attributes for the replicated promoters
			promoter_TU_indexes_new = np.repeat(promoter_TU_indexes[removed_promoters_mask], 2)
			promoter_coordinates_new, promoter_domain_indexes_new = get_replicated_motif_attributes(
				promoter_coordinates[removed_promoters_mask],
				promoter_domain_indexes[removed_promoters_mask])

			# Add new promoters with new domain indexes
			self.promoters.moleculesNew(
				n_new_promoters,
				TU_index=promoter_TU_indexes_new,
				coordinates=promoter_coordinates_new,
				domain_index=promoter_domain_indexes_new,
				bound_TF=np.zeros((n_new_promoters, self.n_TFs), dtype=bool))

		# Replicate genes
		n_new_genes = 2 * np.count_nonzero(removed_genes_mask)

		if n_new_genes > 0:
			# Delete original promoters
			self.genes.delByIndexes(np.where(removed_genes_mask)[0])

			# Set up attributes for the replicated promoters
			gene_cistron_indexes_new = np.repeat(gene_cistron_indexes[removed_genes_mask], 2)
			gene_coordinates_new, gene_domain_indexes_new = get_replicated_motif_attributes(
				gene_coordinates[removed_genes_mask],
				gene_domain_indexes[removed_genes_mask])

			# Add new promoters with new domain indexes
			self.genes.moleculesNew(
				n_new_genes,
				cistron_index=gene_cistron_indexes_new,
				coordinates=gene_coordinates_new,
				domain_index=gene_domain_indexes_new,
				)

		# Replicate DnaA boxes
		n_new_DnaA_boxes = 2*np.count_nonzero(removed_DnaA_boxes_mask)

		if n_new_DnaA_boxes > 0:
			# Delete original DnaA boxes
			self.DnaA_boxes.delByIndexes(np.where(removed_DnaA_boxes_mask)[0])

			# Set up attributes for the replicated boxes
			DnaA_box_coordinates_new, DnaA_box_domain_indexes_new = get_replicated_motif_attributes(
				DnaA_box_coordinates[removed_DnaA_boxes_mask],
				DnaA_box_domain_indexes[removed_DnaA_boxes_mask])

			# Add new promoters with new domain indexes
			self.DnaA_boxes.moleculesNew(
				n_new_DnaA_boxes,
				coordinates=DnaA_box_coordinates_new,
				domain_index=DnaA_box_domain_indexes_new,
				DnaA_bound=np.zeros(n_new_DnaA_boxes, dtype=bool))

	def _compute_new_segment_attributes(self, old_boundary_molecule_indexes,
			old_boundary_coordinates, old_linking_numbers,
			new_molecule_indexes, new_molecule_coordinates,
			spans_oriC, spans_terC):
		# type: (np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray, bool, bool) -> dict
		"""
		Calculates the updated attributes of chromosomal segments belonging to
		a specific chromosomal domain, given the previous and current
		coordinates of molecules bound to the chromosome.
		Args:
			old_boundary_molecule_indexes (np.ndarray, (N, 2)): Array of unique
				indexes of molecules that formed the boundaries of each
				chromosomal segment in the previous timestep.
			old_boundary_coordinates (np.ndarray, (N, 2)): Array of chromosomal
			 	coordinates of molecules that formed the boundaries of each
			 	chromosomal segment in the previous timestep.
			old_linking_numbers (np.ndarray, (N,)): Linking numbers of each
				chromosomal segment in the previous timestep.
			new_molecule_indexes (np.ndarray, (N,)): Unique indexes of all
				molecules bound to the domain at the current timestep.
			new_molecule_coordinates (np.ndarray, (N,)): Chromosomal
				coordinates of all molecules bound to the domain at the current
				timestep.
			spans_oriC (bool): True if the domain spans the origin.
			spans_terC (bool): True if the domain spans the terminus.
		Returns (wrapped as dict):
			boundary_molecule_indexes (np.ndarray, (M, 2)): Array of unique
				indexes of molecules that form the boundaries of new
				chromosomal segments.
			boundary_coordinates (np.ndarray, (M, 2)): Array of chromosomal
				coordinates of molecules that form the boundaries of new
				chromosomal segments.
			linking_numbers (np.ndarray, (M,)): Linking numbers of new
				chromosomal segments.
		"""
		# Sort old segment arrays by coordinates of left boundary
		old_coordinates_argsort = np.argsort(old_boundary_coordinates[:, 0])
		old_boundary_coordinates_sorted = old_boundary_coordinates[old_coordinates_argsort, :]
		old_boundary_molecule_indexes_sorted = old_boundary_molecule_indexes[old_coordinates_argsort, :]
		old_linking_numbers_sorted = old_linking_numbers[old_coordinates_argsort]

		# Sort new segment arrays by molecular coordinates
		new_coordinates_argsort = np.argsort(new_molecule_coordinates)
		new_molecule_coordinates_sorted = new_molecule_coordinates[new_coordinates_argsort]
		new_molecule_indexes_sorted = new_molecule_indexes[new_coordinates_argsort]

		# Domain does not span the origin
		if not spans_oriC:
			# A fragment spans oriC if two boundaries have opposite signs,
			# or both are equal to zero
			oriC_fragment_counts = np.count_nonzero(
				np.logical_not(np.logical_xor(
					old_boundary_coordinates_sorted[:, 0] < 0,
					old_boundary_coordinates_sorted[:, 1] > 0
					)))

			# if oriC fragment did not exist in the domain in the previous
			# timestep, add a dummy fragment that covers the origin with
			# linking number zero. This is done to generalize the
			# implementation of this method.
			if oriC_fragment_counts == 0:
				# Index of first segment where left boundary is nonnegative
				oriC_fragment_index = np.argmax(
					old_boundary_coordinates_sorted[:, 0] >= 0)

				# Get indexes of boundary molecules for this dummy segment
				oriC_fragment_boundary_molecule_indexes = np.array([
					old_boundary_molecule_indexes_sorted[oriC_fragment_index - 1, 1],
					old_boundary_molecule_indexes_sorted[oriC_fragment_index, 0]
					])

				# Insert dummy segment to array
				old_boundary_molecule_indexes_sorted = np.insert(
					old_boundary_molecule_indexes_sorted,
					oriC_fragment_index, oriC_fragment_boundary_molecule_indexes,
					axis=0)
				old_linking_numbers_sorted = np.insert(
					old_linking_numbers_sorted,
					oriC_fragment_index, 0)
			else:
				# There should not be more than one fragment that spans oriC
				assert oriC_fragment_counts == 1

		# Domain spans the terminus
		if spans_terC:
			# If the domain spans the terminus, dummy molecules are added to
			# each end of the chromosome s.t. the segment that spans terC is
			# split to two segments and we can maintain a linear representation
			# for the circular chromosome. These two segments are later
			# adjusted to have the same superhelical densities.
			new_molecule_coordinates_sorted = np.insert(
				new_molecule_coordinates_sorted,
				[0, len(new_molecule_coordinates_sorted)],
				[self.min_coordinates, self.max_coordinates]
				)

			new_molecule_indexes_sorted = np.insert(
				new_molecule_indexes_sorted,
				[0, len(new_molecule_indexes_sorted)], self.terC_index
				)

			# Add dummy molecule to old segments if they do not already exist
			if old_boundary_molecule_indexes_sorted[0, 0] != self.terC_index:
				old_boundary_molecule_indexes_sorted = np.vstack((
					np.array([self.terC_index, old_boundary_molecule_indexes_sorted[0, 0]]),
					old_boundary_molecule_indexes_sorted,
					np.array([old_boundary_molecule_indexes_sorted[-1, 1], self.terC_index])
					))
				old_linking_numbers_sorted = np.insert(
					old_linking_numbers_sorted,
					[0, len(old_linking_numbers_sorted)], 0
					)

		# Recalculate linking numbers of each segment after accounting for
		# boundary molecules that were removed in the current timestep
		linking_numbers_after_removal = []
		right_boundaries_retained = np.isin(
			old_boundary_molecule_indexes_sorted[:, 1],
			new_molecule_indexes_sorted)

		# Add up linking numbers of each segment until each retained boundary
		ln_this_fragment = 0.
		for retained, ln in zip(right_boundaries_retained, old_linking_numbers_sorted):
			ln_this_fragment += ln

			if retained:
				linking_numbers_after_removal.append(ln_this_fragment)
				ln_this_fragment = 0.

		# Number of segments should be equal to number of retained boundaries
		assert len(linking_numbers_after_removal) == right_boundaries_retained.sum()

		# Redistribute linking numbers of the two terC segments such that the
		# segments have same superhelical densities
		if spans_terC and np.count_nonzero(right_boundaries_retained) > 1:
			# Get molecule indexes of the boundaries of the two terC segments
			# left and right of terC
			retained_boundary_indexes = np.where(right_boundaries_retained)[0]
			left_segment_boundary_index = old_boundary_molecule_indexes_sorted[retained_boundary_indexes[0], 1]
			right_segment_boundary_index = old_boundary_molecule_indexes_sorted[retained_boundary_indexes[-2], 1]

			# Get mapping from molecule index to chromosomal coordinates
			molecule_index_to_coordinates = {
				index: coordinates for index, coordinates
				in zip(new_molecule_indexes_sorted, new_molecule_coordinates_sorted)
				}

			# Distribute linking number between two segments proportional to
			# the length of each segment
			left_segment_length = molecule_index_to_coordinates[left_segment_boundary_index] - self.min_coordinates
			right_segment_length = self.max_coordinates - molecule_index_to_coordinates[right_segment_boundary_index]
			full_segment_length = left_segment_length + right_segment_length
			full_linking_number = linking_numbers_after_removal[0] + linking_numbers_after_removal[-1]

			linking_numbers_after_removal[0] = full_linking_number * left_segment_length/full_segment_length
			linking_numbers_after_removal[-1] = full_linking_number * right_segment_length/full_segment_length

		# Get mask for molecules that already existed in the previous timestep
		existing_molecules_mask = np.isin(
			new_molecule_indexes_sorted, old_boundary_molecule_indexes_sorted)

		# Get numbers and lengths of new segments that each segment will be
		# split into
		segment_split_sizes = np.diff(np.where(existing_molecules_mask)[0])
		segment_lengths = np.diff(new_molecule_coordinates_sorted)

		assert len(segment_split_sizes) == len(linking_numbers_after_removal)

		# Calculate linking numbers of each segment after accounting for new
		# boundaries that were added
		new_linking_numbers = []
		i = 0

		for ln, size in zip(linking_numbers_after_removal, segment_split_sizes):
			if size == 1:
				new_linking_numbers.append(ln)
			else:
				# Split linking number proportional to length of segment
				total_length = segment_lengths[i:i + size].sum()
				new_linking_numbers.extend(
					list(ln*segment_lengths[i:i + size]/total_length)
					)
			i += size

		# Handle edge case where a domain was just initialized, and two
		# replisomes are bound to the origin
		if len(new_linking_numbers) == 0:
			new_linking_numbers = [0]

		# Build Mx2 array for boundary indexes and coordinates
		new_boundary_molecule_indexes = np.hstack((
			new_molecule_indexes_sorted[:-1, np.newaxis],
			new_molecule_indexes_sorted[1:, np.newaxis]
			))
		new_boundary_coordinates = np.hstack((
			new_molecule_coordinates_sorted[:-1, np.newaxis],
			new_molecule_coordinates_sorted[1:, np.newaxis]
			))
		new_linking_numbers = np.array(new_linking_numbers)

		# If domain does not span oriC, remove new segment that spans origin
		if not spans_oriC:
			oriC_fragment_mask = np.logical_not(np.logical_xor(
				new_boundary_coordinates[:, 0] < 0,
				new_boundary_coordinates[:, 1] > 0
				))

			assert oriC_fragment_mask.sum() == 1

			new_boundary_molecule_indexes = new_boundary_molecule_indexes[
				np.logical_not(oriC_fragment_mask), :]
			new_boundary_coordinates = new_boundary_coordinates[
				np.logical_not(oriC_fragment_mask), :]
			new_linking_numbers = new_linking_numbers[
				np.logical_not(oriC_fragment_mask)]

		return {
			"boundary_molecule_indexes": new_boundary_molecule_indexes,
			"boundary_coordinates": new_boundary_coordinates,
			"linking_numbers": new_linking_numbers
			}


#!/usr/local/bin/python3
# /usr/bin/python3
# Set the path to your python3 above
import numpy
from gtp_connection import GtpConnection
from board_util import GoBoardUtil
from board import GoBoard
from sys import stdin, stdout, stderr
import numpy as np
from ucb import runUcb
from pattern_util import PatternUtil
import random

class Go0:
    def __init__(self):
        """
        NoGo player that selects moves randomly from the set of legal moves.

        Parameters
        ----------
        name : str
            name of the player (used by the GTP interface).
        version : float
            version number (used by the GTP interface).
        """
        self.name = "Go0"
        self.version = 1.0
        self.selection = "rr"
        self.policy = "random"
        self.sim = 10
        self.limit = 100

    def get_move(self, board, color):
        # return GoBoardUtil.generate_random_move(board, color,
        #                                         use_eye_filter=False)
        cboard = board.copy()
        emptyPoints = board.get_empty_points()
        moves = []
        for p in emptyPoints:
            if board.is_legal(p, color):
                moves.append(p)
        # If there are no more legal moves
        if not moves:
            return None
        if self.selection == 'ucb':
            C = 0.4
            best = runUcb(self, cboard, C, moves, color)

            return best
        else:
            # This is for rr
            moveWins = []
            for move in moves:
                wins = self.simulateMove(cboard, move, color)
                moveWins.append(wins)
            #writeMoves(cboard, moves, moveWins, self.args.sim)

            return select_best_move(board, moves, moveWins)

    def simulateMove(self, board, move, toplay) -> int:
        """
        Run self.sim simulations for a given move. Returns number of wins.
        """
        wins = 0
        for _ in range(self.sim):
            result = self.simulate(board, move, toplay)
            if result == toplay:
                wins += 1
        return wins

    def simulate(self, board, move, toplay):
        """
        Run a simulated game for a given move.
        """
        cboard: GoBoard = board.copy()
        cboard.play_move(move, toplay)
        opp = GoBoardUtil.opponent(toplay)
        return self.playGame(cboard, opp)

    def playGame(self, board, color):
        """
        Run a simulation game.
        """
        for _ in range(self.limit):
            color = board.current_player

            if self.policy == 'random':
                move = GoBoardUtil.generate_random_move(board, color, True)
                if move == None:
                    return GoBoardUtil.opponent(color)
            else:
                legal_moves = GoBoardUtil.generate_legal_moves(board, color)
                if len(legal_moves) == 0:
                    return GoBoardUtil.opponent(color)
                values = []
                for move in legal_moves:
                    value = PatternUtil.get_value(board, color, move)
                    values.append(float(value))
                #maxIndex = values.index(max(values))

                move = random.choices(legal_moves, values)[0]

            board.play_move(move, color)

        return None
    def respond(self, response=""):
        """ Send response to stdout """
        stdout.write("+ {}\n\n".format(response))
        stdout.flush()

def select_best_move(board, moves, moveWins):
    max_child: int = np.argmax(moveWins)
    return moves[max_child]

def run():
    """
    start the gtp connection and wait for commands.
    """
    board = GoBoard(7)
    con = GtpConnection(Go0(), board)
    con.start_connection()

if __name__ == "__main__":
    run()


from django.urls import path

from upload.controllers.upload import (
    UploadStartController,
    UploadPauseController,
    UploadResumeController,
    UploadProgressController,
    UploadTerminateController,
    TableExistController,
)

app_name = "upload"

urlpatterns = [
    path("start", UploadStartController.as_view(), name="upload_start"),
    path("pause", UploadPauseController.as_view(), name="upload_pause"),
    path("resume", UploadResumeController.as_view(), name="upload_resume"),
    path("terminate", UploadTerminateController.as_view(), name="upload_terminate",),
    path("progress", UploadProgressController.as_view(), name="upload_progress"),
    path("exists/<str:userid>", TableExistController.as_view(), name="table_exists"),
]


import json
import shutil
import os
from .settings import LOG
from .print_color import print_colored

class fileManager:
    """
    This class manages files and directories
    """

    def __init__(self, source: str) -> None:
        self.source = source
        self.counter_files = 0
        self.counter_replace_injector = 0
        self.counter_replace_filename = 0
        self.counter_replace_content = 0

        self._count_files_recursively()

    def erase_files(self) -> None:
        for filename in os.listdir(self.source):
            file_path = os.path.join(self.source, filename)
            try:
                if os.path.isfile(file_path) or os.path.islink(file_path):
                    if filename != ".gitkeep":
                        os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)

            except Exception as e:
                print("Failed to delete %s. Reason: %s" % (file_path, e))

        if LOG:
            erased_folder = os.path.basename(self.source)
            print_colored(f"Files in '{erased_folder}' were erased.", color="blue")

    def move_files(self, destination: str) -> None:
        try:
            # Create the destination directory if it doesn't exist
            if not os.path.exists(destination):
                os.makedirs(destination)

            # Iterate over the items in the source directory
            for item in os.listdir(self.source):
                source_path = os.path.join(self.source, item)
                destination_path = os.path.join(destination, item)

                # Check if the item is a file or a directory
                if os.path.isfile(source_path):
                    shutil.copy2(source_path, destination_path)  # Copy the file
                elif os.path.isdir(source_path):
                    shutil.copytree(
                        source_path, destination_path
                    )  # Copy the directory recursively

            if LOG:
                print_colored(
                    f"Files moved from '{self.source}' to '{destination}'.",
                    color="blue",
                )

        except Exception as e:
            print_colored(
                f"An error occurred while MOVING files: {str(e)}", color="red"
            )

    def replace_inject_file(self, file_path, replacements: dict) -> None:
        try:
            filename = os.path.basename(file_path)

            with open(file_path, "r") as file:
                original_content = file.read()

            updated_content = original_content
            for tag, replacement_file in replacements.items():
                with open(replacement_file, "r") as replacement:
                    replacement_content = replacement.read()

                updated_content = updated_content.replace(tag, replacement_content)

                if filename.endswith("json"):
                    updated_content = self._format_json(updated_content, 2)

            with open(file_path, "w") as file:
                file.write(updated_content)

            self.counter_replace_injector += 1

            if LOG:
                print_colored(f"INJECTOR: File {filename} was injected.", color="blue")

        except Exception as e:
            print_colored(
                f"An error occurred while injecting file {filename}:",
                str(e),
                color="red",
            )

    def replace_filename(self, file_path: str, replacements: dict) -> None:
        directory = os.path.dirname(file_path)
        old_filename = os.path.basename(file_path)
        new_filename = old_filename

        for tag, content in replacements.items():
            if new_filename.find(tag) > 0:
                self.counter_replace_filename += 1
            new_filename = new_filename.replace(tag, content)

        new_file_path = os.path.join(directory, new_filename)

        try:
            os.rename(file_path, new_file_path)
            if LOG:
                print_colored(f"FILENAME: renamed to: {new_filename}", color="blue")
        except OSError:
            print_colored(
                f"FILENAME: Failed to rename the file {old_filename}.", color="red"
            )
            return None

    def replace_content(self, file_path: str, replacements: dict) -> None:
        with open(file_path, "r+") as stream:
            try:
                data = stream.read()
            except Exception as err:
                raise Exception(f"{file_path} {err}")

            for tag, content in replacements.items():
                if data.find(tag) > 0:
                    data = data.replace(tag, content)
                    self.counter_replace_content += 1

                    if LOG:
                        filename = os.path.basename(file_path)
                        print_colored(
                            f"CONTENT: {filename}\tOLD: {tag} NEW: {content}",
                            color="blue",
                        )
            stream.truncate(0)
            stream.seek(0)
            stream.write(data)

    def _format_json(self, content: str, spaces: int) -> str:
        return json.dumps(json.loads(content), indent=spaces)

    def _count_files_recursively(self) -> None:
        for root, dirs, files in os.walk(self.source):
            self.counter_files += len(files)


#!/usr/bin/env python3

# %% import
from argparse import ArgumentParser
from functools import reduce
from glob import iglob
from itertools import chain, islice
from math import sin, cos
from typing import List

from pyspark.sql import SparkSession, DataFrame
from pyspark.sql.functions import udf, array, size

from dltools import (in_degree, in_milli_meter, in_electron_volt, in_gauss, Hit, SpkHits,
                     uniform_electric_field, none_field, electron_spectrometer)

# %% parser & parameters
parser = ArgumentParser(prog='sp8export', description="""\
Export SP8 analyzed data.""")
parser.add_argument('rootfiles', metavar='filename', type=str, nargs='+',
                    help='resorted ROOT files for the analysis')
parser.add_argument('-o', '--output', metavar='filename', type=str, default='exported.parquet',
                    help='filename where to export analyzed data')
args = parser.parse_args()
targetfiles = args.rootfiles
save_as = args.output

# %% initialize spark builder
builder = (SparkSession
           .builder
           .appName(parser.prog)
           .config("spark.jars.packages", "org.diana-hep:spark-root_2.11:0.1.15")
           .config("spark.cores.max", 11)
           .config("spark.executor.cores", 5)
           .config("spark.executor.memory", "4g")
           )

# %% initialize spectrometers
#
#   ion2nd                 ion1st       electron
# ┌───┐│                      │             │                    │┌───┐
# │   ││                      │             │                    ││   │
# │   ││                      │             │                    ││   │
# │   ││                      │             │                    ││   │
# │ion││                      │             │                    ││ele│
# │mcp││        acc_reg       │   sep_reg   │     draft_reg      ││mcp│
# │   ││                      │             │                    ││   │
# │   ││                      │             │                    ││   │
# │   ││                      │────x────────│                    ││   │
# │   ││                      │             │                    ││   │
# └───┘│                      │             │                    │└───┘
#
#                        uniform magnetic field
#                       symbol x: reaction point
#
c = {
    'draft_reg': 67.4,  # mm
    'elesep_reg': 33,  # mm
    'ionsep_reg': 16.5,  # mm
    'acc_reg': 82.5,  # mm
    'mcpgep_reg': 10,  # mm
    'electron_epoten': -200,  # V
    'ion1st_epoten': -285,  # V
    'ion2nd_epoten': -2000,  # V
    'ionmcp_epoten': -3200,  # V
    'uniform_mfield': 6.843,  # Gauss
}
ion_acc = (
        uniform_electric_field(length=in_milli_meter(c['mcpgep_reg']),
                               electric_field=(in_electron_volt(c['ion2nd_epoten'] - c['ionmcp_epoten'])
                                               / in_milli_meter(c['mcpgep_reg']))) *
        uniform_electric_field(length=in_milli_meter(c['acc_reg']),
                               electric_field=(in_electron_volt(c['ion1st_epoten'] - c['ion2nd_epoten'])
                                               / in_milli_meter(c['acc_reg']))) *
        uniform_electric_field(length=in_milli_meter(c['ionsep_reg']),
                               electric_field=(in_electron_volt(c['electron_epoten'] - c['ion1st_epoten'])
                                               / in_milli_meter(c['ionsep_reg'] + c['elesep_reg'])))
)
ele_acc = (
        none_field(length=in_milli_meter(c['draft_reg'])) *
        uniform_electric_field(length=in_milli_meter(c['elesep_reg']),
                               electric_field=(in_electron_volt(c['ion1st_epoten'] - c['electron_epoten'])
                                               / in_milli_meter(c['ionsep_reg'] + c['elesep_reg'])))
)
ele_spt = electron_spectrometer(ele_acc, magnetic_filed=in_gauss(c['uniform_mfield']))

# %% spark udfs
@udf(SpkHits)
def combine_hits(tarr: List[float],
                 xarr: List[float],
                 yarr: List[float],
                 flagarr: List[float],  # todo: nullable
                 nhits: int,  # todo: nullable
                 ) -> List[dict]:
    zipped = ({'t': t, 'x': x, 'y': y, 'flag': f} for t, x, y, f in zip(tarr, xarr, yarr, flagarr))
    return list(islice(zipped, nhits))

@udf(SpkHits)
def analyse_ihits(hits: List[dict]) -> List[dict]:
    hasgoodflag = ({'t': h['t'] - -101.590,
                    'x': 1.12 * (h['x'] - 0.7719),
                    'y': 1.12 * (h['y'] - -1.99585),
                    } for h in hits if not 14 < h['flag'])
    notdead = [h for h in hasgoodflag if 0 < h['t'] < 18000]
    if len(notdead) < 3:
        return []
    if ((3500 < notdead[0]['t'] < 9750) and
        (3500 < notdead[1]['t'] < 9750) and
        (3500 < notdead[2]['t'] < 9750)):
        return notdead
    return []

@udf(SpkHits)
def analyse_ehits(hits: List[dict]) -> List[dict]:
    th = in_degree(-30)
    hasgoodflag = ({'t': h['t'] - -160.322,
                    'x': 1.03840 * (cos(th)*h['x'] - sin(th)*h['y'] - 0),
                    'y': 1.05967 * (sin(th)*h['x'] + cos(th)*h['y'] - 0.082456),
                    'as': {},
                    } for h in hits if not 14 < h['flag'])
    notdead = [h for h in hasgoodflag if 0 < h['t'] < 60]
    [h['as'].update(e=ele_spt(Hit.in_experimental_units(t=h['t'], x=h['x'], y=h['y']))
                      .to_experimental_units())
     for h in notdead if 20 < h['t'] < 40]
    return notdead

# %% connect to spark master & read root files
with builder.getOrCreate() as spark:
    globbed = (iglob(f) for f in targetfiles)
    filenames = sorted(set(chain.from_iterable(globbed)))
    loaded = (spark.read.format("org.dianahep.sparkroot").load(f) for f in filenames)
    df = reduce(DataFrame.union, loaded)

    # %% restructure data
    imhits = sum(1 for c in df.columns if c.startswith('IonT'))
    emhits = sum(1 for c in df.columns if c.startswith('ElecT'))
    restructured = (
        df
            .withColumn('itarr', array(*['IonT{}'.format(i) for i in range(imhits)]))
            .withColumn('ixarr', array(*['IonX{}'.format(i) for i in range(imhits)]))
            .withColumn('iyarr', array(*['IonY{}'.format(i) for i in range(imhits)]))
            .withColumn('iflagarr', array(*['IonFlag{}'.format(i) for i in range(imhits)]))
            .withColumnRenamed('IonNum', 'inhits')
            .withColumn('etarr', array(*['ElecT{}'.format(i) for i in range(emhits)]))
            .withColumn('exarr', array(*['ElecX{}'.format(i) for i in range(emhits)]))
            .withColumn('eyarr', array(*['ElecY{}'.format(i) for i in range(emhits)]))
            .withColumn('eflagarr', array(*['ElecFlag{}'.format(i) for i in range(emhits)]))
            .withColumnRenamed('ElecNum', 'enhits')
            .select(combine_hits('itarr', 'ixarr', 'iyarr', 'iflagarr', 'inhits').alias('ihits'),
                    combine_hits('etarr', 'exarr', 'eyarr', 'eflagarr', 'enhits').alias('ehits'))
    )

    # %% analyse hits & export them
    analyzed = (restructured
                .withColumn('ihits', analyse_ihits('ihits'))
                .filter(0 < size('ihits'))
                .withColumn('ehits', analyse_ehits('ehits'))
                .filter(0 < size('ehits'))
                )
    (analyzed
     .write
     .option("maxRecordsPerFile", 10000)  # less than 10 MB assuming a record of 1 KB,
     .parquet(save_as)
     )


# -*- coding: utf-8 -*-
"""
Created on Tue Feb 22 17:13:45 2022

@author: Dr. Rakesh Moulick
"""
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 10, 0.1)
y = np.sin(x)
z = np.cos(x)

plt.figure(1)
plt.plot(x,y,'o-',x,z,'^-')
plt.xlabel('x')
plt.ylabel('y and z')
plt.legend(('sine','cosine'),loc=0)
plt.grid(True)

plt.savefig('test_1.png',format='png',dpi=300)
plt.show()


# -*- coding: utf-8 -*-

import inspect
import os
import sys
import shutil
import tempfile
import unittest
from unittest import mock
from unittest.mock import patch

current_path = os.path.abspath(inspect.getsourcefile(lambda: 0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]
sys.path.insert(0, parent_dir)
from tools import Tools

INFO_JSON_CONTENT = "{" + \
                    "\"id\": \"PluginId\"," + \
                    "\"name\": \"PluginName\"" + \
                    "}"

class TestTools(unittest.TestCase):
    test_dir = None
    tools = None

    def setUp(self):
        self.test_dir = tempfile.mkdtemp()
        self.tools = Tools()

    def tearDown(self):
        shutil.rmtree(self.test_dir)

    def test_parse_args_simple_help(self):
        argv = ['script_path', '--help']
        result = self.tools.parse_args(argv)
        self.assertIsNone(result)

    def test_parse_args_help_with_too_much_args(self):
        argv = ['script_path', '--help', 'test']
        result = self.tools.parse_args(argv)
        self.assertIsNone(result)

    def test_parse_args_too_much_args(self):
        argv = ['script_path', 'first', 'second']
        result = self.tools.parse_args(argv)
        self.assertIsNone(result)

    def test_parse_args_with_plugin_name(self):
        argv = ['script_path', 'myPlugin']
        result = self.tools.parse_args(argv)
        self.assertEqual(result, 'myPlugin')

    @patch('os.path.exists')
    def test_is_plugin_dir_good(self, mock_exists):
        mock_exists.return_value = True
        self.assertTrue(self.tools.is_plugin_dir('.'))

    @patch('os.path.exists')
    def test_is_plugin_dir_bad(self, mock_exists):
        mock_exists.return_value = False
        self.assertFalse(self.tools.is_plugin_dir('.'))

    @patch('builtins.open', new_callable=mock.mock_open,
           read_data=INFO_JSON_CONTENT)
    def test_get_plugin_data_good_data(self, mock_file):
        result = self.tools.get_plugin_data(
            self.test_dir + os.sep + 'PluginIdPath')
        self.assertEqual(result, [self.test_dir + os.sep + 'PluginIdPath',
                                  'PluginId'])

    @patch('builtins.open', new_callable=mock.mock_open,
           read_data="")
    def test_get_plugin_data_no_data(self, mock_file):
        result = self.tools.get_plugin_data('PluginIdPath')
        self.assertIsNone(result)

    def test_get_plugins_in_dir_with_one(self):
        # Création de fichiers temporaires
        plugin_dir = self.test_dir + os.sep + 'plugin_dir'
        os.mkdir(self.test_dir + os.sep + 'useless_dir')
        os.mkdir(self.test_dir + os.sep + 'plugin_dir')
        os.mkdir(self.test_dir + os.sep + 'another_useless_dir')
        os.mkdir(plugin_dir + os.sep + 'plugin_info')
        with open(os.path.join(plugin_dir, 'plugin_info',
                               'info.json'), 'w') as info_file:
            info_file.write(INFO_JSON_CONTENT)
        result = self.tools.get_plugins_in_dir(self.test_dir)
        self.assertEqual(result, [[plugin_dir, 'PluginId']])

    def test_get_plugins_in_dir_with_no_one(self):
        # Création de fichiers temporaires
        os.mkdir(self.test_dir + os.sep + 'useless_dir')
        result = self.tools.get_plugins_in_dir(self.test_dir)
        self.assertEqual(result, [])


from abc import ABC
class Polygon(ABC):
	def __init__(self, numberOfSides):
		self.numberOfSides = numberOfSides

class Triangle(Polygon):
	def triPerimeter(self, side1L, side2L, side3L):
		outerEdge = side1L + side2L + side3L
		return(outerEdge)
	def triAarea(self, base, height):
		theInside = base * height / 2
		return(theInside)

class Quadrilateral(Polygon):
	def quadPerimeter(self, side1L, side2L, side3L, side4L):
		outerEdge = side1L + side2L + side3L + side4L
		return(outerEdge)
	def quadArea(self, length, width):
		theInside = length * width
		return(theInside)

bob = Triangle(3)
bobsPerim = bob.triPerimeter(15,30,19)
print(bobsPerim,"cm")
bobsArea = bob.triArea(30,19)
print(bobsArea,"cm2")

quin = Quadrilateral(4)
quinsPerim = quin.quadPerimeter(15,85,99,10)
print(quinsPerim, "cm")
quinsArea = quin.quadArea(15,99)
print(quinsArea,"cm2")


# Define a function for testing game mechanics
def test_game_mechanics(game_state):
    # Test for bugs or glitches
    if bug_detected:
        debug_bug()
        fix_bug()

    # Gather feedback from testers
    feedback = gather_feedback()

    # Identify any imbalances in game mechanics
    if game_state.difficulty > feedback.difficulty:
        adjust_difficulty()

    if game_state.player_progression < feedback.player_progression:
        adjust_progression()

    if game_state.enemy_AI > feedback.enemy_AI:
        adjust_AI()

    # Refine game mechanics based on feedback and testing
    refine_game_mechanics(game_state, feedback)

    # Continue testing and refining until game is polished
    while game_state.quality != "polished":
        continue_testing(game_state)
        refine_game_mechanics(game_state, feedback)


import evdev
from evdev import UInput, InputDevice

mouse = InputDevice('/dev/input/event16')
keybd = '/dev/input/event5'

ui1 = UInput.from_device(mouse, keybd, name='keyboard-mouse-device')
ui1.capabilities(verbose=True).keys()

ui2 = UInput.from_device('/dev/input/event6', name='touchpad-device')
ui2.capabilities(verbose=True).keys()

print(evdev.list_devices())

devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
for device in devices:
    print(device.path, device.name, device.info, device.phys, device.capabilities())


import random
stages = ['''
  +---+
  |   |
  O   |
 /|\  |
 / \  |
      |
=========
''', '''
  +---+
  |   |
  O   |
 /|\  |
 /    |
      |
=========
''', '''
  +---+
  |   |
  O   |
 /|\  |
      |
      |
=========
''', '''
  +---+
  |   |
  O   |
 /|   |
      |
      |
=========''', '''
  +---+
  |   |
  O   |
  |   |
      |
      |
=========
''', '''
  +---+
  |   |
  O   |
      |
      |
      |
=========
''', '''
  +---+
  |   |
      |
      |
      |
      |
=========
''']
word_list=['penguien','whale','tuna']
chosen_word=random.choice(word_list)
print(f"Hint: chosen word is {chosen_word}")
display=[]
for letter in range(len(chosen_word)):
    display+='_'
lives=6
end_of_game=False
while not end_of_game:
    guess = input("Guess a letter: ").lower()

    for position in range(len(chosen_word)):
        holds_char = chosen_word[position]
        if holds_char == guess:
            display[position] = holds_char
    if guess not in chosen_word:
        lives -= 1
        if lives == 0:
            end_of_game = True
            print('You lose!')
    print(f"{' '.join(display)}")#*******Important ##here they converted the list into string using syntax:- ' '.join(list)*********.
    if "_" not in display:
        end_of_game = True
        print("You win.")
    print(stages[lives])


import numpy as np
from queue import Queue
import logging
import networkx as nx
from graphviz import Digraph
from eg_mcts.algorithm.mol_node import MolNode
from eg_mcts.algorithm.reaction_node import ReactionNode
from eg_mcts.algorithm.syn_route import SynRoute

class SearchTree:
    def __init__(self, target_mol, building_blocks, value_fn, zero_known_value=True):
        self.target_mol = target_mol
        # building_blocks
        self.building_blocks = building_blocks
        # Experience Guidance Network
        self.value_fn = value_fn
        self.zero_known_value = zero_known_value
        self.mol_nodes = []
        self.reaction_nodes = []
        self.root = self._add_mol_node(target_mol, None)
        self.succ = target_mol in building_blocks

        self.expand_model_call = 0
        self.value_model_call = 0
        if self.succ:
            logging.info('Synthesis route found: target in building blocks')

    def _add_mol_node(self, mol, parent):
        # already in building blocks
        is_known = mol in self.building_blocks

        mol_node = MolNode(
            mol=mol,
            parent=parent,
            is_known=is_known,
            zero_known_value=self.zero_known_value
        )
        self.mol_nodes.append(mol_node)
        mol_node.id = len(self.mol_nodes)

        return mol_node

    def _add_reaction_and_mol_nodes(self, pro, mols, parent, template, init_value, ancestors=[]):
        assert pro >= 0
        # repeat : ignored
        for mol in mols:
            if mol in ancestors:
                return None

        reaction_node = ReactionNode(parent, pro, template, init_value)
        succe = True
        for mol in mols:
            node = self._add_mol_node(mol, reaction_node)

            succe = succe & node.succ
        # all mol are successful
        if succe:
            reaction_node.set_success()
        self.reaction_nodes.append(reaction_node)
        reaction_node.id = len(self.reaction_nodes)

        return reaction_node

    # expand phase
    def expand(self, mol_node, reactant_lists, pros, templates):
        assert not mol_node.is_known and not mol_node.children
        if pros is None:

            # there is no decomposition action: mol node failed -> -inf
            mol_node.value = np.NINF
            # already expanded
            mol_node.open = False
            return
        else :
            #  mol node has some decomposition actions
            assert mol_node.open
            ancestors = mol_node.get_ancestors()
            succe = False
            for i in range(len(pros)):
                # experience guidance network
                init_value = self.value_fn(mol_node.mol, templates[i])
                self.value_model_call += 1
                node = self._add_reaction_and_mol_nodes(pros[i], reactant_lists[i], mol_node, templates[i], init_value, ancestors)

                if node != None:
                    succe = succe|node.succ

            # all are invalid actions : mol node fails -> -inf and open = false: has been expanded
            if len(mol_node.children) == 0:
                mol_node.value = np.NINF
                mol_node.open = False
                return
            # there is a successful action
            if succe:
                # then  mol node is successful  (or node)
                mol_node.succ = True
                mol_node.value = 10.0
            else:
                # mol node value = max child.Q
                valid_children = mol_node.children_list()
                valid_children_Q = [valid_child.Q_value for valid_child in valid_children]
                max_child_Q = np.max(valid_children_Q)

                mol_node.value = max_child_Q
            # has been expanded
            mol_node.open = False
            return

    # update phase
    def update(self, mol_node):

        current_mol_node = mol_node
        current_R_node = None
        while 1:
            if current_mol_node == self.root:
                if current_mol_node.succ ==  True:

                    self.succ = True
                    break
                else:
                    break
            # update its parent reaction_node and its grandparent mol_node
            # mol node has no actions
            if current_mol_node.v_self() == np.NINF:
                # reaction node( and node) if one of its children fails then it fails
                current_R_node = current_mol_node.parent
                current_R_node.set_invaild()
                current_mol_node = current_R_node.parent
                # check if reaction node' parent fail or not
                valid_children = current_mol_node.children_list()

                if valid_children is None:
                    current_mol_node.value = np.NINF
                else :
                    # last_R_Q = current_R_node.Q_value
                    old_Vm = current_mol_node.value
                    # all valid reactions
                    valid_children_Q = [valid_child.Q_value for valid_child in valid_children]
                    valid_child_number = len(valid_children_Q)
                    child_number = len(current_mol_node.children)
                    max_child_Q = np.max(valid_children_Q)
                    # new_Vm = last_R_Q * 0.05 + max_child_Q * 0.95
                    # new_Vm = valid_child_number/child_number*max_child_Q
                    # new_Vm = max_child_Q
                    if max_child_Q == old_Vm:
                        # no more update upwards, update stop
                        break
                    else :
                        current_mol_node.value = max_child_Q
            # mol node not failed
            else :
                # update its parent reaction_node
                current_R_node = current_mol_node.parent
                current_R_node.update_Q()

                current_mol_node = current_R_node.parent
                valid_children = current_mol_node.children_list()
                # check if there is a successful reaction
                succe = False
                for child in valid_children:
                    if child.succ == True:
                        succe = True
                        break
                if succe :
                    current_mol_node.value = 10.0
                    current_mol_node.succ = True
                    continue
                # last_R_Q = current_R_node.Q_value
                old_Vm = current_mol_node.value
                valid_children_Q = [valid_child.Q_value for valid_child in valid_children]
                max_child_Q = np.max(valid_children_Q)
                # new_Vm = last_R_Q*0.05+max_child_Q*0.95
                # valid_child_number = len(valid_children_Q)
                # child_number = len(current_mol_node.children)
                # new_Vm = valid_child_number / child_number * max_child_Q
                if max_child_Q == old_Vm:
                    # no more update
                    break
                else:
                    current_mol_node.value = max_child_Q
        return self.succ

    # get the synthetic experience
    def get_tree_Qvalue(self):
        experience = []
        for reaction_node in self.reaction_nodes:
            # valid but not succ and updata count<3 and Q>0  not collected
            if reaction_node.count < 3 and reaction_node.valid == True and reaction_node.succ == False and reaction_node.Q_value > 0.0:
                continue
            mol = reaction_node.parent.mol
            template = reaction_node.template
            Q_value = reaction_node.Q_value
            # succ = reaction_node.succ
            # childs = reaction_node.children
            # child_list = [(child.value, child.succ, child.open) for child in childs]
            # experience( (m,T),Q_value)
            experience.append((mol, template, Q_value))
        return experience

    def get_solution_route(self,iterations):
        if not self.succ:
            return None

        syn_route = SynRoute(
            target_mol=self.root.mol,
        )

        mol_queue = Queue()
        mol_queue.put(self.root)
        while not mol_queue.empty():
            mol = mol_queue.get()
            if mol.is_known:
                syn_route.set_value(mol.mol, mol.value)
                continue

            reaction_nodes = mol.children_list()

            reaction_succ = [reaction_node.succ for reaction_node in reaction_nodes]
            best_reaction = reaction_nodes[np.argmax(reaction_succ)]

            assert best_reaction.succ == True

            reactants = []
            for reactant in best_reaction.children:
                mol_queue.put(reactant)
                reactants.append(reactant.mol)

            syn_route.add_reaction(
                mol=mol.mol,
                value=mol.value,
                template=best_reaction.template,
                prob = best_reaction.pro,
                Q0 = best_reaction.value,
                reactants=reactants,
            )

        return syn_route

    # from <https://github.com/binghong-ml/retro_star/>
    def viz_search_tree(self, viz_file):
        G = Digraph('G', filename=viz_file)
        G.attr(rankdir='LR')
        G.attr('node', shape='box')
        G.format = 'pdf'

        node_queue = Queue()
        node_queue.put((self.root, None))
        while not node_queue.empty():
            node, parent = node_queue.get()

            color = 'lightgrey'
            if hasattr(node, 'mol'):
                shape = 'box'
            else:
                shape = 'rarrow'

            if node.succ:
                color = 'red'
                if hasattr(node, 'mol') and node.is_known:
                    color = 'lightyellow'
                print(color)
            G.node(node.serialize(), shape=shape, color=color, style='filled')

            label = ''
            if hasattr(parent, 'mol'):
                label = '%.3f' % node.Q_value
                # label = 'pro:%.3f  Q:%,3f'%(node.pro,node.Q_value)

            if parent is not None:
                G.edge(parent.serialize(), node.serialize(), label=label)

            if node.children is not None:
                for c in node.children:
                    node_queue.put((c, node))

        G.render()


import cv2
import numpy as np
import time
from twilio.rest import Client
import authKeys

start = time.time()
client = Client(authKeys.account_sid,authKeys.auth_token)

Cascade = cv2.CascadeClassifier("haarCascade_FrontalFace_default.xml")
cap = cv2.VideoCapture(2)
c=0
z=0
t=0

while True:
    ret, frames= cap.read()
    gray = cv2.cvtColor(frames, cv2.COLOR_BGR2GRAY)

    faces = Cascade.detectMultiScale(gray,1.4,5)

    for (x,y,w,h) in faces:
        cv2.rectangle(frames,(x,y),(x+w,y+h),(0,255,0),5)
        t=t+1

    cv2.imshow("Frame",frames)

    if(time.time()-start>z*60): # Update time, 'z' is an integer. z*60 = 60s ,120s ,180s... To change the update time, change the numeric multiplier of 'z' (ie,60)

        z=z+1
        if(t>c):
            message = client.messages.create(
            body="Attention, there's someone detected in the vicinity of your security cameras. Updated Every minute", # Alert Message
            from_= authKeys.twilio_num,
            to= authKeys.target_num
        )
            print(message.sid)
            c=t

    if cv2.waitKey(1) == ord("q"):
        break
cap.release()
cv2.destroyAllWindows()


# -*- coding: utf-8 -*-
"""
Created on Thu May 23 10:23:26 2019

@author: Lenovo
"""
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import style
style.use('fivethirtyeight')
from sklearn.tree import DecisionTreeClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_validate
import scipy.stats as sps
import pandas as pd
from sklearn.tree import DecisionTreeClassifier # Import Decision Tree Classifier
from sklearn.model_selection import train_test_split # Import train_test_split function
from sklearn import metrics #Import scikit-learn metrics module for accuracy calculation

def train(x,y):
    print("training")

f=open("data.txt", "r")
contents =f.readlines()
#print(contents)
data = []
X = []
y = []
for line in contents:
    data.append(line.rstrip('\n'))

train_data = data[70:]
test_data = data[:30]

print(len(test_data))
print(len(train_data))

train_x = []
train_y = []
test_x = []
test_y = []

for i in test_data:
    data_test = i.split(',')
    x1 = data_test[0].replace('[','')
    test_x.append([float(x1),float(data_test[1]),float(data_test[2]),float(data_test[3])])
    test_y.append([float(data_test[4].rstrip(']').replace(' ',''))])
for i in train_data:
    data_train = i.split(',')
    x2 = data_train[0].replace('[','')
    train_x.append([float(x2),float(data_train[1]),float(data_train[2]),float(data_train[3])])
    train_y.append([float(data_train[4].rstrip(']').replace(' ',''))])

print(test_y)
#print(data)
#train(train_x, train_y)

y = []
z = []
n = []
weight = []
n2 = len(train_x)
for i in train_x:
    y.append(i[0])
    z.append(i[1])
    weight.append(1/n2)
for i in train_y:
    n.append(i[0])
#y = train_x[0]
#z = train_x[1]
#n = train_y

#print(y)
#print(z)
#print(weight)
print("MNN")
print(n)

models = []
alphas = []
# Create Decision Tree classifer object
clf = DecisionTreeClassifier()

# Train Decision Tree Classifer
Evaluation = pd.DataFrame(train_y.copy())
#print(Evaluation['predictions'])
Evaluation['weights'] = weight

for i in range(1):
    model = clf.fit(train_x,train_y, sample_weight=np.array(Evaluation['weights']))
    models.append(model)
    y_pred = model.predict(train_x)

    #y_pred2 = clf.predict(train_x)
    print("Accuracy:",metrics.accuracy_score(train_y, y_pred))
    #print("Accuracy:",metrics.accuracy_score(train_y, y_pred2))

    error = 0
    for i in range(len(y_pred)):
      #  print(y_pred2[i])
     #   print(train_y[i])
        if (y_pred[i] != train_y[i]):
            error += 1
    print("ERREOR")
    print(error)
    print("pred")
    print(y_pred)
    Evaluation['predictions'] = y_pred
    Evaluation['target'] = n
 #   print("rped")
 #   print(Evaluation['predictions'])
    Evaluation['evaluation'] = np.where(Evaluation['predictions'] == Evaluation['target'],1,0)
    print("eval")
    print(Evaluation['evaluation'])
    Evaluation['misclassified'] = np.where(Evaluation['predictions'] != Evaluation['target'],1,0)
    # Calculate the misclassification rate and accuracy
    accuracy = sum(Evaluation['evaluation'])/len(Evaluation['evaluation'])
    misclassification = sum(Evaluation['misclassified'])/len(Evaluation['misclassified'])
    # Caclulate the error
    err = np.sum(Evaluation['weights']*Evaluation['misclassified'])/np.sum(Evaluation['weights'])

    print("erre")
    print(err)
    # Calculate the alpha values
    alpha = np.log((1-err)/err)
    print("alpha")
    alphas.append(alpha)
    print(alpha)
 #   print(Evaluation['misclassified'])
    Evaluation['weights'] *= np.exp(alpha*Evaluation['misclassified'])
    print("WEITH")
    print(Evaluation['weights'])
#fig, ax = plt.subplots()
#ax.scatter(z, y)

#for i, txt in enumerate(n):
   # ax.annotate(txt, (z[i], y[i]))
 #   hold on
#ax.scatter(train_x[0][:], train_x[1][:])


# Calculando números complexos na forma algébrica

import cmath

p_real1 = float(input("Digite a parte real do primeiro número complexo: "))
p_imag1 = float(input("Digite a parte imaginária do primeiro número complexo: "))
z1 = complex(p_real1,p_imag1)
print("Número complexo digitado: ",z1)

p_real2 = float(input("Digite a parte real do segundo número complexo: "))
p_imag2 = float(input("Digite a parte imaginária do segundo número complexo: "))
z2 = complex(p_real2,p_imag2)
print("Número complexo digitado: ",z2)

print(" ")

# Operações

soma = z1 + z2
subtracao = z1 - z2
produto = z1 * z2
divisao = z1 / z2

print("Soma :",soma)
print("Subtração :",subtracao)
print("Multiplicação :",produto)
print("Divisão :",divisao)


from multiprocessing import Process
import threading
import random
import paho.mqtt.client as mqtt
import time
import json
from paho.mqtt import client as mqtt_client
import RPi.GPIO as GPIO

TOKEN_MAP = {
    "SN-001": "Na5tkJmV9FRIUyhnqUEq",
    "SN-003": "soIsnoRIT6n7jsiN3J0B"
}

TIME_SCHEDULE = {
    "SN-001":0,
    "SN-003":0
}

THRESHOLD = 10

DURATION = {
    "SN-001":5,
    "SN-003":5
}

ledPin = 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(ledPin, GPIO.OUT)
GPIO.output(ledPin, False)

def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected success")
    else:
        print(f"Connected fail with code {rc}")
    client.subscribe(topic='v1/devices/me/rpc/request/+', qos=1)

def on_message(client, userdata, msg):
    print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
    json_object = json.loads(msg.payload.decode())
    date_time = int(json_object['params']['date']/1000)
    print(client._client_id.decode())
    TIME_SCHEDULE[client._client_id.decode()] = date_time
    print(type(client._client_id.decode()))

def schedule_action(date_time):
    print(int(time.time()))

def connect_mqtt(device_name):
    client = mqtt.Client(client_id = device_name)
    client.on_connect = on_connect
    client.on_message = on_message
    client.username_pw_set(TOKEN_MAP[device_name])

    client.connect("hustiot.tech", 1883, keepalive=60) # connect sensor to gateway
    try:
        client.loop_forever()
    except KeyboardInterrupt:
        GPIO.cleanup()

class RxScheduleMsg(threading.Thread):
    def __init__(self, device_name):
        threading.Thread.__init__(self)
        self.device_name = device_name

    def run(self):
        print('Starting thread %s.' % self.device_name)
        connect_mqtt(self.device_name)
        print('Finished thread %s.' % self.device_name)

class HandleSchdule(threading.Thread):
    def __init__(self, device_name):
        threading.Thread.__init__(self)
        self.device_name = device_name

    def run(self):
        while True:
            # print(TIME_SCHEDULE[self.device_name])
            cur_time = time.time()
            threshold = DURATION[self.device_name]
            print(threshold)
            if((cur_time - threshold)< TIME_SCHEDULE[self.device_name] < (cur_time + threshold)):
                print(TIME_SCHEDULE[self.device_name])
                GPIO.output(ledPin, True)
                print(f"Do action for `{self.device_name}`")
            time.sleep(1)

def f1():
    thread1 = RxScheduleMsg("SN-001")
    thread2 = RxScheduleMsg("SN-003")
    thread3 = HandleSchdule("SN-001")
    thread4 = HandleSchdule("SN-003")

    thread1.start()
    thread2.start()
    thread3.start()
    thread4.start()

    thread1.join()
    thread2.join()
    thread3.join()
    thread4.join()

    print('Finished.')

if __name__ == '__main__':
    p1 = Process(name='Worker 1', target=f1)
    p1.start()
    p1.join()