import sys
import numpy as np

from tensorflow.keras.applications import VGG16
from tensorflow.keras.applications.vgg16 import preprocess_input

from FaultInjector.StuckAtFaultInjector import StuckAtFaultInjector
from RunManager.NetworkManager import NetworkManager

from FaultDetector.FaultDetectorMetrics import FaultDetectorMetrics
from FaultDetector.ScoreBasedFaultDetector import ScoreBasedFaultDetector
from FaultDetector.MavFaultDetector import MavFaultDetector
from FaultDetector.FaultDetectorEvaluator import FaultDetectorEvaluator

if __name__ == "__main__":

    # Testing_dir: The folder where the testing dataset using to perform the inference. This is used to compute how much
    #              a fault impacts a run
    # Detection_dir: The folder containing the detection dataset used to compute the metrics useful for the fault
    #                detectors.
    testing_dir = sys.argv[1]
    detection_dir = sys.argv[2]

    # mav_dir: where to load/save the file containing the mean activation vector for the detection dataset.
    # threshold_dir: where to load/save the file containing the threshold for the detection dataset.
    mav_file_location = sys.argv[3]
    # threshold_file_location = sys.argv[4]

    number_of_experiments = 1000

    batch_size = 128

    top_n = 5
    output_format = 'pickle'
    number_of_faults_list = [25, 50, 75, 100, 125]
    max_fault_list_length = 1000

    generator_seed = 1234
    generator = np.random.default_rng(generator_seed)

    list_beginning = 0
    list_end = 100

    seed_list = generator.choice(int(10e6), size=number_of_experiments, replace=False)
    seed_list = seed_list[list_beginning: list_end]

    # STEP 1 - Golden Run
    # 1.1 - Create the network
    vgg = VGG16(classifier_activation=None)
    vgg.compile(metrics=['accuracy'])
    # 1.2 - Initialize the network manager
    network_manager = NetworkManager(network=vgg, dataset_dir=testing_dir)

    # 1.3 - Initialize the fault detector metrics
    metrics = FaultDetectorMetrics(network=vgg, dataset_dir=detection_dir)
    open_max_activation_vectors = metrics.compute_mean_activation_vectors(file_location=f'{mav_file_location}/mav.pkl',
                                                                          pre_processing_function=preprocess_input)
    open_max_distances = metrics.compute_mav_distance(mav=open_max_activation_vectors,
                                                      file_location=f'{mav_file_location}/distance.pkl',
                                                      pre_processing_function=preprocess_input)

    open_max_weibull = metrics.fit_weibull(open_max_distances,
                                           tail_size=20)

    # score_based_threshold = metrics.compute_score_based_threshold(file_location=threshold_file_location,
    #                                                               pre_processing_function=preprocess_input)

    # 1.4 - Execute the golden run
    print(f'Starting golden run... \n')
    network_manager.run_and_export(run_name=f'vgg_imagenet',
                                   output_dir='GoldenRunResults-OpenMax',
                                   top_n=top_n,
                                   output_format=output_format,
                                   pre_processing_function=preprocess_input,
                                   open_max_activation_vectors=open_max_activation_vectors,
                                   open_max_weibull=open_max_weibull)

    network_manager.save_golden_results()

    # STEP 2 - Faulty Run
    for count, seed in enumerate(seed_list):
        print(f'Beginning run #{count} of {len(seed_list)}.\n')
        # 2.1 - reset the network to its original state (i.e. load the original weights)
        network_manager.reset_network()
        # 2.2 - Initialize the fault injector
        fault_injector = StuckAtFaultInjector(vgg, seed)
        # 2.3 - Generate a fault list and perform a fault injection campaign for the number of faults in the list
        for number_of_faults in number_of_faults_list:
            fault_injector.fault_injection_campaign(number_of_faults=number_of_faults,
                                                    folder_path='FaultList',
                                                    fault_list_length=max_fault_list_length)

            # 2.4 - Execute a faulty run
            print(f'Starting faulty run {seed}_{number_of_faults}... \n')
            inference_results = network_manager.run_and_export(run_name=f'vgg_imagenet_{seed}_{number_of_faults}',
                                                               output_dir='FaultyRunResults-OpenMax',
                                                               top_n=top_n,
                                                               compute_sdc_metrics=True,
                                                               output_format=output_format,
                                                               pre_processing_function=preprocess_input,
                                                               open_max_activation_vectors=open_max_activation_vectors,
                                                               open_max_weibull=open_max_weibull)

            # 2.5 - Initialize the fault detectors
            # score_based_fault_detector = ScoreBasedFaultDetector(inference_result=inference_results,
            #                                                      threshold=score_based_threshold)
            # mav_fault_detector = MavFaultDetector(inference_result=inference_results,
            #                                       threshold=open_max_threshold)

            # 2.6 - Run the fault detectors
            # score_based_fault_detector_results = score_based_fault_detector.detect_faults()
            # mav_fault_detector_results = mav_fault_detector.detect_faults()

            # 2.7 - Evaluate the performance of the fault detectors
            # score_based_evaluation = FaultDetectorEvaluator.evaluate_and_export_fault_detector(
            #     fault_detector_dict=score_based_fault_detector_results,
            #     run_sdc=inference_results,
            #     file_name=f'vgg_imagenet_{seed}_{number_of_faults}_score_based',
            #     output_dir='FaultDetectorResults')
            # mav_evaluation = FaultDetectorEvaluator.evaluate_and_export_fault_detector(
            #     fault_detector_dict=mav_fault_detector_results,
            #     run_sdc=inference_results,
            #     file_name=f'vgg_imagenet_{seed}_{number_of_faults}_mav',
            #     output_dir='FaultDetectorResults')


from fastapi import APIRouter

from app.api.segmentation import doc_parser, paddle
from app.core.config import settings
from app.schemas.doc_parser import ImageInput, ImageOutput

router = APIRouter(prefix="/segment", tags=["segment"])

@router.post("/detect-image")
async def doc_parser_api(*, img_in: ImageInput):
    # print("requesting `doc_parser_api`")
    return await doc_parser.detect_image(img_in)

@router.post("/detect-text")
async def paddle_api(*, img_in: ImageInput):
    # print("requesting `paddle_text_api`")
    return await paddle.detect_text(img_in)

@router.post("/detect-bitmap")
async def paddle_bitmap_api(*, img_in: ImageInput):
    # print("requesting `paddle_bitmap_api`")
    return await paddle.db_detect_bitmap(img_in)

@router.post("/detect-text-fast")
async def paddle_math_api(*, img_in: ImageInput):
    # print("requesting `detect_text_fast`")
    return await paddle.detect_text_fast(img_in)


import contextlib
import hashlib
import httplib
import socket
import tempfile
import urllib2

try:
    from PIL import Image as PILImage
except ImportError:
    import Image as PILImage  # noqa

from django.conf import settings
from django.core.files import File
from django.db import transaction

from comics.aggregator.exceptions import (
    DownloaderHTTPError, ImageTypeError, ImageIsCorrupt, ImageAlreadyExists,
    ImageIsBlacklisted)
from comics.core.models import Release, Image

# Image types we accept, and the file extension they are saved with
IMAGE_FORMATS = {
    'GIF': '.gif',
    'JPEG': '.jpg',
    'PNG': '.png',
}

class ReleaseDownloader(object):
    def download(self, crawler_release):
        images = self._download_images(crawler_release)
        return self._create_new_release(
            crawler_release.comic, crawler_release.pub_date, images)

    def _download_images(self, crawler_release):
        image_downloader = ImageDownloader(crawler_release)
        return map(image_downloader.download, crawler_release.images)

    @transaction.commit_on_success
    def _create_new_release(self, comic, pub_date, images):
        release = Release(comic=comic, pub_date=pub_date)
        release.save()
        for image in images:
            release.images.add(image)
        return release

class ImageDownloader(object):
    def __init__(self, crawler_release):
        self.crawler_release = crawler_release

    def download(self, crawler_image):
        self.identifier = self.crawler_release.identifier

        with self._download_image(
                crawler_image.url, crawler_image.request_headers
                ) as image_file:
            checksum = self._get_sha256sum(image_file)
            self.identifier = '%s/%s' % (self.identifier, checksum[:6])

            self._check_if_blacklisted(checksum)

            existing_image = self._get_existing_image(
                comic=self.crawler_release.comic,
                has_rerun_releases=self.crawler_release.has_rerun_releases,
                checksum=checksum)
            if existing_image is not None:
                return existing_image

            image = self._validate_image(image_file)

            file_extension = self._get_file_extension(image)
            file_name = self._get_file_name(checksum, file_extension)

            return self._create_new_image(
                comic=self.crawler_release.comic,
                title=crawler_image.title,
                text=crawler_image.text,
                image_file=image_file,
                file_name=file_name,
                checksum=checksum)

    def _download_image(self, url, request_headers):
        try:
            request = urllib2.Request(url, None, request_headers)
            with contextlib.closing(urllib2.urlopen(request)) as http_file:
                temp_file = tempfile.NamedTemporaryFile(suffix='comics')
                temp_file.write(http_file.read())
                temp_file.seek(0)
                return temp_file
        except urllib2.HTTPError as error:
            raise DownloaderHTTPError(self.identifier, error.code)
        except urllib2.URLError as error:
            raise DownloaderHTTPError(self.identifier, error.reason)
        except httplib.BadStatusLine:
            raise DownloaderHTTPError(self.identifier, 'BadStatusLine')
        except socket.error as error:
            raise DownloaderHTTPError(self.identifier, error)

    def _get_sha256sum(self, file_handle):
        original_position = file_handle.tell()
        hash = hashlib.sha256()
        while True:
            data = file_handle.read(8096)
            if not data:
                break
            hash.update(data)
        file_handle.seek(original_position)
        return hash.hexdigest()

    def _check_if_blacklisted(self, checksum):
        if checksum in settings.COMICS_IMAGE_BLACKLIST:
            raise ImageIsBlacklisted(self.identifier)

    def _get_existing_image(self, comic, has_rerun_releases, checksum):
        try:
            image = Image.objects.get(comic=comic, checksum=checksum)
            if image is not None and not has_rerun_releases:
                raise ImageAlreadyExists(self.identifier)
            return image
        except Image.DoesNotExist:
            return None

    def _validate_image(self, image_file):
        try:
            image = PILImage.open(image_file)
            image.load()
            return image
        except IndexError:
            raise ImageIsCorrupt(self.identifier)
        except IOError as error:
            raise ImageIsCorrupt(self.identifier, error.message)

    def _get_file_extension(self, image):
        if image.format not in IMAGE_FORMATS:
            raise ImageTypeError(self.identifier, image.format)
        return IMAGE_FORMATS[image.format]

    def _get_file_name(self, checksum, extension):
        if checksum and extension:
            return '%s%s' % (checksum, extension)

    @transaction.commit_on_success
    def _create_new_image(
            self, comic, title, text, image_file, file_name, checksum):
        image = Image(comic=comic, checksum=checksum)
        image.file.save(file_name, File(image_file))
        if title is not None:
            image.title = title
        if text is not None:
            image.text = text
        image.save()
        return image


import json
import uuid
import websocket
import time
import threading
from parlai.core.params import ParlaiParser

# the socket callback functions operate asynchronously.
# upon exit of a chat, we do not want the user to view any additional messages from the server.
# alas, it is necessary to send two messages ([DONE], and EXIT) in order to fully exist the world pool
# to prevent receiving a message after sending [DONE], we track the user's state with
# this global variable.
RUNNING = True

def _get_rand_id():
    """
    :return: The string of a random id using uuid4
    """
    return str(uuid.uuid4())

def _prBlueBG(text):
    """
    Print given in text with a blue background.

    :param text: The text to be printed
    """
    print("\033[44m{}\033[0m".format(text), sep="")

def on_message(ws, message):
    """
    Prints the incoming message from the server.

    :param ws: a WebSocketApp
    :param message: json with 'text' field to be printed
    """
    if not RUNNING:
        return
    incoming_message = json.loads(message)
    print("\033[0m\n")
    print("Bot: " + incoming_message['text'])
    quick_replies = incoming_message.get('quick_replies')
    if quick_replies is not None and len(quick_replies) > 0:
        print(f"\nOptions: [{'|'.join(quick_replies)}]")
    print("\033[44m\n")

def on_error(ws, error):
    """
    Prints an error, if occurs.

    :param ws: WebSocketApp
    :param error: An error
    """
    print(error)

def on_close(ws):
    """
    Cleanup before closing connection.

    :param ws: WebSocketApp
    """
    # Reset color formatting if necessary
    print("\033[0m")
    print("Connection closed")

def _run(ws, id):
    """
    Takes user input and sends it to a websocket.

    :param ws: websocket.WebSocketApp
    """
    global RUNNING
    while True:
        x = input("\033[44m Me: ")
        print("\033[0m", end="")
        data = {}
        data['id'] = id
        data['text'] = x
        if x == "[DONE]":
            RUNNING = False
        json_data = json.dumps(data)
        ws.send(json_data)
        time.sleep(1)
        if x == "[DONE]":
            time.sleep(1)
            data['text'] = 'EXIT'
            ws.send(json.dumps(data))
            break
    ws.close()

def on_open(ws):
    """
    Starts a new thread that loops, taking user input and sending it to the websocket.

    :param ws: websocket.WebSocketApp that sends messages to a terminal_manager
    """
    id = _get_rand_id()
    threading.Thread(target=_run, args=(ws, id)).start()

def setup_args():
    """
    Set up args, specifically for the port number.

    :return: A parser that parses the port from commandline arguments.
    """
    parser = ParlaiParser(False, False)
    parser_grp = parser.add_argument_group('Terminal Chat')
    parser_grp.add_argument(
        '--port', default=35496, type=int, help='Port to run the terminal chat server'
    )
    parser_grp.add_argument(
        '--host', default='localhost', type=str, help='Host to connect to.'
    )
    return parser.parse_args()

if __name__ == "__main__":
    opt = setup_args()
    port = opt.get('port', 34596)
    host = opt.get('host', 'localhost')
    print("Connecting to port: ", port)
    ws = websocket.WebSocketApp(
        f"ws://{host}:{port}/websocket",
        on_message=on_message,
        on_error=on_error,
        on_close=on_close,
    )
    ws.on_open = on_open
    ws.run_forever()


import numpy as np
import os
import argparse
import h5py
import sys
from spad_tools.listFiles import listFiles
from spad_tools.array2tiff import array2tiff, array2RGBtiff
from spad_tools.getFCSinfo import getFileInfo
from libttp import ttp

"""
This set of functions allows to read a binary file containing SPAD measurements
using only the file name. The parameters are extracted from the matrix using
the tags. The assumpstion is that the parameters are constant and that all the
frames are complete.
Author: Sebastian Acuna
"""

def file_to_count(fname, datatype=np.uint16, printInfo=False):
    """
    Read a bin file and returns an array with the decoded count for each measurement
    Args:
        fname: name of the file containing the data

    Returns:
        A numpy array of unsigned int16 os size N x 25 where N is the number of measurements
    """
    try:
        raw = np.fromfile(fname, dtype=">u8")

    except:
        if printInfo:
            print("Error reading binary file")
        return None

    elements = raw.shape[0]
    positions = int(elements/2)
    raw_pos = np.reshape(raw, (positions, 2))
    if printInfo:
        print(f"Elements: {elements}")
        print(f"Positions: {positions}")
        print(f"data table: {raw_pos.shape}")

    time_per_pixel_tag = np.bitwise_and(raw_pos[:,1], 0b1)
    idx = np.argmax(time_per_pixel_tag != time_per_pixel_tag[0]) # positions per time
    time_per_pixel = int(idx)
    if printInfo:
        print(f"time per pixel: {time_per_pixel}")

    frame_tag = np.bitwise_and(np.right_shift(raw_pos[:,1], 2), 0b1)
    idx = np.argmax(frame_tag != frame_tag[0]) # positions per frame
    if idx == 0:
        if printInfo:
            print("Unique frame")
        frames = 1
    else:
        frames = int(positions/idx) # TODO: check condition with larger dataset

    line_tag = np.bitwise_and(np.right_shift(raw_pos[:,1], 1), 0b1)
    idx = int(np.argmax(line_tag != line_tag[0])/time_per_pixel) # positions  per line
    if printInfo:
        print(f"Positions per lines: {idx}")
    x = int(idx)
    y = int(positions/x/time_per_pixel/frames)

    if printInfo:
        print(f"Dimensions: Y:{y}, X:{x}")

    out = np.zeros((positions , 25), dtype = datatype)

    matrix_to_count(raw_pos, out)

    return out, frames, y, x, time_per_pixel

def file_to_FCScount(fname, datatype=np.uint16, Npoints=-1, Noffset=0):
    """
    Read a bin file and returns an array with the decoded count for each measurement
    Args:
        fname: name of the file containing the data
    Returns:
        A numpy array of unsigned int16 os size N x 25 where N is the number of measurements
    """
    try:
        Npoints = Npoints * 2
        NbytesOffset = 16 * Noffset
        raw = np.fromfile(fname, dtype=">u8", count=Npoints, offset=NbytesOffset)

    except:
        print("Error reading binary file")
        return None

    elements = raw.shape[0]
    print(f"Elements: {elements}")
    positions = int(elements/2)
    print(f"Positions: {positions}")

    print("Freeing memory")
    out = np.zeros((positions , 25), dtype = datatype)
    print("Done.")

    raw_pos = np.reshape(raw, (positions, 2))
    print(f"data table: {raw_pos.shape}")

    print("Converting data to counts")
    matrix_to_count(raw_pos, out)
    print("Done.")

    return out

def matrix_to_count(values, out):
    """
    Read an array of N measurements and write the count values in the out
    array

    Args:
        values: N x 2 unsigned int array with measurements
        out:    N x 25 unsigned int array for storing results

    Returns:
        The matrix out filled with the count
    """

    out[:,0] = np.bitwise_and(np.right_shift(values[:,0], 64 - 59), 0b1111) # 4 bits
    out[:,1] = np.bitwise_and(np.right_shift(values[:,0], 64 - 55), 0b1111) # 4 bits
    out[:,2] = np.bitwise_and(np.right_shift(values[:,0], 64 - 51), 0b1111) # 4 bits
    out[:,3] = np.bitwise_and(np.right_shift(values[:,0], 64 - 47), 0b1111) # 4 bits
    out[:,4] = np.bitwise_and(np.right_shift(values[:,0], 64 - 43), 0b1111) # 4 bits
    out[:,5] = np.bitwise_and(np.right_shift(values[:,0], 64 - 39), 0b1111) # 4 bits

    out[:,6] = np.bitwise_and(np.right_shift(values[:,1], 64 - 59), 0b11111) # 5 bits
    out[:,7] = np.bitwise_and(np.right_shift(values[:,1], 64 - 54), 0b111111) # 6 bits
    out[:,8] = np.bitwise_and(np.right_shift(values[:,1], 64 - 48), 0b11111) # 5 bits
    out[:,9] = np.bitwise_and(np.right_shift(values[:,1], 64 - 43), 0b1111) # 4 bits
    out[:,10] = np.bitwise_and(np.right_shift(values[:,1], 64 - 39), 0b1111) # 4 bits
    out[:,11] = np.bitwise_and(np.right_shift(values[:,1], 64 - 35), 0b111111) # 6 bits
    out[:,12] = np.bitwise_and(np.right_shift(values[:,1], 64 - 29), 0b1111111111) # 10 bits
    out[:,13] = np.bitwise_and(np.right_shift(values[:,1], 64 - 19), 0b111111) # 6 bits
    out[:,14] = np.bitwise_and(np.right_shift(values[:,1], 64 - 13), 0b1111) # 4 bits
    out[:,15] = np.bitwise_and(np.right_shift(values[:,1], 64 - 9), 0b1111) # 4 bits
    out[:,16] = np.right_shift(values[:,1], 64 - 5) # 5 bits

    out[:,17] = np.bitwise_and(np.right_shift(values[:,0], 64 - 35), 0b111111) # 6 bits
    out[:,18] = np.bitwise_and(np.right_shift(values[:,0], 64 - 29), 0b11111) # 5 bits
    out[:,19] = np.bitwise_and(np.right_shift(values[:,0], 64 - 24), 0b1111) # 4 bits
    out[:,20] = np.bitwise_and(np.right_shift(values[:,0], 64 - 20), 0b1111) # 4 bits
    out[:,21] = np.bitwise_and(np.right_shift(values[:,0], 64 - 16), 0b1111) # 4 bits
    out[:,22] = np.bitwise_and(np.right_shift(values[:,0], 64 - 12), 0b1111) # 4 bits
    out[:,23] = np.bitwise_and(np.right_shift(values[:,0], 64 - 8), 0b1111) # 4 bits
    out[:,24] = np.bitwise_and(np.right_shift(values[:,0], 64 - 4), 0b1111) # 4 bits

def reshape_to_5d(count, frames, y, x, time_per_pixel):
    """
    Reshapes the 2D count matrix to a 5D array (frames, y, x, time, sensor)

    Args:
        count: N x 25 count matrix
        frames: number of frames contained in matrix
        y:
        x:
        time:

    Returns:
        A 5-D matrix with dimensions (frames, y, x, time, sensor)
    """

    return np.reshape(count, (frames, y, x, time_per_pixel, 25))

def reshape_to_6d(count, r, z, y, x, t=1, c=25):
    """
    Reshapes the data to a 6D array

    Args:
        count: N x 25 count matrix
        frames: number of frames contained in matrix
        y:
        x:
        time:

    Returns:
        A 6-D matrix with dimensions (r, z, y, x, time, sensor)
    """

    return np.reshape(count, (r, z, y, x, t, 25))

def image2h5(fname, sumTime=True, saveTimeInd=False):
    """
    Convert bin file to h5 file
        fname       file name
        sumTime     True to sum over all time bins, false otherwise
        saveTimeInd Save all time frames in separate files
        TO DO:
            add metadata to file:
                data.pixelsize = 0.05
                data.pixelsizeU = 'um', etc.
    """
    print(fname)
    [out, frames, y, x, time_per_pixel] = file_to_count(fname)
    data = reshape_to_5d(out, frames, y, x, time_per_pixel)
    if np.ndim(data) == 4 and frames == 1 and sumTime:
        # 4D data set [y, x, time, ch] --> sum over time bins
        dataOut = np.sum(data, 2)
        dataOut = np.float64(dataOut)
        # channel must be first channel
        dataOut = np.transpose(dataOut, (2, 0, 1))
    elif np.ndim(data) == 5 and sumTime:
        # 5D data set [z, y, x, time, ch] --> sum over time bins
        dataOut = np.sum(data, 3)
        dataOut = np.float64(dataOut)
        dataOut = np.transpose(dataOut, (3, 0, 1, 2))
    else:
        print('not summed over time bins')
        # channel must be first channel
        dataOut = np.squeeze(data)
        if saveTimeInd:
            dataOut = np.transpose(dataOut, (3, 0, 1, 2))

    dataOut = np.squeeze(dataOut)

    if type(saveTimeInd) == bool and saveTimeInd:
        for i in range(np.shape(dataOut)[-1]):
            print("Saving frame " + str(i))
            h5f = h5py.File(fname[:-4] + "_frame_" + str(i) + ".h5", 'w')
            h5f.create_dataset('dataset_1', data=dataOut[:,:,:,i])
            h5f.close()
    elif saveTimeInd == "alternate":
        # channel, y, x, time
        Nt = np.shape(dataOut)[-1]
        for sumT in range(int(Nt/2)):
            print("Summing over " + str(sumT+1) + " frames")
            dataOutSum0 = np.squeeze(np.sum(dataOut[:,:,:,0:2*sumT+1:2], 3))
            dataOutSum1 = np.squeeze(np.sum(dataOut[:,:,:,1:2*sumT+2:2], 3))
            # store frame 0
            h5f = h5py.File(fname[:-4] + "_sum_" + str(sumT+1) + "_frame_0.h5", 'w')
            h5f.create_dataset('dataset_1', data=dataOutSum0)
            h5f.close()
            # store frame 1
            h5f = h5py.File(fname[:-4] + "_sum_" + str(sumT+1) + "_frame_1.h5", 'w')
            h5f.create_dataset('dataset_1', data=dataOutSum1)
            h5f.close()
    else:
        h5f = h5py.File(fname[:-3] + "h5", 'w')
        h5f.create_dataset('dataset_1', data=dataOut)
        h5f.close()

    return dataOut

def ttr2h5(fnamettr, reorder25channels=True, CHANNELS=25, laser_MHz=80.0, dwell_time_us=10):
    df = ttp.readNewProtocolFileToPandas(fnamettr, reorder25channels=reorder25channels, CHANNELS=CHANNELS)
    ttp.convertFromPandasDataFrame(df, fnamettr[:-4] + '.h5', laser_MHz=laser_MHz, dwell_time_us=dwell_time_us, list_of_channels=list(np.arange(CHANNELS)))

def allTtr2h5(folder=''):
    files = listFiles(folder, filetype='ttr')
    filesh5 = listFiles(folder, filetype='h5')
    for i, file in enumerate(filesh5):
        filesh5[i] = file[:-3] + '.ttr'
    for file in files:
        if file not in filesh5:
            print("converting " + file)
            ttr2h5(file)
    print('Done')

def bin2h5(fname):
    """
    Convert bin file to h5 file with always 6D (r, z, x, y, t, c)
        fname       file name
            add metadata to file:
                data.pixelsize = 0.05
                data.pixelsizeU = 'um', etc.
    """

    [out, frames, y, x, time_per_pixel] = file_to_count(fname)
    data = reshape_to_6d(out, 1, frames, y, x, time_per_pixel, 25)

    # store data
    h5f = h5py.File(fname[:-4] + ".h5", 'w')
    h5f.create_dataset('dataset_1', data=data)
    h5f.close()
    print('Done')

def allBinImages2tiff(folder):
    """
    Convert all bin files in a folder to tiff images
        folder      path to folder (use either \\ or / to go into a folder)
    """
    files = listFiles(folder)
    for file in files:
        print("saving " + file)
        dummy = image2tiff(file)

def image2tiff(fname):
    """
    Convert bin file to tiff image file
        fname       file name
    """

    [out, frames, y, x, time_per_pixel] = file_to_count(fname)
    data = reshape_to_5d(out, frames, y, x, time_per_pixel)
    print(np.shape(data))
    info = getFileInfo(fname[:-4] + '_info.txt')
    if np.ndim(data) == 4 and frames == 1:
        # 4D data set [y, x, time, ch] --> sum over time bins
        dataOut = np.sum(data, 2)
    elif np.ndim(data) == 5:
        # 5D data set [z, y, x, time, ch] --> sum over time bins and z
        dataOut = np.sum(data, 3)
        dataOut = np.sum(dataOut, 0)

    dataOut = np.float64(dataOut)
    dataOut = np.squeeze(dataOut)

    print(np.shape(dataOut))

    array2tiff(dataOut, fname[:-4], pxsize=info.pxsize, dim="yxz", transpose3=True)
    array2RGBtiff(np.sum(dataOut, 2), fname[:-4] + '_RGB')

def allBinImages2h5(folder, sumTime=True, saveTimeInd=False):
    """
    Convert all bin files in a folder to h5 files
        folder      path to folder (use either \\ or / to go into a folder)
        sumTime     True to sum over all time bins, false otherwise
    """
    files = listFiles(folder)
    for file in files:
        print("converting " + file)
        dummy = image2h5(file, sumTime, saveTimeInd)

if __name__ == "__main__":

    parser = argparse.ArgumentParser(
        description="Converter from binary file to measurement matrix"
    )

    parser.add_argument(
        "binary",
        help="binary file name")

    args = parser.parse_args()
    fname = args.binary
    count, frames, y, x, time_per_pixel = file_to_count(fname)

    if count is None:
        print("Failed to process data. Closing.")
        sys.exit(0)

    file_name, extension = os.path.splitext(fname) # Get filename without extension

    print("Saving 5D matrix...", sep="")
    count5d = reshape_to_5d(count, frames, y, x, time_per_pixel)
    np.save(file_name + ".npy", count5d)
    print("Done.")


import argparse

from . import board
from . import constants
from . import solver

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("board", nargs="?")
    parser.add_argument("-m", "--manual", default=False, action="store_true")
    return parser.parse_args()

def main():
    args = parse_args()

    if not args.board:
        main_board = board.Board(constants.TEST_BOARD)
    else:
        main_board = board.Board(args.board)

    # print(tile.Tile.get((1, 1)).render())
    # print(tile.Tile.get((2, 2)).render())
    # print(main_board.render())

    s = solver.Solver(main_board, manual=args.manual)
    s.solve()

if __name__ == '__main__':
    main()


class Subscriber:
    def __init__(self):
        self.clients = []

    def add(self, name, email):
        for client in self.clients:
            if client["name"] == name and client["email"] == email:
                raise Exception("This client exists")
        if type(name) == str and type(email) == str:
            self.clients.append({"name": name, "email": email})
            return self.clients
        else:
            raise TypeError("Bad type name or/and email")

    def delete(self, name, email):
        for client in self.clients:
            if client["name"] == name and client["email"] == email:
                self.clients.remove({"name": name, "email": email})
                return "Delete: %s, email: %s" % (name, email)

        raise Exception("Lack client")

    def sendMessage(self, email, textMessage):
        for client in self.clients:
            if client["email"] == email:
                if type(textMessage) == str:
                    return "Send message to %s" % email
                else:
                    raise TypeError("Type text message have to be string")
        raise Exception("No client has this email")

from unittest.mock import *
from unittest import TestCase, main

class testSubscriber(TestCase):
    def setUp(self):
        self.temp = Subscriber()

    def test_add_client_OK(self):
        self.temp.add = Mock()
        self.temp.add.return_value = [{"name": "Piotr", "email": "piotrnowak@example.com"}]

        result = self.temp.add("Piotr", "piotrnowak@example.com")
        self.assertListEqual(result, [{"name": "Piotr", "email": "piotrnowak@example.com"}])

    def test_add_client_BAD_exists(self):
        self.temp.add = Mock()
        self.temp.clients = [{"name": "Piotr", "email": "piotrnowak@example.com"}]
        self.temp.add.side_effect = Exception("This client exists")

        result = self.temp.add
        self.assertRaisesRegex(Exception, "This client exist", result, "Piotr", "piotrnowak@example.com")

    def test_add_client_BAD_name(self):
        self.temp.add = Mock()
        self.temp.add.side_effect = TypeError("Bad type name or/and email")
        result = self.temp.add
        self.assertRaisesRegex(TypeError, "Bad type name or/and email", result, 123, "piotrnowak@example.com")

    def test_delete(self):
        self.temp.delete = Mock()
        self.temp.clients = [{"name": "Wiktoria", "email": "wolnikowa@example.com"},
                             {"name": "Kasia", "email": "kasiapolak@example.com"}]
        self.temp.delete.return_value = "Delete: Wiktoria, email: wolnikowa@example.com"
        result = self.temp.delete("Wiktoria", "wolnikowa@example.com")
        self.assertEqual(result, "Delete: Wiktoria, email: wolnikowa@example.com")

    def test_delete_client_lack_client(self):
        self.temp.delete = Mock()
        self.temp.clients = [{"name": "Wiktoria", "email": "wolnikowa@example.com"},
                             {"name": "Kasia", "email": "kasiapolak@example.com"}]
        self.temp.delete.side_effect = Exception("Lack client")
        result = self.temp.delete
        self.assertRaisesRegex(Exception, "Lack client", result, "Filip", "filipostrowski@example.com")

    def test_send_message(self):
        self.temp.sendMessage = Mock()
        self.temp.clients = [{"name": "Wiktoria", "email": "wolnikowa@example.com"},
                             {"name": "Kasia", "email": "kasiapolak@example.com"}]
        self.temp.sendMessage.return_value = "Send message to kasiapolak@example.com"

        result = self.temp.sendMessage("kasiapolak@example.com", "Hello")
        self.assertEqual(result, "Send message to kasiapolak@example.com")

    def test_send_message_bad_type_message(self):
        self.temp.sendMessage = Mock()
        self.temp.clients = [{"name": "Wiktoria", "email": "wolnikowa@example.com"},
                             {"name": "Kasia", "email": "kasiapolak@example.com"}]
        self.temp.sendMessage.side_effect = TypeError("Type text message have to be string")

        result = self.temp.sendMessage
        self.assertRaisesRegex(TypeError, "Type text message have to be string", result, "kasiapolak@example.com",
                               False)

    def test_send_message_clients_BAD_email(self):
        self.temp.sendMessage = Mock()
        self.temp.clients = [{"name": "Wiktoria", "email": "wolnikowa@example.com"},
                             {"name": "Kasia", "email": "kasiapolak@example.com"}]
        self.temp.sendMessage.side_effect = Exception("No client has this email")

        result = self.temp.sendMessage
        self.assertRaisesRegex(Exception, "No client has this email", result, "bartekkowalslki@example.com", "Hello")

if __name__ == '__main__':
    main()


from selenium import webdriver
from selenium.webdriver.common.keys import Keys

url = ''
driver = webdriver.Chrome()
driver.get(url)

element_founder = driver.find_element_by_name('q')
element_founder.send_keys('selenium')
element_founder.send_keys(Keys.RETURN)

results = driver.find_elements_by_css_selector('h3 > a')
for result in results:
    print(result.text)


# To sort an array considering it as a nearly complete binary tree and then sorting it using max heapify

def max_heapify(mh, idx):
    left = (idx << 1) + 1
    right = (idx + 1) << 1
    largest = idx
    if left < len(mh) and mh[left] > mh[largest]:
        largest = left
    if right < len(mh) and mh[right] > mh[largest]:
        largest = right
    if largest != idx:
        mh[idx], mh[largest] = mh[largest], mh[idx]
        max_heapify(mh, largest)

def build_max_heap(mh):
    n = len(mh)//2
    for i in range(n, -1, -1):
        max_heapify(mh, i)

def heap_sort(mh):
    y = []
    while len(mh) > 0:
        n = len(mh) - 1
        build_max_heap(mh)
        mh[0], mh[n] = mh[n], mh[0]
        y.append(mh[n])
        mh.pop(n)
        max_heapify(mh, 0)
    return y


#!/usr/bin/env python
# coding: utf-8

# In[6]:

import time
import json
import pandas as pd
import re
import logging
from datetime import date, datetime, timedelta
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
opts=webdriver.ChromeOptions()
opts.headless=False
driver = webdriver.Chrome(ChromeDriverManager().install() ,options=opts)

def date_extract(jobs):
    filtered_data=[]
    for value in jobs:
        if not value:
            filtered_data.append(str(date.today()))
        else:
            for item in value:
                integer_value=int(str(item))
                dt=date.today()-timedelta(integer_value)
                filtered_data.append(str(dt))
    return filtered_data

def get_df_from_dict(jobs):
    df=pd.DataFrame.from_dict(jobs) #Creating DataFrame
    df.head(10)
    df=df.apply(lambda x: x.astype(str).str.lower()) #converting into lowercase to remove redundancy
    df.head()
    #df.skills=[skill.split("\n") for skill in df.skills]
    df.location=[location.split(" ") for location in df.location]
    df=df.dropna()
    return df

def task_scrape():

    jobs={"title":[],
        "company":[],

        "experience":[],
        #"skills":[],
        "date":[],
        "scraper_run_dt_time":[],
        "location":[]
        #"jd_url":[]
        }
    final_df=pd.DataFrame(jobs)
        #This outer loop is for number of pages to be scraped
        #for role in data["job_roles"]:
         #   jobs={key:[] for key in jobs}
            #print("hello",jobs)
    for n in range(1,4):
        driver.get('https://www.naukri.com/software-engineer-software-developer-data-analyst-data-scientist-machine-learning-engineer-hr-manager-project-manager-cloud-architect-full-stack-developer-full-stack-web-developer-big-data-consultant-jobs-'+str(n)+'?k=Software%20Engineer%2C%20Software%20Developer%2C%20Data%20Analyst%2C%20Data%20Scientist%2C%20Machine%20Learning%20Engineer%2C%20HR%20Manager%2C%20Project%20Manager%2C%20Cloud%20Architect%2C%20Full%20Stack%20Developer%2C%20Full%20Stack%20Web%20Developer%2C%20Big%20Data%20Consultant')
        time.sleep(4)
        job_container = driver.find_elements(By.CSS_SELECTOR,".jobTuple.bgWhite.br4.mb-8")
                # scraping the details from webpage
        for job in job_container:
            driver.implicitly_wait(20)
            title=job.find_element(By.CSS_SELECTOR,"a.title.fw500.ellipsis").text
            company=job.find_element(By.CSS_SELECTOR,"a.subTitle.ellipsis.fleft").text
            location=job.find_element(By.CSS_SELECTOR,".fleft.grey-text.br2.placeHolderLi.location").text
            try:
                exp=job.find_element(By.CSS_SELECTOR,".fleft.grey-text.br2.placeHolderLi.experience").text
            except Exception:
                exp="0 yrs"
            #skills=job.find_element(By.CSS_SELECTOR,".tags.has-description").text
            date_string=job.find_element(By.CSS_SELECTOR,"[class^='type br2 fleft']").text
                    # date_string contains strings like 2 day ago,just now,few hours ago
            #jd=job.find_element(By.TAG_NAME,"a").get_attribute("href")
            date=re.findall(r'\d+',date_string) #extracting numbers out of the date_string
            jobs["title"].append(title)
            jobs["company"].append(company)
            jobs["location"].append(location)
            jobs["experience"].append(exp)
            #jobs["skills"].append(skills)
            jobs["date"].append(date)
            #jobs["jd_url"].append(jd)
            jobs["scraper_run_dt_time"].append(datetime.today())
    jobs["date"]=date_extract(jobs["date"])
    try:
        print(type(jobs))
        dataframe=get_df_from_dict(jobs)
        print(type(dataframe))
        dataframe[15:25]
        final_df=final_df.append(dataframe)
    except:
        logging.error("Error in dict_to_df")
    now=datetime.today()
    dt_time=now.strftime("%H%M%S")
    dt=now.strftime("%Y%m%d")
    filename="scraped_"+dt+"_"+dt_time
    final_df.info()
    final_df[40:45]
    final_df.to_csv('{}.csv'.format(filename))
    driver.quit

task_scrape()

# In[ ]:


#!/usr/bin/env python

import sys
import fitsio
import healpy
import numpy as np
import scipy as sp
import argparse
import matplotlib.pyplot as plt

from scipy.interpolate import interp1d
from picca.data import forest
from picca.data import delta
from picca import io

if __name__ == '__main__':

    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument('--plate', type = int, default = None, required=True,
            help = 'Plate of spectrum')

    parser.add_argument('--mjd', type = int, default = None, required=True,
            help = 'Modified Julian Date of spectrum')

    parser.add_argument('--fiberid', type = int, default = None, required=True,
            help = 'fiber of spectrum')

    parser.add_argument('--drq', type = str, default = None, required=True,
            help = 'DRQ file')

    parser.add_argument('--nside', type = int, default = 16, required=False,
            help = 'healpix nside')

    parser.add_argument('--spectrum', type = str, default = None, required=True,
            help = 'data directory for all the spectra')

    parser.add_argument('--no-project', action="store_true", required=False,
            help = 'do not project out continuum fitting modes')

    parser.add_argument('--in-dir',type = str,default=None,required=True,
            help='data directory')

    parser.add_argument('--lambda-min',type = float,default=3600.,required=False,
            help='lower limit on observed wavelength [Angstrom]')

    parser.add_argument('--lambda-max',type = float,default=5500.,required=False,
            help='upper limit on observed wavelength [Angstrom]')

    parser.add_argument('--lambda-rest-min',type = float,default=1040.,required=False,
            help='lower limit on rest frame wavelength [Angstrom]')

    parser.add_argument('--lambda-rest-max',type = float,default=1200.,required=False,
            help='upper limit on rest frame wavelength [Angstrom]')

    parser.add_argument('--rebin',type = int,default=3,required=False,
            help='rebin wavelength grid by combining this number of adjacent pixels (ivar weight)')

    parser.add_argument('--mode',type = str,default='pix',required=False,
            help='open mode: pix, spec, spcframe')

    parser.add_argument('--dla-vac',type = str,default=None,required=False,
            help='dla catalog file')

    parser.add_argument('--dla-mask',type = float,default=0.8,required=False,
            help='lower limit on the DLA transmission. Transmissions below this number are masked')

    parser.add_argument('--mask-file',type = str,default=None,required=False,
            help='Path to file to mask regions in lambda_OBS and lambda_RF. In file each line is: region_name region_min region_max (OBS or RF) [Angstrom]')

    parser.add_argument('--flux-calib',type = str,default=None,required=False,
            help='Path to file to previously produced picca_delta.py file to correct for multiplicative errors in the flux calibration')

    parser.add_argument('--ivar-calib',type = str,default=None,required=False,
            help='Path to previously produced picca_delta.py file to correct for multiplicative errors in the pipeline inverse variance calibration')

    args = parser.parse_args()

    ### forest args
    forest.lmin = np.log10(args.lambda_min)
    forest.lmax = np.log10(args.lambda_max)
    forest.lmin_rest = np.log10(args.lambda_rest_min)
    forest.lmax_rest = np.log10(args.lambda_rest_max)
    forest.rebin = args.rebin
    forest.dll = args.rebin*1e-4
    forest.dla_mask = args.dla_mask

    ### Get Healpy pixel of the given QSO
    objs = {}
    ra,dec,zqso,thid,plate,mjd,fid = io.read_drq(args.drq,0.,1000.,keep_bal=True)
    cut = (plate==args.plate) & (mjd==args.mjd) & (fid==args.fiberid)
    if cut.sum()==0:
        print("Object not in drq")
        sys.exit()
    ra = ra[cut]
    dec = dec[cut]
    zqso = zqso[cut]
    thid = thid[cut]
    plate = plate[cut]
    mjd = mjd[cut]
    fid = fid[cut]
    phi = ra
    th = sp.pi/2.-dec
    pix = healpy.ang2pix(args.nside,th,phi)

    ### Get data
    data = None
    if args.mode == "pix":
        data = io.read_from_pix(args.in_dir,pix[0],thid, ra, dec, zqso, plate, mjd, fid, order=None, log=None)
    elif args.mode in ["spec","corrected-spec"]:
        data = io.read_from_spec(args.in_dir,thid, ra, dec, zqso, plate, mjd, fid, order=None, mode=args.mode,log=None)
    elif args.mode =="spcframe":
        data = io.read_from_spcframe(args.in_dir,thid, ra, dec, zqso, plate, mjd, fid, order=None, mode=args.mode, log=None)
    if data is None:
        print("Object not in in_dir")
        sys.exit()
    else:
        data = data[0]

    ### Correct multiplicative flux calibration
    if (args.flux_calib is not None):
        try:
            vac = fitsio.FITS(args.flux_calib)
            head = vac[1].read_header()

            ll_st = vac[1]['loglam'][:]
            st    = vac[1]['stack'][:]
            w     = (st!=0.)
            forest.correc_flux = interp1d(ll_st[w],st[w],fill_value="extrapolate")
            vac.close()
        except:
            print(" Error while reading flux_calib file {}".format(args.flux_calib))
            sys.exit(1)

    ### Correct multiplicative pipeline inverse variance calibration
    if (args.ivar_calib is not None):
        try:
            vac = fitsio.FITS(args.ivar_calib)
            ll  = vac[2]['LOGLAM'][:]
            eta = vac[2]['ETA'][:]
            forest.correc_ivar = interp1d(ll,eta,fill_value="extrapolate",kind="nearest")
            vac.close()
        except:
            print(" Error while reading ivar_calib file {}".format(args.ivar_calib))
            sys.exit(1)

    ### Get the lines to veto
    usr_mask_obs    = None
    usr_mask_RF     = None
    usr_mask_RF_DLA = None
    if (args.mask_file is not None):
        try:
            usr_mask_obs    = []
            usr_mask_RF     = []
            usr_mask_RF_DLA = []
            with open(args.mask_file, 'r') as f:
                loop = True
                for l in f:
                    if (l[0]=='#'): continue
                    l = l.split()
                    if (l[3]=='OBS'):
                        usr_mask_obs    += [ [float(l[1]),float(l[2])] ]
                    elif (l[3]=='RF'):
                        usr_mask_RF     += [ [float(l[1]),float(l[2])] ]
                    elif (l[3]=='RF_DLA'):
                        usr_mask_RF_DLA += [ [float(l[1]),float(l[2])] ]
                    else:
                        raise
            usr_mask_obs    = np.log10(np.asarray(usr_mask_obs))
            usr_mask_RF     = np.log10(np.asarray(usr_mask_RF))
            usr_mask_RF_DLA = np.log10(np.asarray(usr_mask_RF_DLA))
            if usr_mask_RF_DLA.size==0:
                usr_mask_RF_DLA = None

        except:
            print(" Error while reading mask_file file {}".format(args.mask_file))
            sys.exit(1)

    ### Veto lines
    if not usr_mask_obs is None:
        if ( usr_mask_obs.size+usr_mask_RF.size!=0):
            data.mask(mask_obs=usr_mask_obs , mask_RF=usr_mask_RF)

    ### Correct for DLAs
    if not args.dla_vac is None:
        print("adding dlas")
        dlas = io.read_dlas(args.dla_vac)
        for p in data:
            for d in data[p]:
                if d.thid in dlas:
                    for dla in dlas[d.thid]:
                        data.add_dla(dla[0],dla[1],usr_mask_RF_DLA)

    ### Get delta from picca_delta
    done_delta = None
    f = args.spectrum+"/delta-"+str(pix[0])+".fits.gz"
    hdus = fitsio.FITS(f)
    ds = [delta.from_fitsio(h) for h in hdus[1:]]
    for d in ds:
        if (d.plate==args.plate) and (d.mjd==args.mjd) and (d.fid==args.fiberid):
            d.project()
            done_delta = d
            hdus.close()
            break
    if done_delta is None:
        hdus.close()
        print("Object not in spectrum")
        sys.exit()

    ### Observed l
    plt.errorbar(10**data.ll,data.fl,linewidth=2,color='black')
    plt.errorbar(10**done_delta.ll,done_delta.co,linewidth=4,color='red')
    plt.xlabel(r'$\lambda_{\mathrm{Obs.}} \, [\mathrm{\AA}]$',fontsize=30)
    plt.ylabel(r'$f \, [10^{-19} \mathrm{W \, m^{-2} \, nm^{-1}}]$',fontsize=30)
    plt.grid()
    plt.show()

    ### RF l
    plt.errorbar(10**data.ll/(1.+done_delta.zqso),data.fl,linewidth=4,color='black')
    plt.errorbar(10**done_delta.ll/(1.+done_delta.zqso),done_delta.co,linewidth=4,color='red')
    plt.xlabel(r'$\lambda_{\mathrm{R.F.}} \, [\mathrm{\AA}]$',fontsize=30)
    plt.ylabel(r'$f \, [10^{-19} \mathrm{W \, m^{-2} \, nm^{-1}}]$',fontsize=30)
    plt.grid()
    plt.show()


#max duty_ns is 20ms and min is 5ms. We want 180 degrees (divisions)#Some variables
# This values may change depending on your servos
MIN_DUTY_NS = 500000
MAX_DUTY_NS = 2000000
PWM_FRECUENCY = 50 #hz
DEGREE_TO_NS = (MAX_DUTY_NS-MIN_DUTY_NS)/180

PWM_PATH = "/sys/class/pwm/"

# -------------- from bonescript's bone.js ----------------------
gpio0 = 0
gpio1 = gpio0+32
gpio2 = gpio1+32
gpio3 = gpio2+32

pwm_pins = {
    "P8_13": { "name": "EHRPWM2B", "gpio": gpio0+23, "mux": "gpmc_ad9", "eeprom": 15, "pwm" : "ehrpwm.2:1"  },
    "P8_19": { "name": "EHRPWM2A", "gpio": gpio0+22, "mux": "gpmc_ad8", "eeprom": 14, "pwm" : "ehrpwm.2:0"  },
    "P9_14": { "name": "EHRPWM1A", "gpio": gpio1+18, "mux": "gpmc_a2", "eeprom": 34, "pwm" : "ehrpwm.1:0" },
    "P9_16": { "name": "EHRPWM1B", "gpio": gpio1+19, "mux": "gpmc_a3", "eeprom": 35, "pwm" : "ehrpwm.1:1" },
    "P9_31": { "name": "SPI1_SCLK", "gpio": gpio3+14, "mux": "mcasp0_aclkx", "eeprom": 65 , "pwm": "ehrpwm.0:0"},
    "P9_29": { "name": "SPI1_D0", "gpio": gpio3+15, "mux": "mcasp0_fsx", "eeprom": 61 , "pwm": "ehrpwm.0:1"},
    "P9_42": { "name": "GPIO0_7", "gpio": gpio0+7, "mux": "ecap0_in_pwm0_out", "eeprom": 4, "pwm": "ecap.0"},
    "P9_28": { "name": "SPI1_CS0", "gpio": gpio3+17, "mux": "mcasp0_ahclkr", "eeprom": 63, "pwm": "ecap.2" },
}

class Servo:

	def attach(self, pin):
		if not pin in pwm_pins:
			raise Exception('Pin ' + pin + ' is not pwm capable')
		else:
			self.__pin = PWM_PATH+pwm_pins[pin]["pwm"]

			val = open(self.__pin + "/request").read()
			if val.find('free') < 0:
				raise Exception('Pin ' + pin + ' is already in use')

			self.__lastValue = 0

			open(self.__pin + "/request", 'w').write("1")
			open(self.__pin + "/run", 'w').write("0")
			open(self.__pin + "/period_freq", 'w').write(str(PWM_FRECUENCY))
			open(self.__pin + "/duty_ns", 'w').write(str(MIN_DUTY_NS)) #init to 0 degree
			open(self.__pin + "/run", 'w').write("1")

			self.__attached = True

	def write(self, value):
		duty_ns = MIN_DUTY_NS + value * DEGREE_TO_NS
		self.__lastValue = value
		open(self.__pin + "/duty_ns", 'w').write(str(duty_ns))

	def writeMicroseconds(self, value):
		open(self.__pin + "/duty_ns", 'w').write(str(value)+"000") #micro to nano

	def read(self):
		return self.__lastValue

	def attached(self):
		return self.__attached

	def detach(self):
		open(self.__pin + "/run", 'w').write("0")
		open(self.__pin + "/request", 'w').write("0")
		self.__attached = False


# Copyright (c) 2023 Graphcore Ltd. All rights reserved.
# The functional definition in this file was ported to Python
# from XCFun, which is Copyright Ulf Ekström and contributors 2009-2020
# and provided under the Mozilla Public License (v2.0)
# see also:
#   - https://github.com/dftlibs/xcfun
#   - https://github.com/dftlibs/xcfun/blob/master/LICENSE.md

import jax.numpy as jnp
import jax
import numpy as np

def __b88(a, gaa):
        # precompute
        c1 = (4.0 / 3.0)
        c2 = (-8.0 / 3.0)
        c3 = (-3.0 / 4.0) * (6.0 / np.pi) ** (1.0 / 3.0) * 2
        d  = 0.0042
        d2 = d * 2.
        d12 = d *12.

        # actual compute
        log_a     = jnp.log(a/2)
        na43      = jnp.exp(log_a * c1)
        chi2      = gaa / 4* jnp.exp(log_a * c2 )
        chi       = jnp.exp(jnp.log( chi2 ) / 2 )
        b88       = -(d * na43 * chi2) / (1.0 + 6*d * chi * jnp.arcsinh(chi)) *2
        slaterx_a = c3 * na43
        return slaterx_a + b88


def palindrome(string):
    try:
        if len(string) == 0:
            raise ValueError("We cannot catch a void string")
        return string == string[::-1]
    except ValueError as ex:
        print(ex)
        return False

def main():
    try:
        # print(palindrome(121))
        print(palindrome(""))
    except TypeError as e:
        print(f"Only we can catch strings. Error: {e}. This is bad.")

if __name__ == "__main__":
    main()


from ipywidgets import Box, HBox, VBox, FloatSlider, FloatProgress, Label, Layout
s1 = FloatSlider(description='Apple', min=-5, max=5, step=0.01, value=0, layout=Layout(width='90%'))
s2 = FloatSlider(description='Horse', min=-5, max=5, step=0.01, value=0, layout=Layout(width='90%'))
s3 = FloatSlider(description='Flower', min=-5, max=5, step=0.01, value=0, layout=Layout(width='90%'))
s4 = FloatSlider(description='Car', min=-5, max=5, step=0.01, value=0, layout=Layout(width='90%'))
p1 = FloatProgress(min=0, max=1, step=0.01, value=0)
p2 = FloatProgress(min=0, max=1, step=0.01, value=0)
p3 = FloatProgress(min=0, max=1, step=0.01, value=0)
p4 = FloatProgress(min=0, max=1, step=0.01, value=0)
l1 = Label(value="0.00")
l2 = Label(value="0.00")
l3 = Label(value="0.00")
l4 = Label(value="0.00")

import numpy as np
values = np.array([0.0, 0.0, 0.0, 0.0])
def softmax(i):
    return np.exp(values[i]) / np.sum(np.exp(values))

def set_values():
    l1.value = "%.2f" % softmax(0)
    l2.value = "%.2f" % softmax(1)
    l3.value = "%.2f" % softmax(2)
    l4.value = "%.2f" % softmax(3)
    p1.value = softmax(0)
    p2.value = softmax(1)
    p3.value = softmax(2)
    p4.value = softmax(3)

def on_value_change(change):
    if change.owner == s1:
        values[0] = change.new
    if change.owner == s2:
        values[1] = change.new
    if change.owner == s3:
        values[2] = change.new
    if change.owner == s4:
        values[3] = change.new
    set_values()

s1.observe(on_value_change, names='value')
s2.observe(on_value_change, names='value')
s3.observe(on_value_change, names='value')
s4.observe(on_value_change, names='value')

def main():
	set_values()
	left_box = VBox([s1, s2, s3, s4], layout=Layout(width='50%'))
	middle_box = VBox([p1, p2, p3, p4])
	right_box = VBox([l1, l2, l3, l4])
	return HBox([left_box, middle_box, right_box])

if __name__ == "__main__":
	main()


import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

from math import sqrt

def wn_conv1d(*args, **kwargs):
    return nn.utils.weight_norm(nn.Conv1d(*args, **kwargs))

def wn_conv_transpose1d(*args, **kwargs):
    return nn.utils.weight_norm(nn.ConvTranspose1d(*args, **kwargs))

def wn_linear(*args, **kwargs):
    return nn.Linear(*args, **kwargs)

class BaseQuantize(nn.Module):
    def embed_code(self, embed_id):
        raise NotImplementedError

class Quantize(BaseQuantize):
    def __init__(self, dim, n_embed, decay=0.999, eps=1e-5):
        super().__init__()

        self.dim = dim
        self.n_embed = n_embed
        self.decay = decay
        self.eps = eps

        embed = torch.randn(dim, n_embed)
        self.register_buffer('embed', embed)
        self.register_buffer('cluster_size', torch.zeros(n_embed))
        self.register_buffer('embed_avg', embed.clone())

    def forward(self, input):
        flatten = input.reshape(-1, self.dim)
        dist = (
            flatten.pow(2).sum(1, keepdim=True)
            - 2 * flatten @ self.embed
            + self.embed.pow(2).sum(0, keepdim=True)
        )

        _, embed_ind = (-dist).max(1)
        embed_onehot = F.one_hot(embed_ind, self.n_embed).type(flatten.dtype)
        embed_ind = embed_ind.view(*input.shape[:-1])
        quantize = self.embed_code(embed_ind)

        if self.training:
            self.cluster_size.data.mul_(self.decay).add_(
                1 - self.decay, embed_onehot.sum(0)
            )
            embed_sum = flatten.transpose(0, 1) @ embed_onehot
            self.embed_avg.data.mul_(self.decay).add_(1 - self.decay, embed_sum)
            n = self.cluster_size.sum()
            cluster_size = (
                (self.cluster_size + self.eps) / (n + self.n_embed * self.eps) * n
            )
            embed_normalized = self.embed_avg / cluster_size.unsqueeze(0)
            self.embed.data.copy_(embed_normalized)

        diff = (quantize.detach() - input).pow(2).mean()
        quantize = input + (quantize - input).detach()

        return quantize, diff, embed_ind

    def embed_code(self, embed_id):
        return F.embedding(embed_id, self.embed.transpose(0, 1))

class DecomposedQuantize(BaseQuantize):
    def __init__(self, length, dim, n_embed, decay=0.999, eps=1e-5):
        super().__init__()

        self.dim = dim
        self.n_embed = n_embed
        self.quantizations = nn.ModuleList([Quantize(dim, n_embed, decay, eps) for _ in range(length)])

    def forward(self, input):
        out = torch.empty_like(input)
        diff = None
        ids = torch.empty(*input.shape[:-1], dtype=torch.long, device=input.device)
        for i in range(input.size(1)):
            quant, diff, code = self.quantizations[i](input[:, i])
            out[:, i] = quant
            ids[:, i] = code
            if diff is None:
                diff = diff
            else:
                diff += diff
        return out, diff / len(self.quantizations), ids

    def embed_code(self, embed_id):
        out = torch.empty(*embed_id.size(), self.dim, dtype=torch.float, device=embed_id.device)
        for i in range(embed_id.size(1)):
            out[:, i] = self.quantizations[i].embed_code(embed_id[:, i])
        return out

class SlicedQuantize(nn.Module):
    def __init__(self, d_slice, dim, **kwargs):
        super().__init__()

        self.dim = dim // d_slice
        self.quantize = Quantize(dim=self.dim, **kwargs)
        self.d_slice = d_slice

    def forward(self, input):
        shape = input.size()
        input = input.reshape(*input.shape[:-2], -1, self.dim)
        z, diff, ids = self.quantize(input)
        z = z.view(shape)
        return z, diff, ids

class CategoricalNoise(nn.Module):
    def __init__(self, n_classes, p):
        super().__init__()

        self.n_classes = n_classes
        self.p = p

    def forward(self, input):
        if self.training:
            mask = (torch.rand(input.shape, device=input.device) > self.p).type(input.dtype)
            noise = torch.randint_like(input, 0, self.n_classes)

            return input * mask + (1 - mask) * noise
        else:
            return input

class GeometricCategoricalDropout(nn.Module):
    def __init__(self, n, q, alpha):
        super().__init__()

        if not (0 < q < 1):
            raise ValueError('q must be a value 0 < ... < 1')

        self.a = 1 / (((q ** (n + 1) - 1) / (q - 1)) - 1)
        self.n = n
        self.q = q
        self.alpha = alpha
        #
        # self.probs = 1 - alpha * (1 - torch.full([n], self.a) * torch.pow(self.q, (torch.arange(n) + 1).type(torch.float)))
        # self.m = torch.distributions.Bernoulli(self.probs)

    def forward(self, input):
        assert input.max() <= self.n

        if self.training:
            probs = 1 - torch.pow(self.q, input.type(torch.float))
        else:
            probs = torch.zeros_like(input)

        mask = (torch.rand(input.shape, device=input.device) <= probs).type(input.dtype)
        return mask

class Noise(nn.Module):
    def __init__(self, alpha=0.1):
        super().__init__()
        self.alpha = alpha

    def forward(self, input):
        if not self.training:
            return input
        return input + self.alpha * torch.randn_like(input)

class ResBlock(nn.Module):
    def __init__(self, in_channel, channel, kernel_size=3, padding=1, dilation=1):
        super().__init__()

        self.conv = nn.Sequential(
            nn.ELU(),
            nn.Conv1d(in_channel, channel, kernel_size=kernel_size, padding=padding, dilation=dilation),

            nn.ELU(),
            nn.Conv1d(channel, in_channel, kernel_size=1),
        )

    def forward(self, input):
        out = self.conv(input)
        out += input

        return out

class ChannelWiseLayerNorm(nn.Module):
    def __init__(self, channels):
        super().__init__()
        self.ln = nn.LayerNorm(channels)

    def forward(self, input):
        shape = input.size()
        input = input.view(shape[0], shape[1], -1).transpose(1, 2)
        input = self.ln(input)
        input = input.transpose(1, 2).view(shape)
        return input

class Attention(nn.Module):
    def __init__(self, in_dim, key_query_dim, value_dim, n_heads=1, tau=1.0):
        super().__init__()

        self.query_w = wn_linear(in_dim, key_query_dim)
        self.key_w = wn_linear(in_dim, key_query_dim)
        self.value_w = wn_linear(in_dim, value_dim)

        self.n_heads = n_heads
        self.kq_head_dim = key_query_dim // n_heads
        self.val_head_dim = value_dim // n_heads

        self.tau = tau

    def forward(self, query, key):
        bs, _, l = query.size()

        query_ = query.transpose(1, 2)
        key_ = key.transpose(1, 2)

        def reshape(x, head_dim):
            return x.view(bs, -1, self.n_heads, head_dim).transpose(1, 2)

        query = reshape(self.query_w(query_), self.kq_head_dim)
        key = reshape(self.key_w(key_), self.kq_head_dim).transpose(2, 3)
        value = reshape(self.value_w(key_), self.val_head_dim)

        attn = (query @ key) / sqrt(self.kq_head_dim)
        attn = attn / self.tau
        attn = F.softmax(attn, dim=-1)

        out = attn @ value
        out = out.transpose(1, 2).reshape(
            bs, l, self.n_heads * self.val_head_dim
        )
        out = out.permute(0, 2, 1)

        return out

class EqualizedConv1d(nn.Module):
    def __init__(self, c_in, c_out, kernel_size, stride=1, padding=0, bias=True):
        super().__init__()

        # define the weight and bias if to be used
        self.weight = nn.Parameter(nn.init.normal_(
            torch.empty(c_out, c_in, *nn.modules.utils._single(kernel_size))
        ))

        self.use_bias = bias
        self.stride = stride
        self.pad = padding

        if self.use_bias:
            self.bias = nn.Parameter(torch.FloatTensor(c_out).fill_(0))

        fan_in = np.prod(nn.modules.utils._single(kernel_size)) * c_in  # value of fan_in
        self.scale = np.sqrt(2) / np.sqrt(fan_in)

    def forward(self, x):
        return F.conv1d(input=x,
                        weight=self.weight * self.scale,  # scale the weight on runtime
                        bias=self.bias if self.use_bias else None,
                        stride=self.stride,
                        padding=self.pad)

class EqualizedConvTranspose1d(nn.Module):
    def __init__(self, c_in, c_out, kernel_size, stride=1, padding=0, bias=True):
        super().__init__()

        self.weight = nn.Parameter(torch.nn.init.normal_(
            torch.empty(c_in, c_out, *nn.modules.utils._single(kernel_size))
        ))

        self.use_bias = bias
        self.stride = stride
        self.pad = padding

        if self.use_bias:
            self.bias = nn.Parameter(torch.FloatTensor(c_out).fill_(0))

        fan_in = c_in  # value of fan_in for deconv
        self.scale = np.sqrt(2) / np.sqrt(fan_in)

    def forward(self, x):
        return F.conv_transpose1d(input=x,
                                  weight=self.weight * self.scale,  # scale the weight on runtime
                                  bias=self.bias if self.use_bias else None,
                                  stride=self.stride,
                                  padding=self.pad)

class EqualizedLinear(nn.Module):
    def __init__(self, c_in, c_out, bias=True):
        """
        Linear layer modified for equalized learning rate
        """
        from numpy import sqrt

        super().__init__()

        self.weight = nn.Parameter(torch.nn.init.normal_(
            torch.empty(c_out, c_in)
        ))

        self.use_bias = bias

        if self.use_bias:
            self.bias = nn.Parameter(torch.FloatTensor(c_out).fill_(0))

        fan_in = c_in
        self.scale = sqrt(2) / sqrt(fan_in)

    def forward(self, x):
        return F.linear(x, self.weight * self.scale,
                        self.bias if self.use_bias else None)

if __name__ == '__main__':
    n = 4096

    do = GeometricCategoricalDropout(n, 0.998, 1.0)

    i = 10000
    res = torch.zeros(n)
    for j in range(i):
        sample = torch.randint(0, n, [128])
        out = do(sample)
        for k, m in enumerate(out):
            if m:
                res[sample[k]] += 1

    res /= i

    import numpy as np
    import matplotlib.pyplot as plt
    plt.plot(np.arange(n), res.numpy())
    plt.ylim(bottom=0)
    plt.show()


#!/usr/bin/env python3
"""An Implement of an autoencoder with pytorch.
This is the template code for 2020 NIAC https://naic.pcl.ac.cn/.
The code is based on the sample code with tensorflow for 2020 NIAC and it can only run with GPUS.
Note:
    1.This file is used for designing the structure of encoder and decoder.
    2.The neural network structure in this model file is CsiNet, more details about CsiNet can be found in [1].
[1] C. Wen, W. Shih and S. Jin, "Deep Learning for Massive MIMO CSI Feedback", in IEEE Wireless Communications Letters, vol. 7, no. 5, pp. 748-751, Oct. 2018, doi: 10.1109/LWC.2018.2818160.
    3.The output of the encoder must be the bitstream.
"""
import numpy as np
import h5py
import torch
from transformer import  *
from dataloader import *
from loss import *
import os
import torch.nn as nn
import pickle
import random
from copy import deepcopy
from util import *
def save_obj(obj, name ):
    with open( name + '.pkl', 'wb') as f:
        pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)

def load_obj(name ):
    with open(  name + '.pkl', 'rb') as f:
        return pickle.load(f)
# Parameters for training
torch.backends.cudnn.benchmark=True
np.set_printoptions(suppress=True)

os.environ["CUDA_VISIBLE_DEVICES"] = '0'
use_single_gpu = True  # select whether using single gpu or multiple gpus
torch.manual_seed(1)
batch_size = 16
epochs = 8000
learning_rate = 1e-3
num_workers = 4
print_freq = 3200  # print frequency (default: 60)
# parameters for data
# feedback_bits = 48  # sim2 = 0.26814688715868884, multi2 = 2.3217122101795313, multi_div_sim_2 = 8.658359732535498
feedback_bits = 48
B = 2
size_packet = 100

NUM_RX = 4
NUM_TX = 32
NUM_DELAY = 32
NUM_SAMPLE_TRAIN = 4000

def norm_data(x, num_sample, num_rx, num_tx, num_delay):
    x2 = np.reshape(x, [num_sample, num_rx * num_tx * num_delay * 2])
    x_max = np.max(abs(x2), axis=1)
    x_max = x_max[:,np.newaxis]
    x3 = x2 / x_max / 2.0
    y = np.reshape(x3, [num_sample, num_rx, num_tx, num_delay, 2])
    return y

# Model construction
model = AutoEncoder(feedback_bits=48, dropout=0.1)

# model.encoder.load_state_dict(torch.load('submit_pt/encoder_2.pth.tar')['state_dict'])
# model.decoder.load_state_dict(torch.load('submit_pt/generator_2.pth.tar')['state_dict'])

if use_single_gpu:
    model = model.cuda()
else:
    # DataParallel will divide and allocate batch_size to all available GPUs
    model = torch.nn.DataParallel(model).cuda()

import scipy.io as scio
criterion = SmiLoss()
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate)
"""
scheduler = WarmUpCosineAnnealingLR(optimizer=optimizer,
                                            T_max=epochs * len(train_loader),
                                            T_warmup=epochs//20 * len(train_loader),
                                            eta_min=1e-6)
"""

data_train = h5py.File('data/H2_32T4R.mat', 'r')
data_train = np.transpose(data_train['H2_32T4R'][:])
data_train = data_train[:, :, :, :, np.newaxis]
data_train = np.concatenate([data_train['real'], data_train['imag']], 4) # 500 4 32 32 2
# data_train = np.reshape(data_train, [NUM_SAMPLE_TRAIN, NUM_RX* NUM_TX, NUM_DELAY* 2, 1])
# x_train = norm_data(data_train, NUM_SAMPLE_TRAIN, NUM_RX, NUM_TX, NUM_DELAY)
data_train = data_train.astype(np.float32)

x_train = data_train
x_test = data_train

"""
x_test = x_test[1000:,:,:,:]
"""

x_train_hat = np.transpose(x_train, (0,3,1,2,4)).reshape(-1, 32, 256)
x_train_paterns = np.unique((np.sum(np.abs(x_train_hat), axis=2) != 0).astype(np.float32), axis=0)

# dataLoader for training
train_dataset = DatasetFolder(x_train, data_an=True)
print(train_dataset.__len__())
train_loader = torch.utils.data.DataLoader(
    train_dataset, batch_size=batch_size, shuffle=True, pin_memory=True, num_workers=num_workers)

def random_cutmix(x):
    a = x[:,:,:,:16,:]
    b = x[:,:,:,16:,:]
    idx = [i for i in range(a.size(0))]
    random.shuffle(idx)
    res = torch.cat([a,b[idx]], dim=3)
    return res

def random_mixup(x, num=3):
    weight = np.random.randn(num)
    weight = weight / np.sum(weight)
    res = x * weight[0]
    for i in range(1, num):
        idx = [i for i in range(x.size(0))]
        random.shuffle(idx)
        res += x[idx] * weight[i]
    return res

best_loss = 100000
"""
scheduler = WarmUpCosineAnnealingLR(optimizer=optimizer,
                                    T_max=epochs * len(train_loader),
                                    T_warmup=epochs//20 * len(train_loader),
                                    eta_min=1e-6)
"""
print('----', len(train_loader))
for epoch in range(epochs):

    if epoch == 200:
        for param_group in optimizer.param_groups:
            param_group['lr'] = learning_rate * 0.1

    # model training
    model.train()
    total_loss = []
    for i, x in enumerate(train_loader):
        input = x
        input = input.cuda()
        # compute output
        output = model(input)

        loss_list = criterion(output, input, epoch=epoch)
        loss = sum(loss_list[1:])
        total_loss.append([item.detach().cpu().numpy()*input.size(0) for item in loss_list])
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if i % print_freq == 0:
            print('Epoch: [{0}][{1}/{2}]\t'
                  'Loss {loss:.6f}\t'.format(
                epoch, i, len(train_loader), loss=loss.item()))
    # model evaluating
    total_loss = np.sum(np.array(total_loss), axis=0) / len(train_dataset)
    print('train loss:{},  other loss:{}\t'.format(total_loss[1], total_loss[2]))
    model.eval()
    total_loss = []
    totalNMSE = 0
    y_test = []
    count = 0
    if epoch%1==0:
        with torch.no_grad():
            for idx in range(int(4000 / size_packet)):
                x = np.random.randint(2, size=(size_packet,feedback_bits))
                x = torch.from_numpy(x)
                x = x.cuda()
                """
                B,_,_,_ = x.size()
                x_var = torch.mean((x.view(B,126,-1).detach() - 0.5)**2,dim = -1)
                x_sort = torch.sort(-x_var,dim = -1)[1] + torch.arange(B).unsqueeze(-1).to(x_var.device)*126
                x_sort = x_sort.view(-1)
                x = x.view(B*126,128,2)
                input = torch.index_select(x, 0, x_sort).view(B,2,126,128)
                """
                input = x
                output = model.decoder(input)   # bx4x32x32x2

                output = output.detach().cpu().numpy()
                if idx == 0:
                    output_all = output
                else:
                    output_all = np.concatenate([output_all, output], axis=0)

        new_output_all = output_all

        real = x_test[:,:,:,:,0] + x_test[:,:,:,:,1]*1j
        fake = new_output_all[:,:,:,:,0] + new_output_all[:,:,:,:,1]*1j

        sim_1, multi_1, multi_div_sim_1 = K_nearest(real, fake, NUM_RX, NUM_TX, NUM_DELAY, 2)
        print('sim:{}, multi:{}, multi_div_sim_1:{}'.format(sim_1, multi_1, multi_div_sim_1))

        if multi_div_sim_1 < best_loss:
            modelSave2 = './submit_pt/generator_2.pth.tar'
            torch.save({'state_dict': model.decoder.state_dict(), }, modelSave2)
            modelSave2 = './submit_pt/encoder_2.pth.tar'
            torch.save({'state_dict': model.encoder.state_dict(), }, modelSave2)

            print("Model saved")
            best_loss = multi_div_sim_1


import io
import unittest

from glop.host import Host
import glop.tool
from .host_fake import FakeHost

SIMPLE_GRAMMAR = "grammar = anything*:as end -> join('', as) ,"

class ToolTests(unittest.TestCase):
    maxDiff = None

    def check_call_and_return_files(self, host, args, files):
        orig_wd = None
        tmpdir = None
        try:
            orig_wd = host.getcwd()
            tmpdir = host.mkdtemp()

            host.chdir(tmpdir)
            host.write_text_files(files)
            self._call(host, args, returncode=0)

            return host.read_text_files(tmpdir)

        finally:
            if tmpdir:
                host.rmtree(tmpdir)
            if orig_wd:
                host.chdir(orig_wd)

    def check_cmd(self, args, stdin=None, files=None,
                  returncode=None, out=None, err=None, output_files=None,
                  actual_output_files=None):
        host = self._host()
        orig_wd = None
        tmpdir = None
        try:
            orig_wd = host.getcwd()
            tmpdir = host.mkdtemp()
            host.chdir(tmpdir)
            if files:
                host.write_text_files(files)

            rv = self._call(host, args, stdin, returncode, out, err)
            actual_ret, actual_out, actual_err = rv

            if output_files:
                actual_output_files = host.read_text_files(host.getcwd())
        finally:
            if tmpdir:
                host.rmtree(tmpdir)
            if orig_wd:
                host.chdir(orig_wd)

        if output_files:
            self._assert_files(output_files, actual_output_files)
        return actual_ret, actual_out, actual_err

    def _host(self):
        return FakeHost()

    def _call(self, host, args, stdin=None, returncode=None, out=None,
            err=None):
        if stdin is not None:
            host.stdin.write(str(stdin))
            host.stdin.seek(0)
        actual_ret = glop.tool.main(host, args)
        actual_out = host.stdout.getvalue()
        actual_err = host.stderr.getvalue()
        if returncode is not None:
            self.assertEqual(returncode, actual_ret)
        if out is not None:
            self.assertEqual(str(out), actual_out)
        if err is not None:
            self.assertEqual(str(err), actual_err)
        return actual_ret, actual_out, actual_err

    def _assert_files(self, expected_files, actual_files):
        for k, v in actual_files.items():
            self.assertEqual(expected_files[k], v)
        self.assertEqual(set(actual_files.keys()), set(expected_files.keys()))

    def test_bad_command_line_switch(self):
        self.check_cmd(['--not-a-switch'], returncode=2)

    def test_ctrl_c(self):
        host = FakeHost()

        def raise_ctrl_c(*_comps):
            raise KeyboardInterrupt

        host.read_text_file = raise_ctrl_c
        host.write_text_file('simple.g', SIMPLE_GRAMMAR)

        self._call(host, ['simple.g'], returncode=130,
                   out='', err='Interrupted, exiting ...\n')

    def test_compile_bad_grammar(self):
        files = {
            'bad.g': 'grammar',
        }
        self.check_cmd(['-c', 'bad.g'], files=files,
                       returncode=1, out='', err=None)

    def test_files(self):
        files = {
            'simple.g': SIMPLE_GRAMMAR,
            'input.txt': 'hello, world\n',
        }
        out_files = files.copy()
        out_files['output.txt'] = '"hello, world\\n"\n'
        self.check_cmd(['-i', 'input.txt', '-o', 'output.txt',
                        'simple.g'],
                       files=files, returncode=0, out='', err='',
                       output_files=out_files)

    def test_grammar_file_not_found(self):
        self.check_cmd(['missing.g'], returncode=1,
                       err='Error: no such file: "missing.g"\n')

    def test_help(self):
        self.check_cmd(['--help'], returncode=0)

    def test_input_is_expr(self):
        self.check_cmd(['-e', SIMPLE_GRAMMAR], stdin='hello, world\n',
                       returncode=0)

    def test_input_on_stdin(self):
        files = {
            'simple.g': SIMPLE_GRAMMAR,
        }
        self.check_cmd(['-i', '-', 'simple.g'], stdin="hello, world\n",
                       files=files, returncode=0, out='"hello, world\\n"\n',
                       err='')

    def test_main(self):
        host = self._host()
        files = {
            'simple.g': SIMPLE_GRAMMAR,
        }
        args = ['-c', '--main', 'simple.g']

        output_files = self.check_call_and_return_files(host, args, files)
        self.assertIn('simple.py', output_files.keys())
        self.assertIn("if __name__ == '__main__'",
                      output_files['simple.py'])

    def test_no_grammar(self):
        self.check_cmd([], returncode=2)

    def test_no_main(self):
        host = self._host()
        files = {
            'simple.g': SIMPLE_GRAMMAR,
        }
        args = ['-c', 'simple.g']

        output_files = self.check_call_and_return_files(host, args, files)
        self.assertIn('simple.py', output_files.keys())
        self.assertNotIn("if __name__ == '__main__'",
                         output_files['simple.py'])

    def test_interpret_bad_grammar(self):
        files = {
            'bad.g': 'grammar',
        }
        self.check_cmd(['bad.g'], files=files,
                       returncode=1, out='', err=None)

    def test_output_flags(self):
        self.check_cmd(['-e', 'grammar = -> "ok"'],
                       returncode=0, out = '"ok"\n')
        self.check_cmd(['-e', 'grammar = -> "ok"', '--as-string'],
                       returncode=0, out = 'ok\n')
        self.check_cmd(['-e', 'grammar = -> "ok"', '--as-string',
                        '--no-appended-newline'],
                       returncode=0, out = 'ok')
        self.check_cmd(['-e', 'grammar = -> ["o", "k"]', '--as-string'],
                       returncode=0, out = 'ok\n')

    def test_pretty_print(self):
        files = {
            'simple.g': SIMPLE_GRAMMAR,
        }
        self.check_cmd(['-p', 'simple.g'], files=files,
                       returncode=0,
                       out="grammar = anything*:as end -> join('', as)\n")

    def test_pretty_print_glop(self):
        # This tests pretty-printing of a non-trivial grammar (glop itself)
        # in a limited way: it tests that pretty-printing an already
        # pretty-printed grammar doesn't change anything.

        h = Host()
        glop_contents = h.read_text_file(
            h.join(h.dirname(h.path_to_host_module()), '..',
                   'grammars', 'glop.g'))

        files = {'glop.g': glop_contents}

        host = self._host()
        orig_wd = None
        tmpdir = None
        try:
            orig_wd = host.getcwd()
            tmpdir = host.mkdtemp()
            host.chdir(tmpdir)
            if files:
                host.write_text_files(files)
            ret, _, _ = self._call(host,
                                  ['--pretty-print', 'glop.g',
                                   '-o', 'glop2.g'])
            self.assertEqual(0, ret)
            ret, _, _ = self._call(host,
                                   ['--pretty-print', 'glop2.g',
                                    '-o', 'glop3.g'])
            self.assertEqual(0, ret)
            actual_output_files = host.read_text_files(host.getcwd())
            self.assertMultiLineEqual(actual_output_files['glop2.g'],
                                      actual_output_files['glop3.g'])
        finally:
            if tmpdir:
                host.rmtree(tmpdir)
            if orig_wd:
                host.chdir(orig_wd)

    def test_print_ast(self):
        self.check_cmd(['-e', 'grammar = "hello"', '--ast'],
                       returncode=0,
                       out='[\n'
                           '  "rules",\n'
                           '  [\n'
                           '    [\n'
                           '      "rule",\n'
                           '      "grammar",\n'
                           '      [\n'
                           '        "lit",\n'
                           '        "hello"\n'
                           '      ]\n'
                           '    ]\n'
                           '  ]\n'
                           ']\n')

    def test_version(self):
        self.check_cmd(['-V'], returncode=0, out=(glop.tool.VERSION + '\n'),
                       err=None)
        self.check_cmd(['--version'], returncode=0, out=(glop.tool.VERSION + '\n'),
                       err=None)


#!/usr/bin/python3
# Script responsible for removing extra tags of nightly images
# QUAY_ACCESS_TOKEN is needed to set as environment variable before executing script
# The access token is used for authentication against the quay api.

import os
import json
import requests
from dateutil.relativedelta import *
from dateutil.easter import *
from dateutil.rrule import *
from dateutil.parser import *
from datetime import *
import argparse

try:
    QUAY_ACCESS_TOKEN = os.environ['QUAY_ACCESS_TOKEN']
except KeyError as e:
    print("QUAY_ACCESS_TOKEN environment variable is not set. Please, set it before running the script.")
    exit('Script exiting....')

REGISTRY  = "quay.io"
NAMESPACE = "kiegroup"

IMAGES={"kogito-data-index-nightly","kogito-quarkus-ubi8-nightly",
        "kogito-quarkus-jvm-ubi8-nightly","kogito-quarkus-ubi8-s2i-nightly",
        "kogito-springboot-ubi8-nightly","kogito-springboot-ubi8-s2i-nightly",
        "kogito-jobs-service-nightly","kogito-management-console-nightly",
        "kogito-cloud-operator-nightly"
    }
def get_image_tags(image):
    '''
    Get all the available tags for the image
    :param image: image name whose tags needs to be fetched
    :return: tags: List of a strcut with tagName and lastModified as fields
    '''
    tags = []
    r = requests.get('https://{0}/api/v1/repository/{1}/{2}/tag/?onlyActiveTags=true'.format(REGISTRY,NAMESPACE,image) , headers={'content-type': 'application/json', 'Authorization': 'Bearer ' + QUAY_ACCESS_TOKEN })
    image_metadata= json.loads(r.text)
    num_tags = len(image_metadata['tags'])
    for i in range(num_tags):
        tags.append({
            "tagName" : image_metadata['tags'][i]['name'],
            "lastModified" : parse(image_metadata['tags'][i]['last_modified'])
        })

    return tags

def delete_image_tags(image, tags):
    '''
    Deletes the extra image tags from the repository
    :param image: Image whose tags needs to be deleted
    :param tags: List of struct with `tagName` and `last_modified` as fields for the image that needs to be deleted
    '''
    if len(tags) == 0:
        print("Image {} does not have extra tags that needs to be deleted".format(image))
    else:
        for tag in tags:
            requests.delete('https://{0}/api/v1/repository/{1}/{2}/tag/{3}'.format(REGISTRY,NAMESPACE,image,tag['tagName']) , headers={'content-type': 'application/json', 'Authorization': 'Bearer ' + QUAY_ACCESS_TOKEN })
        print("Successfully deleted {} tags for the image {}".format(len(tags),image))

def get_and_delete_old_tags(image,max_tags):
    '''
    Driver function, calls the `get_image_tags` to get all the available tags for a image
    finds the tags that needs to be deleted and then passes them to `delete_image_tags`
    :param image: image name whose old tags needs to be deleted
    :param max_tags: Number of maximum tags to be kept for the image
    '''
    all_tags = get_image_tags(image)

    all_tags = list(filter(lambda tag: tag["tagName"]!="latest", all_tags))   #Filter out the entry with latest as tagName from the struct list
    all_tags.sort(key=lambda tagInfo: tagInfo.get("lastModified"))  #sorting in ascending order to get oldest tag on top
    delete_tags = []
    if (len(all_tags) - max_tags) > 0:
        delete_tags = all_tags[:len(all_tags) - max_tags]

    delete_image_tags(image,delete_tags)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Removes extra tags from the registry')
    parser.add_argument('--max-tags', dest='max_tags', default=50,type=int, help='Defines the maximum number of tags for the image to be available, defaults to 10')
    args = parser.parse_args()

    for image in IMAGES:
        get_and_delete_old_tags(image,args.max_tags)


n = int(input())
n_list = input()
m = int(input())
m_list = input()

n_list = list(map(int, n_list.split(" ")))
m_list = list(map(int, m_list.split(" ")))

dic = {}

for i in n_list:
    if i not in dic:
        dic[i] = 1
    else:
        dic[i] = dic[i]+1

for i in m_list:
    if i in dic:
        print(dic[i], end=" ")
    else:
        print(0,end=" ")


import pytest
import pytest_spec.basic as basic

class TestErrors:
    def test_zero(parameter_list):
        with pytest.raises(ZeroDivisionError) as e:
            basic.division_by_zero(1)
        assert e.type == ZeroDivisionError
        assert e.typename == "ZeroDivisionError"
        assert str(e.value) == "division by zero"

# 引数を変えて行うtest
def add(a, b):
    if type(a) is not int or type(b) is not int:
        raise TypeError
    return a + b

@pytest.mark.parametrize("a,b,expected", [(1, 2, 3), (4, 5, 9), (10, 23, 33)])
def test_add(a, b, expected):
    assert add(a, b) == expected

# 引数を変えて、いずれも例外を吐くことを確認するtest
@pytest.mark.parametrize("a,b,expected", [("1", 2, 3), (None, 5, 9), (10, [1], 33)])
def test_add_2(a, b, expected):
    with pytest.raises(TypeError):
        add(a, b)


# -------------------------------------------------
# [programmers] 큰수 만들기 (그리디)
# 1. 가장 큰 수를 찾음
# 2. 가장 큰수의 왼쪽 중 가장 작은 수 날림
# 3. k의 개수가 남으면 가장 큰수 오른쪽 가장 작은수 날림
# -------------------------------------------------
# def solution(number, k):
#     max_value = max(number)     # 아스키 코드로 가장 큰 문자열 반환
#     # for i in number[::-1]:
#     #     if i > max_value:
#     #         max_value = i

#     left = []
#     right = []
#     for i in range(len(number)):
#         if max_value == number[i]:
#             left, right = list(number[:i]), list(number[i:])     # 큰 수 기준 왼쪽리스트, 오른쪽 리스트 나눔
#             break       # 첫번째로 큰수만나면 탈출
#     while(k):
#         if len(left) != 0:
#             left.remove(min(left))
#             k -= 1
#         else:
#             # k가 남고 left가 0이면
#             right.remove(min(right))
#             k -= 1

#     answer = "".join(left + right)
#     return answer

# print(solution("01010", 3))
# ----------------------------------------------------------------
#  테스트 케이스 2 ~ 10 실패
#  실패요인 : 예제 테스트케이스들만 고려해 알고리즘을 해석
# ----------------------------------------------------------------
def solution(number, k):
    answer = []     # stack

    for i in number:
        if len(answer) == 0:
            answer.append(i)
            continue
        if k>0:
            while answer[-1] < i:
                answer.pop()
                k -= 1
                if len(answer) == 0 or k <= 0:
                    break
        answer.append(i)

    if k > 0:               # "4321" 앞의 숫자가 뒤의 숫자 보다 모두 큰 경우(뒤부터 k개수 삭제)
        answer = answer[:-k]
    else:
        answer

    return ''.join(answer)

print(solution("928857066163493066555730841879", 7))


from tespy.networks import Network
from tespy.components import (Turbine, Pump, Condenser, HeatExchangerSimple, CycleCloser, Source, Sink)
from tespy.connections import Connection, Bus
import matplotlib.pyplot as plt
import numpy as np

def easy_process():
    # network
    fluid_list = ['Water']
    rankine_nw = Network(fluids=fluid_list)
    rankine_nw.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg')

    # components
    turb = Turbine('turbine')
    cond = Condenser('condenser')
    so = Source('source')
    si = Sink('sink')
    pump = Pump('pump')
    stm_gen = HeatExchangerSimple('steam generator')
    cc = CycleCloser('cycle closer')

    # define connections and add to network
    conn_cc_turb = Connection(cc, 'out1', turb, 'in1', label='1')
    conn_turb_cond = Connection(turb, 'out1', cond, 'in1', label='2')
    conn_cond_pump = Connection(cond, 'out1', pump, 'in1', label='3')
    conn_pump_stm_gen = Connection(pump, 'out1', stm_gen, 'in1', label='4')
    conn_stm_gen_cc = Connection(stm_gen, 'out1', cc, 'in1', label='0')

    rankine_nw.add_conns(conn_cc_turb,
                         conn_turb_cond,
                         conn_cond_pump,
                         conn_pump_stm_gen,
                         conn_stm_gen_cc)

    # define connections and add to network
    conn_so_cond = Connection(so, 'out1', cond, 'in2', label='11')
    conn_cond_si = Connection(cond, 'out2', si, 'in1', label='12')

    rankine_nw.add_conns(conn_so_cond,
                         conn_cond_si)

    # set the component and connection parameters.
    # turbine
    # m input, P output or the opposite
    turb.set_attr(eta_s=0.9)
    conn_cc_turb.set_attr(m=5, p=100, T=500, fluid={'Water': 1})
    conn_turb_cond.set_attr(x=0.95)

    # condenser
    cond.set_attr(pr1=1, pr2=1)
    conn_so_cond.set_attr(m=1000, p=1, T=20, fluid={'Water': 1})

    # pump
    conn_pump_stm_gen.set_attr(x=0)
    stm_gen.set_attr(pr=1)

    rankine_nw, powergen = assess_elect_power(rankine_nw, turb, pump)
    return rankine_nw

def analyze_process():
    """
    we will analyze the power production and the efficiency of the cycle, given constant steam mass flow and with
    varying values for the

    live steam pressure,
    live steam temperature and
    cooling water temperature level.
    """

    # network
    fluid_list = ['Water']
    rankine_nw = Network(fluids=fluid_list)
    rankine_nw.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg')

    # components
    turb = Turbine('turbine')
    cond = Condenser('condenser')
    so = Source('source')
    si = Sink('sink')
    pump = Pump('pump')
    stm_gen = HeatExchangerSimple('steam generator')
    cc = CycleCloser('cycle closer')

    # define connections and add to network
    conn_cc_turb = Connection(cc, 'out1', turb, 'in1', label='1')
    conn_turb_cond = Connection(turb, 'out1', cond, 'in1', label='2')
    conn_cond_pump = Connection(cond, 'out1', pump, 'in1', label='3')
    conn_pump_stm_gen = Connection(pump, 'out1', stm_gen, 'in1', label='4')
    conn_stm_gen_cc = Connection(stm_gen, 'out1', cc, 'in1', label='0')

    rankine_nw.add_conns(conn_cc_turb,
                         conn_turb_cond,
                         conn_cond_pump,
                         conn_pump_stm_gen,
                         conn_stm_gen_cc)

    # define connections and add to network
    conn_so_cond = Connection(so, 'out1', cond, 'in2', label='11')
    conn_cond_si = Connection(cond, 'out2', si, 'in1', label='12')

    rankine_nw.add_conns(conn_so_cond,
                         conn_cond_si)

    # set the component and connection parameters.
    # turbine
    # m input, P output or the opposite
    turb.set_attr(eta_s=0.90) #
    conn_cc_turb.set_attr(m=10, p=150, T=600, fluid={'Water': 1}) #
    conn_turb_cond.set_attr(p=0.1) #
    # conn_turb_cond.set_attr(x=0.95)

    # condenser
    cond.set_attr(pr1=1, pr2=1, ttd_u = 10) #
    conn_so_cond.set_attr( p=1.2, T=20, fluid={'Water': 1})  #
    # conn_cond_si.set_attr(T=30) #

    # pump
    pump.set_attr(eta_s=0.75) #
    # conn_pump_stm_gen.set_attr(x=0)

    # steam generator
    stm_gen.set_attr(pr=0.9) #

    rankine_nw, powergen = assess_elect_power(rankine_nw, turb, pump)

    """
     ### from here starts the analysis ###
     """

    data, eta, power = define_data()

    """ case 1:T steam is variable. p steam and T cooling constant """
    # for T in data['T_livesteam']:
    #     conn_cc_turb.set_attr(T=T)
    #     rankine_nw.solve('design')
    #     eta['T_livesteam'] += [abs(powergen.P.val) / stm_gen.Q.val * 100]
    #     power['T_livesteam'] += [abs(powergen.P.val) / 1e6]

    """ case 2:T cooling is variable. T steam and p steam constant """
    conn_cc_turb.set_attr(T=600)
    for T in data['T_cooling']:
        conn_so_cond.set_attr(T=T)
        rankine_nw.solve('design')
        eta['T_cooling'] += [abs(powergen.P.val) / stm_gen.Q.val * 100]
        power['T_cooling'] += [abs(powergen.P.val) / 1e6]

    return rankine_nw

def define_data():
    data = {
        'T_livesteam': np.linspace(450, 750, 7),
        'T_cooling': np.linspace(15, 45, 7),
        'p_livesteam': np.linspace(75, 225, 7)
    }
    eta = {
        'T_livesteam': [],
        'T_cooling': [],
        'p_livesteam': []
    }
    power = {
        'T_livesteam': [],
        'T_cooling': [],
        'p_livesteam': []
    }
    return data, eta, power

def assess_elect_power(rankine_nw, turb, pump):
    powergen = Bus("electrical power output")

    powergen.add_comps(
        {"comp": turb, "char": 0.97, "base": "component"},
        {"comp": pump, "char": 0.97, "base": "bus"},
    )
    # base: definition of efficiency -> see docu
    # see difference between component value and bus value in results
    # turbine: bus > component. mech to ele
    # pump: component > bus. ele to mech

    rankine_nw.add_busses(powergen)
    return rankine_nw, powergen

def solve(rankine_nw):
    # solve
    rankine_nw.set_attr(iterinfo=False)  # disable the printout of the convergence history
    rankine_nw.solve(mode='design')
    rankine_nw.print_results()

if __name__ =='__main__':
    # rankine_nw = easy_process()
    rankine_nw = analyze_process()
    solve(rankine_nw)