import sys; sys.path.append('..'); sys.path.append('../lib/')
from lib.raster_io import raster_to_array, array_to_raster, raster_to_metadata
from lib.raster_resample import resample
from lib.stats_filters import mode_filter, feather_s2_filter
from lib.stats_local_no_kernel import radiometric_quality
from lib.stats_kernel import create_kernel
from lib.utils_core import madstd
from multiprocessing import Pool, cpu_count
from time import time
import cv2
import os
import xml.etree.ElementTree as ET
import datetime
from shutil import copyfile
import math
from glob import glob
import numpy as np

def get_band_paths(safe_folder):
    bands = {
        "10m": {
          "B02": None,
          "B03": None,
          "B04": None,
          "B08": None,
        },
        "20m": {
          "B02": None,
          "B03": None,
          "B04": None,
          "B05": None,
          "B06": None,
          "B07": None,
          "B8A": None,
          "B11": None,
          "B12": None,
          "SCL": None,
        },
        "60m": {
          "B01": None,
          "B02": None,
          "B03": None,
          "B04": None,
          "B05": None,
          "B06": None,
          "B07": None,
          "B8A": None,
          "B09": None,
          "B11": None,
          "B12": None,
          "SCL": None,
        },
        "QI": {
            'CLDPRB_20m': None,
            'CLDPRB_60m': None,
        }
    }

    assert os.path.isdir(safe_folder), f"Could not find folder: {safe_folder}"

    bands['QI']['CLDPRB_20m'] = glob(f"{safe_folder}/GRANULE/*/QI_DATA/MSK_CLDPRB_20m.jp2")[0]
    bands['QI']['CLDPRB_60m'] = glob(f"{safe_folder}/GRANULE/*/QI_DATA/MSK_CLDPRB_60m.jp2")[0]

    bands_10m = glob(f"{safe_folder}/GRANULE/*/IMG_DATA/R10m/*_???_*.jp2")
    for band in bands_10m:
        basename = os.path.basename(band)
        band_name = basename.split('_')[2]
        if band_name == 'B02':
            bands['10m']['B02'] = band
        if band_name == 'B03':
            bands['10m']['B03'] = band
        if band_name == 'B04':
            bands['10m']['B04'] = band
        if band_name == 'B08':
            bands['10m']['B08'] = band
        if band_name == 'AOT':
            bands['10m']['AOT'] = band

    bands_20m = glob(f"{safe_folder}/GRANULE/*/IMG_DATA/R20m/*.jp2")
    for band in bands_20m:
        basename = os.path.basename(band)
        band_name = basename.split('_')[2]
        if band_name == 'B02':
            bands['20m']['B02'] = band
        if band_name == 'B03':
            bands['20m']['B03'] = band
        if band_name == 'B04':
            bands['20m']['B04'] = band
        if band_name == 'B05':
            bands['20m']['B05'] = band
        if band_name == 'B06':
            bands['20m']['B06'] = band
        if band_name == 'B07':
            bands['20m']['B07'] = band
        if band_name == 'B8A':
            bands['20m']['B8A'] = band
        if band_name == 'B09':
            bands['20m']['B09'] = band
        if band_name == 'B11':
            bands['20m']['B11'] = band
        if band_name == 'B12':
            bands['20m']['B12'] = band
        if band_name == 'SCL':
            bands['20m']['SCL'] = band
        if band_name == 'AOT':
            bands['20m']['AOT'] = band

    bands_60m = glob(f"{safe_folder}/GRANULE/*/IMG_DATA/R60m/*_???_*.jp2")
    for band in bands_60m:
        basename = os.path.basename(band)
        band_name = basename.split('_')[2]
        if band_name == 'B01':
            bands['60m']['B01'] = band
        if band_name == 'B02':
            bands['60m']['B02'] = band
        if band_name == 'B03':
            bands['60m']['B03'] = band
        if band_name == 'B04':
            bands['60m']['B04'] = band
        if band_name == 'B05':
            bands['60m']['B05'] = band
        if band_name == 'B06':
            bands['60m']['B06'] = band
        if band_name == 'B07':
            bands['60m']['B07'] = band
        if band_name == 'B8A':
            bands['60m']['B8A'] = band
        if band_name == 'B09':
            bands['60m']['B09'] = band
        if band_name == 'B11':
            bands['60m']['B11'] = band
        if band_name == 'B12':
            bands['60m']['B12'] = band
        if band_name == 'SCL':
            bands['60m']['SCL'] = band
        if band_name == 'AOT':
            bands['60m']['AOT'] = band

    for outer_key in bands:
        for inner_key in bands[outer_key]:
            current_band = bands[outer_key][inner_key]
            assert current_band != None, f'{outer_key} - {inner_key} was not found. Verify the folders. Was the decompression interrupted?'

    return bands

def get_metadata(safe_folder):
    metadata = {
        "PRODUCT_START_TIME": None,
        "PRODUCT_STOP_TIME": None,
        "PRODUCT_URI": None,
        "PROCESSING_LEVEL": None,
        "PRODUCT_TYPE": None,
        "PROCESSING_BASELINE": None,
        "GENERATION_TIME": None,
        "SPACECRAFT_NAME": None,
        "DATATAKE_SENSING_START": None,
        "SENSING_ORBIT_NUMBER": None,
        "SENSING_ORBIT_DIRECTION": None,
        "EXT_POS_LIST": None,
        "Cloud_Coverage_Assessment": None,
        "NODATA_PIXEL_PERCENTAGE": None,
        "SATURATED_DEFECTIVE_PIXEL_PERCENTAGE": None,
        "DARK_FEATURES_PERCENTAGE": None,
        "CLOUD_SHADOW_PERCENTAGE": None,
        "VEGETATION_PERCENTAGE": None,
        "NOT_VEGETATED_PERCENTAGE": None,
        "WATER_PERCENTAGE": None,
        "UNCLASSIFIED_PERCENTAGE": None,
        "MEDIUM_PROBA_CLOUDS_PERCENTAGE": None,
        "HIGH_PROBA_CLOUDS_PERCENTAGE": None,
        "THIN_CIRRUS_PERCENTAGE": None,
        "SNOW_ICE_PERCENTAGE": None,
        "ZENITH_ANGLE": None,
        "AZIMUTH_ANGLE": None,
        "SUN_ELEVATION": None,
        "folder": safe_folder,
        "gains": {}
    }

    meta_xml = os.path.join(safe_folder, "MTD_MSIL2A.xml")
    meta_solar = glob(safe_folder + '/GRANULE/*/MTD_TL.xml')[0]

    assert os.path.isfile(meta_xml), f"{safe_folder} did not contain a valid metadata file."
    assert os.path.isfile(meta_solar), f"{meta_solar} did not contain a valid metadata file."

    # Parse the xml tree and add metadata
    root = ET.parse(meta_xml).getroot()
    for elem in root.iter():
        if elem.tag in metadata:
            try:
                metadata[elem.tag] = float(elem.text)  # Number?
            except:
                try:
                    metadata[elem.tag] = datetime.datetime.strptime(
                        elem.text, "%Y-%m-%dT%H:%M:%S.%f%z"
                    )  # Date?
                except:
                    metadata[elem.tag] = elem.text
        if elem.tag == 'PHYSICAL_GAINS':
            if elem.attrib['bandId'] == '0':
                metadata['gains']['B01'] = float(elem.text)
            if elem.attrib['bandId'] == '1':
                metadata['gains']['B02'] = float(elem.text)
            if elem.attrib['bandId'] == '2':
                metadata['gains']['B03'] = float(elem.text)
            if elem.attrib['bandId'] == '3':
                metadata['gains']['B04'] = float(elem.text)
            if elem.attrib['bandId'] == '4':
                metadata['gains']['B05'] = float(elem.text)
            if elem.attrib['bandId'] == '5':
                metadata['gains']['B06'] = float(elem.text)
            if elem.attrib['bandId'] == '6':
                metadata['gains']['B07'] = float(elem.text)
            if elem.attrib['bandId'] == '7':
                metadata['gains']['B08'] = float(elem.text)
            if elem.attrib['bandId'] == '8':
                metadata['gains']['B8A'] = float(elem.text)
            if elem.attrib['bandId'] == '9':
                metadata['gains']['B09'] = float(elem.text)
            if elem.attrib['bandId'] == '10':
                metadata['gains']['B10'] = float(elem.text)
            if elem.attrib['bandId'] == '11':
                metadata['gains']['B11'] = float(elem.text)
            if elem.attrib['bandId'] == '12':
                metadata['gains']['B12'] = float(elem.text)

    # Parse the xml tree and add metadata
    root = ET.parse(meta_solar).getroot()
    for elem in root.iter():
        if elem.tag == 'Mean_Sun_Angle':
            metadata['ZENITH_ANGLE'] = float(elem.find('ZENITH_ANGLE').text)
            metadata['SUN_ELEVATION'] = 90 - metadata['ZENITH_ANGLE']
            metadata['AZIMUTH_ANGLE'] = float(elem.find('AZIMUTH_ANGLE').text)

    # Did we get all the metadata?
    for name in metadata:
        assert (
            metadata[name] != None
        ), f"Input metatadata file invalid. {metadata[name]}"

    metadata["INVALID"] = (
        metadata['NODATA_PIXEL_PERCENTAGE']
        + metadata["SATURATED_DEFECTIVE_PIXEL_PERCENTAGE"]
        + metadata["CLOUD_SHADOW_PERCENTAGE"]
        + metadata["MEDIUM_PROBA_CLOUDS_PERCENTAGE"]
        + metadata["HIGH_PROBA_CLOUDS_PERCENTAGE"]
        + metadata["THIN_CIRRUS_PERCENTAGE"]
        + metadata["SNOW_ICE_PERCENTAGE"]
        + metadata["DARK_FEATURES_PERCENTAGE"]
    )

    metadata["timestamp"] = float(metadata['DATATAKE_SENSING_START'].timestamp())

    return metadata

def assess_radiometric_quality(metadata, calc_quality='high', score=False):
    if calc_quality == 'high':
        scl = raster_to_array(metadata['path']['20m']['SCL']).astype('intc')
        aot = raster_to_array(metadata['path']['20m']['AOT']).astype('intc')
        band_02 = raster_to_array(metadata['path']['20m']['B02']).astype('intc')
        band_12 = raster_to_array(metadata['path']['20m']['B12']).astype('intc')
        band_cldprb = raster_to_array(metadata['path']['QI']['CLDPRB_20m'])
        distance = 63
    else:
        scl = raster_to_array(metadata['path']['60m']['SCL']).astype('intc')
        aot = raster_to_array(metadata['path']['60m']['AOT']).astype('intc')
        band_cldprb = raster_to_array(metadata['path']['QI']['CLDPRB_60m'])
        band_02 = raster_to_array(metadata['path']['60m']['B02']).astype('intc')
        band_12 = raster_to_array(metadata['path']['60m']['B12']).astype('intc')
        distance = 21

    kernel_nodata = create_kernel(201, weighted_edges=False, weighted_distance=False, normalise=False).astype('uint8')

    # Dilate nodata values by 1km each side
    nodata_dilated = cv2.dilate((scl == 0).astype('uint8'), kernel_nodata).astype('intc')

    darkprb = np.zeros(scl.shape)
    darkprb = np.where(scl == 2, 55, 0)
    darkprb = np.where(scl == 3, 45, darkprb).astype('uint8')
    darkprb = cv2.GaussianBlur(darkprb, (distance, distance), 0).astype(np.double)
    band_cldprb = cv2.GaussianBlur(band_cldprb, (distance, distance), 0).astype(np.double)

    quality = np.zeros(scl.shape, dtype=np.double)

    td = 0.0 if score is True else metadata['time_difference'] / 86400

    # OBS: the radiometric_quality functions mutates the quality input.
    combined_score = radiometric_quality(scl, band_02, band_12, band_cldprb, darkprb, aot, nodata_dilated, quality, td, metadata['SUN_ELEVATION'])

    if score is True:
        return combined_score

    blur_dist = 31
    quality_blurred = cv2.GaussianBlur(quality, (blur_dist, blur_dist), 0).astype(np.double)

    return quality_blurred, scl

def prepare_metadata(list_of_SAFE_images):

    metadata = []

    # Verify files
    for index, image in enumerate(list_of_SAFE_images):
        image_name = os.path.basename(image)
        assert (len(image_name.split("_")) == 7), f"Input file has invalid pattern: {image_name}"
        assert (image_name.rsplit(".")[1] == "SAFE"), f"Input is not a .SAFE folder: {image_name}"

        # Check if / or // or \\ at end of string, if not attach /
        if image.endswith("//"):
            list_of_SAFE_images[index] = image[:-2]

        if image.endswith("\\"):
            list_of_SAFE_images[index] = image[:-2]

        if image.endswith("/"):
            list_of_SAFE_images[index] = image[:-1]

        # Check if safe folder exists
        assert os.path.isdir(list_of_SAFE_images[index]), f"Could not find input folder: {list_of_SAFE_images[index]}"

        # Check if all images are of the same tile.
        if index == 0:
            tile_name = image_name.split("_")[5]
        else:
            this_tile = image_name.split("_")[5]
            assert (tile_name == this_tile), f"Multiple tiles in inputlist: {tile_name}, {this_tile}"

        image_metadata = get_metadata(list_of_SAFE_images[index])
        image_metadata['path'] = get_band_paths(list_of_SAFE_images[index])
        image_metadata['name'] = os.path.basename(os.path.normpath(image_metadata['folder'])).split('_')[-1].split('.')[0]
        metadata.append(image_metadata)

    # lowest_invalid_percentage = 100
    best_image = None
    highest_quality = 0

    for index, value in enumerate(metadata):
        quality_score = assess_radiometric_quality(value, calc_quality='low', score=True)
        metadata[index]['quality_score'] = quality_score
        if quality_score > highest_quality:
            highest_quality = quality_score
            best_image = value

    # Calculate the time difference from each image to the best image
    for meta in metadata:
        meta['time_difference'] = abs(meta['timestamp'] - best_image['timestamp'])

    # Sort by distance to best_image
    metadata = sorted(metadata, key=lambda k: -k['quality_score'])

    return metadata

# TODO: handle all bands
# TODO: add pansharpen
# TODO: ai resample of SWIR

def mosaic_tile(
    list_of_SAFE_images,
    out_dir,
    out_name='mosaic',
    dst_projection=None,
    feather=True,
    target_quality=100,
    threshold_change=0.5,
    threshold_quality=10.0,
    feather_dist=21,
    feather_scl=5,
    filter_tracking=True,
    match_mean=True,
    allow_nodata=False,
    max_days=120,
    max_images_include=15,
    max_images_search=25,
    output_scl=True,
    output_tracking=True,
    output_quality=False,
    verbose=True,
):
    start_time = time()

    # Verify input
    assert isinstance(list_of_SAFE_images, list), "list_of_SAFE_images is not a list. [path_to_safe_file1, path_to_safe_file2, ...]"
    assert isinstance(out_dir, str), f"out_dir is not a string: {out_dir}"
    assert isinstance(out_name, str), f"out_name is not a string: {out_name}"
    assert len(list_of_SAFE_images) > 1, "list_of_SAFE_images is empty or only a single image."

    if verbose: print('Selecting best image..')
    metadata = prepare_metadata(list_of_SAFE_images)

    # Sorted by best, so 0 is the best one.
    best_image = metadata[0]
    best_image_name = best_image['name']

    if verbose: print(f'Selected: {best_image_name} {out_name}')

    if verbose: print('Preparing base image..')
    master_quality, master_scl = assess_radiometric_quality(best_image)
    tracking_array = np.zeros(master_quality.shape, dtype='uint8')

    if match_mean is True:
        metadata[0]['scl'] = np.copy(master_scl)

    time_limit = (max_days * 86400)

    master_quality_avg = (master_quality.sum() / master_quality.size)
    i = 1  # The 0 index is for the best image
    processed_images_indices = [0]

    # Loop the images and update the tracking array (SYNTHESIS)
    if verbose: print(f'Initial. tracking array: (quality {round(master_quality_avg, 2)}%) (0/{max_days} days) (goal {target_quality}%)')
    while (
        (master_quality_avg < target_quality)
        and i < len(metadata) - 1
        and len(processed_images_indices) <= max_images_include
    ):
        if (metadata[i]['time_difference'] > time_limit):
            i += 1
            continue

        if (i >= max_images_search):
            if (master_scl == 0).sum() == 0 or allow_nodata is True:
                break
            if verbose: print('Continuing dispite reaching max_images_search as there is still nodata in tile..')

        # Time difference
        td = int(round(metadata[i]['time_difference'] / 86400, 0))

        # Assess quality of current image
        quality, scl = assess_radiometric_quality(metadata[i])

        # Calculate changes. Always update nodata.
        change_mask = (quality > master_quality) | ((master_scl == 0) & (scl != 0))
        percent_change = (change_mask.sum() / change_mask.size) * 100

        # Calculate the global change in quality
        quality_global = np.where(change_mask, quality, master_quality)
        quality_global_avg = quality_global.sum() / quality_global.size
        quality_global_change = quality_global_avg - master_quality_avg

        if ((percent_change > threshold_change) and (quality_global_change > threshold_change)):

            # Udpdate the trackers
            tracking_array = np.where(change_mask, i, tracking_array).astype('uint8')
            master_scl = np.where(change_mask, scl, master_scl).astype('intc')
            master_quality = np.where(change_mask, quality, master_quality).astype(np.double)
            master_quality_avg = quality_global_avg

            # Save the scene classification in memory. This cost a bit of RAM but makes harmonisation much faster..
            metadata[i]['scl'] = scl.astype('uint8')

            # Append to the array that keeps track on which images are used in the synth process..
            processed_images_indices.append(i)

            img_name = metadata[i]['name']
            if verbose: print(f'Updating tracking array: (quality {round(master_quality_avg, 2)}%) ({td}/{max_days} days) (goal {target_quality}%) (name {img_name})')
        else:
            if verbose: print(f'Skipping image due to low change.. ({round(threshold_change, 3)}% threshold) ({td}/{max_days} days)')

        i += 1

    # Free memory
    change_mask = None
    change_mask_inv = None
    quality_global = None
    quality = None
    scl = None

    # Only merge images if there are more than one.
    multiple_images = len(processed_images_indices) > 1
    if match_mean is True and multiple_images is True:
        if verbose: print('Harmonising layers..')

        total_counts = 0
        counts = []
        weights = []

        for i in processed_images_indices:
            metadata[i]['stats'] = { 'B02': {}, 'B03': {}, 'B04': {}, 'B08': {} }
            pixel_count = (tracking_array == i).sum()
            total_counts += pixel_count
            counts.append(pixel_count)

        for i in range(len(processed_images_indices)):
            w = counts[i] / total_counts
            weights.append(w)

        medians = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }
        medians_4 = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }
        medians_5 = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }
        medians_6 = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }

        madstds = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }
        madstds_4 = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }
        madstds_5 = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }
        madstds_6 = { 'B02': [], 'B03': [], 'B04': [], 'B08': [] }

        for v, i in enumerate(processed_images_indices):
            layer_mask_4 = metadata[i]['scl'] != 4
            layer_mask_4_sum = (layer_mask_4 == False).sum()
            layer_mask_5 = metadata[i]['scl'] != 5
            layer_mask_5_sum = (layer_mask_5 == False).sum()
            layer_mask_6 = metadata[i]['scl'] != 6
            layer_mask_6_sum = (layer_mask_6 == False).sum()

            layer_mask = (layer_mask_4 | layer_mask_5 | layer_mask_6 | (metadata[i]['scl'] == 7)) == False

            for band in ['B02', 'B03', 'B04', 'B08']:
                if band == 'B08':
                    array = raster_to_array(resample(metadata[i]['path']['10m'][band], reference_raster=metadata[i]['path']['20m']['B02']))
                else:
                    array = raster_to_array(metadata[i]['path']['20m'][band])

                calc_array = np.ma.array(array, mask=layer_mask)
                calc_array_4 = np.ma.array(array, mask=layer_mask_4)
                calc_array_5 = np.ma.array(array, mask=layer_mask_5)
                calc_array_6 = np.ma.array(array, mask=layer_mask_6)

                med, mad = madstd(calc_array)
                if layer_mask_4_sum > 1000:
                    med_4, mad_4 = madstd(calc_array_4)
                else:
                    med_4, mad_4 = madstd(calc_array)

                if layer_mask_5_sum > 1000:
                    med_5, mad_5 = madstd(calc_array_5)
                else:
                    med_5, mad_5 = madstd(calc_array)

                if layer_mask_6_sum > 1000:
                    med_6, mad_6 = madstd(calc_array_6)
                else:
                    med_6, mad_6 = madstd(calc_array)

                if med == 0 or mad == 0: med, mad = madstd(array)
                if med_4 == 0 or mad_4 == 0: med_4, mad_4 = (med, mad)
                if med_5 == 0 or mad_5 == 0: med_5, mad_5 = (med, mad)
                if med_6 == 0 or mad_6 == 0: med_6, mad_6 = (med, mad)

                medians[band].append(med)
                medians_4[band].append(med_4)
                medians_5[band].append(med_5)
                medians_6[band].append(med_6)

                madstds[band].append(mad)
                madstds_4[band].append(mad_4)
                madstds_5[band].append(mad_5)
                madstds_6[band].append(mad_6)

        targets_median = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }
        targets_median_4 = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }
        targets_median_5 = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }
        targets_median_6 = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }

        targets_madstd = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }
        targets_madstd_4 = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }
        targets_madstd_5 = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }
        targets_madstd_6 = { 'B02': None, 'B03': None, 'B04': None, 'B08': None }

        for band in ['B02', 'B03', 'B04', 'B08']:
            targets_median[band] = np.average(medians[band], weights=weights)
            targets_median_4[band] = np.average(medians_4[band], weights=weights)
            targets_median_5[band] = np.average(medians_5[band], weights=weights)
            targets_median_6[band] = np.average(medians_6[band], weights=weights)

            targets_madstd[band] = np.average(madstds[band], weights=weights)
            targets_madstd_4[band] = np.average(madstds_4[band], weights=weights)
            targets_madstd_5[band] = np.average(madstds_5[band], weights=weights)
            targets_madstd_6[band] = np.average(madstds_6[band], weights=weights)

        for v, i in enumerate(processed_images_indices):
            for band in ['B02', 'B03', 'B04', 'B08']:
                metadata[i]['stats'][band]['src_median'] = medians[band][v] if medians[band][v] > 0 else targets_median[band]
                metadata[i]['stats'][band]['src_median_4'] = medians_4[band][v] if medians_4[band][v] > 0 else targets_median_4[band]
                metadata[i]['stats'][band]['src_median_5'] = medians_5[band][v] if medians_5[band][v] > 0 else targets_median_5[band]
                metadata[i]['stats'][band]['src_median_6'] = medians_6[band][v] if medians_6[band][v] > 0 else targets_median_6[band]

                metadata[i]['stats'][band]['src_madstd'] = madstds[band][v] if madstds[band][v] > 0 else targets_madstd[band]
                metadata[i]['stats'][band]['src_madstd_4'] = madstds_4[band][v] if madstds_4[band][v] > 0 else targets_madstd_4[band]
                metadata[i]['stats'][band]['src_madstd_5'] = madstds_5[band][v] if madstds_5[band][v] > 0 else targets_madstd_5[band]
                metadata[i]['stats'][band]['src_madstd_6'] = madstds_6[band][v] if madstds_6[band][v] > 0 else targets_madstd_6[band]

                metadata[i]['stats'][band]['target_median'] = targets_median[band]
                metadata[i]['stats'][band]['target_median_4'] = targets_median_4[band]
                metadata[i]['stats'][band]['target_median_5'] = targets_median_5[band]
                metadata[i]['stats'][band]['target_median_6'] = targets_median_6[band]

                metadata[i]['stats'][band]['target_madstd'] = targets_madstd[band]
                metadata[i]['stats'][band]['target_madstd_4'] = targets_madstd_4[band]
                metadata[i]['stats'][band]['target_madstd_5'] = targets_madstd_5[band]
                metadata[i]['stats'][band]['target_madstd_6'] = targets_madstd_6[band]

    # Clear memory of scl images
    for j in range(len(metadata)):
        metadata[j]['scl'] = None

    if output_tracking is True:
        array_to_raster(tracking_array.astype('uint8'), reference_raster=best_image['path']['20m']['B04'], out_raster=os.path.join(out_dir, f"tracking_{out_name}.tif"), dst_projection=dst_projection)

    if output_scl is True:
        array_to_raster(master_scl.astype('uint8'), reference_raster=best_image['path']['20m']['B04'], out_raster=os.path.join(out_dir, f"scl_{out_name}.tif"), dst_projection=dst_projection)

    if output_quality is True:
        array_to_raster(master_quality.astype('float32'), reference_raster=best_image['path']['20m']['B04'], out_raster=os.path.join(out_dir, f"quality_{out_name}.tif"), dst_projection=dst_projection)

    # Resample scl and tracking array
    tracking_array = raster_to_array(resample(array_to_raster(tracking_array, reference_raster=best_image['path']['20m']['B04']), reference_raster=best_image['path']['10m']['B04']))
    master_scl = raster_to_array(resample(array_to_raster(master_scl, reference_raster=best_image['path']['20m']['B04']), reference_raster=best_image['path']['10m']['B04']))

    # Run a mode filter on the tracking array
    if filter_tracking is True and multiple_images is True:
        if verbose: print('Filtering tracking array..')

        tracking_array = mode_filter(tracking_array, 7).astype('uint8')

    # Feather the edges between joined images (ensure enough valid pixels are on each side..)
    if feather is True and multiple_images is True:
        feathers = {}

        print('Precalculating classification feathers..')
        feather_rest = feather_s2_filter(master_scl, np.array([0, 1, 2, 3, 7, 8, 9, 10, 11], dtype='intc'), feather_scl).astype('float32')
        feather_4 = feather_s2_filter(master_scl, np.array([4], dtype='intc'), feather_scl).astype('float32')
        feather_5 = feather_s2_filter(master_scl, np.array([5], dtype='intc'), feather_scl).astype('float32')
        feather_6 = feather_s2_filter(master_scl, np.array([6], dtype='intc'), feather_scl).astype('float32')

        if verbose: print('Precalculating inter-layer feathers..')
        for i in processed_images_indices:
            feathers[str(i)] = feather_s2_filter(tracking_array, np.array([i], dtype='intc'), feather_dist).astype('float32')

    if match_mean is True and feather is False and len(processed_images_indices) > 1:
        mask_4 = (master_scl == 4)
        mask_5 = (master_scl == 5)
        mask_6 = (master_scl == 6)
        mask_rest = (master_scl != 4) & (master_scl != 5) & (master_scl != 6)

    bands_to_output = ['B02', 'B03', 'B04', 'B08']
    if verbose: print('Merging band data..')
    for band in bands_to_output:
        if verbose: print(f'Writing: {band}..')
        base_image = raster_to_array(metadata[0]['path']['10m'][band]).astype('float32')

        for i in processed_images_indices:

            if match_mean and len(processed_images_indices) > 1:
                src_med = metadata[i]['stats'][band]['src_median']
                src_med_4 = metadata[i]['stats'][band]['src_median_4']
                src_med_5 = metadata[i]['stats'][band]['src_median_5']
                src_med_6 = metadata[i]['stats'][band]['src_median_6']

                src_mad = metadata[i]['stats'][band]['src_madstd']
                src_mad_4 = metadata[i]['stats'][band]['src_madstd_4']
                src_mad_5 = metadata[i]['stats'][band]['src_madstd_5']
                src_mad_6 = metadata[i]['stats'][band]['src_madstd_6']

                target_med = metadata[i]['stats'][band]['target_median']
                target_med_4 = metadata[i]['stats'][band]['target_median_4']
                target_med_5 = metadata[i]['stats'][band]['target_median_5']
                target_med_6 = metadata[i]['stats'][band]['target_median_6']

                target_mad = metadata[i]['stats'][band]['target_madstd']
                target_mad_4 = metadata[i]['stats'][band]['target_madstd_4']
                target_mad_5 = metadata[i]['stats'][band]['target_madstd_5']
                target_mad_6 = metadata[i]['stats'][band]['target_madstd_6']

            if i == 0:
                if match_mean and len(processed_images_indices) > 1:
                    dif = base_image - src_med
                    dif_4 = base_image - src_med_4
                    dif_5 = base_image - src_med_5
                    dif_6 = base_image - src_med_6

                    if feather is True and len(processed_images_indices) > 1:
                        base_image = (((dif * target_mad) / src_mad) + target_med) * feather_rest
                        base_image = np.add(base_image, (((dif_4 * target_mad_4) / src_mad_4) + target_med_4) * feather_4)
                        base_image = np.add(base_image, (((dif_5 * target_mad_5) / src_mad_5) + target_med_5) * feather_5)
                        base_image = np.add(base_image, (((dif_6 * target_mad_6) / src_mad_6) + target_med_6) * feather_6)

                    else:
                        base_image_rest = ((dif * target_mad) / src_mad) + target_med
                        base_image_4 = ((dif_4 * target_mad_4) / src_mad_4) + target_med_4
                        base_image_5 = ((dif_5 * target_mad_5) / src_mad_5) + target_med_5
                        base_image_6 = ((dif_6 * target_mad_6) / src_mad_6) + target_med_6

                        base_image = np.where(mask_rest, base_image_rest, base_image)
                        base_image = np.where(mask_4, base_image_4, base_image)
                        base_image = np.where(mask_5, base_image_5, base_image)
                        base_image = np.where(mask_6, base_image_6, base_image)

                    base_image = np.where(base_image >= 0, base_image, 0)

                if feather is True and len(processed_images_indices) > 1:
                    base_image = base_image * feathers[str(i)]

            else:
                add_band = raster_to_array(metadata[i]['path']['10m'][band]).astype('float32')

                if match_mean:
                    dif = add_band - src_med
                    dif_4 = add_band - src_med_4
                    dif_5 = add_band - src_med_5
                    dif_6 = add_band - src_med_6

                    if feather is True:
                        add_band = (((dif * target_mad) / src_mad) + target_med) * feather_rest
                        add_band = np.add(add_band, (((dif_4 * target_mad_4) / src_mad_4) + target_med_4) * feather_4)
                        add_band = np.add(add_band, (((dif_5 * target_mad_5) / src_mad_5) + target_med_5) * feather_5)
                        add_band = np.add(add_band, (((dif_6 * target_mad_6) / src_mad_6) + target_med_6) * feather_6)
                    else:
                        add_band_rest = ((dif * target_mad) / src_mad) + target_med
                        add_band_4 = ((dif_4 * target_mad_4) / src_mad_4) + target_med_4
                        add_band_5 = ((dif_5 * target_mad_5) / src_mad_5) + target_med_5
                        add_band_6 = ((dif_6 * target_mad_6) / src_mad_6) + target_med_6

                        add_band = np.where(mask_rest, add_band_rest, add_band)
                        add_band = np.where(mask_4, add_band_4, add_band)
                        add_band = np.where(mask_5, add_band_5, add_band)
                        add_band = np.where(mask_6, add_band_6, add_band)

                    add_band = np.where(add_band >= 0, add_band, 0)

                if feather is True:
                    base_image = np.add(base_image, (add_band * feathers[str(i)]))
                else:
                    base_image = np.where(tracking_array == i, add_band, base_image).astype('float32')

        array_to_raster(np.rint(base_image).astype('uint16'), reference_raster=best_image['path']['10m'][band], out_raster=os.path.join(out_dir, f"{band}_{out_name}.tif"), dst_projection=dst_projection)

    if verbose: print(f'Completed mosaic in: {round((time() - start_time) / 60, 1)}m')


from config import get_arguments
from load_data import LoadData
from model import FastText, get_classifier
from utils import get_one_hot_labels
import pandas as pd
import pickle
from sklearn.metrics import accuracy_score
import numpy as np

def load_test_data(config):
    """
    load test data from config.
    """
    load_instance = LoadData.load(config.preprocessing_class_path)
    if config.preprocess:
        load_instance.df_data = pd.read_csv(config.path_test_data)
        df_test = load_instance.preprocess()
        return df_test
    else:
        config.n_classes = load_instance.config.n_classes
        df = pd.read_csv(config.path_test_data)
        df["labels"] = df["labels"].apply(eval)
        return df

def get_IoU_score(y_test, predictions):
    """
    give a target list y_test and the predictions of the multilabel classifier  ,
    this function returns the IoU score.
    """
    score = 0
    for target, pred in zip(y_test, predictions):
        target_ones = np.where(target == 1)[0]
        pred_ones = np.where(np.array(pred) == 1)[0]
        current_score = len(
            set(target_ones).intersection(set(pred_ones))
        ) / len(set(target_ones).union(set(pred_ones)))
        score += current_score

    return score / len(y_test)

if __name__ == "__main__":
    parser = get_arguments()
    config = parser.parse_args()
    df_test = load_test_data(config)
    fast_text = FastText(config, df_test)
    X_test = fast_text.get_embeddings()
    y_test = get_one_hot_labels(df_test, config)

    # load classifer
    classifier = pickle.load(open(config.model_path, "rb"))
    print('generating predictions ...')
    predictions = classifier.predict(X_test)
    print("Exact accuracy is {}".format(accuracy_score(y_test, predictions)))
    print("IoU metric score is {}".format(get_IoU_score(y_test, predictions)))


# -*- coding: utf-8 -*-
from openerp import fields, models, api

class AccountVoucher(models.Model):

    _inherit = "account.voucher"

    billing_id = fields.Many2one(
        'account.billing',
        string='Billing Ref',
        domain=[('state', '=', 'billed'), ('payment_id', '=', False)],
        readonly=True,
        states={'draft': [('readonly', False)]})

    @api.multi
    def proforma_voucher(self):
        for rec in self:
            # Write payment id back to Billing Document
            if rec.billing_id:
                rec.billing_id.write({'payment_id': rec.id,
                                      'state': 'billed'})
        return super(AccountVoucher, self).proforma_voucher()

    @api.multi
    def cancel_voucher(self):
        for rec in self:
            # Set payment_id in Billing back to False
            if rec.billing_id:
                rec.billing_id.payment_id = False
        return super(AccountVoucher, self).cancel_voucher()

    def onchange_billing_id(self, cr, uid, ids, partner_id, journal_id,
                            amount, currency_id, ttype, date, context=None):
        if not partner_id or not journal_id:
            return {}
        res = self.recompute_voucher_lines(cr, uid, ids, partner_id,
                                           journal_id, amount, currency_id,
                                           ttype, date, context=context)
        vals = self.recompute_payment_rate(cr, uid, ids, res, currency_id,
                                           date, ttype, journal_id,
                                           amount)
        for key in vals.keys():
            res[key].update(vals[key])
        if ttype == 'sale':
            del(res['value']['line_dr_ids'])
            del(res['value']['pre_line'])
            del(res['value']['payment_rate'])
        elif ttype == 'purchase':
            del(res['value']['line_cr_ids'])
            del(res['value']['pre_line'])
            del(res['value']['payment_rate'])
        if context.get('billing_id', False):
            bill_obj = self.pool.get('account.billing')
            billing = bill_obj.browse(cr, uid, context.get('billing_id'))
            res['value'].update({'amount': billing.billing_amount})
        return res

    def finalize_voucher_move_lines(self, cr, uid, ids, account_move_lines,
                                    partner_id, journal_id, price,
                                    currency_id, ttype, date, context=None):

        super(AccountVoucher, self).finalize_voucher_move_lines(
            cr, uid, ids, account_move_lines,
            partner_id, journal_id, price,
            currency_id, ttype, date, context=None)

        if context is None:
            context = {}

        # Rewrite code from get account type.
        account_type = None
        if context.get('account_id'):
            account_type = self.pool['account.account'].browse(
                cr, uid,
                context['account_id'],
                context=context).type
        if ttype == 'payment':
            if not account_type:
                account_type = 'payable'
        else:
            if not account_type:
                account_type = 'receivable'

        move_line_pool = self.pool.get('account.move.line')
        if not context.get('move_line_ids', False):
            billing_id = context.get('billing_id', False)
            if billing_id > 0:
                billing_obj = self.pool.get('account.billing')
                billing = billing_obj.browse(cr, uid,
                                             billing_id, context=context)
                ids = move_line_pool.search(
                    cr, uid, [
                        ('state', '=', 'valid'),
                        ('account_id.type', '=', account_type),
                        ('reconcile_id', '=', False),
                        ('partner_id', '=', partner_id),
                        ('id', 'in', [
                            line.reconcile and
                            line.move_line_id.id or
                            False
                            for line in billing.line_cr_ids])
                    ], context=context)
            else:  # -- ecosoft
                ids = move_line_pool.search(
                    cr, uid, [
                        ('state', '=', 'valid'),
                        ('account_id.type', '=', account_type),
                        ('reconcile_id', '=', False),
                        ('partner_id', '=', partner_id)],
                    context=context)
        else:
            ids = context['move_line_ids']
        # Or the lines by most old first
        ids.reverse()
        account_move_lines = move_line_pool.browse(
            cr, uid, ids, context=context)

        return account_move_lines

class AccountVoucherLine(models.Model):
    _inherit = "account.voucher.line"

    reference = fields.Char(
        string='Invoice Reference',
        size=64,
        help="The partner reference of this invoice.")


import numpy as np
import pandas as pd
import random
from scipy.stats import norm

def historical_var(returns, confidence_level):
    # Calculate the historical value-at-risk
    var = np.percentile(returns, 100 - confidence_level * 100)
    return var

def monte_carlo_var(returns, confidence_level, simulations):
    # Generate random returns using Monte Carlo simulation
    simulated_returns = []
    for i in range(simulations):
        simulated_return = random.choices(returns, k=len(returns))
        simulated_returns.append(simulated_return)

    # Calculate the mean of each simulated return
    mean_simulated_returns = [np.mean(returns) for returns in simulated_returns]

    # Calculate the value-at-risk using the mean of the simulated returns
    var = np.percentile(mean_simulated_returns, 100 - confidence_level * 100)
    return var

def parametric_volatility_var(returns, confidence_level):
    # Calculate the mean and standard deviation of the returns using EWMA
    mean = returns[0]
    stddev = 0
    for i in range(1, len(returns)):
        mean = decay_factor * mean + (1 - decay_factor) * returns[i]
        stddev = np.sqrt(decay_factor * stddev**2 + (1 - decay_factor) * (returns[i] - mean)**2)

    # Calculate the z-score for the confidence level
    z_score = norm.ppf(confidence_level)

    # Calculate the value-at-risk using the mean and standard deviation of the returns
    var = mean - z_score * stddev

    return var

def risk_management(positions, returns, confidence_level, max_risk, method, simulations=1000):
    if method == "historical":
        # Calculate the historical value-at-risk
        var = historical_var(returns, confidence_level)
    elif method == "monte_carlo":
        # Calculate the Monte Carlo value-at-risk
        var = monte_carlo_var(returns, confidence_level, simulations)
    elif method == "parametric_volatility":
        # Calculate the parametric volatility value-at-risk
        var = parametric_volatility_var(returns, confidence_level)
    else:
        raise ValueError("Invalid method specified")

    # Calculate the portfolio value
    portfolio_value = positions.sum()

    # Calculate the maximum allowed risk
    max_allowed_risk = portfolio_value * max_risk

    # Check if the calculated value-at-risk exceeds the maximum allowed risk
    if var > max_allowed_risk:
        # Scale down the positions to meet the maximum risk constraint
        scale_factor = max_allowed_risk / var
        scaled_positions = positions * scale_factor
        return scaled_positions
    else:
        # Return the original positions if the value-at-risk is within bounds
        return positions

# Load the returns data into a pandas DataFrame
returns = pd.read_csv("returns.csv")

# Convert the returns data into a numpy array
returns = returns["returns"].values

# Define the positions in the portfolio
positions = np.array([100, 200, 300, 400])
# Define the confidence level
confidence_level = 0.95

# Define the maximum allowed risk as a fraction of portfolio value
max_risk = 0.1

# Define the method for calculating value-at-risk
method1 = "historical"
method2 = "monte_carlo"
method3 = "parametric_volatility"

# Apply the risk management model
scaled_positions_1 = risk_management(positions, returns, confidence_level, max_risk, method1)
scaled_positions_2 = risk_management(positions, returns, confidence_level, max_risk, method2)
scaled_positions_3 = risk_management(positions, returns, confidence_level, max_risk, method3)

# Print results
print("Scaled positions in historical VaR:", scaled_positions_1)
print("Scaled positions in Monte Carlo VaR:", scaled_positions_2)
print("Scaled positions in Parametric Volatility VaR:", scaled_positions_3)


import math
import random
import socket
from collections import deque
from struct import pack, unpack
import typing

import numpy as np

import cv2

def preprocess_image(camera_image: np.ndarray) -> np.ndarray:

    #print('camera image shape', camera_image.shape)

    frame = camera_image
    frame = cv2.flip(frame, 0)
    #frame = cv2.flip(frame, 1)

    # ignore pixels too far away
    #frame[int(len(frame)/1.5):,:] = 0

    lower = np.array([160])#np.array([0,0,150])
    upper = np.array([255])#np.array([255,255,255])
    # Threshold the HSV image to get only blue colors

    #test = cv2.GaussianBlur(rgb, (3, 3), 0)
    mask = cv2.inRange(frame, lower, upper)
    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame,frame, mask= mask)

    return res

class Action:

    COUNT = 9

    def __init__(self, vertical: int, horizontal: int):
        if vertical > 1 or vertical < -1:
            raise ValueError('Vertical must be -1, 0 or 1')
        if horizontal > 1 or horizontal < -1:
            raise ValueError('Horizontal must be -1, 0 or 1')
        self.vertical = vertical
        self.horizontal = horizontal

    @classmethod
    def from_code(cls, code: int):
        return cls(code // 3 - 1, code % 3 - 1)

    @classmethod
    def random(cls):
        return cls(random.randrange(3) - 1, random.randrange(3) - 1)

    def get_code(self) -> int:
        return (self.vertical + 1) * 3 + self.horizontal + 1

class LeftRightAction(Action):

    COUNT = 3

    def __init__(self, horizontal: int):
        super().__init__(1, horizontal)

    @classmethod
    def from_code(cls, code: int):
        return cls(code - 1)

    @classmethod
    def random(cls):
        return cls(random.randrange(3) - 1)

    def get_code(self) -> int:
        return self.horizontal + 1

class State:

    def __init__(self, data: np.ndarray, is_terminal: bool):

        # image = data[:,:,:-1]
        #cv2.imwrite('b.png', data[:,:,:-1])
        data.setflags(write=1)

        for i in range(0,4):
            image = data[:,:,i]
            preprocessed_image = preprocess_image(image)
            data[:,:,i] = preprocessed_image
        # cv2.imwrite('0.png', data[:,:,0])
        # cv2.imwrite('1.png', data[:,:,1])
        # cv2.imwrite('2.png', data[:,:,2])
        # cv2.imwrite('3.png', data[:,:,3])
        data.setflags(write=0)
        #cv2.imshow('b', data[:,:,:-1])
        #cv2.waitKey(0);
        #self.data =self.data.astype(np.float32) / 255
        #self.data = (self.data - np.mean(self.data)) / np.std(self.data, ddof=1)
        # Convert to 0 - 1 ranges
        self.data = (data.astype(np.float32) - 128) / 128
        # Z-normalize
        #self.data = (self.data - np.mean(self.data)) / np.std(self.data, ddof=1)
        # Add channel dimension
        if len(self.data.shape) < 3:
            self.data = np.expand_dims(self.data, axis=2)
        self.is_terminal = is_terminal

    def _preprocess_image(self, camera_image: np.ndarray) -> np.ndarray:

        #print('camera image shape', camera_image.shape)

        frame = camera_image
        #frame = cv2.flip(frame, 0)
        frame = cv2.flip(frame, 1)
        cv2.imshow('b',frame)
        cv2.waitKey(0)

        # ignore pixels too far away
        #frame[int(len(frame)/1.5):,:] = 0

        lower = np.array([160])#np.array([0,0,150])
        upper = np.array([255])#np.array([255,255,255])
        # Threshold the HSV image to get only blue colors

        #test = cv2.GaussianBlur(rgb, (3, 3), 0)
        mask = cv2.inRange(frame, lower, upper)
        # Bitwise-AND mask and original image
        res = cv2.bitwise_and(frame,frame, mask= mask)

        cv2.imshow('a',res)
        cv2.waitKey(0)

        return res

class StateBare:
    def __init__(self, data, is_terminal):
        self.data = data
        self.is_terminal = is_terminal

def sigmoid(x: float) -> float:
    return 1 / (1 + math.exp(-x))

class StateAssembler:

    FRAME_COUNT = 4

    def __init__(self):
        self.cache = deque(maxlen=self.FRAME_COUNT)

    def assemble_next(self, camera_image: np.ndarray, is_terminal: bool) -> State:
        self.cache.append(camera_image)
        # If cache is still empty, put this image in there multiple times
        while len(self.cache) < self.FRAME_COUNT:
            self.cache.append(camera_image)
        images = np.stack(self.cache, axis=2)
        return State(images, is_terminal)

class EnvironmentInterface:

    REQUEST_READ_SENSORS = 1
    REQUEST_WRITE_ACTION = 2

    def __init__(self, host: str, port: int):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((host, port))
        self.assembler = StateAssembler()

    @staticmethod
    def _calc_reward(disqualified: bool, finished: bool, velocity: float) -> float:
        print(disqualified, finished, velocity)
        if disqualified:
            return -10
        return velocity

    def read_sensors(self, width: int, height: int) -> (State, int):
        request = pack('!bii', self.REQUEST_READ_SENSORS, width, height)
        self.socket.sendall(request)

        # Response size: disqualified, finished, velocity, camera_image
        response_size = width * height + 2 + 4
        response_buffer = bytes()
        while len(response_buffer) < response_size:
            response_buffer += self.socket.recv(response_size - len(response_buffer))

        disqualified, finished, velocity = unpack('!??i', response_buffer[:6])
        # Velocity is encoded as x * 2^64
        velocity /= 0xffffff
        camera_image = np.frombuffer(response_buffer[6:], dtype=np.uint8)
        camera_image = np.reshape(camera_image, (height, width), order='C')

        #print('cam SHAPE', camera_image.shape)

        reward = self._calc_reward(disqualified, finished, velocity)
        ##### PLACE
        camera_image.setflags(write=1)
        state = self.assembler.assemble_next(preprocess_image(camera_image), disqualified or finished)

        #cv2.imwrite('b.png', preprocess_image(camera_image))

        return state, reward

    def write_action(self, action: Action):
        request = pack('!bii', self.REQUEST_WRITE_ACTION, action.vertical, action.horizontal)
        self.socket.sendall(request)

    def _preprocess_image(self, camera_image: np.ndarray) -> np.ndarray:

        #print('camera image shape', camera_image.shape)

        frame = camera_image
        #frame = cv2.flip(frame, 0)
        frame = cv2.flip(frame, 1)

        # ignore pixels too far away
        #frame[int(len(frame)/1.5):,:] = 0

        lower = np.array([160])#np.array([0,0,150])
        upper = np.array([255])#np.array([255,255,255])
        # Threshold the HSV image to get only blue colors

        #test = cv2.GaussianBlur(rgb, (3, 3), 0)
        mask = cv2.inRange(frame, lower, upper)
        # Bitwise-AND mask and original image
        res = cv2.bitwise_and(frame,frame, mask= mask)

        return res

        # print('camera image shape', camera_image.shape)

        # lower_blue = np.array([200])
        # upper_blue = np.array([255])

        # rows,cols = camera_image.shape
        # M = cv2.getRotationMatrix2D((cols/2,rows/2),180,1)
        # camera_image = cv2.warpAffine(camera_image,M,(cols,rows))

        # return camera_image

        # mask = cv2.inRange(camera_image, lower_blue, upper_blue)
        # res = cv2.bitwise_and(camera_image,camera_image, mask= mask)

        # kernel = np.ones((3,3),np.uint8)
        # dilation = cv2.dilate(res,kernel,iterations = 1)
        # dilation = cv2.GaussianBlur(dilation, (3, 3), 5)

        # edges = cv2.Canny(dilation,50,150)

        # lines = cv2.HoughLines(edges,1,np.pi/180,25)

        # sum_rho = 0
        # sum_theta = 0
        # if lines is not None:
        #     for rho,theta in lines[0]:
        #         sum_rho += rho
        #         sum_theta += theta
        # else:
        #     return np.array([0,0])

        # sum_rho /= len(lines[0])
        # sum_theta /= len(lines[0])

        # return np.array([sum_rho, sum_theta])


from back_mobile.response_data_types.product.store_link import StoreLink
from utils.url_provider import URLProvider
from utils.api_utils.test_request import TestRequest

class GetStoreLink(TestRequest):
    def __init__(self, context):
        super().__init__(
            URLProvider().url("back_mobile", "api/v1/mobile/product/store/1"),
            "get",
            data_type=StoreLink,
            headers=context.auth_token()
        )


import pandas as pd
df = pd.read_csv("./Data/example_data.csv")

### Suspected COVID19 ( symptoms)

patients_with_covid19 = df.loc[((df.covid19_has_symptoms=="yes") | (df.covid19_suspected_case == "yes"))]["secret_name"]
print(f"Number of patients with covid : {patients_with_covid19.shape[0]}")

patients_confirmed = df.loc[df.covid19_confirmed_case=="yes"]
print(f"Number of CONFIRMED patients with covid : {patients_confirmed.shape[0]}")

### Type of MS

print("Number of patients per MS Type : ")
print(df.groupby("ms_type").count()["secret_name"])

### Number of different countries

unique_countries = df["covid19_country"].nunique()
print(f"Number of unique countries : {unique_countries}")
print("Number of patients per country : ")
print(df.groupby("covid19_country").count()["secret_name"])

### Counts of patients ( treated - non treated - never treated)
print("Counts of patients : ")
print(df.groupby("current_dmt")["secret_name"].count())

### Subset of treated patients

print("Subset of treated patients : ")
current_dmt = df.loc[df.current_dmt=="yes"].groupby("type_dmt").count().copy()

print(current_dmt.sort_values("current_dmt",ascending=False)["secret_name"])

import matplotlib.pyplot as plt

labels = current_dmt.index
sizes = current_dmt.current_dmt.values
#colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
plt.pie(sizes, shadow=True, autopct='%1.1f%%', startangle=90)
plt.legend( labels, bbox_to_anchor=(0.8, 1.05))
plt.axis('equal')
plt.tight_layout()
plt.title("Repartition of patients currently treated")
plt.savefig('Repartition of patients currently treated.pdf')
plt.show(block=True)

### Subset of previously treated patients

print("Subset of previously treated patients : ")
last_dmt = df.loc[df.current_dmt=="no"].groupby("type_dmt").count().copy() # no is "no but was in the past"
print(last_dmt.sort_values("current_dmt",ascending=False)["secret_name"])

labels = last_dmt.index
sizes = last_dmt.current_dmt.values
#colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral']
plt.pie(sizes, shadow=True, autopct='%1.1f%%', startangle=90)
plt.legend( labels, bbox_to_anchor=(0.8, 1.05))
plt.axis('equal')
plt.tight_layout()
plt.title("Repartition of patients treated in the past but not currently treated")
plt.savefig("Repartition of patients treated in the past but not currently treated.pdf")
plt.show(block=True)


'''
You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n,
representing the number of elements in nums1 and nums2 respectively.
Merge nums1 and nums2 into a single array sorted in non-decreasing order.

Example 1:
Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
The result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.
'''

class Solution:
    def merge(self, nums1, m, nums2, n) -> None:
        i = j = 0
        result = []
        ##--- nums1 and nums2 have only one item in array;
        if m < 1 and n < 1:
            if nums1[0] < nums2[0]:
                result.append(nums1[0])
                result.append(nums2[0])
            else:
                result.append(nums2[0])
                result.append(nums1[0])

        else:
            ## Elements of nums1 and nums2 are equal
            while (i < m and j < n):
                if nums1[i] != 0 and nums1[i] <= nums2[j]:
                    result.append(nums1[i])
                    i += 1
                else:
                    if nums2[j] != 0:
                        result.append(nums2[j])
                    j += 1

            ## Elements of nums1 greater nums2;
            if i < len(nums1):
                while (i < len(nums1)):
                    if nums1[i] != 0:
                        result.append(nums1[i])
                    i += 1

            ## Elements of nums2 greater nums1;
            if j < len(nums2):
                while (j < len(nums2)):
                    if nums2[j] != 0:
                        result.append(nums2[j])
                    j += 1

            ## Update Reference nums1;
            nums1.clear()
            nums1.extend(result)

def main():
    m = 3
    n = 3
    nums1 = [1, 2, 3, 0, 0, 0]
    nums2 = [2, 5, 6]
    obj = Solution()
    obj.merge(nums1, m, nums2, n)
    for x in nums1:
        print(x, end=" ")

if __name__ == "__main__":
    main()


import json
from stix_shifter_utils.modules.base.stix_transmission.base_sync_connector import BaseSyncConnector
from .api_client import APIClient
from stix_shifter_utils.utils.error_response import ErrorResponder
import pandas as pd
from stix_shifter_utils.utils import logger
from azure.monitor.query import LogsQueryStatus
from azure.core.exceptions import ODataV4Format
from datetime import datetime, timedelta
import re

class Connector(BaseSyncConnector):

    def __init__(self, connection, configuration):
        """Initialization.
        :param connection: dict, connection dict
        :param configuration: dict,config dict"""
        self.logger = logger.set_logger(__name__)
        self.connector = __name__.split('.')[1]
        self.api_client = APIClient(connection, configuration)

    async def ping_connection(self):
        """Ping the endpoint."""
        return_obj = dict()
        response = await self.api_client.ping_box()
        response_code = response.code
        try:
            response_dict = json.loads(response.read())
        except:
            response_dict = json.loads(response.bytes)

        if 200 <= response_code < 300:
            return_obj['success'] = True
        elif response_code == 404:
            error_dict = {"error": response_dict['error']['message'], "code": response_dict['error']['code']}
            ErrorResponder.fill_error(return_obj, error_dict, ['error', 'message'], connector=self.connector)
        else:
            ErrorResponder.fill_error(return_obj, response_dict, ['error', 'message'], connector=self.connector)

        return return_obj

    async def delete_query_connection(self, search_id):
        """"delete_query_connection response
        :param search_id: str, search_id"""
        return {"success": True, "search_id": search_id}

    async def create_results_connection(self, query, offset, length):
        """"built the response object
        :param query: str, search_id
        :param offset: int,offset value
        :param length: int,length value"""
        length = int(length)
        offset = int(offset)
        return_obj = dict()
        query = """{query} | serialize rn = row_number() | where rn >= {offset} | limit {len}""".format(query=query,
                                                                                offset=offset,
                                                                                len=length)
        matches = re.findall(r'(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+?Z)', query)
        if matches:
            stop_time = datetime.strptime(matches[1].replace('Z', ""), "%Y-%m-%dT%H:%M:%S.%f")
            start_time = datetime.strptime(matches[0].replace('Z', ""), "%Y-%m-%dT%H:%M:%S.%f")
        else:
            stop_time = datetime.utcnow()
            start_time = stop_time - timedelta(hours=24)

        response = await self.api_client.run_search(query, start_time, stop_time)

        if response["success"]:
            if response["response"].status == LogsQueryStatus.PARTIAL:
                error = response["response"].partial_error
                data = response["response"].partial_data
                self.logger.warn(error.message)
            elif response["response"].status == LogsQueryStatus.SUCCESS:
                data = response["response"].tables

            for table in data:
                df = pd.DataFrame(data=table.rows, columns=table.columns)
                return_obj = {"success": True, "data": df.astype(str).to_dict(orient='records')}
                return_obj['data'] = return_obj['data']

        else:
            if isinstance(response["error"], ODataV4Format):
                response_dict = {"error": response["error"], "code": response["error"].code}
            else:
                response_dict = {"error": response["error"]}
            ErrorResponder.fill_error(return_obj, response_dict, ['error', 'message'], connector=self.connector)
        return return_obj


import logging
import os
import sys

from argparse import ArgumentParser
from pathlib import Path
from typing import Callable

from google.cloud import firestore

from external.api import ExternalAPI
from external.dictionary.factory import KnowledgeBaseFactory
from external.tg import TelegramFacade

from ltquiz.application import BotApplication
from external.storage import StorageFacade
from utils import fs

logger = logging.getLogger('lt-quiz-bot')

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

def env_var(env, default=None, prefix='LT_QUIZ_'):
    return os.environ.get(f'{prefix}{env}', default)

def get_args():
    parser = ArgumentParser()
    parser.add_argument("--gcp-project-id", default=env_var('GCP_PROJECT_ID', 'test'), type=str)
    parser.add_argument("--environment-name", default=env_var('ENVIRONMENT_NAME', 'test'), type=str)
    parser.add_argument("--version", default=env_var('VERSION', 'local'), type=str)
    parser.add_argument("--telegram-token", default=env_var('TELEGRAM_TOKEN', None))

    subparsers = parser.add_subparsers(dest='command')

    parser_polling = subparsers.add_parser('polling', help='Run Telegram MessageHandler')
    parser_polling.set_defaults(command_func=cmd_polling)

    parser_webhook = subparsers.add_parser('webhook', help='Run Telegram MessageHandler')
    parser_webhook.add_argument("--secret-token", default=env_var('SECRET_TOKEN', None), type=str)
    parser_webhook.add_argument("--url", default=env_var('URL', None), type=str)
    parser_webhook.add_argument("--port", default=int(env_var('PORT', 8080)), type=int)
    parser_webhook.set_defaults(command_func=cmd_webhook)

    parser_gen = subparsers.add_parser('generate', help='Generate dictionary')
    parser_gen.add_argument("--data-dir", default=env_var('DATA_DIR', fs.data_dir()), type=Path)
    parser_gen.set_defaults(command_func=cmd_generate)

    parser_migrate = subparsers.add_parser('migrate', help='Migrate App')
    parser_migrate.set_defaults(command_func=cmd_migrate)

    return parser.parse_args()

def create_bot(gcp_project_id: str, environment_name: str, telegram_token: str, version: str):
    external = ExternalAPI(
        db=StorageFacade(firestore.Client(project=gcp_project_id), namespace=environment_name),
        tg=TelegramFacade(telegram_token),
    )
    knowledge = KnowledgeBaseFactory.create_knowledge_base()
    return BotApplication(external, knowledge, version)

def cmd_polling(bot_creator: Callable[[], BotApplication]):
    bot_creator().run_polling()

def cmd_webhook(bot_creator: Callable[[], BotApplication], port: int, secret_token: str, url: str):
    bot_creator().run_webhook(port, secret_token, url)

def cmd_generate(bot_creator: Callable[[], BotApplication], data_dir):
    KnowledgeBaseFactory.generate_dicitionary_from_google_sheet(data_dir)

def cmd_migrate(bot_creator: Callable[[], BotApplication]):
    bot_creator().migrate()

def main(command_func,
         command: str,
         gcp_project_id: str,
         environment_name: str,
         telegram_token: str,
         version: str,
         **kwargs):
    logger.info(f'Start bot with command {command}')

    def bot_creator() -> BotApplication:
        return create_bot(gcp_project_id, environment_name, telegram_token, version)

    command_func(bot_creator, **kwargs)

if __name__ == '__main__':
    args = get_args()
    logger.info(args)

    main(**vars(args))


# CH6 Exercise 6-6: Polling
#
# August 7, 2019
#
# Given languages.py
# Make list of people who should take favorite languages poll.  Include some names in the dictionary
# and some that are not

favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python',
    }

new_list = ['curt', 'john', 'jen', 'danesh', 'phil', 'jeff']

# loop through new_list and check if they took the poll.  If their name exists in favorite_languages,
# thank them for taking the poll.  If not, ask them to take the poll.
for name in new_list:
    if name in favorite_languages.keys():
        print("Thanks for taking the poll, " + name.title() + "!\n")
    else:
        print(name.title() + ", please take the poll.\n")


# Part 1

total = 0

def solve(line,total):
	lista = line.split('|')
	digits = lista[1].split()
	print(digits)
	for digit in digits:
		if len(digit) == 7: # digit = 8
			total += 1
		elif len(digit) == 3: # digit = 7
			total += 1
		elif len(digit) == 4: # digit = 4
			total += 1
		elif len(digit) == 2: # digit = 1
			total += 1
	return total

file = open("day8.txt",'r')

lines = file.readlines()

for line in lines:
	total = solve(line[:-1], total)

print(total)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Oct  6 17:50:38 2019

@author: emmanuel
"""
#reduce(función, iterable) aplica dos argumentos a los elementos en el
#iterable, de izquierda a derecha de forma acumulativa

from functools import reduce  # Esto es necesario si se está usando Python 3

lista = [2,4,6,8]
a = reduce(lambda x,y: x-y, lista)
print(a)


#!/usr/local/anaconda2/bin/python

import argparse
import numpy as np
import sys

# ---------------------------
#     Parse
# ---------------------------

parser = argparse.ArgumentParser()

parser.add_argument("-i", dest="inputfile", required=True,
                    help="Input file in PDB format with CONECT entries", metavar="FILE")
parser.add_argument("-o", dest="outputfile", required=True,
                    help="RTP file", metavar="FILE")

args = parser.parse_args()
Input  = args.inputfile
Output = args.outputfile

# ---------------------------
#     Read Data
# ---------------------------

InputFile  = open(Input)
OutputFile = open(Output,'w')

AtomList   = []
ConectList = []
for Line in InputFile:
    if (Line[0:4] == 'ATOM') or (Line[0:6] == 'HETATM'):
        AtomList.append( [Line.split()[i] for i in [2,3,5,6,7]] )
    if Line[0:6] == 'CONECT':
        ConectList.append( map(int,Line.split()[1:]) )

NAtoms  = len(AtomList)

# --- Check if is a single residue
for i in range(NAtoms):
    if AtomList[i][1] != AtomList[0][1]:
        sys.exit("Error. There should be only one residue")

# --- Check if if there is at least one CONECT
if len(ConectList) == 0:
    sys.exit("Error. There must be CONNECT entries")

# --- Check if all atoms are conected

for i in range(len(AtomList)):
    Conected=False
    for Entry in ConectList:
        for j in range(len(Entry)):
            if i == Entry[j] -1:
                Conected = True
    if Conected == False:
        sys.stdout.write("Warning. Atom "+AtomList[i][0]+" is not conected to other atoms.\n")
        sys.stdout.write("         If this is wrong, add a CONECT entry in "+Input+".\n ")

# ---------------------------
#     Bonds
# ---------------------------

def distance (a,b):
    a = np.array( a[2:5],dtype=float )
    b = np.array( b[2:5],dtype=float )
    Norm = np.linalg.norm(a-b)/10.
    return "%5.3f"%Norm

BondList = []
for Entry in ConectList:
    for i in range(1,len(Entry)):
        A1 = AtomList[Entry[0] -1]
        A2 = AtomList[Entry[i] -1]

        # Eliminates repeated
        Repeated = False
        for Bond in BondList:
            if (A1[0] == Bond[0]) and (A2[0] == Bond[1]):
                    Repeated = True
            if (A1[0] == Bond[1]) and (A2[0] == Bond[0]):
                    Repeated = True
        if not Repeated:
            BondList.append( [ A1[0], A2[0], distance(A1,A2), 627.6 ])
NBonds=len(BondList)

# ---------------------------
#     Angles
# ---------------------------

def findAtom(AtomName):
    for Atom in AtomList:
        if Atom[0] == AtomName:
            break
    return Atom

def angle(a,b,c):
    a   = np.array( a[2:5],dtype=float )
    b   = np.array( b[2:5],dtype=float )
    c   = np.array( c[2:5],dtype=float )
    ba  = a-b
    bc  = c-b
    Nba = np.linalg.norm(ba)
    Nbc = np.linalg.norm(bc)
    Angle = np.arccos( ba.dot(bc)/(Nba*Nbc) ) *180 /np.pi
    return  "%5.3f"%Angle

# --- Loop over atoms
# Angles are defined through a the central atom

AngleList = []
for Atom in AtomList:

    # --- Creates Bonded List.
    # From all the Bond list keeps the ones bonded with this specific atom

    BondedList=[]
    for Bond in BondList:
        if (Atom[0] == Bond[0]):
            BondedList.append( findAtom(Bond[1]) )
        if (Atom[0] == Bond[1]):
            BondedList.append( findAtom(Bond[0]) )

    # --- Creates Angle List
    # Iterates over the Bonded list without considering repeated angles

    for A1 in BondedList:
        for A2 in BondedList:

            if A1[0] == A2[0]:
                continue

            Repeated=False
            for Angle in AngleList:
                if (A1[0] == Angle[0]) and (Atom[0] == Angle[1]) and (A2[0] == Angle[2]):
                        Repeated = True
                if (A1[0] == Angle[2]) and (Atom[0] == Angle[1]) and (A2[0] == Angle[0]):
                        Repeated = True

            if not Repeated:
                AngleList.append([ A1[0], Atom[0], A2[0], angle(A1,Atom,A2), 627.6])

NAngles = len(AngleList)

# ---------------------------
#     Dihedrals
# ---------------------------

DihedList = []
for Bond in BondList:

    # --- Creates Bonded List for each atom in bond
    # From all the Bond list keeps the ones bonded with this specific atom

    Atom = findAtom(Bond[0])
    BondedList1=[]
    for xBond in BondList:
        if (Atom[0] == xBond[0]):
            BondedList1.append( findAtom(xBond[1]) )
        if (Atom[0] == xBond[1]):
            BondedList1.append( findAtom(xBond[0]) )

    Atom = findAtom(Bond[1])
    BondedList2=[]
    for xBond in BondList:
        if (Atom[0] == xBond[0]):
            BondedList2.append( findAtom(xBond[1]) )
        if (Atom[0] == xBond[1]):
            BondedList2.append( findAtom(xBond[0]) )

    for A1 in BondedList1:
        for A2 in BondedList2:

            if A1[0] == A2[0]:
                continue
            if A1[0] == Bond[0] or A1[0] == Bond[1]:
                continue
            if A2[0] == Bond[0] or A2[0] == Bond[1]:
                continue

            Repeated=False
            for Dihed in DihedList:
                if (A1[0] == Angle[0]) and (Atom[0] == Angle[1]) and (A2[0] == Angle[2]):
                        Repeated = True
                if (A1[0] == Angle[2]) and (Atom[0] == Angle[1]) and (A2[0] == Angle[0]):
                        Repeated = True

            if not Repeated:
                DihedList.append([ A1[0], Bond[0], Bond[1], A2[0], 0, 0, 0])

NDiheds = len(DihedList)

# ---------------------------
#     OutputFile
# ---------------------------

OutputFile.write('\n['+AtomList[0][1]+' ]\n')
OutputFile.write('\n [ atoms ]\n')
for i in range(NAtoms):
    OutputFile.write('      '+'%-5s'%AtomList[i][0]+'   XXX   0.0    '+str(i+1)+'\n')

OutputFile.write('\n [ bonds ]\n')
for i in range(NBonds):
    OutputFile.write('      '+'   '.join(map(str,BondList[i][0:4]))+'\n')

OutputFile.write('\n [ angles ]\n')
for i in range(NAngles):
    OutputFile.write('      '+'   '.join(map(str,AngleList[i][0:5]))+'\n')

OutputFile.write('\n [ dihedrals ]\n')
for i in range(NDiheds):
    OutputFile.write('      '+'   '.join(map(str,DihedList[i][0:7]))+'\n')

OutputFile.write('\n [ impropers ]\n')


#作者：zengziwei
#创建时间：2021/8/13 10:56
#文件名：requests_json.py
import requests
import json
class request_port():
    def __init__(self,url,method,header,data):
        self.url = url
        self.method = method
        self.header = header
        self.data = data
    def request_post(self):
        #判断
        if self.method == "post":
            response = requests.post(url=self.url, headers=self.header, data=json.dumps(self.data))
        else:
            response = requests.get(url=self.url, headers=self.header)
        return  response


import numpy as np
import matplotlib.pylab as plt
from glob import glob
from datetime import datetime

#############################################################
################## Text files ###############################
#############################################################

def extract_area(name):
    """Use helper functions to extract sample,time and area of a txt file.
       Handle txt file of different lengths."""

    li_time = []
    li_H2 = []
    li_CO2 = []
    li_CO = []
    li_CH4 = []

    for fi in name:
        with open(fi) as f:
            lin = f.read().splitlines()
        if len(lin)-1 == 1:
            """Get time string 1st line. Appends to li_time"""
            li_time.append(lin[0].replace('"','').split(',')[1].split(' ')[1])
        elif len(lin)-1 == 2:
            """Get time string 1st line. Appends to li_time"""
            li_time.append(lin[0].replace('"','').split(',')[1].split(' ')[1])
            """Get H2 area 2nd line. Appends to li_H2"""
            li_H2.append(float(lin[1].replace('"','').split(',')[1]))
        elif len(lin)-1 == 3:
            """Get time string 1st line. Appends to li_time"""
            li_time.append(lin[0].replace('"','').split(',')[1].split(' ')[1])
            """Get H2 area 2nd line. Appends to li_H2"""
            li_H2.append(float(lin[1].replace('"','').split(',')[1]))
            """Get CO2 area 3rd line. Appends to li_CO2"""
            li_CO2.append(float(lin[2].replace('"','').split(',')[1]))
        elif len(lin)-1 == 4:
            """Get time string 1st line. Appends to li_time"""
            li_time.append(lin[0].replace('"','').split(',')[1].split(' ')[1])
            """Get H2 area 2nd line. Appends to li_H2"""
            li_H2.append(float(lin[1].replace('"','').split(',')[1]))
            """Get CO2 area 3rd line. Appends to li_CO2"""
            li_CO2.append(float(lin[2].replace('"','').split(',')[1]))
            """Get CO area 4th line. Appends to li_CO"""
            li_CO.append(float(lin[3].replace('"','').split(',')[1]))
        elif len(lin)-1 == 5:
            """Get time string 1st line. Appends to li_time"""
            li_time.append(lin[0].replace('"','').split(',')[1].split(' ')[1])
            """Get H2 area 2nd line. Appends to li_H2"""
            li_H2.append(float(lin[1].replace('"','').split(',')[1]))
            """Get CO2 area 3rd line. Appends to li_CO2"""
            li_CO2.append(float(lin[2].replace('"','').split(',')[1]))
            """Get CO area 4th line. Appends to li_CO"""
            li_CO.append(float(lin[3].replace('"','').split(',')[1]))
            """Get CH4 area 5th line. Appends to li_CH4"""
            li_CH4.append(float(lin[4].replace('"','').split(',')[1]))
    return li_time,li_H2, li_CO, li_CO2, li_CH4

def make_datetime(lst):
    """Used as a key in lambda function"""
    date_str = lst.split('_')[1]
    return datetime.strptime(date_str, '%H-%M-%S')

def conv_inmin(lst):
    """Convert H:M:S format in minutes for a list of files. Returns a numpy array with time"""
    FMT = '%H:%M:%S'
    li_x = [(datetime.strptime(i, FMT) - datetime.strptime(lst[0], FMT)).total_seconds()/60.0 for i in lst]
    return np.array(li_x)

def ev_mis(np1, np2):
    """Even the mismatch between two numpy arrays. The second should be always time"""
    if len(np1) < len(np2):
         diff = np.zeros(len(np2)-len(np1))
         np_f = np.concatenate((diff,np1))
         return np_f
    else:
        return np1

def ref(np1, strg):
    """Takes numpy array (np1) and a string (strg) and zip them in a list
       of tuples of length = len(np1)"""
    lst = zip([strg]*len(np1),np1)
    return lst

if __name__ == "__main__":

    # Dump files into a list and sort them in time order
    file_txt = glob('*TrendData.txt')
    sorted_txt = sorted(file_txt, key=make_datetime)

    # Fill empy lists with the content of SORTED file's name
    li_time,li_H2,li_CO,li_CO2,li_CH4 = extract_area(sorted_txt)

    # Make up numpy arrays
    np_time = conv_inmin(li_time)
    np_H2 = np.array(li_H2)
    np_CO2 = np.array(li_CO2)
    np_CO = np.array(li_CO)
    np_CH4 = np.array(li_CH4)

    # Even the mismatch
    H2_f = ev_mis(np_H2, np_time)
    CO2_f = ev_mis(np_CO2, np_time)
    CO_f = ev_mis(np_CO, np_time)
    CH4_f = ev_mis(np_CH4, np_time)

    # Dict comprehension
    ltp1 = ref(H2_f, 'H2')
    ltp2 = ref(CO2_f, 'CO2')
    ltp3 = ref(CO_f, 'CO')
    ltp4 = ref(CH4_f, 'CH4')
    d = {v:(ltp1[i],ltp2[i],ltp3[i],ltp4[i]) for i,v in enumerate(np_time.tolist())}

#plt.figure(1)
#plt.title('Normalized Area')
#plt.plot(np_time,np_H2/max(np_H2), marker='o',label='H2')
#plt.plot(np_time,CO2_f/max(CO2_f), marker='o',label='CO2')
#plt.plot(np_time,CO_f/max(CO_f), marker='o',label='CO')
#plt.plot(np_time,CH4_f/max(CH4_f), marker='o',label='CH4')
#plt.grid()
#plt.xlabel('Time / minutes')
#plt.ylabel('Area')
#plt.legend(loc='best')


from typing import Any, Dict, List

import jsons  # type: ignore
from trakt.core.exceptions import TraktResponseError

TYPE_TYPE = int.__class__
ITERABLES = {list, dict}

GLOBAL_NAME_MAPPING = {"costume & make-up": "costume_make_up"}

def parse_tree(data: Any, tree_structure: Any) -> Any:
    try:
        data = _apply_name_mapping(data)
        data = _substitute_none_val(data)
        return _parse_tree(data, tree_structure)
    except Exception as e:
        raise TraktResponseError(errors=[e])

def _apply_name_mapping(data: Any):
    if isinstance(data, list):
        data = [_apply_name_mapping(v) for v in data]
    if isinstance(data, dict):
        data = {
            GLOBAL_NAME_MAPPING.get(k, k): _apply_name_mapping(v)
            for k, v in data.items()
        }

    return data

def _substitute_none_val(data: Any):
    """Trakt represents null-value as {}. Change it to None."""
    if data == {}:
        return None

    if isinstance(data, list):
        data = [_substitute_none_val(v) for v in data]
    if isinstance(data, dict):
        data = {k: _substitute_none_val(v) for k, v in data.items()}

    return data

def _parse_tree(data: Any, tree_structure: Any) -> Any:
    level_type = tree_structure.__class__

    if level_type not in ITERABLES:
        return jsons.load(data, tree_structure)

    if level_type == list:
        return _parse_list(data, tree_structure)

    if level_type == dict:
        return _parse_dict(data, tree_structure)

def _is_arbitrary_value(x: Any) -> bool:
    return x.__class__ not in (ITERABLES | {type})

def _parse_list(data: List[Any], tree_structure: List[Any]) -> List[Any]:
    if not tree_structure:
        return tree_structure

    single_item_type = tree_structure[0]
    if single_item_type is Any:
        return data
    if data is None or not data:
        return []

    return [_parse_tree(e, single_item_type) for e in data]

def _parse_dict(data: Dict[Any, Any], tree_structure: Dict[Any, Any]) -> Dict[Any, Any]:
    if not tree_structure:
        return tree_structure

    wildcards = {  # eg {str: str} / {str: Any}
        k: v for k, v in tree_structure.items() if isinstance(k, type)
    }

    defaults = {  # eg {value: value}
        k: v
        for k, v in tree_structure.items()
        if (k not in wildcards) and _is_arbitrary_value(v)
    }

    result = __parse_dict_items(data, tree_structure, wildcards)

    # set defaults if any keys are missing
    for k, v in defaults.items():
        if k not in result:
            result[k] = v

    return result

def __parse_dict_items(
    data: Dict[Any, Any], tree_structure: Dict[Any, Any], wildcards: Dict[type, Any]
):
    result = {}
    for k, v in data.items():
        if k in tree_structure:
            # v may be a default value -> use its type as subtree type
            subtree = tree_structure[k]
            subtree = subtree.__class__ if _is_arbitrary_value(subtree) else subtree

            result[k] = _parse_tree(v, subtree)
        elif k.__class__ in wildcards:
            wildcard = wildcards[k.__class__]
            result[k] = v if wildcard is Any else _parse_tree(v, wildcard)

    return result


import csv
import sys, traceback
from base import base
import logging
import logging.handlers

class dataloader:
  #
  #Initializer
  #
  def __init__(self):
    self.baseinstance = base("user1", "test1")
    self.SUCCESS = 0
    self.FAILURE = 1
    LOG_FILENAME = "/home/akhilesh/sandBox/tripIt/logs/dbloader.log"
    self.dblogger = logging.getLogger('tripit.dbloader')
    self.dblogger.setLevel(logging.DEBUG)
    logformat = logging.Formatter('%(asctime)s %(filename)s %(funcName)s %(lineno)d %(levelname)s %(message)s')
    dbhandler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=15000000, backupCount=5)
    dbhandler.setFormatter(logformat)
    self.dblogger.addHandler(dbhandler)
    self.dblogger.handlers[0].doRollover()

  #Loads data from a csv file
  def csvloader(self, filename, tablename, dbop):
    #debug
    print ("DEBUG: Running csvloader...")
    self.dblogger.info("Running csvloader()...")
    CSV_FILENAME = filename
    insertcount  = 0
    updatecount  = 0
    if (open(CSV_FILENAME)):
      with open(CSV_FILENAME) as csvfile:
        keyFileReader = csv.DictReader(csvfile, restval="noMetaKey")
        if dbop == "insert":
          if tablename == "airportcities":
            for row in keyFileReader:
              insertdict = {}
              #readline
              if row["airportcity"] and row["country"] and row["latitude"] and row["longitude"]:
                insertdict['airportcity'] = row["airportcity"]
                insertdict['country'] = row["country"]
                insertdict['latitude'] = row["latitude"]
                insertdict['longitude'] = row["longitude"]
              try:
                self.dblogger.debug("insertdict {0}".format(insertdict))
                self.baseinstance.dbinit("apimetadata")
                self.baseinstance.dbinsert(tablename, insertdict)
                self.baseinstance.dbclose()
                self.dblogger.debug("Database insert complete.")
                insertcount += 1
              except:
                self.dblogger.error("Database operation 'INSERT' failed.")
                self.baseinstance.dbinit("apimetadata")
                self.baseinstance.dbrollback()
                self.baseinstance.dbclose()
                return self.FAILURE
                sys.exit(1)
              finally:
                if not row or (insertcount == 1000):
                  if insertcount == 1000:
                    insertcount = 0
                  try:
                    self.baseinstance.dbinit("apimetadata")
                    self.baseinstance.dbcommit()
                    self.baseinstance.dbclose()
                    self.dblogger.debug("Database commit complete.")
                  except:
                    self.dblogger.error("Database commit failed due to unknown reasons.")
                    return self.FAILURE
                    sys.exit(1)
          if tablename == "categorydna":
            for row in keyFileReader:
              insertdict = {}
              #readline
              if row["category"] and row["chillpoint"] and row["partypoint"]:
                insertdict['category'] = row["category"]
                insertdict['chillout'] = row["chillpoint"]
                insertdict['party'] = row["partypoint"]
              try:
                self.dblogger.debug("insertdict {0}".format(insertdict))
                self.baseinstance.dbinit("algometadata")
                self.baseinstance.dbinsert(tablename, insertdict)
                self.baseinstance.dbclose()
                self.dblogger.debug("Database insert complete.")
                insertcount += 1
              except:
                self.dblogger.error("Database operation 'INSERT' failed.")
                self.baseinstance.dbinit("algometadata")
                self.baseinstance.dbrollback()
                self.baseinstance.dbclose()
                return self.FAILURE
                sys.exit(1)
              finally:
                if not row or (insertcount == 1000):
                  if insertcount == 1000:
                    insertcount = 0
                  try:
                    self.baseinstance.dbinit("algometadata")
                    self.baseinstance.dbcommit()
                    self.baseinstance.dbclose()
                    self.dblogger.debug("Database commit complete.")
                  except:
                    self.dblogger.error("Database commit failed due to unknown reasons.")
                    return self.FAILURE
                    sys.exit(1)
        elif dbop == "update":
          for row in keyFileReader:
            updatedict = {}
            if row["weekendtrip"] and row["explorecountry"] and row["skiing"] and row["familyvacation"]:
              updatedict['weekendtrip'] = row["weekendtrip"]
              updatedict['explorecountry'] = row["explorecountry"]
              updatedict['skiing'] = row["skiing"]
              updatedict['familyvacation'] = row["familyvacation"]
            matchrowdict = {}
            if row["category"]:
              matchrowdict['category'] = row["category"]
            try:
              self.dblogger.debug("updatedict {0}".format(updatedict))
              self.dblogger.debug("matchrowdict {0}".format(matchrowdict))
              self.baseinstance.dbinit("algometadata")
              self.baseinstance.dbupdate(tablename, updatedict, matchrowdict)
              self.baseinstance.dbclose()
              self.dblogger.debug("Database update complete.")
              updatecount += 1
            except:
              self.dblogger.error("Database operation 'UPDATE' failed.")
              self.baseinstance.dbinit("algometadata")
              self.baseinstance.dbrollback()
              self.baseinstance.dbclose()
              return self.FAILURE
              sys.exit(1)
            finally:
              if not row or (updatecount == 1000):
                if updatecount == 1000:
                  updatecount = 0
                try:
                  self.baseinstance.dbinit("algometadata")
                  self.baseinstance.dbcommit()
                  self.baseinstance.dbclose()
                  self.dblogger.debug("Database commit complete.")
                except:
                  self.dblogger.error("Database commit failed due to unknown reasons.")
                  return self.FAILURE
                  sys.exit(1)
    else:
      self.dblogger.error("Unable to open data file for processing due to unkown errors.")
      self.dblogger.error("Errormessage - {0}".format(sys.exc_info()))
    self.dblogger.info("Data has been loaded to the database successfully.")
    return self.SUCCESS

#testing/debug
instance = dataloader()
#output = instance.csvloader("/home/akhilesh/TripppIn/data/airports.csv", "airportcities")
output = instance.csvloader("/home/akhilesh/TripppIn/data/categories.csv", "categorydna", "update")
if output is not None and output != 1:
  print ("Data has been loaded to the database successfully.")
else:
  print ("Data loading to database failed.")


import time

try:
    from typing import Tuple
except ImportError:
    pass

try:
    ticks_diff = time.ticks_diff
    ticks_ms = time.ticks_ms
except AttributeError:
    def ticks_ms():
        return time.time_ns() / 1000000

    def ticks_diff(t1, t2):
        # TODO: Probably need to handle wrap around here.
        return t1 - t2

def _is_leap_year(year: int) -> bool:
    if year % 100 == 0:
        return year % 400 == 0
    return year % 4 == 0

def _days_in_month(year: int, month: int) -> int:
    if month in (4, 6, 9, 11):
        return 30
    if month == 2:
        return 29 if _is_leap_year(year) else 28
    return 31

class Date:
    """Represents a specific date."""
    def __init__(self, year: int, month: int, day: int):
        assert year >= 1970, "Dates before 1970 are not supported."
        assert month >= 1 and month <= 12, f"Month {month} out of range."
        assert day >= 1 and day <= _days_in_month(year, month), \
            f"Day {day} out of range for {year} {month}."
        self.__days_since_1970 = (year - 1970) * 365
        for i in range(1970, year):
            if _is_leap_year(i):
                self.__days_since_1970 += 1
        for m in range(1, month):
            self.__days_since_1970 += _days_in_month(year, m)
        self.__days_since_1970 += day

    def __year_month_day(self) -> Tuple[int, int, int]:
        y, m, d = 1970, 1, self.__days_since_1970
        while d > (366 if _is_leap_year(y) else 365):
            d -= (366 if _is_leap_year(y) else 365)
            y += 1
        while d > _days_in_month(y, m):
            d -= _days_in_month(y, m)
            m += 1
        return y, m, d

    def weekday(self) -> int:
        """Returns the day of the week. 0 is Monday, 6 is Sunday."""
        return ((self.__days_since_1970 % 7) + 2) % 7

    def __iadd__(self, days: int) -> "Date":
        self.__days_since_1970 += days
        return self

    def __isub__(self, days: int) -> "Date":
        self.__days_since_1970 -= days
        return self

    @property
    def year(self) -> int:
        return self.__year_month_day()[0]

    @property
    def month(self) -> int:
        return self.__year_month_day()[1]

    @property
    def day(self) -> int:
        return self.__year_month_day()[2]

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Date):
            return False
        return self.__days_since_1970 == other.__days_since_1970

class DateTime:
    """Represents a specific date and a time."""
    BASE: int = 0

    def __init__(self,
                 year: int,
                 month: int,
                 day: int,
                 weekday: int = 0,
                 hour: int = 0,
                 minute: int = 0,
                 second: int = 0,
                 microsecond: int = 0) -> None:
        self.__date = Date(year, month, day)
        self.hour = hour
        self.minute = minute
        self.second = second

    def weekday(self) -> int:
        """Returns the day of the week. 0 is Monday, 6 is Sunday."""
        return self.__date.weekday()

    @property
    def year(self) -> int:
        return self.__date.year

    @property
    def month(self) -> int:
        return self.__date.month

    @property
    def day(self) -> int:
        return self.__date.day

    def __add__(self, other: "TimeDelta") -> "DateTime":
        dt = DateTime(self.year,
                      self.month,
                      self.day,
                      hour=self.hour,
                      minute=self.minute,
                      second=self.second)
        dt.second += other.seconds
        while dt.second > 60:
            dt.minute += 1
            dt.second -= 60
        while dt.minute > 60:
            dt.hour += 1
            dt.minute -= 60
        dt.hour += other.hours
        while dt.hour > 24:
            dt.__date += 1
            dt.hour -= 24
        dt.__date += other.days
        return dt

    def __iadd__(self, other: "TimeDelta") -> "DateTime":
        self.second += other.seconds
        while self.second > 60:
            self.minute += 1
            self.second -= 60
        while self.minute > 60:
            self.hour += 1
            self.minute -= 60
        self.hour += other.hours
        while self.hour > 24:
            self.__date += 1
            self.hour -= 24
        self.__date += other.days
        return self

    def __sub__(self, other: "TimeDelta") -> "DateTime":
        dt = DateTime(self.year,
                      self.month,
                      self.day,
                      hour=self.hour,
                      minute=self.minute,
                      second=self.second)
        dt.second -= other.seconds
        while dt.second < 0:
            dt.minute -= 1
            dt.second += 60
        while dt.minute < 0:
            dt.hour -= 1
            dt.minute += 60
        dt.hour -= other.hours
        while dt.hour < 0:
            dt.__date -= 1
            dt.hour += 24
        dt.__date -= other.days
        return dt

    def __isub__(self, other: "TimeDelta") -> "DateTime":
        self.second -= other.seconds
        while self.second < 0:
            self.minute -= 1
            self.second += 60
        while self.minute < 0:
            self.hour -= 1
            self.minute += 60
        self.hour -= other.hours
        while self.hour < 24:
            self.__date -= 1
            self.hour += 24
        self.__date -= other.days
        return self

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, DateTime):
            return False
        return self.__date == other.__date \
            and self.hour == other.hour \
            and self.minute == other.minute \
            and self.second == other.second

    def __str__(self):
        return f"{self.year}-{self.month:02n}-{self.day:02n} " \
             + f"{self.hour:02n}:{self.minute:02n}:{self.second:02n}"

    def __repr__(self):
        return f"{self.year}-{self.month:02n}-{self.day:02n} " \
             + f"{self.hour:02n}:{self.minute:02n}:{self.second:02n}"

class TimeDelta:
    """Represents a difference between two times."""
    def __init__(self,
                 days: int = 0,
                 hours: int = 0,
                 seconds: int = 0) -> None:
        self.days = days
        self.hours = hours
        self.seconds = seconds


from django.db import models
from imagekit.models import ProcessedImageField, ImageSpecField
from imagekit.processors import ResizeToFit, ResizeToFill
from django.conf import settings
from django.template.defaultfilters import slugify
import datetime

# Create your models here.
class ProjectImage(models.Model):
    name = models.CharField(max_length=500, blank=True, null=True)
    image = ProcessedImageField(upload_to='projectimages/', processors=[
                                ResizeToFit(2000, 2000, False)], format='JPEG',
                                options={'quality': 85})
    thumbnail = ImageSpecField(source='image', processors=[
        ResizeToFill(700, 700, False)], format='JPEG',
        options={'quality': 100})
    project = models.ForeignKey(
        'Project', on_delete=models.CASCADE, blank=True, null=True)
    creation_date = models.DateTimeField(auto_now_add=True, auto_now=False)

    def __str__(self):
        if not self.project:
            return str(self.pk)
        else:
            return "Bilde til prosjekt nummer: %d" % self.project.pk

    class Meta:
        verbose_name = "Prosjektbilde"
        verbose_name_plural = "Prosjektbilder"
        ordering = ('creation_date',)

class Project(models.Model):

    YEAR_CHOICES = [
        ('1. klasse', '1. klasse'),
        ('2. klasse', '2. klasse'),
        ('3. klasse', '3. klasse'),
        ('4. klasse', '4. klasse'),
        ('5. klasse', '5. klasse'),
    ]

    description = models.TextField(blank=True, null=True)

    creator = models.CharField(max_length=300, blank=True, null=True)
    class_year = models.CharField(
        'Klasse', choices=YEAR_CHOICES, max_length=10, blank=True, null=True)
    course = models.CharField(max_length=150, blank=True, null=True)

    creation_date = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)

    def __str__(self):
        if self.creator and self.course:
            return "%s" % (self.creator)
        else:
            return str(self.pk)

    class Meta:
        verbose_name = "Prosjekt"
        verbose_name_plural = "Prosjekter"
        ordering = ('-creation_date',)


import pathlib
import argparse
from . import parser

arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('path', type=pathlib.Path)

path = arg_parser.parse_args().path
with path.open() as f:
    code = f.read()
    p = parser.Parser(code)
    doc = p.document()
    print(doc.render())


__author__ = 'dileep'
# Naive string matching
def naive_str(text, pattern) -> list:
	"""Naive string matching
	:param text: Str
	:param pattern: Str
	returns indices of matches"""
	pat_len = len(pattern)
	indices = []
	for ind, val1 in enumerate(text):
		if text[ind:ind + pat_len] == pattern:
			indices += [ind]
	if not indices:
		return ['Pattern not present in text']
	return indices

if __name__ == '__main__':
	print(naive_str('ATCGCTAGCTAGTAGCT', "TAG"))

data structures and algorithms/naive_str.py


from collections import deque

orders = deque([int(s) for s in input().split(', ')])
employees = [int(s) for s in input().split(', ')]
total_pizza = 0
while orders and employees:
    order = orders.popleft()
    employee = employees.pop()
    if order > 10 or order < 1:
        employees.append(employee)
        continue
    if order <= employee:
        total_pizza += order
    else:
        left_pizza = order - employee
        total_pizza += employee
        orders.appendleft(left_pizza)
if orders:
    print(f'Not all orders are completed.')
    print(f'Orders left: {", ".join(map(str,orders))}')
else:
    print(f'All orders are successfully completed!')
    print(f"Total pizzas made: {total_pizza}")
    print(f"Employees: {', '.join(map(str,employees))}")


#비지도 학습
#단순히 입력을 출력으로 복사하는 방법을 배우나, 네트워크에 제약을 가해 학습시킨다
import sklearn
import tensorflow as tf
from tensorflow import keras
import numpy as np
import os

import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)

def plot_image(image):
  plt.imshow(image, cmap="binary")
  plt.axis("off")

#3D->2D, 주성분 분석. PCA.
def generate_3d_data(m, w1=0.1, w2=0.3, noise=0.1):
    angles = np.random.rand(m) * 3 * np.pi / 2 - 0.5
    data = np.empty((m, 3))
    data[:, 0] = np.cos(angles) + np.sin(angles)/2 + noise * np.random.randn(m) / 2
    data[:, 1] = np.sin(angles) * 0.7 + noise * np.random.randn(m) / 2
    data[:, 2] = data[:, 0] * w1 + data[:, 1] * w2 + noise * np.random.randn(m)
    return data

X_train = generate_3d_data(60)
X_train = X_train - X_train.mean(axis=0, keepdims=0)

np.random.seed(42)
tf.random.set_seed(42)
#케라스 모델은 다른 모델의 층으로 사용할 수 있다. 오토인코더의 출력 개수가 입력의 개수와 동일하다. *3개
encoder = keras.models.Sequential([keras.layers.Dense(2, input_shape=[3])]) #인코더라고 말했지만 평범한 덴스층이네.
decoder = keras.models.Sequential([keras.layers.Dense(3, input_shape=[2])])
autoencoder = keras.models.Sequential([encoder, decoder])

autoencoder.compile(loss="mse", optimizer=keras.optimizers.SGD(lr=1.5))

history= autoencoder.fit(X_train,X_train, epochs=20)

#훈련의 부산물 코딩(그 코딩 아님)
codings = encoder.predict(X_train)

fig = plt.figure(figsize=(4,3))
plt.plot(codings[:,0], codings[:, 1], "b.")
plt.xlabel("$z_1$", fontsize=18)
plt.ylabel("$z_2$", fontsize=18, rotation=0)
plt.grid(True)
plt.show()


## Program: Find the largest among three;
try:
    num = 0
    myList = []
    for x in range(0, 3):
        temp = int(input("Enter number: "))
        myList.append(temp)
    print(max(myList))

except ValueError:
    print("Something went wrong ...")