import numpy as np

from nn.load_mnist import load_monkey_datasets
from nn.utils import to_categorical
import os
url = os.path.join(os.path.abspath('.'),'nn/monkey_dataset/')
train_set, val_set, test_set = load_monkey_datasets(url)
x_train,val_x,x_test=np.reshape(train_set[0],(-1,3,128,128)).swapaxes(1,3),np.reshape(val_set[0],(-1,3,128,128)).swapaxes(1,3),np.reshape(test_set[0],(-1,3,128,128)).swapaxes(1,3)
y_train,val_y,y_test=to_categorical(train_set[1]),to_categorical(val_set[1]),to_categorical(test_set[1])

print('训练数据集样本数： %d ,标签个数 %d ' % (len(x_train), len(y_train)))
print('测试数据集样本数： %d ,标签个数  %d ' % (len(x_test), len(y_test)))

print(x_train.shape)
print(x_test.shape)

#定义模型架构：
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPool2D
from keras.models import Sequential

model = Sequential()
model.add(Conv2D(filters = 3, kernel_size = (3,3),data_format='channels_first', padding = 'same', activation = 'relu',input_shape = (128, 128, 3)))
model.add(MaxPool2D(pool_size = 2))
model.add(Flatten())
model.add(Dense(64, activation = 'relu'))
model.add(Dense(10, activation = 'softmax'))

model.summary()

#编译模型
model.compile(loss = 'categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

#训练模型
# x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
# x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
# print(x_train.shape)
# print(x_test.shape)
model.fit(x_train, y_train, batch_size=64, epochs = 5, verbose=1, validation_data=(x_test, y_test))

#评估模型
score = model.evaluate(x_test, y_test, verbose=0)
# print(score)
print('Test score:', score[0])
print('Test accuracy:', score[1])


#!/usr/bin/env python

import argparse
import multiprocessing

import jsk_data

def download_data(*args, **kwargs):
    p = multiprocessing.Process(
        target=jsk_data.download_data,
        args=args,
        kwargs=kwargs)
    p.start()

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose', dest='quiet', action='store_false')
    args = parser.parse_args()
    quiet = args.quiet

    PKG = 'jsk_perception'

    download_data(
        pkg_name=PKG,
        path='learning_datasets/kitchen_dataset.tgz',
        url='https://drive.google.com/uc?id=1iBSxX7I0nFDJfYNpFEb1caSQ0nl4EVUa',
        md5='61d6fcda7631fd0a940bc751c8f21031',
        quiet=quiet,
        extract=True,
    )

    download_data(
        pkg_name=PKG,
        path='learning_datasets/human_size_mirror_dataset.tgz',
        url='https://drive.google.com/uc?id=1uImtm0Drv5prFBUzxHxVcRTH-CESXj7d',
        md5='27d0b6937a749d2643f66d378dd2d6d6',
        quiet=quiet,
        extract=True,
    )

if __name__ == '__main__':
    main()


import turtle

from turtle import *
color('black', 'white')

begin_fill()

turtle.home()
turtle.position()

tur = turtle.Turtle()

for j in range(4):
    for i in range(4):
        tur.forward(100)
        tur.left(90)
    tur.left(90)

end_fill()
done()


# load conda env with open3d >=0.17.0

import open3d as o3d
import numpy as np

NUM_POINTS = 2048

hithand_np = np.load('hithand_pc.npy')
hithand_pcd = o3d.geometry.PointCloud()
hithand_pcd.points = o3d.utility.Vector3dVector(hithand_np)

ds_pcd = hithand_pcd.farthest_point_down_sample(NUM_POINTS)

o3d.visualization.draw_geometries([ds_pcd])
o3d.io.write_point_cloud('ds_hithand.pcd',ds_pcd)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This is the Tswana rule-based syllabification algorithm.
"""

__author__ = "Daniel van Niekerk"
__email__ = "dvn.demitasse@gmail.com"

import sys

from syl_sot import SothoSyllabifier, main

class TswanaSyllabifier(SothoSyllabifier):
    def is_valid_CC(self, cluster, consider_foreign=True):
        """ We only explicitly check for Cw
        """
        if cluster[1] == self.phone_w and any(isf(cluster[0]) for isf in [self.is_plosivelike, self.is_fricative, self.is_nasal, self.is_approximant, self.is_trill]):
            #print("CC1:", "/".join(cluster), sep="\t", file=sys.stderr)
            return True
        elif consider_foreign and cluster in self.clusters_foreign_CC_onsets:
            #print("CC5:", "/".join(cluster), sep="\t", file=sys.stderr)
            print("syllabify(): WARNING: foreign onset cluster: '{}'".format("".join(cluster)), file=sys.stderr)
            return True
        return False

if __name__ == "__main__":
    main(TswanaSyllabifier)


import csv
import numpy as np
import matplotlib.pyplot as plt
import cv2
from preprocess import image_preprocess

class DataPreparator:
    """
    This class reads a CSV file and prepares a list of the paths of the images and specifies what augmentations to apply later on
    It does NOT read images or apply transformations. It only generates a list with the required transformations
    This allows the usage of generator when reading images

    Attributes
    ----------
    X_train : list of tuples
        A list of tuples - (image path, should we flip this images, brightness adjust factor)
    y_train : list
        The angles for the each image are stored here. Same indexing as X_train
    """
    X_train = []
    y_train = []
    directory = '/'

    def set_prepend_directory(self, directory):
        """
        Changes what is the directory name we should prepend to the path from the CSV file
        Used when parsing CSV files with relative paths.

        Parameters
        ----------
        directory : string
            The path to append in front
        """
        self.directory = directory + '/'

    def _prepend_path(self, filename):
        return self.directory + '/' + filename

    def _append_to_list(self, path, angle, flip = False, brightness_adjust = 1.0):
        """
        Adds one image to the X/y_train list

        Parameters
        ----------
        path : string
            The path to the image
        angle : float
            Steering angle
        flip : boolean
            Should we flip the image when reading the list
        brightness_adjusts: float
            Brightness adjust factor
        """
        self.X_train.append((self._prepend_path(path), flip, brightness_adjust))
        if flip: #Flipped images angle needs correction
            angle = angle * -1
        self.y_train.append(angle)

    def _append_brightness_adjusts(self, path, angle, flip, brightness_adjusts = [1.0]):
        """
        Specifies what the needed brightness adjusts for a specific image are and appends them to X/y_train

        Parameters
        ----------
        path : string
            The path to the image
        angle : float
            Steering angle
        flip : boolean
            Should we flip the image when reading the list
        brightness_adjusts: list
            List of floats specifying what brightness adjusts to add
        """
        for brightness in brightness_adjusts:
            self._append_to_list(path, angle, flip, brightness)

    def _append_adjusted_images(self, row):
        """
        Specifies what the needed transformations for a specific row are and appends them to X/y_train

        Parameters
        ----------
        row : dict
            A row from the CSV file
        """
        angle = float(row[3])
        ANGLE_ADJUST = 0.25 # How much to adjust angle for left/right camera

        # Add the image from the central camera
        if abs(float(row[3])) > 0.01: #Do not flip images with angle close to 0. This helps balance the data
            self._append_brightness_adjusts(row[0], angle, False)
            self._append_brightness_adjusts(row[0], angle, True)
        else:
            self._append_to_list(row[0], angle)

        # Add images from left/right camera
        self._append_brightness_adjusts(row[1], angle + ANGLE_ADJUST, False)
        self._append_brightness_adjusts(row[2], angle - ANGLE_ADJUST, False)
        # Add images from left/right camera, flipped
        self._append_brightness_adjusts(row[1], angle + ANGLE_ADJUST, True)
        self._append_brightness_adjusts(row[2], angle - ANGLE_ADJUST, True)

    def read_csv(self, directory_name, absolute_path = True):
        """
        Reads a CSV file in the Udacity driving log format
        Goes over each row and adds the information to X_train and y_train

        Parameters
        ----------
        directory_name : string
            The directory where drivinig_log.csv and the images are stored
        absolute_path: boolean
            Should we prepend the directory_name to the paths in the CSV file or are they absolute paths
        """
        if not absolute_path:
            self.set_prepend_directory(directory_name)

        with open(directory_name + '/driving_log.csv', newline='') as csvfile:
            logreader = csv.reader(csvfile, delimiter=',', quotechar='|', skipinitialspace=True)
            for row in logreader:
                self._append_adjusted_images(row)

def save_image_data(paths, labels):
    """
    This functions reads lists in the DataPreparator format, opens an image,
    applies transformations and saves them in numpy binary format

    Parameters
    ----------
    paths : string
        The path to append in front

    """
    # Output data format
    X_train = np.empty([len(paths), 16, 32, 1])
    y_train = np.empty([len(paths)])

    # Go over all images
    for index in range(0, len(paths)):
        image = plt.imread(paths[index][0])

        # Apply the needed transformations
        arr = image_preprocess(image, paths[index][2])
        if (paths[index][1]):
            arr = cv2.flip(arr, 1)

        # Store the data for output, reshaping it from 16X32 to 16X32X1
        X_train[index] = arr.reshape((16, 32, 1))
        y_train[index] = labels[index]

    # Save the data in numpy binary format.
    # This speeds up training because we need to do image parsing only once, not before every training
    np.save("x.data", X_train)
    np.save("y.data", y_train)

if __name__ == '__main__':
    # Open the CSV file and parse it
    data_preparator = DataPreparator()
    data_preparator.read_csv(directory_name = 'udacity', absolute_path=False)

    # Save the image data in numpy binary files
    save_image_data(data_preparator.X_train, data_preparator.y_train)


import csv
import json
from PIL import Image
import os

# legge il file csv e restituisce le righe corrispondenti al img_name e al img_text per ricavare i BB
def get_row_csv(csv_name, img_name, img_text):
    annotation_list = []  # una lista perchè nella stessa immagine ci sono parole ripetute
    with open(csv_name) as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        for riga in csv_reader:
            # print(riga)
            if riga[0][0] == '#':
                riga[0] = riga[0].replace('#', '')  # elimino il cancelletto
            if riga[0] == img_name and riga[9] == img_text:
                annotation_list.append(riga)
        return annotation_list

# ritorna i BB dei caratteri della parola e salva le immagini dei char
def get_crop_img(csv_name, img_name, img_text):
    is_vertical = False  # mi indica se il testo da tagliare è in verticale o orizzontale
    ann_list = get_row_csv(csv_name, img_name, img_text)
    # print(ann_list)
    first_img = ann_list[0]  # se c'è più di un testo uguale, prendo per ora il primo

    im = Image.open(csv_name[:-4] + "/" + first_img[0])  # gli passo il nome dell immagine

    left = int(first_img[1])  # 1.1
    bottom = int(first_img[4])  # 2.2 sarebbe la linea bassa orizzontale
    right = int(first_img[3])  # 2.1
    top = int(first_img[6])  # 3.2 sarebbe la linea alta orizzontale
    if top - bottom > right - left:
        dim_x = top - bottom
        is_vertical = True
    else:
        dim_x = right - left

    os.chdir('../')
    #im1 = im.crop((left, bottom, right, top))  # per vedere il bb della parola
    #im1.show()

    # Opening JSON file
    with open('charLength.json', 'r') as openfile:
        # Reading from json file
        json_object = json.load(openfile)  # è un dizionario

    os.chdir('CSVmarketfiles/')

    # print(json_object)
    somma = 0  # indica la somma dei valori delle lettere che formano il testo
    for letter in img_text:
        somma = somma + json_object[letter]

    charBB = []  # array che andrà a contenere i charBB
    i = 0  # serve per il nome dell immagine
    for letter in img_text:
        crop_dim = json_object[letter] * dim_x / somma
        if is_vertical:
            bottom = top - crop_dim  # vado dall'alto verso il basso
        else:
            right = left + crop_dim
        charBB.append([letter, left, bottom, right, bottom, right, top, left, top])  # scrivo il char e il BB del char

        im1 = im.crop((left, bottom, right, top))
        if is_vertical:
            top = bottom
            im1 = im1.rotate(270)  # ruoto l'immagine
        else:
            left = right

        im1.save('new_img_' + str(i) + letter + img_name)  # salvo l'immagine del carattere
        i += 1

    return charBB

if __name__ == "__main__":
    os.chdir('E-Shop Dataset/CSVmarketfiles/')
    #print(get_crop_img('healthpersonalcare.csv', '0027.jpg', 'ACIDOPHILUS'))
    print(get_crop_img('healthpersonalcare.csv', '0005.jpg', 'HEALTH'))
    print(get_crop_img('grocery.csv', '0017.jpg', 'COINTREAU'))  # bb non rettangolare, risultato non preciso


# https://www.reddit.com/r/dailyprogrammer/comments/aq6gfy/20190213_challenge_375_intermediate_a_card/

from copy import deepcopy

# Flips card at specified index of hand if there's a card present
def flip_card(hand, index):
	hand_copy = deepcopy(hand)

	if hand_copy[index] != 'x':
		hand_copy[index] = str(1 - int(hand_copy[index]))

	return hand_copy

# Remove card at specified index and returns new hand. Reverses move if replace == True
def remove_card(hand, index):
	if hand[index] != '1':
		print('Invalid operation, specified entry is {}'.format(hand[index]))
		return

	hand_copy = deepcopy(hand)
	hand_copy[index] = 'x'

	# Perform flips to the left and right if necessary
	if index-1 >= 0:
		hand_copy = flip_card(hand_copy, index-1)
	if index+1 <= len(hand_copy)-1:
		hand_copy = flip_card(hand_copy, index+1)

	return hand_copy

# Check if the hand is successfully completed, stuck, or still in progress
def check_hand(hand):
	# If all entries are 'x', hand is successfully completed
	if set(hand) == {'x'}:
		return 1

	# If there are no 1s to remove, hand is deemed stuck
	if '1' not in set(hand):
		return -1

	# Otherwise, hand is deemed to be still in progress
	return 0

# From left to right, perform flips until no more can be performed
def play(hand):
	# Check if hand is completed
	hand_status = check_hand(hand)
	if hand_status == 1:
		return []
	elif hand_status == -1:
		return -1

	# Otherwise, make a move and iterate. Get a list of the indexes of hand which have value 1
	valid_moves = [i for i in range(len(hand)) if hand[i] == '1']

	for move in valid_moves:
		move_result = play(remove_card(hand, move))

		if move_result == -1:
			continue
		else:
			return [move] + move_result

	# If none of the valid moves result in success, return -1 to indicate an insolvable hand
	return -1

print('\nBeginning game!')

while True:
	input_str = input('\nEnter a starting hand, or enter "F" to finish\n')

	if input_str.upper() == 'F':
		print('\nThanks for playing!\n')
		break

	input_list = list(input_str)
	game_result = play(input_list)

	if game_result == []:
		print('Boring! Game was trivial. Already solved ...')
	elif game_result == -1:
		print('No solutions!')
	else:
		print('Solution found! Consider the sequence: {}'.format(game_result))


"""
This script removes duplicate blast hits from candidate ILE insertions outside genes.

Required input:
A file with a list of prefixes for each considered genome (one line per prefix).
For each genome:
1. Output from "outsideGenes_symbiodinium.py"
all contained within a directory named with the given {Prefix}.
"""

outDic = {}
inDic = {}
from pathlib import Path
from sequenceAnalyzer import FastAreader
import os

with open('test','r') as f:
    for line in f:
        removeList = []
        outDic = {}
        inDic = {}

        species = line.strip()
        if os.stat('{0}/outsidegenes.fa'.format(species)).st_size > 0:
            myReaderGenome = FastAreader('{0}/outsidegenes.fa'.format(species))
            for header, sequence in myReaderGenome.readFasta():
                outDic[header] = sequence
       	if os.stat('{0}/insidegenes.fa'.format(species)).st_size > 0:

            myReaderGenome = FastAreader('{0}/insidegenes.fa'.format(species))
            for header, sequence in myReaderGenome.readFasta():
                inDic[header] = sequence
        for head1 in outDic:
            for head2 in outDic:
                if head1 != head2:
                    start1 = int(head1.split('_')[-2])
                    stop1 = int(head1.split('_')[-1])

                    start2 = int(head2.split('_')[-2])
                    stop2 = int(head2.split('_')[-1])
                    if (start1 <= start2 and start2 <= stop1) or (start1 <= stop2 and stop2 <= stop1):
                        removeList.append(head2)
        for key in removeList:

            try:
                outDic.pop(key)
            except KeyError:
       	       	pass

       	        #print(key)

        removeList = []
        for head1 in inDic:
            for head2 in inDic:
                if head1 != head2:
                    start1 = int(head1.split('_')[-2])
                    stop1 = int(head1.split('_')[-1])

                    start2 = int(head2.split('_')[-2])
                    stop2 = int(head2.split('_')[-1])
                    if (start1 <= start2 and start2 <= stop1) or (start1 <= stop2 and stop2 <= stop1):
       	       	       	removeList.append(head2)
        for key in removeList:
            try:
                inDic.pop(key)
            except KeyError:
                pass
                #print(key)
        print(species,'\t',len(outDic),'\t',len(inDic))
        with open('{0}/outsideDeduped.fa'.format(species),'w') as f:
            for head in outDic:
                f.write('>{0}\n{1}\n'.format(head,outDic[head]))
       	with open('{0}/insideDeduped.fa'.format(species),'w') as f:
       	    for	head in	inDic:
       	       	f.write('>{0}\n{1}\n'.format(head,inDic[head]))


#!/usr/bin/env python
import argparse
import logging
import sys

from DevTools.Analyzer.utilities import getTestFiles
from AnalysisBase import AnalysisBase
from utilities import ZMASS, deltaPhi, deltaR

from Candidates import *
import KinematicFitter

import sys
import itertools
import operator

import ROOT

logger = logging.getLogger("MuMuTauTauAnalysis")
logging.basicConfig(level=logging.INFO, stream=sys.stderr,format='%(asctime)s.%(msecs)03d %(levelname)s %(name)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')

def load_events(h,a):
    events = []
    #with open('events_{h}_{a}_ktos.txt'.format(h=h,a=a)) as f:
    with open('h{h}a{a}_Events_in_Kyle_Not_Devin.txt'.format(h=h,a=a)) as f:
        for l in f.readlines():
            events += [l.strip()]
    return events

doPacked = False

class MuMuTauTauAnalysis(AnalysisBase):
    '''
    MuMuTauTau analysis
    '''

    def __init__(self,**kwargs):
        outputFileName = kwargs.pop('outputFileName','muMuTauTauTree.root')
        outputTreeName = kwargs.pop('outputTreeName','MuMuTauTauTree')
        super(MuMuTauTauAnalysis, self).__init__(outputFileName=outputFileName,outputTreeName=outputTreeName,**kwargs)

        self._kinfit = None

        # setup cut tree
        self.cutTree.add(self.metFilter,'metFilter')
        self.cutTree.add(self.trigger,'trigger')

        # open a file of events
        self.events = []
        if 'SUSYGluGluToHToAA_AToMuMu_AToTauTau' in self.fileNames[0]:
            for h in [125,300,750]:
                if 'M-{h}_'.format(h=h) not in self.fileNames[0] and h!=125: continue
                for a in ['3p6',4,5,6,7,8,9,10,11,12,13,14,15,17,19,21]:
                    if 'M-{a}_'.format(a=a) not in self.fileNames[0]: continue
                    try:
                        self.events = load_events(h,a)
                    except:
                        logging.warning('failed to load events {h} {a}'.format(h=h,a=a))

        # setup analysis tree

        # event counts
        self.tree.add(self.getGenChannel, 'genChannel', ['C',5])
        self.tree.add(lambda cands: self.numJets(cands['cleanJets'],'isLoose',20), 'numJetsLoose20', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJets'],'isTight',20), 'numJetsTight20', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJets'],'passCSVv2L',20), 'numBjetsLoose20', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJets'],'passCSVv2M',20), 'numBjetsMedium20', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJets'],'passCSVv2T',20), 'numBjetsTight20', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJetsDR08'],'isLoose',20), 'numJetsLoose20DR08', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJetsDR08'],'isTight',20), 'numJetsTight20DR08', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJetsDR08'],'passCSVv2L',20), 'numBjetsLoose20DR08', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJetsDR08'],'passCSVv2M',20), 'numBjetsMedium20DR08', 'I')
        self.tree.add(lambda cands: self.numJets(cands['cleanJetsDR08'],'passCSVv2T',20), 'numBjetsTight20DR08', 'I')
        self.tree.add(lambda cands: len(self.getCands(self.electrons,self.passLoose)), 'numLooseElectrons', 'I')
        self.tree.add(lambda cands: len(self.getCands(self.electrons,self.passTight)), 'numTightElectrons', 'I')
        self.tree.add(lambda cands: len(self.getCands(self.muons,self.passLoose)), 'numLooseMuons', 'I')
        self.tree.add(lambda cands: len(self.getCands(self.muons,self.passTight)), 'numTightMuons', 'I')
        self.tree.add(lambda cands: len(self.getCands(self.taus,self.passLoose)), 'numLooseTaus', 'I')
        self.tree.add(lambda cands: len(self.getCands(self.taus,self.passTight)), 'numTightTaus', 'I')

        # trigger
        if self.version=='76X':
            self.tree.add(lambda cands: self.event.IsoMu20Pass(), 'pass_IsoMu20', 'I')
            self.tree.add(lambda cands: self.event.IsoTkMu20Pass(), 'pass_IsoTkMu20', 'I')
        else:
            self.tree.add(lambda cands: self.event.IsoMu24Pass(), 'pass_IsoMu24', 'I')
            self.tree.add(lambda cands: self.event.IsoTkMu24Pass(), 'pass_IsoTkMu24', 'I')
            self.tree.add(lambda cands: self.event.Mu17_Mu8_SameSign_DZPass(), 'pass_Mu17_Mu8_SameSign_DZ', 'I')
            self.tree.add(lambda cands: self.event.Mu20_Mu10_SameSign_DZPass(), 'pass_Mu20_Mu10_SameSign_DZ', 'I')

        self.tree.add(lambda cands: self.triggerEfficiency(cands)[0], 'triggerEfficiency', 'F')
        self.tree.add(lambda cands: self.triggerEfficiency(cands)[1], 'triggerEfficiencyUp', 'F')
        self.tree.add(lambda cands: self.triggerEfficiency(cands)[2], 'triggerEfficiencyDown', 'F')
        self.tree.add(lambda cands: self.triggerEfficiencyMC(cands)[0], 'triggerEfficiencyMC', 'F')
        self.tree.add(lambda cands: self.triggerEfficiencyMC(cands)[1], 'triggerEfficiencyMCUp', 'F')
        self.tree.add(lambda cands: self.triggerEfficiencyMC(cands)[2], 'triggerEfficiencyMCDown', 'F')
        self.tree.add(lambda cands: self.triggerEfficiencyData(cands)[0], 'triggerEfficiencyData', 'F')
        self.tree.add(lambda cands: self.triggerEfficiencyData(cands)[1], 'triggerEfficiencyDataUp', 'F')
        self.tree.add(lambda cands: self.triggerEfficiencyData(cands)[2], 'triggerEfficiencyDataDown', 'F')

        # add mmm
        #self.addComposite('mmm')
        #self.addCompositeMet('mmmmet')
        #self.addComposite('mmt')
        #self.addCompositeMet('mmtmet')

        # h
        self.addGenParticle('gh')
        self.addComposite('h')
        self.tree.add(lambda cands: self.kinfit(cands).getComposite('h').M(), 'h_massKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getFitStatus(), 'kinFitStatus', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).atLowerBound, 'kinFitAtLowerBound', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).atUpperBound, 'kinFitAtUpperBound', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).getFitX(), 'kinFitX', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getFitChi2(), 'kinFitChi2', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getRecoil().Px(), 'kinFitRecoilPx', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getRecoil().Py(), 'kinFitRecoilPy', 'F')
        self.addCompositeMet('hmet')
        self.tree.add(lambda cands: cands['hmet'].Mcat(2,3), 'hmet_mcat', 'F')

        # amm leptons
        self.addCompositeGenParticle('gamm','gam1','gam2')
        self.addDiLepton('amm')
        if doPacked:
            self.addCandidate('ch1')
            self.addComposite('mmch')
        self.tree.add(lambda cands: self.kinfit(cands).getComposite('amm').M(), 'amm_massKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getCompositeStatus('amm'), 'amm_kinFitStatus', 'I')
        self.addCompositeMet('ammmet')
        self.addLepton('am1')
        self.addGenDeltaR('am1','gam1')
        self.addGenParticle('gam1')
        self.addDetailedMuon('am1')
        self.tree.add(lambda cands: self.kinfit(cands).getParticleStatus('m1'),    'am1_kinFitStatus', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m1').Pt(),     'am1_ptKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m1').Eta(),    'am1_etaKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m1').Phi(),    'am1_phiKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m1').Energy(), 'am1_energyKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m1').M(),      'am1_massKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m1').getChi2(),'am1_kinFitChi2', 'F')
        self.addLeptonMet('am1met')
        self.addLepton('am2')
        self.addGenDeltaR('am2','gam2')
        self.addGenParticle('gam2')
        self.addDetailedMuon('am2')
        self.tree.add(lambda cands: self.kinfit(cands).getParticleStatus('m2'),    'am2_kinFitStatus', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m2').Pt(),     'am2_ptKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m2').Eta(),    'am2_etaKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m2').Phi(),    'am2_phiKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m2').Energy(), 'am2_energyKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m2').M(),      'am2_massKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('m2').getChi2(),'am2_kinFitChi2', 'F')
        self.addLeptonMet('am2met')

        # att leptons
        self.addCompositeGenParticle('gatt','gat1','gat2')
        self.addDiLepton('att')
        if doPacked:
            self.addCandidate('ch2')
            self.addComposite('ttch')
        self.tree.add(lambda cands: self.kinfit(cands).getComposite('att').M(), 'att_massKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getCompositeStatus('att'), 'att_kinFitStatus', 'I')
        self.addCompositeMet('attmet')
        self.tree.add(lambda cands: cands['attmet'].Mcat(0,1), 'attmet_mcat', 'F')
        self.addGenParticle('gat1',isTau=True)
        self.addLepton('atm')
        self.addGenDeltaR('atm','gatm')
        self.addDetailedMuon('atm')
        self.tree.add(lambda cands: self.kinfit(cands).getParticleStatus('tm'),    'atm_kinFitStatus', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('tm').Pt(),     'atm_ptKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('tm').Eta(),    'atm_etaKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('tm').Phi(),    'atm_phiKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('tm').Energy(), 'atm_energyKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('tm').M(),      'atm_massKinFit', 'F')
        self.addLeptonMet('atmmet')
        self.addGenParticle('gat2',isTau=True)
        self.addLepton('ath')
        self.addGenDeltaR('ath','gath')
        self.addDetailedTau('ath')
        self.tree.add(lambda cands: self.kinfit(cands).getParticleStatus('th'), 'ath_kinFitStatus', 'I')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('th').Pt(),     'ath_ptKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('th').Eta(),    'ath_etaKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('th').Phi(),    'ath_phiKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('th').Energy(), 'ath_energyKinFit', 'F')
        self.tree.add(lambda cands: self.kinfit(cands).getParticle('th').M(),      'ath_massKinFit', 'F')
        self.addLeptonMet('athmet')
        self.addJet('athjet')

        # met
        self.addMet('met')

        # other event
        self.tree.add(lambda cands: sum([x.pt() for x in cands['cleanJets']]), 'ht', 'F')

    ############################
    ### Additional functions ###
    ############################
    def addDetailedMuon(self,label):
        '''Add detailed  variables'''
        self.addCandVar(label,'matches_IsoMu24','matches_IsoMu24','I')
        self.addCandVar(label,'matches_IsoTkMu24','matches_IsoTkMu24','I')
        super(MuMuTauTauAnalysis,self).addDetailedMuon(label)

    def addGenParticle(self,label,isTau=False):
        self.tree.add(lambda cands: cands[label].pt()     if label in cands else 0, '{0}_pt'.format(label),     'F')
        self.tree.add(lambda cands: cands[label].eta()    if label in cands else 0, '{0}_eta'.format(label),    'F')
        self.tree.add(lambda cands: cands[label].phi()    if label in cands else 0, '{0}_phi'.format(label),    'F')
        self.tree.add(lambda cands: cands[label].energy() if label in cands else 0, '{0}_energy'.format(label), 'F')
        self.tree.add(lambda cands: cands[label].mass()   if label in cands else 0, '{0}_mass'.format(label),   'F')
        self.tree.add(lambda cands: cands[label].charge() if label in cands else 0, '{0}_charge'.format(label), 'F')
        self.tree.add(lambda cands: cands[label].pdgId()  if label in cands else 0, '{0}_pdgId'.format(label),  'I')
        if isTau:
            self.tree.add(lambda cands: self.getGenDecayMode(cands[label])  if label in cands else 0, '{0}_decayMode'.format(label),  'I')

    def addCompositeGenParticle(self,label,d1,d2):
        self.addGenParticle(label)
        self.tree.add(lambda cands: deltaR(cands[d1].eta(),cands[d1].phi(),cands[d2].eta(),cands[d2].phi()) if label in cands else 0, '{0}_deltaR'.format(label), 'F')

    def addGenDeltaR(self,label,gen):
        self.tree.add(lambda cands: deltaR(cands[label].eta(),cands[label].phi(),cands[gen].eta(),cands[gen].phi()) if gen in cands else 9, '{0}_genTruthDeltaR'.format(label), 'F')

    def passMuon(self,cand):
        if cand.pt()<3: return False
        if not cand.isPFMuon(): return False
        if not (cand.isGlobalMuon() or cand.isTrackerMuon()): return False
        if abs(cand.dxy())>=0.2: return False
        if abs(cand.dz())>=0.5: return False
        return True

    def passTau(self,cand):
        if cand.pt()<10: return False
        #if abs(cand.dxy())>=0.2: return False
        if abs(cand.dz())>=0.5: return False
        if not cand.decayModeFinding(): return False
        return True

    def kinfit(self,cands):
        # return fitted constraints
        if self._kinfit: return self._kinfit

        # create constraints
        m1 = cands['am1']
        m2 = cands['am2']
        tm = cands['atm']
        th = cands['ath']
        m1p4 = KinematicFitter.Muon(       'm1', m1.pt(), m1.eta(), m1.phi(), m1.energy())
        m2p4 = KinematicFitter.Muon(       'm2', m2.pt(), m2.eta(), m2.phi(), m2.energy())
        tmp4 = KinematicFitter.MuonTau(    'tm', tm.pt(), tm.eta(), tm.phi(), tm.energy())
        thp4 = KinematicFitter.HadronicTau('th', th.pt(), th.eta(), th.phi(), th.energy(), th.decayMode())
        # add cov of muons/taus with appropriate error on energy
        #unc1 = 0.01 if abs(m1.eta())<0.9 else 0.02
        #unc2 = 0.01 if abs(m2.eta())<0.9 else 0.02
        #if m1.pt()>100: unc1 = 0.05
        #if m2.pt()>100: unc2 = 0.05
        #m1p4.setErrors(unc1*m1p4.E(),0,0)
        #m2p4.setErrors(unc2*m2p4.E(),0,0)

        met = cands['met']
        metp4 = KinematicFitter.MET('met', met.et(), met.phi(), met.cov00(), met.cov01(), met.cov01(), met.cov11())

        kinfit = KinematicFitter.KinematicFitter()
        kinfit.addParticle('m1',m1p4)
        kinfit.addParticle('m2',m2p4)
        kinfit.addParticle('tm',tmp4)
        kinfit.addParticle('th',thp4)
        kinfit.addParticle('met',metp4)

        unc = 0.01
        amm = cands['amm']
        if abs(amm.eta())>1.2: unc = 0.018
        kinfit.addComposite('amm','m1','m2',uncertainty=unc*amm.M())
        kinfit.addComposite('att','tm','th')
        kinfit.addComposite('h','m1','m2','tm','th')

        kinfit.addMassConstraint('amm','att',0)

        if 'gh' in cands:
            gh  = cands['gh']
            gmm = cands['gamm']
            gtt = cands['gatt']
            gm1 = cands['gam1']
            gm2 = cands['gam2']
            gt1 = cands['gat1']
            gt2 = cands['gat2']
            gm1p4 = KinematicFitter.Muon(       'gm1', gm1.pt(), gm1.eta(), gm1.phi(), gm1.energy())
            gm2p4 = KinematicFitter.Muon(       'gm2', gm2.pt(), gm2.eta(), gm2.phi(), gm2.energy())
            gt1p4 = KinematicFitter.Tau(        'gt1', gt1.pt(), gt1.eta(), gt1.phi(), gt1.energy(), -1)
            gt2p4 = KinematicFitter.Tau(        'gt2', gt2.pt(), gt2.eta(), gt2.phi(), gt2.energy(), -1)
            gmmp4 = KinematicFitter.Particle(   'gmm', gmm.pt(), gmm.eta(), gmm.phi(), gmm.energy())
            gttp4 = KinematicFitter.Particle(   'gtt', gtt.pt(), gtt.eta(), gtt.phi(), gtt.energy())
            ghp4  = KinematicFitter.Particle(   'gh',  gh.pt(),  gh.eta(),  gh.phi(),  gh.energy())
            kinfit.addGenParticle('gm1',gm1p4)
            kinfit.addGenParticle('gm2',gm2p4)
            kinfit.addGenParticle('gt1',gt1p4)
            kinfit.addGenParticle('gt2',gt2p4)
            kinfit.addGenParticle('gmm',gmmp4)
            kinfit.addGenParticle('gtt',gttp4)
            kinfit.addGenParticle('gh', ghp4)

        # perform fit with constraints
        kinfit.setMinimizationParticles('th')
        kinfit.fit(useUncertainty=True)

        self._kinfit = kinfit

        return self._kinfit

    ############################
    ### select 4l candidates ###
    ############################
    def selectCandidates(self):
        # reset kinfit
        self._kinfit = None

        candidate = {
            'am1' : None,
            'am1met' : None,
            'am2' : None,
            'am2met' : None,
            'atm' : None,
            'atmmet' : None,
            'ath' : None,
            'athmet' : None,
            'amm' : None,
            'ammmet' : None,
            'att' : None,
            'attmet' : None,
            'mmm' : None,
            'mmmmet' : None,
            'mmt' : None,
            'mmtmet' : None,
            'h' : None,
            'hmet' : None,
            'mmm' : None,
            'mmmmet' : None,
            'met': self.pfmet,
            'athjet': Candidate(None),
            'cleanJets' : [],
            'cleanJetsNoTau' : [],
        }

        # get leptons
        muons = [m for m in self.muons if self.passMuon(m)]
        taus = [t for t in self.taus if self.passTau(t)]
        leps = muons+taus
        if len(muons)<3:
            self.report_failure('fails 3 muon requirement')
            return candidate
        if len(taus)<1:
            self.report_failure('fails 1 tau requirement')
            return candidate

        # get the candidates
        hCand = []
        mmDeltaR = 999
        ttDeltaR = 999
        m1pt = 0
        furthest = 0
        nperms = 0
        nvalid = 0
        for quad in itertools.permutations(leps,4):
            nperms += 1
            # require mmmt
            if not quad[0].__class__.__name__=='Muon': continue
            if not quad[1].__class__.__name__=='Muon': continue
            if not quad[2].__class__.__name__=='Muon': continue
            if not quad[3].__class__.__name__=='Tau': continue
            # trigger match
            matchTrigger = quad[0].matches_IsoMu24() or quad[0].matches_IsoTkMu24()
            if not matchTrigger: continue
            furthest = max([1,furthest])
            # charge OS
            if quad[0].charge()==quad[1].charge(): continue
            if quad[2].charge()==quad[3].charge(): continue
            furthest = max([2,furthest])
            nvalid += 1
            # require lead m pt>25
            if quad[0].pt()<25: continue
            furthest = max([3,furthest])
            # make composites
            amm = DiCandidate(quad[0],quad[1])
            att = DiCandidate(quad[2],quad[3])
            # reject events with mu1/mu2 near tm/th
            m1tm = DiCandidate(quad[0],quad[2])
            m1th = DiCandidate(quad[0],quad[3])
            m2tm = DiCandidate(quad[1],quad[2])
            m2th = DiCandidate(quad[1],quad[3])
            if m1tm.deltaR()<0.4: continue
            if m1th.deltaR()<0.8: continue
            if m2tm.deltaR()<0.4: continue
            if m2th.deltaR()<0.8: continue
            furthest = max([4,furthest])
            # choose best
            if not hCand: hCand = quad
            better = True
            if amm.deltaR()>mmDeltaR:
                better = False
            elif amm.deltaR()==mmDeltaR and att.deltaR()>ttDeltaR:
                better = False
            elif amm.deltaR()==mmDeltaR and att.deltaR()==ttDeltaR and quad[0].pt()<m1pt:
                better = False
            if better:
                hCand = quad
                mmDeltaR = amm.deltaR()
                ttDeltaR = att.deltaR()
                m1pt = quad[0].pt()

        #print 'number perms: {}, number valid: {}'.format(nperms,nvalid)

        furthestMap = {
            0: 'topology',
            1: 'trigger',
            2: 'OS',
            3: 'lead pt',
            4: 'deltaR',
        }

        if not hCand:
            self.report_failure('no higgs candidate, furthest {}'.format(furthestMap[furthest]))
            return candidate

        am1 = hCand[0] #if hCand[0].pt()>hCand[1].pt() else hCand[1]
        am2 = hCand[1] #if hCand[0].pt()>hCand[1].pt() else hCand[0]
        atm = hCand[2]
        ath = hCand[3]

        amm = DiCandidate(am1,am2)
        if amm.M()>30:
            self.report_failure('selected higgs amm M>30')
            return candidate
        att = DiCandidate(atm,ath)
        if att.deltaR()>0.8:
            self.report_failure('selected higgs att DR>0.8')
            return candidate

        candidate['am1'] = am1
        candidate['am1met'] = MetCompositeCandidate(self.pfmet,am1)
        candidate['am2'] = am2
        candidate['am2met'] = MetCompositeCandidate(self.pfmet,am2)
        candidate['atm'] = atm
        candidate['atmmet'] = MetCompositeCandidate(self.pfmet,atm)
        candidate['ath'] = ath
        candidate['athmet'] = MetCompositeCandidate(self.pfmet,ath)
        candidate['amm'] = DiCandidate(am1,am2)
        candidate['ammmet'] = MetCompositeCandidate(self.pfmet,am1,am2)
        candidate['att'] = DiCandidate(atm,ath)
        candidate['attmet'] = MetCompositeCandidate(self.pfmet,atm,ath)
        candidate['h'] = CompositeCandidate(am1,am2,atm,ath)
        candidate['hmet'] = MetCompositeCandidate(self.pfmet,am1,am2,atm,ath)
        candidate['mmm'] = CompositeCandidate(am1,am2,atm)
        candidate['mmmmet'] = MetCompositeCandidate(self.pfmet,am1,am2,atm)
        candidate['mmt'] = CompositeCandidate(am1,am2,ath)
        candidate['mmtmet'] = MetCompositeCandidate(self.pfmet,am1,am2,ath)

        if doPacked:
            candidate['ch1'] = Candidate(None)
            candidate['ch2'] = Candidate(None)
            candidate['mmch'] = CompositeCandidate()
            candidate['ttch'] = CompositeCandidate()

            def passPacked(ch):
                if ch.dz()>0.5: return False
                return True

            packed = [p for p in self.packed if passPacked(p)]

            ch1 = None
            ch2 = None
            for ch in packed:
                if not ch1: ch1 = ch
                if not ch2: ch2 = ch
                drmm = deltaR(ch.eta(), ch.phi(), candidate['amm'].eta(), candidate['amm'].phi())
                drm1 = deltaR(ch.eta(), ch.phi(), candidate['am1'].eta(), candidate['am1'].phi())
                drm2 = deltaR(ch.eta(), ch.phi(), candidate['am2'].eta(), candidate['am2'].phi())
                drtt = deltaR(ch.eta(), ch.phi(), candidate['att'].eta(), candidate['att'].phi())
                drtm = deltaR(ch.eta(), ch.phi(), candidate['atm'].eta(), candidate['atm'].phi())
                drth = deltaR(ch.eta(), ch.phi(), candidate['ath'].eta(), candidate['ath'].phi())
                if drmm < deltaR(ch1.eta(), ch1.phi(), candidate['amm'].eta(), candidate['amm'].phi()) and drm1>0.02 and drm2>0.02:
                    ch1 = ch
                if drtt < deltaR(ch2.eta(), ch2.phi(), candidate['att'].eta(), candidate['att'].phi()) and drtm>0.02 and drth>0.02:
                    ch2 = ch
            if ch1:
                candidate['ch1'] = ch1
                candidate['mmch'] = CompositeCandidate(am1,am2,ch1)
            if ch2:
                candidate['ch2'] = ch2
                candidate['ttch'] = CompositeCandidate(atm,ath,ch2)

        # clean the jets
        candidate['cleanJets'] = self.cleanCands(self.jets,[am1,am2,atm,ath],0.4)
        candidate['cleanJetsDR08'] = self.cleanCands(candidate['cleanJets'],[ath],0.8)

        # match jet to tau
        dr = 999
        j = None
        for jet in self.jets:
            jt = DiCandidate(jet,ath)
            if jt.deltaR()<dr:
                j = jet
                dr = jt.deltaR()
        if j:
            candidate['athjet'] = j

        candidate.update(self.getGenCandidates())

        return candidate

    def getGenCandidates(self):
        if 'SUSY' not in self.fileNames[0]:
            return {}
        if 'HToAA_AToMuMu_AToTauTau' not in self.fileNames[0]:
            return {}
        gmuons = [g for g in self.gen if abs(g.pdgId())==13]
        gtaus = [g for g in self.gen if abs(g.pdgId())==15]
        gas = [g for g in self.gen if abs(g.pdgId())==36]
        ghs = [g for g in self.gen if abs(g.pdgId()) in [25,35]]

        gmfromas = [g for g in gmuons if g.mother_1()==36 or g.mother_2()==36]
        gtfromas = [g for g in gtaus if g.mother_1()==36 or g.mother_2()==36]
        lastgh = [g for g in ghs if g.daughter_1()==36 and g.daughter_2()==36]

        if len(lastgh)<1:
            logging.warning('No h cand found')

        h = lastgh[0]
        amm = gas[0] if abs(gas[0].daughter_1())==13 else gas[1]
        att = gas[1] if abs(gas[0].daughter_1())==13 else gas[0]
        am1 = gmfromas[0] if gmfromas[0].pt()>gmfromas[1].pt() else gmfromas[1]
        am2 = gmfromas[1] if gmfromas[0].pt()>gmfromas[1].pt() else gmfromas[0]
        at1 = gtfromas[0] if gtfromas[0].pt()>gtfromas[1].pt() else gtfromas[1]
        at2 = gtfromas[1] if gtfromas[0].pt()>gtfromas[1].pt() else gtfromas[0]

        cands = {
            'gh': h,
            'gamm': amm,
            'gam1': am1,
            'gam2': am2,
            'gatt': att,
            'gat1': at1,
            'gat2': at2,
        }

        if self.getGenDecayMode(at1)==-13 and self.getGenDecayMode(at2)==99:
            cands['gatm'] = at1
            cands['gath'] = at2
        elif self.getGenDecayMode(at2)==-13 and self.getGenDecayMode(at1)==99:
            cands['gatm'] = at2
            cands['gath'] = at1
        else:
            if self.getGenDecayMode(at2)==-13:
                cands['gatm'] = at2
            if self.getGenDecayMode(at2)==99:
                cands['gath'] = at2
            if self.getGenDecayMode(at1)==-13:
                cands['gatm'] = at1
            if self.getGenDecayMode(at1)==99:
                cands['gath'] = at1

        return cands

    def getGenChannel(self,cands):
        if 'gh' not in cands: return 'xxxx'
        dm1 = self.getGenDecayMode(cands['gat1'])
        dm2 = self.getGenDecayMode(cands['gat2'])
        channel = 'mm'
        dmMap = {
            -11: 'e',
            -13: 'm',
            -99: 'x',
            99 : 'h',
            0  : 'x',
        }
        channel += dmMap[dm1]
        channel += dmMap[dm2]

        return channel

    # find tau decay modes
    def getGenDecayMode(self,t):
        gtaus = [g for g in self.gen if abs(g.pdgId())==15]
        # check for decays to taus
        if abs(t.daughter_1())==15 or abs(t.daughter_2())==15:
            # find the last daughter that doesnt decay to a tau
            oktaus = [g for g in gtaus if g.pdgId()==t.pdgId()]
            oktaus = [g for g in oktaus if abs(g.daughter_1())!=15 and abs(g.daughter_2())!=15]
            if len(oktaus)==0: return -99
            return self.getGenDecayMode(oktaus[-1])
        # leptons
        elif abs(t.daughter_1())==13 or abs(t.daughter_2())==13:
            return -13
        elif abs(t.daughter_1())==11 or abs(t.daughter_2())==11:
            return -11
        # hadronic
        # not enough info to determine which dm, only have num particles here
        else:
            return 99

    ###########################
    ### analysis selections ###
    ###########################
    def trigger(self,cands):
        isData = self.event.isData()>0.5
        if self.version=='76X':
            triggerNames = {
                'SingleMuon'     : [
                    'IsoMu20',
                    'IsoTkMu20',
                ],
            }
        else:
            triggerNames = {
                'SingleMuon'     : [
                    'IsoMu24',
                    'IsoTkMu24',
                    #'Mu45_eta2p1',
                    #'Mu50',
                ],
            }
        # the order here defines the heirarchy
        # first dataset, any trigger passes
        # second dataset, if a trigger in the first dataset is found, reject event
        # so forth
        datasets = [
            'SingleMuon',
        ]
        result = self.checkTrigger(*datasets,**triggerNames)
        if not result: self.report_failure('fails trigger')
        return result

    def triggerEfficiencyMC(self,cands):
        return self.triggerEfficiency(cands,mode='mc')

    def triggerEfficiencyData(self,cands):
        return self.triggerEfficiency(cands,mode='data')

    def triggerEfficiency(self,cands,mode='ratio'):
        candList = [cands[c] for c in ['am1']] #,'am2','atm','ath']]
        triggerList = ['IsoMu20_OR_IsoTkMu20'] if self.version=='76X' else ['IsoMu24_OR_IsoTkMu24']
        if mode=='data':
            return self.triggerScales.getDataEfficiency(triggerList,candList,doError=True)
        elif mode=='mc':
            return self.triggerScales.getMCEfficiency(triggerList,candList,doError=True)
        elif mode=='ratio':
            return self.triggerScales.getRatio(triggerList,candList,doError=True)

def parse_command_line(argv):
    parser = argparse.ArgumentParser(description='Run analyzer')

    parser.add_argument('--inputFiles', type=str, nargs='*', default=getTestFiles('SingleMuon' if doPacked else 'haa_125_15',version='80XMuMuTauTau{}'.format('Packed' if doPacked else '')), help='Input files')
    parser.add_argument('--inputFileList', type=str, default='', help='Input file list')
    parser.add_argument('--outputFile', type=str, default='muMuTauTauTree.root', help='Output file')
    parser.add_argument('--shift', type=str, default='', choices=['','ElectronEnUp','ElectronEnDown','MuonEnUp','MuonEnDown','TauEnUp','TauEnDown','JetEnUp','JetEnDown','JetResUp','JetResDown','UnclusteredEnUp','UnclusteredEnDown'], help='Energy shift')

    return parser.parse_args(argv)

def main(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    args = parse_command_line(argv)

    muMuTauTauAnalysis = MuMuTauTauAnalysis(
        outputFileName=args.outputFile,
        outputTreeName='MuMuTauTauTree',
        inputFileNames=args.inputFileList if args.inputFileList else args.inputFiles,
        inputTreeName='MiniTree',
        inputLumiName='LumiTree',
        inputTreeDirectory='miniTree',
        shift = args.shift,
    )

    try:
       muMuTauTauAnalysis.analyze()
       muMuTauTauAnalysis.finish()
    except KeyboardInterrupt:
       muMuTauTauAnalysis.finish()

    return 0

if __name__ == "__main__":
    status = main()
    sys.exit(status)


# coding=utf-8
# @author:walter000
# github: https://github.com/Walter000/tencent_competition

"""
 模型训练结束后，将lightgbm的叶子结点onehot处理，再结合原来的特征重新训练得到最终结果
"""

import numpy as np
import pandas as pd
import os
from scipy import sparse
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import StandardScaler
from sklearn.externals import joblib
import xgboost as xgb
import lightgbm as lgb

predict = pd.read_csv('./datasets/test2.csv')
res = predict[['aid', 'uid']]

train_x = sparse.load_npz('./datasets/train.npz')
test_x = sparse.load_npz('./datasets/test.npz')
train_y = pd.read_csv('./datasets/train_label.csv', names=['label'])  # 直接读入label文件，省去了读取train源文件时间
train_y[train_y == -1] = 0

def LGB_train(train_x, train_y):
    print("LGB test")
    clf = lgb.LGBMClassifier(
        boosting_type='gbdt', num_leaves=10, reg_alpha=0.0, reg_lambda=1,
        max_depth=-1, n_estimators=30, objective='binary', scale_pos_weight=3,
        subsample=0.79, colsample_bytree=0.79, subsample_freq=1,
        learning_rate=0.07, min_child_weight=70, random_state=2018, n_jobs=-1
    )
    clf.fit(train_x, train_y, eval_set=[(train_x, train_y)], eval_metric='auc',early_stopping_rounds=100)
    return clf

def LGB_retrain(train_x, train_y, test_x, res):
    clf = lgb.LGBMClassifier(
        boosting_type='gbdt', num_leaves=90, reg_alpha=0.0, reg_lambda=1,
        max_depth=-1, n_estimators=5000, objective='binary', scale_pos_weight=3,
        subsample=0.79, colsample_bytree=0.79, subsample_freq=1,
        learning_rate=0.07, min_child_weight=70, random_state=2018, n_jobs=-1
    )
    clf.fit(train_x, train_y, eval_set=[(train_x, train_y)], eval_metric='auc', early_stopping_rounds=60)
    res['score'] = clf.predict_proba(test_x)[:, 1]
    res['score'] = res['score'].apply(lambda x: float('%.6f' % x))
    res.to_csv('./submissions/submission_model_add5_combine_leaf_5000_test2.csv', index=False)
    return clf

clf = LGB_train(train_x, train_y)

# get new feature and onehot

print("get new feature")
train_new = clf.apply(train_x)
test_new = clf.apply(test_x)
one = OneHotEncoder()
one.fit(train_new)
train_new = one.transform(train_new)
test_new = one.transform(test_new)

# combine with origin featurees

print("combine new feature")
# train_new = sparse.load_npz('./datasets/model_crossfea_origin_train_fea10_tree30.npz')
# test_new = sparse.load_npz('./datasets/model_crossfea_origin_test_fea10_tree30.npz')
X_train_new = sparse.hstack((train_x, train_new))
X_test_new = sparse.hstack((test_x, test_new))

print("saving new feature")
sparse.save_npz('./datasets/model_fea_add5_fea10_tree30_train_test2.npz', train_new)
sparse.save_npz('./datasets/model_fea_add5_fea10_tree30_test_test2.npz', test_new)
del train_new
del test_new
del train_x
del test_x
import gc
gc.collect()

# retrain and predict

# from sklearn.model_selection import train_test_split

# train_x_real, valid_x_real, train_y_real, valid_y_real = train_test_split(X_train_new, train_y, random_state=2018, test_size=0.3)

print('retrain the model with new feature...')

# X_train_new = sparse.load_npz('./datasets/model_crossfea_train.npz')
# X_test_new = sparse.load_npz('./datasets/model_crossfea_test.npz')
model = LGB_retrain(X_train_new, train_y, X_test_new, res)
joblib.dump(model, './model/model_add5_combine_leaf_5000_test2.model')

model = joblib.load('./datasets/model_combine_leaf_add5_5000.model')

res['score'] = model.predict_proba(X_test_new)[:, 1]
res['score'] = res['score'].apply(lambda x: float('%.6f' % x))
res.to_csv('./datasets/submission_model_combine_leaf_add5_5000_test2.csv', index=False)


from math import isclose
from typing import TYPE_CHECKING

from PyQt5.QtWidgets import QGraphicsPixmapItem
from PyQt5.QtGui import QTransform

from ..utils.expression import Condition, Expression

if TYPE_CHECKING:
    from typing import Optional, Any, Dict
    from PyQt5.QtGui import QPixmap

class ConditionGraphicsPixmapItem(QGraphicsPixmapItem):

    def __init__(self, condition: 'Optional[str]', *args: 'Any',
                 names: 'Optional[Dict[str, Any]]' = None,
                 **kwargs: 'Any') -> None:
        super().__init__(*args, **kwargs)

        self.__condition = Condition(condition) if condition else None
        self.__is_visible = True
        self.__condition_met = False
        self.__names = {} if names is None else names.copy()
        self.__x_offset_func: 'Optional[Expression]' = None
        self.__y_offset_func: 'Optional[Expression]' = None
        self.__x_offset_func_mul: float = 1
        self.__y_offset_func_mul: float = 1
        self.__x_offset_calc: float = 0
        self.__y_offset_calc: float = 0
        self.__angle_offset_func: 'Optional[Expression]' = None
        self.__angle_offset_calc: float = 0

        self.__pixmap = super().pixmap()

        self.evaluate()

    def show(self) -> None:
        self.setVisible(True)

    def hide(self) -> None:
        self.setVisible(False)

    def setVisible(self, visible: bool) -> None:
        super().setVisible(visible and self.__condition_met)
        self.__is_visible = visible

    def isVisible(self) -> bool:
        return self.__is_visible

    def setPixmap(self, pixmap: 'QPixmap') -> None:
        super().setPixmap(pixmap)

        self.__pixmap = pixmap

    def setOffset(self, *args: 'Any') -> None:
        super().setOffset(*args)

        if self.__x_offset_calc != 0 or self.__y_offset_calc != 0:

            offset = super().offset()

            super().setOffset(offset.x() + self.__x_offset_calc,
                              offset.y() + self.__y_offset_calc)

    def setXOffsetExpression(self, expression: 'Optional[str]',
                             multiplier: float = 1) -> None:

        if expression is None:
            self.__x_offset_func = None
        else:
            self.__x_offset_func = Expression(expression, default_value=0)

        self.__x_offset_func_mul = multiplier
        self.evaluate()

    def setYOffsetExpression(self, expression: 'Optional[str]',
                             multiplier: float = 1) -> None:

        if expression is None:
            self.__y_offset_func = None
        else:
            self.__y_offset_func = Expression(expression, default_value=0)

        self.__y_offset_func_mul = multiplier
        self.evaluate()

    def setAngleOffsetExpression(self, expression: 'Optional[str]') -> None:

        if expression is None:
            self.__angle_offset_func = None
        else:
            self.__angle_offset_func = Expression(expression, default_value=0)

        self.evaluate()

    def __updateOffset(self, new_calc_x: float, new_calc_y: float) -> None:

        offset = super().offset()

        super().setOffset(
            offset.x() - self.__x_offset_calc + new_calc_x,
            offset.y() - self.__y_offset_calc + new_calc_y)

        self.__x_offset_calc = new_calc_x
        self.__y_offset_calc = new_calc_y

    def evaluate(self, **kwargs: 'Any') -> None:

        self.__condition_met = self.__condition.evaluate(
            **self.__names, **kwargs) if self.__condition is not None else True

        if self.__is_visible:
            super().setVisible(self.__condition_met)

        offset_modif = False

        new_calc_x = 0
        if self.__x_offset_func is not None:
            new_calc_x = self.__x_offset_func.evaluate(
                **self.__names, **kwargs)*self.__x_offset_func_mul
            offset_modif = True

        new_calc_y = 0
        if self.__y_offset_func is not None:
            new_calc_y = self.__y_offset_func.evaluate(
                **self.__names, **kwargs)*self.__y_offset_func_mul
            offset_modif = True

        if offset_modif:
            self.__updateOffset(new_calc_x, new_calc_y)

        if self.__angle_offset_func is not None:
            new_angle = self.__angle_offset_func.evaluate(**self.__names,
                                                          **kwargs)

            if not isclose(self.__angle_offset_calc, new_angle,
                           rel_tol=0, abs_tol=0.5):

                self.__angle_offset_calc = new_angle
                super().setPixmap(self.__pixmap.transformed(
                    QTransform().rotate(new_angle)))


def partial_sums(*args):
    print(args)
    lst = [0]
    for i in range(len(args)):
        sums = 0
        for j in range(i + 1):
            sums += args[j]
        lst.append(sums)
    return lst

print(*partial_sums(1, 0.5, 0.25, 0.125))


import random

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
def demo_view(request):
    return HttpResponse('Hello world!')
    # return render(request, 'demo.html')

def lotto_view(request):
    game = request.GET.get('game')

    lotto_list = list()
    for index in range(int(game)):

        lotto_number = list()
        for index2 in range(6):
            number = random.randint(1, 45)
            lotto_number.append(number)
        lotto_list.append(lotto_number)

    print(lotto_list)

    if game:
        return render(request, 'lotto.html', {'lotto_list': lotto_list, 'game': game})
    else:
        return render(request, 'lotto.html')


import random

import pygame

from core import config

class Snake:
    def __init__(self):
        random_init_position = random.randrange(10, config.frame_size_x, 10)
        self.position = [100, random_init_position]
        self.body = [[100, random_init_position], [100-10, random_init_position], [100-(2*10), random_init_position]]
        self.score = 0
        self.direction = 'RIGHT'
        self.change_to = self.direction

    def change_direction(self, event):
        # W -> Up; S -> Down; A -> Left; D -> Right
        if event.key == pygame.K_UP or event.key == ord('w'):
            self.change_to = 'UP'
        if event.key == pygame.K_DOWN or event.key == ord('s'):
            self.change_to = 'DOWN'
        if event.key == pygame.K_LEFT or event.key == ord('a'):
            self.change_to = 'LEFT'
        if event.key == pygame.K_RIGHT or event.key == ord('d'):
            self.change_to = 'RIGHT'
        # Esc -> Create event to quit the game
        if event.key == pygame.K_ESCAPE:
            pygame.event.post(pygame.event.Event(pygame.QUIT))

    def move(self, food):
        # Making sure the snake cannot move in the opposite direction instantaneously
        if self.change_to == 'UP' and self.direction != 'DOWN':
            self.direction = 'UP'
        if self.change_to == 'DOWN' and self.direction != 'UP':
            self.direction = 'DOWN'
        if self.change_to == 'LEFT' and self.direction != 'RIGHT':
            self.direction = 'LEFT'
        if self.change_to == 'RIGHT' and self.direction != 'LEFT':
            self.direction = 'RIGHT'

        # Moving the snake
        if self.direction == 'UP':
            self.position[1] -= 10
        if self.direction == 'DOWN':
            self.position[1] += 10
        if self.direction == 'LEFT':
            self.position[0] -= 10
        if self.direction == 'RIGHT':
            self.position[0] += 10

        # Snake body growing mechanism
        self.body.insert(0, list(self.position))
        if self.position[0] == food.position[0] and self.position[1] == food.position[1]:
            self.score += 1
            food.spawn = False
        else:
            self.body.pop()


import unittest

import numpy as np

from mo.front.common.partial_infer.inner_product import caffe_inner_product
from mo.ops.inner_product import InnerProduct
from mo.utils.unittest.graph import build_graph

class TestInnerProductOp(unittest.TestCase):
    # There are tests for InnerProduct.infer in mo/front/common/partial_infer/inner_product_test.py
    nodes_attributes = {
        'node_1': {
            'shape': np.array([227, 5, 2, 1])
        },
        'fc_node': {
        },
        'node_3': {
            'kind': 'data'
        }
    }

    def test_concat_op(self):
        graph = build_graph(self.nodes_attributes,
                            [
                                ('node_1', 'fc_node'),
                                ('fc_node', 'node_3')
                            ])
        fc_node = InnerProduct(graph, self.nodes_attributes['fc_node']).add_node()
        self.assertEqual(fc_node.type, 'FullyConnected')
        self.assertEqual(fc_node.op, 'FullyConnected')
        self.assertEqual(fc_node.infer, caffe_inner_product)


import json

import pytest
import responses

from abusor.client.abusor_api_client import parse_arguments, post_to_api

try:
    from django.urls import reverse
except ImportError:
    # for django < 1.10
    from django.core.urlresolvers import reverse

def test_post_to_api(fake, mock_resp):
    """Verify that the data is posted correctly to the Abusor API."""
    uri = fake.url().rstrip("/")
    token = fake.sha1()
    ip = fake.ipv4()
    subject = fake.sentence()

    # prepare the mock response
    endpoint = uri + reverse("event-list")
    mock_resp.add(responses.POST, endpoint, status=201)

    result = post_to_api(uri, token, ip, subject)
    assert result is None

    # inspect the performed request
    req = mock_resp.calls[-1].request
    assert "Authorization" in req.headers
    assert req.headers["Authorization"] == "Token {}".format(token)

    payload = json.loads(req.body.decode())
    assert "ip_address" in payload
    assert payload["ip_address"] == ip
    assert "subject" in payload
    assert payload["subject"] == subject

def test_post_to_api_error(fake, mock_resp):
    """Verify that an API error is reported correctly."""
    uri = fake.uri().rstrip("/")
    token = None
    ip = fake.ipv4()
    subject = fake.sentence()

    # prepare the mock response
    endpoint = uri + reverse("event-list")
    mock_resp.add(responses.POST, endpoint, body="No unauthorized access", status=401)

    with pytest.raises(SystemExit) as excinfo:
        post_to_api(uri, token, ip, subject)
    assert "[401]" in str(excinfo.value)
    assert "No unauthorized access" in str(excinfo.value)

def test_parse_arguments_subject_escaping(fake, monkeypatch):
    """Verify that subject escaping using double underscore works properly."""
    ip = fake.ipv4()
    subject = fake.sentence()
    assert " " in subject

    escaped_subject = subject.replace(" ", "__")
    assert " " not in escaped_subject

    monkeypatch.setattr(
        "sys.argv", ["progname", "--subject", escaped_subject, "--ip", ip]
    )
    args = parse_arguments()
    assert args.subject == subject

def test_parse_arguments_environment_vars(fake, monkeypatch):
    """Verify that we can set various arguments using environment vars."""
    uri = fake.uri().rstrip("/")
    token = fake.sha1()
    monkeypatch.setenv("ABUSOR_URI", uri)
    monkeypatch.setenv("ABUSOR_TOKEN", token)

    monkeypatch.setattr("sys.argv", ["progname", "-i", "1.2.3.4", "-s", "foo"])
    args = parse_arguments()
    assert args.uri == uri
    assert args.token == token


class CircularNode:
    __slots__ = ("_data", "_next")

    def __init__(self):
        self._data = None
        self._next = self

    def set_data(self, data):
        self._data = data

    def get_data(self):
        return self._data

    def set_next(self, next_ptr):
        self._next = next_ptr

    def get_next(self):
        return self._next

class CircularList:

    def __init__(self):
        self.head = None

    def display(self):
        current = self.head
        result = []
        while current:
            result.append(str(current.get_data()))
            if current.get_next() is self.head:
                break
            current = current.get_next()
        print("->".join(result))

    def add_at_beg(self, data):
        new_node = CircularNode()
        new_node.set_data(data)

        if not self.head:
            self.head = new_node
        else:
            new_node.set_next(self.head)

            current = self.head
            while current.get_next() != self.head:
                current = current.get_next()

            current.set_next(new_node)
            self.head = new_node

    def add_at_end(self, data):
        new_node = CircularNode()
        new_node.set_data(data)
        if not self.head:
            self.head = new_node
        else:
            new_node.set_next(self.head)
            current = self.head

            while current.get_next() is not self.head:
                current = current.get_next()
            current.set_next(new_node)
            self.head = new_node
    def del_at_beg(self):
        if not self.head or (self.head.get_next() is self.head):
            self.head = None
        else:
            current = self.head
            while current.get_next() is not self.head:
                current = current.get_next()
            current.set_next(self.head.get_next())
            self.head = self.head.get_next()

    def del_at_end(self):

        if not self.head or (self.head.get_next() is self.head):
            self.head = None
        else:
            temp = self.head
            current = self.head
            while current.get_next() is not self.head:
                temp = current
                current  = current.get_next()

            temp.set_next(self.head)

if __name__ == "__main__":
    x = CircularList()
    x.add_at_beg(3)
    x.add_at_beg(4)
    x.add_at_beg(5)
    x.add_at_beg(6)
    x.add_at_end(2)
    x.display()
    print("After deleting last node")
    x.del_at_end()
    x.display()


import csv
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data=list(csv.reader(open('spx_prices.csv')))
del(data[0])
data_prices=[]
for line in data:
    line[0],line[1]=int(line[0]),float(line[1])
    data_prices.append(line[1])

mean_tab=[]
var_tab=[]
min_tab=[]
max_tab=[]
best_10=[]
cum_26=[]
cum_28=[]

#Testuje strategie dla signal_window od 2 do 99, best_10 bedzie tabelka na 10 najlepszych wynikow
#patrzac na sredni profit w latach 2004-2014.

for n in range(2,100):

    signal=0
    signal_window=n
    position=0
    max_position=100
    cum_pnl=[0.0]

    for i in range(100,len(data)):
        pnl_daily=0

        if data[i][1]>max(data_prices[i-signal_window:i]):
            signal=1
        elif data[i][1]<min(data_prices[i-signal_window:i]):
                signal=-1

        pnl_daily=50*position*(data[i][1]-data[i-1][1])
        cum_pnl.append(cum_pnl[-1]+pnl_daily)
        position=max_position*signal

    if n==26:
        cum_26=cum_pnl
    if n==28:
        cum_28=cum_pnl

    mean_tab.append(np.mean(cum_pnl))
    var_tab.append(np.var(cum_pnl))
    min_tab.append(round(min(cum_pnl),2))
    max_tab.append(round(max(cum_pnl),2))

    if len(best_10)<10:
        best_10.append(np.mean(cum_pnl))
    else:
        if np.mean(cum_pnl)>min(best_10):
            for i,x in enumerate(best_10):
                if x==min(best_10):
                    del best_10[i]
                    best_10.append(np.mean(cum_pnl))
                    break
#Teraz ogarniam statystyki dla 10 najlepszych wynikow do dataframe'a
col_n=[]
col_mean=[]
col_var=[]
col_min=[]
col_max=[]

for i,x in enumerate(mean_tab):
    for el in best_10:
        if x==el :
            col_n.append(i+2)
            col_mean.append(round(mean_tab[i],2))
            col_var.append(round(var_tab[i]))
            col_min.append(min_tab[i])
            col_max.append(max_tab[i])
            break

#Dodaje sobie jeszcze wiersz ze srednimi wartosciami dla wszystkich parametrow signal_window

col_n.append('avg')
col_mean.append(round(np.mean(mean_tab),2))
col_var.append(round(np.mean(var_tab)))
col_min.append(round(np.mean(min_tab)))
col_max.append(round(np.mean(max_tab)))

data={'Mean':col_mean,'Variance':col_var,'Min':col_min, 'Max':col_max}
df=pd.DataFrame(data,index=(col_n),columns=('Mean','Variance','Min','Max'))
print(df)

#Zatem najlepszy wynik strategia osiagnela dla signal_window=26, dla 28 byla najstabilniejsza, wiec sygnal
#generowany dl takiej wartosci byl najpewniejszy. Srednio przynosila strate prawie 670 000.

#Jeszcze widac ze strategia bylaby srednio oplacalna gdyby nie jedna seria spadkow miedzy 1000 a 1500
#dniem z pobranych danych

plt.plot(cum_26)
plt.plot(cum_28)

plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
    File Name:     req
    Author:        Administrator
    Date:          2018/7/20
    Description:
# code is far away from bugs with the god animal protecting
    I love animals. They taste delicious.
              ┏┓      ┏┓
            ┏┛┻━━━┛┻┓
            ┃      ☃       ┃
            ┃  ┳┛  ┗┳  ┃
            ┃      ┻      ┃
            ┗━┓      ┏━┛
                ┃      ┗━━━┓
                ┃  神兽保佑    ┣┓
                ┃  永无BUG！   ┏┛
                ┗┓┓┏━┳┓┏┛
                  ┃┫┫  ┃┫┫
                  ┗┻┛  ┗┻┛
"""
__author__ = 'Administrator'
import requests
session = requests.session()

def get_result(url,data={},header={}):
    result = session.get(url,data=data,headers=header)
    print('url:  %s    ===================================================================================' % url)
    # print(result.status_code,result.text)
   # assert int(result.status_code) < 400
    return result.text,result.status_code

def post_result(url,data={}):
    result = session.post(url,data)
    print('url:  %s    ===================================================================================' % url)
    print(result.status_code, result.text)
    # assert int(result.status_code) < 400
    return result.text

def post_file(url,data,files={}):
    print('url:  %s    ===================================================================================' % url)
    result = session.request('post', url,
            params=None, data=data, headers=None, cookies=None, files=files,
            auth=None, timeout=5, allow_redirects=True, proxies=None,
            hooks=None, stream=None, verify=None, cert=None, json=None)
    print(result.status_code, result.text)
    # assert int(result.status_code) < 400
    return result.text

def get_download(url,data,fn):
    if not fn:
        print("文件名不能为空")
    print('url:  %s    ===================================================================================' % url)
    result = session.get(url,data=data)
    print(result.status_code,'download file %s succeed!')
    if int(result.status_code) < 400:
        ct = result.content
        with open(fn,'wb') as file:
            file.write(ct)

if __name__ == "__main__":
    ret,code = get_result('http://www.360doc.com/content/13/0722/22/998704_301833252.shtml')
    # print(ret)
    txt = ret[ret.find('旧历的'):ret.find('二月七日')+4]
    with open('../data/祥林嫂.txt','w',encoding='utf8') as tx:
        tx.write(txt)


class UnionFind(object):
    def __init__(self, N):
        self.parent = list(range(N))

    def find(self, i):
        if self.parent[i] == i:
            return i
        return self.find(self.parent[i])

    def union(self, i, j):
        i_r = self.find(i)
        j_r = self.find(j)
        self.parent[j_r] = i_r

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if not grid:
            return 0
        row = len(grid)
        col = len(grid[0])
        island = set()
        uf = UnionFind(row*col)
        for x in range(row):
            for y in range(col):
                # all the h/v positions
                for (dx, dy) in [
                    [-1, 0], [0, 1], [1, 0], [0, -1]
                ]:
                    newx, newy = x + dx, y + dy
                    if newx >=0 and newy >= 0 and newx <= row-1 and newy <= col-1 and grid[newx][newy] == "1" and grid[x][y] == "1":
                        uf.union(x*col+y, newx*col+newy)

        for x in range(row):
            for y in range(col):
                if grid[x][y] == "1":
                    island.add(uf.find(x*col+y))
        return len(island)


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import argparse

def load_dateset(dir, rate, size, df_ ):
    if df_ is None:
        df_ = pd.DataFrame()
    f_name = "{f}/exp_rate{t}_size{s}.txt".format(
        f=dir, s=size, t=rate
    )
    df = pd.read_csv(f_name, header=None, names=['lat'])

    df_[f'{dir}: {rate} Mpps: {size} Bytes'] = df['lat']
    #df_[f'{rate} Mpps'] = df['lat']

    return df_

def load_rate(dir, rate, df_, size):
    for dir in dir:
        for x in size:
            df_ = load_dateset(dir, rate, x, df_)
    return df_
def load_rate2(dir, rate, df_, size ):
    for dir in dir:
        for x in size:
            df_ = load_dateset(dir, rate, x, df_)
    return df_

def main(rel, dir, name, size):
    df = pd.DataFrame()
    if rel == 1:
        df = load_rate(dir, 1, df, size)
        #df = load_rate(dir, 10, df, size)
        df = load_rate(dir, 100, df, size)
        df = load_rate(dir, 1000, df, size)
    elif rel == 2:
        df = load_rate(dir, 100, df, size)
        df = load_rate(dir, 1000, df, size)
    elif rel == 3:
        df = load_rate2(dir, 1, df, size)
        #df = load_rate2(dir, 10, df, size)
    elif rel == 4:
        #df = load_rate2(dir, 102, pd.DataFrame(), size)
        df = load_rate2(dir, 1000, df, size)

    print(df)
    if args.kde:
        g = sns.kdeplot(data=df, cumulative=True)
    elif args.cdf:
        g = sns.ecdfplot(data=df)
        g.set(xlabel = 'Latency ($u$s)', ylabel = 'Cumulative Distribution Function')
    elif args.cat:
        g = sns.catplot(data=df)
    elif args.bar:
        sns.catplot(data=df, kind="bar")
    elif args.box:
        sns.boxplot(data=df)
    elif args.his:
        sns.histplot(data=df)
    plt.savefig(f"{name}_{rel}2.pdf")
    plt.show()

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('-kde', help='kde plot', action='store_true')
parser.add_argument('-cdf', help='cdf plot (default)', action='store_true')
parser.add_argument('-cat', help='cat plot', action='store_true')
parser.add_argument('-bar', help='bar plot', action='store_true')
parser.add_argument('-box', help='box plot', action='store_true')
parser.add_argument('-his', help='box plot', action='store_true')

args = parser.parse_args()

print(args)
#size = [1024, 512, 256, 128, 64]
size = [123, 351]
#dir1 = ['baseline', 'tree']
#dir2 = ['baseline_e', 'tree_e']

dir1 = ['tree']
dir2 = ['tree_e']
main(1, dir1, 'plot_rat_BE', [123])
main(1, dir1, 'plot_rat_AT', [351])
dir1 = ['baseline']
main(1, dir1, 'plot_rat_BL', [123,351])
#main(2, dir1, 'plot_rat', size)

#size = [9000, 8192, 4096, 2048]
size = [4096]

#main(3, dir2, 'plot_elephant',size)
#main(4, dir2, 'plot_elephant', size)


import time

from selenium import webdriver
from selenium.webdriver import ActionChains

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://www.baidu.com')

# 复杂版
# 初始化 ActionChains:动作链条
action = ActionChains(driver)
# 定位一个元素
elem = driver.find_element('xpath',"//span[@id='s-usersetting-top']")
# click操作
action.click(elem).perform()
time.sleep(5)

# 简单版
# h2 = driver.find_element('xpath','//h2')
# h2.click()