import ezdxf
from ezdxf.math import Vec3
from ezdxf.enums import MTextEntityAlignment

# This is the only way to create MTEXT entities where the "width" attribute
# is missing or equals 0.
# MTEXT entities created by AutoCAD or BricsCAD ALWAYS have a
# "width" attribute > 0.

CONTENT = "This is a long MTEXT line without line wrapping!\\PThe second line."

doc = ezdxf.new(setup=True)
doc.layers.new("MTEXT", dxfattribs={"color": ezdxf.const.RED})
msp = doc.modelspace()
attribs = {
    "char_height": 0.7,
    "style": "OpenSans",
    "layer": "MTEXT",
}

def add_mtext(
    location: Vec3, attachment_point: MTextEntityAlignment, size: float = 2
):
    msp.add_line(location - (size, 0), location + (size, 0))
    msp.add_line(location - (0, size), location + (0, size))
    mtext = msp.add_mtext(CONTENT, attribs)
    mtext.set_location(location, attachment_point=attachment_point)

params = [
    ((0, 0), MTextEntityAlignment.BOTTOM_LEFT),
    ((100, 0), MTextEntityAlignment.BOTTOM_CENTER),
    ((200, 0), MTextEntityAlignment.BOTTOM_RIGHT),
    ((0, 100), MTextEntityAlignment.MIDDLE_LEFT),
    ((100, 100), MTextEntityAlignment.MIDDLE_CENTER),
    ((200, 100), MTextEntityAlignment.MIDDLE_RIGHT),
    ((0, 200), MTextEntityAlignment.TOP_LEFT),
    ((100, 200), MTextEntityAlignment.TOP_CENTER),
    ((200, 200), MTextEntityAlignment.TOP_RIGHT),
]

for location, attachment_point in params:
    add_mtext(Vec3(location), attachment_point)

doc.set_modelspace_vport(300, (100, 100))
doc.saveas("mtext_simple_all_alignments.dxf")


import torch
import numpy as np

from torch.utils.data import Dataset
import cv2
from visdrone_db import VisDroneDataBase

class VisDroneDataset(Dataset):
    def __init__(self, path, device='cpu'):
        self.db = VisDroneDataBase(path)
        self.device= device

    def __getitem__(self, index):
        numpy_img, annotations = self.db[index]
        # w h c -> c w h
        numpy_img = numpy_img.transpose((2, 0, 1))
        numpy_img = np.asarray(numpy_img, dtype=np.float32) / 255
        [bbox, cls_label, info] = annotations
        bbox = np.asarray(bbox, dtype=np.float32)
        numpy_img = torch.from_numpy(numpy_img)
        bbox = torch.from_numpy(bbox)
        cls_label = torch.LongTensor(cls_label)
        target = {"boxes":bbox.to(self.device), "labels":cls_label.to(self.device),
                  "scores": torch.Tensor(info[0]).to(self.device)}
        return numpy_img.to(self.device), target

    def __len__(self):
        return len(self.db)

def collater(data):
    imgs = [s['img'] for s in data]
    annots = [s['annot'] for s in data]
    scales = [s['scale'] for s in data]

    imgs = torch.from_numpy(np.stack(imgs, axis=0))

    max_num_annots = max(annot.shape[0] for annot in annots)

    if max_num_annots > 0:

        annot_padded = torch.ones((len(annots), max_num_annots, 5)) * -1

        for idx, annot in enumerate(annots):
            if annot.shape[0] > 0:
                annot_padded[idx, :annot.shape[0], :] = annot
    else:
        annot_padded = torch.ones((len(annots), 1, 5)) * -1

    imgs = imgs.permute(0, 3, 1, 2)

    return {'img': imgs, 'annot': annot_padded, 'scale': scales}

class Resizer(object):
    """
    Convert ndarrays in sample to Tensors.
    """

    def __init__(self, img_size=512):
        self.img_size = img_size

    def __call__(self, sample):
        image, annots = sample['img'], sample['annot']
        height, width, _ = image.shape
        if height > width:
            scale = self.img_size / height
            resized_height = self.img_size
            resized_width = int(width * scale)
        else:
            scale = self.img_size / width
            resized_height = int(height * scale)
            resized_width = self.img_size

        image = cv2.resize(image, (resized_width, resized_height), interpolation=cv2.INTER_LINEAR)

        new_image = np.zeros((self.img_size, self.img_size, 3))
        new_image[0:resized_height, 0:resized_width] = image

        annots[:, :4] *= scale

        return {'img': torch.from_numpy(new_image).to(torch.float32), 'annot': torch.from_numpy(annots), 'scale': scale}

class Augmenter(object):
    """Convert ndarrays in sample to Tensors."""

    def __call__(self, sample, flip_x=0.5):
        if np.random.rand() < flip_x:
            image, annots = sample['img'], sample['annot']
            image = image[:, ::-1, :]

            rows, cols, channels = image.shape

            x1 = annots[:, 0].copy()
            x2 = annots[:, 2].copy()

            x_tmp = x1.copy()

            annots[:, 0] = cols - x2
            annots[:, 2] = cols - x_tmp

            sample = {'img': image, 'annot': annots}

        return sample

class Normalizer(object):

    def __init__(self, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)):
        self.mean = np.array([[mean]])
        self.std = np.array([[std]])

    def __call__(self, sample):
        image, annots = sample['img'], sample['annot']

        return {'img': ((image.astype(np.float32) - self.mean) / self.std), 'annot': annots}


import numpy as np
import math
from scipy.stats import cauchy
import phyde as hd
import pandas as pd
from itertools import combinations
from typing import NamedTuple

## A class to keep the detailed results
class result_det(NamedTuple):
    """
    A class to hold the result of the global hybrid detection test.

    Example:
    .. code:: py
      result_det(global_pv, sig_res)

    """

    p_value : float
    detailed : None
    __slot__ = ()
    def __repr__(self):
        return f"\np_value: {self.p_value}\n\ndetailed:\n{self.detailed}"

## A class to keep the p-value of the global test
class result_pv(NamedTuple):
    """
    A class to hold the p_value of the global hybrid detection test.

    Example:
    .. code:: py
      result_pv(global_pv)

    """
    p_value : float
    __slot__ = ()
    def __repr__(self):
        return f"\np_value:{self.p_value}"

## A function to get the combinition of species
def spcomb(species_list, sus_species = None):
    """
    A function that takes the list of species (without the outgroup) and the
    list of suspected hybrid species and return all possible individual test
    setup with two parents and a hybrid species.

    Example:
    .. code:: py
      spcomb(['sp1', 'sp2', 'sp3', 'sp4'], ['sp2'])

    """
    if set(sus_species).issubset(species_list):
        unq_species_new = list(set(species_list).difference(sus_species))
    else:
       return f"Error:The provided suspected hybrid/s {sus_species} is/are not in the list of species in the data!"
    comb = []

    for sh in range(len(sus_species)):
        hyb = sus_species[sh]
        nhy = list(set(sus_species).difference([hyb]))
        new_unq_species = unq_species_new + nhy
        com = combinations(new_unq_species,2)
        for item in com:
            c_item = list(item)
            c_item.insert(1,hyb)
            comb.append(c_item)
    return(comb)

## cauchy combination test codes
def cct(pvals, weights = None):
    """
    A function to perform the Cauchy combination test. It takes a list of
    p-values and a list of weights and return the global p-value.

    Example:
    .. code:: py
      import pyghdet as ghd
      ghd.cct([0.01,0.05,0.55, 0.99, 0.02])

    """

    pv_arr = np.array(pvals)

    ## check if there is any non-numeric values in the p-vals
    if not all(type(e) in (int, float) for e in pvals):
        return "Warning: The individual tests produced p-values containing non-numeric character! Failed to test the global null hypothesis"

    ## check if all the p-vals are between 0 and 1

    if sum(pv_arr<0) > 0 or sum(pv_arr>1) > 0:
        return "Warning: All the individual p-values must be between 0 and 1! Failed to test the global null hypothesis"

    ## check if there are p-values that are exactly 0 or 1

    is_zero = sum(pv_arr==0)
    is_one = sum(pv_arr==1)

    if(is_zero>0 and is_one>0):
        return "Error: cannot have both 0 and 1 p-values!"
    elif(is_zero>0):
        print("Warning: there are p-values that are exactly zero")
        return 0
    elif(is_one>0):
        print("Warning: there are p-values that are exactly one")
        return 1

    ## check the weights
    if weights==None:
        weights = [1/len(pvals)]*len(pvals)
    else:
        if len(pvals) != len(weights):
            return "Error: weights and pvlaues should be same length!"
        else:
            w_ar = np.array(weights)
            if sum(w_ar<0)>0:
                return "Error: All the weights must be positive!"
            else:
                weights = [ w/sum(weights) for w in weights]

    ## create two groups for p-values: very small and large

    small_p = []
    small_w = []
    large_p = []
    large_w = []

    i = 0
    for item in pvals:
        if item < 1e-16:
            small_p.append(item)
            small_w.append(weights[i])
            i = i+1
        else:
            large_p.append(item)
            large_w.append(weights[i])

    if(len(small_p)==0):
        cct_stat = []
        j = 0
        for item in large_p:
            cct_stat.append(large_w[j]*math.tan((0.5 - item)*math.pi))
            j = j+1
        cct_stat = sum(cct_stat)
    else:
        cct_small = []
        cct_large = []
        k = 0
        for item in small_p:
            cct_small.append((weights[k]/item)/math.pi)
            k = k+1
        cct_small = sum(cct_small)

        l = 0
        for item in large_p:
            cct_large.append(large_w[l]*math.tan((0.5 - item)*math.pi))
            l = l+1
        cct_large = sum(cct_large)

        cct_stat = cct_small + cct_large

    ## calculate the p-value for the global test

    if(cct_stat>1e+15):
        pval = (1/cct_stat)/math.pi
    else:
        pval = 1 - cauchy.cdf(cct_stat)

    return(float(pval))

## code for MCM test
def mcm(pval):
    """
    A function to perform the MCM test. It takes a list of
    p-values and return the global p-value.

    Example:
    .. code:: py
      import pyghdet as ghd
      ghd.mcm([0.01,0.05,0.55, 0.99, 0.02])

    """
    p_min = min(1,len(pval)*min(pval))
    p_mcm = min(1, 2*min(cct(pval),p_min))
    return p_mcm

## code for CMC test
def cmc(pval):
    """
    A function to perform the CMC test. It takes a list of
    p-values and return the global p-value.

    Example:
    .. code:: py
      import pyghdet as ghd
      ghd.cmc([0.01,0.05,0.55, 0.99, 0.02])

    """
    p_min = min(1,len(pval)*min(pval))
    p_cmc = cct([cct(pval), p_min])
    return p_cmc

## combination test for individuals
def comb_indiv(infile, mapfile, outgroup, nindiv, ntaxa, nsite, sus_hyb = None, alpha = 0.05, remove_amb_site = False):

    """
    Main method for testing the global null hypothesis: there is no hybrid
    individual in the data. It is also possible to provide a set of suspected
    hybrid species

    Arguments
    ---------

        - infile         <string> : name of the DNA sequence data file.
        - mapfile        <string> : name of the taxon map file.
        - outgroup       <string> : name of the outgroup.
        - nindiv            <int> : number of sampled individuals.
        - ntaxa             <int> : number of sampled taxa/populations.
        - nsites            <int> : number of sampled sites.
        - sus_hyb         <string>: list of suspected hybrid species.
        - alpha            <float>: intended level of significance.
        - ignore_amb_sites <flag> : ignore missing/ambiguous sites.

    Example(No suspected hybrid):
    .. code:: py
      import pyghdet as ghd
      res = ghd.comb_indiv("data.txt", "map.txt", "out", 16, 4, 50000)

    Example(with suspected hybrid):
    .. code:: py
      import pyghdet as ghd
      res = ghd.comb_indiv("data.txt", "map.txt", "out", 16, 4, 50000, ['sp1'])
    """

    ## creating hyde data file and reading the map file
    if remove_amb_site:
        dat = hd.HydeData(infile, mapfile, outgroup, nindiv, ntaxa, nsite, True)
    else:
        dat = hd.HydeData(infile, mapfile, outgroup, nindiv, ntaxa, nsite)

    mapf = pd.read_csv(mapfile, delimiter='\t', header=None)

    ## get the name of all the species as list
    species_all = list(mapf.iloc[:, 1])

    ## remove the outgroup from the list of species

    species_all = [ sp for sp in species_all if sp!= outgroup ]

    ## select all the unique species

    unq_species =[]

    for sp in species_all:
        if sp not in unq_species:
            unq_species.append(sp)

    if sus_hyb == None:
        comb = spcomb(unq_species, unq_species)
    else:
        if set(sus_hyb).issubset(unq_species):
            comb = spcomb(unq_species, sus_hyb)
        else:
           return f"Error:The provided suspected hybrid/s {sus_hyb} is/are not in the list of species in the data!"

    p_val=[]
    Z_score=[]
    gamma = []
    parent1=[]
    hybrid=[]
    parent2=[]

    for item in comb:
        p1 = item[0]
        h = item[1]
        p2 = item[2]

        res1 = dat.test_individuals(p1, h, p2)

        for item in res1:
            res_each = res1[item]
            p_val.append(res_each["Pvalue"])
            Z_score.append(res_each["Zscore"])
            gamma.append(res_each["Gamma"])
            parent1.append(p1)
            parent2.append(p2)
            hybrid.append(item)

    result = pd.DataFrame(list(zip(parent1, hybrid, parent2, gamma, Z_score, p_val)),
                          columns=["Parent1", "Hybrid", "Parent2","Gamma","Z_score",
                                   "P_value"])

    sig_res = result[result["P_value"]<alpha]
    sig_res = sig_res[sig_res["Gamma"] <= 1]
    sig_res = sig_res[sig_res["Gamma"]>= 0]

    ## making the p-value ready for cct
    pvs = []

    for p in p_val:
        if p==0:
            pvs.append(1e-17)
        else:
            if p==1:
                pvs.append(0.99)
            else:
                pvs.append(p)

    ## running the mcm test
    global_pv = mcm(pvs)

    ## returning the significant results if global null is rejected
    if global_pv <= alpha:
        return result_det(global_pv, sig_res)
    else:
        return result_pv(global_pv)

## combination test for species
def comb_species(infile, mapfile, outgroup, nindiv, ntaxa, nsite, sus_hyb = None, alpha = 0.05, remove_amb_site = False):

    """
    Main method for testing the global null hypothesis: there is no hybrid
    species in the data. It is also possible to provide a set of suspected
    hybrid species

    Arguments
    ---------

        - infile         <string> : name of the DNA sequence data file.
        - mapfile        <string> : name of the taxon map file.
        - outgroup       <string> : name of the outgroup.
        - nindiv            <int> : number of sampled individuals.
        - ntaxa             <int> : number of sampled taxa/populations.
        - nsites            <int> : number of sampled sites.
        - sus_hyb         <string>: list of suspected hybrid species.
        - alpha            <float>: intended level of significance.
        - ignore_amb_sites <flag> : ignore missing/ambiguous sites.

    Example(No suspected hybrid):
    .. code:: py
      import pyghdet as ghd
      res = ghd.comb_species("data.txt", "map.txt", "out", 16, 4, 50000)

    Example(with suspected hybrid):
    .. code:: py
      import pyghdet as ghd
      res = ghd.comb_species("data.txt", "map.txt", "out", 16, 4, 50000, ['sp1'])
    """

    ## creating hyde data file and reading the map file
    if remove_amb_site:
        dat = hd.HydeData(infile, mapfile, outgroup, nindiv, ntaxa, nsite, True)
    else:
        dat = hd.HydeData(infile, mapfile, outgroup, nindiv, ntaxa, nsite)

    mapf = pd.read_csv(mapfile, delimiter='\t', header=None)

    ## get the name of all the species as list
    species_all = list(mapf.iloc[:, 1])

    ## remove the outgroup from the list of species
    species_all = [ sp for sp in species_all if sp!= outgroup ]

    ## select all the unique species
    unq_species =[]

    for sp in species_all:
        if sp not in unq_species:
            unq_species.append(sp)

    if sus_hyb == None:
        comb = spcomb(unq_species, unq_species)
    else:
        if set(sus_hyb).issubset(unq_species):
            comb = spcomb(unq_species, sus_hyb)
        else:
           return f"Error:The provided suspected hybrid/s {sus_hyb} is/are not in the list of species in the data!"

    p_val=[]
    Z_score=[]
    gamma = []
    parent1=[]
    hybrid=[]
    parent2=[]

    for item in comb:
        p1 = item[0]
        h = item[1]
        p2 = item[2]

        res1 = dat.test_triple(p1, h, p2)
        parent1.append(p1)
        parent2.append(p2)
        hybrid.append(h)
        p_val.append(res1["Pvalue"])
        Z_score.append(res1["Zscore"])
        gamma.append(res1["Gamma"])

    result = pd.DataFrame(list(zip(parent1, hybrid, parent2, gamma, Z_score, p_val)),
                          columns=["Parent1", "Hybrid", "Parent2","Gamma", "Z_score",
                                   "P_value"])

    sig_res = result[result["P_value"]< alpha]

    ## making the p-value ready for cct
    pvs = []

    for p in p_val:
        if p==0:
            pvs.append(1e-17)
        else:
            if p==1:
                pvs.append(0.99)
            else:
                pvs.append(p)

    ## running the mcm test
    global_pv = mcm(pvs)

    ## returning the significant results if global null is rejected

    if global_pv <= alpha:
        return result_det(global_pv, sig_res)
    else:
        return result_pv(global_pv)


#!/usr/bin/env python3

"""Was ich bis dahin nicht wusste..."""

# Potenzen
x = 5**2

# Vergleiche
1 <= x < 3

# List Comprehension
squares = [x** 2 for x in range(11)]
squares = [x** 2 for x in range(11) if x%2 == 0]
# Dict Comprehension
squares = {x: x** 2 for x in range(11)}

# Mengen
squares_set = { 4, 16, 123 }
squares_set = set(squares)

"""Numpy..."""
import numpy as np

# Matrix mit 2 Zeilen und 3 Spalten
a = np.array([[1, 2, 3], [4, 5, 6]])
a = np.arange(6).reshape(2, 3)

a.shape #(2, 3)
a.ndim  #1

# dritte Spalte
a[:,2]

type(a[0,0]) #numpy.int64, implementiert in C

# Matrix Mutliplikation
a.dot(np.array([1,2,3]))

# Loesung linearer Gleichungen
a = np.array([[1,2], [3,4]])
b = np.array([1,2])
x = np.linalg.solve(a, b)

"""OR Tools"""
from ortools.linear_solver import pywraplp

solver = pywraplp.Solver.CreateSolver('GLOP')

x = solver.NumVar(0, solver.infinity(), 'x')
y = solver.NumVar(0, solver.infinity(), 'y')

solver.variables() # [x,y]

# Nebenbedingungen
solver.Add(x + 2 * y <= 14)
solver.Add(3 * x - y >= 0)
solver.Add(x - y <= 2)

# Operator Overloading in Klassen
x.__sub__
x.__mul__

# Zielfunktion
solver.Maximize(3 * x + 3 * y)

# Loesung
status = solver.Solve() # 0 means optimal solved
x.solution_value()
y.solution_value()


import re
import logging
import warnings
import json
from math import sqrt
import numpy as np
from .base import string_types
from .ndarray import NDArray, load
from . import random
from . import registry
from . import ndarray
from . util import is_np_array
from . import numpy as _mx_np  # pylint: disable=reimported

# inherit str for backward compatibility
class InitDesc(str):
    """
    Descriptor for the initialization pattern.

    Parameters
    ----------
    name : str
        Name of variable.
    attrs : dict of str to str
        Attributes of this variable taken from ``Symbol.attr_dict``.
    global_init : Initializer
        Global initializer to fallback to.
    """
    def __new__(cls, name, attrs=None, global_init=None):
        ret = super(InitDesc, cls).__new__(cls, name)
        ret.attrs = attrs or {}
        ret.global_init = global_init
        return ret

class Initializer(object):
    """The base class of an initializer."""
    def __init__(self, **kwargs):
        self._kwargs = kwargs
        self._verbose = False
        self._print_func = None

    def set_verbosity(self, verbose=False, print_func=None):
        """Switch on/off verbose mode

        Parameters
        ----------
        verbose : bool
            switch on/off verbose mode
        print_func : function
            A function that computes statistics of initialized arrays.
            Takes an `NDArray` and returns an `str`. Defaults to mean
            absolute value str((abs(x)/size(x)).asscalar()).
        """
        self._verbose = verbose
        if print_func is None:
            def asum_stat(x):
                """returns |x|/size(x), async execution."""
                return str((ndarray.norm(x)/sqrt(x.size)).asscalar())
            print_func = asum_stat
        self._print_func = print_func
        return self

    def _verbose_print(self, desc, init, arr):
        """Internal verbose print function

        Parameters
        ----------
        desc : InitDesc or str
            name of the array
        init : str
            initializer pattern
        arr : NDArray
            initialized array
        """
        if self._verbose and self._print_func:
            logging.info('Initialized %s as %s: %s', desc, init, self._print_func(arr))

    def dumps(self):
        """Saves the initializer to string

        Returns
        -------
        str
            JSON formatted string that describes the initializer.

        Examples
        --------
        >>> # Create initializer and retrieve its parameters
        ...
        >>> init = mx.init.Normal(0.5)
        >>> init.dumps()
        '["normal", {"sigma": 0.5}]'
        >>> init = mx.init.Xavier(factor_type="in", magnitude=2.34)
        >>> init.dumps()
        '["xavier", {"rnd_type": "uniform", "magnitude": 2.34, "factor_type": "in"}]'
        """
        return json.dumps([self.__class__.__name__.lower(), self._kwargs])

    def __call__(self, desc, arr):
        """Initialize an array

        Parameters
        ----------
        desc : InitDesc
            Initialization pattern descriptor.

        arr : NDArray
            The array to be initialized.
        """
        if not isinstance(desc, InitDesc):
            self._legacy_init(desc, arr)
            return

        if desc.global_init is None:
            desc.global_init = self
        init = desc.attrs.get('__init__', "")

        if init:
            # when calling Variable initializer
            create(init)._init_weight(desc, arr)
            self._verbose_print(desc, init, arr)
        else:
            # register nnvm::FSetInputVariableAttrs in the backend for new patterns
            # don't add new cases here.
            if desc.endswith('weight'):
                self._init_weight(desc, arr)
                self._verbose_print(desc, 'weight', arr)
            elif desc.endswith('bias'):
                self._init_bias(desc, arr)
                self._verbose_print(desc, 'bias', arr)
            elif desc.endswith('gamma'):
                self._init_gamma(desc, arr)
                self._verbose_print(desc, 'gamma', arr)
            elif desc.endswith('beta'):
                self._init_beta(desc, arr)
                self._verbose_print(desc, 'beta', arr)
            elif desc.endswith('min'):
                self._init_zero(desc, arr)
                self._verbose_print(desc, 'min', arr)
            elif desc.endswith('max'):
                self._init_one(desc, arr)
                self._verbose_print(desc, 'max', arr)
            elif desc.endswith('weight_quantize'):
                self._init_quantized_weight(desc, arr)
                self._verbose_print(desc, 'weight_quantize', arr)
            elif desc.endswith('bias_quantize'):
                self._init_quantized_bias(desc, arr)
                self._verbose_print(desc, 'bias_quantize', arr)
            else:
                self._init_default(desc, arr)

    def _legacy_init(self, name, arr):
        """Legacy initialization method.

        Parameters
        ----------
        name : str
            Name of corresponding NDArray.

        arr : NDArray
            NDArray to be initialized.
        """
        warnings.warn(
            "\033[91mCalling initializer with init(str, NDArray) has been deprecated." \
            "please use init(mx.init.InitDesc(...), NDArray) instead.\033[0m",
            DeprecationWarning, stacklevel=3)
        if not isinstance(name, string_types):
            raise TypeError('name must be string')
        if not isinstance(arr, NDArray):
            raise TypeError('arr must be NDArray')
        if name.startswith('upsampling'):
            self._init_bilinear(name, arr)
        elif name.startswith('stn_loc') and name.endswith('weight'):
            self._init_zero(name, arr)
        elif name.startswith('stn_loc') and name.endswith('bias'):
            self._init_loc_bias(name, arr)
        elif name.endswith('bias'):
            self._init_bias(name, arr)
        elif name.endswith('gamma'):
            self._init_gamma(name, arr)
        elif name.endswith('beta'):
            self._init_beta(name, arr)
        elif name.endswith('weight'):
            self._init_weight(name, arr)
        elif name.endswith("moving_mean"):
            self._init_zero(name, arr)
        elif name.endswith("moving_var"):
            self._init_one(name, arr)
        elif name.endswith("moving_inv_var"):
            self._init_zero(name, arr)
        elif name.endswith("moving_avg"):
            self._init_zero(name, arr)
        elif name.endswith('min'):
            self._init_zero(name, arr)
        elif name.endswith('max'):
            self._init_one(name, arr)
        else:
            self._init_default(name, arr)

    def _init_bilinear(self, _, arr):
        weight = np.zeros(np.prod(arr.shape), dtype='float32')
        shape = arr.shape
        f = np.ceil(shape[3] / 2.)
        c = (2 * f - 1 - f % 2) / (2. * f)
        for i in range(np.prod(shape)):
            x = i % shape[3]
            y = (i // shape[3]) % shape[2]
            weight[i] = (1 - abs(x / f - c)) * (1 - abs(y / f - c))
        arr[:] = weight.reshape(shape)

    def _init_loc_bias(self, _, arr):
        shape = arr.shape
        assert(shape[0] == 6)
        arr[:] = np.array([1.0, 0, 0, 0, 1.0, 0])

    def _init_zero(self, _, arr):
        arr[:] = 0.0

    def _init_one(self, _, arr):
        arr[:] = 1.0

    def _init_bias(self, _, arr):
        arr[:] = 0.0

    def _init_quantized_bias(self, _, arr):
        arr[:] = 0

    def _init_gamma(self, _, arr):
        arr[:] = 1.0

    def _init_beta(self, _, arr):
        arr[:] = 0.0

    def _init_weight(self, name, arr):
        """Abstract method to Initialize weight."""
        raise NotImplementedError("Must override it")

    def _init_quantized_weight(self, _, arr):
        _arr = random.randint(-127, 127, dtype='int32').asnumpy()
        arr[:] = np.int8(_arr)

    def _init_default(self, name, _):
        raise ValueError(
            f'Unknown initialization pattern for {name}. ' \
            'Default initialization is now limited to '\
            '"weight", "bias", "gamma" (1.0), and "beta" (0.0).' \
            'Please use mx.sym.Variable(init=mx.init.*) to set initialization pattern')

    def __eq__(self, other):
        if not isinstance(other, Initializer):
            return NotImplemented
        # pylint: disable=unidiomatic-typecheck
        return type(self) is type(other) and self._kwargs == other._kwargs

# pylint: disable=invalid-name
_register = registry.get_register_func(Initializer, 'initializer')
alias = registry.get_alias_func(Initializer, 'initializer')
create = registry.get_create_func(Initializer, 'initializer')
# pylint: enable=invalid-name

def register(klass):
    """Registers a custom initializer.

    Custom initializers can be created by extending `mx.init.Initializer` and implementing the
    required functions like `_init_weight` and `_init_bias`. The created initializer must be
    registered using `mx.init.register` before it can be called by name.

    Parameters
    ----------
    klass : class
        A subclass of `mx.init.Initializer` that needs to be registered as a custom initializer.

    Example
    -------
    >>> # Create and register a custom initializer that
    ... # initializes weights to 0.1 and biases to 1.
    ...
    >>> @mx.init.register
    ... @alias('myinit')
    ... class CustomInit(mx.init.Initializer):
    ...   def __init__(self):
    ...     super(CustomInit, self).__init__()
    ...   def _init_weight(self, _, arr):
    ...     arr[:] = 0.1
    ...   def _init_bias(self, _, arr):
    ...     arr[:] = 1
    ...
    >>> # block is an instance of 'mxnet.gluon.Block'
    ...
    >>> block.initialize(CustomInit())
    """
    return _register(klass)

class Load(object):
    """Initializes variables by loading data from file or dict.

    **Note** Load will drop ``arg:`` or ``aux:`` from name and
    initialize the variables that match with the prefix dropped.

    Parameters
    ----------
    param: str or dict of str->`NDArray`
        Parameter file or dict mapping name to NDArray.
    default_init: Initializer
        Default initializer when name is not found in `param`.
    verbose: bool
        Flag for enabling logging of source when initializing.

    """
    def __init__(self, param, default_init=None, verbose=False):
        if isinstance(param, str):
            param = load(param)
        assert isinstance(param, dict)
        self.param = {}
        for name, arr in param.items():
            if name.startswith('arg:') or name.startswith('aux:'):
                self.param[name[4:]] = arr
            else:
                self.param[name] = arr
        self.default_init = default_init
        self.verbose = verbose

    def __call__(self, name, arr):
        if name in self.param:
            assert arr.shape == self.param[name].shape, \
                f'Parameter {name} cannot be initialized from loading. ' + \
                f'Shape mismatch, target {str(arr.shape)} vs loaded {self.param[name].shape}'
            arr[:] = self.param[name]
            if self.verbose:
                logging.info('Initialized %s by loading', name)
        else:
            assert self.default_init is not None, \
                f"Cannot Initialize {name}. Not found in loaded param " + \
                "and no default Initializer is provided."
            self.default_init(name, arr)
            if self.verbose:
                logging.info('Initialized %s by default', name)

class Mixed(object):
    """Initialize parameters using multiple initializers.

    Parameters
    ----------
    patterns: list of str
        List of regular expressions matching parameter names.
    initializers: list of Initializer
        List of initializers corresponding to `patterns`.

    Example
    -------
    >>> # Given 'block', an instance of 'mxnet.gluon.Block', initialize biases to zero
    ... # and every other parameter to random values with uniform distribution.
    ...
    >>> init = mx.initializer.Mixed(['bias', '.*'], [mx.init.Zero(), mx.init.Uniform(0.1)])
    >>> block.initialize(init)
    >>>
    >>> for dictionary in module.get_params():
    ...     for key in dictionary:
    ...         print(key)
    ...         print(dictionary[key].asnumpy())
    ...
    fullyconnected1_weight
    [[ 0.0097627   0.01856892  0.04303787]]
    fullyconnected1_bias
    [ 0.]

    """
    def __init__(self, patterns, initializers):
        assert len(patterns) == len(initializers)
        self.map = list(zip([re.compile(p) for p in patterns], initializers))

    def __call__(self, name, arr):
        for prog, init in self.map:
            if prog.match(name):
                init(name, arr)
                return
        raise ValueError('Parameter name %s did not match any pattern. Consider' +
                         'add a ".*" pattern at the and with default Initializer.')

@register
@alias("zeros")
class Zero(Initializer):
    """Initializes weights to zero.

    Example
    -------
    >>> # Given 'block', an instance of 'mxnet.gluon.Block', initialize weights to zero.
    ...
    >>> init = mx.initializer.Zero()
    >>> module.initialize(init)
    >>> for dictionary in module.get_params():
    ...     for key in dictionary:
    ...         print(key)
    ...         print(dictionary[key].asnumpy())
    ...
    fullyconnected0_weight
    [[ 0.  0.  0.]]
    """
    def __init__(self):
        super(Zero, self).__init__()

    def _init_weight(self, _, arr):
        arr[:] = 0

@register
@alias("ones")
class One(Initializer):
    """Initializes weights to one.

    Example
    -------
    >>> # Given 'block', an instance of 'mxnet.gluon.Block', initialize weights to one.
    ...
    >>> init = mx.initializer.One()
    >>> module.initialize(init)
    >>> for dictionary in module.get_params():
    ...     for key in dictionary:
    ...         print(key)
    ...         print(dictionary[key].asnumpy())
    ...
    fullyconnected0_weight
    [[ 1.  1.  1.]]
    """
    def __init__(self):
        super(One, self).__init__()

    def _init_weight(self, _, arr):
        arr[:] = 1

@register
class Constant(Initializer):
    """Initializes the weights to a given value.
    The value passed in can be a scalar or a NDarray that matches the shape
    of the parameter to be set.

    Parameters
    ----------
    value : float, NDArray
        Value to set.
    """
    def __init__(self, value):
        super(Constant, self).__init__(value=value)
        self.value = value

    def _init_weight(self, _, arr):
        arr[:] = self.value

    def dumps(self):
        val = self._kwargs['value']
        if not np.isscalar(val):
            self._kwargs['value'] = val.tolist() if isinstance(val, np.ndarray) else val.asnumpy().tolist()
        return json.dumps([self.__class__.__name__.lower(), self._kwargs])

@register
class Uniform(Initializer):
    """Initializes weights with random values uniformly sampled from a given range.

    Parameters
    ----------
    scale : float, optional
        The bound on the range of the generated random values.
        Values are generated from the range [-`scale`, `scale`].
        Default scale is 0.07.

    Example
    -------
    >>> # Given 'block', an instance of 'mxnet.gluon.Block', initialize weights
    >>> # to random values uniformly sampled between -0.1 and 0.1.
    ...
    >>> init = mx.init.Uniform(0.1)
    >>> module.initialize(init)
    >>> for dictionary in module.get_params():
    ...     for key in dictionary:
    ...         print(key)
    ...         print(dictionary[key].asnumpy())
    ...
    fullyconnected0_weight
    [[ 0.01360891 -0.02144304  0.08511933]]
    """
    def __init__(self, scale=0.07):
        super(Uniform, self).__init__(scale=scale)
        self.scale = scale

    def _init_weight(self, _, arr):
        uniform_fn = _mx_np.random.uniform if is_np_array() else random.uniform
        uniform_fn(-self.scale, self.scale, arr.shape, dtype=arr.dtype, out=arr)

@register
class Normal(Initializer):
    """Initializes weights with random values sampled from a normal distribution
    with a mean of zero and standard deviation of `sigma`.

    Parameters
    ----------
    sigma : float, optional
        Standard deviation of the normal distribution.
        Default standard deviation is 0.01.

    Example
    -------
    >>> # Given 'block', an instance of 'mxnet.gluon.Block', initialize weights
    >>> # to random values sampled from a normal distribution.
    ...
    >>> init = mx.init.Normal(0.5)
    >>> module.initialize(init)
    >>> for dictionary in module.get_params():
    ...     for key in dictionary:
    ...         print(key)
    ...         print(dictionary[key].asnumpy())
    ...
    fullyconnected0_weight
    [[-0.3214761  -0.12660924  0.53789419]]
    """
    def __init__(self, sigma=0.01):
        super(Normal, self).__init__(sigma=sigma)
        self.sigma = sigma

    def _init_weight(self, _, arr):
        normal_fn = _mx_np.random.normal if is_np_array() else random.normal
        normal_fn(0, self.sigma, arr.shape, dtype=arr.dtype, out=arr)

@register
class Orthogonal(Initializer):
    """Initialize weight as orthogonal matrix.

    This initializer implements *Exact solutions to the nonlinear dynamics of
    learning in deep linear neural networks*, available at
    https://arxiv.org/abs/1312.6120.

    Parameters
    ----------
    scale : float optional
        Scaling factor of weight.

    rand_type: string optional
        Use "uniform" or "normal" random number to initialize weight.

    """
    def __init__(self, scale=1.414, rand_type="uniform"):
        super(Orthogonal, self).__init__(scale=scale, rand_type=rand_type)
        self.scale = scale
        self.rand_type = rand_type

    def _init_weight(self, _, arr):
        nout = arr.shape[0]
        nin = np.prod(arr.shape[1:])
        if self.rand_type == "uniform":
            tmp = random.uniform(-1.0, 1.0, shape=(nout, nin)).asnumpy()
        elif self.rand_type == "normal":
            tmp = random.normal(0.0, 1.0, shape=(nout, nin)).asnumpy()
        u, _, v = np.linalg.svd(tmp, full_matrices=False) # pylint: disable=invalid-name
        if u.shape == tmp.shape:
            res = u
        else:
            res = v
        res = self.scale * res.reshape(arr.shape)
        arr[:] = res

@register
class Xavier(Initializer):
    """Returns an initializer performing "Xavier" initialization for weights.

    This initializer is designed to keep the scale of gradients roughly the same
    in all layers.

    By default, `rnd_type` is ``'uniform'`` and `factor_type` is ``'avg'``,
    the initializer fills the weights with random numbers in the range
    of :math:`[-c, c]`, where :math:`c = \\sqrt{\\frac{3.}{0.5 * (n_{in} + n_{out})}}`.
    :math:`n_{in}` is the number of neurons feeding into weights, and :math:`n_{out}` is
    the number of neurons the result is fed to.

    If `rnd_type` is ``'uniform'`` and `factor_type` is ``'in'``,
    the :math:`c = \\sqrt{\\frac{3.}{n_{in}}}`.
    Similarly when `factor_type` is ``'out'``, the :math:`c = \\sqrt{\\frac{3.}{n_{out}}}`.

    If `rnd_type` is ``'gaussian'`` and `factor_type` is ``'avg'``,
    the initializer fills the weights with numbers from normal distribution with
    a standard deviation of :math:`\\sqrt{\\frac{3.}{0.5 * (n_{in} + n_{out})}}`.

    Parameters
    ----------
    rnd_type: str, optional
        Random generator type, can be ``'gaussian'`` or ``'uniform'``.

    factor_type: str, optional
        Can be ``'avg'``, ``'in'``, or ``'out'``.

    magnitude: float, optional
        Scale of random number.
    """
    def __init__(self, rnd_type="uniform", factor_type="avg", magnitude=3):
        super(Xavier, self).__init__(rnd_type=rnd_type, factor_type=factor_type,
                                     magnitude=magnitude)
        self.rnd_type = rnd_type
        self.factor_type = factor_type
        self.magnitude = float(magnitude)

    def _init_weight(self, name, arr):
        shape = arr.shape
        hw_scale = 1.
        if len(shape) < 2:
            raise ValueError('Xavier initializer cannot be applied to vector {0}. It requires at'
                             ' least 2D.'.format(name))
        if len(shape) > 2:
            hw_scale = np.prod(shape[2:])
        fan_in, fan_out = shape[1] * hw_scale, shape[0] * hw_scale
        factor = 1.
        if self.factor_type == "avg":
            factor = (fan_in + fan_out) / 2.0
        elif self.factor_type == "in":
            factor = fan_in
        elif self.factor_type == "out":
            factor = fan_out
        else:
            raise ValueError("Incorrect factor type")
        scale = np.sqrt(self.magnitude / factor)
        if self.rnd_type == "uniform":
            uniform_fn = _mx_np.random.uniform if is_np_array() else random.uniform
            uniform_fn(-scale, scale, arr.shape, dtype=arr.dtype, out=arr)
        elif self.rnd_type == "gaussian":
            normal_fn = _mx_np.random.normal if is_np_array() else random.normal
            normal_fn(0, scale, arr.shape, dtype=arr.dtype, out=arr)
        else:
            raise ValueError("Unknown random type")

@register
class MSRAPrelu(Xavier):
    """Initialize the weight according to a MSRA paper.

    This initializer implements *Delving Deep into Rectifiers: Surpassing
    Human-Level Performance on ImageNet Classification*, available at
    https://arxiv.org/abs/1502.01852.

    This initializer is proposed for initialization related to ReLu activation,
    it makes some changes on top of Xavier method.

    Parameters
    ----------
    factor_type: str, optional
        Can be ``'avg'``, ``'in'``, or ``'out'``.

    slope: float, optional
        initial slope of any PReLU (or similar) nonlinearities.
    """
    def __init__(self, factor_type="avg", slope=0.25):
        magnitude = 2. / (1 + slope ** 2)
        super(MSRAPrelu, self).__init__("gaussian", factor_type, magnitude)
        self._kwargs = {'factor_type': factor_type, 'slope': slope}

@register
class Bilinear(Initializer):
    """Initialize weight for upsampling layers."""
    def __init__(self):
        super(Bilinear, self).__init__()

    def _init_weight(self, _, arr):
        weight = np.zeros(np.prod(arr.shape), dtype='float32')
        shape = arr.shape
        f = np.ceil(shape[3] / 2.)
        c = (2 * f - 1 - f % 2) / (2. * f)
        for i in range(np.prod(shape)):
            x = i % shape[3]
            y = (i // shape[3]) % shape[2]
            weight[i] = (1 - abs(x / f - c)) * (1 - abs(y / f - c))
        arr[:] = weight.reshape(shape)

@register
class LSTMBias(Initializer):
    """Initialize all biases of an LSTMCell to 0.0 except for
    the forget gate whose bias is set to custom value.

    Parameters
    ----------
    forget_bias: float, default 1.0
        bias for the forget gate. Jozefowicz et al. 2015 recommends
        setting this to 1.0.
    """
    def __init__(self, forget_bias=1.0):
        super(LSTMBias, self).__init__(forget_bias=forget_bias)
        self.forget_bias = forget_bias

    def _init_weight(self, name, arr):
        arr[:] = 0.0
        # in the case of LSTMCell the forget gate is the second
        # gate of the 4 LSTM gates, we modify the according values.
        num_hidden = int(arr.shape[0] / 4)
        arr[num_hidden:2*num_hidden] = self.forget_bias

@register
class RNNFused(Initializer):
    """Initialize RNN fused parameter with bias part initialized to 0.0 and
    weight initialized with random values uniformly sampled from a given range.

    Parameters
    ----------
    mode : {'gru', 'lstm', 'rnn_relu', 'rnn_tanh'}, required
        the type of RNN to compute
    num_layers : int (non-negative), required
        number of stacked layers
    state_size : int (non-negative), required
        size of the state for each layer
    bidirectional : boolean, optional, default=0
        whether to use bidirectional recurrent layers
    projection_size : int or None, optional, default='None'
        size of project size
    scale : float, optional
        The bound on the range of the generated random values for weights.
        Values are generated from the range [-`scale`, `scale`].
        Default scale is 0.07.
    """
    def __init__(self, mode, num_layers, state_size, bidirectional=False,
                 projection_size=None, i2h_weight_initializer=None,
                 h2h_weight_initializer=None, i2h_bias_initializer=None,
                 h2h_bias_initializer=None, h2r_weight_initializer=None):
        super(RNNFused, self).__init__(mode=mode, num_layers=num_layers,
                                       state_size=state_size,
                                       bidirectional=bidirectional,
                                       projection_size=projection_size,
                                       i2h_weight_initializer=i2h_weight_initializer,
                                       h2h_weight_initializer=h2h_weight_initializer,
                                       i2h_bias_initializer=i2h_bias_initializer,
                                       h2h_bias_initializer=h2h_bias_initializer,
                                       h2r_weight_initializer=h2r_weight_initializer)
        self.gates = {'rnn_relu': 1, 'rnn_tanh': 1, 'lstm': 4, 'gru': 3}[mode]
        self.num_layers = num_layers
        self.num_hidden = state_size
        self.dir = 2 if bidirectional else 1
        self.projection_size = projection_size
        self._i2h_weight_initializer = i2h_weight_initializer
        self._h2h_weight_initializer = h2h_weight_initializer
        self._i2h_bias_initializer = i2h_bias_initializer
        self._h2h_bias_initializer = h2h_bias_initializer
        self._h2r_weight_initializer = h2r_weight_initializer

    # pylint: disable=too-many-nested-blocks
    def _init_weight(self, name, arr):
        arr_len = arr.shape[0]
        size = self.num_hidden * self.dir * self.gates
        if not self.projection_size:
            # second layer size
            size2 = (self.num_hidden * self.dir + self.num_hidden + 2) * size
            input_size = (arr_len - (self.num_layers - 1) * size2) // \
                size - 2 - self.num_hidden
        else:
            # second layer size
            size2 = (self.projection_size * self.dir + self.projection_size + 2) * size
            size_projection = self.projection_size * self.num_hidden * self.num_layers * self.dir
            input_size = (arr_len - size_projection - (self.num_layers - 1) * size2) // \
                size - 2 - self.projection_size
        begin = 0
        if not self.projection_size:
            for param in ['weight', 'bias']:
                for layer_num in range(self.num_layers):
                    for _ in range(self.dir):
                        for connect in ['i2h', 'h2h']:
                            num_inputs = input_size
                            if layer_num != 0:
                                num_inputs = self.num_hidden * self.dir
                            if connect == 'h2h':
                                num_inputs = self.num_hidden
                            shape0 = self.gates * self.num_hidden
                            if param == 'weight':
                                cur_len = shape0 * num_inputs
                            else:
                                cur_len = shape0
                            self._init_util(param, connect, arr[begin:begin+cur_len])
                            begin += cur_len
        else:
            for param in ['weight', 'bias']:
                for layer_num in range(self.num_layers):
                    for _ in range(self.dir):
                        for connect in ['i2h', 'h2h', 'h2r']:
                            if connect != 'h2r' or param != 'bias':
                                if connect == 'h2r':
                                    cur_len = self.projection_size * self.num_hidden
                                else:
                                    num_inputs = input_size
                                    if layer_num != 0:
                                        num_inputs = self.projection_size * self.dir
                                    if connect == 'h2h':
                                        num_inputs = self.projection_size
                                    shape0 = self.gates * self.num_hidden
                                    if param == 'weight':
                                        cur_len = shape0 * num_inputs
                                    else:
                                        cur_len = shape0
                                self._init_util(param, connect, arr[begin:begin+cur_len])
                                begin += cur_len

    def _init_util(self, param, connect, arr):
        name = "_{}_{}_initializer".format(connect, param)
        init = getattr(self, name)
        create(init)(InitDesc(name, {'__init__': init}), arr)

    def set_initializer(self, init):
        self._i2h_weight_initializer = \
            init if not self._i2h_weight_initializer else 'uniform'
        self._h2h_weight_initializer = \
            init if not self._h2h_weight_initializer else 'uniform'
        self._i2h_bias_initializer = \
            init if not self._i2h_bias_initializer else 'zero'
        self._h2h_bias_initializer = \
            init if not self._i2h_bias_initializer else 'zero'
        self._h2r_weight_initializer = \
            init if not self._h2r_weight_initializer else 'uniform'


import pandas as pd
import numpy as np
import sys
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import matplotlib.ticker as mtick

from graph_utils import *
plt.style.use('seaborn-whitegrid')
font0 = FontProperties()

SF_LABEL2R = "SF fused2 Red"
SF_LABEL2 = "SF fused2"
SF_LABEL4 = "SF fused4"
SF_LABEL6 = "SF fused6"
JD_WF2 = "Wavefront fused2"
JD_WF4 = "Wavefront fused4"
JD_LBC2 = "LBC fused2"
JD_LBC4 = "LBC fused4"
JD_DAGP = ""
PARSY = "LBC Non-fused"
SEQ = "Serial Non-fused"

SECs = " (sec)"
ANA = " Analysis"
ITR = " Iters"

NNZ = "A Nonzero"

ITR_MAX = 1020
MAX_VAL = 1e10

fig = plt.figure(figsize=(10, 4))

def geo_mean(iterable):
    a = np.array(iterable)
    return a.prod()**(1.0/len(a))

def plot_scatter_chart_gs( all_data, legend_labels, x_axis_labels, y_axis_label,
                   out_file_name='', y_scale="linear", location=(0,0), colspan=1, legend_need=True):

    if len(all_data) <= 0:
        print("all_data invalid.")
        return -1
    n_groups = len(all_data)
    n_elements = len(all_data[0])
    for l in all_data:
        if len(l) != n_elements:
            print("all_data inconsistent.")
            return -1
    if len(legend_labels) != n_groups or len(x_axis_labels) != n_elements:
        print("legend_labels or x_axis_labels are invalid.")
        return -1

    width = 0.26
    max_y = np.amax(all_data)+2
    if legend_need:
        max_y = 4.75
    ind = (n_groups + 1) * width * np.arange(0,n_elements, (n_elements-1)/2)
    x_label = np.arange(1, n_elements + 1)
    y_label = np.arange(0, max_y, 5)
    font_axis = font0.copy()
    metric_label = 'solve time(sec)'

    #ax1 = fig.add_subplot(location)
    ax1 = plt.subplot2grid((1, 3), location, colspan=colspan)
    ax1.set_ylim([0, max_y])
    #ax1.set_xlim(1e6,1e8)
    ax1.set_yscale(y_scale)
    for i in range(n_groups):
        ax1.scatter(x_label, all_data[i, :], s=10, color=colors[i*3],
                    marker=markers[i], label=legend_labels[i])

    font_axis.set_weight(weights[6])  # ['light', 'normal', 'medium', 'semibold', 'bold', 'heavy', 'black']
    if legend_need:
        ax1.set_ylabel(y_axis_label, fontsize=14)
    if location == (0, 1):
        ax1.set_xlabel("Number of NNZ", fontsize=14)
    #ax1.set_yticklabels()
    #ax1.set_yticks(y_label, minor=False)
    #ax1.set_yticks([0, 0.4, 0.8, 1.2, 1.6, 2, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 100 ])
    #ax1.axhline(y=[1], linestyle='--', color='gray')  #

    ax1.set_xticks(ind)
    x_axis_label_reduced = np.zeros(3)
    x_axis_label_reduced = np.array([x_axis_labels[0], x_axis_labels[int(n_elements/2)],  x_axis_labels[n_elements-1]])
    ax1.set_xticklabels(x_axis_label_reduced, fontsize=14)
    #ax1.xaxis.set_minor_formatter(mtick.FormatStrFormatter('%.2e'))
    #ax1.ticklabel_format(axis="x", style="sci")

    ax1.grid(False)
    ax1.tick_params(axis='y', which='both', left='off', right='off', color='w')
    ax1.tick_params(axis='x', which='both', left='off', right='off', color='w')
    ax1.spines['right'].set_visible(False)
    ax1.spines['top'].set_visible(False)
    ax1.spines['left'].set_color('k')
    ax1.spines['bottom'].set_color('k')
#    plt.yticks(Fontsize=14)
    plt.xlim(-width)
    plt.xticks(rotation=45)
    if legend_need:
        handles, labels = ax1.get_legend_handles_labels()
        fig.legend(handles, labels, fontsize=14, ncol=3, loc='upper center', frameon=True, borderaxespad=1)

        #plt.legend(loc='upper left', fontsize=14, ncol=1,  frameon=True)
    #plt.show()
    dir_out = os.path.dirname(out_file_name)
    base_out = os.path.basename(out_file_name).split('.')[0]
    if os.path.exists(dir_out):
        fig.savefig(join(dir_out, base_out + ".pdf"), bbox_inches='tight')
    else:
        print("Output path is not valid, saving current dir!")
        fig.savefig(base_out + ".pdf", bbox_inches='tight')

def plot_gs_scatter(input_path1):
    lib_file = False
    global_dict["ERRORS"] = preprocess_text_file(input_path1)
    in_csv_log = pd.read_csv(input_path1)
    in_csv_log = in_csv_log.sort_values(by=[NNZ])
    lab1 = c_labs[Index.MAT_NAME.value]  # key label
    #sorted_dic = preprocess_csv(in_csv_log, lab1, lab1)

    NZ = in_csv_log[NNZ].values
    MATRICES = in_csv_log["Matrix Name"].values

    ### Baseline
    SERIAL = in_csv_log[SEQ + SECs].values

    ### ParSy
    PARSYV = in_csv_log[PARSY + SECs].values
    PARSYVI = in_csv_log[PARSY + ITR].values

    ### SF Fused
    SF2R = in_csv_log[SF_LABEL2R + SECs].values
    SF2 = in_csv_log[SF_LABEL2 + SECs].values
    SF4 = in_csv_log[SF_LABEL4 + SECs].values
    SF6 = in_csv_log[SF_LABEL6 + SECs].values

    SF2RI = in_csv_log[SF_LABEL2R + ITR].values
    SF2I = in_csv_log[SF_LABEL2 + ITR].values
    SF4I = in_csv_log[SF_LABEL4 + ITR].values
    SF6I = in_csv_log[SF_LABEL6 + ITR].values

    n = len(SF2)
    BEST_SF = np.zeros(n)
    BEST_SF_loop = np.zeros(n)
    BEST_WF_loop = np.zeros(n)
    BEST_LBC_loop = np.zeros(n)
    min_vals = np.zeros(4)
    best_k = np.zeros(4)
    for i in range(n):
        min_vals[0] = SF2R[i] if SF2RI[i] == PARSYVI[i] else MAX_VAL
        min_vals[1] = SF2[i] if SF2I[i] == PARSYVI[i] or abs(SF2I[i] - PARSYVI[i])==1 else MAX_VAL
        min_vals[2] = SF4[i] if SF4I[i] == PARSYVI[i] else MAX_VAL
        min_vals[3] = SF6[i] if SF6I[i] == PARSYVI[i] else MAX_VAL
        BEST_SF[i] = np.min(min_vals)
        if BEST_SF[i] == min_vals[0] or BEST_SF[i] == min_vals[1]:
            BEST_SF_loop[i] = 2
        if BEST_SF[i] == min_vals[2]:
            BEST_SF_loop[i] = 4
        if BEST_SF[i] == min_vals[3]:
            BEST_SF_loop[i] = 6

        if BEST_SF[i] == MAX_VAL:
            print( "===> ", i)
        num = np.where(BEST_SF[0] == min_vals)[0]
        best_k[num] += 1

    # number of fused
    print("SF2: ", np.sum(BEST_SF_loop == 2), " - ", np.sum(BEST_SF_loop == 2)/n)
    print("SF4: ", np.sum(BEST_SF_loop == 4), " - ", np.sum(BEST_SF_loop == 4)/n)
    print("SF6: ", np.sum(BEST_SF_loop == 6), " - ", np.sum(BEST_SF_loop == 6)/n)

    JD_WF2V = in_csv_log[JD_WF2 + SECs].values
    JD_WF4V = in_csv_log[JD_WF4 + SECs].values
    JD_LBC2V = in_csv_log[JD_LBC2 + SECs].values
    JD_LBC4V = in_csv_log[JD_LBC4 + SECs].values

    JD_WF2VI = in_csv_log[JD_WF2 + ITR].values
    JD_WF4I = in_csv_log[JD_WF4 + ITR].values
    JD_LBC2VI = in_csv_log[JD_LBC2 + ITR].values
    JD_LBC4VI = in_csv_log[JD_LBC4 + ITR].values

    BEST_JD = np.zeros(n)
    min_vals = np.zeros(4)
    for i in range(n):
        min_vals[0] = JD_WF2V[i] if JD_WF2VI[i] == PARSYVI[i] else MAX_VAL
        min_vals[1] = JD_WF4V[i] if JD_WF4I[i] == PARSYVI[i] else MAX_VAL
        min_vals[2] = JD_LBC2V[i] if JD_LBC2VI[i] == PARSYVI[i] else MAX_VAL
        min_vals[3] = JD_LBC4V[i] if JD_LBC4VI[i] == PARSYVI[i] else MAX_VAL
        BEST_JD[i] = np.min(min_vals)
        best_wf = np.min((min_vals[0], min_vals[1]))
        if best_wf == min_vals[0]:
            BEST_WF_loop[i] = 2
        if best_wf == min_vals[1]:
            BEST_WF_loop[i] = 4

        best_jd = np.min((min_vals[2], min_vals[3]))
        if best_jd == min_vals[2]:
            BEST_LBC_loop[i] = 2
        if best_jd == min_vals[3]:
            BEST_LBC_loop[i] = 4

        if BEST_JD[i] == MAX_VAL:
            print( "===> ", i)
        num = np.where(BEST_SF[0] == min_vals)[0]

    print("AVG Speedup over ParSy:", gmean(PARSYV/BEST_SF))
    print("Max Speedup over ParSy:", np.max(PARSYV / BEST_SF))
    print("Min Speedup over ParSy:", np.min(PARSYV / BEST_SF))
    print("AVG Speedup over JD:", gmean(BEST_JD / BEST_SF))
    print("Max Speedup over JD:", np.max(BEST_JD / BEST_SF))
    print("Min Speedup over JD:", np.min(BEST_JD / BEST_SF))

    fig, ax = plt.subplots()
    #fig.suptitle('Scalability of SPILU0', fontsize=16)
    ax.scatter(NZ, PARSYV, s=100, c='g', marker='x', label='GS ParSy')
    ax.scatter(NZ, BEST_SF,s=80, facecolors='none', edgecolors='r', marker='o', label='GS Sparse Fusion')
    ax.scatter(NZ, BEST_JD, s=100, c='b', marker='4', label='GS Joint-DAG')
    # set grid off
    ax.grid(False)
    # set x and y axis label
    ax.set_xlabel('NNZ', fontsize=20, fontweight='bold')
    ax.set_ylabel('Time (seconds)', fontsize=20, fontweight='bold')
    # set x and y axis tick size
    ax.tick_params(axis='x', labelsize=20)
    ax.tick_params(axis='y', labelsize=20)
    # set right and top axis off
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    # set left and bottom axis bold
    ax.spines['left'].set_linewidth(2)
    ax.spines['bottom'].set_linewidth(2)
    fig.set_size_inches(18, 8)
    # set x tick black
    ax.tick_params(axis='x', colors='black')
    # set y tick black
    ax.tick_params(axis='y', colors='black')
    ax.set_xscale('log')
    ax.set_yscale('log')
    # show legend
    #fig.legend(handles, labels, fontsize=14, ncol=3, loc='upper center', frameon=True, borderaxespad=1)
    ax.legend(loc='upper left', fontsize=20, ncol=3, frameon=True, borderaxespad=1)
    ax.spines['left'].set_color('k')
    ax.spines['bottom'].set_color('k')
    #fig.show()
    fig.savefig('gs_all.pdf', bbox_inches='tight')
    #
    # sw = True
    # if sw:
    #     filename = "GS_K_Fusion"
    #
    #     half = 30
    #     data_array1 = np.zeros((3, half))
    #     # data_array[0, :] = SERIAL
    #     data_array1[0, :] = BEST_SF[0:half]
    #     data_array1[1, :] = PARSYV[0:half]
    #     data_array1[2, :] = BEST_JD[0:half]
    #     plot_scatter_chart_gs(data_array1, ["GS-Sparse-Fusion", "GS-ParSy", "GS-Joint-DAG"], NZ[0:half],
    #                           "Seconds", filename, "linear", (0, 0), 1, True)
    #
    #     half1 = 63
    #     data_array1 = np.zeros((3, half1 - half))
    #     # data_array[0, :] = SERIAL
    #     data_array1[0, :] = BEST_SF[half:half1]
    #     data_array1[1, :] = PARSYV[half:half1]
    #     data_array1[2, :] = BEST_JD[half:half1]
    #     plot_scatter_chart_gs(data_array1, ["GS-Sparse-Fusion", "GS-ParSy", "GS-Joint-DAG"], NZ[half:half1],
    #                           "Seconds", filename, "linear", (0, 1), 1, False)
    #
    #     data_array1 = np.zeros((3, n - half1))
    #     # data_array[0, :] = SERIAL
    #     data_array1[0, :] = BEST_SF[half1:n]
    #     data_array1[1, :] = PARSYV[half1:n]
    #     data_array1[2, :] = BEST_JD[half1:n]
    #     plot_scatter_chart_gs(data_array1, ["GS-Sparse-Fusion", "GS-ParSy", "GS-Joint-DAG"], NZ[half1:n],
    #                           "Seconds", filename, "linear", (0, 2), 1, False)
    #
    #     data_array_loopno = np.zeros((3, n))
    #
    #     # plt.legend(loc='upper left', fontsize=14, ncol=1, frameon=True)
    #
    # else:
    #     # data_array1 = np.zeros((3, n))
    #     # # data_array[0, :] = SERIAL
    #     # data_array1[0, :] = BEST_SF_loop[0:n]
    #     # data_array1[1, :] = BEST_WF_loop[0:n]
    #     # data_array1[2, :] = BEST_LBC_loop[0:n]
    #     # plot_scatter_chart_gs(data_array1, ["GS-Sparse-Fusion", "GS-ParSy", "GS-Joint-DAG"], NZ[0:n],
    #     #                       "Number of loops", filename, "linear", (0, 2), 1, False)
    #
    #     print("AVG Speedup over two loops:", np.average(SF2 / BEST_SF))
    #     print("min Speedup over two loops:", np.min(SF2 / BEST_SF))
    #     print("max Speedup over two loops:", np.max(SF2 / BEST_SF))
    #     filename = "GS_K_Fusion_twomore"
    #     legend =  ["GS-Sparse-Fusion \n(best of 2-6 loops)", "GS-Sparse-Fusion \n(only two loops)"]
    #     half = 30
    #     data_array2 = np.zeros((2, half))
    #     # data_array[0, :] = SERIAL
    #     data_array2[0, :] = BEST_SF[0:half]
    #     data_array2[1, :] = SF2[0:half]
    #     plot_scatter_chart_gs(data_array2, legend, NZ[0:half],
    #                           "Seconds", filename, "linear", (0, 0), 1, True)
    #
    #     half1 = 63
    #     data_array2 = np.zeros((2, half1 - half))
    #     # data_array[0, :] = SERIAL
    #     data_array2[0, :] = BEST_SF[half:half1]
    #     data_array2[1, :] = SF2[half:half1]
    #     plot_scatter_chart_gs(data_array2, legend, NZ[half:half1],
    #                           "Seconds", filename, "linear", (0, 1), 1, False)
    #
    #     data_array2 = np.zeros((2, n - half1))
    #     # data_array[0, :] = SERIAL
    #     data_array2[0, :] = BEST_SF[half1:n]
    #     data_array2[1, :] = SF2[half1:n]
    #     plot_scatter_chart_gs(data_array2,legend, NZ[half1:n],
    #                           "Seconds", filename, "linear", (0, 2), 1, False)

    #plt.show()

if __name__ == "__main__":
    args = sys.argv[1:]
    plot_gs_scatter(args[0])


import json
import logging
import os
import zipfile
from multiprocessing import Process

from ..common import *

logging.basicConfig(format="%(levelname)s:\t  %(message)s", level=logging.DEBUG)
_logger = logging.getLogger()

class VM:
    def __init__(
            self,
            new: bool = False,  # False to open an exist VM, True to create a new VM
            name: str = "",  # If you want to create a new vm, this is used to specify the name of the vm
            cpu: int = 2,  # When creating a new vm, you should set the cpu core with this pragma
            ram: float = 4,  # Used to set the ram size when creating a new vm, make sure that the unit is Gigabyte
            template: str = "",  # Initialize the new vm with the template you choose here
            directory: str = ""  # If you are opening an existed vm, use this to specify the directory of it
    ):

        self.name: str = ""
        self.vm_process: Process = Process()
        self.config: dict = {}

        if new:
            if not template:
                _logger.error("No given template of a new VM")
                raise ValueError("No given template of a new VM")

            self.new(name, cpu, ram, template)
        else:
            if not directory:
                _logger.error("No given directory of any VM")
                raise ValueError("No given directory of any VM")

            self.load(directory)

    def load(self, directory: str):
        self.name = directory.split("/")[len(directory.split("/")) - 1]
        _logger.info(f"Loading vm: {self.name}")

        try:
            with open(f"{directory}/config.json", "rt") as f:
                self.config = json.loads(f.read())
        except FileNotFoundError:
            _logger.error("Broken VM")
            raise FileNotFoundError("Broken VM")

    def new(self, name: str, cpu: int, ram: float, template: str):
        _logger.info(f"Creating a new vm with template: {template}")

        template_file = zipfile.ZipFile(template)
        template_file.extractall(f"vms/{name}")

        _logger.info(f"Initializing vm: {name}")
        self.load(f"vms/{name}")
        self.reconfig(cpu=cpu, ram=ram)

    def run(self) -> int:
        _logger.info(f"Starting up vm: {self.name}")

        port = -1

        for i in range(8090, 65535):
            if not check_port(i):
                port = i
                break

        if port == -1:
            _logger.error(f"No empty port exist, cannot start vm: {name}")
            raise IOError(f"No empty port exist, cannot start vm: {name}")

        self.vm_process = Process(target=lambda: os.popen(self.config["run_command"].format(cpu, ram, port)))
        self.vm_process.start()

        return port

    def kill(self):
        _logger.warning(f"Killing vm: {name} by sending a SIGKILL signal")
        self.vm_process.kill()

    def reconfig(self, cpu: int = 0, ram: float = 0):
        if cpu:
            self.config["cpu"] = cpu
        if ram:
            self.config["ram"] = ram

        _logger.info(f"Configuring vm: {self.name}")
        with open(f"vms/{self.name}/config.json", "wt") as f:
            f.write(json.dumps(self.config))

    def is_living(self):
        _logger.info(f"Getting vm's stature, current stature is: {self.vm_process.is_alive()}")
        return self.vm_process.is_alive()

    def get_name(self):
        return self.name


from scrapy.spiders import SitemapSpider

from locations.structured_data_spider import StructuredDataSpider
from locations.user_agents import BROWSER_DEFAULT

class HarveysSpider(SitemapSpider, StructuredDataSpider):
    name = "harveys"
    item_attributes = {"brand": "Harvey's", "brand_wikidata": "Q1466184"}
    allowed_domains = ["harveys.ca"]
    sitemap_urls = ["https://www.harveys.ca/en/locations/sitemap.xml"]
    sitemap_rules = [(r"/locations/[-\w]+/[-\w]+/[-\w]+", "parse_sd")]
    wanted_types = ["Restaurant"]
    user_agent = BROWSER_DEFAULT


# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
# Created by Mingfei Chen (chenmingfei.lasia@bytedance.com)
# Created On: 2020-1-8
# ------------------------------------------------------------------------------
import torch
import torch.nn as nn
import torch.nn.functional as F

from units.units import Scale, fcosfpn_conv2d

class FPN(nn.Module):

    def __init__(self,
                 in_channels,
                 out_channels,
                 num_outs,
                 start_level=0,
                 end_level=-1,
                 add_extra_convs=True,
                 extra_convs_on_inputs=False,
                 relu_before_extra_convs=True,
                 ):
        """ FCOSFPN. FPN based on lateral backbone, top-down paramid with extra pyramid layers.

        Args:
            in_channels (list): Channel num of input from the backbone
            out_channels (int): FPN output channel num
            num_outs (int): FPN output layer num
            end_level (int, -1): FPN layer num based on in_channel list length
            add_extra_convs (bool): Extra FPN layers
            extra_convs_on_inputs (bool): Extra FPN layers based on backbone input or FPN P5 layer
            relu_before_extra_convs (bool): ReLU activation before each extra layer

        Forward:
            fpn_in(list): len FPN_In_Layer_Num(4)  `([BS X In_Channel_1 X W_1 X H_1, ...])`

        Return:
            fpn_out(list): len FPN_Out_Layer_Num(5)  `([BS X Out_Channel X W_1 X H_1, ...])`

        """
        super(FPN, self).__init__()
        assert isinstance(in_channels, list)
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.num_ins = len(in_channels)
        self.num_outs = num_outs
        self.relu_before_extra_convs = relu_before_extra_convs

        if end_level == -1:
            self.backbone_end_level = self.num_ins
            assert num_outs >= self.num_ins - start_level
        else:
            # if end_level < inputs, no extra level is allowed
            self.backbone_end_level = end_level
            assert end_level <= len(in_channels)
            assert num_outs == end_level - start_level
        self.start_level = start_level
        self.end_level = end_level
        self.add_extra_convs = add_extra_convs
        self.extra_convs_on_inputs = extra_convs_on_inputs
        self.lateral_convs = nn.ModuleList()
        self.fpn_convs = nn.ModuleList()

        for i in range(self.start_level, self.backbone_end_level):
            # backbone for top features
            l_conv = fcosfpn_conv2d(
                in_channels[i],
                out_channels,
                1)
            # fpn backbone for bottom features
            fpn_conv = fcosfpn_conv2d(
                out_channels,
                out_channels,
                3,
                padding=1)
            self.lateral_convs.append(l_conv)
            self.fpn_convs.append(fpn_conv)
        # add extra conv layers (e.g., RetinaNet)
        extra_levels = num_outs - self.backbone_end_level + self.start_level
        if add_extra_convs and extra_levels >= 1:
            for i in range(extra_levels):
                if i == 0 and self.extra_convs_on_inputs:
                    in_channels = self.in_channels[self.backbone_end_level - 1]
                else:
                    in_channels = out_channels
                extra_fpn_conv = fcosfpn_conv2d(
                    in_channels,
                    out_channels,
                    3,
                    stride=2,
                    padding=1)
                self.fpn_convs.append(extra_fpn_conv)
        self.init_weights()

    def init_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def forward(self, inputs):
        assert len(inputs) == len(self.in_channels)
        # build laterals C3 C4 C5
        laterals = [
            lateral_conv(inputs[i + self.start_level])
            for i, lateral_conv in enumerate(self.lateral_convs)
        ]
        # build top-down path
        used_backbone_levels = len(laterals)
        for i in range(used_backbone_levels - 1, 0, -1):
            # upsample P4 P5
            laterals[i - 1] += F.interpolate(
                laterals[i], scale_factor=2, mode='nearest')
        # build outputs
        # append the bottom two outputs
        outs = [
            self.fpn_convs[i](laterals[i]) for i in range(used_backbone_levels)
        ]
        # append P6 P7
        if self.num_outs > len(outs):
            # when no extra layers, use max pool to get more levels on top of outputs
            if not self.add_extra_convs:
                for i in range(self.num_outs - used_backbone_levels):
                    outs.append(F.max_pool2d(outs[-1], 1, stride=2))
            # add conv layers on top of original feature maps (RetinaNet)
            else:
                # append the mid layer
                if self.extra_convs_on_inputs:
                    # apply the top input layer as base layer for extra convs
                    orig = inputs[self.backbone_end_level - 1]
                    outs.append(self.fpn_convs[used_backbone_levels](orig))
                else:
                    # appy P5 as base layer for extra convs
                    outs.append(self.fpn_convs[used_backbone_levels](outs[-1]))
                # append two top layers
                for i in range(used_backbone_levels + 1, self.num_outs):
                    # apply ReLU before extra convs
                    if self.relu_before_extra_convs:
                        outs.append(self.fpn_convs[i](F.relu(outs[-1])))
                    else:
                        outs.append(self.fpn_convs[i](outs[-1]))
        return tuple(outs)

if __name__ == "__main__":
    from torch.autograd import Variable
    neck = FPN(in_channels=[256, 512, 1024, 2048],
               out_channels=256,
               start_level=1,
               add_extra_convs=True,
               extra_convs_on_inputs=False,
               num_outs=5,
               relu_before_extra_convs=True)
    x = []
    in_dim = 256
    w = 200
    h = 256
    for i in range (4):
        x.append(Variable(torch.randn(2, in_dim, w, h)))
        in_dim = in_dim * 2
        w = int(w / 2)
        h = int(h / 2)
    outs = neck(x)
    for i in range (len(outs)):
        print(outs[i].shape)


from json import JSONDecoder

from togglcmder.toggl.builders.project_builder import ProjectBuilder

class ProjectDecoder(JSONDecoder):
    def __init__(self, *args: tuple, **kwargs: dict):
        JSONDecoder.__init__(self,
                             object_hook=ProjectDecoder.object_hook,
                             *args,
                             **kwargs)

    @staticmethod
    def object_hook(obj: dict):
        if 'data' in obj:
            return obj['data']

        if 'id' in obj:
            return ProjectBuilder()\
                .identifier(obj['id'])\
                .name(obj['name'])\
                .workspace_identifier(obj['wid'])\
                .color(int(obj['color']))\
                .last_updated(last_update=obj['at'])\
                .created(created=obj.get('created_at', None))\
                .build()

        return obj


import sys
import os
os.environ['QT_MAC_WANTS_LAYER'] = '1'
from PySide2 import QtWidgets
from PySide2 import QtCore
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import (
    QApplication, QVBoxLayout, QHBoxLayout,
    QFormLayout, QGridLayout, QTableWidget,
    QComboBox,
    QPushButton, QCheckBox, QListWidget, QFrame,
    QWidget, QMainWindow, QLineEdit, QLabel
)
from PySide2.QtGui import QFontMetrics
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from qt_material import apply_stylesheet

extra = {
    # Button colors
    'danger': '#dc3545',
    'warning': '#ffc107',
    'success': '#17a2b8',

    # Font
    'font': 'Monaco',
    'font_size': '22px',
    'line_height': '13px',

    # Density scale
    'density_scale': '0',

    # environ:
    'pyside2': True,
    'linux': True,
}

class QHLine(QFrame):
    def __init__(self):
        super(QHLine, self).__init__()
        self.setFrameShape(QFrame.HLine)
        self.setFrameShadow(QFrame.Sunken)

class QVLine(QFrame):
    def __init__(self):
        super(QVLine, self).__init__()
        self.setFrameShape(QFrame.VLine)
        self.setFrameShadow(QFrame.Sunken)

class QVLine(QFrame):
    def __init__(self):
        super(QVLine, self).__init__()
        self.setFrameShape(QFrame.VLine)
        self.setFrameShadow(QFrame.Sunken)

class MainWindowBrazzers(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Main menu manually V0.5")

        # #############################################
        #  Define the layout
        # #############################################
        # Create the complete layout
        self.complete_layout = QVBoxLayout()

        # Layout for label_picture and site_pictures
        self.label_pic_and_site_pictures = QHBoxLayout()
        self.braz_pic = QLabel("Label braz")
        print('width of label: ', self.braz_pic.width())
        self.braz_pic.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        #self.braz_pic.setFixedWidth(480)
        #self.braz_pic.setFixedHeight(640)
        #self.braz_pic.setStyleSheet("background-color: rgb(162, 162, 162)")
        self.braz_pixmap = QPixmap("/Users/joerg/repos/braz/site_pictures/brazzers.png")
        scaled_braz = self.braz_pixmap.scaled(self.braz_pic.size() / 4, QtCore.Qt.KeepAspectRatio)
        self.braz_pic.setPixmap(scaled_braz)
        self.braz_pic.setScaledContents(False)

        self.label_for_site_picture = QLabel("Site_picture")
        #self.label_for_site_picture.setStyleSheet("background-color: rgb(255, 255, 255)")
        name_tmp = "big_tits_in_uniform.png"
        path_folder_site_pictures = "/Users/joerg/repos/braz/site_pictures"
        path_to_site_picture = os.path.join(path_folder_site_pictures, name_tmp)

        self.site_pixmap = QPixmap(path_to_site_picture)
        scaled_site_picture = self.site_pixmap.scaled(self.label_for_site_picture.size() / 4, QtCore.Qt.KeepAspectRatio)
        picture_height = self.label_for_site_picture.height()
        self.braz_pic.setFixedWidth(picture_height)
        print('label_size: ', self.braz_pic.geometry())
        self.label_for_site_picture.setPixmap(scaled_site_picture)
        print('label_total: ', self.label_for_site_picture.width())
        # Fill the label_picture layout
        self.label_pic_and_site_pictures.addWidget(self.braz_pic)
        self.label_pic_and_site_pictures.addStretch()
        self.label_pic_and_site_pictures.addWidget(self.label_for_site_picture)

        # layout for QTableWidget AND search_btn_layout
        self.qtable_search_btn_layout = QHBoxLayout()

        # layout only for QTablewidget
        self.qtable_layout = QHBoxLayout()
        self.bra_dir_table = QTableWidget()
        print('width: ', self.bra_dir_table.width())
        # self.bra_dir_table.setGeometry(QtCore.QRect(0, 0, 1411, 161))
        self.bra_dir_table.setColumnCount(15)
        self.bra_dir_table.setHorizontalHeaderLabels(["Nr.", "Site", "PS1", "PS2", "PS3", "PS4",
                                                      "PS5", "PS6", "PS7", "PS8", "PS9", "PS10",
                                                      "title", "loc", "link"])
        # self.bra_dir_table.setColumnWidth(0, 25)
        # self.bra_dir_table.setColumnWidth(1, 80)
        # self.bra_dir_table.setColumnWidth(2, 80)

        header = self.bra_dir_table.horizontalHeader()
        #header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        #header.setSectionResizeMode(8, QtWidgets.QHeaderView.Stretch)

        self.qtable_layout.addWidget(self.bra_dir_table)

        # layout for the control_buttons on the right side
        self.search_btn_layout = QVBoxLayout()

        # Define layout for a horizontal line...
        self.hor_lin_1_layout = QHBoxLayout()
        self.hor_lin_1_layout.addWidget(QHLine())

        # Define layout for a horizontal line...
        self.hor_lin_2_layout = QHBoxLayout()
        self.hor_lin_2_layout.addWidget(QHLine())

        # Define layout for a horizontal line...
        self.hor_lin_3_layout = QHBoxLayout()
        self.hor_lin_3_layout.addWidget(QHLine())

        # first horizontal button row...
        self.first_horizontal_box = QHBoxLayout()
        self.sites_label = QLabel("Sites: ")
        self.comboBox_sites = QComboBox()
        self.first_horizontal_box.addWidget(self.sites_label)
        self.first_horizontal_box.addWidget(self.comboBox_sites)

        # first second button row...
        self.second_horizontal_box = QHBoxLayout()
        self.site_label_search = QLabel("Search for PS: ")
        #self.site_label_search.setStyleSheet("font-size: 12px;" "color: green;")
        self.site_comboBox_search_ps = QComboBox()
        self.second_horizontal_box.addWidget(self.site_label_search)
        self.second_horizontal_box.addWidget(self.site_comboBox_search_ps)

        # first third button row...
        self.third_horizontal_box = QHBoxLayout()

        self.header_selected_ps = QLabel("Sites of the selected PS")
        #self.header_selected_ps.setStyleSheet("font: Monaco;" "color: blue;")
        self.third_horizontal_box.addWidget(self.header_selected_ps)

        # Define layout for a horizontal line...
        self.hor_lin_4_layout = QHBoxLayout()
        self.hor_lin_4_layout.addWidget(QHLine())

        # first second button row...
        self.fourth_horizontal_box = QHBoxLayout()
        selected_ps_name = "Rebecca More"
        self.lbl_selected_ps = QLabel(selected_ps_name)
        #self.lbl_selected_ps.setStyleSheet("font-size: 12px;" "color: green;")
        self.sites_of_selected_ps = QComboBox()
        for cnts in ['Milfs Like It Big', 'Big Tits In Uniform',
                     'Big Tits At School', 'Big Tits In Sports']:
            self.sites_of_selected_ps.addItem(cnts)
        width = self.sites_of_selected_ps.minimumSizeHint().width()
        self.sites_of_selected_ps.view().setMinimumWidth(width*1.5)
        print("width_: ", width)
        self.fourth_horizontal_box.addWidget(self.lbl_selected_ps)
        self.fourth_horizontal_box.addWidget(self.sites_of_selected_ps)

        # Fill the vertical layout on the right side.
        self.search_btn_layout.addLayout(self.first_horizontal_box)
        self.search_btn_layout.addLayout(self.hor_lin_1_layout)
        self.search_btn_layout.addLayout(self.second_horizontal_box)
        self.search_btn_layout.addLayout(self.hor_lin_2_layout)
        self.search_btn_layout.addLayout(self.third_horizontal_box)
        self.search_btn_layout.addLayout(self.fourth_horizontal_box)
        self.search_btn_layout.addStretch()

        # FIll the QTableWidget_layout and search_btn_layout
        self.qtable_search_btn_layout.addLayout(self.qtable_layout)
        #self.qtable_search_btn_layout.addStretch()
        #self.qtable_search_btn_layout.insertStretch(0, 10)
        self.qtable_search_btn_layout.addLayout(self.search_btn_layout)
        #self.qtable_search_btn_layout.addStretch()

        # Arange the layout in the desired manner:
        self.complete_layout.addLayout(self.label_pic_and_site_pictures)
        #self.complete_layout.addStretch()
        self.complete_layout.addLayout(self.qtable_search_btn_layout)
        #elf.complete_layout.addStretch()

        # Set the hand-made complete layout in a superordinate QWidget called dummy_widget
        dummy_widget = QWidget()
        dummy_widget.setLayout(self.complete_layout)
        self.setCentralWidget(dummy_widget)

        # #############################################
        #  End of definition of the layout
        # #############################################

if __name__ == "__main__":
    current_path = os.path.dirname(__file__)
    print('current_path: ', current_path)
    #style_path = os.path.join(current_path, 'app.css')
    # load and set stylesheet

    app = QApplication(sys.argv)

    # first variant: Define the apply_stylesheet method...
    #apply_stylesheet(app, theme='my_dark_amber.xml', extra=extra)

    # second variant
    # define, load and set stylesheet
    #current_path = os.path.dirname(__file__)
    #style_path = os.path.join(current_path, 'app.css')
    #with open(style_path, "r") as fh:
    #    app.setStyleSheet(fh.read())

    # Third variant:
    apply_stylesheet(app, theme='dark_cyan.xml')

    stylesheet = app.styleSheet()
    # with open("my_style_2.css") as file:
    #     app.setStyleSheet(stylesheet + file.read().format(**os.environ))

    window = MainWindowBrazzers()
    window.resize(800, 600)
    window.show()
    sys.exit(app.exec_())


# coding=utf-8

import requests
from bs4 import BeautifulSoup
import re
import csv
import time
import datetime
import os
import pymongo

re_r = '1[3|4|5|7|8]\d{9}'  # 1代表第一个号码为1;;;[3|4|5|7|8]第二位指定为这几个数；；；\d代表0~9，{9}循环9次

one_url = ['https://www.atobo.com.cn/Companys/s-p26-y{}/'.format(str(i)) for i in range(10,50)]

one_title_url = '#setcolor_area > div.product_contextlist.bplist > ul > li'
one_href_url = ' div > ul > li.p_name > div > ul > li.pp_name > a.CompanyName'

name = 'body > div.contextf > div > div > div.cont-r > div:nth-of-type(1) > div > div > ul:nth-of-type(3) > li.card-right'
telephone = 'body > div.contextf > div > div > div.cont-r > div:nth-of-type(1) > div > div > ul:nth-of-type(4) > li.card-right'
phone = 'body > div.contextf > div > div > div.cont-r > div:nth-of-type(1) > div > div > ul:nth-of-type(5) > li.card-right'

def get_html_url():
    print()
    for var_url in one_url:
        time.sleep(100)
        url_html = requests.get(var_url)
        soup = BeautifulSoup(url_html.text, 'html.parser')
        for var_one in soup.select(one_title_url):
            one_href = var_one.select(one_href_url)
            for two_url in one_href:
                url_url = two_url.get('href')
                home_url = 'https:' + url_url
                print(home_url)
                time.sleep(5)
                # # 调用只获得手机号码的方法
                # get_phone(home_url)
                # 调用获得手机号和姓名
                get_name_phone(home_url)

# 获得手机号和姓名
def get_name_phone(url):
    arr_two = []
    two_url = requests.get(url)
    soup = BeautifulSoup(two_url.text, 'html.parser')
    var_name1 = soup.select(name)
    var_telephone1 = soup.select(telephone)
    var_phone1 = soup.select(phone)
    for var_name, var_telephone, var_phone in zip(var_name1,var_telephone1,var_phone1):
        data_two = (
            var_name.text,
            var_telephone.text,
            var_phone.text
        )
        arr_two.append(data_two)
        print(arr_two)
        set_name_phone(set_data_time('name'), arr_two)

# 存储姓名，手机号，座机号
def set_name_phone(folder, _arr1):
    if os.access(folder, os.F_OK):
        with open(folder, 'a+', newline='')as folders:
            writers = csv.writer(folders)
            writers.writerows(_arr1)
            folders.close()
    else:
        with open(folder, 'a+', newline='')as folders:
            writers = csv.writer(folders)
            writers.writerow(['name', 'telephone', 'phone'])
            writers.writerows(_arr1)
            folders.close()

# 获得手机号码
def get_phone(url):
    arr_data = []
    url_html = requests.get(url).text
    re_phone = re.findall(re_r, url_html, re.M | re.S | re.I)
    re_phone = set(re_phone)
    for car_phone in re_phone:
        data_a = (
            car_phone
        )
        arr_data.append(data_a)
    set_csv(set_data_time('phone'), arr_data)

# 设置文件生成时间
def set_data_time(st):
    time_ = time.localtime(time.time())
    data_day = datetime.date.today()
    folder = 'E:\sc\四川%s-%s点%s.csv' % (data_day, time_.tm_hour, st)
    return folder

# 文件存储
def set_csv(folder, _arr1):
    if os.access(folder, os.F_OK):
        with open(folder, 'a+', newline='')as folders:
            writers = csv.writer(folders)
            writers.writerows(_arr1)
            folders.close()
    else:
        with open(folder, 'a+', newline='')as folders:
            writers = csv.writer(folders)
            writers.writerow(['phone'])
            writers.writerows(_arr1)
            folders.close()

if __name__ == '__main__':
    print('开始运行！！！')
    # get_phone('https://hyb8816.atobo.com.cn/')
    get_html_url()


import boto3
import os
import json

aws_key = open('/var/openfaas/secrets/openfaas-aws-access-key', 'r').read()
aws_secret = open('/var/openfaas/secrets/openfaas-aws-secret-key', 'r').read()
dynamodb_region = os.environ['dynamodb_region']
dynamodb_table  = os.environ['dynamodb_table']

client = boto3.Session(region_name=dynamodb_region).resource('dynamodb', aws_access_key_id=aws_key, aws_secret_access_key=aws_secret)
table = client.Table(dynamodb_table)

def handle(req):
    event = json.loads(req)
    response = table.get_item(
        Key={
            'hash_value': event['hash_value']
        }
    )

    if 'Item' not in response:
        item_data = 'Item not found'
    else:
        item_data = response['Item']

    return item_data