"""
Functions to convert pmfs to latex arrays.
"""

import contextlib
import os
import subprocess  # noqa: S404
import tempfile

from debtcollector import removals

import numpy as np
import numpy.core.arrayprint as arrayprint

from .context import cd, named_tempfile, tempdir
from .misc import default_opener

__all__ = (
    'printoptions',
    'to_latex',
    'to_pdf',
)

# http://stackoverflow.com/questions/2891790/pretty-printing-of-numpy-array
#
# Includes hack to prevent NumPy from removing trailing zeros.
#
@removals.remove(message="Please use np.core.arrayprint.printoptions",
                 version='1.2.3')
@contextlib.contextmanager
def printoptions(strip_zeros=True, **kwargs):
    if strip_zeros:
        kwargs['trim'] = 'k'
    origcall = arrayprint.FloatingFormat.__call__

    def __call__(self, x):
        return origcall.__call__(self, x)

    arrayprint.FloatingFormat.__call__ = __call__
    original = np.get_printoptions()
    np.set_printoptions(**kwargs)
    yield
    np.set_printoptions(**original)
    arrayprint.FloatingFormat.__call__ = origcall

def to_latex__numerical(a, decimals, tab):
    # The elements of each column are aligned on the decimal, if present.
    # Spacing is automatically adjusted depending on if `a` contains negative
    # numbers or not. For float data, trailing zeros are included so that
    # array output is uniform.

    array = np.atleast_2d(a)
    array = np.around(array, decimals)

    # Determine the number of digits left of the decimal.
    # Grab integral part, convert to string, and get maximum length.
    # This does not handle negative signs appropriately since -0.5 goes to 0.
    # So we make sure it never counts a negative sign by taking the abs().
    integral = np.abs(np.trunc(array.flat).astype(int))
    left_digits = max(map(len, map(str, integral)))

    # Adjust for negative signs.
    if np.any(array < 0):
        left_digits += 1

    # Set decimal digits to 0 if data are not floats.
    try:
        np.finfo(array.dtype)
    except ValueError:
        decimals = 0

    # Align the elements on the decimal, making room for largest element.
    coltype = r"\newcolumntype{{X}}{{D{{.}}{{.}}{{{0},{1}}}}}"
    coltype = coltype.format(left_digits, decimals)

    # Specify that we want all columns to have the same column type.
    nCols = array.shape[1]
    cols = r"*{{{nCols}}}{{X}}".format(nCols=nCols)

    # Build the lines in the array.
    #
    # In general, we could just use the rounded array and map(str, row),
    # but NumPy strips trailing zeros on floats (undesirably). So we make
    # use of the context manager to prevent that.
    options = {
        'precision': decimals,
        'suppress': True,
        'strip_zeros': False,
        'threshold': nCols + 1,
    }
    with printoptions(**options):
        lines = []
        for row in array:
            # Strip [ and ], remove newlines, and split on whitespace
            elements = row.__str__()[1:-1].replace('\n', '').split()
            # hack to fix trailing zeros, really the numpy stuff needs to be updated.
            try:
                elements = [element + '0' * (decimals - len(element.split('.')[1])) for element in elements]
            except:  # noqa; S110
                pass
            line = [tab, ' & '.join(elements), r' \\']
            lines.append(''.join(line))

    # Remove the \\ on the last line.
    lines[-1] = lines[-1][:-3]

    # Create the LaTeX code
    subs = {'coltype': coltype, 'cols': cols, 'lines': '\n'.join(lines)}
    template = r"""{coltype}
\begin{{array}}{{{cols}}}
{lines}
\end{{array}}"""

    return template.format(**subs)

def to_latex__exact(a, tol, tab):

    from dit.math import approximate_fraction

    array = np.atleast_2d(a)

    to_frac = lambda f: approximate_fraction(f, tol)
    fractions = np.array(list(map(to_frac, array.flat))).reshape(array.shape)

    # Specify that we want all columns to have the same column type.
    nCols = array.shape[1]
    cols = r"*{{{nCols}}}{{c}}".format(nCols=nCols)

    def to_frac(f):
        if f.denominator != 1:
            return r'\frac{{{}}}{{{}}}'.format(f.numerator, f.denominator)
        else:
            return str(f.numerator)

    # Build the lines in the array.
    lines = []
    for row in fractions:
        # Strip [ and ], remove newlines, and split on whitespace
        elements = map(to_frac, row)
        line = [tab, ' & '.join(elements), r' \\']
        lines.append(''.join(line))

    # Remove the \\ on the last line.
    lines[-1] = lines[-1][:-3]

    # Create the LaTeX code
    subs = {'cols': cols, 'lines': '\n'.join(lines)}
    template = r"""\begin{{array}}{{{cols}}}
{lines}
\end{{array}}"""

    return template.format(**subs)

def to_latex(a, exact=False, decimals=3, tab='  '):
    r"""
    Convert an array-like object into a LaTeX array.

    Parameters
    ----------
    a : array-like
        A list, tuple, NumPy array, etc. The elements are written into a
        LaTeX array environment.

    exact : bool
        When `exact` is False, the elements of each column are aligned on the
        decimal, if present. Spacing is automatically adjusted depending on if
        `a` contains negative numbers or not. For float data, trailing zeros
        are included so that array output is uniform.

        When `exact` is `True`, then each float is turned into a fraction and
        placed in a column. One may specify `exact` as a small float to be used
        as the tolerance while converting to a fraction.

    decimals : int
        The number of decimal places to round to before writing to LaTeX.

    tab : str
        The tab character to use for indentation within LaTeX.

    Examples
    --------
    >>> x = [1,2,-3]
    >>> print to_latex(x)
    \newcolumntype{X}{D{.}{.}{2,0}}
    \begin{array}{*{3}{X}}
      1 & 2 & -3
    \end{array}

    >>> import numpy as np
    >>> np.random.seed(0)
    >>> y = np.random.rand(12).reshape(4,3) - 0.5
    >>> print to_latex(y, decimals=2)
    \newcolumntype{X}{D{.}{.}{2,2}}
    \begin{array}{*{3}{X}}
      0.05 & 0.22 & 0.10 \\
      0.04 & -0.08 & 0.15 \\
      -0.06 & 0.39 & 0.46 \\
      -0.12 & 0.29 & 0.03
    \end{array}

    Notes
    -----
    The resultant array environment should be used within LaTeX's mathmode,
    and the following should appear in the preamble:

        \usepackage{array}
        \usepackage{dcolumn}

    """
    if exact:
        if exact is True:
            tol = 1e-6
        else:
            tol = exact
        return to_latex__exact(a, tol, tab)
    else:
        return to_latex__numerical(a, decimals, tab)

def to_pdf(a, exact=False,
              decimals=3,
              line="p(x) = \\left[\n{0}\n\\right]",
              show=True):
    """
    Converts a NumPy array to a LaTeX array, compiles and displays it.

    Examples
    --------
    >>> a = np.array([[.1, .23, -1.523],[2.1, .23, .523]])
    >>> to_pdf(a) # pragma: no cover

    """
    template = r"""\documentclass{{article}}
\usepackage{{amsmath}}
\usepackage{{array}}
\usepackage{{dcolumn}}
\pagestyle{{empty}}
\begin{{document}}
\begin{{displaymath}}
{0}
\end{{displaymath}}
\end{{document}}"""

    fline = line.format(to_latex(a, exact=exact, decimals=decimals))
    latex = template.format(fline)

    with contextlib.ExitStack() as stack:  # pragma: no cover
        EC = stack.enter_context
        tmpdir = EC(tempdir())
        EC(cd(tmpdir))
        latexfobj = EC(named_tempfile(dir=tmpdir, suffix='.tex'))

        # Write the latex file
        latexfobj.write(latex.encode('utf8'))
        latexfobj.close()

        # Compile to PDF
        args = ['pdflatex', '-interaction=batchmode', latexfobj.name]
        with open(os.devnull, 'w') as fp:
            subprocess.call(args, stdout=fp, stderr=fp)  # noqa: S603
            subprocess.call(args, stdout=fp, stderr=fp)  # noqa: S603

        # Create another tempfile which will not be deleted.
        pdffobj = tempfile.NamedTemporaryFile(suffix='_pmf.pdf', delete=False)
        pdffobj.close()

        # Crop the PDF and copy to persistent tempfile.
        pdfpath = latexfobj.name[:-3] + 'pdf'
        # Cannot add &>/dev/null to cmd, as Ghostscript is unable to find the
        # input file. This seems to be some weird interaction between
        # subprocess and pdfcrop. Also, we need to use shell=True since some
        # versions of pdfcrop rely on a hack to determine what perl interpreter
        # to call it with.
        cmd = r'pdfcrop --debug {} {}'.format(pdfpath, pdffobj.name)
        with open(os.devnull, 'w') as fp:
            subprocess.call(cmd, stdout=fp)  # noqa: S603

        # Open the PDF
        if show:
            default_opener(pdffobj.name)

        return pdffobj.name


from tensorboard.plugins.hparams import api as hp

HP_TOKEN_TYPE = hp.HParam('token_type', hp.Discrete(['word-piece', 'character']))
HP_VOCAB_SIZE = hp.HParam('vocab_size', hp.Discrete([2**12]))

# Preprocessing Hparams
HP_MEL_BINS = hp.HParam('mel_bins', hp.Discrete([80]))
HP_FRAME_LENGTH = hp.HParam('frame_length', hp.Discrete([0.025]))
HP_FRAME_STEP = hp.HParam('frame_step', hp.Discrete([0.01]))
HP_HERTZ_LOW = hp.HParam('hertz_low', hp.Discrete([125.0]))
HP_HERTZ_HIGH = hp.HParam('hertz_high', hp.Discrete([7600.0]))
HP_DOWNSAMPLE_FACTOR = hp.HParam('downsample_factor', hp.Discrete([3]))

# Model Hparams
HP_EMBEDDING_SIZE = hp.HParam('embedding_size', hp.Discrete([500]))
HP_ENCODER_LAYERS = hp.HParam('encoder_layers', hp.Discrete([8]))
HP_ENCODER_SIZE = hp.HParam('encoder_size', hp.Discrete([2048]))
HP_PROJECTION_SIZE = hp.HParam('projection_size', hp.Discrete([640]))
HP_TIME_REDUCT_INDEX = hp.HParam('time_reduction_index', hp.Discrete([1]))
HP_TIME_REDUCT_FACTOR = hp.HParam('time_reduction_factor', hp.Discrete([2]))
HP_PRED_NET_LAYERS = hp.HParam('pred_net_layers', hp.Discrete([2]))
HP_PRED_NET_SIZE = hp.HParam('pred_net_size', hp.Discrete([2048]))
HP_JOINT_NET_SIZE = hp.HParam('joint_net_size', hp.Discrete([640]))
HP_DROPOUT = hp.HParam('dropout', hp.Discrete([0]))

# HP_EMBEDDING_SIZE = hp.HParam('embedding_size', hp.Discrete([32]))
# HP_ENCODER_LAYERS = hp.HParam('encoder_layers', hp.Discrete([4]))
# HP_ENCODER_SIZE = hp.HParam('encoder_size', hp.Discrete([20]))
# HP_PROJECTION_SIZE = hp.HParam('projection_size', hp.Discrete([50]))
# HP_TIME_REDUCT_INDEX = hp.HParam('time_reduction_index', hp.Discrete([1]))
# HP_TIME_REDUCT_FACTOR = hp.HParam('time_reduction_factor', hp.Discrete([2]))
# HP_PRED_NET_LAYERS = hp.HParam('pred_net_layers', hp.Discrete([2]))
# HP_PRED_NET_SIZE = hp.HParam('pred_net_size', hp.Discrete([100]))
# HP_JOINT_NET_SIZE = hp.HParam('joint_net_size', hp.Discrete([50]))
# HP_DROPOUT = hp.HParam('dropout', hp.Discrete([0.2]))

HP_LEARNING_RATE = hp.HParam('learning_rate', hp.Discrete([1e-4]))

METRIC_TRAIN_LOSS = 'train_loss'
METRIC_TRAIN_ACCURACY = 'train_accuracy'
METRIC_EVAL_LOSS = 'eval_loss'
METRIC_EVAL_ACCURACY = 'eval_accuracy'
METRIC_EVAL_CER = 'eval_cer'
METRIC_EVAL_WER = 'eval_wer'
METRIC_ACCURACY = 'accuracy'
METRIC_CER = 'cer'
METRIC_WER = 'wer'


import pickle
import sys
from collections import deque

sys.setrecursionlimit(1000000)

class Graph(object):

    def __init__(self, size):
        self.nodes = {}
        self.size = size

    def __repr__(self):
        return '<Graph with {} nodes>'.format(self.size)

    def get_node(self, id):
        node = self.nodes.get(id)
        if node is None:
            node = Node(id)
            self.nodes[id] = node
        return node

    def add_data(self, u, v):
        N = self.size
        if u > 0:
            if v > 0:
                o = self.get_node(N+u)
                d = self.get_node(v)
                o.set_out(d.id)
                d.set_in(o.id)
                o = self.get_node(N+v)
                d = self.get_node(u)
                o.set_out(d.id)
                d.set_in(o.id)
            else:
                o = self.get_node(N+u)
                d = self.get_node(N-v)
                o.set_out(d.id)
                d.set_in(o.id)
                o = self.get_node(-v)
                d = self.get_node(u)
                o.set_out(d.id)
                d.set_in(o.id)
        else:
            if v > 0:
                o = self.get_node(-u)
                d = self.get_node(v)
                o.set_out(d.id)
                d.set_in(o.id)
                o = self.get_node(N+v)
                d = self.get_node(N-u)
                o.set_out(d.id)
                d.set_in(o.id)
            else:
                o = self.get_node(-u)
                d = self.get_node(N-v)
                o.set_out(d.id)
                d.set_in(o.id)
                o = self.get_node(-v)
                d = self.get_node(N-u)
                o.set_out(d.id)
                d.set_in(o.id)

    def calc_finish(self):
        print('First pass')
        ft = 0
        q = deque()
        first = list(sorted(self.nodes.values(), key=lambda x: x.id, reverse=True))
        for node in first:
            if node.bck:
                continue
            self.dfs(node, q, False)
            while q:
                ft += 1
                n = q.pop()
                n.set_finish(ft)

        print('Second pass')
        second = list(sorted(self.nodes.values(), key=lambda x: x.finish, reverse=True))
        for node in second:
            if node.fwd:
                continue
            q = deque()
            scc = {node.id}
            self.dfs(node, q, True, scc)

    def dfs(self, node, queue, fw=True, scc=None):
        queue.append(node)
        if fw:
            node.fwd = True
            for n in node.outgoing:
                n = self.get_node(n)
                if n.fwd:
                    continue
                if n.id > self.size and (n.id - self.size) in scc:
                    print(scc)
                    raise ValueError('unsatisfied')
                elif n.id < self.size and (n.id + self.size) in scc:
                    print(scc)
                    raise ValueError('unsatisfied')
                scc.add(n.id)
                self.dfs(n, queue, fw, scc)
        else:
            node.bck = True
            for n in node.incoming:
                n = self.get_node(n)
                if n.bck:
                    continue
                self.dfs(n, queue, fw)

class Node(object):

    def __init__(self, id):
        assert id > 0
        self.id = id
        self.finish = None
        self.incoming = set()
        self.outgoing = set()
        self.fwd = False
        self.bck = False

    def __repr__(self):
        return '<Node {}. in:{} out:{}>'.format(self.id, self.incoming, self.outgoing)

    def set_finish(self, value):
        self.finish = value

    def set_in(self, id):
        self.incoming.add(id)

    def set_out(self, id):
        self.outgoing.add(id)

def main():
    count = None
    with open(sys.argv[1], 'rt') as f:
        for r in f.read().split('\n'):
            if not r:
                continue
            if count is None:
                count = int(r)
                graph = Graph(count)
            else:
                graph.add_data(*tuple(map(int, r.split())))
    try:
        graph.calc_finish()
    except ValueError:
        print('unsatisfied')
    else:
        print('satisfied')

if __name__ == '__main__':
    main()


from __future__ import print_function
import sys
import os
from pymongo import MongoClient
from pymongo.errors import InvalidDocument
import json

class factory(object):
    """ output class generator helper """
    def __init__(self, config, resconf, dry_run=False):
        outconf = config.getsection("outputdatabase")

        if 'db_engine' not in outconf and 'type' in outconf:
            # Older versions of the documentation recommended 'type' as the
            # configuration parameter use this if 'db_engine' is absent
            outconf['db_engine'] = outconf['type']

        if outconf['db_engine'].lower() == "mongodb":
            self._impl = MongoOutput(outconf, resconf) if not dry_run else NullOutput()
        elif outconf['db_engine'].lower() == "stdout":
            self._impl = StdoutOutput(outconf, resconf)
        elif outconf['db_engine'] == 'file':
            self._impl = FileOutput(outconf, resconf)
        else:
            raise Exception("Unsupported output mechanism {0}".format(outconf['db_engine']))

    def __enter__(self):
        return self._impl.__enter__()

    def __exit__(self, exception_type, exception_val, trace):
        return self._impl.__exit__(exception_type, exception_val, trace)

class FileOutput(object):
    """
    Dumps output into a file in one of two fashions
    1. Fragment - dumps snippets of json (currently one json object per job) into
                  a file as the process runs. This file will NOT be valid json, however
                  useful for pseudo interactive debugging purposes.
    2. Complete - dumps entire result as one large json array at end of process.
                  File will be empty during runtime, but will be valid json.
    """
    def __init__(self, outconf, resconf):
        self._resid = resconf['resource_id']

        jsonoption = outconf['json_format']
        if jsonoption == 'both':
            self._fragjson = True
            self._completejson = True
        elif jsonoption == 'fragment':
            self._fragjson = True
            self._completejson = False
        elif jsonoption == 'complete':
            self._fragjson = False
            self._completejson = True
        else:
            raise Exception("Not a valid json option {0}".format(jsonoption))

        if self._fragjson:
            self._fragpath = outconf['frag_file']
        if self._completejson:
            self._comppath = outconf['comp_file'].replace("%r", resconf["name"])

        if self._fragjson:
            self._fragfile = open(self._fragpath, 'w')
        if self._completejson:
            self._jsonarray = []

    def __enter__(self):
        return self

    def process(self, summary, mdata):
        """
        json print
        """
        if self._fragjson:
            print(self._resid, json.dumps(summary, indent=4, default=str), file=self._fragfile)
            print("MDATA: ", json.dumps(mdata, indent=4, default=str), file=self._fragfile)
        if self._completejson:
            self._jsonarray.append(summary)
            self._jsonarray.append(mdata)

    def __exit__(self, exception_type, exception_val, trace):
        if self._fragjson:
            self._fragfile.close()
        if self._completejson:
            with open(self._comppath, 'w') as f:
                json.dump(self._jsonarray, f, indent=4, default=str)

class MongoOutput(object):
    """ Support for mongodb output """
    def __init__(self, outconf, resconf):
        self._uri = outconf['uri']
        self._dname = outconf.get('dbname', outconf.get('db', 'supremm'))
        self._collection = "resource_" + str(resconf['resource_id'])
        self._timeseries = "timeseries-" + self._collection
        self._client = None
        self._outdb = None

    def __enter__(self):
        self._client = MongoClient(host=self._uri)
        self._outdb = self._client[self._dname]
        return self

    def process(self, summary, mdata):
        """ output the summary record """

        mongoid = str(summary['acct']['id']) + '-' + str(summary['acct']['end_time'])
        summary['_id'] = mongoid
        summary['summarization'].update(mdata)

        if 'timeseries' in summary:
            summary['timeseries']['_id'] = summary["_id"]
            self._outdb[self._timeseries].update({"_id": summary["_id"]}, summary['timeseries'], upsert=True)
            del summary['timeseries']

        self._outdb[self._collection].update({"_id": summary["_id"]}, summary, upsert=True)

    def __exit__(self, exception_type, exception_val, trace):
        if self._client != None:
            self._outdb = None
            self._client.close()
            self._client = None

class StdoutOutput(object):
    """
    Simple outputter that dumps the job summary to stdout. Intended for debug purposes.
    """
    def __init__(self, _, resconf):
        self._resid = resconf['resource_id']

    def __enter__(self):
        return self

    def process(self, summary, mdata):
        """
        json print
        """
        print(self._resid, json.dumps(summary, default=str, indent=4))
        print("MDATA: ", json.dumps(mdata, default=str, indent=4))

    def __exit__(self, exception_type, exception_val, trace):
        pass

class NullOutput(object):
    """
    Outputter used when configured outputter is a database (Mongo) but the dry-run option is set.
    Discards all data.
    """
    def __enter__(self):
        return self

    def process(self, summary, mdata):
        pass

    def __exit__(self, exception_type, exception_val, trace):
        pass


from typing import List, Tuple

import ethereum.frontier.trie as normal_trie
import ethereum_optimized.trie as optimized_trie
from ethereum.base_types import Bytes

operations: List[List[Tuple[Bytes, Bytes]]] = [
    [],  # Empty Trie
    [(b"1234", b"foo")],  # Add a leaf
    [(b"1234", b"bar")],  # Change the value of a leaf
    [(b"1234", b"")],  # Delete a leaf
    [(b"abcde", b"foo"), (b"abcdef", b"foo")],  # Make an extension node
    [(b"abc", b"foo")],  # Split an extension node
    [(b"abcde", b"")],  # Merge an extension and leaf
    [(b"abcde1", b"foo"), (b"abcde2", b"")],  # Split a leaf node
    [  # Delete all subnodes of an extension node but not the value at the node
        (b"abcde1", b""),
        (b"abcde2", b""),
        (b"abcdef", b""),
    ],
    [(b"abcde", b"")],
    [(b"abcde1", b"foo"), (b"abcde2", b"")],
    [  # Delete all subnodes of an extension node and the value at the node
        (b"abcde1", b""),
        (b"abcde2", b""),
        (b"abcde", b""),
    ],
    [(b"a", b"foo"), (b"aaa", b"foo"), (b"aaaa", b"foo")],
    [(b"a", b""), (b"aa", b"foo")],
    [(b"\x00\x00\x00\x00", b"foo"), (b"\x00\x00\x00\x01", b"foo")],
    [(b"\x00\x00\x00\x10", b"foo")],
    [(b"a", b"foo"), (b"b", b"foo"), (b"c", b"foo"), (b"d", b"foo")],
]

def test_trie() -> None:
    trie_normal = normal_trie.Trie(False, b"")
    trie_optimized = optimized_trie.Trie(False, b"")
    for insert_list in operations:
        for (key, value) in insert_list:
            normal_trie.trie_set(trie_normal, key, value)
            optimized_trie.trie_set(trie_optimized, key, value)
        assert normal_trie.root(trie_normal) == optimized_trie.root(
            trie_optimized
        )


#!/opt/anaconda3.7/bin/python3.7
import numpy as np, matplotlib.pyplot as plt, os, sys
import regex as re, ast
import argparse
from setup_functions import *
from subroutines.parse_input import *
from subroutines.scatter import *
from subroutines.bar import *
from subroutines.dev import *

if len(sys.argv) == 1:
    print(f"\n\n\tERROR: This script must be called with an additional argument, ie: "
          f"\n\n\t\t\t plotpro input.txt (--suppress)\n\n")
    sys.exit()

filenames = sys.argv[1:]

# Set up the ArgumentParser to interpret the command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("file", help="Name(s) of the file(s) to plot. If more than one input, all files will be processed.", nargs='+')
parser.add_argument("-s", "--suppress", help="Suppress the display of figures. Default: False")
args = parser.parse_args()
boolsuppress = False    # Default: Don't suppress the showing of figures.
if args.suppress:
    if args.suppress.lower() in ("y", "j", "yes", "ja", "on", "true") or args.suppress == True:
        boolsuppress = True

    filenames = filenames[:-2]  # Remove the "--suppress" and "arg" from the list of input arguments

(save_list, keys_list, keys, keys_default, cosmetics_list, cosmstr, cosmval, cosmcol, cosmetic_defaults,
 hatch_list) = definitions()

# print_string = "\n\nRunning PlotPro"
print_string = initiate_output()
sep2 = "-"*35 + "="*50 + "-"*35 + "\n"*2
sep = "\n"*2 + sep2 + "\n"*2

for filename in filenames:
    if os.path.isfile(filename):
        print("Working on file: "+filename)
    else:
        print(filename+" is not a filename.")
        continue

    output_name = f"{os.path.splitext(filename)[0]}.out"

    print_string += f"\n\n{'Input file':30} {filename:25}\n{'Current working directory':30} {os.getcwd()}{sep}"

    # PPPPPPP     AAAAAA    RRRRRRR      SSSSSSS    EEEEEEEE
    # P      P   A      A   R      R    S           E
    # P      P  A        A  R      R    S           E
    # PPPPPPP   AAAAAAAAAA  RRRRRRR      SSSSS      EEEEE
    # P         A        A  R R                S    E
    # P         A        A  R   R               S   E
    # P         A        A  R    R              S   E
    # P         A        A  R     R            S    E
    # P         A        A  R      R    SSSSSSS     EEEEEEEE

    data_table, keywords, cosmetics, plot_name, print_string = read_input(
        filename,
        save_list,
        keys_list,
        keys,
        cosmetics_list,
        print_string
    )

    if "devcolour" not in cosmetics.keys():
        if "bar" in keywords["plot"]:
            if "legend" not in cosmetics.keys():
                cosmetics["legend"] = ""

            if len(cosmetics["legend"].split(";")) <= 4:
                cosmetics["devcolour"] = update_default_bar_colours(legends=cosmetics["legend"].split(";"))

        elif "dev" in keywords["plot"]:
            if "legend" not in cosmetics.keys():
                ref = ""
                for i in keywords["deviation"]:
                    if i not in ("scatter", "ref", "type"):
                        ref += i+";"

                cosmetics["legend"] = ref[:-1]  # Remove the trailing ";"

            if sum([i not in ("scatter", "ref", "type") for i in keywords["deviation"]]) <= 4:
                cosmetics["devcolour"] = update_default_bar_colours(legends=cosmetics["legend"].split(";"))

    """
    if "bar" in keywords["plot"]:
        if "devcolour" not in cosmetics.keys():
            if "legend" not in cosmetics.keys():
                cosmetics["legend"] = ""
                cosmetics["devcolour"] = update_default_bar_colours(legends=cosmetics["legend"].split(";"))

            elif len(cosmetics["legend"].split(";")) <= 4:
                cosmetics["devcolour"] = update_default_bar_colours(legends=cosmetics["legend"].split(";"))

    elif "dev" in keywords["plot"]:
        if "devcolour" not in cosmetics.keys():
            if "legend" not in cosmetics.keys():
                ref = ""
                for i in keywords["deviation"]:
                    if i not in ("scatter", "ref"):
                        ref += i+";"

                cosmetics["legend"] = ref[:-1]

            if sum([i != "scatter" and i != "ref" for i in keywords["deviation"]]) <= 4:
                cosmetics["devcolour"] = update_default_bar_colours(legends=cosmetics["legend"].split(";"))
    """

    # Input default values

    cosmetics, keywords, gridbool, print_fit, figsize, legloc, print_string = add_defaults(
        cosmetics,
        cosmetic_defaults,
        cosmetics_list,
        keywords,
        keys_default,
        keys_list,
        hatch_list,
        print_string
    )

    ref = keywords["ref"]       # put the reference column in a variable for easy use in arrays

    # Sanitate data for bad reference values - only if fractional deviations are to be made

    if keywords["frac"]:
        data_backup = np.array(data_table)
        data_table, print_string = sanitate_data(
            data_table,
            keywords["ref"],
            output_name,
            print_string
        )
    else:
        data_table = np.array(data_table)

    # Print all parameters to output (that way, it is clear exactly which keywords exist, and which values have been used)
    print_string += "Used parameters".center(len(sep2))
    print_string += f"\n{sep2}".ljust(len(sep2))
    print_string += "routecard:\n"
    # for key in sorted(list(keywords.keys())):
    for key in sorted(keys_list):
        if type(keywords[key]) == type(keys_list):
            if len(keywords[key]) == 1:
                print_string += "\t{0:<20} {1}\n".format(key, keywords[key][0])
            elif len(keywords[key]) > 1:
                print_string += "\t{0:<20} ".format(key)
                for i in np.arange(len(keywords[key])):
                    if i == len(keywords[key])-1:
                        print_string += f"{keywords[key][i]}\n"
                    else:
                        print_string += f"{keywords[key][i]}, "
            else:
                continue
        else:
            print_string += "\t{0:<20} {1}\n".format(key, keywords[key])

    print_string += "\n\ntitlecard:\n"
    # for key in cosmetics:
    for key in sorted(cosmetics_list):
        if (key == "devpattern") and cosmetics[key] == "on":
            print_string += "\t{0:<20} {1}\t\t\"".format(key, cosmetics[key])
            for i, hat in enumerate(cosmetics[key]):
                if not i == len(cosmetics[key]) - 1:
                    print_string += "{0};".format(hat)
                else:
                    print_string += "{0}\"\n".format(hat)
        else:
            print_string += "\t{0:<20} {1}\n".format(key, cosmetics[key])
    print_string += sep

    data_table = rearrange_table(data_table, ref)

    # PPPPPPP   L           OOOO    TTTTTTTT
    # P      P  L         OO    OO     TT
    # P      P  L         O      O     TT
    # PPPPPPP   L         O      O     TT
    # P         L         O      O     TT
    # P         L         O      O     TT
    # P         L         O      O     TT
    # P         L         OO    OO     TT
    # P         LLLLLLLL    OOOO       TT

    if "plot" in keywords.keys():
        spac, dec = cosmetics["outdec"] + 5, cosmetics["outdec"]
        format_dict = {"spac": spac, "dec": dec, "sep2": sep2, "figsize": figsize, "legloc": legloc, "print_fit": print_fit}
        bool_dict = {"gridbool": gridbool, "diagonal": cosmetics["diagonal"], "show_legend": cosmetics["show_legend"]}

        if "scatter" in keywords["plot"]:
            print_string += "Scatter plot".center(len(format_dict["sep2"]))
            print_string += f"\n{format_dict['sep2']}".ljust(len(format_dict["sep2"]))
            fig, ax, print_string = plot_scatter(
                data_table,
                keywords,
                cosmetics,
                print_string,
                format_dict,
                bool_dict,
                plot_name
            )
            fig.patch.set_facecolor(cosmetics["background"])
            ax.set_facecolor(cosmetics["background"])

        if "dev" in keywords["plot"]:
            print_string += "Deviations".center(len(sep2))
            print_string += f"\n{sep2}".ljust(len(sep2))
            fig, ax, print_string = plot_dev(
                data_table,
                keywords,
                cosmetics,
                print_string,
                format_dict,
                bool_dict,
                plot_name,
                output_name
            )
            fig.patch.set_facecolor(cosmetics["background"])
            for a in list(ax):
                a.set_facecolor(cosmetics["background"])

        if "bar" in keywords["plot"]:
            print_string += "Pre-calculated bar plots".center(len(sep2))
            print_string += f"\n{sep2}".ljust(len(sep2))
            print_string += "This bar plot is made directly as a bar plot of the input data.\n" \
                            "The user is therefore responsible for the quality of the calculations.\n\n"
            fig, ax, print_string = plot_bars(
                data_table,
                keywords,
                cosmetics,
                print_string,
                format_dict,
                bool_dict,
                plot_name
            )
            fig.patch.set_facecolor(cosmetics["background"])
            ax.set_facecolor(cosmetics["background"])

    # for name in plot_name:
        # name, ext = name.split(sep='.')
        # plt.savefig(f"{name}.{ext}", dpi=cosmetics["dpi"])
    #     plt.savefig(name, dpi=cosmetics["dpi"])

    print_string += sep
    print_string += "Printing content of input file:\n\n"

    with open(filename, 'r') as inFile:
        for line in inFile:
            print_string += f"{line}"

    print_string += sep

    print_string += "\n\n\nExiting PlotPro. Have a nice day :)"

    with open(output_name, 'w') as outFile:
        outFile.write(print_string)

if boolsuppress:
    print("Output figures have been suppressed by the '--suppress' argument")
else:
    plt.show()


"""
Main Functon that initializes the User Interface class to run the chess
Game on pygame
"""
import pygame
from board import ChessBoard
from userInterface import UserInterface
if __name__ == "__main__":
    pygame.init()
    surface = pygame.display.set_mode([600, 600], 0, 0)
    pygame.display.set_caption('pyChess')
    Board = ChessBoard()
    UI = UserInterface(surface, Board)
    UI.playGame()
    pygame.quit()


"""
This script will add a software to a server.
Unlike the server to OS server, it will not remove any existing connection.
"""
import argparse
import logging
import sys
from lib import my_env
from lib import murcsstore
from lib import murcsrest

if __name__ == "__main__":
    # Configure command line arguments
    parser = argparse.ArgumentParser(
        description="Connect a server to software (database)"
    )
    parser.add_argument('-s', '--hostName', type=str, required=True,
                        help='Please provide hostName to identify the server.')
    parser.add_argument('-o', '--softId', type=str, required=True,
                        help='Please provide softId of the software to add.')
    parser.add_argument('-i', '--instance', type=str, required=False,
                        help='Optionally provide the instance schema. If schema used, then | is delimiter')
    args = parser.parse_args()
    cfg = my_env.init_env("bellavista", __file__)
    mdb = murcsstore.Murcs(cfg)
    r = murcsrest.MurcsRest(cfg)
    logging.info("Arguments: {a}".format(a=args))

    # Get server record
    hostName = args.hostName
    server_rec = mdb.get_server(hostName)
    if not server_rec:
        sys.exit("Server {h} not found.".format(h=hostName))
    serverId = server_rec["serverId"]

    # Get SW record, to know the softSubType. This will be used for instType attribute from SWInstance
    soft_rec = mdb.get_soft(args.softId)
    instType = soft_rec["softSubType"]

    # Then add requested OS
    params = dict(
        instType=instType
    )
    if args.instance:
        params["instSubType"] = args.instance
    r.add_softInst_calc(args.softId, serverId, **params)
    mdb.close()


from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from redis import asyncio as aioredis
from auth.base_config import auth_backend, fastapi_users
from auth.schemas import UserRead, UserCreate
from config import REDIS_HOST, REDIS_PORT
from operations.router import router as router_operation
from tasks.router import router as router_tasks
from pages.router import router as router_pages
from chat.router import router as router_chat

app = FastAPI(
    title="Trading App"
)

app.mount("/static", StaticFiles(directory="static"), name="static")

app.include_router(
    fastapi_users.get_auth_router(auth_backend),
    prefix="/auth",
    tags=["Auth"],
)

app.include_router(
    fastapi_users.get_register_router(UserRead, UserCreate),
    prefix="/auth",
    tags=["Auth"],
)

app.include_router(router_operation)
app.include_router(router_tasks)
app.include_router(router_pages)
app.include_router(router_chat)

async def startup_event():
    redis = aioredis.from_url(
        f"redis://{REDIS_HOST}:{REDIS_PORT}", encoding="utf8", decode_responses=True)
    FastAPICache.init(RedisBackend(redis), prefix="fastapi-cache")

origins = [
    "http://localhost:3000",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["GET", "POST", "OPTIONS", "DELETE", "PATCH", "PUT"],
    allow_headers=["Content-Type", "Set-Cookie", "Access-Control-Allow-Headers", "Access-Control-Allow-Origin",
                   "Authorization"],
)

# Регистрируем событие запуска приложения
app.add_event_handler("startup", startup_event)


from src.parsers.parser import Parser
from src.dependency_parse import DependencyParse
import spacy
from spacy.tokens import Doc

class SpacyParser(Parser):

    def __init__(self, model_name: str):
        self.model = spacy.load(model_name)

    def parse(self,sentence: str, tokens: list): #-> DependencyParse:
        """Use the specified spaCy model to parse the sentence.py.

        The function should return the parse in the Dependency format.

        You should refer to the spaCy documentation for how to use the model for dependency parsing.
        """
        custom_tokenize = Doc(self.model.vocab,tokens)
        spacy_op = self.model(custom_tokenize)
        heads = []
        deps = []
        for token in spacy_op:
            head_id = tokens.index(token.head.text)+1
            token_dep = token.dep_
            if token_dep=="ROOT":
                token_dep = "root"
                head_id = 0
            deps.append(token_dep)
            heads.append(str(head_id))
        return DependencyParse(sentence,tokens,heads,deps)


import pandas as pd
import os
from get_dataframe import get_dataframe
from get_question_type import check
from matplotlib import pyplot as plt
import numpy as np

if __name__ == '__main__':
    directory = '../csv/'
    width = 0.2
    counter = 0

    files = ['EARL_question_wise_NEW_MODEL_lcquad.csv', 'FALCON_question_wise_lcquad.csv',
             'EARL_question_wise_NEW_MODEL_qald.csv', 'FALCON_question_wise_qald.csv']

    for file in files:
        counter += 1
        filename = os.fsdecode(file)
        if ('EARL' in filename):
            full_file = os.path.join(directory, filename)
            df_EARL = get_dataframe(full_file)
            df_EARL.dropna(inplace=True)
            df_EARL['question_type'] = df_EARL.apply(lambda row: check(row['params.question'], row['params.query_db']),
                                                     axis=1)
            avg_EARL = df_EARL.groupby('question_type').mean()
            count_df = df_EARL.groupby('question_type')['params.question'].count()
            avg_EARL = avg_EARL[['metrics.precision', 'metrics.recall', 'metrics.f1']]

        if ('FALCON' in filename):
            full_file = os.path.join(directory, filename)
            df_FALCON = get_dataframe(full_file)
            df_FALCON.dropna(inplace=True)
            df_FALCON['question_type'] = df_FALCON.apply(lambda row: check(row['params.question'], row['params.query_db']),
                                                     axis=1)
            avg_FACLON = df_FALCON.groupby('question_type').mean()
            count_df = df_FALCON.groupby('question_type')['params.question'].count()
            avg_FACLON = avg_FACLON[['metrics.precision', 'metrics.recall', 'metrics.f1']]

        if counter % 2 == 0:
            x = np.arange(avg_EARL.shape[0])
            fig = plt.figure(figsize=(10, 8))
            ax1 = fig.add_subplot(111)
            ax2 = ax1.twiny()
            ax1.bar(x-0.5*width, avg_EARL['metrics.f1'], width, color='cyan')
            ax1.bar(x+0.5*width, avg_FACLON['metrics.f1'], width, color='green')
            ax1.set_xticks(x, avg_EARL.index)
            ax1.set_xlabel(r"Fragetypen", fontsize=18)
            ax1.set_ylabel('F1-Score', fontsize=18)
            ax1.legend(['EARL', 'FALCON'], fontsize=18)
            if 'lcquad' in filename:
                title_name = 'LC-QuAD 1.0'
            if 'qald' in filename:
                title_name = 'QALD 9'
            # ax1.set_title(f'Vergleich Performance der Systeme für verschiedene \nFragetypen auf {title_name}')
            ax1.set_ylim(0,1)
            ax2.set_xlim(ax1.get_xlim())
            ax2.set_xticks(x, count_df)
            ax2.set_xticklabels(count_df)
            ax2.set_xlabel(r"Anzahl Fragetypen", fontsize=18)
            # ax2.legend(fontsize=18)
            ax1.tick_params(labelsize=18)
            ax2.tick_params(labelsize=18)
            plt.savefig(f'../bar plots/{title_name}.png')
            plt.close()


import torch.nn as nn

def _real_init_weights(m, nonlinearity='relu'):
    if isinstance(m, list):
        for mini_m in m:
            _real_init_weights(mini_m)
    else:
        if isinstance(m, nn.Conv2d):
            # print('initializing Convolution layer...')
            nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity=nonlinearity)
            if m.bias is not None:
                nn.init.zeros_(m.bias)
        elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm, nn.InstanceNorm2d)):
            # print('initializing BN layer...')
            nn.init.ones_(m.weight)
            if m.bias is not None:
                nn.init.zeros_(m.bias)
        elif isinstance(m, nn.Linear):
            # print('initializing Linear layer...')
            nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity=nonlinearity)
            if m.bias is not None:
                nn.init.zeros_(m.bias)
        elif isinstance(m, nn.Module):
            for mini_m in m.children():
                _real_init_weights(mini_m)
        else:
            raise NotImplementedError('Unknown init module.')

def init_weights(*models, nonlinearity='relu'):
    """
    Initialize model's modules.
    """
    print('initializing modules...')
    for model in models:
        _real_init_weights(model, nonlinearity=nonlinearity)


import json
from pathlib import Path

import click
from tqdm import tqdm

from aspects.data_io.parsers import parse_gzip
from aspects.utilities.settings import AMAZON_REVIEWS_DATASETS_PATH

@click.command()
@click.option('--dataset-path', required=False, type=str, help='Path to the amazon domain gz file')
@click.option('--column', required=False, type=str, default='reviewText')
@click.option('--n-reviews', required=False, type=int, default=None)
def amazon_domain_gz_to_json(dataset_path, column='reviewText', n_reviews: int = None):
    reviews = {}
    dataset_name = Path(dataset_path).name.replace('.gz', '')
    json_output = AMAZON_REVIEWS_DATASETS_PATH / dataset_name
    for idx, d in tqdm(enumerate(parse_gzip(dataset_path)), desc=f'JSON is saving to: {json_output.as_posix()}'):
        reviews[idx] = d[column]
        if n_reviews is not None and idx > n_reviews:
            break
    with open(json_output.as_posix(), 'w') as j:
        json.dump(reviews, j)

if __name__ == '__main__':
    amazon_domain_gz_to_json()


# -*- coding: utf-8 -*-
from collections import OrderedDict

import django_filters
from django.db import transaction
from rest_framework import serializers

from ralph.api import RalphAPISerializer, RalphAPIViewSet, router
from ralph.api.serializers import RalphAPISaveSerializer
from ralph.networks.models.networks import IPAddress
from ralph.security.models import any_exceeded, SecurityScan, Vulnerability

class VulnerabilitySerializer(RalphAPISerializer):

    class Meta:
        model = Vulnerability
        depth = 1

class VulnerabilityViewSet(RalphAPIViewSet):
    queryset = Vulnerability.objects.all()
    serializer_class = VulnerabilitySerializer
    filter_fields = [
        'external_vulnerability_id',
    ]

class SecurityScanSerializer(RalphAPISerializer):
    vulnerabilities = VulnerabilitySerializer(many=True)

    class Meta:
        model = SecurityScan

class SaveSecurityScanSerializer(RalphAPISaveSerializer):

    class Meta:
        model = SecurityScan

    def to_internal_value(self, data):
        errors = OrderedDict()

        # external_id to local_id
        if 'external_vulnerabilities' in data:
            external_ids = set(data.get('external_vulnerabilities', []))
            converted = Vulnerability.objects.filter(
                external_vulnerability_id__in=external_ids)
            if len(converted) != len(external_ids):
                unknown = external_ids - set(
                    [str(v.external_vulnerability_id) for v in converted]
                )
                msg = "Unknow external_vulnerabilities: {}".format(
                    ', '.join(unknown)
                )
                errors['external_vulnerability'] = msg
            merged_vulnerabilities = data.get('vulnerabilities', [])
            merged_vulnerabilities.extend([c.id for c in converted])
            data['vulnerabilities'] = merged_vulnerabilities

        host_ip = data.get('host_ip', None)
        if host_ip:
            base_object = None
            # try to get base object by IPAddress
            try:
                ip_address = IPAddress.objects.get(address=host_ip)
            except IPAddress.DoesNotExist:
                pass
            else:
                base_object = ip_address.base_object
            if not base_object:
                errors['host_ip'] = "IP is not assigned to any host"
        else:
            errors['host_ip'] = "Host IP is required"

        if errors:
            raise serializers.ValidationError(errors)
        data['base_object'] = base_object.pk
        data['is_patched'] = not any_exceeded(
            Vulnerability.objects.filter(id__in=data['vulnerabilities'])
        )
        result = super().to_internal_value(data)
        return result

class IPFilter(django_filters.FilterSet):
    ip = django_filters.CharFilter(
        name='base_object__ethernet_set__ipaddress__address'
    )

class SecurityScanViewSet(RalphAPIViewSet):
    queryset = SecurityScan.objects.all()
    serializer_class = SecurityScanSerializer
    save_serializer_class = SaveSecurityScanSerializer

    additional_filter_class = IPFilter

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        ip = IPAddress.objects.filter(address=self.request.data.get(
            'host_ip', None)
        ).first()
        if ip:
            # one scan can exist for ip (because there are linked by onetoone)
            # so this removes old scan to allow updates by post
            SecurityScan.objects.filter(base_object=ip.base_object.id).delete()
        return super().create(request, *args, **kwargs)

router.register(r'vulnerabilities', VulnerabilityViewSet)
router.register(r'security-scans', SecurityScanViewSet)
urlpatterns = []


import logging
import os.path

formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')

class Logger:
    __logger = None
    __logging = None
    __error_logging = None

    @staticmethod
    def get_instance():

        if Logger.__logger is None:
            Logger()
        return Logger.__logger

    def __init__(self):

        if Logger.__logger is not None:
            raise Exception("Unauthorized access to Logger constructor")
        else:
            Logger.__logger = self

    @staticmethod
    def start_logger(log_file_path=os.path.dirname(__file__) + "\\LogFiles\\Event_Log.txt",
                     error_file_path=os.path.dirname(__file__) + "\\LogFiles\\Error_Log.txt"):
        # logging.basicConfig(filename=log_file_path, format=formatter)
        handler = logging.FileHandler(log_file_path)
        handler.setFormatter(formatter)
        Logger.__logging = logging.getLogger('main')
        Logger.__logging.setLevel(logging.DEBUG)
        Logger.__logging.addHandler(handler)

        handler = logging.FileHandler(error_file_path)
        handler.setFormatter(formatter)
        Logger.__error_logging = logging.getLogger('error_log')
        Logger.__error_logging.setLevel(logging.DEBUG)
        Logger.__error_logging.addHandler(handler)

    """ Adds a information log to the log file with the given message"""

    @staticmethod
    def info_log(message: str):
        if Logger.__logging is None:
            raise Exception('Logger not initiated')
        Logger.__logging.info('Info: ' + message)

    """ Adds a warning log to the log file with the given message"""

    @staticmethod
    def warning_log(message: str):
        if Logger.__logging is None:
            raise Exception('Logger not initiated')
        Logger.__error_logging.warning('Warning: ' + message)

    """ Adds a error log to the log file with the given message"""

    @staticmethod
    def error_log(message: str):
        if Logger.__logging is None:
            raise Exception('Logger not initiated')
        Logger.__error_logging.error('Error: ' + message)

    """ Adds a critical event log to the log file with the given message"""

    @staticmethod
    def critical_log(message: str):
        if Logger.__logging is None:
            raise Exception('Logger not initiated')
        Logger.__error_logging.critical('Critical: ' + message)


# Pacakge Imports
from utils import *
import importlib
import utils
importlib.reload(utils)
import os.path
from os import path
import matplotlib.pyplot as plt
import math
import pandas as pd

class Visualization :
    def __init__(self) :
        """ Constructor. Creates a path to the Maxtrix Asset file for visualization functions to use. """

        file_path = pathlib.Path().absolute().joinpath('../QGIS/MileMarker/Matrix Files')
        self.file_name = file_path.joinpath('total_asset_matrix.csv')

    def plot_graph(self, start_loc, end_loc) :
        """ Creates a visual representation graph of all assets on the highway.

        Args :
            start_loc : Starting point of the graph. Any number from 0 ~ 30.
            end_loc : Ending point of the graph. Any number from 0 ~ 30.
        """
        df = read_data(self.file_name, start_loc, end_loc)

        fig, ax = plt.subplots(figsize=(15,2))
        plt.xlim(start_loc + 52, end_loc + 52)
        plt.ylim(0, 120)
        ax.set_facecolor('grey')
        ax.axhline(y=60, color='yellow')

        rds_x, rds_y = get_asset_xy_coords(df, 'rds')
        dms_x, dms_y = get_asset_xy_coords(df, 'dms')
        cctv_x, cctv_y = get_asset_xy_coords(df, 'cctv')
        rds = plt.scatter(rds_x, rds_y, color='red', label='RDS')
        dms = plt.scatter(dms_x, dms_y, color='green', label='DMS')
        cctv = plt.scatter(cctv_x, cctv_y, color='yellow', label='CCTV')

        plt.title(f'Assets from Miles {start_loc+52} to {end_loc+52}', fontdict={'fontsize':'large','fontweight':'bold'}, pad=20)
        plt.legend(loc='upper center', bbox_to_anchor=(1, 1.55), fancybox=True, shadow=True, ncol=1)
        plt.xlabel('Miles')
        plt.ylabel('ft')
        plt.savefig('../Output Graphs/asset_graph.jpg', bbox_inches='tight')

def read_data(file_name, start_loc, end_loc) :
    """ Reads the Matrix CSV file and querys only the assets that are within the given range.

    Args :
        file_name : The location / name of the Matrix CSV file.
        start_loc : Starting point of the query. Any number from 0 ~ 30.
        end_loc : Ending point of the query. Any number from 0 ~ 30.

    Return :
        The queryed DataFrame.
    """
    df = pd.read_csv(file_name, skiprows=0, error_bad_lines=False, index_col=False)
    df = df.query('Direction != "other"')
    df = df.loc[df['Milemarker Number'] >= (start_loc + 52.0)]
    df = df.loc[df['Milemarker Number'] <= (end_loc + 52.0)]
    df = df.reset_index(drop = True)

    return df

def findYVal(direction) :
    """ Helper function that acts like a dictionary to find the Y value of an asset depedning on
    its direction.

    Args :
        direction : One of three possible placements on the highway : east, center, or west.

    Return :
        The corresponding Y coordinate value of the asset.
    """
    if(direction == 'east') :
        return 10;
    if(direction == 'center') :
        return 60;
    if(direction == 'west') :
        return 110;

def get_asset_xy_coords(df, asset_type) :
    """ From the total DataFrame, chooses one type of asset and saves its x,y coordinates into
    a list for plotting purposes.

    Args :
        df : Total DataFrame.
        asset_type : The type of asset that we wish to obtain the coordinate from.

    Return :
        2 lists : first contains the X coordinates of the assets, second contains Y coordinates.
    """
    df = df[df.Type == asset_type]
    df = df.reset_index(drop = True)

    xcoord, ycoord = [], []

    for i in range(len(df)) :
        xcoord.append(df.at[i, 'Milemarker Number'])
        ycoord.append(findYVal(df.at[i, 'Direction']))

    return xcoord, ycoord


import os
import json
THIS_FILE = os.path.dirname(os.path.abspath(__file__))
PROJ_FILE = os.path.abspath(os.path.join(THIS_FILE, "../"))
db_path = PROJ_FILE + '/commentry/db.json'
class GetComment:
    def __init__(self) -> None:
        pass
    def checkdb_commentry(self):
        f = open(db_path,'r')
        l = json.load(f)
        f.close()
        if l["1"] == []:
            return 0
        else:
            path = l["1"][0]
            l["1"].remove(l["1"][0])
            f = open(db_path,'w')
            json.dump(l,f)
            f.close()
            return  1,path
f = GetComment()
print(f.checkdb_commentry())


import django
# from django.conf import settings
# from django.contrib.auth import get_user_model
# from django.http import request
from django.shortcuts import render
from django.urls import reverse_lazy

from .models import Patient, RadStaff, RadioUser
from django.views import View
from django.contrib.auth.decorators import login_required
from django.views.generic.base import TemplateView
from django.views.generic.list import ListView
from django.views.generic.edit import FormView, CreateView
from django.contrib.auth.mixins import LoginRequiredMixin

# Create your views here.
'''
class RadioWelcomeView(LoginRequiredMixin, View):
    login_url = reverse_lazy('authentication:login')
    allRadUser = RadioUser.objects.all().order_by('username_id')
    first = allRadUser[0]
    second = allRadUser[1]
    last = allRadUser.last()
    # firstRadUser = RadioUser.objects.all().order_by('username_id').first()
    # radUserUsername = radUser.username
    if user == first or user == second or user == last:

        def get(self, request):
            context = {
                "title": 'Medical Radiology Department',
                "page_title": 'Welcome to "RADIOLOGY"'
            }
            return render(request, "radio/radio_welcome.html", context)

    else:
        def get(self, request):
            context = {
                "title": 'Medical Radiology Department',
                "page_title": 'Welcome to "RADIOLOGY"'
            }
            return render(request, "root/welcome.html", context) '''

def regUserList(request):
    allUser = RadioUser.objects.all().order_by('username_id')
    user = request.user
    if user in allUser:
        return True
    else:
        return False

@login_required(login_url="/login/")
def radioWelcomeView(request):
    check = regUserList(request)
    if check == True:
        print("logged in")
        context = {
            "title": 'Medical Radiology Department',
            "page_title": 'Welcome to "RADIOLOGY"'
        }
        return render(request, 'radio/radio_welcome.html', context)
    else:
        print("Not Department User")
        return render(request, 'root/welcome.html')

class EchoHomeView(View):

    def get(self, request):
        context = {
            "title": 'Ultrasound',
            'page_title': 'ULTRASOUND',
            'subtitle': 'HOME PAGE',
            # "short_title": 'RH'
        }
        return render(request, 'echo/echo_home.html', context)

class XrayHomeView(View):

    def get(self, request):
        context = {
            "title": 'XRAY',
            # "short_title": 'PH',
            'page_title': 'XRAY',
            'subtitle': 'HOME PAGE',
        }
        return render(request, 'xray/xray_home.html', context)


# we will change the BGR value using a trackbar
import numpy as np
import cv2 as cv

'''
def nothing(x):
    # x is the value of current position of trackbar
    print(x)

# create a black image, a window
img = np.zeros((300, 512, 3), np.uint8)
cv2.namedWindow('image')

# create a trackbar which will change B channel
cv2.createTrackbar('B', 'image', 0, 255, nothing)
cv2.createTrackbar('G', 'image', 0, 255, nothing)
cv2.createTrackbar('R', 'image', 0, 255, nothing)

# create a switch trackbar
switch = '0: OFF\n 1:ON'
cv2.createTrackbar(switch, 'image', 0, 1, nothing)

while (1):
    cv2.imshow('image', img)
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break

    # get the initial trackbar values
    b = cv2.getTrackbarPos('B', 'image')
    g = cv2.getTrackbarPos('G', 'image')
    r = cv2.getTrackbarPos('R', 'image')
    s = cv2.getTrackbarPos(switch, 'image')

    # use switch to control the BGR trackbar
    if s == 0:
        img[:] = 0  # nothing will change in image
    else:
        img[:] = [b, g, r]

cv2.destroyAllWindows()

'''

def nothing(x):
    print(x)

# Create a black image, a window
cv.namedWindow('image')

cv.createTrackbar('CP', 'image', 10, 400, nothing)

switch = 'color/gray'
cv.createTrackbar(switch, 'image', 0, 1, nothing)

while (1):
    img = cv.imread('lena.jpg')
    pos = cv.getTrackbarPos('CP', 'image')
    font = cv.FONT_HERSHEY_SIMPLEX
    cv.putText(img, str(pos), (50, 150), font, 6, (0, 0, 255), 10)

    k = cv.waitKey(1) & 0xFF
    if k == 27:
        break

    s = cv.getTrackbarPos(switch, 'image')

    if s == 0:
        pass
    else:
        img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    img = cv.imshow('image', img)

cv.destroyAllWindows()


from pathlib import Path

from linebot import LineBotApi
from linebot.models import RichMenu, RichMenuArea, RichMenuBounds, RichMenuSize
from linebot.models.actions import PostbackAction, URIAction

from kb_2315.config import conf

line_bot_api = LineBotApi(conf.line_channel_access_token)

def create_rich_menu() -> None:
    cal_url = (
        "https://larrybolt.github.io/online-ics-feed-viewer/"
        + f"#feed={conf.host_url}/api/calendar/"
        + "&cors=false&title=Shoe%20History&hideinput=true"
    )

    rich_menu_to_create = RichMenu(
        size=RichMenuSize(width=1200, height=800),
        selected=True,
        name="richmenu",
        chat_bar_text="メニュー",
        areas=[
            # カレンダー
            RichMenuArea(
                bounds=RichMenuBounds(x=0, y=0, width=600, height=800),
                action=URIAction(
                    uri=cal_url,
                    label="カレンダーの表示",
                ),
            ),
            # データ
            RichMenuArea(
                bounds=RichMenuBounds(x=600, y=0, width=600, height=400),
                action=URIAction(uri=f"{conf.host_url}/analyze/", label="データの表示"),
            ),
            # 靴一覧
            RichMenuArea(
                bounds=RichMenuBounds(x=600, y=400, width=600, height=400),
                action=PostbackAction(data="shoes_list:"),
            ),
        ],
    )

    richMenuId = line_bot_api.create_rich_menu(rich_menu=rich_menu_to_create)

    with open(Path(__file__).parent / "image/menu.png", "rb") as f:
        line_bot_api.set_rich_menu_image(richMenuId, "image/png", f)

    line_bot_api.set_default_rich_menu(richMenuId)


from sqlalchemy import Column, ForeignKey, Integer, BigInteger, DateTime, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func

Base = declarative_base()

class Wallet(Base):
    __tablename__ = 'wallets'

    id = Column(Integer, primary_key=True)
    balance = Column(BigInteger)

class Refill(Base):
    __tablename__ = 'refills'

    id = Column(Integer, primary_key=True)
    wallet_id = Column(Integer, ForeignKey('wallets.id'))
    amount = Column(BigInteger)
    datetime = Column(DateTime, server_default=func.now())

class Transaction(Base):
    __tablename__ = 'transactions'

    id = Column(Integer, primary_key=True)
    wallet_id = Column(Integer, ForeignKey('wallets.id'))
    amount = Column(BigInteger)
    datetime = Column(DateTime, server_default=func.now())
    ip = Column(String)


#Source: https://stackoverflow.com/questions/31940285/plot-a-polar-color-wheel-based-on-a-colormap-using-python-matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
import matplotlib as mpl

fig = plt.figure(figsize=(10.24,10.24))

display_axes = fig.add_axes([0.01,0.01,0.98,0.98], projection='polar')
display_axes._direction = 2*np.pi ## This is a nasty hack - using the hidden field to
                                  ## multiply the values such that 1 become 2*pi
                                  ## this field is supposed to take values 1 or -1 only!!

norm = mpl.colors.Normalize(0.0, 2*np.pi)

# Plot the colorbar onto the polar axis
# note - use orientation horizontal so that the gradient goes around
# the wheel rather than centre out
quant_steps = 2048
cb = mpl.colorbar.ColorbarBase(display_axes, cmap=cm.get_cmap('hsv',quant_steps),
    norm=norm, orientation='horizontal')

# aesthetics - get rid of border and axis labels
cb.outline.set_visible(False)
display_axes.set_axis_off()

#plt.show()
plt.savefig('color-wheel.png', transparent=True)
display_axes.set_rlim([-20,1]) # radius limit [min,max]: ring thickness = max/(-min)
plt.savefig('color-ring.png', transparent=True)


import csv
from matplotlib import pyplot as plt
from datetime import datetime

# Pull precip values from file.
filename = 'tucson_tia_precip_2019.csv'

with open(filename) as file:
    reader = csv.reader(file)
    header_row = next(reader)

    precipitation, dates = [], []
    for row in reader:
        current_date = datetime.strptime(row[2], "%m/%d/%Y")
        dates.append(current_date)

        value = float(row[3])
        precipitation.append(value)

# Plot data.
fig = plt.figure(dpi=128, figsize=(10, 4))
plt.plot(dates, precipitation, c='blue', alpha=0.7)
plt.fill_between(dates, precipitation, 0, facecolor="blue", alpha=0.5)

# Format plot.
plt.title('Precipitation totals, Tucson 2019', fontsize=18)
plt.xlabel('', fontsize=12)
fig.autofmt_xdate()
plt.ylabel('Precipitation (inches)', fontsize=12)
plt.tick_params(axis='both', which='major', labelsize=12)

plt.savefig('tucson_precip_2019.png')

Project 2 - Data Visualization/Chapter 16 - Downloading Data/16-3 Rainfall.py


# -*- coding: utf-8 -*-
"""
Created on Thu Oct 26 13:39:38 2017

@author: Amira AYADI
"""
import os
import numpy as np
from math import *
from scipy.misc import imread
import matplotlib.pyplot as plt

img = imread('TP1.jpg')
plt.imshow(img, cmap='Greys_r')
transform = np.log(np.abs(np.fft.fft2(img))) # on prend le log que pour pouvoir voir l'image, en effet si on ne prend pas le log les valeurs seront trop grande et donc on ne verra rien
plt.imshow(transform, cmap='Greys_r' )

# Question 1 : ca donne la direction du texte

# Question 2 : creation d'une fonction descripteur

def descripteur(image):
    descripteur = []
    image = imread(image, mode ="L")
    # Trans de fourier
    image = np.abs(np.fft.fft2(image))
    shape_x = np.shape(image)[0]
    shape_y = np.shape(image)[1]
    pasdex = 3
    pasdey = 3*2
    liste_x = np.arange(0,int(shape_x/2),int(shape_x/pasdex))
    liste_y = np.arange(0,int(shape_y/2),int(shape_y/pasdey))
    # Creation descripteur
    for x in liste_x :
        for y in liste_y:
            bloc_energ=np.log(np.mean(image[x:x+int(shape_x/pasdex),y:y+int(shape_y/pasdey)]**2))
            descripteur.append(bloc_energ)
    return descripteur

# Question 3 :

def indexation(path):
    tot_descri = {}
    rep = os.listdir(path)
    for s in rep :
        #plt.imshow(image, cmap = 'Greys_r')
        image = path + s
        tot_descri[s] = descripteur(image)
    return tot_descri

path = "./BE/"
indexation(path)

def distance_manhattan(x,y):
    return sum(abs(a-b) for a,b in zip(x,y))

def image_plus_proche():
    liste=[]
    liste_nom=[]
    a_comparer = int(input(" Quelle est l'image que vous voulez comparer ? Veuillez entrer son numero \n"))
    path = "./BE/"
    if a_comparer in [1,2,3,4,5,6,7,8,9]:
        image_comp = path+"0"+str(a_comparer)+'.jpg'
    else:
        image_comp = path+str(a_comparer)+'.jpg'
    descripteur_image_comp = descripteur(image_comp)
    dico_descri = indexation(path)
    for index, key in dico_descri.items():
        liste.append(distance_manhattan(key,descripteur_image_comp))
        liste_nom.append(index)
    position=liste.index(0.0)
    del liste[position]
    del liste_nom[position]
    print("les images les plus proches sont : \n")
    for i in range(10):
        print(str(liste_nom[liste.index(min(liste))]))
        min_supp = liste.index(min(liste))
        del liste[min_supp]
        del liste_nom[min_supp]

image_plus_proche()


import pytest
import urllib

import numpy as np
from matplotlib import pyplot as plt

from wave_unify import WaveUnifyData
from freq_detect import FreqDetect
from note import NoteName, Note

show_plots = False
normalize_plots = True
plot_length = 5000

# region helper functions

def plot_show():
    if show_plots:
        plt.show()

def create_wav_files():
    file_links = {
        'sine1.wav': "https://www3.nd.edu/~dthain/courses/cse20211/fall2013/wavfile/sine.wav",
        'sine2.wav': "https://www3.nd.edu/~dthain/courses/cse20211/fall2013/wavfile/sine2.wav",
        'sine3.wav': "https://www3.nd.edu/~dthain/courses/cse20211/fall2013/wavfile/sine3.wav",
    }
    for name, link in file_links.items():
        # check if file exists,
        try:
            file = open(name)
        except IOError:
            file_exists = False
        else:
            file_exists = True
        finally:
            file.close()
        if not file_exists:
            urllib.request.urlretrieve(link, name)
    return file_links.keys()

def get_waves():
    files = create_wav_files()
    wave_dict = {}
    for file in files:
        wavdat = WaveUnifyData(file)
        wave_dict.update({file: wavdat})
    return wave_dict

def get_freqs():
    freq_dict ={}
    for name, wave in get_waves().items():
        freq_det = FreqDetect(wave.samples_mono, wave.sample_rate)
        freq_dict.update({name: freq_det})
    return freq_dict

def get_notes():
    notes_list = [
        {'freq': 440,    'note_name': NoteName.A, 'octave': 4, 'error': +0},
        {'freq': 8.1854, 'note_name': NoteName.C, 'octave':-1, 'error': +2},
        {'freq': 200,    'note_name': NoteName.G, 'octave': 3, 'error': +35},
        {'freq': 27.2,   'note_name': NoteName.A, 'octave': 0, 'error': -19},
    ]
    return notes_list

# endregion

# region fixtures

@pytest.fixture()
def wav_files():
    return create_wav_files()

@pytest.fixture()
def notes_list():
    return get_notes()

# endregion

# region tests

def test_plot_signals(wav_files):
    for filename in wav_files:
        fmi = WaveUnifyData(filename)
        fmi.end = plot_length
        plot_args = {
            'title': "Signal " + filename,
            'normalize': normalize_plots,
        }
        if fmi.mono:
            fmi.plot_mono(**plot_args)
        else:
            stereo_sum = fmi.stereo_sum
            signals = [
                fmi.stereo_diff,
                stereo_sum,
                np.diff(stereo_sum),
            ]
            fmi.plot_signals(
                signals,
                **plot_args,
            )
    plot_show()

def test_plot_fft(wav_files):
    for filename in wav_files:
        wave_i = WaveUnifyData(filename)
        fd1 = FreqDetect(wave_i.samples_mono, wave_i.sample_rate)
        fft_i = fd1.fft()
        fd1.plot_fft(
            fft_i,
            title="FFT "+filename,
            normalize=normalize_plots,
        )
    plot_show()

def test_notes(notes_list):
    # print("Frequency C0: ", Note._freq_note_0())
    assert Note._freq_note_0() == 440 * 2**(3/12) / 2**6
    octave_offset = 1  # offset from numeric octave to notation
    for note_i in notes_list:
        freq = note_i['freq']
        note = note_i['note_name']
        octv = note_i['octave']
        errv = note_i['error']
        name = str(note).split('.')[-1] + str(octv)
        str_expected = name
        if errv:
            str_expected += " %+d cent" % errv
        str_expected += " %.3f Hz" % freq
        # print("expected: ", str_expected)
        ref1 = Note(freq)
        note_num = note + (octv + octave_offset) * 12 + errv / 100
        ref2 = Note.create(note_num)
        for ref in (ref1, ref2):
            # print(ref)
            assert round(ref.num) == note + 12 * (octv + octave_offset)
            assert int(ref.octave) == octv + octave_offset
            assert ref.name == name, str_expected
            assert repr(ref) == str_expected

def test_note_detect(wav_files):
    for filename in wav_files:
        wav_i = WaveUnifyData(filename)
        fdi = FreqDetect(wav_i.samples_mono, wav_i.sample_rate)
        fft1 = fdi.fft()
        peaks = fdi.get_peaks(fft1, -20)
        for freq in peaks:
            root_note = Note(freq)
            print(filename, ": ", root_note)

# endregion

# region exports

files_list = list(create_wav_files())
file1 = files_list[0]

waves_dict = get_waves()
waves_list = list(waves_dict.values())
wave1 = waves_list[0]

freqs_dict = get_freqs()
freqs_list = list(freqs_dict.values())
freq1 = freqs_list[0]

# endregion

# region main

if __name__ == '__main__':
    show_plots = True
    normalize_plots = 2 ** 15
    plot_length = 5000

    pytest.main()


from contextlib import AsyncExitStack
from datetime import datetime

from google.protobuf.message import Message as ProtoBufMessage
from google.protobuf.struct_pb2 import Struct
from google.protobuf.timestamp_pb2 import Timestamp

from grpc_stubs.kafkacomms.producer_pb2 import SampleMsg
from producer.exceptions import NotSerialisable
from producer.kafka import KafkaProducer

BOOTSTRAP_SERVERS = ['127.0.0.1:9092']

def serialise(msg: ProtoBufMessage) -> bytes:
	""" Serialises a protobuf message """
	if not isinstance(msg, ProtoBufMessage):
		raise NotSerialisable()
	return msg.SerializeToString()

async def run() -> None:
	async with AsyncExitStack() as stack:

		# Create a Kafka producer client
		print(f"Running Kafka producer at: {BOOTSTRAP_SERVERS}")

		kafka_producer = await stack.enter_async_context(
			KafkaProducer(
				max_request_size=10000,
				bootstrap_servers=BOOTSTRAP_SERVERS,
				request_timeout_ms=10000,
			)
		)

		# Create a GRPC message
		msg_other_data = Struct()
		msg_other_data.update({
			'key_1': 'val_1',
			'key_2': 'val_2',
		})

		kafka_grpc_msg = SampleMsg(
			msg_no=1,
			msg_body='my text',
			msg_date=Timestamp(),
			msg_other_data=msg_other_data,
		)

		# Send the message to the Kafka broker
		await kafka_producer.send_and_wait(
			'my_topic',
			value=serialise(kafka_grpc_msg),
			key=bytes('my_key', 'utf-8'),
			headers=[
				('my_header_name', b'my_header_value')
			],
		)

		print(f"Sent message: {kafka_grpc_msg}")


from sqlalchemy.orm import Session
import models, schemas

# Diet Create Utility Function
def create_pet_diet(db: Session, diet: schemas.DietCreate, pet_id: int):
    db_diet = models.Diet(**diet.dict(), owner_id=pet_id)
    db.add(db_diet)
    db.commit()
    db.refresh(db_diet)
    return db_diet

# Diet READ utility functions
def get_diet(db: Session, diet_id: int, pet_id: int):
    return (
        db.query(models.Diet)
        .filter(models.Diet.owner_id == pet_id)
        .filter(models.Diet.id == diet_id)
        .first()
    )

# Diet DELETE utility functions
def delete_diet(db: Session, diet_id: int, pet_id: int):
    (
        db.query(models.Diet)
        .filter(models.Diet.owner_id == pet_id)
        .filter(models.Diet.id == diet_id)
        .delete(synchronize_session=False)
    )
    db.commit()

    return "Successfully Deleted"


import re
import struct
import pdg
import basf2
import pybasf2
import uproot

import numpy as np

def _bitwiseConversion(value, i='f', o='i'):
    """
    Bitwise conversion between to python types
    This is equivalently to
    union {
        Type_i i;
        Type_o o;
    } conversion;
    conversion.i = input;
    return conversion.o
    @param i input data type (e.g. f for float)
    @param o output data type (e.g. i for integer)
    """
    s = struct.pack('>' + i, value)
    return struct.unpack('>' + o, s)[0]

def _decayHashFloatToInt(decayHash, decayHashExtended):
    """
    Convert decayHash and decayHashExtended 32 bit floats to an 64 bit integer
    """
    decayHashInt = _bitwiseConversion(np.float32(decayHash))
    decayHashExtendedInt = _bitwiseConversion(np.float32(decayHashExtended))
    decayHashFullInt = decayHashInt << 32
    decayHashFullInt += decayHashExtendedInt
    return decayHashFullInt

class DecayHashMap:
    """
    DecayHashMap using the C++ implementation of DecayTree and DecayNode
    """

    def __init__(self, rootfile, removeRadiativeGammaFlag=False):
        """Constructor"""
        # Always avoid the top-level 'import ROOT'.
        import ROOT  # noqa
        with uproot.open(rootfile) as rf:
            trees = rf.keys()
            assert len(trees) == 1
            ntuple = rf[trees[0]].arrays(library='np')
        # self._removeGammaFlag = removeRadiativeGammaFlag
        #: Dict Int -> DecayStrings
        self._string = {}
        #: Dict Int -> Reconstructed DecayTree
        self._forest = {}
        for decayHash, decayHashExtended, decayString in zip(
                ntuple['decayHash'], ntuple['decayHashExtended'], ntuple['decayString']):
            decayInt = ROOT.Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)
            if decayInt in self._string:
                continue
            self._string[decayInt] = decayString
            self._forest[decayInt] = ROOT.Belle2.DecayForest(decayString, True, removeRadiativeGammaFlag)

    def get_string(self, decayHash, decayHashExtended):
        """
        Return DecayString given the decayHash and decayHashExtended
        @param decayHash output of extraInfo(decayHash)
        @param decayHashExtended output of extraInfo(decayHashExtended)
        """
        # Always avoid the top-level 'import ROOT'.
        import ROOT  # noqa
        return self._string[ROOT.Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)]

    def get_original_decay(self, decayHash, decayHashExtended):
        """
        Return original (MC) DecayTree given the decayHash and decayHashExtended
        @param decayHash output of extraInfo(decayHash)
        @param decayHashExtended output of extraInfo(decayHashExtended)
        """
        # Always avoid the top-level 'import ROOT'.
        import ROOT  # noqa
        return self._forest[ROOT.Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)].getOriginalTree()

    def get_reconstructed_decay(self, decayHash, decayHashExtended):
        """
        Return reconstructed DecayTree given the decayHash and decayHashExtended
        @param decayHash output of extraInfo(decayHash)
        @param decayHashExtended output of extraInfo(decayHashExtended)
        """
        # Always avoid the top-level 'import ROOT'.
        import ROOT  # noqa
        return self._forest[ROOT.Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)].getReconstructedTree()

    def print_hash(self, decayHash, decayHashExtended):
        """
        Print the DecayString in a fancy way given the decayHash and decayHashExtended
        @param decayHash output of extraInfo(decayHash)
        @param decayHashExtended output of extraInfo(decayHashExtended)
        """
        entry = self.get_string(decayHash, decayHashExtended)
        entries = entry.split('|')
        all_particles = re.findall(r"(-?[0-9]+)", entries[0])

        if len(all_particles) != len(entries) - 1:
            print(entry)
            raise RuntimeError("Bad format of decay string: " +
                               str(len(all_particles)) + " " + str(len(entries)) + " " + str(entries))

        table = []
        table.append(["Decay ", prettify_pdg_codes(entries[0])])
        for particle, mc_decay_string in zip(all_particles, entries[1:]):
            table.append([prettify_pdg_codes(particle), prettify_pdg_codes(mc_decay_string)])

        basf2.pretty_print_table(table, column_widths=[6, '*'])

def _pdg_to_name(x):
    """
    Convert PDG code to a name
    @param a pdg code
    """
    selected = False
    if x[0] == '^':
        selected = True
        x = x[1:]

    pdg_code = int(x)
    pdg_string = str(pdg_code)
    try:
        pdg_string = pdg.to_name(pdg_code)
    except BaseException:
        pass

    if selected:
        if pybasf2.LogPythonInterface.terminal_supports_colors():
            return '\x1b[31m' + pdg_string + '\x1b[0m'
        else:
            return '^' + pdg_string
    return pdg_string

def prettify_pdg_codes(text):
    """
    Prettifiy a string containing PDG codes by replacing PDG codes
    with their corresponding names.
    @param text the text
    """
    text = re.sub(r"(\^?-?[0-9]+)", lambda x: _pdg_to_name(x.group(0)), text)
    text = text.replace('gamma', 'g').replace('--> ', '').replace('anti-', 'a-')
    text = text.replace('Upsilon', 'Y').replace(') ', ')').replace(' (', '(')
    return text