import numpy as np
import os,re
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, Input
import time
import matplotlib.pyplot as plt
from tensorflow.keras.callbacks import ReduceLROnPlateau,EarlyStopping,ModelCheckpoint
import horovod.tensorflow.keras as hvd
import horovod.tensorflow as hvd_tf
import preprocessing
import argparse
import tensorflow.keras.backend as K
import pickle

import tensorflow_addons as tfa

import tensorflow_probability as tfp
tfb = tfp.bijectors
tfd = tfp.distributions
import fjord_regularization
tf.random.set_seed(1233)

class TubeletEmbedding(layers.Layer):
    def __init__(self, embed_dim, patch_size,is_1D=False, **kwargs):
        super().__init__(**kwargs)
        if is_1D:
            self.projection = layers.Conv1D(
                filters=embed_dim,
                kernel_size=patch_size,
                strides=patch_size,
                padding="VALID",
                use_bias=False,
            )
        else:
            self.projection = layers.Conv3D(
                filters=embed_dim,
                kernel_size=patch_size,
                strides=patch_size,
                padding="VALID",
                use_bias=False,
            )
        self.flatten = layers.Reshape(target_shape=(-1, embed_dim))

    def call(self, videos):
        projected_patches = self.projection(videos)
        flattened_patches = self.flatten(projected_patches)
        return flattened_patches

class PositionalEncoder(layers.Layer):
    def __init__(self, embed_dim, **kwargs):
        super().__init__(**kwargs)
        self.embed_dim = embed_dim

    def build(self, input_shape):
        _, num_tokens, _ = input_shape
        self.position_embedding = layers.Embedding(
            input_dim=num_tokens, output_dim=self.embed_dim
        )
        self.positions = tf.range(start=0, limit=num_tokens, delta=1)

    def call(self, encoded_tokens):
        # Encode the positions and add it to the encoded tokens
        encoded_positions = self.position_embedding(self.positions)
        encoded_tokens = encoded_tokens + encoded_positions
        return encoded_tokens

class BACKBONE_ODE(keras.Model):
    """ODE backbone network implementation"""
    def __init__(self, data_shape,num_cond,config,name='mlp_ode',
                 use_1D=False,use_dense=False):
        super(BACKBONE_ODE, self).__init__()
        if config is None:
            raise ValueError("Config file not given")
        self._num_cond = num_cond
        self._data_shape = data_shape
        self._data_shape_flat = [np.prod(data_shape)]

        self.config = config
        #config file with ML parameters to be used during training
        self.activation = self.config['ACT']
        self.use_1D=use_1D

        #transformation applied to conditional inputs
        inputs_time = Input((1))
        inputs_cond = Input((self._num_cond))

        if self.config['USE_MLP_COND']:
            conditional = layers.Dense(16,activation=self.activation)(inputs_cond)
            conditional = tf.concat([inputs_time,conditional],-1)
        else:
            conditional = tf.concat([inputs_time,inputs_cond],-1)

        if use_dense:
            inputs,outputs = self.DenseModel(conditional)
        else:
            inputs,outputs = self.ViTModel(conditional)

        self._model = keras.Model(inputs=[inputs,inputs_time,inputs_cond],outputs=outputs)

    def call(self, t, data,conditional):
        t_reshape = t*tf.ones_like(conditional[:,:1],dtype=tf.float32)
        return self._model([data,t_reshape,conditional])

    def DenseModel(self,time_embed):
        inputs = Input((self._data_shape))
        inputs_reshape = tf.expand_dims(inputs,-1)
        nlayers =self.config['NDENSE']
        ndim=self._data_shape[0]
        nhidden = self.config['HIDDEN_MULTIPLIER']*ndim

        layer_encoded = self.time_dense(inputs,time_embed,nhidden)
        for ilayer in range(1,nlayers-1):
            layer_encoded=self.time_dense(layer_encoded,time_embed,nhidden)

        #outputs=self.time_dense(layer_encoded,time_embed,ndim,activation=False)
        outputs = layers.Dense(ndim,activation=None)(layer_encoded)
        #outputs = layers.Flatten()(layer_encoded)
        return inputs, outputs

    def ViTModel(self,time_embed):
        ''' Visual transformer model as the network backbone for the FFJORD implementation'''
        inputs = Input((self._data_shape_flat))

        if self.use_1D:
            time_layer = tf.reshape(time_embed,(-1,1,time_embed.shape[-1]))
        else:
            time_layer = tf.reshape(time_embed,(-1,1,1,1,time_embed.shape[-1]))

        time_layer = tf.tile(time_layer,[1]+self._data_shape)
        transformer_layers = self.config['NLAYERS']
        num_heads=self.config['NHEADS']
        projection_dim = self.config['PROJECTION_SIZE']
        mlp_dim = self.config['MLP_SIZE']

        inputs_reshape = tf.concat([tf.reshape(inputs,[-1]+self._data_shape),time_layer],-1)
        patches = TubeletEmbedding(embed_dim=projection_dim,is_1D=self.use_1D,
                                   patch_size=self.config['STRIDE'])(inputs_reshape)

        # Encode patches.
        encoded_patches = PositionalEncoder(embed_dim=projection_dim)(patches)

        for _ in range(transformer_layers):
            # Layer normalization 1.
            x1 = layers.LayerNormalization(epsilon=1e-6)(encoded_patches)

            # Create a multi-head attention layer.
            attention_output = layers.MultiHeadAttention(
                num_heads=num_heads, key_dim=projection_dim)(x1, x1)
            # Skip connection 1.
            x2 = layers.Add()([attention_output, encoded_patches])

            # Layer normalization 2.
            x3 = layers.LayerNormalization(epsilon=1e-6)(x2)
            #x3=x2
            # MLP.
            #tf.nn.gelu

            # x3 = self.time_dense(x3,time_patch,2*projection_dim)
            # x3 = self.time_dense(x3,time_patch,projection_dim)

            x3 = layers.Dense(2*projection_dim,activation=self.activation)(x3)
            x3 = layers.Dense(projection_dim,activation=self.activation)(x3)

            # Skip connection 2.
            encoded_patches = layers.Add()([x3, x2])

        representation = layers.LayerNormalization(epsilon=1e-6)(encoded_patches)
        pooling = layers.GlobalAvgPool1D()(representation)
        representation = layers.Flatten()(representation)
        representation = self.time_dense(tf.concat([representation,pooling],-1),time_embed,mlp_dim)
        #representation = layers.Dropout(0.1)(representation)
        representation = self.time_dense(representation,time_embed,mlp_dim//2)
        outputs = layers.Dense(self._data_shape_flat[0])(representation)
        return inputs, outputs

    def time_dense(self,input_layer,embed,hidden_size,activation=True):
        #Incorporate the time information to each layer used in the model
        layer = tf.concat([input_layer,embed],-1)
        layer = layers.Dense(hidden_size,activation=None)(layer)

        #layer = layers.LayerNormalization(epsilon=1e-6)(layer)
        # layer = layers.Dropout(0.1)(layer)
        if activation:
            return self.activate(layer)
        else:
            return layer

    def activate(self,layer):
        if self.activation == 'leaky_relu':
            return keras.layers.LeakyReLU(-0.01)(layer)
        elif self.activation == 'tanh':
            return keras.activations.tanh(layer)
        elif self.activation == 'softplus':
            return keras.activations.softplus(layer)
        elif self.activation == 'relu':
            return keras.activations.relu(layer)
        elif self.activation == 'swish':
            return keras.activations.swish(layer)
        else:
            raise ValueError("Activation function not supported!")

def make_bijector_kwargs(bijector, name_to_kwargs):
    #Hack to pass the conditional information through all the bijector layers
    if hasattr(bijector, 'bijectors'):
        return {b.name: make_bijector_kwargs(b, name_to_kwargs) for b in bijector.bijectors}
    else:
        for name_regex, kwargs in name_to_kwargs.items():
            if re.match(name_regex, bijector.name):
                return kwargs
    return {}

def save_model(model,name="ffjord",checkpoint_dir = '../checkpoints'):
    if not os.path.exists(checkpoint_dir):
        os.makedirs(checkpoint_dir)
    model.save_weights('{}/{}'.format(checkpoint_dir,name),save_format='tf')
    np.save('optimizer.npy', model.optimizer.get_weights())

def load_model(model,name="ffjord",checkpoint_dir = '../checkpoints'):
    model.load_weights('{}/{}'.format(checkpoint_dir,name)).expect_partial()

class FFJORD(keras.Model):
    def __init__(self, stacked_layers,stacked_energies,
                 num_output,num_energy,
                 config,trace_type='hutchinson',
                 is_training=True,mask=None,name='FFJORD'):

        super(FFJORD, self).__init__()

        if config is None:
            raise ValueError("Config file not given")

        self.config = config

        ode_solve_fn = tfp.math.ode.DormandPrince(
            atol=1e-3,
            # rtol=1e-3,
            # first_step_size=0.2
        ).solve

        ode_solve_fn_energy = tfp.math.ode.DormandPrince(
            atol=1e-4,
            rtol=1e-4,
            #rtol=1e-5,
            #first_step_size=0.2
        ).solve

        #Gaussian noise to trace solver
        if trace_type=='hutchinson':
            if is_training:
                trace_augmentation_fn = fjord_regularization.trace_jacobian_hutchinson
            else:
                trace_augmentation_fn = tfb.ffjord.trace_jacobian_hutchinson
        elif trace_type == 'exact':
            trace_augmentation_fn = tfb.ffjord.trace_jacobian_exact #Regularization code only
        else:
            raise Exception("Invalid trace estimator")

        self.bijectors = []
        self.bijectors_energy = []

        for ilayer,layer in enumerate(stacked_layers):
            if is_training:
                ffjord = fjord_regularization.FFJORD(
                    state_time_derivative_fn=layer, #Each of the models we build
                    ode_solve_fn=ode_solve_fn,
                    is_training=is_training,
                    trace_augmentation_fn=trace_augmentation_fn,
                    name='bijector{}'.format(ilayer), #Bijectors need to be named to receive conditional inputs
                    jacobian_factor = self.config['JAC'], #Regularization strength
                    kinetic_factor = self.config['REG'],
                    b = self.config['b'],
                )
            else:

                ffjord = tfb.FFJORD(
                    state_time_derivative_fn=layer, #Each of the  models we build
                    ode_solve_fn=ode_solve_fn,
                    trace_augmentation_fn=tfb.ffjord.trace_jacobian_exact,
                    #trace_augmentation_fn=trace_augmentation_fn,
                    name='bijector{}'.format(ilayer),
            )

            self.bijectors.append(ffjord)

        for ilayer,layer in enumerate(stacked_energies):
            if is_training:
                ffjord = fjord_regularization.FFJORD(
                    state_time_derivative_fn=layer, #Each of the models we build
                    ode_solve_fn=ode_solve_fn_energy,
                    is_training=is_training,
                    trace_augmentation_fn=trace_augmentation_fn,
                    name='energy{}'.format(ilayer), #Bijectors need to be named to receive conditional inputs
                    jacobian_factor = self.config['JAC'], #Regularization strength
                    kinetic_factor = self.config['REG'],
                    b = self.config['b'],
                )
            else:

                ffjord = tfb.FFJORD(
                    state_time_derivative_fn=layer, #Each of the  models we build
                    ode_solve_fn=ode_solve_fn_energy,
                    trace_augmentation_fn=trace_augmentation_fn,
                    #trace_augmentation_fn=tfb.ffjord.trace_jacobian_exact,
                    name='energy{}'.format(ilayer),
                )

            self.bijectors_energy.append(ffjord)

        #Reverse the bijector order
        self.chain = tfb.Chain(list(reversed(self.bijectors)))
        self.chain_energy = tfb.Chain(list(reversed(self.bijectors_energy)))

        self.loss_tracker = keras.metrics.Mean(name="loss")

        #Determine the base distribution
        self.base_distribution = tfp.distributions.MultivariateNormalDiag(
            loc=np.zeros(num_output,dtype=np.float32),
            scale_diag=np.ones(num_output,dtype=np.float32)
        )

        self.base_distribution_energy = tfp.distributions.MultivariateNormalDiag(
            loc=np.zeros(num_energy,dtype=np.float32),
            scale_diag=np.ones(num_energy,dtype=np.float32)
        )

        self.flow=tfd.TransformedDistribution(distribution=self.base_distribution, bijector=self.chain)
        self.flow_energy=tfd.TransformedDistribution(distribution=self.base_distribution_energy,
                                                     bijector=self.chain_energy)
    @property
    def metrics(self):
        """List of the model's metrics.
        We make sure the loss tracker is listed as part of `model.metrics`
        so that `fit()` and `evaluate()` are able to `reset()` the loss tracker
        at the start of each epoch and at the start of an `evaluate()` call.
        """
        return [self.loss_tracker]

    def compile(self,e_optimizer, v_optimizer):
        super(FFJORD, self).compile(experimental_run_tf_function=False)
        self.e_optimizer = e_optimizer
        self.v_optimizer = v_optimizer

    # def call(self, inputs, conditional=None):
    #     kwargs = make_bijector_kwargs(self.flow.bijector,{'bijector.': {'conditional':conditional }})
    #     return self.flow.bijector.forward(inputs,**kwargs)

    def generate(self,conditional,nsplit=10):
        voxel = []
        energy = []

        for cond_split in np.array_split(np.array(conditional), nsplit):
            bijector_kwargs_energy = make_bijector_kwargs(
                self.flow_energy.bijector, {'energy.': {'conditional': cond_split}})
            energies = self.flow_energy.sample(cond_split.shape[0],bijector_kwargs= bijector_kwargs_energy)
            energy.append(energies.numpy())
            bijector_kwargs = make_bijector_kwargs(
                self.flow.bijector, {'bijector.': {'conditional': tf.concat([energies,cond_split],-1)}})
            voxels = self.flow.sample(cond_split.shape[0],bijector_kwargs= bijector_kwargs)
            voxel.append(voxels.numpy())
        voxel = np.concatenate(voxel,0)
        energy = np.concatenate(energy,0)
        return voxel,energy

    def log_loss(self,voxel,energies,conditional):
        bijector_kwargs = make_bijector_kwargs(
            self.flow.bijector, {'bijector.': {'conditional': tf.concat([energies,conditional],-1)}})

        #loss = loss_energy
        loss = -tf.reduce_mean(self.flow.log_prob(voxel,bijector_kwargs= bijector_kwargs))

        return loss

    def log_loss_energy(self,energies,conditional):
        bijector_kwargs_energy = make_bijector_kwargs(
            self.flow_energy.bijector, {'energy.': {'conditional': conditional}})

        loss_energy = -tf.reduce_mean(self.flow_energy.log_prob(energies,
                                                                bijector_kwargs= bijector_kwargs_energy))

        return loss_energy

    @tf.function()
    def train_step(self, inputs):
        data,energy,cond = inputs
        with tf.GradientTape() as tape:
            loss_voxel = self.log_loss(data,energy,cond)

        v = tape.gradient(loss_voxel, self.flow.trainable_variables)
        v = [tf.clip_by_norm(grad, 1) for grad in v]
        self.v_optimizer.apply_gradients(zip(v, self.flow.trainable_variables))
        self.loss_tracker.update_state(loss_voxel)

        with tf.GradientTape() as tape:
            loss_energy = self.log_loss_energy(energy,cond)

        e = tape.gradient(loss_energy, self.flow_energy.trainable_variables)
        self.e_optimizer.apply_gradients(zip(e, self.flow_energy.trainable_variables))

        return {"loss": self.loss_tracker.result(),'energy':loss_energy}

    @tf.function
    def test_step(self, inputs):
        data,energy,cond = inputs
        loss_voxel=self.log_loss(data,energy,cond)
        loss_energy = self.log_loss_energy(energy,cond)
        loss = loss_voxel+loss_energy
        self.loss_tracker.update_state(loss)
        return {"loss": self.loss_tracker.result()}

if __name__ == '__main__':
    #Start horovod and pin each GPU to a different process
    hvd.init()
    gpus = tf.config.experimental.list_physical_devices('GPU')
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)
    if gpus:
        tf.config.experimental.set_visible_devices(gpus[hvd.local_rank()], 'GPU')

    parser = argparse.ArgumentParser()

    parser.add_argument('--model', default='calogan', help='Name of the model to train. Options are: mnist, challenge, calogan')
    parser.add_argument('--nevts', default=-1, help='Name of the model to train. Options are: mnist, moon, calorimeter')
    parser.add_argument('--load', action='store_true', default=False,help='Load pretrained weights to continue the training')
    flags = parser.parse_args()

    model_name = flags.model #Let's try the parallel training using different models and different network architectures. Possible options are [mnist,moon,calorimeter]

    if model_name == 'mnist':
        from tensorflow.keras.datasets import mnist, fashion_mnist
        dataset_config = preprocessing.LoadJson('config_mnist.json')
        (X_train, y_train), (X_test, y_test) = mnist.load_data()
        ntrain,samples_train =preprocessing.MNIST_prep(X_train, y_train)
        ntest,samples_test =preprocessing.MNIST_prep(X_test, y_use)

        test_1D = False #Use convolutional networks for the model backbone
    elif model_name == 'calogan':
        dataset_config = preprocessing.LoadJson('config_calogan_vit.json')
        file_path=dataset_config['FILE']
        ntrain,ntest,samples_train,samples_test,mask = preprocessing.CaloGAN_prep(file_path,int(flags.nevts),use_logit=True)
        use_1D = True
    elif model_name == 'calochallenge':
        dataset_config = preprocessing.LoadJson('config_challenge_vit.json')
        file_path=dataset_config['FILE']
        ntrain,ntest,samples_train,samples_test,mask = preprocessing.CaloChallenge_prep(file_path,int(flags.nevts),use_logit=True)
        use_1D = False
    else:
        raise ValueError("Model not implemented!")

    LR = float(dataset_config['LR'])
    NUM_EPOCHS = dataset_config['MAXEPOCH']
    STACKED_FFJORDS = dataset_config['NSTACKED'] #Number of stacked transformations

    NUM_LAYERS = dataset_config['NLAYERS'] #Hiddden layers per bijector
    BATCH_SIZE = dataset_config['BATCH']
    NLAYER = dataset_config['NENERGY']

    #Stack of bijectors
    stacked_vit = []
    stacked_dense = []
    for istack in range(1):
        vit_model = BACKBONE_ODE(dataset_config['SHAPE'], NLAYER+1,
                                 config=dataset_config,use_1D=use_1D)
        stacked_vit.append(vit_model)

    for istack in range(STACKED_FFJORDS):
        dense_model = BACKBONE_ODE([NLAYER], 1, config=dataset_config,use_1D=True,
                                   name='mlp_energy',use_dense=True)
        stacked_dense.append(dense_model)

    #Create the model
    model = FFJORD(stacked_vit,stacked_dense,
                   np.prod(list(dataset_config['SHAPE'])),NLAYER,
                   mask=mask,
                   config=dataset_config)

    opt_v = tfa.optimizers.AdamW(learning_rate=LR,weight_decay=1e-2*LR)
    # opt_v = tf.optimizers.Adam(learning_rate=LR)
    opt_v = hvd.DistributedOptimizer(opt_v)

    opt_e = tfa.optimizers.AdamW(learning_rate=0.1*LR,weight_decay=1e-2*LR)
    # opt_e = tf.optimizers.SGD(learning_rate=LR)
    # opt_e = tf.optimizers.Adam(learning_rate=LR)
    opt_e = hvd.DistributedOptimizer(opt_e)

    # Horovod: add Horovod DistributedOptimizer.
    model.compile(v_optimizer=opt_v,e_optimizer=opt_e)

    if flags.load:
        load_model(model,checkpoint_dir='../checkpoint_{}'.format(dataset_config['MODEL']))

    callbacks = [
        hvd.callbacks.BroadcastGlobalVariablesCallback(0),
        hvd.callbacks.MetricAverageCallback(),
        ReduceLROnPlateau(patience=30, min_lr=1e-7,verbose=hvd.rank() == 0),
        EarlyStopping(patience=dataset_config['EARLYSTOP'],restore_best_weights=True),
        hvd.callbacks.LearningRateWarmupCallback(warmup_epochs=10, initial_lr=LR, verbose=1),
    ]

    if hvd.rank()==0:
        checkpoint = ModelCheckpoint('../checkpoint_{}/ffjord'.format(dataset_config['MODEL']),save_best_only=True,mode='auto',
                                                               period=1,save_weights_only=True)
        callbacks.append(checkpoint)
        # model(np.zeros((1,dataset_config['SHAPE'][0])),np.zeros((1,1)))
        # print(model.summary())

    history = model.fit(
        samples_train.batch(BATCH_SIZE),
        steps_per_epoch=int(ntrain/BATCH_SIZE),
        validation_data=samples_test.batch(BATCH_SIZE),
        validation_steps=max(1,int(ntest/BATCH_SIZE)),
        epochs=NUM_EPOCHS,
        verbose=hvd.rank() == 0,
        callbacks=callbacks,
    )

    if hvd.rank() == 0:
        save_model(model,checkpoint_dir='../checkpoint_{}'.format(dataset_config['MODEL']))


from typing import List
class Solution:
    def isPrefixString(self, s: str, words: List[str]) -> bool:
        n = len(words)
        for i in range(n):
            cur = words[:i + 1]
            ss = ''.join(cur)
            # print(ss)
            if s == ss:
                return True
        return False

# 看了0x3f的题解，返现了一个更好的解法

# class Solution {
# public:
#     bool isPrefixString(string s, vector<string>& words) {
#         int sum = 0;
#         string cur;
#         for(auto& ss:words){
#             sum += ss.size();
#             cur += ss;
#             if(sum > s.size()) return false;
#             else if(sum == s.size()){
#                 return cur == s;
#             }
#         }
#         return false;
#     }
# };


from app import mail
from flask import current_app, render_template
from flask_mail import Message

class Helper:
    @staticmethod
    def enviar_email(cls, subject, to, template, **kwargs) -> None:
        msg = Message(
            subject=subject,
            sender=current_app.config["MAIL_SENDER"],
            recipients=[to],
        )

        msg.body = render_template(f"mails/{template}.txt", **kwargs)
        msg.html = render_template(f"mails/{template}.html", **kwargs)
        mail.send(msg)


# -*- coding:utf-8 -*-
import re
import json
import requests
import xlwt

# 信息
data = []

first_url = 'https://s.taobao.com/search?\
initiative_id=tbindexz_20170906&ie=utf8&spm\
=a21bo.50862.201856-taobao-item.2&sourceId\
=tb.index&search_type=item&ssid=s5-e&commend=a\
ll&imgfile=&q=python%E8%A7%86%E9%A2%\
91&suggest=0_2&_input_charset=utf-8\
&wq=python&suggest_query=python&source=suggest'
res = requests.get(first_url)
html = res.text

# 取出所需要的数据
content = re.findall(r'g_page_config = .*g_srp_loadCss', html, re.S)[0]
# 进一步提取，把无效的字符取消掉
content = re.findall(r'{.*}', content)[0]

# 转换成json 格式
content = json.loads(content)

# print(content)
# print(content['mods'])
# print(content['mods']['itemlist'])
# print(content['mods']['itemlist']['data']['auctions'][0])

# 获取信息
data_list = content['mods']['itemlist']['data']['auctions']
for item in data_list:
    temp = {
        'title': item['title'],
        'view_price': item['view_price'],
        'view_sales': item['view_sales'],
        'view_fee': '否' if float(item['view_fee']) else '是',
        'isTmall': '是' if item['shopcard']['isTmall'] else '否',
        'area': item['item_loc'],
        'name': item['nick'],
        'detail_url': item['detail_url'],
    }
    data.append(temp)
# print(data[0])
f = xlwt.Workbook(encoding='utf-8')
sheet01 = f.add_sheet(u'sheet1', cell_overwrite_ok=True)

# 写标题
sheet01.write(0, 0, '标题')
sheet01.write(0, 1, '标价')
sheet01.write(0, 2, '购买人数')
sheet01.write(0, 3, '是否包邮')
sheet01.write(0, 4, '是否天猫')
sheet01.write(0, 5, '地区')
sheet01.write(0, 6, '店名')
sheet01.write(0, 7, 'url')

# 写内容
for i in range(len(data)):
    sheet01.write(i + 1, 0, data[i]['title'])
    sheet01.write(i + 1, 1, data[i]['view_price'])
    sheet01.write(i + 1, 2, data[i]['view_sales'])
    sheet01.write(i + 1, 3, data[i]['view_fee'])
    sheet01.write(i + 1, 4, data[i]['isTmall'])
    sheet01.write(i + 1, 5, data[i]['area'])
    sheet01.write(i + 1, 6, data[i]['name'])
    sheet01.write(i + 1, 7, data[i]['detail_url'])

# 保存
f.save(u'搜索%s的结果.xls' % u'python视频教程')


import streamlit as st
from program import pre

def local_css(file_name):
    with open(file_name) as f:
        st.markdown(f'', unsafe_allow_html=True)

def remote_css(url):
    st.markdown(f'<link href="{url}" rel="stylesheet">', unsafe_allow_html=True)

local_css("style.css")
st.markdown("""

""", unsafe_allow_html=True)
remote_css('https://fonts.googleapis.com/icon?family=Material+Icons')
# import base64
#
#
# @st.cache(allow_output_mutation=True)
# def get_base64_of_bin_file(bin_file):
#     with open(bin_file, 'rb') as f:
#         data = f.read()
#     return base64.b64encode(data).decode()
#
#
# def set_png_as_page_bg(png_file):
#     bin_str = get_base64_of_bin_file(png_file)
#     page_bg_img = '''
#
#     ''' % bin_str
#
#     st.markdown(page_bg_img, unsafe_allow_html=True)
#     return
#
#
# set_png_as_page_bg('background.png')

st.title('Chương trình phân loại văn bản tự động')
article = st.text_area("Nhập văn bản", height=300)
if st.button('Enter'):
    if not article.strip():
        st.warning('Chưa có văn bản nào đưuọc nhập!!')
        st.stop()
    category, proba = pre(article)
    st.markdown("Văn bản này thuộc về thể loại {}".format(category), unsafe_allow_html=True)
    st.markdown("Độ tin cậy: {} % ".format(proba), unsafe_allow_html=True)


from flask import Flask,request,jsonify,json
import jiomusic

app = Flask(__name__)
app.secret_key = 'thankyoutonystark#weloveyou3000'

@app.route('/')
def home():
   return "Thanks for testing JioMusic API. To get started head up to my GitHub for documentation."

@app.route('/result/', methods=['GET'])
def result():
    query=request.args.get('query')
    if jiomusic.song_search(query=query) is not None:
        return jsonify(jiomusic.song_search(query=query))
    else:
        # Not catching any error because I hope this will never crash!
        # You should not get this message eveeeeeeeeeeeeer!
        return "Something went wrong!"

if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0',port=5000,use_reloader=True,threaded = True)


from flask import jsonify
from flask import abort

#
# Method that will get the valid actors based upon
# user specified queries and boolean operators
#
# https://stackoverflow.com/questions/23030106/intersection-of-two-lists-of-dict-python
# https://www.geeksforgeeks.org/python-remove-duplicates-list/
#
def get_actors_list(queries, bool_operators, data):
    actor_list = get_actor_query_elements(queries.get(), data)
    while queries.empty() == False:
        query_list = get_actor_query_elements(queries.get(), data)
        bool_operator = bool_operators.get()
        if bool_operator == '&':
            actor_list = [i for i in actor_list for j in query_list if i['name'] == j['name']]
        else:
            final_list = []
            actor_list.extend(query_list)
            for dictionary in actor_list:
                if dict not in final_list:
                    final_list.append(dictionary)
            actor_list = final_list
    return jsonify(actor_list)

#
# Method that splits a query into its parameter name and value
# then returns all actor elements with the relevant information
#
def get_actor_query_elements(query, data):
    query_vals = query.split('=')
    query_list = []
    if query_vals[0] == 'name':
        query_list = get_actors_by_name(query_vals[1], data)
    elif query_vals[0] == 'age':
        query_list = get_actors_by_age(int(query_vals[1]), data)
    elif query_vals[0] == 'total_gross':
        query_list = get_actors_by_gross(int(query_vals[1]), data)
    else:
        query_list = get_actors_by_film(query_vals[1], data)
    return query_list

#
# Method that returns all actor JSON elements with
# the actor_name
#
def get_actors_by_name(actor_name, data):
    actors_list = []
    for element in data.keys():
        if actor_name in element:
            actors_list.append(data[element])
    if not actors_list:
        abort(400) # actor not in data
    else:
        return actors_list

#
# Method that returns all actor JSON elements with
# the actor_age
#
def get_actors_by_age(actor_age, data):
    actors_list = []
    for element in data.keys():
        if data[element]['age'] == actor_age:
            actors_list.append(data[element])
    if not actors_list:
        abort(400)
    else:
        return actors_list

#
# Method that returns all actor JSON elements >=
# the actor_gross
#
def get_actors_by_gross(actor_gross, data):
    actors_list = []
    for element in data.keys():
        if data[element]['total_gross'] == actor_gross:
            actors_list.append(data[element])
    if not actors_list:
        abort(400)
    else:
        return actors_list

#
# Method that returns all actor JSON elements with
# the actor_film
#
def get_actors_by_film(actor_film, data):
    actors_list = []
    for element in data.keys():
        filmography = data[element]['movies']
        for film in filmography:
            if actor_film in film:
                actors_list.append(data[element])
                break
    if not actors_list:
        abort(400)
    else:
        return actors_list

#
# A method to create an actor element for
# the JSON table in memory. Only used for
# POST HTTP Requests
#
def create_actor(modification, data):
    actor_name = modification['name']
    if actor_name in data.keys():
        modify_actor(actor_name, modification, data)
    else:
        data[actor_name] = modification
        return jsonify(data[actor_name])

#
# A method to modify an already existing actor
# element from the JSON table in memory. Can be
# used for POST and PUT HTTP Requests
#
def modify_actor(name, modification, data):
    element = data[name]
    for key in modification.keys():
        element[key] = modification.get(key)
    return jsonify(element)


"""clinic URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.urls import path, include # new
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('pages.urls')), # new
    path('patients/', include('patient.urls')), # new
    path('referrers/', include('referrer.urls')), # new
    path('causes/', include('cause.urls')), # new
    path('investigations/', include('investigation.urls')), # new
    path('diagnose/', include('diagnose.urls')), # new
    path('operation/', include('operation.urls')), # new
    path('treatment/', include('treatment.urls')), # new
    path('appointment/', include('appointment.urls')), # new
    path('accounts/', include('django.contrib.auth.urls')), # new
    path('followup/', include('followup.urls')), # new
    path('newVisit/', include('newVisit.urls')), # new
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


"""Sensor platform for zagonel."""
from __future__ import annotations

from typing import Any

import homeassistant.util.color as color_util
from homeassistant.components.light import ColorMode, LightEntity, LightEntityDescription
from homeassistant.util import slugify
from .api import ZagonelRGBMode
from .const import DOMAIN
from .coordinator import ZagonelDataUpdateCoordinator
from .entity import ZagonelEntity

ENTITY_DESCRIPTIONS = (
    LightEntityDescription(
        key="shower_light",
        name="Shower light",
        icon="mdi:led-strip",
        translation_key="shower_light"
    ),
)

async def async_setup_entry(hass, entry, async_add_devices):
    """Set up the sensor platform."""
    coordinator = hass.data[DOMAIN][entry.entry_id]
    unique_id = slugify(coordinator.data.chars.Device_Id)
    async_add_devices(
        ZagonelLight(
            unique_id=f"{entity_description.key}_{unique_id}",
            coordinator=coordinator,
            entity_description=entity_description,
        )
        for entity_description in ENTITY_DESCRIPTIONS
    )

class ZagonelLight(ZagonelEntity, LightEntity):
    """Zagonel Light class."""

    _attr_color_mode = ColorMode.RGB
    _attr_supported_color_modes = {ColorMode.RGB}

    def __init__(
            self,
            unique_id: str,
            coordinator: ZagonelDataUpdateCoordinator,
            entity_description: LightEntityDescription,
    ) -> None:
        """Initialize the sensor class."""
        super().__init__(unique_id, coordinator)
        self.entity_description = entity_description

    @property
    def rgb_color(self) -> tuple[int, int, int] | None:
        """Return the rgb color value [int, int, int]."""
        hex_color = self.coordinator.data.chars.Rgb_Color
        rgb_color = color_util.rgb_hex_to_rgb_list(hex_color[1:])
        return rgb_color[0], rgb_color[1], rgb_color[2]

    @property
    def is_on(self) -> bool | None:
        """Return True if entity is on."""
        return self.coordinator.data.chars.Rgb_Mode == ZagonelRGBMode.FIXED

    async def async_turn_on(self, **kwargs: Any) -> None:
        """Turn the entity on."""
        if not self.is_on:
            await self.send(
                "Rgb_Mode",
                ZagonelRGBMode.FIXED
            )
        rgb_color = kwargs.get("rgb_color")
        if rgb_color is not None:
            await self.send(
                "Rgb_Color",
                f"#{color_util.color_rgb_to_hex(rgb_color[0], rgb_color[1], rgb_color[2]).upper()}"
            )

    async def async_turn_off(self, **kwargs: Any) -> None:
        """Turn the entity off."""
        await self.send(
            "Rgb_Mode",
            ZagonelRGBMode.POWER
        )


import argparse
import os
import tarfile
import urllib

import numpy as np
import pyprind

import utils

"""
次の理由から、本家の```create_ubuntu_dataset.py```の代わりにこちらを使う。
- ubuntu_dialogs.tgzはサイズが莫大で、また今回に関してはそのすべては必要ではないため、解凍せずに条件にあうものだけを抽出する
- 今回に関しては (context, response, label) のtripletsの生成までは不要であり、条件にあうdialogだけが必要
"""

URL = 'http://cs.mcgill.ca/~jpineau/datasets/ubuntu-corpus-1.0/ubuntu_dialogs.tgz'
ARCHIVE_NAME = 'ubuntu_dialogs.tgz'

def main(args):
    archive_dir = args.input
    output_dir = args.output

    # Download archived dialogues (```ubuntu_dialogs.tgz```) to ```archive_dir```
    prepare_data_maybe_download(archive_dir)

    # Extract dialogues that meet the given conditions
    dialogues = extract_dialogues(archive_path=os.path.join(archive_dir, ARCHIVE_NAME),
                                  n_dialogues=args.n_dialogues,
                                  min_dialogue_length=args.min_dialogue_length,
                                  max_dialogue_length=args.max_dialogue_length,
                                  max_utterance_length=args.max_utterance_length,
                                  max_speakers=args.max_speakers)
    assert len(dialogues) <= args.n_dialogues

    # Save the extracted dialogues to ```output_dir```
    save_dialogues(output_dir=output_dir, dialogues=dialogues)

    utils.writelog("Done.")

def prepare_data_maybe_download(archive_dir):
    """
    Download archived dialogues if necessary.
    This functions is mainly copied from the following original repository:
        https://github.com/rkadlec/ubuntu-ranking-dataset-creator
    """
    # Check
    filenames = os.listdir(archive_dir)
    assert "generate.sh" in filenames
    assert "create_ubuntu_dataset.py" in filenames
    assert "download_punkt.py" in filenames
    assert "meta" in filenames

    # dialogs are missing
    archive_path = os.path.join(archive_dir, ARCHIVE_NAME)
    if not os.path.exists(archive_path):
        # archive missing, download it
        utils.writelog("Downloading %s to %s" % (URL, archive_path))
        filepath, _ = urllib.request.urlretrieve(URL, archive_path)
        utils.writelog("Successfully downloaded " + filepath)
    else:
        utils.writelog("Found archive: %s" % archive_path)

def extract_dialogues(
        archive_path,
        n_dialogues,
        min_dialogue_length,
        max_dialogue_length,
        max_utterance_length,
        max_speakers):
    utils.writelog("Number of dialogues: %d" % n_dialogues)
    utils.writelog("Min. dialogue length: %d" % min_dialogue_length)
    utils.writelog("Max. dialogue length: %d" % max_dialogue_length)
    utils.writelog("Max. utterance length: %d" % max_utterance_length)
    utils.writelog("Max. speakers: %d" % max_speakers)

    utils.writelog("Extracting dialogues from %s ..." % archive_path)
    dialogues = []

    with tarfile.open(name=archive_path, mode="r") as tar:
        # Get archived files (including directories)
        utils.writelog("Extracting archived information ...")

        members = tar.getmembers() # May take several minutes
        utils.writelog("Number of archived entries (files + directories): %d" % len(members))
        members = [m for m in members if m.name.endswith(".tsv")]
        utils.writelog("Number of archived TSV files: %d" % len(members))

        count = 0
        avg_dialogue_length = []
        avg_utterance_length = []
        avg_speakers = []
        for member_i, member in enumerate(members):
            # Content
            with tar.extractfile(member) as f:
                binary = f.read()
                text = binary.decode("utf-8")
            lines = text.split("\n")
            lines = [line.split("\t") for line in lines]

            # Clean lines
            new_lines = []
            for items in lines:
                assert len(items) == 4 or len(items) == 1 or len(items) == 0
                if len(items) == 4:
                    new_lines.append(items)
            lines = new_lines

            # Clean utterance
            lines = [items for items in lines if len(items) == 4]
            for i in range(len(lines)):
                assert len(lines[i]) == 4
                utterance = lines[i][3]
                utterance = utterance.strip()
                lines[i][3] = utterance

            # If conditions are met, record this dialogue
            avg_dialogue_length.append(len(lines))
            if min_dialogue_length <= len(lines) <= max_dialogue_length:
                # Dialogue length is OK
                all_with_response = True
                for items in lines[2:]:
                    _, _, listener, _ = items
                    if listener == "":
                         all_with_response = False
                all_with_utterance = True
                for items in lines:
                    _, _, _, utterance = items
                    if utterance == "":
                        all_with_utterance = False
                if all_with_response and all_with_utterance:
                    # All utterances (except for the first one) are with response-to markers
                    temp_max_utterance_length = -1
                    speakers = []
                    for items in lines:
                        _, speaker, listener, utterance = items
                        n_tokens = len(utterance.split(" ")) # rough whitespace-based tokenization
                        temp_max_utterance_length = max(temp_max_utterance_length, n_tokens)
                        speakers.append(speaker)
                        speakers.append(listener)
                    speakers = set(speakers)
                    avg_utterance_length.append(temp_max_utterance_length)
                    avg_speakers.append(len(speakers))
                    if temp_max_utterance_length <= max_utterance_length and len(speakers) <= max_speakers:
                        # Utterance length and the number of speakers are OK
                        dialogues.append(lines)
                        count += 1
                        # Progress
                        if count % 1000 == 0:
                            utils.writelog("##### Extracted %d dialogues #####" % count)
                        if count == n_dialogues:
                            break

            # Progress
            if (member_i + 1) % 5000 == 0:
                utils.writelog("Processed %d dialogues" % (member_i + 1))
                utils.writelog("Avg. dialogue length: %f" % np.mean(avg_dialogue_length))
                utils.writelog("Avg. max utterange length: %f" % np.mean(avg_utterance_length))
                utils.writelog("Avg. number of speakers: %f" % np.mean(avg_speakers))
                avg_dialogue_length = []
                avg_utterance_length = []
                avg_speakers = []

    ratio = float(count) / len(members) * 100.0
    utils.writelog("Extracted %d dialogues (utility: %d/%d=%.2f%%)" % (count, count, len(members), ratio))
    return dialogues

def save_dialogues(output_dir, dialogues):
    utils.writelog("Saving dialogues to %s ..." % output_dir)
    utils.mkdir(output_dir)
    for dialogue_i, dialogue in enumerate(pyprind.prog_bar(dialogues)):
        with open(os.path.join(output_dir, "%06d.tsv" % dialogue_i), "w") as f:
            for items in dialogue:
                assert len(items) == 4
                line = "\t".join(items)
                f.write("%s\n" % line)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--input", type=str, required=True)
    parser.add_argument("--output", type=str, required=True)
    parser.add_argument("--n_dialogues", type=int, required=True)
    parser.add_argument("--min_dialogue_length", type=int, default=7)
    parser.add_argument("--max_dialogue_length", type=int, default=16)
    parser.add_argument("--max_utterance_length", type=int, default=20)
    parser.add_argument("--max_speakers", type=int, default=9)
    args = parser.parse_args()
    main(args)


import os

from django.core.files import File
from django.db import migrations

base_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                         'avatars')

def save_image_from_file(field, name):
    path = os.path.join(base_path, name)
    f = open(path, 'rb')
    field.save(name, File(f), save=True)

def add_item(apps, schema_editor):
    Teacher = apps.get_model('app', 'Teacher')
    Achievement = apps.get_model('app', 'Achievement')

    teachers = Teacher.objects.all()

    for i, teacher in enumerate(teachers):
        if i > 20:
            break

        titles = ['特级教师', '全国奥数总冠军']
        for j in range(2):
            achievement = Achievement(teacher=teacher, title=titles[j])
            name = 'img%d.jpg' % ((i + j) % 8)
            save_image_from_file(achievement.img, name)
            achievement.save()

class Migration(migrations.Migration):

    dependencies = [
        ('app', '0048_highscore'),
    ]

    operations = [
        migrations.RunPython(add_item),
    ]


import re
from django.conf import settings
from django.http import HttpResponse
from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
from django.utils.html import format_html
from django.core.files.storage import FileSystemStorage

from uuslug import slugify, uuslug
from os import path, remove, rename
from glob import glob
from shutil import rmtree
from PIL import Image
from imagekit import ImageSpec
from imagekit.processors import ResizeToFit #, ResizeToFill
from imagekit.cachefiles import ImageCacheFile

# delete main image and its thumbs
def remove_images(obj, delete_original=True):
	if obj and obj.path:
		filename, ext = path.splitext(obj.path)
		cache_folder = filename.replace('/media/', '/media/CACHE/images/')
		rmtree(cache_folder, ignore_errors=True)
		# select all thumbs for original file
		files = glob(filename+'_[0-9][0-9][0-9]*w'+ext)
		# add to files array if original file exists on disk
		if delete_original and (path.isfile(obj.path) or path.islink(obj.path)):
			files.append(obj.path)
		for f in files:
			remove(f)

def is_file_exist(obj):
	#return path.isfile(path.join(settings.MEDIA_ROOT,obj.name))
	return path.isfile(obj.path)

def is_image_file(obj):
	filename, ext = path.splitext(obj.file.name)
	return ext.lower() == '.jpg' or ext.lower() == '.jpeg' or ext.lower() == '.png'

class MediaFileStorage(FileSystemStorage):

	def get_available_name(self, name, max_length=None):
		upload_folder, filename = path.split(name.lower())
		filename, ext = path.splitext(filename)
		filename = slugify(filename)
		name = path.join(upload_folder, filename+ext)

		# add index to file name if it exists
		index=1
		while self.exists(name):
			name = path.join(upload_folder, f'{filename}-{index:02}'+ext)
			index += 1
			if index == 20:
				break

		return name

class AdminThumbnail(ImageSpec):
	processors = [ResizeToFit(100, 100)]
	format = 'JPEG'
	options = {'quality': 75 }

class GalleryThumbnail(ImageSpec):
	processors = [ResizeToFit(1200, 900)]
	format = 'JPEG'
	autoconvert = True
	options = {'quality': 80 }

class Thumbnail(ImageSpec):
	processors = [ResizeToFit(900, 600)]
	format = 'JPEG'
	autoconvert = True
	options = {'quality': 80 }

def update_admin_thumb(obj):
	thumbnail = ImageCacheFile(AdminThumbnail(obj))
	#print(thumbnail)
	thumbnail.generate()
	return thumbnail

def get_admin_thumb(obj):
	if obj and is_file_exist(obj) and is_image_file(obj) :
		thumb = update_admin_thumb(obj)
		#print(f'get admin thumb {thumb.url}')
		if thumb.url:
			return format_html('', thumb.url)
	return format_html('')

def generate_thumbs(obj, sizes):
	if obj and is_file_exist(obj) and is_image_file(obj) :
		file = obj.path
		filename, ext = path.splitext(file)
		with Image.open(file) as image:
			im_w, im_h = image.size
			aspect_ratio = im_w / float(im_h)

			for size in sizes:
				im = image.copy()
				thumb_w = size
				thumb_h = int(thumb_w / aspect_ratio)
				im.thumbnail((thumb_w, thumb_h))
				thumb_filename = '{0}_{1}w{2}'.format(filename, size, ext)
				im.save(thumb_filename)

def generate_images(obj, thumbnail='thumbnail', *sizes):
	if obj and is_image_file(obj) :
		file = obj.path
		old_file = file + '.old'
		try:
			source = open(file, 'rb')
			if thumbnail == 'full':
				image_generator = GalleryThumbnail(source=source)
			else:
				image_generator = Thumbnail(source=source)

			result = image_generator.generate()
			rename(file, old_file)

			dest = open(file, 'wb')
			dest.write(result.read())
			dest.close()
			remove(old_file)

			if sizes :
				generate_thumbs(obj, *sizes)

		except IOError:
			print('error in file: %s' % file)
			if path.isfile(old_file):
				rename(old_file, file)
			return HttpResponse('Ошибка открытия файла %s!' % file)

def update_google_sitemap():
	try:
		ping_google() #сообщим Google о изменениях в sitemap.xml
	except Exception:
		pass

def addDomainToUrl(request, value, pattern, start=False):
	if request:
		scheme = request.is_secure() and "https" or "http"
		SITE_DOMAIN = '%s://%s' % (scheme, request.META['HTTP_HOST'])
		SEARCH_PATTERN = pattern.replace('<URL>', '')
		REPLACE_WITH = pattern.replace('<URL>', SITE_DOMAIN)
		to_replace = value.startswith(SEARCH_PATTERN) if start else True
		if to_replace:
			url = value.replace(SEARCH_PATTERN, REPLACE_WITH)

		return url
	return value

def get_site_domain(url):
	if not url:
		return ""
	name = re.sub(r'^https?:\/\/|\/(www\.)?$', '', url, flags=re.MULTILINE)
	return name.strip().strip('/').split('.', 1)[0]


import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from PyQt5.QtGui import QFont
import seaborn as sns
from pptx import Presentation
from pptx.util import Cm
import ecl_data_io as eclio
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
import plotly.graph_objects as go
import data_generation as dg
import os
import math

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.button = QtWidgets.QPushButton('Построить', self)
        self.button.setFont(QFont('Arial', 12))
        self.export_button = QtWidgets.QPushButton('Экспорт', self)
        self.export_button.setFont(QFont('Arial', 12))
        self.well_button = QtWidgets.QPushButton('Выгрузка по \nскважинам', self)
        self.well_button.setFont(QFont('Arial', 12))
        self.report_button = QtWidgets.QPushButton('Сформировать \nотчет', self)
        self.report_button.setFont(QFont('Arial', 12))
        self.clear_cache_button = QtWidgets.QPushButton('Очистить \nкэш', self)
        self.clear_cache_button.setFont(QFont('Arial', 12))
        self.browser = QtWebEngineWidgets.QWebEngineView(self)

        self.well_button.move(870, 20)
        self.well_button.setFixedHeight(70)
        self.well_button.setFixedWidth(120)

        self.report_button.move(730, 20)
        self.report_button.setFixedHeight(70)
        self.report_button.setFixedWidth(120)

        self.clear_cache_button.move(590, 20)
        self.clear_cache_button.setFixedHeight(70)
        self.clear_cache_button.setFixedWidth(120)

        self.property_combo = QtWidgets.QComboBox(self)

        self.property_label = QtWidgets.QLabel('Свойство:', self)
        self.property_label.move(15, -5)
        self.property_combo.setFixedHeight(25)
        self.property_combo.setFixedWidth(120)
        self.property_combo.move(15, 20)

        self.time_combo = QtWidgets.QComboBox(self)
        self.time_label = QtWidgets.QLabel('Шаг:', self)
        self.time_label.move(15, 40)
        self.time_combo.setFixedHeight(25)
        self.time_combo.setFixedWidth(120)
        self.time_combo.move(15, 65)

        self.fip_combo = QtWidgets.QComboBox(self)
        self.fip_label = QtWidgets.QLabel('Номер/Имя:', self)
        self.fip_label.move(150, 40)
        self.fip_combo.setFixedHeight(25)
        self.fip_combo.setFixedWidth(120)
        self.fip_combo.move(150, 65)

        self.export_combo = QtWidgets.QComboBox(self)
        self.export_label = QtWidgets.QLabel('Метод экспорта:', self)
        self.export_label.move(285, 40)
        self.export_combo.setFixedHeight(25)
        self.export_combo.setFixedWidth(120)
        self.export_combo.move(285, 65)

        self.method_combo = QtWidgets.QComboBox(self)
        self.method_label = QtWidgets.QLabel('Метод построения:', self)
        self.method_label.move(285, -5)
        self.method_combo.setFixedHeight(25)
        self.method_combo.setFixedWidth(120)
        self.method_combo.move(285, 20)

        self.region_combo = QtWidgets.QComboBox(self)
        self.region_label = QtWidgets.QLabel('Регион:', self)
        self.region_label.move(150, -5)
        self.region_combo.setFixedHeight(25)
        self.region_combo.setFixedWidth(120)
        self.region_combo.move(150, 20)

        self.property = dg.get_static_property()
        self.dynamic_property = dg.get_dynamic_property()

        self.property_combo.addItem('Hэфф')
        self.property_combo.addItem('Hэфф(газ)')
        self.property_combo.addItem('Hэфф(нефть)')
        self.property_combo.addItem('Hэфф(нефть/газ)')

        remove = ['INTEHEAD', 'LOGIHEAD', 'DOUBHEAD','TABDIMS ', 'TAB     ','TNAVHEAD',
                  'IGRP    ', 'IWEL    ', 'SWEL    ', 'XWEL    ', 'ZWEL    ', 'ICON    ',
                  'SCON    ', 'XCON    ', 'STARTSOL','ENDSOL  ']

        for property_num in self.property:
            if property_num not in remove:
                self.property_combo.addItem(str(property_num))

        for i in range(len(self.dynamic_property)):
            if self.dynamic_property[i] not in self.property and self.dynamic_property[i] not in remove:
                self.property_combo.addItem(str(self.dynamic_property[i]))

        for time_step in list(dg.ts_reading().keys()):
            self.time_combo.addItem(time_step)

        self.export_combo.addItem('Раздельно')
        self.export_combo.addItem('Все регионы')

        self.method_combo.addItem('Сумма')
        self.method_combo.addItem('Среднее')
        self.method_combo.addItem('Средн.взвеш.(V)')
        self.method_combo.addItem('Средн.взвеш.(PORV)')
        self.method_combo.addItem('Плотность')
        self.method_combo.addItem('Минимум')

        self.region_combo.addItem('-')
        self.region_combo.addItem('FIPNUM')
        self.region_combo.addItem('EQLNUM')
        self.region_combo.addItem('PVTNUM')
        self.region_combo.addItem('SATNUM')
        self.region_combo.addItem('ROCKNUM')

        vlayout = QtWidgets.QVBoxLayout(self)
        vlayout.addWidget(self.button, alignment=QtCore.Qt.AlignHCenter)
        vlayout.addWidget(self.export_button, alignment=QtCore.Qt.AlignHCenter)
        self.browser.setMaximumHeight(680)
        vlayout.addWidget(self.browser)

        self.button.clicked.connect(self.show_graph)
        self.export_button.clicked.connect(self.export_cps)
        self.clear_cache_button.clicked.connect(dg.clear_cache)
        self.region_combo.currentIndexChanged.connect(self.num_region)
        self.resize(1000, 800)

        self.df_ijk, self.df_cps = dg.read_ijk()

        self.x_depart = dg.init_reading('DX')[0]
        self.y_depart = dg.init_reading('DY')[0]

        self.report_button.clicked.connect(self.report)

    def report(self):
        self.report_label = QtWidgets.QLabel('Тип отчета', self)
        time_report = self.time_combo.currentText()
        region_report = self.fip_combo.currentText()

        class MakeReport(QtWidgets.QWidget):
            def __init__(self, parent=None):
                super().__init__(parent)

                self.report_label = QtWidgets.QLabel('Тип отчета', self)

                self.report_1_button = QtWidgets.QPushButton('Общий отчет', self)
                self.report_2_button = QtWidgets.QPushButton('Для целей ПЗ', self)

                vlayout = QtWidgets.QVBoxLayout(self)
                vlayout.addWidget(self.report_label, alignment=QtCore.Qt.AlignHCenter)
                vlayout.addWidget(self.report_1_button)
                vlayout.addWidget(self.report_2_button)

                self.resize(200, 100)

                self.report_1_button.clicked.connect(self.report_1)

            def report_1(self):
                tic = time.perf_counter()
                if not os.path.isdir(dg.path_reports_export):
                    os.mkdir(dg.path_reports_export)

                if not os.path.isdir(dg.path_reports_export + '/01.Отчет_общий/'):
                    os.mkdir(dg.path_reports_export + '/01.Отчет_общий/')

                if not os.path.isdir(dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/'):
                    os.mkdir(dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/')

                if not dg.check_cache('cached/'+'df_report_1' + '_' + dg.model_name):
                    df, dummy = dg.read_ijk()
                    df.reset_index(inplace=True)
                    df['FIPNUM'] = dg.init_reading('FIPNUM')

                    df['Heff'] = np.array(dg.init_reading('NTG')) * np.array(dg.init_reading('DZ'))
                    df['VOL'] = np.array(dg.init_reading('DX')) * np.array(dg.init_reading('DY')) * np.array(
                        dg.init_reading('DZ'))
                    df['NTG'] = dg.init_reading('NTG')
                    df['PORO'] = dg.init_reading('PORO')
                    df['DZ'] = dg.init_reading('DZ')
                    df['DEPTH'] = dg.init_reading('DEPTH')
                    df['PERMX'] = dg.init_reading('PERMX')

                    for item in eclio.lazy_read(
                            dg.path_to_model + "/" + 'RESULTS/' + dg.model_name + '/' + dg.model_name + dg.x_files_list()[0]):
                        if 'FGIP' in item.read_keyword():
                            df['FGIP_init'] = item.read_array().astype(float)
                            print(df['FGIP_init'])

                    df.to_pickle('cached/'+'df_report_1' + '_' + dg.model_name)
                else:
                    df = pd.read_pickle('cached/'+'df_report_1' + '_' + dg.model_name).drop(columns='index')

                if not dg.check_cache('cached/'+'df_report_1' + '_' + dg.model_name + time_report):
                    df['SGAS'] = dg.unrst_reading('SGAS', time_report)
                    df['SOIL'] = dg.unrst_reading('SOIL', time_report)
                    df['FOIP'] = dg.unrst_reading('FOIP', time_report)
                    df['VOIP'] = dg.unrst_reading('VOIP', time_report)
                    df['FGIP'] = dg.unrst_reading('FGIP', time_report)
                    df['PRESSURE'] = dg.unrst_reading('PRESSURE', time_report)
                    df.to_pickle('cached/'+'df_report_1' + '_' + dg.model_name + time_report)
                else:
                    df = pd.read_pickle('cached/'+'df_report_1' + '_' + dg.model_name + time_report)

                region_number_list = dg.get_fip_dict(dg.path_to_fip_xlx)[region_report]

                index = ['Регион',
                         'Дата выгрузки',
                         'Средняя глубина залегания, м',
                         'Запасы свободного газа, млрд.м3',
                         'Запасы конденсата, тыс.т',
                         'Запасы нефти, тыс.т',
                         'Эффективный объем (газ), млн.м3',
                         'Эффективный поровый объем (газ), млн.м3',
                         'Эффективный поровый газонасыщенный объем, млн.м3',
                         'Эффективный объем (нефть), млн.м3',
                         'Эффективный поровый объем (нефть), млн.м3',
                         'Эффективный поровый нефтенасыщенный объем, млн.м3',
                         'Средн. эффективная газонасыщенная толщина, м',
                         'Средн. эффективная нефтенасыщенная толщина, м',
                         'Площадь газоносности, млн.м2',
                         'Площадь нефтеносности, млн.м2',
                         'Средн. пористость (газ), д.ед',
                         'Средн. пористость (нефть), д.ед',
                         'Средн. проницаемость (газ), мДарси',
                         'Средн. проницаемость (нефть), мДарси',
                         'Средн. газонасыщенность, д.ед',
                         'Средн. нефтенасыщенность, д.ед',
                         'Средн. пластовое давление (газ), бар',
                         'Средн. пластовое давление (нефть), бар']

                df_all = pd.DataFrame(index=index)
                df_all['0'] = range(24)

                df = df.query('FIPNUM in @region_number_list')

                df_gas = df.query('SGAS != 0')
                df_oil = df.query('SOIL != 0')

                df_all.iloc[0, 0] = region_report
                df_all.iloc[1, 0] = time_report
                df_all.iloc[2, 0] = round(df['DEPTH'].mean(),2)
                df_all.iloc[3, 0] = round(df['FGIP'].sum()/10**9,2)
                df_all.iloc[4, 0] = round(df['VOIP'].sum()/10**3,2)
                df_all.iloc[5, 0] = round(df['FOIP'].sum()/10**3,2)

                df_all.iloc[6, 0] = round(sum(df_gas['NTG'] * df_gas['VOL'])/10**6,2)
                df_all.iloc[7, 0] = round(sum(df_gas['NTG'] * df_gas['VOL'] * df_gas['PORO'])/10**6,2)
                df_all.iloc[8, 0] = round(sum(df_gas['NTG'] * df_gas['VOL'] * df_gas['PORO'] * df_gas['SGAS'])/10**6,2)

                df_all.iloc[9, 0] = round(sum(df_oil['NTG'] * df_oil['VOL'])/10**6,2)
                df_all.iloc[10, 0] = round(sum(df_oil['NTG'] * df_oil['VOL'] * df_oil['PORO'])/10**6,2)
                df_all.iloc[11, 0] = round(sum(df_oil['NTG'] * df_oil['VOL'] * df_oil['PORO'] * df_oil['SOIL'])/10**6,2)

                df_all.iloc[12, 0] = round(df_gas.groupby(['i', 'j'])['Heff'].sum().mean(),2)
                df_all.iloc[13, 0] = round(df_oil.groupby(['i', 'j'])['Heff'].sum().mean(),2)

                try:
                    df_all.iloc[14, 0] = round(df_all.iloc[6, 0] / df_all.iloc[12, 0],2)
                except ZeroDivisionError:
                    df_all.iloc[14, 0] = 0

                try:
                    df_all.iloc[15, 0] = round(df_all.iloc[9, 0] / df_all.iloc[13, 0],2)
                except ZeroDivisionError:
                    df_all.iloc[15, 0] = 0

                try:
                    df_all.iloc[16, 0] = round(df_all.iloc[7, 0] / df_all.iloc[6, 0],3)
                except ZeroDivisionError:
                    df_all.iloc[16, 0] = 0

                try:
                    df_all.iloc[17, 0] = round(df_all.iloc[10, 0] / df_all.iloc[9, 0],3)
                except ZeroDivisionError:
                    df_all.iloc[17, 0] = 0

                df_all.iloc[18, 0] = round(df_gas['PERMX'].mean(),2)
                df_all.iloc[19, 0] = round(df_oil['PERMX'].mean(),2)

                try:
                    df_all.iloc[20, 0] = round(df_all.iloc[8, 0] / df_all.iloc[7, 0],3)
                except ZeroDivisionError:
                    df_all.iloc[20, 0] = 0

                try:
                    df_all.iloc[21, 0] = round(df_all.iloc[11, 0] / df_all.iloc[10, 0],3)
                except ZeroDivisionError:
                    df_all.iloc[21, 0] = 0

                df_all.iloc[22, 0] = round(df_gas['PRESSURE'].mean(),2)
                df_all.iloc[23, 0] = round(df_oil['PRESSURE'].mean(),2)

                df_all.fillna(0, inplace=True)

                x_label = ['Начальные\n'+dg.get_key(dg.ts_reading(), dg.x_files_list()[0]), 'Текущие\n'+time_report]
                values = [round(df['FGIP_init'].sum()/10**9,2), round(df_all.iloc[3, 0],2)]

                def autolabel(rects, labels=None, height_factor=1.01):
                    try:
                        for i, rect in enumerate(rects):
                            height = rect.get_height()
                            if labels is not None:
                                try:
                                    label = labels[i]
                                except (TypeError, KeyError):
                                    label = ' '
                            else:
                                label = '%d' % int(height)
                            ax.text(rect.get_x() + rect.get_width() / 2., height_factor * height,
                                    '{}'.format(label),
                                    ha='center', va='bottom', size=20, weight='bold')
                    except IndexError:
                        pass

                bars = sns.barplot(x_label, values)
                ax = plt.gca()
                autolabel(ax.patches, values, height_factor=0.5)
                plt.ylabel('Запасы газа, млрд.м3')
                path_pic_1 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report +'_'+ time_report + '_RESERVES.PNG'
                plt.savefig(path_pic_1,transparent=True)
                plt.close()

                df_gas['SGAS'].plot.hist(bins=100, alpha=0.8)
                plt.title('Гистограмма газонасыщенности пласта ПК1')
                plt.ylabel('Кол-во')
                plt.xlabel('Газонасыщенность, д.ед')

                mean_gas = df_gas['SGAS'].mean()

                plt.axvline(mean_gas, color='k', linestyle='dashed', linewidth=1)
                min_ylim, max_ylim = plt.ylim()
                plt.text(mean_gas * 1.01, max_ylim * 0.9, 'Mean: {:.2f}'.format(mean_gas), weight='bold')
                path_pic_2 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report +'_'+ time_report + '_SGAS.PNG'
                plt.savefig(path_pic_2,transparent=True)
                plt.close()

                df['PORO'].plot.hist(bins=100, alpha=0.8)
                plt.title('Гистограмма пористости пласта ПК1')
                plt.ylabel('Кол-во')
                plt.xlabel('Пористость, д.ед')

                mean_poro = df['PORO'].mean()

                plt.axvline(mean_poro, color='k', linestyle='dashed',linewidth=1)
                min_ylim, max_ylim = plt.ylim()
                plt.text(mean_poro * 1.01, max_ylim * 0.9,'Mean: {:.2f}'.format(mean_poro), weight='bold')
                path_pic_3 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report +'_'+ time_report + '_PORO.PNG'
                plt.savefig(path_pic_3,transparent=True)

                colorscale_iso = [[0, "rgb(255, 255, 255)"], [1, 'rgb(129, 193, 129)']]  # isobar
                colorscale_heff = [[0, "rgb(255, 255, 255)"], [1, 'rgb(175, 104, 0)']]  # heffg
                colorscale_struct = [[0, "rgb(182, 255, 255)"], [0.5, "rgb(255, 253, 253)"],
                                     [1, 'rgb(255, 182, 182)']]  # structure
                colorscale_res = [[0, "rgb(255, 255, 255)"], [0.1, "rgb(182, 255, 255)"], [0.5, "rgb(252, 254, 185)"],
                                  [1, 'rgb(255, 146, 146)']]  # reserves

                def property_check(colorscale, property, property_rus, i, df):
                    if property != 'Heff':
                        fig = go.Figure()
                        fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
                        if property == 'PRESSURE':
                            df = df.groupby(['i', 'j'])[property].mean().reset_index()

                        elif property == 'DEPTH':
                            df = df.groupby(['i', 'j'])[property].min().reset_index()
                            df[property] *= -1
                        elif property == 'FGIP':
                            x_depart = dg.init_reading('DX')[0]
                            y_depart = dg.init_reading('DY')[0]
                            df = df.groupby(['i', 'j'])[property].sum()
                            df = df / (x_depart * y_depart)
                            df = df.reset_index()
                        fig.add_trace(
                            go.Contour(x=df['i'], y=df['j'], z=df[property],
                                       colorscale=colorscale, connectgaps=False,
                                       colorbar=dict(title=property_rus,
                                                     titleside='right',
                                                     titlefont=dict(size=14, family='Arial, sans-serif')),
                                       contours=dict(showlabels=True, labelfont=dict(size=12, color='black'))))

                    else:
                        fig = go.Figure()
                        fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
                        df = df.groupby(['i', 'j'])[property].sum().reset_index()
                        fig.add_trace(
                            go.Contour(x=df['i'], y=df['j'], z=df[property],
                                       colorscale=colorscale, connectgaps=False,
                                       colorbar=dict(title=property_rus,
                                                     titleside='right',
                                                     titlefont=dict(size=14, family='Arial, sans-serif')),
                                       contours=dict(showlabels=True, labelfont=dict(size=12, color='black'),
                                                     start=0, end=math.ceil(df[property].max()))))

                    fig.update_layout(
                        paper_bgcolor='rgba(0,0,0,0)',
                        plot_bgcolor='rgba(0,0,0,0)'
                    )
                    fig.update_yaxes(title='y', visible=False, showticklabels=False)
                    fig.update_xaxes(title='x', visible=False, showticklabels=False)
                    fig.write_image(dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report + '_'+ time_report +'_MAP_'+ property + '.PNG')
                    plt.close('all')

                color_list = [colorscale_iso,colorscale_heff,colorscale_struct,colorscale_res]
                property_list = ['PRESSURE', 'Heff', 'DEPTH', 'FGIP']
                property_rus_list = ['Давление, бар', 'Эфф.газ.толщина, м', 'Глубина, м', 'Плотность запасов газа, тыс.м3/м2']

                for i in range(len(property_list)):
                    print('начали цикл построения')
                    property_check(color_list[i], property_list[i], property_rus_list[i], i, df_gas)

                currencies_ppt = Presentation('templates/REPORT_1_template.pptx')
                slide = currencies_ppt.slides[0]

                shapes = slide.shapes

                for shape in shapes:
                    if shape.shape_type == 13:
                        shapes.element.remove(shape.element)

                pic1 = path_pic_1
                pic2 = path_pic_2
                pic3 = path_pic_3
                map1 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report + '_'+ time_report +'_MAP_'+ property_list[0] + '.PNG'
                map2 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report + '_'+ time_report +'_MAP_'+ property_list[1] + '.PNG'
                map3 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report + '_'+ time_report +'_MAP_'+ property_list[2] + '.PNG'
                map4 = dg.path_reports_export + '/01.Отчет_общий/' + 'PNG/' + region_report + '_'+ time_report +'_MAP_'+ property_list[3] + '.PNG'

                top_pic = slide.shapes.add_picture(pic1, Cm(8.7), Cm(1.1), width=Cm(8.5))
                mid_pic = slide.shapes.add_picture(pic2, Cm(8.7), Cm(6.8), width=Cm(8.5))
                bottom_pic = slide.shapes.add_picture(pic3, Cm(8.7), Cm(12.8), width=Cm(8.5))
                map1_pic = slide.shapes.add_picture(map1, Cm(16.6), Cm(2.5), width=Cm(8.7), height=Cm(7.5))
                map2_pic = slide.shapes.add_picture(map2, Cm(25.2), Cm(2.5), width=Cm(8.7), height=Cm(7.5))
                map3_pic = slide.shapes.add_picture(map3, Cm(25.2), Cm(11.2), width=Cm(8.7), height=Cm(7.5))
                map4_pic = slide.shapes.add_picture(map4, Cm(16.6), Cm(11.2), width=Cm(8.7), height=Cm(7.5))

                shapes = slide.shapes
                text_box_list = []
                auto_shape_list = []
                table_list = []
                place_holder_list = []
                for shape_idx in range(len(shapes)):
                    shape = shapes[shape_idx]
                    if shape.shape_type == 17:
                        text_box_list.append(shape_idx)
                    if shape.shape_type == 1:
                        auto_shape_list.append(shape_idx)
                    if shape.shape_type == 19:
                        table_list.append(shape_idx)
                    if shape.shape_type == 14:
                        place_holder_list.append(shape_idx)

                names = ['Карта изобар на ' + time_report,
                         'Карта плотности остаточных \nподвижных запасов газа на ' + time_report,
                         'Структурная карта на \n ' + time_report, 'Карта эфф.гн.толщин на ' + time_report]

                for i in range(len(text_box_list)):
                    paragraph = shapes[text_box_list[i]].text_frame.paragraphs[0]
                    paragraph.runs[0].text = names[i]

                paragraph = shapes[place_holder_list[1]].text_frame.paragraphs[0]
                paragraph.runs[0].text = 'Общий отчет по пласту '+ region_report +' на ' + time_report

                table = shapes[table_list[0]].table

                for i in range(len(df_all)):
                    cell = table.cell(i, 1)
                    paragraph = cell.text_frame.paragraphs[0]
                    run = paragraph.runs[0]
                    run.text = str(df_all.iloc[i,0])

                currencies_ppt.save(dg.path_reports_export + '/01.Отчет_общий/' + region_report + '_' + time_report + '_Общий_отчет.pptx')

        self.w3 = MakeReport()
        self.w3.show()

    def num_region(self):
        self.fip_combo.clear()
        self.fip_combo.addItem('ALL')

        if os.path.exists(dg.path_to_model + '/'+self.region_combo.currentText()+'.xlsx') is True:
            dg.path_to_fip_xlx = dg.path_to_model + '/'+self.region_combo.currentText()+'.xlsx'
        else:
            dg.path_to_fip_xlx = None

        if dg.path_to_fip_xlx == None and self.region_combo.currentText() != '-':
            for item in eclio.lazy_read(
                    dg.path_to_model + "/" + 'RESULTS/' + dg.model_name + '/' + dg.model_name + '.INIT'):
                if self.region_combo.currentText() in item.read_keyword():
                    for fip in list(set(item.read_array())):
                        self.fip_combo.addItem(str(fip))
        elif dg.path_to_fip_xlx == None and self.region_combo.currentText() == '-':
            self.fip_combo.clear()
            self.fip_combo.addItem('-регион не выбран-')
        else:
            for object in dg.get_fip_dict(dg.path_to_fip_xlx).keys():
                self.fip_combo.addItem(object)

    def show_graph(self):
        tic = time.perf_counter()
        self.df_ijk_plot = self.df_ijk.copy()
        self.df_ijk_plot.reset_index(drop=True, inplace=True)
        self.df_ijk_plot['region'] = dg.init_reading(self.region_combo.currentText())

        if self.property_combo.currentText() == 'Hэфф':
            dznet = dg.get_dznet()
            self.df_ijk_plot[self.property_combo.currentText()] = dznet

        elif self.property_combo.currentText() == 'Hэфф(газ)':
            dznet = dg.get_dznet()
            self.df_ijk_plot[self.property_combo.currentText()] = dznet
            self.df_ijk_plot['SGAS'] = dg.unrst_reading('SGAS', self.time_combo.currentText())
            self.df_ijk_plot = self.df_ijk_plot.query('SGAS != 0')
            self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['SGAS']

        elif self.property_combo.currentText() == 'Hэфф(нефть)':
            dznet = dg.get_dznet()
            self.df_ijk_plot[self.property_combo.currentText()] = dznet
            self.df_ijk_plot['SOIL'] = dg.unrst_reading('SOIL', self.time_combo.currentText())
            self.df_ijk_plot = self.df_ijk_plot.query('SOIL != 0')
            self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['SOIL']

        elif self.property_combo.currentText() == 'Hэфф(нефть/газ)':
            dznet = dg.get_dznet()
            self.df_ijk_plot[self.property_combo.currentText()] = dznet
            sgas = dg.unrst_reading('SGAS', self.time_combo.currentText())
            soil = dg.unrst_reading('SOIL', self.time_combo.currentText())
            shc = sgas + soil
            self.df_ijk_plot['SHC'] = shc
            self.df_ijk_plot = self.df_ijk_plot.query('SHC != 0')
            self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['SHC']

        elif self.property_combo.currentText() in self.dynamic_property:
            self.df_ijk_plot[self.property_combo.currentText()] = dg.unrst_reading(self.property_combo.currentText(), self.time_combo.currentText())
        else:
            self.df_ijk_plot[self.property_combo.currentText()] = dg.init_reading(self.property_combo.currentText())

        self.df_ijk_all = self.df_ijk_plot.copy()

        if dg.path_to_fip_xlx == None:
            if self.fip_combo.currentText() != 'ALL':
                fip = int(self.fip_combo.currentText())
                self.df_ijk_plot = self.df_ijk_plot.query('region == @fip')
            if self.method_combo.currentText() == 'Среднее':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].mean().reset_index()
            elif self.method_combo.currentText() == 'Сумма':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].sum().reset_index()
            elif self.method_combo.currentText() == 'Плотность':
                x_depart = dg.init_reading('DX')[0]
                y_depart = dg.init_reading('DY')[0]
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].sum()
                self.grid = self.grid / (self.x_depart * self.y_depart)
                self.grid = self.grid.reset_index()
            elif self.method_combo.currentText() == 'Средн.взвеш.(V)':
                self.df_ijk_plot['volume'] = dg.get_volume()
                self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['volume']
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText(),'volume'].sum()
                self.grid[self.property_combo.currentText()] = self.grid[self.property_combo.currentText()] / self.grid['volume']
                self.grid = self.grid.reset_index()
            elif self.method_combo.currentText() == 'Средн.взвеш.(PORV)':
                self.df_ijk_plot['volume'] = dg.init_reading('PORV')
                self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['volume']
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText(),'volume'].sum()
                self.grid[self.property_combo.currentText()] = self.grid[self.property_combo.currentText()] / self.grid['volume']
                self.grid = self.grid.reset_index()
            elif self.method_combo.currentText() == 'Минимум':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].min().reset_index()
                self.grid[self.property_combo.currentText()] = self.grid[self.property_combo.currentText()]*(-1)
        else:
            if self.fip_combo.currentText() != 'ALL':
                fip = dg.get_fip_dict(dg.path_to_fip_xlx)[self.fip_combo.currentText()]
                self.df_ijk_plot = self.df_ijk_plot.query('region in @fip')
            if self.method_combo.currentText() == 'Среднее':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].mean().reset_index()
            elif self.method_combo.currentText() == 'Сумма':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].sum().reset_index()
            elif self.method_combo.currentText() == 'Плотность':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].sum()
                self.grid = self.grid/(self.x_depart*self.y_depart)
                self.grid = self.grid.reset_index()
            elif self.method_combo.currentText() == 'Средн.взвеш.(V)':
                self.df_ijk_plot['volume'] = dg.get_volume()
                self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['volume']
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText(),'volume'].sum()
                self.grid[self.property_combo.currentText()] = self.grid[self.property_combo.currentText()] / self.grid['volume']
                self.grid = self.grid.reset_index()
            elif self.method_combo.currentText() == 'Средн.взвеш.(PORV)':
                self.df_ijk_plot['volume'] = dg.init_reading('PORV')
                self.df_ijk_plot[self.property_combo.currentText()] = self.df_ijk_plot[self.property_combo.currentText()] * self.df_ijk_plot['volume']
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText(),'volume'].sum()
                self.grid[self.property_combo.currentText()] = self.grid[self.property_combo.currentText()] / self.grid['volume']
                self.grid = self.grid.reset_index()
            elif self.method_combo.currentText() == 'Минимум':
                self.grid = self.df_ijk_plot.groupby(['i', 'j'])[self.property_combo.currentText()].min().reset_index()
                self.grid[self.property_combo.currentText()] = self.grid[self.property_combo.currentText()] * (-1)

        fig = go.Figure()
        config = dict({'scrollZoom': True})
        colorscale_iso = [[0, "rgb(255, 255, 255)"], [1, 'rgb(129, 193, 129)']] # isobar
        colorscale_heff = [[0, "rgb(255, 255, 255)"], [1, 'rgb(175, 104, 0)']] # heffg
        colorscale_struct = [[0, "rgb(182, 255, 255)"], [0.5, "rgb(255, 253, 253)"], [1, 'rgb(255, 182, 182)']] # structure
        colorscale_res = [[0, "rgb(255, 255, 255)"], [0.1, "rgb(182, 255, 255)"], [0.5, "rgb(252, 254, 185)"], [1, 'rgb(255, 146, 146)']] # reserves
        fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))

        def property_check(colorscale):
            fig.add_trace(go.Contour(x=self.grid['i'], y=self.grid['j'], z=self.grid[self.property_combo.currentText()],
                                     colorscale=colorscale, connectgaps=False,
                                     colorbar=dict(title=self.property_combo.currentText(),
                                                   titleside='right',
                                                   titlefont=dict(size=14, family='Arial, sans-serif')),
                                     contours=dict(showlabels=True, labelfont=dict(size=12, color='black'))))

        if 'PRESSURE' in self.property_combo.currentText():
            property_check(colorscale_iso)
        elif 'Hэфф' in self.property_combo.currentText():
            property_check(colorscale_heff)
        elif 'DEPTH' in self.property_combo.currentText():
            property_check(colorscale_struct)
        elif 'FIPGAS' in self.property_combo.currentText():
            property_check(colorscale_res)
        else:
            property_check('viridis_r')

        fig.update_layout(
            paper_bgcolor='rgba(0,0,0,0)',
            plot_bgcolor='rgba(0,0,0,0)'
        )
        fig.update_yaxes(title='y', visible=False, showticklabels=False)
        fig.update_xaxes(title='x', visible=False, showticklabels=False)

        self.browser.setHtml(fig.to_html(include_plotlyjs='cdn', config=config))

    def export_cps(self):
        dg.export_cps(self.export_combo.currentText(),self.grid,self.property_combo.currentText(),
                      self.df_cps,self.time_combo.currentText(),self.fip_combo.currentText(),
                      self.df_ijk_all,self.region_combo.currentText(),self.method_combo.currentText())


"""
Asynchronous python demonstration.
© 2021 Craig de Stigter; https://github.com/craigds
BSD 2-clause license.

Prerequisite:
    pip install -r requirements.txt
"""
import time
import asyncio

from aiohttp_requests import requests

async def get_url(url):
    print(f"starting to get {url}")
    start_time = time.monotonic()
    response = await requests.get(url)
    time_elapsed = time.monotonic() - start_time
    print(f"got {url} in {time_elapsed:.3f}s!")
    print()
    return response

async def main():
    start_time = time.monotonic()
    awaitables = []
    awaitables.append(get_url("http://example.com"))
    awaitables.append(get_url("http://example.com/a"))
    awaitables.append(get_url("http://example.com/b"))
    awaitables.append(get_url("http://example.com/c"))

    # wait for all the above, then do something else
    responses = await asyncio.gather(*awaitables)
    await get_url("http://example.com/final_url")

    time_elapsed = time.monotonic() - start_time
    print(f"did everything in {time_elapsed:.3f}s")

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())


"""Tool for the Google Scholar"""

from typing import Optional

from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool

from langchain_community.utilities.google_scholar import GoogleScholarAPIWrapper

class GoogleScholarQueryRun(BaseTool):
    """Tool that queries the Google search API."""

    name: str = "google_scholar"
    description: str = (
        "A wrapper around Google Scholar Search. "
        "Useful for when you need to get information about"
        "research papers from Google Scholar"
        "Input should be a search query."
    )
    api_wrapper: GoogleScholarAPIWrapper

    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)


import os

from fairseq.data import FileAudioDataset
from . import FairseqTask, register_task

@register_task('audio_pretraining')
class AudioPretrainingTask(FairseqTask):
    """

    """

    @staticmethod
    def add_args(parser):
        """Add task-specific arguments to the parser."""
        parser.add_argument('data', help='path to data directory')
        parser.add_argument('--sample-rate', default=16000, type=int,
                            help='target sample rate. audio files will be up/down sampled to this rate')
        parser.add_argument('--max-sample-size', default=None, type=int,
                            help='max sample size to crop to for batching. default = min sample length')
        parser.add_argument('--min-sample-size', default=None, type=int,
                            help='min sample size to crop to for batching. default = same as --max-sample-size')

    def __init__(self, args):
        super().__init__(args)

    @classmethod
    def setup_task(cls, args, **kwargs):
        """Setup the task (e.g., load dictionaries).

        Args:
            args (argparse.Namespace): parsed command-line arguments
        """
        return cls(args)

    def load_dataset(self, split, **kwargs):
        """Load a given dataset split.

        Args:
            split (str): name of the split (e.g., train, valid, test)
        """

        manifest = os.path.join(self.args.data, '{}.tsv'.format(split))
        self.datasets[split] = FileAudioDataset(manifest,
                                                 sample_rate=self.args.sample_rate,
                                                 max_sample_size=self.args.max_sample_size,
                                                 min_sample_size=self.args.min_sample_size)

    @property
    def target_dictionary(self):
        """Return the :class:`~fairseq.data.Dictionary` for the language
        model."""
        return None