import asyncio
import itertools
from typing import List, Optional, Tuple, Union

import pandas as pd

import util
from const import HoleDirection, IHSPath, ProdStatRange

__all__ = [
    "prodstat_option_matrix",
    "status_assignment_detail",
    "PRODSTAT_DEFAULT_OPTIONS",
    "PRODSTAT_DEFAULT_RATIO_OPTIONS",
]

def prodstat_option_matrix(
    ranges: Union[ProdStatRange, List[ProdStatRange]],
    months: Optional[Union[int, List[int]]],
    include_zeroes: Union[bool, List[bool]] = [True, False],
) -> List[Tuple[ProdStatRange, int, bool]]:
    return list(
        itertools.product(
            util.ensure_list(ranges),
            util.ensure_list(months),
            util.ensure_list(include_zeroes),
        )
    )

def status_assignment_detail(
    hole_dir: Union[HoleDirection, str], api14s: List[str]
) -> Tuple[pd.DataFrame, pd.DataFrame]:
    hole_dir = HoleDirection(hole_dir)

    async def coro() -> Tuple[pd.DataFrame, pd.DataFrame]:

        wells, *other = await pd.DataFrame.wells.from_multiple(
            hole_dir=hole_dir, api14s=api14s
        )

        # TODO: Move to Router
        if hole_dir == HoleDirection.H:
            prodpath = IHSPath.prod_h_headers
        elif hole_dir == HoleDirection.V:
            prodpath = IHSPath.prod_v_header
        else:
            raise ValueError(f"cant determine IHSPath from hole_dir ({hole_dir})")

        prod_headers = await wells.wells.last_prod_date(
            path=prodpath, prefer_local=False
        )
        wells = wells.join(prod_headers)
        indicators = wells.wells.assign_status(detail=True)
        print(f"\n{indicators.T}\n")
        labels = wells.wells.assign_status(detail=True, as_labels=True)
        print(f"\n{labels.T}\n")
        return indicators, labels

    loop = asyncio.get_event_loop()
    return loop.run_until_complete(coro())

PRODSTAT_DEFAULT_OPTIONS: frozenset = frozenset(  # TODO: define this in config somehow?
    itertools.chain(
        prodstat_option_matrix(
            ProdStatRange.FIRST, months=[1, 3, 6, 9, 12, 18, 24, 30, 36, 42, 48],
        ),
        prodstat_option_matrix(ProdStatRange.LAST, months=[1, 3, 6, 12],),
        prodstat_option_matrix(ProdStatRange.PEAKNORM, months=[1, 3, 6],),
        prodstat_option_matrix(ProdStatRange.ALL, months=None),
    )
)

PRODSTAT_DEFAULT_RATIO_OPTIONS: frozenset = frozenset(
    itertools.chain(
        prodstat_option_matrix(ProdStatRange.FIRST, months=[1, 3, 6, 9, 12, 18, 24]),
        prodstat_option_matrix(ProdStatRange.LAST, months=[1, 3, 6]),
        prodstat_option_matrix(ProdStatRange.PEAKNORM, months=[1, 3, 6]),
        prodstat_option_matrix(ProdStatRange.ALL, months=None),
    )
)

if __name__ == "__main__":
    api14s = [
        "42461409160000",
        "42383406370000",
        "42461412100000",
        "42461412090000",
        "42461411750000",
        "42461411740000",
        "42461411730000",
        "42461411720000",
        "42461411600000",
        "42461411280000",
        "42461411270000",
        "42461411260000",
        "42383406650000",
        "42383406640000",
        "42383406400000",
        "42383406390000",
        "42383406380000",
        "42461412110000",
        "42383402790000",
    ]

    status_assignment_detail(hole_dir="H", api14s=api14s)


import sys
sys.path.append('gen-py')

import datetime

from task_gateway import TaskGateway

from thrift.transport import TSocket, TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

class TaskGatewayHandler(TaskGateway.Iface):

    def create_task(self, task):
        print("Task with identifier {task.identifier}, and name ``{task.name}``, created\n".format(task=task))
        with open(task.filename, 'wb') as storage_file:
            storage_file.write(task.file)
        print("Task execution saved as ``{task.filename}``\n".format(task=task))
        task.created_at = datetime.datetime.now().astimezone().isoformat()
        return task

if __name__ == '__main__':
    handler = TaskGatewayHandler()
    processor = TaskGateway.Processor(handler)
    transport = TSocket.TServerSocket(port=9090)
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

    print('Starting the TaskGateway server...')
    server.serve()


# -*- coding: utf-8 -*-

"""Additional profile for OnTaskUsers."""
from django.contrib.auth import get_user_model
from django.db import models

class OnTaskUser(models.Model):
    """Extend the existing authtools.User with additional fields."""

    # OneToOne relationship with the authentication model
    user = models.OneToOneField(
        get_user_model(),
        on_delete=models.CASCADE,
        related_name='ontask_info',
        primary_key=True,
    )

    def is_instructor(self) -> bool:
        """Return boolean with is_instructor answer."""
        return (
            self.user.is_authenticated
            and (
                self.user.groups.filter(name='instructor').exists()
                or self.user.is_superuser
            )
        )

    def __str__(self) -> str:
        """Provide string representation (email)."""
        return self.user.email

    class Meta:
        """Additional attributes for the model."""

        verbose_name = 'ontaskuser'
        verbose_name_plural = 'ontaskusers'


#cluster mode
# spark-submit --master yarn --deploy-mode cluster binomial_logistic_regression.py

#local mode
# spark-submit binomial_logistic_regression.py

from pyspark.ml.classification import LogisticRegression
from pyspark.sql import SparkSession
from datetime import datetime

start_time = datetime.now()
print("Program started : ",start_time)

#spark = SparkSession.builder.appName("ML-DEMO").getOrCreate()

#training = spark.read.format("libsvm").load("data_mllib_sample_libsvm_data.txt")
# Load training data
training_lr = spark.read.format("libsvm").load("data_mllib_sample_libsvm_data_large.txt")

logreg = LogisticRegression(maxIter=10, regParam=0.3, elasticNetParam=0.8)

# Fit the model
lrModel = logreg.fit(training_lr)

# Print the coefficients and intercept for logistic regression
print("Coefficients: " + str(lrModel.coefficients))
print("Intercept: " + str(lrModel.intercept))

# We can also use the multinomial family for binary classification
mlogreg = LogisticRegression(maxIter=10, regParam=0.3, elasticNetParam=0.8, family="multinomial")

# Fit the model
mlrModel = mlogreg.fit(training_lr)

# Print the coefficients and intercepts for logistic regression with multinomial family
print("Multinomial coefficients: " + str(mlrModel.coefficientMatrix))
print("Multinomial intercepts: " + str(mlrModel.interceptVector))

end_time = datetime.now()
print("Program end : ",end_time)

time_taken = end_time -start_time
print("Total time taken in minuntes",int(time_taken.seconds))


import sys

from PyQt5 import QtWidgets as qw
from qt_material import apply_stylesheet

from miniPoly.core.minion import TimerMinion

class AbstractGUIAPP(TimerMinion):
    def __init__(self, name, compiler, refresh_interval=10, **kwargs):
        super(AbstractGUIAPP, self).__init__(name, refresh_interval)
        self._param_to_compiler = kwargs
        self._compiler = compiler

    def initialize(self):
        self._app = qw.QApplication(sys.argv)
        apply_stylesheet(self._app, theme='dark_red.xml')
        super().initialize()
        self._compiler = self._compiler(self, **self._param_to_compiler)
        self.info(f"GUI '{self.name}' initialized")
        self._compiler.show()

    def on_time(self,t):
        self._app.processEvents()
        self.poll_GUI_windows()

    def poll_GUI_windows(self):
        win_status = []
        for win in self._app.allWindows():
            win_status.append(win.isVisible())
        if not any(win_status):
            self.shutdown()

    def shutdown(self):
        def kill_minion(minion_name):
            self.set_state_to(minion_name, 'status', -1)

        safe_to_shutdown = False
        while not safe_to_shutdown:
            minion_status = self.poll_minion(kill_minion)
            if not any(minion_status):
                safe_to_shutdown = True

        self.status = -1


# -*- coding:utf-8 -*-
from typing import List

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    def pathSum(self, root: TreeNode, sum_value: int) -> List[List[int]]:
        if root is None: return []

        from copy import deepcopy
        self.paths, self.path = [], []

        def helper(root, sum_value):
            if root is None:
                return None

            self.path.append(root.val)
            helper(root.left, sum_value)
            helper(root.right, sum_value)
            if sum(self.path) == sum_value and root.left is None and root.right is None:
                self.paths.append(deepcopy(self.path))

            self.path.pop()

        helper(root, sum_value)
        return self.paths

if __name__ == '__main__':
    # t1 = TreeNode(5)
    # t2 = TreeNode(4)
    # t3 = TreeNode(8)
    # t4 = TreeNode(11)
    # t5 = TreeNode(13)
    # t6 = TreeNode(4)
    # t7 = TreeNode(7)
    # t8 = TreeNode(2)
    # t9 = TreeNode(5)
    # t10 = TreeNode(1)
    # t1.left = t2
    # t1.right = t3
    # t2.left = t4
    # t3.left = t5
    # t3.right = t6
    # t4.left = t7
    # t4.right = t8
    # t6.left = t9
    # t6.right = t10
    # sum_value = 22

    t1 = TreeNode(1)
    t2 = TreeNode(2)
    t1.left = t2
    sum_value = 1
    ans = Solution().pathSum(t1, sum_value)
    print(ans)

34.二叉树中和为某一值的路径.py


import logging

class Module:
    """Base class used for modules in a pipeline.
    """

    def __init__(self):
        """Module initialization
        """
        self.logger = logging.getLogger()
        self.features = []
        self.feature_begins_with = []
        self.ignore_features = []

    def set_logger(self, logger):
        """ Set logger of module

        :param logger: input logger
        """
        self.logger = logger

    def get_datastore_object(self, datastore, feature, dtype, default=None):
        """Get object from datastore.

        Bit more advanced than dict.get()

        :param dict datastore: input datastore
        :param str feature: key of object to retrieve
        :param obj dtype: required datatype of object. Could be specific data type or tuple of dtypes
        :param obj default: object to default to in case key not found.
        :return: retrieved object
        """
        obj = datastore.get(feature)
        if obj is None:
            if default is not None:
                obj = default
            else:
                raise RuntimeError(f"`{feature}` not found in the datastore!")
        if not isinstance(obj, dtype):
            raise RuntimeError(f"obj `{feature}` is not an instance of `{dtype}`!")
        return obj

    def get_features(self, all_features):
        """Get all features that meet feature_begins_with and ignore_features requirements

        :param list all_features: input features list
        :return: pruned features list
        :rtype: list
        """
        all_features = sorted(all_features)
        features = self.features
        if not self.features:
            features = all_features
        if self.feature_begins_with:
            features = [k for k in features if k.startswith(self.feature_begins_with)]
        if self.ignore_features:
            features = [k for k in features if k not in self.ignore_features]

        features_not_in_input = [
            feature for feature in features if feature not in all_features
        ]
        features = [feature for feature in features if feature in all_features]

        for feature in features_not_in_input:
            self.logger.warning(f'Feature "{feature}" not in input data; skipping.')

        return features

    def transform(self, datastore):
        """Central function of the module.

        Typically transform() takes something from the datastore, does something to it, and puts the results
        back into the datastore again, to be passed on to the next module in the pipeline.

        :param dict datastore: input datastore
        :return: updated output datastore
        :rtype: dict
        """
        return datastore


from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('register/', views.register, name='register'),
    path('registration-edit/<int:id>', views.regEdit, name='regEdit'),
    path('verify/<str:id>', views.regVerification, name='regVerification'),
    path('thank-you/<str:id>', views.thankyou, name='thankyou'),

    path('search/', views.search, name='search'),
    path('search-results/', views.searchResults, name='searchResults')
]


from django.urls import path
from . import views

urlpatterns = [
    # path('',views.read, name="home"),
    path('new/',views.create, name="new"),
    path('update/<int:pk>',views.update, name="update"),
    path('delete/<int:pk>',views.delete, name="delete"),
    path('detail/<int:pk>',views.detail, name="detail"),
    path('comment_delete/<int:pk>/<int:comment_id>', views.comment_delete, name="comment_delete"),
    path('comment_edit/<int:comment_id>', views.comment_edit, name="comment_edit"),
]


from fastapi import FastAPI, APIRouter, Request, Response
# importamos los archivos de la carpeta router
from backend.routers import users, audio, reproducir, copyright, count, artista, canciones, facturacion_pagos, personas
from fastapi.responses import FileResponse
# Nos permite exponer archivos estaticos como archivos HTML
from fastapi.staticfiles import StaticFiles

app = FastAPI()

# Creamos un objeto APIRouter para envolver la lista de routers
router = APIRouter()

# Agregamos los routers a la ruta
router.include_router(artista.router)
router.include_router(audio.router)
router.include_router(canciones.router)
router.include_router(facturacion_pagos.router)
router.include_router(personas.router)
router.include_router(users.router)
router.include_router(copyright.router)
router.include_router(count.router)
router.include_router(reproducir.router)#127.0.0.1:8000/reproducir/<<El Nombre de la cancion>>

# Incluimos el router en la aplicación FastAPI
app.include_router(router)

# Routers
#app.include_router([products.router, users.router, audio.router])

#Va a reproducir los auidos que tengamos en la carpeta audios, http://127.0.0.1:8000/audios/<<El Nombre de la cancion>>
app.mount("/audios", StaticFiles(directory="backend/audios"), name="audios")#Al momento de poner http://127.0.0.1:8000/static y el nombre de la carpeta y el nombre del archivo tiene que verse o exponerse
app.mount("/static", StaticFiles(directory="backend/static"), name="static")

#url local: http://127.0.0.1:8000

@app.get("/")
async def root(request: Request):
    return FileResponse('backend/static/templates/index.html')

#Esto es para que no salga el error de "Get /favicon.ico HTTP/1.1" 404 Not Found
@app.get("/favicon.ico")
async def favicon():
    return Response(content="", media_type="image/x-icon")


#! /usr/bin/env python
import boto
import re

CACHE_CONTROL_VALUE = "max-age=" + str(60*60*24*30) #one month
BUCKET_NAME = 'highlandadventures'
print(CACHE_CONTROL_VALUE)
print(BUCKET_NAME)

s3 = boto.connect_s3()
bucket = s3.get_bucket(BUCKET_NAME)
rs = bucket.list()

def update_img_metadata(key):
    if key.name.lower().endswith('.jpg'):
        contentType = 'image/jpeg'
    elif key.name.lower().endswith('.png'):
        contentType = 'image/png'
    elif key.name.lower().endswith('.gif'):
        contentType = 'image/gif'
    else:
        contentType = None

    if contentType is not None:
        key.metadata.update({
            'Content-Type': contentType,
            'Cache-Control': CACHE_CONTROL_VALUE
            })
        #need the following to push up to S3 otherwise just local change
        key.copy(
            key.bucket.name,
            key.name,
            key.metadata,
            preserve_acl=True
            )
        return key
    else:
        print("skipping mera image update: " + key.name)
        return None

for key in rs:
    update_img_metadata(key)


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

import numpy as np
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "3"
import scanpy as sc
import pandas as pd
import torch
import scipy
import time
from STEM.model import *
from STEM.utils import *

scdata = pd.read_csv('./data/mousedata_2020/E1z2/simu_sc_counts.csv',index_col=0)
scdata = scdata.T
stdata = pd.read_csv('data/mousedata_2020/E1z2/simu_st_counts.csv',index_col=0)
stdata = stdata.T
stgtcelltype = pd.read_csv('./data/mousedata_2020/E1z2/simu_st_celltype.csv',index_col=0)
spcoor = pd.read_csv('./data/mousedata_2020/E1z2/simu_st_metadata.csv',index_col=0)
scmetadata = pd.read_csv('./data/mousedata_2020/E1z2/metadata.csv',index_col=0)

adata = sc.AnnData(scdata,obs=scmetadata)
sc.pp.normalize_total(adata)
sc.pp.log1p(adata)
scdata = pd.DataFrame(adata.X,index=adata.obs_names,columns=adata.var_names)
stadata = sc.AnnData(stdata)
sc.pp.normalize_total(stadata)
sc.pp.log1p(stadata)
stdata = pd.DataFrame(stadata.X,index=stadata.obs_names,columns=stadata.var_names)

adata.obsm['spatial'] = scmetadata[['x_global','y_global']].values
stadata.obsm['spatial'] = spcoor

sc.pp.calculate_qc_metrics(adata,percent_top=None, log1p=False, inplace=True)
adata.obs['n_genes_by_counts'].median()

sc.pp.calculate_qc_metrics(stadata,percent_top=None, log1p=False, inplace=True)
stadata.obs['n_genes_by_counts'].median()

dp = 1- adata.obs['n_genes_by_counts'].median()/stadata.obs['n_genes_by_counts'].median()

class setting( object ):
    pass
seed_all(2022)
opt= setting()
setattr(opt, 'device', 'cuda:0') # device
setattr(opt, 'outf', 'log/test') # folder to save log files
setattr(opt, 'n_genes', 351) # number of genes for the input
setattr(opt, 'no_bn', False) # duplicated
setattr(opt, 'lr', 0.002) # learning rate
setattr(opt, 'sigma', 3)  # the spatial variance parameter in the Gaussian function
setattr(opt, 'alpha', 0.8) # MMD loss weight default:0.8
setattr(opt, 'verbose', True) # verbose
setattr(opt, 'mmdbatch', 1000) # batch for MMD loss
setattr(opt, 'dp', dp) # dropout rate for ST data

testmodel = SOmodel(opt)
testmodel.togpu()
loss_curve = testmodel.train_wholedata(400,torch.tensor(scdata.values).float(),torch.tensor(stdata.values).float(),torch.tensor(spcoor.values).float())

testmodel.modeleval()
scembedding = testmodel.netE(torch.tensor(scdata.values,dtype=torch.float32).cuda())
stembedding = testmodel.netE(torch.tensor(stdata.values,dtype=torch.float32).cuda())
netst2sc = F.softmax(stembedding.mm(scembedding.t()),dim=1).detach().cpu().numpy()
netsc2st = F.softmax(scembedding.mm(stembedding.t()),dim=1).detach().cpu().numpy()

# np.save('result/230215_testdp_pure_mmd-E1z2.npy',netst2sc)
# np.save('result/230215_testdp_pure_sc2st_mmd-E1z2.npy',netsc2st)
# np.save('result/230215_scembbedding-E1z2.npy',scembedding.detach().cpu().numpy())
# np.save('result/230215_stembbedding-E1z2.npy',stembedding.detach().cpu().numpy())


import argparse
import os
import json
import logging
import torch

from seq_simul.statistics.seq_statistics import get_indelsub_statitstics
from seq_simul.utils.align import align_list, mean_editdistance, remove_pads
from seq_simul.utils.convert import convert_onehot_to_read

def get_default_args(parser):
    # DO NOT USE THIS FUNCTION
    # This function is used to record and interpret default values
    # General model/training related parameters
    parser.add_argument("--gpu_num", type=int, default=None,
                        help="GPU ID to use while training")
    parser.add_argument("--total_epoch", type=int, default=1,
                        help="total epoch of training iteration")
    parser.add_argument("--batch_num", type=int, default=5,
                        help="batch size of data")
    parser.add_argument("--b1", type=float, default=0.5,
                        help="ADAM: decay of first order momentum of gradient")
    parser.add_argument("--b2", type=float, default=0.999,
                        help="ADAM: decay of second order momentum of gradient")
    parser.add_argument("--drop_prob", type=float, default=0,
                        help="probability of dropout")
    parser.add_argument("--lambda_gp", type=float, default=0,
                        help="lambda of gradient penalty for WGAN-GP")

    # Data related paramters
    parser.add_argument("--datapath", type=str, default="seq_simul/data/oligo_data/",
                        help="location of dataset folder")

    # Discriminator related parameters
    parser.add_argument("--D_CNN_kernel", type=int, default=3,
                        help="size of kernel in CNN Discriminator")
    parser.add_argument("--D_CNN_padding", type=int, default=1,
                        help="zero-pads added to both sides of the input")
    parser.add_argument("--D_critic", type=int, default=1,
                        help="number of training steps for generator per iteration")
    parser.add_argument("--D_model", type=str, default="GRU",
                        help="Discriminator model (GRU|CNN)")
    parser.add_argument("--D_hidden_size", type=int, default=20,
                        help="hidden size of Discriminator")
    parser.add_argument("--D_init_param_fname", type=str, default=None,
                        help="pretrained parameters file path for Discriminator `*.pth`")
    parser.add_argument("--D_lr", type=float, default=0.00005,
                        help="Discriminator learning-rate")
    parser.add_argument("--D_num_layer", type=int, default=2,
                        help="number of layers in Discriminator")

    # Generator related parameters
    parser.add_argument("--G_bidirectional", type=bool, default=True,
                        help="define GRU Generator's bidirectional")
    parser.add_argument("--G_critic", type=int, default=1,
                        help="number of training steps for discriminator per iter")
    parser.add_argument("--G_CNN_kernel", type=int, default=3,
                        help="size of kernel in CNN generator")
    parser.add_argument("--G_CNN_padding", type=int, default=1,
                        help="zero-pads added to both sides of the input")
    parser.add_argument("--G_model", type=str, default="GRU",
                        help="Generator model (GRU|CNN)")
    parser.add_argument("--G_hidden_size", type=int, default=50,
                        help="hidden size of both GRU and CNN Generator")
    parser.add_argument("--G_init_param_fname", type=str, default=None,
                        help="file name that contains initilize parameters for Generator")
    parser.add_argument("--G_input_size", type=int, default=9,
                        help="input shape of GRU Generator")
    parser.add_argument("--G_lr", type=float, default=0.00005,
                        help="Generator learning-rate")
    parser.add_argument("--G_num_layer", type=int, default=3,
                        help="number of layers in both GRU and CNN Generator")

    # Alignment related parameters
    parser.add_argument("--gap_cost", type=int, default=-1,
                        help="the score when deletion or insertion occurred.")
    parser.add_argument("--match_score", type=int, default=1,
                        help="In the Needleman-Wunsch algorithm, it is expressed as"
                             "the score when the two letters at the current index are the same.")
    parser.add_argument("--mismatch_score", type=int, default=-1,
                        help="In the Needleman-Wunsch algorithm, it is expressed as"
                             "the score when the two letters at the current index are different.")

    # Data structure related parameters
    parser.add_argument("--padding_num", type=int, default=9,
                        help="number of pads to equalize the length of reads")
    parser.add_argument("--oligo_len", type=int, default=3,
                        help="length of the oligo sequence")
    parser.add_argument("--qscore_bias", type=int, default=33,
                        help="number of element for normalize."
                             "33 is the ASCII number of the starting character '!' of qscore.")
    parser.add_argument("--qscore_range", type=int, default=38,
                        help="Number of element for normalize."
                             "38 is the number of types of qscore characters.")

    # Qscore-only related parameters
    parser.add_argument("--qscore_max_len", type=int, default=50,
                        help="maximum length of aligned read and qscore for padding")
    parser.add_argument("--qscore_pad", type=str, default="!",
                        help="symbol of pad in quality score")

    # Display related parameters
    parser.add_argument("--result_num", type=int, default=3,
                        help="number of generated result at every epoch")
    parser.add_argument("--verbose", type=bool, default=True,
                        help="if True, print out training process and save in log file."
                             "if False,just save in log file")

    opt = parser.parse_args()

    return opt

def save_args(opt, args_fname):
    with open(args_fname, 'w') as f:
        json.dump(opt.__dict__, f, indent=2)

def update_args(opt, fname):
    with open(fname, 'r') as f:
        target_dict = json.load(f)

    opt_dict = vars(opt)
    valid_keys = opt_dict.keys()

    # update opt for fixed values
    target_keys = target_dict.keys()
    for key in target_keys:
        if key in valid_keys:
            opt_dict[key] = target_dict[key]

    opt = argparse.Namespace(**opt_dict)

    return opt

def load_default():
    default_args_fname = 'seq_simul/data/default_args.json'
    return load_args(default_args_fname)

def load_args(fname):
    with open(fname, 'r') as f:
        opt_dict = json.load(f)

    opt = argparse.Namespace(**opt_dict)

    return opt

def output_processing(oligos, output, opt, read_only=True):
    # Process output data to get sequence
    # Convert oligos onehot to read
    gen_reads, gen_qscores = convert_onehot_to_read(output, opt.qscore_bias,
                                                    opt.qscore_range, read_only)

    # Ignore the padding symbol 'P'
    oligo_no_pad, read_no_pad, qscores_no_pad = remove_pads(oligos, gen_reads,
                                                            gen_qscores, read_only)
    # Align generated reads with oligos
    aligned_read, aligned_oligo, aligned_qscore = \
        align_list(read_no_pad, oligo_no_pad, read_only, qscores=qscores_no_pad)

    # Caculate edit distance and errors
    mean_distance = mean_editdistance(aligned_oligo, aligned_read)
    insertion, deletion, substitution = \
        get_indelsub_statitstics(aligned_read, aligned_oligo)

    return aligned_read, aligned_oligo, insertion, deletion, substitution, mean_distance

def save_output(result_oligo, result_read, idx, interval, opt,
                epoch, dataloader, loss_1, loss_2,
                insertion, deletion, substitution, mean_distance):
    r"""
        Save training output to log file
        loss_1 is Training loss, loss_2 is Validation loss when the model is Transformer
        loss_1 is Generator loss, loss_2 is Discriminator loss when the model is GAN
    """
    # Save training output to log file at every epoch
    if idx % interval == 0:
        for i in range(opt.result_num):
            train_msg = f'original oligo         : {result_oligo[i]}\n' \
                        f'generated read         : {result_read[i]}\n'
            logging.debug(train_msg)

            # Print out training output
            if opt.verbose and i < 10:
                print(f'original oligo         : {result_oligo[i]}\n'
                      f'generated read         : {result_read[i]}\n')

    # Save training loss to log file
    log_msg = f'[Epoch:{epoch+1}/{opt.total_epoch}],' \
              f'[Batch:{idx+1}/{len(dataloader)}],'

    log_msg += f'[G_loss: {loss_1.item()}],' \
               f'[D_loss: {loss_2.item()}],'

    log_msg += f'[ins/del/sub: {insertion}/{deletion}/{substitution}],' \
               f'[Mean of edit distance: {mean_distance}]'
    logging.debug(log_msg)

    return log_msg

def save_statistics(number, statistics_dict, epoch, idx, loss_1, loss_2, mean_distance,
                    insertion, deletion, substitution, symbol_num, opt):
    r"""
        Save statistics information
        loss_1 is Training loss, loss_2 is Validation loss when the model is Transformer
        loss_1 is Generator loss, loss_2 is Discriminator loss when the model is GAN
    """
    statistics_dict.setdefault('epoch', []).append(epoch + 1)
    statistics_dict.setdefault('batch', []).append(idx + 1)
    statistics_dict.setdefault('gloss', []).append(loss_1.item())
    statistics_dict.setdefault('dloss', []).append(loss_2.item())
    statistics_dict.setdefault('distance', []).append(mean_distance)
    statistics_dict.setdefault('ins', []).append(insertion / symbol_num * 100)
    statistics_dict.setdefault('del', []).append(deletion / symbol_num * 100)
    statistics_dict.setdefault('sub', []).append(substitution / symbol_num * 100)
    statistics_dict.setdefault('No', []).append(number)

    return statistics_dict, number

def save_checkpoint(error_name, G, D, optimizer_G, optimizer_D, epoch,
                    ins_num, del_num, sub_num, save_path, log_fname):
    r"""
        This function saves pure-error-occurred checkpoint file.
    """
    if error_name == 'insertion' and (del_num == 0 and sub_num == 0):
        save_pth(G, D, optimizer_G, optimizer_D, epoch, save_path, log_fname)
    elif error_name == 'deletion' and (ins_num == 0 and sub_num == 0):
        save_pth(G, D, optimizer_G, optimizer_D, epoch, save_path, log_fname)
    elif error_name == 'substitution' and (ins_num == 0 and del_num == 0):
        save_pth(G, D, optimizer_G, optimizer_D, epoch, save_path, log_fname)
    elif error_name == 'oligo_data':
        save_pth(G, D, optimizer_G, optimizer_D, epoch, save_path, log_fname)
    else:
        save_pth(G, D, optimizer_G, optimizer_D, epoch, save_path, log_fname)

def save_pth(G, D, optimizer_G, optimizer_D, epoch, save_path, log_fname):
    r"""
        This function saves the end of the epoch pth file
    """
    check_point_G = {'G_state_dict': G.state_dict(), 'G_optimizer': optimizer_G.state_dict()}
    check_point_D = {'G_state_dict': D.state_dict(), 'D_optimizer': optimizer_D.state_dict()}

    G_param_fname = os.path.join(save_path, log_fname + f'_epoch{epoch:03d}_Generator.pth')
    D_param_fname = os.path.join(save_path, log_fname + f'_epoch{epoch:03d}_Discriminator.pth')
    torch.save(check_point_G, G_param_fname)
    torch.save(check_point_D, D_param_fname)


from functools import cached_property
from typing import Tuple

import numpy as np

from zonda import excepciones
from zonda.cirsoc import geometria
from zonda.enums import (
    TipoPresionCubiertaAislada,
    ExtremoPresion,
    ZonaPresionCubiertaAislada,
    PosicionBloqueoCubierta,
    TipoCubierta,
)
from zonda.tipos import ValoresCpCubiertaAislada

class CubiertaAislada:
    """CubiertaAislada.

    Determinar los coeficientes de presión neta de cubiertas aisladas.
    """

    def __init__(
        self,
        tipo_cubierta: TipoCubierta,
        angulo: float,
        relacion_bloqueo: float,
        posicion_bloqueo: PosicionBloqueoCubierta,
    ) -> None:
        """

        Args:
            tipo_cubierta: El tipo de cubierta.
            angulo: El ángulo de la cubierta.
            relacion_bloqueo: La relación de bloqueo de la cubierta.
            posicion_bloqueo: Las posicion de bloqueo de la cubierta. Solo es usada cuando la cubierta es a un agua.

        Raises:
            ErrorLineamientos si el -5° < angulo < 5°.
            ValueError si la relación de bloque no está entre 0 y 1.
        """
        if not 0 <= relacion_bloqueo <= 1:
            raise ValueError("La relación de bloqueo debe ser un valor entre 0 y 1")
        if tipo_cubierta not in (TipoCubierta.DOS_AGUAS, TipoCubierta.UN_AGUA):
            raise excepciones.ErrorLineamientos(
                "El Reglamento solo provee lineamientos para calcular los coeficientes de presión neta para cubiertas"
                " a dos aguas y a un agua."
            )
        if -5 < angulo < 5 and tipo_cubierta == TipoCubierta.DOS_AGUAS:
            raise excepciones.ErrorLineamientos(
                "El Reglamento no provee lineamientos para calcular los coeficientes de presión neta para cubiertas aisladas"
                f" a dos aguas con ángulo igual a {angulo:.2f}°."
            )
        if not 0 <= angulo <= 30 and tipo_cubierta == TipoCubierta.UN_AGUA:
            raise excepciones.ErrorLineamientos(
                "El Reglamento no provee lineamientos para calcular los coeficientes de presión neta para cubiertas aisladas"
                f" a un agua con ángulo igual a {angulo}°."
            )

        self.tipo_cubierta = tipo_cubierta
        self.angulo = angulo
        self.relacion_bloqueo = relacion_bloqueo
        self.posicion_bloqueo = posicion_bloqueo

    @cached_property
    def referencia(self) -> str:
        """Obtiene la referencia de la tabla del reglamento.

        Returns:
            La referencia de la tabla del reglamento desde donde se calculan los valores.
        """
        if self.tipo_cubierta == TipoCubierta.UN_AGUA:
            return "Tabla I.1"
        return "Tabla I.2"

    @cached_property
    def valores(
        self,
    ) -> ValoresCpCubiertaAislada:
        """Calcula los factores cpn para la cubierta.

        Returns:
            Los factores cpn.
        """
        if self.tipo_cubierta == TipoCubierta.UN_AGUA:
            return self._cpn_un_agua()
        return self._cpn_dos_aguas()

    def _cpn_dos_aguas(
        self,
    ) -> ValoresCpCubiertaAislada:
        """Calcula los factores cpn para una cubierta a dos aguas.

        Returns:
            Los valores de cpn de la cubierta.
        """
        angulos = (-20, -15, -10, -5, 5, 10, 15, 20, 25, 30)
        maximos_valores_globales = (0.7, 0.5, 0.4, 0.3, 0.3, 0.4, 0.4, 0.6, 0.7, 0.9)
        maximos_valores_zona_a = (0.8, 0.6, 0.6, 0.5, 0.6, 0.7, 0.9, 1.1, 1.2, 1.3)
        maximos_valores_zona_b = (1.6, 1.5, 1.4, 1.5, 1.8, 1.8, 1.9, 1.9, 1.9, 1.9)
        maximos_valores_zona_c = (0.6, 0.7, 0.8, 0.8, 1.3, 1.4, 1.4, 1.5, 1.6, 1.6)
        maximos_valores_zona_d = (1.7, 1.4, 1.1, 0.8, 0.4, 0.4, 0.4, 0.4, 0.5, 0.7)
        minimos_valores_globales = (
            (-0.7, -1.5),
            (-0.6, -1.5),
            (-0.6, -1.4),
            (-0.5, -1.4),
            (-0.6, -1.2),
            (-0.7, -1.2),
            (-0.8, -1.2),
            (-0.9, -1.2),
            (-1.0, -1.2),
            (-1.0, -1.2),
        )
        minimos_valores_zona_a = (
            (-0.9, -1.5),
            (-0.8, -1.5),
            (-0.8, -1.4),
            (-0.5, -1.4),
            (-0.6, -1.2),
            (-0.7, -1.2),
            (-0.9, -1.2),
            (-1.2, -1.2),
            (-1.4, -1.2),
            (-1.4, -1.2),
        )
        minimos_valores_zona_b = (
            (-1.3, -2.4),
            (-1.3, -2.7),
            (-1.3, -2.5),
            (-1.3, -2.3),
            (-1.4, -2.0),
            (-1.5, -1.8),
            (-1.7, -1.6),
            (-1.8, -1.5),
            (-1.9, -1.4),
            (-1.9, -1.3),
        )
        minimos_valores_zona_c = (
            (-1.6, -2.4),
            (-1.6, -2.6),
            (-1.5, -2.5),
            (-1.6, -2.4),
            (-1.4, -1.8),
            (-1.4, -1.6),
            (-1.4, -1.3),
            (-1.4, -1.2),
            (-1.4, -1.1),
            (-1.4, -1.1),
        )
        minimos_valores_zona_d = (
            (-0.6, -1.2),
            (-0.6, -1.2),
            (-0.6, -1.2),
            (-0.6, -1.2),
            (-1.1, -1.5),
            (-1.4, -1.6),
            (-1.8, -1.7),
            (-2.0, -1.7),
            (-2.0, -1.6),
            (-2.0, -1.6),
        )
        valor_maximo_global: float = np.interp(
            self.angulo, angulos, maximos_valores_globales
        )
        valor_maximo_zona_a: float = np.interp(
            self.angulo, angulos, maximos_valores_zona_a
        )
        valor_maximo_zona_b: float = np.interp(
            self.angulo, angulos, maximos_valores_zona_b
        )
        valor_maximo_zona_c: float = np.interp(
            self.angulo, angulos, maximos_valores_zona_c
        )
        valor_maximo_zona_d: float = np.interp(
            self.angulo, angulos, maximos_valores_zona_d
        )

        bloqueos = [0, 1]

        minimos_valores_globales_relacion: Tuple = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_globales
        )
        minimos_valores_caso_a_relacion: Tuple = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_a
        )
        minimos_valores_caso_b_relacion: Tuple = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_b
        )
        minimos_valores_caso_c_relacion: Tuple = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_c
        )
        minimos_valores_caso_d_relacion: Tuple = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_d
        )
        # TODO Corregir esto, es repetitivo
        valor_minimo_global: float = np.interp(
            self.angulo, angulos, minimos_valores_globales_relacion
        )
        valor_minimo_zona_a: float = np.interp(
            self.angulo, angulos, minimos_valores_caso_a_relacion
        )
        valor_minimo_zona_b: float = np.interp(
            self.angulo, angulos, minimos_valores_caso_b_relacion
        )
        valor_minimo_zona_c: float = np.interp(
            self.angulo, angulos, minimos_valores_caso_c_relacion
        )
        valor_minimo_zona_d: float = np.interp(
            self.angulo, angulos, minimos_valores_caso_d_relacion
        )

        return {
            TipoPresionCubiertaAislada.GLOBAL: {
                ExtremoPresion.MAX: valor_maximo_global,
                ExtremoPresion.MIN: valor_minimo_global,
            },
            TipoPresionCubiertaAislada.LOCAL: {
                ZonaPresionCubiertaAislada.A: {
                    ExtremoPresion.MAX: valor_maximo_zona_a,
                    ExtremoPresion.MIN: valor_minimo_zona_a,
                },
                ZonaPresionCubiertaAislada.B: {
                    ExtremoPresion.MAX: valor_maximo_zona_b,
                    ExtremoPresion.MIN: valor_minimo_zona_b,
                },
                ZonaPresionCubiertaAislada.C: {
                    ExtremoPresion.MAX: valor_maximo_zona_c,
                    ExtremoPresion.MIN: valor_minimo_zona_c,
                },
                ZonaPresionCubiertaAislada.D: {
                    ExtremoPresion.MAX: valor_maximo_zona_d,
                    ExtremoPresion.MIN: valor_minimo_zona_d,
                },
                ZonaPresionCubiertaAislada.BC: {
                    ExtremoPresion.MAX: max(valor_maximo_zona_b, valor_maximo_zona_c),
                    ExtremoPresion.MIN: min(valor_minimo_zona_b, valor_minimo_zona_c),
                },
                ZonaPresionCubiertaAislada.BD: {
                    ExtremoPresion.MAX: max(valor_maximo_zona_b, valor_maximo_zona_d),
                    ExtremoPresion.MIN: min(valor_minimo_zona_b, valor_minimo_zona_d),
                },
            },
        }

    def _cpn_un_agua(
        self,
    ) -> ValoresCpCubiertaAislada:
        """Calcula los factores cpn para una cubierta a un agua.

        Returns:
            Los valores de cpn de la cubierta.
        """
        angulos = (0, 5, 10, 15, 20, 25, 30)
        maximos_valores_globales = (0.2, 0.4, 0.5, 0.7, 0.8, 1, 1.2)
        maximos_valores_zona_a = (0.5, 0.8, 1.2, 1.4, 1.7, 2, 2.2)
        maximos_valores_zona_b = (1.8, 2.1, 2.4, 2.7, 2.9, 3.1, 3.2)
        maximos_valores_zona_c = (1.1, 1.3, 1.6, 1.8, 2.1, 2.3, 2.4)
        minimos_valores_globales = {
            PosicionBloqueoCubierta.ALERO_BAJO: (
                (-0.5, -1.2),
                (-0.7, -1.4),
                (-0.9, -1.4),
                (-1.1, -1.5),
                (-1.3, -1.5),
                (-1.6, -1.4),
                (-1.8, -1.4),
            ),
            PosicionBloqueoCubierta.ALERO_ALTO: (
                (-0.5, -1.2),
                (-0.7, -1.2),
                (-0.9, -1.1),
                (-1.1, -1),
                (-1.3, -0.9),
                (-1.6, -0.8),
                (-1.8, -0.8),
            ),
        }
        minimos_valores_zona_a = {
            PosicionBloqueoCubierta.ALERO_BAJO: (
                (-0.6, -1.3),
                (-1.1, -1.4),
                (-1.5, -1.4),
                (-1.8, -1.5),
                (-2.2, -1.5),
                (-2.6, -1.4),
                (-3.0, -1.4),
            ),
            PosicionBloqueoCubierta.ALERO_ALTO: (
                (-0.6, -1.3),
                (-1.1, -1.2),
                (-1.5, -1.1),
                (-1.8, -1),
                (-2.2, -0.9),
                (-2.6, -0.8),
                (-3.0, -0.8),
            ),
        }
        minimos_valores_zona_b = (
            (-1.3, -1.8),
            (-1.7, -2.6),
            (-2.0, -2.6),
            (-2.4, -2.9),
            (-2.8, -2.9),
            (-3.2, -2.5),
            (-3.8, -2.0),
        )
        minimos_valores_zona_c = {
            PosicionBloqueoCubierta.ALERO_BAJO: (
                (-1.4, -2.2),
                (-1.8, -2.6),
                (-2.1, -2.7),
                (-2.5, -2.8),
                (-2.9, -2.7),
                (-3.2, -2.5),
                (-3.6, -2.3),
            ),
            PosicionBloqueoCubierta.ALERO_ALTO: (
                (-1.4, -2.2),
                (-1.8, -2.1),
                (-2.1, -1.8),
                (-2.5, -1.6),
                (-2.9, -1.5),
                (-3.2, -1.4),
                (-3.6, -1.2),
            ),
        }
        # TODO corregir, es repetitivo
        valor_maximo_global = np.interp(self.angulo, angulos, maximos_valores_globales)
        valor_maximo_zona_a = np.interp(self.angulo, angulos, maximos_valores_zona_a)
        valor_maximo_zona_b = np.interp(self.angulo, angulos, maximos_valores_zona_b)
        valor_maximo_zona_c = np.interp(self.angulo, angulos, maximos_valores_zona_c)

        bloqueos = [0, 1]

        minimos_valores_globales_relacion = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_globales[self.posicion_bloqueo]
        )
        minimos_valores_caso_a_relacion = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_a[self.posicion_bloqueo]
        )
        minimos_valores_caso_b_relacion = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_b
        )
        minimos_valores_caso_c_relacion = tuple(
            np.interp(self.relacion_bloqueo, bloqueos, valores)
            for valores in minimos_valores_zona_c[self.posicion_bloqueo]
        )
        # TODO Corregir, es repetitivo
        valor_minimo_global = np.interp(
            self.angulo, angulos, minimos_valores_globales_relacion
        )
        valor_minimo_zona_a = np.interp(
            self.angulo, angulos, minimos_valores_caso_a_relacion
        )
        valor_minimo_zona_b = np.interp(
            self.angulo, angulos, minimos_valores_caso_b_relacion
        )
        valor_minimo_zona_c = np.interp(
            self.angulo, angulos, minimos_valores_caso_c_relacion
        )
        return {
            TipoPresionCubiertaAislada.GLOBAL: {
                ExtremoPresion.MAX: valor_maximo_global,
                ExtremoPresion.MIN: valor_minimo_global,
            },
            TipoPresionCubiertaAislada.LOCAL: {
                ZonaPresionCubiertaAislada.A: {
                    ExtremoPresion.MAX: valor_maximo_zona_a,
                    ExtremoPresion.MIN: valor_minimo_zona_a,
                },
                ZonaPresionCubiertaAislada.B: {
                    ExtremoPresion.MAX: valor_maximo_zona_b,
                    ExtremoPresion.MIN: valor_minimo_zona_b,
                },
                ZonaPresionCubiertaAislada.C: {
                    ExtremoPresion.MAX: valor_maximo_zona_c,
                    ExtremoPresion.MIN: valor_minimo_zona_c,
                },
                ZonaPresionCubiertaAislada.BC: {
                    ExtremoPresion.MAX: max(valor_maximo_zona_b, valor_maximo_zona_c),
                    ExtremoPresion.MIN: min(valor_minimo_zona_b, valor_minimo_zona_c),
                },
            },
        }

    @classmethod
    def desde_cubierta(cls, cubierta: geometria.Cubierta):
        """Crea una instancia desde la geometria de una cubierta.

        Args:
            cubierta: La geometria de una cubierta.
        """
        return cls(
            cubierta.tipo_cubierta,
            cubierta.angulo,
            cubierta.relacion_bloqueo,
            cubierta.posicion_bloqueo,
        )

    def __call__(
        self,
    ) -> ValoresCpCubiertaAislada:
        return self.valores


""" This module defines the model for training and instantiating A3C agents """

from collections import deque
from statistics import stdev

from blaze.config.config import Config
from blaze.config.train import TrainConfig
from blaze.environment import Environment
from blaze.logger import logger

from .model import SavedModel

WINDOW_SIZE = 50
MAX_ITERATIONS = 150
MIN_ITERATIONS = 50
MAX_TIME_SECONDS = 2 * 60 * 60  # 2 hours

def stop_condition():
    """
    Implements a stateful stopping condition to automatically stop the training based on analyzing the running
    episode reward mean over a certain window size. It also stop automatically if the number of training iterations
    exceeds some maximum, but not before it exceeds some minimum.
    """

    log = logger.with_namespace("stop_condition")
    num_iters = 0
    past_rewards = deque()

    def stopper(trial_id, result):
        nonlocal num_iters, past_rewards
        num_iters += 1

        if "time_since_restore" in result and result["time_since_restore"] >= MAX_TIME_SECONDS:
            log.info("auto stopping", time_seconds=result["time_since_restore"], iters=num_iters)
            return True

        if "episode_reward_max" in result and "episode_reward_min" in result and "episode_reward_mean" in result:
            rewards = (result["episode_reward_min"], result["episode_reward_mean"], result["episode_reward_max"])
            log.debug("recording trial result", trial_id=trial_id, num_iters=num_iters, rewards=rewards)
            past_rewards.append(rewards)
        else:
            log.warn("unable to record episode result", result=result, trial_id=trial_id)
            return False

        # truncate the rewards list to past `WINDOW_SIZE` iterations only
        if len(past_rewards) > WINDOW_SIZE:
            past_rewards.popleft()

        if num_iters > MIN_ITERATIONS:
            stdev_min, stdev_mean, stdev_max = tuple(map(stdev, zip(*past_rewards)))
            log.debug("reward stats", stdev_min=stdev_min, stdev_mean=stdev_mean, stdev_max=stdev_max)
            relative_stdev_based_stop = stdev_mean <= 0.05 * abs(past_rewards[-1][1])

            if num_iters > MAX_ITERATIONS or relative_stdev_based_stop:
                log.info("auto stopping", time_seconds=result.get("time_since_restore", 0), iters=num_iters)
                return True

        return False

    stopper.past_rewards = past_rewards
    return stopper

COMMON_CONFIG = {
    "sample_batch_size": 256,
    "train_batch_size": 1024,
    "batch_mode": "truncate_episodes",
    "collect_metrics_timeout": 1200,
    "num_workers": 2,
    "num_gpus": 0,
    "model": {"use_lstm": True, "lstm_use_prev_action_reward": True},
}

def train(train_config: TrainConfig, config: Config):
    """ Trains an A3C agent with the given training and environment configuration """
    # lazy load modules so that they aren't imported if they're not necessary
    import ray
    from ray.tune import run_experiments

    ray.init(num_cpus=train_config.num_workers + 1, log_to_driver=False)

    name = train_config.experiment_name
    run_experiments(
        {
            name: {
                "run": "A3C",
                "env": Environment,
                "stop": ray.tune.function(stop_condition()),
                "checkpoint_at_end": True,
                "checkpoint_freq": 10,
                "max_failures": 3,
                "config": {**COMMON_CONFIG, "num_workers": train_config.num_workers, "env_config": config},
            }
        },
        resume=train_config.resume,
    )

def get_model(location: str):
    """ Returns a SavedModel for instantiation given a model checkpoint directory """
    from ray.rllib.agents.a3c import A3CAgent

    return SavedModel(A3CAgent, Environment, location, COMMON_CONFIG)


# SteelEye
# API Developer Assessment

from fastapi import FastAPI, Query, HTTPException
from pydantic import BaseModel, Field, HttpUrl
from typing import Optional, List, Set
import datetime as dt
from datetime import datetime
import random as rd
# from elasticsearch import Elasticsearch

#//////////////////////////////////////////////////////////////////////////////
# instance of module

app = FastAPI()

#//////////////////////////////////////////////////////////////////////////////
# DB Models
class TradeDetails(BaseModel):
    buySellIndicator: str = Field(description="A value of BUY for buys, SELL for sells.")
    price: float = Field(description="The price of the Trade.")
    quantity: int = Field(description="The amount of units traded.")

class Trade(BaseModel):
    trade_id: str = Field(alias="tradeId", default=None, description="The unique ID of the trade")
    trader: str = Field(description="The name of the Trader")
    asset_class: Optional[str] = Field(alias="assetClass", default=None, description="The asset class of the instrument traded. E.g. Bond, Equity, FX...etc")
    counterparty: Optional[str] = Field(default=None, description="The counterparty the trade was executed with. May not always be available")
    instrument_id: str = Field(alias="instrumentId", description="The ISIN/ID of the instrument traded. E.g. TSLA, AAPL, AMZN...etc")
    instrument_name: str = Field(alias="instrumentName", description="The name of the instrument traded.")
    trade_date_time: dt.datetime = Field(alias="tradeDateTime", description="The date-time the Trade was executed")
    trade_details: TradeDetails = Field(alias="tradeDetails", description="The details of the trade, i.e. price, quantity")

#........ Mock Database
DBmock = [
    {
        "trade_id": "1",
        "trader": "Akashay Anand",
        "asset_class": "Equity",
        "counterparty": "Zerodha",
        "instrument_id": "TSLA",
        "instrument_name": "Tesla Inc.",
        "trade_date_time": dt.datetime(2023, 4, 20, 12, 0, 0),
        "trade_details": {
            "buySellIndicator": "BUY",
            "price": 110.0,
            "quantity": 1000
        }
    },
    {
        "trade_id": "2",
        "trader": "Auysh",
        "asset_class": "Equity",
        "counterparty": "Narnolia",
        "instrument_id": "AAPL",
        "instrument_name": "Apple Inc.",
        "trade_date_time": dt.datetime(2023, 4, 19, 11, 30, 0),
        "trade_details": {
            "buySellIndicator": "BUY",
            "price": 170.0,
            "quantity": 1000
        }
    },
    {
        "trade_id": "3",
        "trader": "Shruti",
        "asset_class": "Equity",
        "counterparty": "UPStox",
        "instrument_id": "AMZN",
        "instrument_name": "Amazon.com, Inc.",
        "trade_date_time": dt.datetime(2023, 4, 21, 13, 0, 0),
        "trade_details": {
            "buySellIndicator": "SELL",
            "price": 50.0,
            "quantity": 500
        }
    },
    {
        "trade_id": "4",
        "trader": "Pooja",
        "asset_class": "Equity",
        "counterparty": "UPStox",
        "instrument_id": "AMZN",
        "instrument_name": "Amazon.com, Inc.",
        "trade_date_time": dt.datetime(2023, 4, 22, 13, 0, 0),
        "trade_details": {
            "buySellIndicator": "BUY",
            "price": 55.0,
            "quantity": 400
        }
    }
]

#/////////////////////////////////////////////////////////////////////////////
# Routes / End Point

#////// Root path ////
@app.get('/')
def fun():
    return 'hello world // API Assingment // this API will retun data based on url'

#//// All List of Trade ///
@app.get("/trades")
async def Listing_trades():
    return DBmock

@app.get("/trades/{trade_id}")
async def Single_trade(trade_id: str):
    for trade in DBmock :
        if trade["trade_id"] == trade_id:
            return trade
    raise HTTPException(status_code=404, detail="Trade not found")

#///// Searching trades ////
@app.get("/filter")
async def Search_trades(search: Optional[str] = None):
    # return "hello"
    if search is None:
        return "Please provide search string through url  ex: http://127.0.0.1:8000/trades/filter?search=bob%20smith"
    else:
        filtered_trades = []
        for trade in DBmock:
            if (search.lower() in trade.get("counterparty", "").lower()
                or search.lower() in trade.get("instrument_id", "").lower()
                or search.lower() in trade.get("instrument_name", "").lower()
                or search.lower() in trade.get("trader", "").lower()):
                filtered_trades.append(trade)
        return filtered_trades

#////// Advance filtering ////
@app.get("/Advfilter")
async def get_trades(
    assetClass: Optional[str] = Query(None, description="Asset class of the trade."),
    end: Optional[datetime] = Query(None, description="The maximum date for the tradeDateTime field."),
    maxPrice: Optional[float] = Query(None, description="The maximum value for the tradeDetails.price field."),
    minPrice: Optional[float] = Query(None, description="The minimum value for the tradeDetails.price field."),
    start: Optional[datetime] = Query(None, description="The minimum date for the tradeDateTime field."),
    tradeType: Optional[str] = Query(None, description="The tradeDetails.buySellIndicator is a BUY or SELL")
):
    # return assetClass
    # filtered_trades = DBmock.copy()
    filtered_trades = []

    # filter by asset class
    if assetClass:
        for trade in DBmock:
            if (assetClass.lower() in trade.get("asset_class", "").lower() ):
                filtered_trades.append(trade)

    # filter by end date // having doubt in its implementation // so commenting it for now
    # if end:
    #     for trade in DBmock:
    #         if (end >= trade.get("", "") ):
    #             filtered_trades.append(trade)

    # filter by min and max price
    if maxPrice:
        for trade in DBmock:
            if (maxPrice >= trade.get("trade_details.price", "") ):
                filtered_trades.append(trade)

    if minPrice:
        for trade in DBmock:
            if (maxPrice <= trade.get("trade_details.price", "") ):
                filtered_trades.append(trade)

    # filter by start date
    if start:
        for trade in DBmock:
            if (start <= trade.get("trade_date_time", "") ):
                filtered_trades.append(trade)

    # filter by trade type
    if tradeType:
        for trade in DBmock:
            if (tradeType.lower() in trade.get("trade_details.buySellIndicator", "").lower() ):
                filtered_trades.append(trade)

    return filtered_trades

# ///////////////////////////////////////////////////////


import re
import time
import warnings
import argparse
import wordcloud
from tqdm import tqdm
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from bs4 import BeautifulSoup
import pandas as pd

warnings.filterwarnings('ignore')

def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-w',
        '--search_word',
        type=str,
        default='semantic+segmentation',
        help='Keyword searched')
    parser.add_argument(
        '-p',
        '--num_page',
        type=int,
        default=100,
        help='Number of pages')
    return parser

def github_crawler(html_source):

    page = BeautifulSoup(html_source, 'lxml')

    info, csv_info = [], []
    infos = [a.text for a in page.find_all('div', 'mt-n1')]
    if infos == []:
        infos = [a.text for a in page.find_all('div', 'mt-n1')]
    if len(infos) == 0:
        print('none')
        return [], []

    names = [a.text for a in page.find_all('a', 'v-align-middle')]
    urls = ['https://github.com/' + name for name in names]

    stars = [re.findall(".*            (.*)\n   .*", info) for info in infos]
    stars = ['0' if star == [] else star[0] for star in stars]
    states = ["Updated" + str(re.findall(".*Updated(.*)\n.*", info)[0]) for info in infos]

    # readme
    readme = []
    for url in urls:
        repo_source = url2html(url)
        repo_page = BeautifulSoup(repo_source, 'lxml')
        repo_infos = [str(a.text).strip() for a in repo_page.find_all(id='readme')]
        repo_infos = '' if repo_infos == [] else repo_infos[0]
        repo_info = ''
        for text in repo_infos.splitlines():
            text = text.rstrip() + ' '
            repo_info += text
        readme.append(repo_info)

    for i in range(len(infos)):
        info.append(
            {
                'name': names[i],
                'star': stars[i],
                # 'language': languages[i],
                'url': urls[i],
                'state': states[i],
                'readme': readme[i]
            }
        )
        csv_info.append([names[i], stars[i], urls[i], states[i], readme[i]])
    return info, csv_info

def url2html(url):
    chrome_options = webdriver.ChromeOptions()
    chrome_options.headless = True
    chrome_options.add_argument("--disable-gpu")
    prefs = {"profile.managed_default_content_setting.images": 2}
    chrome_options.add_experimental_option("prefs", prefs)
    chrome = webdriver.Chrome(chrome_options=chrome_options)

    print(url)
    try:
        chrome.set_page_load_timeout(3000)
        chrome.get(url)
        return chrome.page_source
    except TimeoutException as ex:
        print("Exception has been thrown. " + str(ex))
        chrome.close()
        return None

if __name__ == '__main__':
    args = get_parser().parse_args()
    information, csv_information = [], []
    name = ['repo name', 'star', 'url', 'state', 'readme']

    urls = ["https://github.com/search?q=" + args.search_word, ]
    for i in range(2, args.num_page + 1):
        urls.append("https://github.com/search?p=" + str(i) + "&q=" + args.search_word + "&type=Repositories")

    for url in tqdm(urls):
        html_source = url2html(url)
        if html_source is not None:
            info = github_crawler(html_source)
        else:
            continue
        information += info[0]
        csv_information += info[1]

    # print(information)
    # print()
    # print(csv_information)

    pd_reader = pd.DataFrame(columns=name, data=csv_information)
    pd_reader.to_csv('./result/' + args.search_word + '.csv', encoding='utf-8')

    w = wordcloud.WordCloud(width=2000, height=1000, max_words=500)
    all_readme = ''
    for readme in pd_reader['readme']:
        # print(readme)
        all_readme += ' ' + str(readme)
    pat_letter = re.compile(r'[^a-zA-Z \']+')
    all_readme = pat_letter.sub(' ', all_readme).strip().lower()
    w.generate(all_readme)
    w.to_file('./img/output1.png')


from keras.callbacks import EarlyStopping, ModelCheckpoint, TensorBoard
from keras.preprocessing import image
from keras.applications import imagenet_utils
from keras.preprocessing.image import ImageDataGenerator
from keras.layers import Input
from keras.optimizers import Adam
import numpy as np
from sklearn.externals import joblib
from keras.utils import plot_model
import os

import config
import util

class BaseModel(object):
    """All of the methods can be extended in the sub class. Be cautious about your model."""
    def __init__(self,
                 class_weight=None,
                 nb_epoch=1000,
                 batch_size=32,
                 freeze_layers_number=None):
        self.model = None
        self.class_weight = class_weight
        self.nb_epoch = nb_epoch
        self.fine_tuning_patience = 20
        self.batch_size = batch_size
        self.freeze_layers_number = freeze_layers_number
        self.img_size = (224, 224)

    def _create(self):
        raise NotImplementedError('subclasses must override _create()')

    def _fine_tuning(self):
        self.freeze_top_layers()

        self.model.compile(
            loss='categorical_crossentropy',
            optimizer=Adam(lr=1e-5),
            metrics=['accuracy'])
        self.model.summary()
        # save the model to png in order to visualize
        plot_model(self.model, to_file='model1.png', show_shapes=True)
        train_data = self.get_train_datagen(rotation_range=30., shear_range=0.2, zoom_range=0.2, horizontal_flip=True,
                                            preprocessing_function=self.preprocess_input)
        # early stopping
        callbacks = self.get_callbacks(config.get_fine_tuned_weights_path(), patience=self.fine_tuning_patience)

        if util.is_keras2():
            self.model.fit_generator(
                train_data,
                steps_per_epoch=config.nb_train_samples / float(self.batch_size),
                epochs=self.nb_epoch,
                validation_data=self.get_validation_datagen(),
                validation_steps=config.nb_validation_samples / float(self.batch_size),
                callbacks=callbacks,
                class_weight=self.class_weight)
        else:
            self.model.fit_generator(
                train_data,
                samples_per_epoch=config.nb_train_samples,
                nb_epoch=self.nb_epoch,
                validation_data=self.get_validation_datagen(),
                nb_val_samples=config.nb_validation_samples,
                callbacks=callbacks,
                class_weight=self.class_weight)

        self.model.save(config.get_model_path())

    def train(self):
        print("Creating model...")
        self._create()
        # self.model.load_weights(config.get_fine_tuned_weights_path(), by_name=True, skip_mismatch=True)
        print("Model is created")
        print("Fine tuning...")
        self.save_classes()
        self._fine_tuning()
        print("Classes are saved")

    # add the default preprocess function in tf mode
    def preprocess_input(self, x):
        """Preprocesses a numpy array encoding a batch of images.

        # Arguments
            x: a 4D numpy array consists of RGB values within [0, 255].

        # Returns
            Preprocessed array.
        """
        return imagenet_utils.preprocess_input(x, mode='tf')

    def load(self):
        print("Creating model")
        self.load_classes()
        self._create()
        self.model.load_weights(config.get_fine_tuned_weights_path())
        return self.model

    @staticmethod
    def save_classes():
        joblib.dump(config.classes, config.get_classes_path())

    def get_input_tensor(self):
        if util.get_keras_backend_name() == 'theano':
            return Input(shape=(1,) + self.img_size)
        else:
            return Input(shape=self.img_size + (1,))

    @staticmethod
    def make_net_layers_non_trainable(model):
        for layer in model.layers:
            layer.trainable = False

    def freeze_top_layers(self):
        if self.freeze_layers_number:
            print("Freezing {} layers".format(self.freeze_layers_number))
            for layer in self.model.layers[:self.freeze_layers_number]:
                layer.trainable = False
            for layer in self.model.layers[self.freeze_layers_number:]:
                layer.trainable = True

    @staticmethod
    def get_callbacks(weights_path, patience=30, monitor='val_loss', embedding_mode=False,
                      target_object=None, visual_embedding=None, center_loss_input=False):
        early_stopping = EarlyStopping(verbose=1, patience=patience, monitor=monitor)
        model_checkpoint = ModelCheckpoint(weights_path, save_best_only=True, save_weights_only=True, monitor=monitor)
        # if the embedding should be visualized
        if embedding_mode and visual_embedding is not None and target_object is not None:
            metadata_file_name = 'metadata.tsv'
            embeddings_metadata = {layer_name: metadata_file_name
                                   for layer_name in visual_embedding}
            test_data = util.write_csv_and_get_embedinput('.' + os.sep + 'sorted' + os.sep + 'test',
                                                          metadata_file_name,
                                                          '.' + os.sep + 'logs' + os.sep,
                                                          target_object,
                                                          limit_each_class=10,
                                                          center_loss_input=center_loss_input)
            tensor_board = TensorBoard(histogram_freq=0,
                                       # if there is histogram(not 0) we can not give the validation data in sequence
                                       write_graph=True,
                                       embeddings_freq=5,
                                       batch_size=32,
                                       write_images=True,
                                       embeddings_layer_names=visual_embedding,
                                       embeddings_metadata=embeddings_metadata,
                                       embeddings_data=test_data)

            return [early_stopping, model_checkpoint, tensor_board]
        else:
            return [early_stopping, model_checkpoint]

    @staticmethod
    def apply_mean(image_data_generator):
        """Subtracts the dataset mean"""
        image_data_generator.mean = np.array([103.939, 116.779, 123.68], dtype=np.float32).reshape((3, 1, 1))

    @staticmethod
    def load_classes():
        config.classes = joblib.load(config.get_classes_path())

    def load_img(self, img_path):
        img = image.load_img(img_path, target_size=self.img_size)
        x = image.img_to_array(img)
        x = np.expand_dims(x, axis=0)
        return self.preprocess_input(x)[0]

    def get_train_datagen(self, *args, **kwargs):
        idg = ImageDataGenerator(*args, **kwargs)
        # self.apply_mean(idg)
        return idg.flow_from_directory(config.train_dir, target_size=self.img_size, classes=config.classes)

    def get_validation_datagen(self, *args, **kwargs):
        idg = ImageDataGenerator(*args, **kwargs)
        # self.apply_mean(idg)
        return idg.flow_from_directory(config.validation_dir, target_size=self.img_size, classes=config.classes)

    # class TrainValTensorBoard(TensorBoard):
    #     def __init__(self, log_dir='./logs', **kwargs):
    #         # Make the original `TensorBoard` log to a subdirectory 'training'
    #         training_log_dir = os.path.join(log_dir, 'training')
    #         super(TrainValTensorBoard, self).__init__(training_log_dir, **kwargs)
    #
    #         # Log the validation metrics to a separate subdirectory
    #         self.val_log_dir = os.path.join(log_dir, 'validation')
    #
    #     def set_model(self, model):
    #         # Setup writer for validation metrics
    #         self.val_writer = tf.summary.FileWriter(self.val_log_dir)
    #         super(TrainValTensorBoard, self).set_model(model)
    #
    #     def on_epoch_end(self, epoch, logs=None):
    #         # Pop the validation logs and handle them separately with
    #         # `self.val_writer`. Also rename the keys so that they can
    #         # be plotted on the same figure with the training metrics
    #         logs = logs or {}
    #         val_logs = {k.replace('val_', ''): v for k, v in logs.items() if k.startswith('val_')}
    #         for name, value in val_logs.items():
    #             summary = tf.Summary()
    #             summary_value = summary.value.add()
    #             summary_value.simple_value = value.item()
    #             summary_value.tag = name
    #             self.val_writer.add_summary(summary, epoch)
    #         self.val_writer.flush()
    #
    #         # Pass the remaining logs to `TensorBoard.on_epoch_end`
    #         logs = {k: v for k, v in logs.items() if not k.startswith('val_')}
    #         super(TrainValTensorBoard, self).on_epoch_end(epoch, logs)
    #
    #     def on_train_end(self, logs=None):
    #         super(TrainValTensorBoard, self).on_train_end(logs)
    #         self.val_writer.close()

    # def generate_arrays_from_file(path):
    #     while 1:
    #         f = open(path)
    #         for line in f:
    #             # create numpy arrays of input data
    #             # and labels, from each line in the file
    #             x, y = process_line(line)
    #             img = load_images(x)
    #             yield (img, y)
    #         f.close()
    # model.fit_generator(generate_arrays_from_file('/my_file.txt'),
    #
    # samples_per_epoch=10000, nb_epoch=10)

    # datagen = ImageDataGenerator(
    #         featurewise_center=True, # set input mean to 0 over the dataset
    #         samplewise_center=False, # set each sample mean to 0
    #         featurewise_std_normalization=True, # divide inputs by std of the dataset
    #         samplewise_std_normalization=False, # divide each input by its std
    #         zca_whitening=False, # apply ZCA whitening
    #         rotation_range=20, # randomly rotate images in the range (degrees, 0 to 180)
    #         width_shift_range=0.2, # randomly shift images horizontally (fraction of total width)
    #         height_shift_range=0.2, # randomly shift images vertically (fraction of total height)
    #         horizontal_flip=True, # randomly flip images
    #         vertical_flip=False) # randomly flip images
    #
    # datagen.fit(X_sample) # let's say X_sample is a small-ish but statistically representative sample of your data
    #
    # # let's say you have an ImageNet generator that yields ~10k samples at a time.
    # for e in range(nb_epoch):
    #     print("epoch %d" % e)
    #     for X_train, Y_train in ImageNet(): # these are chunks of ~10k pictures
    #         for X_batch, Y_batch in datagen.flow(X_train, Y_train, batch_size=32): # these are chunks of 32 samples
    #             loss = model.train(X_batch, Y_batch)
    #
    # # Alternatively, without data augmentation / normalization:
    # for e in range(nb_epoch):
    #     print("epoch %d" % e)
    #     for X_train, Y_train in ImageNet(): # these are chunks of ~10k pictures
    #         model.fit(X_batch, Y_batch, batch_size=32, nb_epoch=1)


import re
import nltk
from nltk.corpus import stopwords
import spacy
import textacy
import contractions

punctuations = '''~!@#$%^&*()"_+-=`;':,./<>?'''

text = '''
Dear PayPal User,

We regret to inform you that your PayPal account has been compromised and we have noticed some unauthorized activities. To protect your account, we kindly request you to verify your information immediately.

Click on the following link to verify your account: paypalredirect.co
b
Please note that failure to verify your account within 24 hours will result in permanent account suspension.

Thank you for your cooperation.

Best regards,
PayPal Security Team
'''

#Contraction fixing
text = contractions.fix(text)

#removing punctuation + lowercase
text = re.sub(r'[^\w\s]', '',text).lower()

nltk.download('punkt')
nltk.download('wordnet')

#tokenization
tokenized_text = nltk.word_tokenize(text)

print(tokenized_text)

nltk.download('stopwords')
stop_words = stopwords.words('english')

#Removing Stop words
filtered_tokens = []
for token in tokenized_text:
    if token.lower() not in stop_words:
        filtered_tokens.append(token)

print(filtered_tokens)

#lemmatization
nlp = spacy.load("en_core_web_sm")

lem_words = []
for word in filtered_tokens:
    doc = nlp(word)
    for token in doc:
        lem_words.append(token.lemma_)

print(lem_words)


"""
"""
from django.conf.urls import patterns, url
from rest_framework.routers import SimpleRouter

from myapp import views

router = SimpleRouter()
router.register(r'projects', views.ProjectViewSet)
router.register(r'tasks', views.TaskViewSet)
router.register(r'users', views.UserViewSet)

urlpatterns = patterns('',
    url(r'^register/', 'myapp.views.create_auth'),
)

urlpatterns += router.urls


#!/usr/bin/env python
import numpy as np
from . import coreaudio
import threading
import queue
import sys

defBuf = 2048

class StreamArray:
    def __init__(self, dtype=np.float32, inBufSize=defBuf, outBufSize=defBuf):
        self.dtype = dtype
        self.inBufSize = inBufSize
        self.outBufSize = outBufSize
    def __len__(self):
        return sys.maxsize
    def __getitem__(self, sl):
        if isinstance(sl, slice):
            count = sl.stop - sl.start
        elif isinstance(sl, int):
            count = 1
        else:
            raise TypeError('Unexpected slice arguments')
        return self.produce(count).astype(self.dtype)
    def append(self, sequence):
        return self.consume(sequence)

class ThreadedStream(StreamArray):
    def __init__(self, channels=1, in_thread=None, out_thread=None, out_queue_depth=64,
                 inBufSize=defBuf, outBufSize=defBuf):
        super().__init__(inBufSize=inBufSize, outBufSize=outBufSize)
        self.channels = channels
        self.in_queue = queue.Queue(64)
        self.out_queue = queue.Queue(out_queue_depth)
        self.out_fragment = None
        self.numSamplesRead = 0
        self.numSamplesWritten = 0
        self.numSamplesProduced = 0
        self.numSamplesConsumed = 0
        self.warnOnUnderrun = True
        if hasattr(self, 'thread_consume') or in_thread:
            self.in_thread = threading.Thread(target=self.in_thread_loop, daemon=True)
            self.in_thread.start()
        if hasattr(self, 'thread_produce') or out_thread:
            self.out_thread = threading.Thread(target=self.out_thread_loop, daemon=True)
            self.out_thread.start()
    def in_thread_loop(self):
        while True:
            work = self.in_queue.get()
            if work is None:
                break
            self.numSamplesConsumed += work.shape[0]
            self.thread_consume(work)
    def out_thread_loop(self):
        while True:
            work = self.thread_produce()
            if work is None:
                break
            self.numSamplesProduced += work.shape[0]
            self.out_queue.put(work)
    def consume(self, sequence):
        self.numSamplesWritten += sequence.shape[0]
        try:
            self.in_queue.put_nowait(sequence)
        except queue.Full:
            print('ThreadedStream overrun')
        except Exception as e:
            print('ThreadedStream exception %s' % repr(e))
    def produce(self, count):
        result = np.empty((count, self.channels), self.dtype)
        i = 0
        if self.out_fragment is not None:
            n = min(self.out_fragment.shape[0], count)
            result[:n] = self.out_fragment[:n]
            i += n
            if n < self.out_fragment.shape[0]:
                self.out_fragment = self.out_fragment[n:]
            else:
                self.out_fragment = None
        while i < count:
            try:
                fragment = self.immediate_produce()
                if len(fragment.shape) == 1:
                    fragment = fragment[:,np.newaxis]
                if fragment.shape[1] != self.channels and fragment.shape[1] != 1:
                    raise Exception('ThreadedStream produced a stream with the wrong number of channels.')
            except queue.Empty:
                result[i:] = 0
                if self.warnOnUnderrun:
                    print('ThreadedStream underrun')
                break
            except Exception as e:
                print('ThreadedStream exception %s' % repr(e))
            else:
                n = min(count-i, fragment.shape[0])
                result[i:i+n] = fragment[:n]
                i += n
                if fragment.shape[0] > n:
                    self.out_fragment = fragment[n:]
        self.numSamplesRead += result.shape[0]
        return result
    def immediate_produce(self):
        return self.out_queue.get_nowait()
    def onMainThread(self, fn):
        coreaudio.add_to_main_thread_queue(fn)
    def stop(self):
        self.in_queue.put(None)

class WhiteNoise(ThreadedStream):
    def thread_produce(self):
        return np.random.standard_normal(1024) * .2

class Sine(ThreadedStream):
    def __init__(self):
        super().__init__(channels=2)
        self.f = 880.
        self.i = 0
        self.Fs = 48000.
    def thread_produce(self):
        j = np.arange(1024) + self.i
        t = j/self.Fs
        omega = self.f*2*np.pi
        self.i += j.size
        l = .2*np.sin(omega*t)
        r = .2*np.sin(omega*t+.5*np.pi)
        return np.hstack((l[:,np.newaxis], r[:,np.newaxis]))

class VUMeter(ThreadedStream):
    def __init__(self, Fs=96e3):
        super().__init__()
        self.peak = 0.
        self.Fs = Fs
    def thread_consume(self, sequence):
        volume = 30 + int(round(10.*np.log10((np.abs(sequence).astype(float)**2).mean())))
        peak = 30 + int(round(10.*np.log10((np.abs(sequence).astype(float)**2).max())))
        self.peak = max(peak, self.peak-8*sequence.size/self.Fs)
        bar = '#'*volume
        n = int(np.ceil(self.peak))
        bar = bar + ' ' * (n-len(bar)) + '|'
        sys.stdout.write('\r\x1b[K' + bar)
        sys.stdout.flush()

class Visualizer(ThreadedStream):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        import pylab as pl
        self.pl = pl
        dpi = pl.rcParams['figure.dpi']
        import AppKit
        screens = AppKit.NSScreen.screens()
        mainScreen = AppKit.NSScreen.mainScreen()
        secondaryScreens = set(screens).difference(set([mainScreen]))
        if len(secondaryScreens):
            screen = next(iter(secondaryScreens))
        else:
            screen = mainScreen
        origin = screen.frame().origin
        screensize = screen.frame().size
        scale = screen.backingScaleFactor()
        self.fig = pl.figure(figsize=(screensize.width/dpi, screensize.height/dpi), facecolor='k', edgecolor='k')
        mgr = self.fig.canvas.manager
        class ignore:
            def __init__(self):
                pass
            def __call__(self, *args, **kwargs):
                pass
            def __getattr__(self, attr):
                return self
        mgr.toolbar = ignore()
        #mgr.window.wm_geometry("=%dx%d%+d%+d" % (screensize.width, screensize.height, .75*origin.x, origin.y))
        mgr.resize(screensize.width, screensize.height)
        mgr.set_window_title('Blurt')
        #self.fig.set_figwidth(screensize.width/dpi)
        #self.fig.set_figheight(screensize.height/dpi)
        self.ax = pl.gca()
        #widget = self.fig.canvas.get_tk_widget()
        #widget.winfo_toplevel().lift()
        coreaudio.sleepDuration = .01
    def draw(self):
        self.onMainThread(self.pl.draw)

class Oscilloscope(Visualizer):
    def __init__(self):
        super().__init__()
        self.line = self.ax.plot(np.zeros(self.inBufSize))[0]
        self.ax.set_ylim(-.5,.5)
    def thread_consume(self, sequence):
        self.line.set_ydata(sequence)
        self.draw()

def set_foregroundcolor(ax, color):
     '''For the specified axes, sets the color of the frame, major ticks,
         tick labels, axis labels, title and legend
     '''
     for tl in ax.get_xticklines() + ax.get_yticklines():
         tl.set_color(color)
     for spine in ax.spines:
         ax.spines[spine].set_edgecolor(color)
     for tick in ax.xaxis.get_major_ticks():
         tick.label1.set_color(color)
     for tick in ax.yaxis.get_major_ticks():
         tick.label1.set_color(color)
     ax.axes.xaxis.label.set_color(color)
     ax.axes.yaxis.label.set_color(color)
     ax.axes.xaxis.get_offset_text().set_color(color)
     ax.axes.yaxis.get_offset_text().set_color(color)
     ax.axes.title.set_color(color)
     lh = ax.get_legend()
     if lh != None:
         lh.get_title().set_color(color)
         lh.legendPatch.set_edgecolor('none')
         labels = lh.get_texts()
         for lab in labels:
             lab.set_color(color)
     for tl in ax.get_xticklabels():
         tl.set_color(color)
     for tl in ax.get_yticklabels():
         tl.set_color(color)

def set_backgroundcolor(ax, color):
     '''Sets the background color of the current axes (and legend).
         Use 'None' (with quotes) for transparent. To get transparent
         background on saved figures, use:
         pp.savefig("fig1.svg", transparent=True)
     '''
     ax.patch.set_facecolor(color)
     lh = ax.get_legend()
     if lh != None:
         lh.legendPatch.set_facecolor(color)

class SpectrumAnalyzer(Visualizer):
    def __init__(self, Fs=96e3, Fc=0., NFFT=2048, noverlap=2048-256, window=None, duration=1., transpose=False, sides=1):
        super().__init__()
        self.Fs = Fs
        self.Fc = Fc
        self.NFFT = NFFT
        self.noverlap = noverlap
        if window is None:
            window = self.pl.mlab.window_hanning
        self.window = window(np.ones(self.NFFT))
        self.duration = duration
        self.transpose = transpose
        self.sides = sides
        self.advance = self.NFFT - self.noverlap
        self.columns = int(round(self.duration * self.Fs / self.advance))
        self.buffer = np.zeros((self.NFFT*self.sides/2, self.columns*2), np.float32)
        self.t = 0.
        self.window_phase = 0
        self.ax = self.pl.gca()
        box = self.ax.bbox.bounds
        self.fim = self.ax.imshow(self.buffer[:,:self.columns] if not self.transpose else self.buffer[:,:self.columns].T,
                                  vmin=0., vmax=1., extent=(self.t, self.t+self.duration, 0, self.Fs/2000.), aspect='auto', interpolation='nearest')
        self.ax.set_xlim(self.t, self.t+self.duration)
        self.ax.set_ylim(0, self.Fs/2000.)
        self.ax.patch.set_visible(False)
        self.ax.set_xlabel('Time (seconds)')
        self.ax.set_ylabel('Frequency (kHz)')
        self.ax.set_title('Time-Frequency Visualizer')
        self.fig.patch.set_facecolor('k')
        set_backgroundcolor(self.ax, 'k')
        set_foregroundcolor(self.ax, 'w')
        self.input_fragment = np.zeros(0, np.complex64)
    def thread_consume(self, input):
        stream = np.r_[self.input_fragment, input]
        n = max(1 + (stream.size-self.NFFT) // self.advance, 0)
        if n < 4: n = 0
        self.input_fragment = stream[n*self.advance:]
        if n > 0:
            idx = np.arange(self.NFFT)[:,np.newaxis] + self.advance * np.arange(n)[np.newaxis,:]
            input = stream[idx] * self.window[:,np.newaxis]
            input = np.fft.fftshift(np.fft.fft(input, axis=0), 0)
            input = (np.log10(np.abs(input)) / 5.) + 1
            k = np.array([-.1,-.3,1.2,-.3,-.1]) * 1.5
            for i in xrange(input.shape[1]):
                input[:,i] = np.convolve(input[:,i], k, 'same')
            input = input[:(2-self.sides)*self.NFFT/2]

            cols = self.columns
            phase = self.window_phase

            if phase+cols+n <= 2*cols:
                self.buffer[:,phase+cols:phase+cols+n] = input
            else:
                m = phase+n-cols
                self.buffer[:,m-n:] = input[:,:n-m]
                self.buffer[:,0:m] = input[:,-m:]
            self.buffer[:,phase:phase+n] = input

            phase = (phase + n) % cols
            self.window_phase = phase

            t = self.t
            b = self.buffer[:,phase:phase+cols]
            self.fim.set_data(b if not self.transpose else b.T)
            self.fim.set_extent((t, t+self.duration, 0, self.Fs/2000.))
            self.ax.set_xlim(t, t+self.duration)
            def onMainThread():
                self.fig.draw_artist(self.fig)
                self.fig.canvas.blit()
            self.onMainThread(onMainThread)
            self.t += float(n * self.advance) / self.Fs

def go():
    import matplotlib
    matplotlib.use('TkAgg')
    matplotlib.rcParams['toolbar'] = 'None'
    import coreaudio
    Fs = 48000
    sa = SpectrumAnalyzer(duration=3, Fs=Fs)
    coreaudio.record(sa, Fs)

if __name__ == '__main__':
    pass #go()


from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.shortcuts import render_to_response

def contact(request):
    errors = []
    if request.method == 'POST':
        if not request.POST.get('subject', ''):
            errors.append('Enter a subject.')
        if not request.POST.get('message', ''):
            errors.append('Enter a message.')
        if request.POST.get('email') and '@' not in request.POST['email']:
            errors.append('Enter a valid e-mail address.')
        if not errors:
            send_mail(
                request.POST['subject'],
                request.POST['message'],
                request.POST.get('email','noreply@texasibiz.net'),
                ['admin@texasibiz.net'], #email address where message is sent.
            )
            return HttpResponseRedirect('/thanks/')
    return render(request, 'contact.html',
        {'errors': errors})

def thanks(request):
    return render_to_response('thanks.html')


# (c) AlenPaulVarghese
# -*- coding: utf-8 -*-

from pathlib import Path
from typing import List

from pikepdf import Pdf

from tools.scaffold import AbstractTask

class RotatePdf(AbstractTask):
    def __init__(self, chat_id: int, message_id: int):
        super().__init__(chat_id, message_id)
        self.input_file: Path
        self.degree: int = 90
        self.page_range: List[int]

    def set_configuration(self, _path: Path, _range: List[int], _degree: int) -> None:
        self.input_file = _path
        self.page_range = _range
        self.degree = _degree

    def process(self):
        with Pdf.open(self.input_file) as input_pdf:
            for index in self.page_range:
                input_pdf.pages[index - 1].rotate(self.degree, False)
            input_pdf.save(self.cwd / self.filename)