class Solution:
    def minimumCost(self, cost: List[int]) -> int:
        cost.sort(reverse=True)
        payment, i, N = 0, 0, len(cost)

        while i < N:
            payment += sum(cost[i : i + 2])
            i += 3

        return payment

Biweekly Contest 70/2144. Minimum Cost of Buying Candies With Discount.py


# coding: utf-8

from datetime import date, datetime

from typing import List, Dict, Type

from openapi_server.models.base_model_ import Model
from openapi_server import util

class AssetReeferResponseReeferStatsEngineHours(Model):
    """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

    Do not edit the class manually.
    """

    def __init__(self, engine_hours: int=None, changed_at_ms: int=None):
        """AssetReeferResponseReeferStatsEngineHours - a model defined in OpenAPI

        :param engine_hours: The engine_hours of this AssetReeferResponseReeferStatsEngineHours.
        :param changed_at_ms: The changed_at_ms of this AssetReeferResponseReeferStatsEngineHours.
        """
        self.openapi_types = {
            'engine_hours': int,
            'changed_at_ms': int
        }

        self.attribute_map = {
            'engine_hours': 'engineHours',
            'changed_at_ms': 'changedAtMs'
        }

        self._engine_hours = engine_hours
        self._changed_at_ms = changed_at_ms

    @classmethod
    def from_dict(cls, dikt: dict) -> 'AssetReeferResponseReeferStatsEngineHours':
        """Returns the dict as a model

        :param dikt: A dict.
        :return: The AssetReeferResponse_reeferStats_engineHours of this AssetReeferResponseReeferStatsEngineHours.
        """
        return util.deserialize_model(dikt, cls)

    @property
    def engine_hours(self):
        """Gets the engine_hours of this AssetReeferResponseReeferStatsEngineHours.

        Engine hours of the reefer.

        :return: The engine_hours of this AssetReeferResponseReeferStatsEngineHours.
        :rtype: int
        """
        return self._engine_hours

    @engine_hours.setter
    def engine_hours(self, engine_hours):
        """Sets the engine_hours of this AssetReeferResponseReeferStatsEngineHours.

        Engine hours of the reefer.

        :param engine_hours: The engine_hours of this AssetReeferResponseReeferStatsEngineHours.
        :type engine_hours: int
        """

        self._engine_hours = engine_hours

    @property
    def changed_at_ms(self):
        """Gets the changed_at_ms of this AssetReeferResponseReeferStatsEngineHours.

        Timestamp in Unix milliseconds since epoch.

        :return: The changed_at_ms of this AssetReeferResponseReeferStatsEngineHours.
        :rtype: int
        """
        return self._changed_at_ms

    @changed_at_ms.setter
    def changed_at_ms(self, changed_at_ms):
        """Sets the changed_at_ms of this AssetReeferResponseReeferStatsEngineHours.

        Timestamp in Unix milliseconds since epoch.

        :param changed_at_ms: The changed_at_ms of this AssetReeferResponseReeferStatsEngineHours.
        :type changed_at_ms: int
        """

        self._changed_at_ms = changed_at_ms


import cv2
import numpy as np

import PIL
from PIL import Image, ImageOps
from PIL.ImageStat import Stat

from ggb.utils.constant import ColorSpace

def preprocessing(image, input_color=ColorSpace.RGB):
    """Preprocess source image.

    :param image: source image
    :param input_color: source image color space
    :return: preprocessed image
    """
    img = image
    if input_color == ColorSpace.BGR:
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = Image.fromarray(img)
    elif input_color == ColorSpace.HSV:
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)
        img = Image.fromarray(img)
    elif input_color == ColorSpace.YUV:
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_YUV2RGB)
        img = Image.fromarray(img)
    return img

def split_normalize(image):
    """Splitting source image then normalize it.

    :param image: source image
    :return: blue and green channel
    """
    im = Image.Image.split(image)
    g = ImageOps.equalize(im[1], mask=None)
    mean = Stat(im[2]).mean[0]
    b = np.array(im[2]).astype('float32')
    b /= (1.0 + mean)
    mean = Stat(g).mean[0]
    g = np.array(g).astype('float32')
    g /= (1.0 + mean)
    b = np.clip(b, 0, 1)
    g = np.clip(g, 0, 1)
    b *= 255.0
    g *= 255.0
    b = Image.fromarray(b.astype('uint8'))
    g = Image.fromarray(g.astype('uint8'))
    return b, g

def postprocessing(b, g, **kwargs):
    """Final GGB process.

    :param b: blue channel
    :param g: green channel
    :param kwargs: dict of custom variable
    :return: GGB image
    """
    img = Image.merge('RGB', (g, g, b))
    return img


import os
import json
import IDELIST.url
import EM_FOREX.url

def make_text_file(filename, data):
    print("make text file for " + filename + "...")
    text = json.dumps(data)
    script_dir = os.path.dirname(__file__)
    rel_path = "../download/IDELIST/" + filename + ".txt"
    abs_file_path = os.path.join(script_dir, rel_path)
    with open(abs_file_path, "w") as f:
        f.write(text)
    print(filename + " file was made successfully!")

if __name__ == "__main__":
    # checking if download folder exists or not.
    if not os.path.isdir("../download"):
        os.mkdir(os.path.dirname(__file__) + "/../download")
    if not os.path.isdir("../download/IDELIST"):
        os.mkdir(os.path.dirname(__file__) + "/../download/IDELIST")

    # stock list
    print("load stock list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_CALIST(pn=1, pz=10000), "stock")
    print("downloaded stock list!")
    make_text_file("CALIST", response)

    #index list
    print("load index list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_CILIST(pn=1, pz=10000), "index")
    print("downloaded index list!")
    make_text_file("CILIST", response)

    #HY list
    print("load HY list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_HYLIST(pn=1, pz=10000), "BK_HY")
    print("downloaded HY list!")
    make_text_file("HYLIST", response)

    # DQ list
    print("load DQ list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_DQLIST(pn=1, pz=10000), "BK_DQ")
    print("downloaded DQ list!")
    make_text_file("DQLIST", response)

    #GN list
    print("load GN list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_GNLIST(pn=1, pz=10000), "BK_GN")
    print("downloaded GN list!")
    make_text_file("GNLIST", response)

    #FOREXLIST
    print("load Forex list from Internet...")
    response = EM_FOREX.url.fetch_push_init(EM_FOREX.url.url_LIST(pn=1, pz=1000), "forex")
    print("downloaded Forex list!")
    make_text_file("FOREXLIST", response)


import itertools
import random
from typing import Any, Generator, Tuple, Type

from p2p.abc import CommandAPI, ProtocolAPI
from p2p.commands import BaseCommand, NoneSerializationCodec
from p2p.protocol import BaseProtocol

ACTIONS = (
    'dig',
    'run',
    'jump',
    'create',
    'destroy',
    'fill',
    'build',
    'create',
    'kill',
    'finish',
    'hello',
    'goodbye',
    'connect',
    'disconnect',
    'activate',
    'disable',
    'enable',
    'validate',
    'post',
    'get',
)

ANIMALS = (
    'dog',
    'cat',
    'bird',
    'fox',
    'panda',
    'unicorn',
    'bear',
    'eagle',
)

COLORS = (
    'red',
    'orange',
    'yellow',
    'green',
    'blue',
    'purple',
    'pink',
    'brown',
    'black',
    'white',
)

def _command_name_enumerator() -> Generator[str, None, None]:
    while True:
        for action in ACTIONS:
            yield action.title()
        for action, animal in itertools.product(ACTIONS, ANIMALS):
            yield f"{action.title()}{animal.title()}"

_command_name_iter = _command_name_enumerator()

def CommandNameFactory() -> str:
    return next(_command_name_iter)

def CommandFactory(name: str = None,
                   command_id: int = None) -> Type[CommandAPI[None]]:
    # TODO: this needs to be simplified to account for codecs.
    if command_id is None:
        command_id = 0
    if name is None:
        name = CommandNameFactory()

    return type(
        name,
        (BaseCommand,),
        {
            'protocol_command_id': command_id,
            'serialization_codec': NoneSerializationCodec(),
        },
    )

def _protocol_name_enumerator() -> Generator[str, None, None]:
    while True:
        for color, animal in itertools.product(COLORS, ANIMALS):
            yield f"{color}_{animal}"

_protocol_name_iter = _protocol_name_enumerator()

def ProtocolNameFactory() -> str:
    return next(_protocol_name_iter)

def ProtocolFactory(name: str = None,
                    version: int = None,
                    commands: Tuple[Type[CommandAPI[Any]], ...] = None) -> Type[ProtocolAPI]:
    if name is None:
        name = ProtocolNameFactory()
    if version is None:
        version = 1
    if commands is None:
        num_commands = random.randrange(1, 6)
        commands = tuple(
            CommandFactory(command_id=command_id)
            for command_id in range(num_commands)
        )

    return type(
        name.title(),
        (BaseProtocol,),
        {
            'name': name,
            'version': version,
            'commands': commands,
            'command_length': len(commands),
        },
    )


import unittest
import re

from google.appengine.api import apiproxy_stub_map
from google.appengine.api.capabilities import capability_stub
from google.appengine.api import datastore_file_stub
from google.appengine.api import urlfetch_stub
from google.appengine.api.memcache import memcache_stub
from google.appengine.api import user_service_stub

from werkzeug import BaseResponse, Client, Request

import kay
from kay.app import get_application
from kay.conf import LazySettings
from kay.tests import capability_stub as mocked_capability_stub

class MaintenanceCheckTestCase(unittest.TestCase):

  def setUp(self):
    apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
    stub = datastore_file_stub.DatastoreFileStub('test','/dev/null',
                                                 '/dev/null')
    apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)

    apiproxy_stub_map.apiproxy.RegisterStub(
      'user', user_service_stub.UserServiceStub())

    apiproxy_stub_map.apiproxy.RegisterStub(
      'memcache', memcache_stub.MemcacheServiceStub())

    apiproxy_stub_map.apiproxy.RegisterStub(
      'urlfetch', urlfetch_stub.URLFetchServiceStub())

    s = LazySettings(settings_module='kay.tests.settings')
    app = get_application(settings=s)
    self.client = Client(app, BaseResponse)
    if apiproxy_stub_map.apiproxy\
          ._APIProxyStubMap__stub_map.has_key('capability_service'):
      del(apiproxy_stub_map.apiproxy\
            ._APIProxyStubMap__stub_map['capability_service'])

  def tearDown(self):
    pass

  def test_success(self):
    """Test with normal CapabilityServiceStub"""
    apiproxy_stub_map.apiproxy.RegisterStub(
      'capability_service',
      capability_stub.CapabilityServiceStub())
    response = self.client.get('/')
    self.assertEqual(response.status_code, 200)

  def test_failure(self):
    """Test with DisabledCapabilityServiceStub
    """
    apiproxy_stub_map.apiproxy.RegisterStub(
      'capability_service',
      mocked_capability_stub.DisabledCapabilityServiceStub())
    response = self.client.get('/')
    self.assertEqual(response.status_code, 302)
    self.assertEqual(response.headers['Location'],
                     'http://localhost/maintenance_page')

    response = self.client.get('/index2')
    self.assertEqual(response.status_code, 302)
    self.assertEqual(response.headers['Location'],
                     'http://localhost/no_decorator')
    response = self.client.get('/no_decorator')
    self.assertEqual(response.status_code, 200)

if __name__ == "__main__":
  unittest.main()


import os
import sys
import logging
import multiprocessing
import progressbar
import threading

from PanACoTA import utils

main_logger = logging.getLogger("align.alignment")

def align_all_families(prefix, all_fams, ngenomes, dname, quiet, threads):
    """
    For each family:

    - align all its proteins with mafft
    - back-translate to nucleotides
    - add missing genomes

    Parameters
    ----------
    prefix :  str
        path to ``aldir/<name of dataset>`` (used to get extraction, alignment and btr files
        easily)
    all_fams : []
        list of all family numbers
    ngenomes : int
        total number of genomes in dataset
    dname : str
        name of dataset (used to name concat and grouped files, as well as tree folder)
    quiet : bool
        True if nothing must be written in stdout/stderr, False otherwise
    threads : int
        max number of threads that can be used by mafft

    Returns
    -------
    bool
        True if everything went well, False if there was a problem in at least 1 family.
    """
    main_logger.info(("Starting alignment of all families: protein alignment, "
                      "back-translation to nucleotides, and add missing genomes in the family"))
    nbfam = len(all_fams)
    bar = None
    if not quiet:
        # Create progressbar
        widgets = ['Alignment: ', progressbar.Bar(marker='█', left='', right='', fill=' '),
                   ' ', progressbar.Counter(), "/{}".format(nbfam), ' (',
                   progressbar.Percentage(), ') - ', progressbar.Timer(), ' - '
                   ]
        bar = progressbar.ProgressBar(widgets=widgets, max_value=nbfam,
                                      term_width=79).start()
    final = []
    if threads == 1:
        update_bar = 1
        for num_fam in all_fams:
            f = handle_family_1thread((prefix, num_fam, ngenomes))
            final.append(f)
            bar.update(update_bar)
            update_bar+=1

    else:
        pool = multiprocessing.Pool(threads)

        # Create a Queue to put logs from processes, and handle them after from a single thread
        m = multiprocessing.Manager()
        q = m.Queue()
        # arguments : (gpath, cores_prokka, name, force, nbcont, q) for each genome
        arguments = [(prefix, num_fam, ngenomes, q) for num_fam in all_fams]
        try:
            final = pool.map_async(handle_family, arguments, chunksize=1)
            pool.close()
            # Listen for logs in processes
            lp = threading.Thread(target=utils.logger_thread, args=(q,))
            lp.start()
            if not quiet:
                while True:
                    if final.ready():
                        break
                    remaining = final._number_left
                    bar.update(nbfam - remaining)
                bar.finish()
            pool.join()
            q.put(None)
            lp.join()
            final = final.get()
        # If an error occurs (or user kills with keybord), terminate pool and exit
        except Exception as excp:  # pragma: no cover
            pool.terminate()
            main_logger.error(excp)
            sys.exit(1)
    # We re-aligned (or added missing genomes) at least one family
    # -> remove concatenated files and groupby files (if they exist)
    if set(final) != {"OK"}:
        aldir = os.path.split(prefix)[0]
        concat_nucl = os.path.join(aldir, f"{dname}-complete.nucl.cat.aln")
        concat_aa = os.path.join(aldir, f"{dname}-complete.aa.cat.aln")
        outdir = os.path.split(aldir)[0]
        treedir = os.path.join(outdir, "Phylo-" + dname)
        grpfile_nucl = os.path.join(treedir, dname + ".nucl.grp.aln")
        grpfile_aa = os.path.join(treedir, dname + ".aa.grp.aln")
        utils.remove(concat_nucl)
        utils.remove(concat_aa)
        utils.remove(grpfile_nucl)
        utils.remove(grpfile_aa)
    return False not in final

def handle_family_1thread(args):
    """
    For the given family:

    - align its proteins with mafft
    - back-translate to nucleotides
    - add missing genomes

    Parameters
    ----------
    args : ()
         (prefix, num_fam, ngenomes, q) with:

         - prefix: path to ``aldir/<name of dataset>``
         - num_fam: the current family number
         - ngenomes: the total number of genomes in dataset

    Returns
    -------
    bool
        - "OK" if the files were not re-created, and have the expected format. This is used by
          ``align_all_families`` function, to know if something was regenerated, or if everything
          already existed with the expected format. If something was redone and concat/group files
          exist, it removes them.
        - False if any problem (extractions, alignment, btr, add missing genomes...)
        - True if just generated all files, and everything is ok
    """
    prefix, num_fam, ngenomes = args
    logger = logging.getLogger('align.align_family')
    # Get file names
    prt_file = f"{prefix}-current.{num_fam}.prt"
    gen_file = f"{prefix}-current.{num_fam}.gen"
    miss_file = f"{prefix}-current.{num_fam}.miss.lst"
    mafft_file = f"{prefix}-mafft-align.{num_fam}.aln"
    btr_file = f"{prefix}-mafft-prt2nuc.{num_fam}.aln"
    # Align all sequences for given family
    status1 = family_alignment(prt_file, gen_file, miss_file, mafft_file, btr_file,
                               num_fam, ngenomes, logger)
    #  status1 is:
    # - False if problem with extractions, alignment or backtranslation -> return False
    # - 'nb_seqs' = number of sequences aligned if everything went well (extractions and
    # alignment ok, btr created without problem)
    # - "OK" if extractions and alignments went well, and btr already exists and is ok
    # If it returned true or the , Add missing genomes
    # If 'OK' or nb_seq, add missing genomes
    if status1:
        added_aa = add_missing_genomes(mafft_file, "protein", miss_file, num_fam, ngenomes, status1, logger)
        added_nucl = add_missing_genomes(btr_file, "back-translated", miss_file, num_fam, ngenomes, status1, logger)
        # 1 of them false: return false
        # both are "OK": return OK (no need to remove concatenated and grouped files)
        # 1 of them true (not "OK"): return true
        if not added_nucl or not added_aa:
            return False
        elif added_aa == "OK" and added_nucl == "OK":
            return "OK"
        else:
            return True
    # Else, return False (there was a problem while trying to align, in any step)
    return False

def handle_family(args):
    """
    For the given family:

    - align its proteins with mafft
    - back-translate to nucleotides
    - add missing genomes

    Parameters
    ----------
    args : ()
         (prefix, num_fam, ngenomes, q) with:

         - prefix: path to ``aldir/<name of dataset>``
         - num_fam: the current family number
         - ngenomes: the total number of genomes in dataset
         - q: a queue, which will be used by logger to put logs while in other process

    Returns
    -------
    bool
        - "OK" if the files were not re-created, and have the expected format. This is used by
          ``align_all_families`` function, to know if something was regenerated, or if everything
          already existed with the expected format. If something was redone and concat/group files
          exist, it removes them.
        - False if any problem (extractions, alignment, btr, add missing genomes...)
        - True if just generated all files, and everything is ok
    """
    prefix, num_fam, ngenomes, q = args
    qh = logging.handlers.QueueHandler(q)
    root = logging.getLogger()
    root.setLevel(logging.DEBUG)
    root.handlers = []
    logging.addLevelName(utils.detail_lvl(), "DETAIL")
    root.addHandler(qh)
    logger = logging.getLogger('align.align_family')
    return handle_family_1thread((prefix, num_fam, ngenomes))

def add_missing_genomes(align_file, ali_type, miss_file, num_fam, ngenomes, status1, logger):
    """
    Once all family proteins are aligned, and back-translated to nucleotides,
    add missing genomes for the family to the alignment with '-'.
    (Add missing genomes to both mafft alignment and back-translated alignment)

    Parameters
    ----------
    align_file : str
        path to file containing alignments (proteins if from mafft output,
        or nucleic sequences if after backtranslating them)
    ali_type : str
        protein or backtranslated
    miss_file : str
        path to file containing the list of missing genomes in this family
    num_fam : int
        family number
    ngenomes : int
        total number of genomes in dataset
    status1 : bool or str
        - "OK" if we did not redo the alignments as they already were as expected. In that case,
          if missing genomes are already present, just add a warning message saying that we
          used the already existing btr file.
        - True if we just did the alignments and backtranslate. So no warning message needed.
        - False if problem with extraction, alignment or backtranslation (will never happen as
          this function is not called if status1 == False)
    logger : logging.Logger
        the logger, having a queue Handler, to give logs to the main logger

    Returns
    -------
    bool or str
        - "OK" if btr file was not recreated, and already has the right number of sequences,
          and all with the same length.
        - False if problem in btr file alignment, so missing genomes not added
        - True if alignment + adding missing genomes is ok. Can happen if there is no missing
          genome for this family (in that case, btr generated already has the right number of
          sequences), or if we just added the missing genomes.

    """
    # btr_file should always exist.
    # Sometimes it comes from previous step ('missing genomes' are missing)
    # Sometimes it comes from a previous run (all genomes should be here)
    status = check_add_missing(align_file, num_fam, ngenomes, logger, prev=True)
    # If btr_file has the correct number of sequences, all the same length, return True
    if status is True:
        if status1 == "OK":
            logger.warning(f"{ali_type} alignment already done for family {num_fam}. The program will use "
                            "it for next steps")
            return "OK"
        else:
            return True
    # If btr_files has problem in alignment (not all sequences with same size)
    elif status is False:
        return False
    # All sequences have same length but some genomes are missing -> Add missing genomes
    # status is length of sequence (if it was True or False, it already ended this function)
    logger.log(utils.detail_lvl(), f"Adding missing genomes for family {num_fam} in {ali_type} alignment.")
    len_aln = status
    with open(miss_file, "r") as missf, open(align_file, "a") as alif:
        for genome in missf:
            genome = genome.strip()
            toadd = ">" + genome + "\n" + "-" * len_aln + "\n"
            alif.write(toadd)
    # check_add_missing called with prev=False :
    # output is True if all ok, or False if problems. Cannot be sequence length (as it can be with prev=True)
    ret = check_add_missing(align_file, num_fam, ngenomes, logger, prev=False)
    return ret

def check_add_missing(btr_file, num_fam, ngenomes, logger, prev):
    """
    Check back-translated alignment while missing genomes have been added

    Parameters
    ----------
    btr_file : str
        path to file containing back-translated alignment
    num_fam : int
        current family number
    ngenomes : int
        total number of genomes in dataset
    logger : logging.Logger
        logger with queueHandler to give logs to main logger
    prev : bool
        True if we are checking alignments before adding missing genomes (in case it comes
        from a previous run and is already done, or in case there are no missing genomes for
        this family, so nothing to do to btr file). In that case, do not write error message
        if the number of sequences does not correspond to the total number of genomes.
        False if we just added missing genomes. In that case, nb sequences should be equal to
        the total number of genomes. If not, write error message.

    Returns
    -------
    bool or int
        - True if right number of sequences in btr file and all the same length (everything is ok)
        - False if problem in alignment (sequences do not all have the same size), or same size but not all
          genomes while not being from previous run (prev=False)
        - alignment length if sequences aligned all have the same length, but missing
          genomes are not added yet (so, will have to add lines with this number of '-')
    """
    res = check_lens(btr_file, num_fam, logger)
    # If all sequences have the same length, res = (length of a sequence, number of sequences in btr file)
    if res:
        len_aln, nb = res
    # otherwise, return False: problem while aligning or back-translating
    else:
        return False
    # If number of sequences in btr file is not the same as the total number of genomes, either:
    #   - btr comes from a previous run, but was not complete (prev)
    #   - we just created btr file, and there are missing genomes in this family.
    # return sequence length, so that we add missing genomes
    if nb != ngenomes:
        # prev = true: this function was called at the beggining of 'add_missing_genomes',
        # so it's ok if there are not all sequences, they will be added just after. We
        # just checked in case this is a file already complete from a previous run, or
        # in case there is no missing genome in this family.
        # prev = false: called after adding missing genomes. So, error message, as it should
        # contain all expected genomes.
        if not prev:
            logger.error((f"ERROR: family {num_fam} contains {nb} genomes in total "
                          f"instead of the {ngenomes} genomes in input.\n"))
            return False
        # If not already has all sequences, return sequence length to add the missing ones
        return len_aln
    # Everything ok (nb genomes ok and all same length)
    return True

def family_alignment(prt_file, gen_file, miss_file, mafft_file, btr_file,
                     num_fam, ngenomes, logger):
    """
    From a given family, align all its proteins with mafft, back-translate
    to nucleotides, and add missing genomes in this family.

    Parameters
    ----------
    prt_file : str
        path to file containing proteins extracted
    gen_file : str
        path to file containing genes extracted
    miss_file : str
        path to file containing list of genomes missing
    mafft_file : str
        path to file which will contain the protein alignment
    btr_file : str
        path to file which will contain the nucleotide alignment back-translated from protein
        alignment
    num_fam : int
        current family number
    ngenomes : int
        total number of genomes in dataset
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool or str
        - False if problem with extractions or with alignment or with backtranslation
        - 'nb_seqs' = number of sequences aligned if everything went well (extractions and
          alignment ok, btr created without problem)
        - "OK" if extractions and alignments went well, and btr already exists and is ok
    """
    # Check number of proteins extracted
    # =check that nb_prt (or nb_gen, which should be the same) + nb_miss = nb_genomes
    # returns number of genomes extracted (so, excludes missing genomes for the family)
    nbfprt = check_extractions(num_fam, miss_file, prt_file, gen_file, ngenomes, logger)
    nbfal = None
    # If problem with extractions (0 proteins extracted), remove mafft and btr files if they exist, so that they will
    # be regenerated
    if not nbfprt:
        utils.remove(mafft_file)
        utils.remove(btr_file)
        return False
    # If mafft file already exists, check the number of proteins aligned corresponds to number of
    #  proteins extracted. If not, remove mafft and btr files.
    if os.path.isfile(mafft_file):
        # There can be nbfprt (number of proteins extracted)
        # or nb_genomes (proteins extracted + missing added with '-')
        nbfal1 = check_nb_seqs(mafft_file, nbfprt, logger, "")
        nbfal2 = check_nb_seqs(mafft_file, ngenomes, logger, "")
        # if nbfal1: missing genomes have not been added yet. Save this value for later
        if nbfal1:
            nbfal = nbfal1
        # if nbfal2: missing genomes already there, save for later
        elif nbfal2:
            nbfal = nbfal2
        # If not any of those 2 numbers: error
        else:
            message = (f"fam {num_fam}: Will redo alignment, because found a different number of proteins "
                       f"extracted in {prt_file} ({nbfprt}) and proteins aligned in "
                       f"existing {mafft_file}")
            logger.error(message)
            os.remove(mafft_file)
            utils.remove(btr_file)
    # If mafft file does not exist (removed because problem in its alignment, or just not generated
    # yet), remove btr (will be regenerated), and do alignment with mafft
    if not os.path.isfile(mafft_file):
        utils.remove(btr_file)  # remove if exists...
        nbfal = mafft_align(num_fam, prt_file, mafft_file, nbfprt, logger)
    # If problem with alignment, return False
    if not nbfal:
        return False
    # If btr file already exists, means that it was already done before, and not removed because
    # extractions and mafft files are ok. So, return True, saying that btr file is done,
    # next step will be to check it, add missing genomes etc.
    if os.path.isfile(btr_file):
        message = (f"fam {num_fam}: Will redo back-translation, because found a different number of "
                   f"proteins aligned in {mafft_file} ({nbfal}) and genes back-translated in "
                   f"existing {btr_file}")
        # btr file contains either nbfal entries (number of proteins extracted) if it was not completed
        # with missing genomes, or ngenomes if it was completed. If it is not the case, remove it
        # (will be regenerated)
        res = check_nb_seqs(btr_file, [nbfal, ngenomes], logger, message)
        if not res:
            utils.remove(btr_file)
        else:
            return "OK"
    # If btr file does not exist (removed because problem with mafft generated before,
    # or just not generated yet), do back-translation, and return:
    # - number of sequences back-translated if it went well,
    # - False otherwise
    return back_translate(num_fam, mafft_file, gen_file, btr_file, nbfal, logger)

def check_extractions(num_fam, miss_file, prt_file, gen_file, ngenomes, logger):
    """
    Check that extractions went well for the given family:

    - check number of proteins and genes extracted compared to the
      number of genomes

    Parameters
    ----------
    num_fam : int
        current family number
    miss_file : str
        path to file containing the list of genomes missing for the current family
    prt_file : str
        path to file containing all proteins extracted
    gen_file : str
        path to file containing all genes extracted
    ngenomes : int
        total number of genomes in dataset
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool or int
        False if any problem (nbmiss+prt != nbgenomes or nbmiss+gen != nbgenomes). If no
        problem, returns the number of proteins/genes extracted
    """
    logger.log(utils.detail_lvl(), f"Checking extractions for family {num_fam}")

    # Check that extractions went well
    nbmiss = utils.count(miss_file)
    # If files with proteins extracted do not even exist, close with error
    # (they should have been created at the previous step)
    if not os.path.isfile(gen_file):
        logger.error(f"fam {num_fam}: no file with genes extracted "
                     f"('{gen_file}'). Cannot align.")
        sys.exit(1)
    if not os.path.isfile(prt_file):
        logger.error(f"fam {num_fam}: no file with proteins extracted "
                     f"('{prt_file}'). Cannot align.")
        sys.exit(1)
    nbfprt = utils.grep(prt_file, "^>", counts=True)
    nbfgen = utils.grep(gen_file, "^>", counts=True)
    if nbmiss + nbfprt != ngenomes:
        logger.error(("fam {}: wrong sum of missing genomes ({}) and prt extracted ({}) for {} "
                      "genomes in the dataset.").format(num_fam, nbmiss, nbfprt, ngenomes))
        return False
    if nbmiss + nbfgen != ngenomes:
        logger.error(("fam {}: wrong sum of missing genomes ({}) and gen extracted ({}) for {} "
                      "genomes in the dataset.").format(num_fam, nbmiss, nbfgen, ngenomes))
        return False
    return nbfprt

def mafft_align(num_fam, prt_file, mafft_file, nbfprt, logger):
    """
    Align all proteins of the given family with mafft

    Parameters
    ----------
    num_fam : int
        current family number
    prt_file : str
        path to file containing all proteins extracted
    mafft_file : str
        path to file which will contain proteins alignment
    nbfprt : int
        number of proteins extracted in prt file
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool
        True if no problem (alignment ok, same number of proteins extracted and aligned),
        False otherwise
    """
    logger.log(utils.detail_lvl(), f"Aligning family {num_fam}")
    cmd = f"mafft --auto {prt_file}"
    error = f"Problem while trying to align fam {num_fam}"
    stdout = open(mafft_file, "w")
    stderr = open(mafft_file + ".log", "w")
    logger.log(utils.detail_lvl(), f"Mafft command: {cmd}")
    ret = utils.run_cmd(cmd, error, stdout=stdout, stderr=stderr, logger=logger)
    stdout.close()
    if not isinstance(ret, int):
        ret = ret.returncode
    if ret != 0:
        os.remove(mafft_file)
        return False
    message = (f"fam {num_fam}: different number of proteins extracted in {prt_file} ({nbfprt}) and proteins "
               f"aligned in {mafft_file}")
    return check_nb_seqs(mafft_file, nbfprt, logger, message)

def back_translate(num_fam, mafft_file, gen_file, btr_file, nbfal, logger):
    """
    Backtranslate protein alignment to nucleotides

    Parameters
    ----------
    num_fam : int
        current family number. Used for log messages
    mafft_file : str
        path to file containing protein alignments by mafft
    gen_file : str
        path to file containing all sequences, not aligned, in nucleotides. It is used to
        convert the alignment in proteins into a nucleotide alignment
    btr_file : str
        path to the file that will contain the nucleotide alignment
    nbfal : int
        number of sequences aligned for the family by mafft
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool
        - False if problem (back-translation, different number of families...)
        - number of sequences in btr file if everything went well
    """
    logger.log(utils.detail_lvl(), f"Back-translating family {num_fam}")
    curpath = os.path.dirname(os.path.abspath(__file__))
    awk_script = os.path.join(curpath, "prt2codon.awk")
    cmd = f"awk -f {awk_script} {mafft_file} {gen_file}"
    stdout = open(btr_file, "w")
    error = f"Problem while trying to backtranslate {mafft_file} to a nucleotide alignment"
    ret = utils.run_cmd(cmd, error, stdout=stdout, logger=logger)
    stdout.close()
    if not isinstance(ret, int):
        ret = ret.returncode
    if ret != 0:
        os.remove(btr_file)
        return False
    message = (f"fam {num_fam}: different number of proteins aligned in {mafft_file} ({nbfal}) and genes "
               f"back-translated in {btr_file}")
    # Check number of sequences in btr file, and return True/False according to it
    # It should contain the same number of sequences as the mafft file.
    return check_nb_seqs(mafft_file, nbfal, logger, message)

def check_nb_seqs(alnfile, nbfal, logger, message=""):
    """
    Check the number of sequences in the given alignment file

    Parameters
    ----------
    alnfile : str
        path to alignment file
    nbfal : int or []
        expected number of sequences, or list of expected numbers of sequences
    logger : logging.Logger
        logger with queueHandler to give logs to main logger
    message : str
        message to write when sequence numbers do not match

    Returns
    -------
    bool or int
        - False if not same number of sequences
        - nbseqs in align file if found among values in 'nbfal'
    """
    nbseqs = utils.grep(alnfile, "^>", counts=True)
    if isinstance(nbfal, int):
        nbfal = [nbfal]
    for num in nbfal:
        if nbseqs == num:
            return nbseqs
    if message:
        logger.error(f"{message} ({nbseqs})")
    return False

def check_lens(aln_file, num_fam, logger):
    """
    In the given alignment file, check that all sequences have the same length.
    If there is no problem, it returns the length of alignment, and the number
    of sequences aligned.

    Parameters
    ----------
    aln_file : str
        path to the alignment file to check
    num_fam : int
        current family number. Used for log message if problem
    logger : logging.Logger
        logger having a queue Handler to give logs to the main logger in the main process

    Returns
    -------
    bool or tuple
        False if there is a problem in the alignment (sequences do not all have the
        same length).
        If they all have the same length, returns this length and the number of sequences
    """
    nb_gen = 0
    all_sums = set()
    with open(aln_file, "r") as btrf:
        cur_sum = 0
        start = True
        for line in btrf:
            if line.startswith(">"):
                nb_gen += 1
                if not start:
                    all_sums.add(cur_sum)
                    cur_sum = 0
            else:
                start = False
                cur_sum += len(line.strip())
        all_sums.add(cur_sum)
    if len(all_sums) > 1:
        logger.error(f"Nucleic alignments for family {num_fam} (in {aln_file}) do not all have the same "
                     f"length. Lengths found are: {all_sums}\n")
        return False
    # Return sequence length and number of sequences in alignment file
    return list(all_sums)[0], nb_gen


import ezrM
from sys import argv
from requests import get, ConnectionError
GITHUB = 'https://github.com/Uralstech/ezrMlang/releases'

def check_version():
	try:
		ov_text = get('https://pastebin.com/raw/Qz8bKPpN').text
		ov, cv = ov_text.split('.'), ezrM.VERSION.split('.')
		for i, v in enumerate(cv):
			if ov[i] > v:
				if i == 0: print(f'UPDATE AVAILABLE: v{ov_text} [MAJOR UPDATE] -> {GITHUB}'); return
				elif i == 1: print(f'UPDATE AVAILABLE: v{ov_text} [Feature update] -> {GITHUB}'); return
				elif i == 2: print(f'UPDATE AVAILABLE: v{ov_text} [Function update] -> {GITHUB}'); return
				elif i == 3: print(f'UPDATE AVAILABLE: v{ov_text} [Library update] -> {GITHUB}'); return
				elif i == 4: print(f'UPDATE AVAILABLE: v{ov_text} [Patch] -> {GITHUB}'); return
			elif ov[i] < v: return
	except ConnectionError: print('Warning: Could not check for latest ezrM version')

def main():
	print(f'ezr Malayalam Shell v{ezrM.VERSION} ({ezrM.VERSION_DATE}) - Ctrl+C to exit')
	check_version()

	first_command = None
	if len(argv) > 1:
		path = argv[1].replace('\\', '//')
		first_command = f'നിർവഹിക്കുക(\'{path}\')'

	while True:
		try:
			if first_command == None:
				input_ = input('>>> ')
				if input_.strip() == '': continue
			else:
				print(f'>>> {first_command}')
				input_ = first_command
				first_command = None

			result, error = ezrM.run('__പ്രധാന_നിർവ്വഹണം__', input_)

			if error: print(error.as_string())
			elif result:
				if len(result.elements) == 1: print(repr(result.elements[0]))
				else: print(repr(result))
		except KeyboardInterrupt: break
		except EOFError: break

if __name__ == '__main__':
	main()


import sys
import clr

from scriptutils import logger
from scriptutils.userinput import CommandSwitchWindow
from revitutils import doc, selection

from System.Collections.Generic import List
from Autodesk.Revit.DB import Element, ElementId, View, ViewType, FilteredElementCollector, BuiltInCategory, \
                              CopyPasteOptions, ElementTransformUtils, ElevationMarker, \
                              Transaction, TransactionGroup, IDuplicateTypeNamesHandler, ViewDuplicateOption, \
                              ViewPlan, ViewDrafting, ViewSection, BoundingBoxXYZ, ElementTypeGroup, XYZ
from Autodesk.Revit.UI import TaskDialog

__doc__ = "Converts selected detail views to selected model view type." \
          "The resulting model views will not show the model and their associated tags are only visible in 1:1 views."

selected_level = None

view_types_dict = {'Floor Plan': ViewPlan,
                   'Section': ViewSection,
                   'Reflected Ceiling Plan': ViewPlan,
                   'Elevation': ViewSection,
                #    'Area Plan': ViewPlan,
                #    'Structural Plan': ViewPlan,
                   }

class CopyUseDestination(IDuplicateTypeNamesHandler):
    def OnDuplicateTypeNamesFound(self, args):
        return DuplicateTypeAction.UseDestinationTypes

def process_selection():
    if not selection.is_empty:
        return [el for el in selection.elements if isinstance(el, ViewDrafting)]
    else:
        TaskDialog.Show('pyRevit', 'At least one Drafting view must be selected.')
        sys.exit(0)

def get_modelview_type():
    switch = CommandSwitchWindow(view_types_dict.keys()).pick_cmd_switch()
    if switch:
        return switch
    else:
        logger.debug('User cancelled.')
        sys.exit(0)

def get_view_level():
    global selected_level
    if not selected_level:
        levels = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels) \
                                              .WhereElementIsNotElementType()         \
                                              .ToElements()
        levels_dict = {lvl.Name:lvl for lvl in levels}
        picked_level = CommandSwitchWindow(levels_dict.keys()).pick_cmd_switch()
        selected_level = levels_dict[picked_level]

    return selected_level

def find_first_floorplan():
    view_list = list(FilteredElementCollector(doc).OfClass(clr.GetClrType(ViewPlan)) \
                                                 .WhereElementIsNotElementType()      \
                                                 .ToElements())
    for view in view_list:
        if view.ViewType == ViewType.FloorPlan:
            return view

def create_dest_view(view_type, view_name, view_scale):
    with Transaction(doc, 'Create model view') as t:
        t.Start()
        try:
            dest_view = None
            if view_type == 'Floor Plan':
                level = get_view_level()
                view_fam_typeid = doc.GetDefaultElementTypeId(ElementTypeGroup.ViewTypeFloorPlan)
                dest_view = ViewPlan.Create(doc, view_fam_typeid, level.Id)
            elif view_type == 'Reflected Ceiling Plan':
                level = get_view_level()
                view_fam_typeid = doc.GetDefaultElementTypeId(ElementTypeGroup.ViewTypeCeilingPlan)
                dest_view = ViewPlan.Create(doc, view_fam_typeid, level.Id)
            elif view_type == 'Section':
                view_fam_typeid = doc.GetDefaultElementTypeId(ElementTypeGroup.ViewTypeSection)
                dest_view = ViewSection.CreateSection(doc, view_fam_typeid, BoundingBoxXYZ())
                scale_param = dest_view.LookupParameter('Hide at scales coarser than')
                scale_param.Set(1)
            elif view_type == 'Elevation':
                view_fam_typeid = doc.GetDefaultElementTypeId(ElementTypeGroup.ViewTypeElevation)
                elev_marker = ElevationMarker.CreateElevationMarker(doc, view_fam_typeid, XYZ(0,0,0), 1)
                default_floor_plan = find_first_floorplan()
                dest_view = elev_marker.CreateElevation(doc, default_floor_plan.Id, 0)
                scale_param = dest_view.LookupParameter('Hide at scales coarser than')
                scale_param.Set(1)

            dest_view.ViewName = view_name
            dest_view.Scale = view_scale
            model_visib_param = dest_view.LookupParameter('Display Model')
            model_visib_param.Set(2)
            dest_view.CropBoxActive = False
            dest_view.CropBoxVisible = False
            t.Commit()
            return dest_view
        except Exception as create_err:
            t.RollBack()
            logger.debug('Can not create model view: {} | {}'.format(view_name, create_err))
            raise create_err

def get_copyable_elements(src_view):
    # get drafting view elements and exclude non-copyable elements
    view_elements = FilteredElementCollector(doc, src_view.Id).ToElements()
    elements_to_copy = []
    for el in view_elements:
        if isinstance(el, Element) and el.Category:
            elements_to_copy.append(el.Id)
        else:
            logger.debug('Skipping Element with id: {0}'.format(el.Id))

    if len(elements_to_copy) < 1:
        logger.debug('Skipping {0}. No copyable elements where found.'.format(src_view.ViewName))

    return elements_to_copy

def copy_paste_elements_btwn_views(src_view, dest_view):
    elements_to_copy = get_copyable_elements(src_view)
    # copying and pasting elements
    try:
        with Transaction(doc, 'Copy and Paste elements') as t:
            t.Start()
            options = CopyPasteOptions()
            options.SetDuplicateTypeNamesHandler(CopyUseDestination())
            copied_element = ElementTransformUtils.CopyElements(src_view,
                                                                List[ElementId](elements_to_copy),
                                                                dest_view,
                                                                None,
                                                                options)

            # matching element graphics overrides and view properties
            for dest, src in zip(copied_element, elements_to_copy):
                dest_view.SetElementOverrides(dest, src_view.GetElementOverrides(src))

            t.Commit()
            return True
    except Exception as err:
        logger.error(err)
        return False

drafting_views = process_selection()
dest_view_type = get_modelview_type()

# iterate over drafting views
with TransactionGroup(doc, 'Convert Drafting to Model') as tg:
    tg.Start()
    for src_view in drafting_views:
        logger.info('Converting: {}'.format(src_view.ViewName))
        dest_view_successfully_setup = False
        try:
            dest_view = create_dest_view(dest_view_type, src_view.ViewName, src_view.Scale)
            dest_view_successfully_setup = True
        except Exception as err:
            logger.error('Error converting: {} | {}'.format(src_view.ViewName, err))
            logger.debug(err)

        if dest_view_successfully_setup:
            copy_paste_elements_btwn_views(src_view, dest_view)

    tg.Assimilate()

extensions/pyRevitTools.extension/pyRevit.tab/Drawing Set.panel/views.stack3/Views.pulldown/Convert Detail View to Model View.pushbutton/script.py


#!/nfs/stak/users/shressag/sagar/venv/bin/python3.6
from slf_dataset import SLFDataset, SLFDatasetMat
from torch.utils.data import DataLoader
import torch
from collections import OrderedDict, namedtuple
import os
from params import ROOT, MODEL_PATH_VAE, RESULT_PATH_VAE, VALIDATION_SET_PATH
from networks.model import Network as Network_raw
from networks.model_batch_norm import Network as Network_batch_norm
from networks.adversarial_model import EncoderDecoder, EncoderDecoder12, AutoencoderLinear, EncoderDecoder128
from run_manager import RunBuilder, RunManager
from tqdm import tqdm
from networks.vae import VAE

if torch.cuda.is_available():
    devices = ['cuda']
else:
    devices = ['cpu']

class VAELoss(torch.nn.Module):
    def __init__(self):
        super(VAELoss, self).__init__()

    def forward(self, bce_loss, mu, logvar):
        """
        This function will add the reconstruction loss (BCELoss) and the
        KL-Divergence.
        KL-Divergence = 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
        :param bce_loss: recontruction loss
        :param mu: the mean from the latent vector
        :param logvar: log variance from the latent vector
        """
        BCE = bce_loss
        KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
        return BCE + KLD

print('starting')
networks = {
    'network_raw': Network_raw,
    'network_batch_norm': Network_batch_norm,
    'encoder_decoder': EncoderDecoder128,
    'autoencoder': AutoencoderLinear,
    'vae64': VAE
}

params = OrderedDict(
    lr = [0.001],
    batch_size = [128],
    device = devices,
    network = ['vae64'],
    shuffle = [True],
    num_workers = [5],
    loss='vae',
    model='vae64_1'
)

train_set = SLFDatasetUnsampled(root_dir=os.path.join(ROOT, 'slf_mat'),
                    csv_file=os.path.join(ROOT, 'details.csv'), total_data=500000)

validation_set = SLFDatasetUnsampled(root_dir=os.path.join(VALIDATION_SET_PATH, 'slf_mat'),
                    csv_file=os.path.join(VALIDATION_SET_PATH, 'details.csv'), total_data=5000)

m = RunManager()
vae_loss = VAELoss()
mse_loss = torch.nn.MSELoss()
for run in RunBuilder.get_runs(params):
    device = torch.device(run.device)
    network = networks[run.network]().to(run.device)
    loader = torch.utils.data.DataLoader(train_set, batch_size=run.batch_size, shuffle=run.shuffle, num_workers=run.num_workers)
    validation_loader = torch.utils.data.DataLoader(validation_set, batch_size=run.batch_size, shuffle=run.shuffle, num_workers=run.num_workers)

    optimizer  = torch.optim.Adam(network.parameters(), lr=run.lr)

    PATH = MODEL_PATH_VAE
    saved_epoch = 0
    lr = run.lr

    l1_loss = torch.nn.L1Loss()

    if os.path.isfile(PATH):
        checkpoint = torch.load(PATH)
        network.load_state_dict(checkpoint['model_state_dict'])
        optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
        saved_epoch = checkpoint['epoch']
        lr = checkpoint['lr']
        # loss = checkpoint['loss']
    m.begin_run(run, network, loader, validation_loader)

    for epoch in range(saved_epoch, 150):
        m.begin_epoch()

        if epoch==30:
            for param_group in optimizer.param_groups:
                param_group['lr'] = 0.0001
        if epoch>70:
            for param_group in optimizer.param_groups:
                param_group['lr'] = 0.00002
        for batch in tqdm(loader):

            # Get data
            in_features, t_slf = batch
            in_features = in_features.to(run.device)
            t_slf = t_slf.to(run.device)
            preds, mu, logvar = network(in_features)

            mse  = mse_loss(t_slf, preds)
            loss = vae_loss(mse, mu, logvar)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            m.track_loss(loss)

        for validation_batch in validation_loader:
            in_features, t_slf = validation_batch
            in_features = in_features.to(run.device)
            t_slf = t_slf.to(run.device)
            preds, mu, logvar = network(in_features)

            mse_valid  = mse_loss(t_slf, preds)
            valid_loss = vae_loss(mse_valid, mu, logvar)
            m.track_validation_loss(valid_loss)
        m.end_epoch()

        for param_group in optimizer.param_groups:
            print(param_group['lr'])
        print('epoch: {}, loss: {}, v_loss: {}, lr: {}'.format(epoch, m.item_loss, m.validation_loss, lr))
        torch.save({'epoch': epoch,
                    'model_state_dict': network.state_dict(),
                    'optimizer_state_dict': optimizer.state_dict(),
                    'loss': m.epoch_loss,
                    'lr': lr},
                    MODEL_PATH_VAE)

    m.end_run()
m.save(RESULT_PATH_)

# PATH = 'models/current.model'
# if os.path.isfile(PATH):
#     checkpoint = torch.load(PATH)
#     network.load_state_dict(checkpoint['model_state_dict'])
#     optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
#     epoch = checkpoint['epoch']
#     # loss = checkpoint['loss']


import csv
array = []

with open('data.csv') as file:
    reader = csv.reader(file)

    for row in reader:
        array.append(row)

call = -20
sms = 0

for i in range(1,10):
    if '915783624' in array[i][1]:
        call+=float(array[i][3])
        sms+=float(array[i][4])

print("%.2f" % (call*2+sms*2))


# Program from Youtube Videos - corey schafer
"""
Tut3 - Class Methods
"""
class Employee:
    hike = 1.06
    def __init__(self,first,last,pay):
        self.first = first
        self.last = last
        self.pay = pay
        self.email = first + '.' + last + '@company.com'

    def apply_raise(self):
        self.pay = int(self.pay * self.hike)

    @classmethod  # This is a Class Method used to set the value for Class Variable
    def set_raise_amt(cls,amount):
        cls.hike = amount

    @classmethod   #using class Method as an alternative Constructor
    def from_string(cls, emp_str):
        firstn,lastn,pay = emp_str.split('-')
        return cls(firstn,lastn,pay)

emp1 = Employee('Habeeba','Banu',55000)
print(emp1.pay)
emp1.apply_raise()
print(emp1.pay)

print(Employee.hike)      # Class Variable hike value before applying set_raise_amt
emp1.set_raise_amt(1.08)  # applying the Class Method and changing the Class Variable value
print(Employee.hike)      # Class Variable hike value after applying set_raise_amt
print(emp1.hike)

emp_str1 = 'Jaffer-Shaik-60000'
new_emp1 = Employee.from_string(emp_str1)  # Using the Class Method from_string
print(new_emp1.first)
print(new_emp1.last)
print(new_emp1.email)


import time
from pages.text_box_page import TextBoxPage
from components.components import WebElement
import allure

@allure.feature('check attr')
@allure.story('Проверка значения атрибута элемента')
@allure.severity(allure.severity_level.BLOCKER)
def test_placeholder(browser):
    '''Проверка значения атрибута элемента'''

    test_box_page = TextBoxPage(browser)

    test_box_page.visit()
    assert test_box_page.full_name.exist()
    assert test_box_page.full_name.get_dom_attribute('placeholder') == 'Full Name'

@allure.feature('check attr')
@allure.story('Проверка наличия атрибута')
@allure.severity(allure.severity_level.CRITICAL)
def test_attr_exist(browser):
    '''Проверка наличия атрибута'''

    text_box_page = TextBoxPage(browser)

    text_box_page.visit()
    text_box_page.btn_first.click()
    assert text_box_page.box_first_menu.get_dom_attribute('style')

@allure.feature('check attr')
@allure.story('Проверка отсутствия атрибута')
@allure.severity(allure.severity_level.NORMAL)
def test_attr_not_exist(browser):
    '''Проверка отсутствия атрибута'''

    text_box_page = TextBoxPage(browser)

    text_box_page.visit()
    assert not text_box_page.btn_first.get_dom_attribute('style')


from abc import ABC, abstractmethod
from typing import Generic, TypeVar

T = TypeVar('T')

# АТД NativeDictionary
class AbsNativeDictionary(ABC, Generic[T]):

    # Конструктор
    # постусловие: создан ассоциативный массив
    def __init__(self) -> None: ...

    # Команды:
    # постусловие: если ключа нет в массиве, то
    # новая пара ключ-значение добавлена в массив;
    # если ключ есть в массиве, то обновлено значение ключа
    @abstractmethod
    def put(self, key: str, value: T) -> None: ...
    # предусловие: в массиве есть запрашиваемый ключ
    # постусловие: пара "ключ-значение" удалена из массива
    @abstractmethod
    def remove(self, key: str) -> None: ...

    # Запросы:
    @abstractmethod
    def is_key(self, key: str) -> bool: ...  # есть ключ в массиве или нет
    @abstractmethod
    def size(self) -> int: ...  # кол-во пар "ключ-значение" в массиве
    # предусловие: запрашиваемый ключ есть в массиве
    @abstractmethod
    def get(self, key: str) -> T: ...  # получено значение по ключу

    # Дополнительные запросы:
    # запросы статусов (возможные значения статусов)
    @abstractmethod
    def get_put_status(self) -> int: ...  # успешно добавлена новая пара
    # "ключ-значение"; успешно обновлено значение по ключу

    @abstractmethod
    def get_remove_status(self) -> int: ...  # успешно удалена пара
    # "ключ-значение"; в массиве нет запрашиваемого ключа

    @abstractmethod
    def get_get_status(self) -> int: ...  # успешно получено значение по ключу;
    # в массиве нет запрашиваемого ключа

# Реализация NativeDictionary
class NativeDictionary(AbsNativeDictionary):

    PUT_NIL = 0  # put() не вызывался
    PUT_OK_1 = 1  # успешно добавлена новая пара "ключ-значение" в массив
    PUT_OK_2 = 2  # успешно обновлено значение по ключу

    REMOVE_NIL = 0  # remove() не вызывался
    REMOVE_OK = 1  # успешно удалена пара "ключ-значение" из массива
    REMOVE_ERR = 2  # в массиве нет запрашиваемоего ключа

    GET_NIL = 0  # get() не вызывался
    GET_OK = 1  # успешно получено значение по ключу
    GET_ERR = 2  # в массиве нет запрашиваемоего ключа

    def __init__(self) -> None:
        super().__init__()
        self.__count = 0
        self.__capacity = 16
        self._slots = [None] * self.__capacity
        self._values = [None] * self.__capacity
        self.__put_status = self.PUT_NIL
        self.__remove_status = self.REMOVE_NIL
        self.__get_status = self.GET_NIL

    def __resize(self, new_capacity):
        new_slots = [None] * new_capacity
        new_values = [None] * new_capacity
        for i in range(self.__count):
            new_slots[i] = self._slots[i]
            new_values[i] = self._values[i]
        self._slots = new_slots
        self._values = new_values
        self.__capacity = new_capacity

    def _hash_fun(self, key):
        hash = sum([ord(sym) for sym in key]) % self.__capacity
        return hash

    def __remove_key_value(self, index: int) -> None:
        for j in range(index, self.__capacity - 1):
            self._slots[j] = self._slots[j + 1]
            self._values[j] = self._values[j + 1]
        decrease_capacity = int(self.__capacity / 1.5)
        if self.__count < self.__capacity * 0.5:
            self.__resize(decrease_capacity if decrease_capacity >= 16 else 16)

    def is_key(self, key) -> bool:
        return key in self._slots

    def put(self, key: str, value: T) -> None:
        index = self._hash_fun(key)
        if not self.is_key(key) and self.__count == self.__capacity:
            self.__resize(2 * self.__capacity)
        count = 0
        while count < self.__capacity:
            if self.is_key(key) and self._slots[index] == key:
                self._values[index] = value
                self.__put_status = self.PUT_OK_2
                return
            if not self.is_key(key) and not self._slots[index]:
                self._slots[index] = key
                self._values[index] = value
                self.__count += 1
                self.__put_status = self.PUT_OK_1
                return
            index += 1
            if index >= self.__capacity:
                index %= self.__capacity
            count += 1

    def remove(self, key: str) -> None:
        if not self.is_key(key):
            self.__remove_status = self.REMOVE_ERR
            return
        index = self._hash_fun(key)
        count = 0
        while count < self.__capacity:
            if self._slots[index] == key:
                self.__remove_key_value(index)
                self.__count -= 1
                self.__remove_status = self.REMOVE_OK
                return
            index += 1
            if index >= self.__capacity:
                index %= self.__capacity
            count += 1

    def size(self) -> int:
        return self.__count

    def get(self, key: str) -> T:
        if not self.is_key(key):
            self.__get_status = self.GET_ERR
            return
        index = self._hash_fun(key)
        count = 0
        while count < self.__capacity:
            if self._slots[index] == key:
                self.__get_status = self.GET_OK
                return self._values[index]
            index += 1
            if index >= self.__capacity:
                index %= self.__capacity
            count += 1

    def get_put_status(self) -> int:
        return self.__put_status

    def get_remove_status(self) -> int:
        return self.__remove_status

    def get_get_status(self) -> int:
        return self.__get_status


from openpyxl import load_workbook
import pandas as pd
import json

class ExcelReader:
    """

    """
    def __init__(self, sheet):
        """

        :param sheet:
        """
        self.sheet = sheet

        f = open("input/files_description.json", "r")
        files_description = json.loads(f.read())

        for description in files_description:
            if description["sheet"] == sheet:
                self.columns = description["columns"]
                self.data = description["data"]
                self.id = description["id"]

    def look_for_sheet(self, input_file):

        wb = load_workbook(input_file)
        sheet_names = wb.sheetnames
        if self.sheet in sheet_names:
            return True
        else:
            return False

    def combine_sheets(self, file_list):
        df = pd.DataFrame()

        f = open(file_list, "r")
        data = json.loads(f.read())

        try:
            for dt in data:
                if dt[self.sheet] == 1:
                    file = dt["file_path"] + dt["file_name"]
                    print(file)
                    df = df.append(pd.read_excel(file, sheet_name=self.sheet), ignore_index=True)

            print(len(df))
            df = df.drop_duplicates(subset=[self.id])
            df = df.sort_values(by=self.id)
            print(len(df))

            print(df.info())

            df.to_csv("output/output.csv", sep=';', encoding='utf-8-sig', index=False)

        except Exception as error:
            print(error)


with open('NoteMapper.txt', 'r') as f:
    mapping_list = []
    for line in f:
        if line.startswith('#') == False:
            NoteListTemp = []
            quoteflag = 0
            for i in range(0,len(line)):
                if quoteflag == 0 and (line[i]== '\'' or line[i] == '\"'):
                    quoteflag = 1
                    tempstr = ''
                elif quoteflag == 1 and line[i].isalnum():
                    tempstr = tempstr + line[i]
                elif quoteflag == 1 and (line[i]== '\'' or line[i] == '\"'):
                    quoteflag = 0
                    NoteListTemp.append(tempstr)
                    tempstr = ''
            if quoteflag == 1:
                quoteflag = 0
                NoteListTemp.append(tempstr)
            mapping_list.append(NoteListTemp)


from functools import partial
from typing import Optional

import torch
import torch.nn.functional as F
from torch.nn.modules.loss import _Loss

# Copypasted from https://github.com/BloodAxe/pytorch-toolbelt

__all__ = ["FocalLoss"]

BINARY_MODE = "binary"
MULTICLASS_MODE = "multiclass"

def focal_loss_with_logits(
        input: torch.Tensor,
        target: torch.Tensor,
        gamma=2.0,
        alpha: Optional[float] = 0.25,
        reduction="mean",
        normalized=False,
        reduced_threshold: Optional[float] = None,
) -> torch.Tensor:
    """Compute binary focal loss between target and output logits.
    See :class:`~pytorch_toolbelt.losses.FocalLoss` for details.
    Args:
        input: Tensor of arbitrary shape
        target: Tensor of the same shape as input
        reduction (string, optional): Specifies the reduction to apply to the output:
            'none' | 'mean' | 'sum' | 'batchwise_mean'. 'none': no reduction will be applied,
            'mean': the sum of the output will be divided by the number of
            elements in the output, 'sum': the output will be summed. Note: :attr:`size_average`
            and :attr:`reduce` are in the process of being deprecated, and in the meantime,
            specifying either of those two args will override :attr:`reduction`.
            'batchwise_mean' computes mean loss per sample in batch. Default: 'mean'
        normalized (bool): Compute normalized focal loss (https://arxiv.org/pdf/1909.07829.pdf).
        reduced_threshold (float, optional): Compute reduced focal loss (https://arxiv.org/abs/1903.01347).
    References::
        https://github.com/open-mmlab/mmdetection/blob/master/mmdet/core/loss/losses.py
    """
    target = target.type(input.type())

    logpt = F.binary_cross_entropy_with_logits(input, target, reduction="none")
    pt = torch.exp(-logpt)

    # compute the loss
    if reduced_threshold is None:
        focal_term = (1 - pt).pow(gamma)
    else:
        focal_term = ((1.0 - pt) / reduced_threshold).pow(gamma)
        focal_term[pt < reduced_threshold] = 1

    loss = focal_term * logpt

    if alpha is not None:
        loss *= alpha * target + (1 - alpha) * (1 - target)

    if normalized:
        norm_factor = focal_term.sum() + 1e-5
        loss /= norm_factor

    if reduction == "mean":
        loss = loss.mean()
    if reduction == "sum":
        loss = loss.sum()
    if reduction == "batchwise_mean":
        loss = loss.sum(0)

    return loss

class FocalLoss(_Loss):
    def __init__(self, mode=MULTICLASS_MODE, alpha=None, gamma=2, ignore_index=None,
                 reduction="mean", normalized=False, reduced_threshold=None):
        """
        Focal loss for multi-class problem.
        :param mode: Metric mode {'binary', 'multiclass'}
        :param alpha:
        :param gamma:
        :param ignore_index: If not None, targets with given index are ignored
        :param reduced_threshold: A threshold factor for computing reduced focal loss
        """
        super().__init__()
        self.mode = mode
        self.ignore_index = ignore_index
        self.focal_loss_fn = partial(
            focal_loss_with_logits,
            alpha=alpha,
            gamma=gamma,
            reduced_threshold=reduced_threshold,
            reduction=reduction,
            normalized=normalized,
        )

    def forward(self, input, target):
        if self.mode == BINARY_MODE:
            target = target.view(-1)
            input = input.view(-1)

            if self.ignore_index is not None:
                # Filter predictions with ignore label from loss computation
                not_ignored = target != self.ignore_index
                input = input[not_ignored]
                target = target[not_ignored]

            loss = self.focal_loss_fn(input, target)
            return loss
        elif self.mode == MULTICLASS_MODE:
            num_classes = input.size(1)
            loss = 0

            # Filter anchors with -1 label from loss computation
            if self.ignore_index is not None:
                not_ignored = target != self.ignore_index

            for cls in range(num_classes):
                cls_label_target = (target == cls).long()
                cls_label_input = input[:, cls, ...]

                if self.ignore_index is not None:
                    cls_label_target = cls_label_target[not_ignored]
                    cls_label_input = cls_label_input[not_ignored]

                loss += self.focal_loss_fn(cls_label_input, cls_label_target)
            return loss
        else:
            raise NotImplementedError("Mode you are asking for is not implemented.")


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head:
            return None

        pre, p = None, head

        while p:
            tmp = p.next
            p.next = pre
            pre = p
            p = tmp
        return pre


import numpy as np
from cmath import tan
import math
from ROOT import *
from array import *
import Helper as h
import array

#This is the angle between strips in the CSC's
#Most of the time, we are working in eighth strips (10 / 75 / 8 = 1/60 of a degree)
nominal_pitch = 10. / 75.

#This file sources the z-coordinate of each chamber in order to accurately draw chamber-origins in space
global z_source
z_source  = "/afs/cern.ch/user/n/nhurley/CMSSW_12_4_6_emtfReEmul/src/EMTFNtuple_geometry_run2.root"

#This folder contains the LUTs that we want to correct
#These should be the same LUTs used to generate the station_station_phi data
global folder
folder = "/afs/cern.ch/user/n/nhurley/CMSSW_12_4_6_emtfReEmul/src/L1Trigger/L1TMuon/data/emtf_luts/ph_lut_GOOD/"

#This folder contains the output LUTs
#This folder should contain all the same LUTs as "folder", however some of files will be later be changed when you run this script
global output
output = "/afs/cern.ch/user/n/nhurley/CMSSW_12_4_6_emtfReEmul/src/L1Trigger/L1TMuon/data/emtf_luts/ph_lut_custom/"

#Obtain this file by running station_station_phi.py on EMTFNTuples generated with the LUTs used in folder (which we intend to correct)
#This file will contain the distribution of station-station delta-phis for every station-transition and every sector
global station_station_phi_data
station_station_phi_data = "/afs/cern.ch/user/n/nhurley/EMTFAnalyzer/AWBTools/macros/plots/alignment/station_station_phi_custom_chamber.root"

#Used to obtain the z-values for the chambers
evt_tree  = TChain('EMTFNtuple/tree')
evt_tree.Add(z_source)
#only need one event
evt_tree.GetEvent()

#The following information is used to extract chamber information from its cscid
#CSCID is required to get a chamber's global phi
MAX_ENDCAP = 2
MAX_STATION = 4
MAX_RING = 4
MAX_CHAMBER = 36
MAX_LAYER = 6

MIN_ENDCAP = 1
MIN_STATION = 1
MIN_RING = 1
MIN_CHAMBER = 1
MIN_LAYER = 1

BITS_ENDCAP = 3
BITS_STATION = 3
BITS_RING = 3
BITS_CHAMBER = 6
BITS_LAYER = 3

MASK_ENDCAP = 7
MASK_STATION = 7
MASK_RING = 7,
MASK_CHAMBER = 0x077
MASK_LAYER = 7

START_CHAMBER = BITS_LAYER
START_RING = START_CHAMBER + BITS_CHAMBER
START_STATION = START_RING + BITS_RING
START_ENDCAP = START_STATION + BITS_STATION

LOWER_THETA = 8.5
UPPER_THETA = 45
theta_scale = float((UPPER_THETA - LOWER_THETA) / 128.)

#Get cscdetid from chamber information
#offline ring is in form: ME1b, ME12, ME13, ME1a
def getCSCDetID(iendcap, istation, iring, ichamber, ilayer = 0):
    #cscid ring in form ME1a, ME1b, ME12, ME13
    if station == 1:
        iring = (iring + 1) % 4
        if iring == 0: iring = 4

    return (ilayer & MASK_LAYER) | ((ichamber & MASK_CHAMBER) << START_CHAMBER) | ((iring & MASK_RING) << START_RING) | ((istation & MASK_STATION) << START_STATION) | ((iendcap & MASK_ENDCAP) << START_ENDCAP)

#get ring from cscdetid
def get_ring(index):
    if (((index  >> START_STATION) & MASK_STATION) == 1):
        iring = (index >> START_RING) & MASK_RING
        i = iring - 1
        if i == 0: i = 4
        return i
    else:
      return ((index >> START_RING) & MASK_RING)

#get chamber number from cscdetid
def get_chamber(index):
    return ((index >> START_CHAMBER) & MASK_CHAMBER)

#get station number from cscdetid
def get_station(index):
    return ((index >> START_STATION) & MASK_STATION)

#get endcap from cscid
def get_endcap(index):
    return ((index >> START_ENDCAP) & MASK_ENDCAP)

#Didn't use this function, but theoretically could shift all chambers by some common (dx, dy) vector
def nudge(dx, dy):
    global nudge_phi
    for iChamb in range(len(evt_tree.geo_cscDetID)):

        #Get chamber coords
        cscid = evt_tree.geo_cscDetID[iChamb]
        z = evt_tree.geo_cscZ[iChamb]
        theta = evt_tree.geo_cscTh[iChamb]
        phi = evt_tree.geo_cscPh[iChamb]

        r = z * math.tan(theta)
        x = r * math.cos(phi)
        y = r * math.Sin(phi)

        #Add shift to geometry
        x += dx
        y += dy

        r = math.sqrt(x*x + y*y)

        new_theta = math.arctan(r / z)
        new_phi = math.arctan(y / x)

        #get changes in radial coordinates
        dtheta = new_theta - theta
        dphi = new_phi - phi

        #save these
        station = station(cscid)
        endcap = endcap(cscid)
        ring = ring(cscid)
        sector = (chamber - 3) / 6 + 1
        if chamber < 3: sector = 6
        cscid, sb = get_sector_cscid_and_substation(station, ring, cscid)
        if sb == 1: station = 0

        #save this chamber shift in LUT format
        nudge_phi[endcap][sector][station][cscid] = dphi

evt_tree.GetEntry(0)

#get displacement of sector's origin from its hard-coded value (-22 + 15 + 60 * (sector - 1))
#sector origin is defined as teh origin of the lowest-neighbor chamber in station 2
def getSectorPhiDispDeg(endcap, sector):

    sector = 6 if sector == 1 else sector - 1
    return (phi_disp[endcap - 1][sector - 1][2][2] * nominal_pitch/2)

#Get global sector position by adding its displacement to its hard-coded value
def getGlobalSectorPhi(endcap, sector):
    return getSectorPhiDispDeg(endcap, sector) - 22 + 15 + (60 * (sector - 1))

#Get global chamber by adding phi_init (displacement from sector origin) to the sector's phi
def getGlobalChamberPhi(endcap, sector, station, substation, chamber):
    return getGlobalSectorPhi(endcap, sector) + (nominal_pitch/8.) * phi_init[endcap - 1][sector - 1][0 if substation == 1 else station][chamber - 1]

#Add chamber's theta_init (theta displacement from sector origin) to sector theta
def getGlobalTheta(endcap, sector, station, substation, chamber):
    return theta_init[endcap - 1][sector - 1][0 if substation == 1 else station][chamber - 1] * theta_scale + LOWER_THETA

#Convert original LUT to array format in order to draw/correct it
'''These chambers are organized in the following format:
        Endcaps (+1, -1)
            Sectors (1-6)
                "Stations" (Subsector 1, subsector 2, Station 2, Station 3, Station 4)
                    Chambers:
                        chamberID(station 1, subsector 1) - | 15 | 7 | 8 | 9 |
                                                            | 14 | 4 | 5 | 6 |
                                                            | 13 | 1 | 2 | 3 |
                                                            | 16 | 10| 11| 12|
                                                        - 15, 14, 13, and 16 are neighbor chambers
                                                        - subsector 2 is that same but no neighbors (12 chambers total)
                        RCSCID(station 1, subsector 1)    - | 9 | 7 | 8 | 9 |
                                                            | 6 | 4 | 5 | 6 |
                                                            | 3 | 1 | 2 | 3 |
                                                            | 3 | 1 | 2 | 3 |
                        chamberID (stations 2 - 4) -         | 11 | 4 | 5 | 6 | 7 | 8 | 9 |
                                                        |   10   |   1   |   2   |   3   |

'''
def file_to_array():

    #Phi Init: takes phi difference between chamber origin (wire 0, strip 0/MAX) and sector origin
    phi_init_flat = []
    with open(folder + 'ph_init_neighbor.txt') as f:
        #Read in text file and turn it into an array
        phi_init_flat = f.read().replace('\n', '')
        phi_init_flat = phi_init_flat.split(" ")

    #take out last element (its just a space)
    phi_init_flat = phi_init_flat[:-1]

    #We count the total number of entries to ensure they match-up with the file
    flat_index = 0
    for endcap in range(2):
        for sector in range(6):
            for s in range(5):
                for ch in range(16):
                    #Station 1, subsector 2 has 12 chambers
                    if s > 0 and ch > 11: continue
                    #Station 2-4 have 11 chambers
                    if s > 1 and ch > 10: continue
                    phi_init[endcap][sector][s][ch] = phi_init_flat[ flat_index ]
                    flat_index += 1

    #Number of terms we saved should equal number of elements in the file
    if flat_index == len(phi_init_flat): print("Phi Init Loaded")

    #Gets difference between preset hard phi and geometry phi of first strip in chamber
    #61 chambers per sector, 6 sectors, 2 endcaps
    phi_disp_flat = []
    with open(folder + 'ph_disp_neighbor.txt') as f:
        phi_disp_flat = f.read().replace('\n', '')
        phi_disp_flat = phi_disp_flat.split(" ")

    phi_disp_flat = phi_disp_flat[:-1]

    flat_index = 0
    for endcap in range(2):
        for sector in range(6):
            for s in range(5):
                for ch in range(16):
                    if s > 0 and ch > 11: continue
                    if s > 1 and ch > 10: continue
                    phi_disp[endcap][sector][s][ch] = phi_disp_flat[ flat_index ]
                    flat_index += 1

    if flat_index == len(phi_disp_flat): print("Phi Disp Loaded")

    #Gets difference between preset hard theta and geometry theta of first strip in chamber
    #61 chambers per sector, 6 sectors, 2 endcaps
    theta_init_flat = []
    with open(folder + 'th_init_neighbor.txt') as f:
        theta_init_flat = f.read().replace('\n', '')
        theta_init_flat = theta_init_flat.split(" ")

    theta_init_flat = theta_init_flat[:-1]

    flat_index = 0
    for endcap in range(2):
        for sector in range(6):
            for s in range(5):
                for ch in range(16):
                    if s > 0 and ch > 11: continue
                    if s > 1 and ch > 10: continue
                    theta_init[endcap][sector][s][ch] = theta_init_flat[ flat_index ]
                    flat_index += 1

    if flat_index == len(theta_init_flat): print("theta init Loaded")

    #Gets difference between preset hard theta and geometry theta of first strip in chamber
    #61 chambers per sector, 6 sectors, 2 endcaps
    theta_disp_flat = []
    with open(folder + 'th_disp_neighbor.txt') as f:
        theta_disp_flat = f.read().replace('\n', '')
        theta_disp_flat = theta_disp_flat.split(" ")

    theta_disp_flat = theta_disp_flat[:-1]

    flat_index = 0
    for endcap in range(2):
        for sector in range(6):
            for s in range(5):
                for ch in range(16):
                    if s > 0 and ch > 11: continue
                    if s > 1 and ch > 10: continue
                    theta_disp[endcap][sector][s][ch] = theta_disp_flat[ flat_index ]
                    flat_index += 1

    if flat_index == len(theta_disp_flat): print("theta disp Loaded")

    #Gets difference between wire theta and wire 0
    theta_lut_flat = []
    with open(folder + 'th_lut_neighbor.txt') as f:
        theta_lut_flat = f.read().replace('\n', '')
        theta_lut_flat = theta_lut_flat.split(" ")

    theta_lut_flat = theta_lut_flat[:-1]

    isME11A = False
    flat_index = 0

    #I decided to 1-index for this LUT in order to more efficiently mirror the coniditionals deciding the max-strips and max-wires
    for endcap in range(1, 3):
        for sector in range(1, 7):
            #index by station and then substation this time
            for s in range(1, 5):
                for sb in range(3):
                    for ch in range(1, 17):
                        #substation 0 does not exist for station 1
                        if s == 1 and sb == 0: continue
                        #stations 2-4 only use substation 0
                        if s > 1 and sb > 0: continue
                        is_neighbor = False
                        isME11A = False

                        #Decide whether a chamber is a neighbor or ME1/1a
                        #Consult the map at the start of this function to better understand what's going on here
                        if s == 1:
                            if ch <= 9: rcscid = ch
                            elif ch <= 12:
                                rcscid = ch - 9
                                isME11A = True
                            elif ch == 13: rcscid = 3
                            elif ch == 14: rcscid = 6
                            elif ch == 15:
                                rcscid = 9
                                isME11A = True
                            elif ch == 16:
                                rcscid = 3
                                is_ME11A = True
                            if ch > 12:
                                is_neighbor = True
                                rsector =  6 if (sector == 1) else sector - 1
                                rsb = 2
                        else:
                            if ch <= 9:
                                rcscid = ch
                            elif ch == 10: rcscid = 3
                            elif ch == 11: rcscid = 6
                            if ch > 9:
                                is_neighbor = True
                                rsector = 6 if (sector == 1) else sector - 1

                        #Set maxWires and maxStrips depending on chamber-type
                        if s == 1:
                            if rcscid <= 3: maxWire = 48
                            elif rcscid <= 6:
                                maxWire = 64
                            else: maxWire = 32
                        elif s == 2:
                            if rcscid <= 3: maxWire = 112
                            else: maxWire = 64
                        else:
                            if rcscid <= 3: maxWire = 96
                            else: maxWire = 64

                        if s == 1:
                            if isME11A: maxStrip = 48
                            elif rcscid <= 3: maxStrip = 64
                            elif 6 < rcscid and rcscid <= 9: maxStrip = 64
                            else: maxStrip = 80
                        else: maxStrip = 80

                        #Set cuts on number of chambers per subsector
                        if s == 1 and sb == 0: continue
                        if s == 1 and sb == 2 and ch > 12: continue
                        if s != 1 and ch > 11: continue

                        for wire in range(maxWire):
                            station = s
                            if sb == 1: station -= 1
                            #Store theta for every wire in a chamber
                            theta_lut[endcap - 1][sector - 1][station][ch - 1][wire] = theta_lut_flat[ flat_index ]
                            flat_index += 1
                        #account for padding (128 per chamber) for counting the elements
                        flat_index += 128 - maxWire

    if flat_index == len(theta_lut_flat): print("theta lut Loaded")

    theta_corr_lut_flat = []
    with open(folder + 'th_corr_lut_neighbor.txt') as f:
        theta_corr_lut_flat = f.read().replace('\n', '')
        theta_corr_lut_flat = theta_corr_lut_flat.split(" ")

    #This is only ME1/1 (both subsectors 1 and 2)
    theta_corr_lut_flat = theta_corr_lut_flat[:-1]

    #Identical to theta_lut above, but takes wires 1/6, 3/6, 5/6, and every other strip
    flat_index = 0
    for endcap in range(1, 3):
        for sector in range(1, 7):
            for s in range(1, 5):
                for sb in range(3):
                    for ch in range(1, 17):
                        if s == 1 and sb == 0: continue
                        if s > 1 and sb > 0: continue
                        is_neighbor = False
                        isME11A = False

                        if s == 1:
                            if ch <= 9: rcscid = ch
                            elif ch <= 12:
                                rcscid = ch - 9
                                isME11A = True
                            elif ch == 13: rcscid = 3
                            elif ch == 14: rcscid = 6
                            elif ch == 15:
                                rcscid = 9
                            elif ch == 16:
                                rcscid = 3
                                isME11A = True
                            if ch > 12:
                                is_neighbor = True
                                rsector =  6 if (sector == 1) else sector - 1
                                rsb = 2
                        else:
                            if ch <= 9:
                                rcscid = ch
                            elif ch == 10: rcscid = 3
                            elif ch == 11: rcscid = 9
                            if ch > 9:
                                is_neighbor = True
                                rsector = 6 if (sector == 1) else sector - 1

                        if s == 1:
                            if rcscid <= 3: maxWire = 48
                            elif rcscid <= 6:
                                maxWire = 64
                            else: maxWire = 32
                        elif s == 2:
                            if rcscid <= 3: maxWire = 112
                            else: maxWire = 64
                        else:
                            if rcscid <= 3: maxWire = 96
                            else: maxWire = 64

                        if s == 1:
                            if isME11A: maxStrip = 48
                            elif rcscid <= 3: maxStrip = 64
                            elif 6 < rcscid and rcscid <= 9: maxStrip = 64
                            else: maxStrip = 80
                        else: maxStrip = 80

                        if s == 1 and sb == 2 and ch > 12: continue
                        if s != 1 and ch > 11: continue

                        if s == 1 and rcscid <= 3 and not isME11A:
                            station  = s
                            if sb == 1: station -= 1
                            #For this LUT, we take wire 1/6, 3/6, 5/6
                            for wire in range(3):
                                #Take every other strip
                                for strip in range(0, maxStrip, 2):
                                    theta_corr_lut[endcap - 1][sector - 1][station][ch - 1][wire * maxStrip // 2 + strip // 2] = theta_corr_lut_flat[ flat_index ]
                                    flat_index += 1
                            flat_index += 128 - 3 * maxStrip // 2

    if flat_index == len(theta_corr_lut_flat): print("theta corr_lut Loaded")
    else:
        print("Mismatch! Length of File: " + str(len(theta_corr_lut_flat)) + ", Length of array: " + str(flat_index))

#Take station, ring, chamber and return cscid (1-16) and substation (0, 1, 2)
def get_sector_cscid_and_substation(station, ring, chamber):

    if station == 1 or ring == 2:
        sector_chamber = (chamber - 3) % 6 + 1
    else:
        sector_chamber = (chamber - 2) % 3 + 1

    sb = 0

    #ring order is ME1/b, ME1/2, ME1/3, ME1/1a
    if station == 1:
        sb = 1
        if sector_chamber > 3:
            sector_chamber -= 3
            sb = 2
        if ring == 2:
            sector_chamber += 3
        if ring == 3:
            sector_chamber += 6
        if ring ==4:
            sector_chamber += 9
    else:
        if ring == 2:
            sector_chamber += 3

    return (sector_chamber, sb)

#Finds station-station phi displacement per sector,station,endcap
'''Algorithm:
     1. Get station-station-dphi distribution of all sectors and station-station transitions from station_station_phi.py's output root file
     2. Per endcap: find station involved with lowest dphi transition^2 sum over its three transitions
     3. This lowest RMS station is the "reference station", which stays stationary and about which the other stations' sectors align
     4. Find shift for the six sectors in each of the other stations, taking their respective dphi to this "reference station"
'''
def correct_from_data():
    #Take average delta-phi for each endcap, station, and sector transition
    #Sector transitions are (1,2), (1,3),(1,4),(2,3),(2,4)(3,4)
    d_phi_shift = np.zeros(shape = (2, 36), dtype=object)
    f  = TFile(station_station_phi_data)
    for endcap in range(2):
        for chamber in range(36):
            #Get station-station-dphi average per transition/sector
            name = 'd_phi_chamber_%s_%d_%d_%d_c0' % ('(1, 2)', endcap, 0, chamber)
            dphi = f.Get(name)

            gauss_fit = dphi.Fit(formula='gaus', option='Q S')

            dphi_average = gauss_fit.Parameters()[1]
            dphi_average = dphi.GetMean()

            #Due to the non-linear nature of the d-phi average, the shift seems to need to be bigger than the average empirically (20%?)
            d_phi_shift[endcap][chamber] = dphi_average * 1.1

    #Return the array with shifts for each sector
    return d_phi_shift

#Add the shifts from correct_from_data() to each sector in the phi_init array and save our custom ph_init_neighbor.txt file
def write_to_file():
    #"station" is [subsector1, subsector2, station 2, station 3, station 4]
    count = 0
    with open(output + "ph_init_neighbor.txt", 'w') as new_file:
        for endcap in range(2):
            for sector in range(1,7):
                for st in range(5):
                    for ch in range(1, 17):
                        #maximum chambers per subsector
                        if st > 0 and ch > 12: continue
                        if st >1 and ch > 11: continue

                        if st == 0: sb = 1
                        elif st == 1: sb = 2
                        else: sb = 0
                        station = 0 if st == 0 else st - 1

                        #determine if a chamber is a neighbor, if so change its rsector to match its "real" sector
                        rsb = sb
                        rsector = sector
                        rcscid = ch
                        is_neighbor = False
                        if ch <= 9: rcscid = ch
                        elif ch <= 12:
                            rcscid = ch - 9
                            isME11A = True
                        elif ch == 13: rcscid = 3
                        elif ch == 14: rcscid = 6
                        elif ch == 15:
                            rcscid = 9
                        elif ch == 16:
                            rcscid = 3
                            isME11A = True

                        if ch > 12:
                            is_neighbor = True
                            rsector =  6 if (sector == 1) else sector - 1
                            rsb = 2

                        #get the chamber's phi init from the old file
                        old_phi_init = phi_init[endcap][sector - 1][st][ch - 1]

                        #Get the shift obtained from correct_from_data()
                        #may or may not use rsector here (still testing this)

                        if station == 0 and rcscid < 4:
                            sector_chamber = rcscid + 3 * (rsb - 1)
                            chamber = ((rsector - 1) * 6 + 1 + sector_chamber) % 36 + 1
                            shift = d_phi_shift[int(not endcap)][chamber - 1] / 2.
                            print("Endcap: %d, Station: %d, Sector: %d, Chamber: %d, cscid: %d, sector-chamber: %d, shift: %1.2f" % (not endcap, station + 1, rsector, chamber, ch, rcscid + 3*(rsb - 1), shift))
                        else: shift = 0
                        #Add shift to old LUT and save to new file
                        new_phi_init = int(round(old_phi_init + shift))
                        new_file.write(str(new_phi_init) + " ")

                        #new line every 30 entries
                        count += 1
                        if count % 30 == 0: new_file.write("\n")

#Array forms for all 6 LUTs
phi_init = np.zeros(shape=(2, 6, 5, 16))
phi_disp = np.zeros(shape=(2, 6, 5, 16))
theta_init = np.zeros(shape=(2, 6, 5, 16))
theta_disp = np.zeros(shape=(2, 6, 5, 16))
theta_corr_lut = np.zeros(shape=(2, 6, 2, 16, 96))
theta_lut = np.zeros(shape=(2, 6, 5, 16, 112))

#Save files to arrays
file_to_array()

#Find sector shifts from data
d_phi_shift = correct_from_data()

#functions for writing shifts to new LUTs and validating with EMTFNtuple file
print(phi_init[0][5][1][2])
write_to_file()


from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib import messages
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
from django.contrib.auth.decorators import login_required
from rest_framework import viewsets

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Request, Listing, Profile, Review
from django.contrib.auth.models import User
from django.db.models import Q
from .serializers import *

# Create your views here.

def home(request):
    return render(request, 'flitting/home.html')

def listing(request):
    return render(request, 'flitting/listing.html')

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            messages.success(request, f'Your account has been created')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'flitting/register.html', {'form': form})

# define profile for flitting app

@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                   request.FILES,
                                   instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            messages.success(request, f'Your account has been udpated')
            return redirect('flitting-profile')
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile)
    context = {
        'u_form': u_form,
        'p_form': p_form
    }
    return render(request, 'flitting/profile.html', context)

# Viewset for profile android call
@api_view(['GET'])
def getRequest(request, pk):
    try:
        r = Request.objects.get(pk=pk)
    except Request.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = RequestSerializer(r)
    return Response(serializer.data)

@api_view(['GET'])
def getListing(request, pk):
    try:
        r = Listing.objects.get(pk=pk)
    except Listing.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ListingSerializer(r)
    return Response(serializer.data)

@api_view(['GET'])
def getUser(request, pk):
    try:
        r = Profile.objects.get(user=pk)
    except Profile.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ProfileSerializer(r)
    return Response(serializer.data)

@api_view(['GET'])
def getListingsOf(request, userId):
    try:
        r = Listing.objects.all().filter(user=userId)
    except Listing.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ListingSerializer(r, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def getReviewsOf(request, userId):
    try:
        r = Review.objects.all().filter(helper=userId)
    except Review.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ReviewSerializer(r, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def getRequestsOf(request, userId):
    try:
        r = Request.objects.all().filter(helper=userId)
    except Request.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = RequestSerializer(r, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def searchListing(request):
    query = request.GET.get('q', None)
    try:
        ps = [u.user.id for u in Profile.objects.all()
              .filter(Q(user__first_name__icontains=query) | Q(user__last_name__icontains=query))]
        print(len(ps))
        ls = Listing.objects.all().filter(Q(city__icontains=query)
                                          | Q(country__icontains=query)
                                          | Q(category__icontains=query)
                                          | Q(user__in=ps))
        print(len(ls))
    except Profile.DoesNotExist:
        print("no users!")
    except Listing.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ListingSerializer(ls, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def getReviewsOf(request, userId):
    try:
        r = Review.objects.all().filter(helper=userId)
    except Review.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ReviewSerializer(r, many=True)
    return Response(serializer.data)

# class ProfileViewSet(viewsets.ModelViewSet):
#     quertset=


from random import randrange

'''
probability function
    - creates a possible instance of an array of 3 numbers randomly selected from numbers: 1-5
    - input     // nothing
    - output    // an array of 3 numbers
'''

def prob_function():
    B = []
    for b in range(3):
        can_number = randrange(1,5)
        B.append(can_number)
    return B

if __name__ == "__main__":
    event = 0
    print("The numbers 1-5 are randomly generated and selected into an array of 3 elements."
          "\nWhat is the frequency that all of the elements in the array are different numbers?")
    trials = int(input("Enter number of trials: "))

    #comment outside loop

    for i in range(trials):
        i += 1
        test = prob_function()
        if ((test[0] != test[1]) and (test[0] != test[2]) and (test[1] != test[2])):
            event += 1

    answer = event/trials
    print(answer)