import math
import time

import os

import processing
from qgis.core import *
from qgis.utils import *
from qgis.gui import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets
import sys
import pandas as pd

from .Andalusian_Population_loader import *
from .Andalusian_Population_startup1 import *

class InterfazDeCarga(QDialog):
    def __init__(self,parent,geometria):
        super().__init__()
        self.widget=QWidget()
        self.setWindowTitle('Cargando')
        self.setGeometry(geometria.x()+geometria.width()/4,geometria.y()+geometria.height()/4,300,150)
        self.setFocus();
        dlggLayout = QVBoxLayout(self)
        self.spinner=QtWaitingSpinner(self.widget)
        dlggLayout.addWidget(self.spinner)
        self.setLayout(dlggLayout)
        self.spinner.start()
        #ventana_error(titulo="Importación finalizada",mensaje="Proceso de importación finalizado correctamente")

    def cerrar(self):
        self.spinner.stop()
        self.close()

class VentanaError(QDialog):
    def __init__(self,parent=None,titulo="ERROR",mensaje="Se ha producido un error"):
        super().__init__()
        self.ventana_errores = QWidget(self)
        self.setWindowTitle(str(titulo))
        self.setGeometry(500, 400, 300, 150)
        vLayout = QVBoxLayout(self)
        self.ventana_errores.setLayout(vLayout)

        texto=QPlainTextEdit (str(mensaje))
        texto.setReadOnly(True)
        texto.setStyleSheet("background-color: transparent;")
        texto.setMaximumHeight(100)
        #texto.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)
        vLayout.addWidget(texto)
        vLayout.addStretch(1)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Close|QDialogButtonBox.Ok)
        self.buttonBox.setCenterButtons(False)
        self.buttonBox.accepted.connect(self.aceptar)
        self.buttonBox.rejected.connect(self.cerrar)
        vLayout.addWidget(self.buttonBox, alignment=Qt.AlignRight | Qt.AlignBottom)
        #vLayoutAux.addWidget(self.buttonBox)

    def cerrar(self):
        self.close()
    def aceptar(self):
        self.accept()

class InterfazMapa(QDialog):
    def __init__(self,parent=None,lista_url_capas250=[],TipoTasa=[]):
        super().__init__()
        self.TipoTasa=TipoTasa
        self.lista_url_capas250=lista_url_capas250

        #self.colores_inv=[0 for i in range(len(TipoTasa))]
        aux=["#00ff00","#009000","#ffff00","#ff9000","#ff0000"]
        self.color_lista=[aux for i in range(len(TipoTasa))]
        aux=[0 for i in range(len(aux))]
        self.condicion_lista=[aux for i in range(len(TipoTasa))]
        self.minimo=[0 for i in range(len(TipoTasa))]
        self.maximo=[1 for i in range(len(TipoTasa))]
        self.idCurrentRow=0

        self.setWindowTitle('Caracterización de la población andaluza')
        self.setGeometry(250, 180, 900, 700)
        self.main_widget = QtWidgets.QWidget(self)
        #self.main_widget.setFocus()

        dlgLayout = QVBoxLayout()
        self.main_widget.setLayout(dlgLayout)

        #Tabs

        self.tabwidget = QTabWidget()
        #tabwidget.addTab(inequidadVLayout, "Tab 1")

        nombres_capas=[]

        self.inequidadGUI()
        self.configuracionGUI()
        dlgLayout.addWidget(self.tabwidget, 0)
        self.setLayout(dlgLayout)

    def inequidadGUI(self):
        inequidadVLayout = QVBoxLayout()
        gb_archivo = QGroupBox("Archivo")
        verticalLayoutArchivo = QVBoxLayout()
        horzLayout01 = QHBoxLayout()
        #gb_archivo.setAlignment(Qt.AlignHCenter)
        gb_archivo.setStyleSheet('QGroupBox {'
        'border: 2px outset gray;'
        'border-radius: 5px;'
        'margin-top: 0.5em;}'
        'QGroupBox::title {'
        'subcontrol-origin: margin;'
        'left: 10px;'
        'padding: 0 3px;}')
        horzLayout01.addWidget(QLabel('Nombre de la imagen:'))
        self.nombre_fichero=QLineEdit('mapa')
        horzLayout01.addWidget(self.nombre_fichero)
        verticalLayoutArchivo.addLayout(horzLayout01)

        horzLayout02 = QHBoxLayout()
        btn_directorio = QPushButton('...')
        btn_directorio.setDefault(False)
        btn_directorio.setAutoDefault(False)
        horzLayout02.addWidget(QLabel('Directorio de la imagen:'))
        self.data_path=QLineEdit(str(QgsProject.instance().readPath("./")))
        horzLayout02.addWidget(self.data_path)
        horzLayout02.addWidget(btn_directorio)
        btn_directorio.clicked.connect(self.obtener_directorio)
        verticalLayoutArchivo.addLayout(horzLayout02)
        gb_archivo.setLayout(verticalLayoutArchivo)

        inequidadVLayout.addWidget(gb_archivo)

        gb_valor_referencia = QGroupBox("Valor de Referencia")
        gb_valor_referencia.setStyleSheet('QGroupBox {'
        'border: 2px inset gray;'
        'border-radius: 5px;'
        'margin-top: 0.5em;}'
        'QGroupBox::title {'
        'subcontrol-origin: margin;'
        'left: 10px;'
        'padding: 0 3px;}')
        verticalLayoutValorReferencia = QVBoxLayout()
        self.horzLayout2 = QHBoxLayout()
        inequidadVLayout.addWidget(QLabel(""))
        self.xqlineedit=QLineEdit("294326")
        self.yqlineedit=QLineEdit("4122700")
        self.horzLayout2.addWidget(QLabel('X:'))
        self.horzLayout2.addWidget(self.xqlineedit)
        self.horzLayout2.addStretch(1)
        self.horzLayout2.addWidget(QLabel('Y:'))
        self.horzLayout2.addWidget(self.yqlineedit)
        self.horzLayout2.addStretch(1)
        self.horzLayout2.addWidget(QLabel('Distancia de visualización del mapa(m):'))
        self.bufferVisionLineedit=QLineEdit("1000")
        self.horzLayout2.addWidget(self.bufferVisionLineedit)
        self.horzLayout2.addStretch(20)
        verticalLayoutValorReferencia.addLayout(self.horzLayout2)

        horzLayout03 = QHBoxLayout()
        horzLayout03.addWidget(QLabel("Tipología:"))
        self.myCombobox_valor_referencia = QComboBox()
        self.myCombobox_valor_referencia.addItem('Andalucia')
        self.myCombobox_valor_referencia.addItem('Provincia')
        self.myCombobox_valor_referencia.addItem('Municipio')
        self.myCombobox_valor_referencia.addItem('Buffer')
        self.myCombobox_valor_referencia.setMinimumContentsLength(15)
        self.myCombobox_valor_referencia.activated.connect(self.mostrar_tipologia_valor_referencia)
        horzLayout03.addWidget(self.myCombobox_valor_referencia)
        horzLayout03.addStretch(1)
        self.valorRererenciaQlabel=QLabel('')
        horzLayout03.addWidget(self.valorRererenciaQlabel)
        self.bufferlineedit= QLineEdit('1000')
        self.bufferlineedit.setVisible(False)
        horzLayout03.addWidget(self.bufferlineedit)
        self.myCombobox_valor_referencia_provincia=QComboBox()
        self.myCombobox_valor_referencia_provincia.addItem('PuntoXY')
        self.myCombobox_valor_referencia_provincia.addItem('Almería')
        self.myCombobox_valor_referencia_provincia.addItem('Cádiz')
        self.myCombobox_valor_referencia_provincia.addItem('Córdoba')
        self.myCombobox_valor_referencia_provincia.addItem('Granada')
        self.myCombobox_valor_referencia_provincia.addItem('Huelva')
        self.myCombobox_valor_referencia_provincia.addItem('Jaén')
        self.myCombobox_valor_referencia_provincia.addItem('Málaga')
        self.myCombobox_valor_referencia_provincia.addItem('Sevilla')
        self.myCombobox_valor_referencia_provincia.setMinimumContentsLength(15)
        self.myCombobox_valor_referencia_provincia.setVisible(False)
        horzLayout03.addWidget(self.myCombobox_valor_referencia_provincia)
        self.municipiolineedit= QLineEdit('PuntoXY')

        basepath = os.path.dirname(os.path.realpath(__file__)) + "\\"
        df=pd.read_csv(basepath + "tabla.csv",sep=";",decimal=",",header=0)
        # sorting by first name
        df.sort_values("municipio", inplace = True)

        # dropping ALL duplicte values
        df.drop_duplicates(subset ="municipio",
                             keep = 'first', inplace = True)
        names=df["municipio"]
        completer = QCompleter(names)
        completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.municipiolineedit.setCompleter(completer)

        self.municipiolineedit.setVisible(False)
        horzLayout03.addWidget(self.municipiolineedit)
        horzLayout03.addStretch(20)
        verticalLayoutValorReferencia.addLayout(horzLayout03)

        gb_valor_referencia.setLayout(verticalLayoutValorReferencia)

        inequidadVLayout.addWidget(gb_valor_referencia)

        inequidadVLayout.addWidget(QLabel(""))
        titulo_listwidget=QLabel("Tasa 250x250")
        titulo_listwidget.setFont(QFont('Arial', 12))
        VertTasaLayout = QVBoxLayout()
        VertTasaLayout.addWidget(titulo_listwidget)
        self.listwidget_capas250=QListWidget()
        #self.listwidget_capas250.setSelectionMode (QAbstractItemView.ExtendedSelection) # Hold CTRL to select multiple

        incr=0
        for malla250 in self.TipoTasa:
            malla250=malla250[1]
            self.listwidget_capas250.addItem(str(incr+1) + ". "+ malla250)#myQListWidgetItem
            self.listwidget_capas250.item(incr).setFont(QFont('Arial', 14))
            incr+=1
        self.listwidget_capas250.setSpacing(5)
        self.listwidget_capas250.itemClicked.connect(self.calculaSimbologia)
        VertTasaLayout.addWidget(self.listwidget_capas250)
        HorzListLayout = QHBoxLayout()
        HorzListLayout.addLayout(VertTasaLayout)

        titulo_listwidget=QLabel("Simbologia")
        titulo_listwidget.setFont(QFont('Arial', 12))
        VertSimbologiaLayout = QVBoxLayout()
        VertSimbologiaLayout.addWidget(titulo_listwidget)
        self.listwidget_capas250_simbologia=QListWidget()

        self.listwidget_capas250_simbologia.itemDoubleClicked.connect(self.cambiar_color)
        self.listwidget_capas250_simbologia.itemPressed.connect(self.deshabilitarImportacion)
        self.listwidget_capas250_simbologia.setFixedHeight(300)
        #self.listwidget_capas250.setSelectionMode (QAbstractItemView.ExtendedSelection) # Hold CTRL to select multiple
        self.listwidget_capas250_simbologia.setDragDropMode(QAbstractItemView.InternalMove)
        self.listwidget_capas250_simbologia.setAcceptDrops(True)
        VertSimbologiaLayout.addWidget(self.listwidget_capas250_simbologia)
        btnLayout1 = QHBoxLayout()
        self.btn1_0 = QPushButton('Eliminar')
        self.btn1_0.clicked.connect(self.eliminarItemSimbologia)
        self.btn1_0.setEnabled(False)
        btnLayout1.addWidget(self.btn1_0)
        btnLayout1.addStretch(1)
        self.btn1_1 = QPushButton('Añadir')
        self.btn1_1.clicked.connect(self.anadirSimbologia)
        self.btn1_1.setEnabled(False)
        btnLayout1.addWidget(self.btn1_1)
        btnLayout1.addStretch(1)
        self.btn1_2 = QPushButton('Invertir colores')
        self.btn1_2.clicked.connect(self.invertirColor)
        self.btn1_2.setEnabled(False)
        btnLayout1.addWidget(self.btn1_2)
        VertSimbologiaLayout.addLayout(btnLayout1)

        HorzListLayout.addLayout(VertSimbologiaLayout)
        inequidadVLayout.addLayout(HorzListLayout)

        self.checkbox_capa_tasa=QtWidgets.QCheckBox("Mantener la capa de la Tasa despues de la importación")
        inequidadVLayout.addWidget(self.checkbox_capa_tasa)
        self.checkbox_centro=QtWidgets.QCheckBox("Mantener la capa del punto central despues de la importación")
        inequidadVLayout.addWidget(self.checkbox_centro)
        self.checkbox_buffer=QtWidgets.QCheckBox("Mantener la capa buffer despues de la importación")
        inequidadVLayout.addWidget(self.checkbox_buffer)
        inequidadVLayout.addStretch(1)
        btnLayout = QHBoxLayout()
        btn1 = QPushButton('Cerrar')
        btn1.clicked.connect(self.cerrar)
        btnLayout.addWidget(btn1)
        btnLayout.addStretch(1)
        self.btn1_3 = QPushButton('Aplicar')
        self.btn1_3.clicked.connect(self.aplicarCambios)
        self.btn1_3.setEnabled(True)
        self.btn1_3.setDefault(True)
        self.btn1_3.setAutoDefault(True)
        btnLayout.addWidget(self.btn1_3)
        self.btn1_4 = QPushButton('Importar')
        self.btn1_4.clicked.connect(self.ejecutar_inequidad)
        self.btn1_4.setEnabled(False)
        btnLayout.addWidget(self.btn1_4)
        inequidadVLayout.addLayout(btnLayout)

        tab1=QWidget()
        tab1.setLayout(inequidadVLayout)
        self.tabwidget.addTab(tab1, "Mapa")

    def configuracionGUI(self):
        configuracionVLayout = QVBoxLayout()

        formLayout = QFormLayout()
        btnLayout = QHBoxLayout()

        self.url_ortofoto=QLineEdit(self.lista_url_capas250[0])
        self.url_municipios=QLineEdit(self.lista_url_capas250[1])
        self.url_gridpob=QLineEdit(self.lista_url_capas250[2])
        self.url_gridcatt=QLineEdit(self.lista_url_capas250[3])
        self.url_gridmort=QLineEdit(self.lista_url_capas250[4])
        self.texto_buffer=QLineEdit(self.lista_url_capas250[5])

        formLayout.addRow('Fuente capa ortofoto(WMS):', self.url_ortofoto)
        formLayout.addRow('Fuente capa municipios(WFS):', self.url_municipios)
        formLayout.addRow('Fuente capa grid de población(WFS):', self.url_gridpob)
        formLayout.addRow('Fuente capa gridcattp de uso del suelo(WFS):', self.url_gridcatt)
        formLayout.addRow('Fuente capa grid de mortalidad(WFS):', self.url_gridmort)
        formLayout.addRow('Nombre capa buffer:', self.texto_buffer)
        configuracionVLayout.addLayout(formLayout)

        btn1 = QPushButton('Cerrar')
        btn1.clicked.connect(self.cerrar)
        btnLayout.addWidget(btn1)
        btnLayout.addStretch(1)
        btn2 = QPushButton('Aplicar')
        btn2.clicked.connect(self.AplicarUrl)
        configuracionVLayout.addStretch(1)
        btnLayout.addWidget(btn2)
        configuracionVLayout.addLayout(btnLayout)

        tab3=QWidget()
        tab3.setLayout(configuracionVLayout)
        self.tabwidget.addTab(tab3, "Configuracion")
    def AplicarUrl(self):
        layer_ortofoto = QgsRasterLayer(self.url_ortofoto.text(), "Capa ortofoto", "WMS")
        layer_municipios = QgsVectorLayer(self.url_municipios.text(), "Capa municipios", "WFS")
        layer_pob = QgsVectorLayer(self.url_gridpob.text(), "Capa pob", "WFS")
        layer_catt = QgsVectorLayer(self.url_gridcatt.text(), "Capa catt", "WFS")
        layer_mort = QgsVectorLayer(self.url_gridmort.text(), "Capa mort", "WFS")
        if not layer_ortofoto.isValid():
            VentanaError(mensaje="La fuente de la capa ortofoto no es válida").exec()
            return
        elif not layer_municipios.isValid():
            VentanaError(mensaje="La fuente de la capa municipios no es válida").exec()
            return
        elif not layer_pob.isValid():
            VentanaError(mensaje="La fuente de la capa grid de población no es válida").exec()
            return
        elif not layer_catt.isValid():
            VentanaError(mensaje="La fuente de la capa gridcattp de uso del suelo no es válida").exec()
            return
        elif not layer_mort.isValid():
            VentanaError(mensaje="La fuente de la capa grid de mortalidad no es válida").exec()
            return
        self.lista_url_capas250[0]=self.url_ortofoto.text()
        self.lista_url_capas250[1]=self.url_municipios.text()
        self.lista_url_capas250[2]=self.url_gridpob.text()
        self.lista_url_capas250[3]=self.url_gridcatt.text()
        self.lista_url_capas250[4]=self.url_gridmort.text()
        self.lista_url_capas250[5]=self.texto_buffer.text()

        if (ComprobarCambiosGridTXT(self.lista_url_capas250)):
            if(VentanaError(titulo="Aplicar cambios",mensaje="Para aplicar los cambios, QGIS se cerrará y cuando se ejecute de nuevo el Plugin, "
            "se llevará a cabo la instalación de la/s nueva/s capa/s.\n\n¿Desea continuar?").exec()):
                ActualizarUrl(self.lista_url_capas250)
                EliminarTablaCSV()
                sys.exit()
            else:#Si el usuario no acepta, se sale sin actualizar la Url en el TXT
                return
        ActualizarUrl(self.lista_url_capas250)
    def aplicarCambios(self):
        self.getSimbologia()
        self.muestraSimbologia()
        self.btn1_4.setEnabled(True)
        self.btn1_4.setDefault(True)
        self.btn1_4.setAutoDefault(True)
    def deshabilitarImportacion(self):
        self.btn1_4.setEnabled(False)
        self.btn1_4.setDefault(False)
        self.btn1_4.setAutoDefault(False)
        self.btn1_3.setDefault(True)
        self.btn1_3.setAutoDefault(True)
    def cerrar(self):
        self.close()
    def ejecutar_inequidad(self): #HACER QUE SE VEA POR DELANTE DEL QDIALOG
        #interfazCarga=InterfazDeCarga(None,self.geometry())
        #interfazCarga.exec()
        self.seleccionar_capas_criterio(importar=1)
        #ventana_error(titulo="Importación finalizada",mensaje="Proceso de importación finalizado correctamente")
        #interfazCarga.cerrar()
    def invertirColor(self):
        self.color_lista[self.idCurrentRow].reverse()
        self.muestraSimbologia()
        self.deshabilitarImportacion()
    def obtener_directorio(self):
        dialog = QFileDialog()
        self.data_path.setText(dialog.getExistingDirectory(None, 'Directorio de la imagen',self.data_path.text()))
    def calculaSimbologia(self):
        #Se inicializan las condiciones
        self.idCurrentRow=self.listwidget_capas250.currentRow()
        self.seleccionar_capas_criterio(importar=0)
        if self.listwidget_capas250_simbologia.count()==0:
            for id in range(len(self.color_lista[self.idCurrentRow])):
                self.CreaItemSimbologia(id)
        self.muestraSimbologia()
        self.btn1_0.setEnabled(True)
        self.btn1_1.setEnabled(True)
        self.btn1_2.setEnabled(True)
        self.deshabilitarImportacion()
    def muestraSimbologia(self):
        for incr in range(len(self.color_lista[self.idCurrentRow])):
            self.listwidget_capas250_simbologia.item(incr).widgetText.setText(str(self.condicion_lista[self.idCurrentRow][incr]))
            self.listwidget_capas250_simbologia.item(incr).widgetLabel.setStyleSheet(
                "border: 1px solid black;min-width: 20px;min-height: 20px;background-color: " + str(self.color_lista[self.idCurrentRow][incr]))
        self.actualiza_leyenda()
    def CreaItemSimbologia(self,id):
        myQListWidgetItem=clase_colores(id=id,color=self.color_lista[self.idCurrentRow][id],condicion=self.condicion_lista[self.idCurrentRow][id])
        self.listwidget_capas250_simbologia.addItem(myQListWidgetItem)#myQListWidgetItem
        self.listwidget_capas250_simbologia.setItemWidget(myQListWidgetItem, myQListWidgetItem.widget)
        self.listwidget_capas250_simbologia.item(id).widgetText.editingFinished.connect(self.actualiza_leyenda)
    def eliminarItemSimbologia(self):
        id=self.listwidget_capas250_simbologia.currentRow()
        if id>=0:
            self.listwidget_capas250_simbologia.takeItem(id)
            self.color_lista[self.idCurrentRow].pop(id)
            self.condicion_lista[self.idCurrentRow].pop(id)
        if self.listwidget_capas250_simbologia.count():
            self.actualiza_leyenda()
        self.deshabilitarImportacion()
    def actualiza_leyenda(self):
        for id in range(self.listwidget_capas250_simbologia.count()-1):
            legend1=self.listwidget_capas250_simbologia.item(id).widgetText.text()
            legend2=self.listwidget_capas250_simbologia.item(id+1).widgetText.text()
            texto=str(legend1) + " - " + str(legend2)
            self.listwidget_capas250_simbologia.item(id).widgetLabelLeyenda.setText(texto)
        #Ultimo valor
        self.listwidget_capas250_simbologia.item(id+1).widgetLabelLeyenda.setText(str(legend2)+" - "+str(self.maximo[self.idCurrentRow]))
    def mostrar_tipologia_valor_referencia(self):
        id=self.myCombobox_valor_referencia.currentIndex()
        if (id==0):#Andalucia
            self.valorRererenciaQlabel.setText('')
            self.bufferlineedit.setVisible(False)
            self.myCombobox_valor_referencia_provincia.setVisible(False)
            self.municipiolineedit.setVisible(False)
        elif(id==1):#Provincia
            self.valorRererenciaQlabel.setText('Provincia:')
            self.bufferlineedit.setVisible(False)
            self.myCombobox_valor_referencia_provincia.setVisible(True)
            self.municipiolineedit.setVisible(False)
        elif(id==2):#Municipio
            self.valorRererenciaQlabel.setText('Municipio:')
            self.bufferlineedit.setVisible(False)
            self.myCombobox_valor_referencia_provincia.setVisible(False)
            self.municipiolineedit.setVisible(True)
        elif (id==3):#Buffer
            self.valorRererenciaQlabel.setText('Dist. buffer(m):')
            self.bufferlineedit.setVisible(True)
            self.myCombobox_valor_referencia_provincia.setVisible(False)
            self.municipiolineedit.setVisible(False)
    def obtener_minmax(self,tipo=0,lista=[0,100]):
        CifRed=1 #numero de cifras de redondeo
        if(tipo==0):
            self.minimo[self.idCurrentRow]=lista[0]
            self.maximo[self.idCurrentRow]=lista[1]
            minimo=self.minimo[self.idCurrentRow]
            maximo=self.maximo[self.idCurrentRow]
            incr=(maximo-minimo)/5
            if not(len(self.condicion_lista[self.idCurrentRow])):
                self.condicion_lista[self.idCurrentRow]=[round(float(minimo),CifRed),round(float(minimo+incr),CifRed),round(float(minimo+2*incr),CifRed),
                round(float(minimo+3*incr),CifRed),round(float(minimo+4*incr),CifRed)]
        elif(tipo==1):
            self.minimo[self.idCurrentRow]=round(float(lista[0]),CifRed)
            self.maximo[self.idCurrentRow]=round(float(lista[5]),CifRed)
            self.condicion_lista[self.idCurrentRow]=[round(float(lista[0]),CifRed),round(float(lista[1]),CifRed),round(float(lista[2]),CifRed),
            round(float(lista[3]),CifRed),round(float(lista[4]),CifRed)]
    def getSimbologia(self):
        for id in range(self.listwidget_capas250_simbologia.count()):
            self.color_lista[self.idCurrentRow][id]=str(self.listwidget_capas250_simbologia.item(id).widgetLabel.palette().button().color().name())
            self.condicion_lista[self.idCurrentRow][id]=str(self.listwidget_capas250_simbologia.item(id).widgetText.text())
    def anadirSimbologia(self):
        color="#000000"
        condicion=0
        id=self.listwidget_capas250_simbologia.count()
        self.color_lista[self.idCurrentRow].append(str(color))
        self.condicion_lista[self.idCurrentRow].append(str(condicion))
        self.CreaItemSimbologia(id)
        self.deshabilitarImportacion()
    def cambiar_color(self):
        color_nuevo_inequidad_1=QColorDialog.getColor().name()
        id=self.listwidget_capas250_simbologia.currentRow()
        self.listwidget_capas250_simbologia.item(id).widgetLabel.setStyleSheet("border: 1px solid black;min-width: 20px;min-height: 20px;background-color: " + color_nuevo_inequidad_1)
        self.deshabilitarImportacion()
    def getcondTasa(self,zLayer):
        condTasa=0
        id=self.myCombobox_valor_referencia.currentIndex()
        if id==0:#Andalucia
            zLayer.setName("Quintiles respecto a Andalucia")
            pass
        elif id==1:#Provincia
            condTasa=self.myCombobox_valor_referencia_provincia.currentText()
            zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
        elif id==2:#Municipio
            condTasa=self.municipiolineedit.text()
            zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            """
            df=df[df['municipio']==condTasa]
            print(df.size)
            if (df.size>0):
                condTasa=float(df.iloc[0]['cmun'])
            """
        elif id==3:#Buffer
            condTasa=[]
            for f in zLayer.getFeatures():
                    condTasa.append(float(f['grd_floaid'].replace('.','')))
            zLayer.setName("Quintiles  respecto a buffer de " + str(self.bufferVisionLineedit.text()) + "m ")

        return condTasa
    def seleccionar_capas_criterio(self,importar=0):
        tipoVersion=getVersion()
        numDecimales=1
        IdTasa=self.listwidget_capas250.currentRow()
        myTargetField=self.TipoTasa[IdTasa][0]
        NombreLeyenda=self.TipoTasa[IdTasa][1]
        tamano_buffer=float(self.bufferVisionLineedit.text())
        x=float(self.xqlineedit.text())
        y=float(self.yqlineedit.text())
        basepath = os.path.dirname(os.path.realpath(__file__)) + "\\"
        df=pd.read_csv(basepath + "tabla.csv",sep=";",decimal=",",header=0)
        if tipoVersion==1:
            tLayer=QgsVectorLayer("Point", "punto", "memory")
            vLayer=QgsVectorLayer("Polygon", "buffer", "memory")
            tLayer.setCrs(QgsCoordinateReferenceSystem(25830))
            vLayer.setCrs(QgsCoordinateReferenceSystem(25830))
        else:
            tLayer=QgsVectorLayer("Point?crs=EPSG:25830", "punto", "memory")
            vLayer=QgsVectorLayer("Polygon?crs=EPSG:25830", "buffer", "memory")
        myField = QgsField( 'id', QVariant.Int )
        vLayer.dataProvider().addAttributes([myField])
        vLayer.updateFields()
        point_centro = QgsGeometry.fromPointXY(QgsPointXY(float(x), float(y)))#yqlineedit.text()
        vpr = tLayer.dataProvider()
        f = QgsFeature()
        f.setGeometry(point_centro)
        vpr.addFeatures([f])
        tLayer.updateExtents()
        tFeats = tLayer.getFeatures()

        for tfeat in tLayer.getFeatures():
            geom = tfeat.geometry()
            buffer = geom.buffer(tamano_buffer, 5)
            feat_vista=tfeat
            tfeat.setGeometry(buffer)
            vLayer.dataProvider().addFeatures([tfeat])

        myTargetField=str(myTargetField)
        NombreLeyenda=str(NombreLeyenda)
        IdRereferencia=self.myCombobox_valor_referencia.currentIndex()
        Layer=AnadirLayerQGIS(url=self.lista_url_capas250[2],nombre="Capa grid de poblacion", tipoCapa="WFS")

        if (IdTasa==0):#Poblacion Total
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            poblacion=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                    poblacion.append(float(f["pob_tot"]))
                    if all(flag > 0 for flag in [poblacion[-1]]):
                        Tasa.append(float(poblacion[-1]))
                    else:
                        Tasa.append(float(-1))

                    zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            Tasa = df[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=df['pob_tot']
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==1):#Tasa menores 15 años
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            poblacion=[]
            poblacion15=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                    poblacion.append(float(f["pob_tot"]))
                    poblacion15.append(float(f["edad0015"]))
                    if all(flag > 0 for flag in [poblacion[-1],poblacion15[-1]+0.1]):
                        Tasa.append(round(float(100*poblacion15[-1]/poblacion[-1]),numDecimales))
                    else:
                        Tasa.append(float(-1))

                    zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            dfReducido=df[(df['edad0015'] >= 0) & (df['pob_tot'] > 0)]
            Tasa = dfReducido[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=100*(dfReducido['edad0015']/dfReducido['pob_tot'])
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})
            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==2):#Tasa mayores 65 años
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            poblacion=[]
            poblacion65=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                    poblacion.append(float(f["pob_tot"]))
                    poblacion65.append(float(f["edad65_"]))
                    if all(flag > 0 for flag in [poblacion[-1],poblacion65[-1]+0.1]):
                        Tasa.append(round(float(100*poblacion65[-1]/poblacion[-1]),numDecimales))
                    else:
                        Tasa.append(float(-1))

                    zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            dfReducido=df[(df['edad65_'] >= 0) & (df['pob_tot'] > 0)]
            Tasa = dfReducido[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=100*(dfReducido['edad65_']/dfReducido['pob_tot'])
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==3):#Poblacion extranejra
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            den=[]
            num=[]
            aux1=[]
            aux2=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                    den.append(float(f['pob_tot']))
                    aux1.append(float(f['esp']))
                    aux2.append(float(f['ue15']))
                    if aux2[-1]>0:
                        num.append(float(den[-1]-aux1[-1]-aux2[-1]))
                    else:
                        num.append(float(den[-1]-aux1[-1]))
                    num.append(float(den[-1]-aux1[-1]-aux2[-1]))
                    if all(flag > 0 for flag in [aux1[-1]+0.1,aux2[-1]+0.1,den[-1],num[-1]+0.1]):
                        Tasa.append(round(float(100*num[-1]/den[-1]),numDecimales))
                    else:
                        Tasa.append(float(-1))

                    zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            dfReducido=df[(df['pob_tot']-df['esp']-df['ue15'] >= 0) & (df['esp'] >= 0) & (df['ue15'] >= 0) & (df['pob_tot'] > 0)]
            Tasa = dfReducido[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=100*((dfReducido['pob_tot']-dfReducido['esp']-dfReducido['ue15'])/dfReducido['pob_tot'])
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==4):#Poblacion activa
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            den=[]
            num=[]
            aux1=[]
            aux2=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                aux1.append(float(f['edad0015']))
                aux2.append(float(f['edad65_']))
                den.append(float(f['pob_tot']-(aux1[-1]+aux2[-1])))
                num.append(float(f['afil_ss']))
                if all(flag > 0 for flag in [aux1[-1]+0.1,aux2[-1]+0.1,den[-1],num[-1]+0.1]):
                    Tasa.append(round(float(100*num[-1]/den[-1]),numDecimales))
                else:
                    Tasa.append(float(-1))

                zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            condTasa=self.getcondTasa(zLayer)
            dfReducido=df[(df['afil_ss'] >= 0) & (df['pob_tot'] > 0) & (f['pob_tot']-(f['edad0015']+f['edad65_'])>0)]
            Tasa = dfReducido[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=100*((dfReducido['afil_ss'])/(dfReducido['pob_tot']-(dfReducido['edad0015']+dfReducido['edad65_'])))
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})
            Tasa.loc[Tasa[myTargetField] > 100, myTargetField] = 100 #Se satura a 100%

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==5):#Paro registrado
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            den=[]
            num=[]
            aux1=[]
            aux2=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                aux1.append(float(f['edad0015']))
                aux2.append(float(f['edad65_']))
                den.append(float(f['pob_tot']-(aux1[-1]+aux2[-1])))
                num.append(float(f['demp_pr']))
                if all(flag > 0 for flag in [aux1[-1]+0.1,aux2[-1]+0.1,den[-1],num[-1]+0.1]):
                    Tasa.append(round(float(100*num[-1]/den[-1]),numDecimales))
                else:
                    Tasa.append(float(-1))

                zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            dfReducido=df[(df['demp_pr'] >= 0) & (df['pob_tot'] > 0) & (f['pob_tot']-(f['edad0015']+f['edad65_'])>0)]
            Tasa = dfReducido[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=100*((dfReducido['demp_pr'])/(dfReducido['pob_tot']-(dfReducido['edad0015']+dfReducido['edad65_'])))
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==6):#RMEs Total
            Layer2=AnadirLayerQGIS(url=self.lista_url_capas250[4],nombre="Capa grid RMEs", tipoCapa="WFS")
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})
                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))

                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer2,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})
                zLayer2=interseccion['OUTPUT']
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            rme=[]
            Tasa=[]
            i=0
            for f in zLayer.getFeatures():
                for f2 in zLayer2.getFeatures():
                    if f2.geometry().equals(f.geometry()):
                        rme.append(float(f2["RMES_A00"]))
                        if all(flag > 0 for flag in [rme[-1]]):
                            Tasa.append(float(rme[-1]))
                        else:
                            Tasa.append(float(-1))

                        zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            Tasa = df[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=df['RMES_A00']
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)
        elif (IdTasa==7):#RMEs 45-65
            Layer2=AnadirLayerQGIS(url=self.lista_url_capas250[4],nombre="Capa grid RMEs", tipoCapa="WFS")
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})
                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))

                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer2,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})
                zLayer2=interseccion['OUTPUT']
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            rme=[]
            Tasa=[]
            i=0
            for f in zLayer.getFeatures():
                for f2 in zLayer2.getFeatures():
                    if f2.geometry().equals(f.geometry()):
                        rme.append(float(f2["RMES_A45"]))
                        if all(flag > 0 for flag in [rme[-1]]):
                            Tasa.append(float(rme[-1]))
                        else:
                            Tasa.append(float(-1))

                        zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            Tasa = df[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=df['RMES_A45']
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==8):#RMEs >65
            Layer2=AnadirLayerQGIS(url=self.lista_url_capas250[4],nombre="Capa grid RMEs", tipoCapa="WFS")
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})
                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))

                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer2,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})
                zLayer2=interseccion['OUTPUT']
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            rme=[]
            Tasa=[]
            i=0
            for f in zLayer.getFeatures():
                for f2 in zLayer2.getFeatures():
                    if f2.geometry().equals(f.geometry()):
                        rme.append(float(f2["RMES_A65"]))
                        if all(flag > 0 for flag in [rme[-1]]):
                            Tasa.append(float(rme[-1]))
                        else:
                            Tasa.append(float(-1))

                        zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            Tasa = df[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=df['RMES_A65']
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        elif (IdTasa==9):#Tasa mujeres
            if tipoVersion==1:
                interseccion=processing.run("qgis:extractbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'OUTPUT':'TEMPORARY_OUTPUT'})

                zLayer=interseccion['OUTPUT']
                zLayer.setName(str(NombreLeyenda))
            else:
                interseccion=processing.run("qgis:selectbylocation",
                {'INPUT':Layer,
                'PREDICATE':0,
                'INTERSECT':vLayer,
                'METHOD':0})
                zLayer = interseccion.materialize(QgsFeatureRequest().setFilterFids(interseccion.selectedFeatureIds()))
                zLayer.setName(str(NombreLeyenda))

            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()
            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            poblacion=[]
            poblacionm=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                    poblacion.append(float(f["pob_tot"]))
                    poblacionm.append(float(f["pob_m"]))
                    if all(flag > 0 for flag in [poblacion[-1],poblacionm[-1]+0.1]):
                        Tasa.append(round(float(100*poblacionm[-1]/poblacion[-1]),numDecimales))
                    else:
                        Tasa.append(float(-1))

                    zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])

            zLayer.commitChanges()
            zLayer.updateFields()

            #A partir de aqui es donde se modifica para cada Tasa
            condTasa=self.getcondTasa(zLayer)
            if condTasa=="PuntoXY":
                condTasa=calcularPuntoXY(Tipo=IdRereferencia,tLayer=tLayer,lista_url_capas250=self.lista_url_capas250)
                if IdRereferencia==1:
                    zLayer.setName("Quintiles respecto a la provincia: " + condTasa)
                elif IdRereferencia==2:
                    zLayer.setName("Quintiles respecto al municipio: " + condTasa)
            dfReducido=df[(df['pob_m'] >= 0) & (df['pob_tot'] > 0)]
            Tasa = dfReducido[['grd_floaid','municipio','cmun']]
            Tasa[myTargetField]=100*(dfReducido['pob_m']/dfReducido['pob_tot'])
            Tasa=Tasa[(Tasa[myTargetField] >= 0)]
            Tasa=Tasa.round({myTargetField:numDecimales})

            (minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo)=calcularValorReferencia(Tipo=IdRereferencia, Tasa=Tasa, condTasa=condTasa)

        """
        elif (IdTasa==3):#muj/hom
            Layer=AnadirLayerQGIS(url=self.lista_url_capas250[2],nombre="Capa grid de poblacion", tipoCapa="WFS")
            #Layer = QgsProject.instance().mapLayersByName("gridpob:gridpob_250")[0]  #gridpob:gridpob_250
            interseccion=processing.run("qgis:extractbylocation",
            {'INPUT':Layer,
            'PREDICATE':0,
            'INTERSECT':vLayer,
            'OUTPUT':'TEMPORARY_OUTPUT'})

            zLayer=interseccion['OUTPUT']
            zLayer.setName(NombreLeyenda)
            myField = QgsField( myTargetField, QVariant.Double )
            zLayer.dataProvider().addAttributes([myField])
            zLayer.updateFields()

            #QgsProject.instance().addMapLayer(zLayer)

            prov = zLayer.dataProvider()
            numero_tasa=zLayer.fields().indexOf(myTargetField)
            zLayer.startEditing()

            gidmp=[]
            hombre=[]
            mujer=[]
            Tasa=[]
            for f in zLayer.getFeatures():
                    gidmp.append(int(f["gidmp"]))
                    hombre.append(float(f["pob_h"]))
                    mujer.append(float(f["pob_m"]))
                    if all(flag > 0 for flag in [mujer[-1],hombre[-1]+0.1]):
                        Tasa.append(round(float(mujer[-1]/hombre[-1]),numDecimales))
                    else:
                        Tasa.append(float(-1))

                    zLayer.changeAttributeValue(f.id(), numero_tasa, Tasa[-1])
            zLayer.commitChanges()
            zLayer.updateFields()
            zLayer.updateExtents()
            zFeats = zLayer.getFeatures()

            dict={'gidmp':gidmp, myTargetField:Tasa}
            df=pd.DataFrame(dict)
            df2=df[df[myTargetField] >= 0]
            df2.sort_values("gidmp", inplace = True)
            df2.drop_duplicates(subset ="gidmp",keep = 'first', inplace = True)
            minimo=df2[myTargetField].min()
            percentil_20=df2[myTargetField].quantile(0.2)
            percentil_40=df2[myTargetField].quantile(0.4)
            percentil_60=df2[myTargetField].quantile(0.6)
            percentil_80=df2[myTargetField].quantile(0.8)
            maximo=df2[myTargetField].max()
            """

        #id=listwidget_capas250.currentRow()
        if importar==0:
            self.obtener_minmax(tipo=1,lista=[minimo,percentil_20,percentil_40,percentil_60,percentil_80,maximo])
        #listwidget_capas250_simbologia.item(IdTasa).actualiza_condicion()

        if (importar==1):
            #print(df2.describe(include='all') )

            myRangeList = []

            #QgsProject.instance().addMapLayer(zLayer)
            graduated_renderer = QgsGraduatedSymbolRenderer()
            lista_cond=self.condicion_lista[self.idCurrentRow]
            max_cond=self.maximo[self.idCurrentRow]
            lista_col=self.color_lista[self.idCurrentRow]
            for id in range(len(self.color_lista[self.idCurrentRow])-1):
                myColour = QColor(str(lista_col[id]))
                mySymbol2 = QgsSymbol.defaultSymbol(zLayer.geometryType())
                mySymbol2.setColor(myColour)
                mySymbol2.setOpacity(0.5)
                if tipoVersion==1:
                    graduated_renderer.addClassRange(QgsRendererRange(QgsClassificationRange(str(lista_cond[id])+' - '+str(lista_cond[id+1]), float(lista_cond[id]), float(lista_cond[id+1])), mySymbol2))
                else:
                    myRange2 = QgsRendererRange(float(lista_cond[id]), float(lista_cond[id+1]), mySymbol2,'Group 1')
                    myRangeList.append(myRange2)
                    #graduated_renderer.addClassRange(QgsRendererRange(float(lista_cond[id]), float(lista_cond[id+1])), mySymbol2,'Group 1')

            myColour = QColor(str(lista_col[id+1]))
            mySymbol2 = QgsSymbol.defaultSymbol(zLayer.geometryType())
            mySymbol2.setColor(myColour)
            mySymbol2.setOpacity(0.5)
            if tipoVersion==1:
                graduated_renderer.addClassRange(QgsRendererRange(QgsClassificationRange(str(lista_cond[id+1])+' - '+str(max_cond), float(lista_cond[id+1]), float(max_cond)), mySymbol2))
            else:
                myRange2=QgsRendererRange(float(lista_cond[id+1]), float(max_cond), mySymbol2,'Group 1')
                myRangeList.append(myRange2)
                graduated_renderer = QgsGraduatedSymbolRenderer('', myRangeList)

            # create renderer object
            graduated_renderer.setClassAttribute(myTargetField)
            zLayer.setRenderer(graduated_renderer)
            zLayer.triggerRepaint()

            #Se añade el label
            if (tamano_buffer<=2000):#Solo si está a menos de 2Km
                layer_settings  = QgsPalLayerSettings()
                text_format = QgsTextFormat()
                text_format.setFont(QFont("Arial", 6))
                buffer_settings = QgsTextBufferSettings()
                buffer_settings.setEnabled(True)
                buffer_settings.setSize(1)
                buffer_settings.setColor(QColor("white"))
                text_format.setBuffer(buffer_settings)
                layer_settings.setFormat(text_format)
                layer_settings.fieldName = myTargetField
                layer_settings.placement = 1
                layer_settings.enabled = True
                layer_settings = QgsVectorLayerSimpleLabeling(layer_settings)
                zLayer.setLabelsEnabled(True)
                zLayer.setLabeling(layer_settings)
                zLayer.triggerRepaint()

            self.importar_inequidad(zLayer,vLayer,tLayer,myTargetField,NombreLeyenda)
    def importar_inequidad(self,zLayer,vLayer,tLayer,TipoAbreviado,TituloLeyenda):#Capa de Tasa, Capa buffer, Capa punto, nombre archivo, titulo leyenda
        tamano_buffer=float(self.bufferVisionLineedit.text())
        borrar_buffer=not(self.checkbox_buffer.isChecked())
        borrar_centro=not(self.checkbox_centro.isChecked())
        borrar_capa_tasa=not(self.checkbox_capa_tasa.isChecked())
        vLayer.setName(self.texto_buffer.text()+ " " +str(tamano_buffer) + "m")
        uLayer=AnadirLayerQGIS(url=self.lista_url_capas250[0],nombre="Ortofoto", tipoCapa="WMS")
        QgsProject.instance().addMapLayer(uLayer)
        lblLayer=AnadirLayerQGIS(url=self.lista_url_capas250[1],nombre="Capa municipios", tipoCapa="WFS")
        QgsProject.instance().addMapLayer(lblLayer)
        AnadirLayerQGIS(url=vLayer,nombre="aux", tipoCapa="WFS",layer=1)
        QgsProject.instance().addMapLayer(vLayer)
        AnadirLayerQGIS(url=zLayer,nombre="aux", tipoCapa="WFS",layer=1)
        QgsProject.instance().addMapLayer(zLayer)
        AnadirLayerQGIS(url=tLayer,nombre="aux", tipoCapa="WFS",layer=1)
        QgsProject.instance().addMapLayer(tLayer)

        symbol = QgsMarkerSymbol.createSimple({'name': 'circle', 'color': 'red'})
        tLayer.renderer().setSymbol(symbol)
        tLayer.triggerRepaint()

        symbol = QgsFillSymbol.createSimple({'name': 'circle', 'width_border' : '0.66', 'style' : 'no'})
        vLayer.renderer().setSymbol(symbol)
        vLayer.triggerRepaint()

        wLayername = "buffer_vista"
        wLayer=QgsVectorLayer("Polygon", wLayername, "memory")
        QgsProject.instance().addMapLayer(wLayer)
        myField = QgsField( 'id', QVariant.Double )
        wLayer.dataProvider().addAttributes([myField])
        wLayer.updateFields()

        uLayer = QgsProject.instance().mapLayersByName(uLayer.name())[0]
        lblLayer = QgsProject.instance().mapLayersByName(lblLayer.name())[0]
        wLayer.setCrs(uLayer.crs())
        wFeats = wLayer.getFeatures()

        symbol = QgsFillSymbol.createSimple({'name': 'square', 'width_border' : '0.66', 'style' : 'no'})
        lblLayer.renderer().setSymbol(symbol)
        layer_settings  = QgsPalLayerSettings()
        text_format = QgsTextFormat()
        text_format.setFont(QFont("Arial", 8))
        buffer_settings = QgsTextBufferSettings()
        buffer_settings.setEnabled(True)
        buffer_settings.setSize(1)
        buffer_settings.setColor(QColor("white"))
        text_format.setBuffer(buffer_settings)
        layer_settings.setFormat(text_format)
        layer_settings.fieldName = "nombre"
        layer_settings.placement = 1
        layer_settings.enabled = True
        layer_settings = QgsVectorLayerSimpleLabeling(layer_settings)
        lblLayer.setLabelsEnabled(True)
        lblLayer.setLabeling(layer_settings)
        lblLayer.triggerRepaint()

        for feat_vista in tLayer.getFeatures():
            geom = feat_vista.geometry()
            dist=float(self.bufferVisionLineedit.text())
            buffer_vista = geom.buffer(dist+0.5*dist, 5)
            feat_vista.setGeometry(buffer_vista)
            wLayer.dataProvider().addFeatures([feat_vista])

        project = QgsProject.instance()
        layout = QgsPrintLayout(project)
        layout.initializeDefaults()
        layout.renderContext().setDpi(150)
        map = QgsLayoutItemMap(layout)
        map.setRect(QRectF(0, 0, 100, 100))
        map.setExtent(wLayer.extent())
        map.setLayers([tLayer,vLayer,lblLayer,zLayer,uLayer])
        map.setBackgroundColor(QColor(255, 255, 255))
        map.attemptResize(QgsLayoutSize(1753,1240, QgsUnitTypes.LayoutPixels))
        layout.addLayoutItem(map)

        legend = QgsLayoutItemLegend(layout)
        legend.setLinkedMap(map)
        legend.setLegendFilterByMapEnabled(True)
        layerTree = QgsLayerTree()
        layers_name = [tLayer.name(),vLayer.name(),zLayer.name()]
        #layers = [i for i in QgsProject().instance().mapLayers().values() if i.name() in layer_names]
        #for l in layers:
        #    layerTree.addLayer(l)
        for l_name in layers_name:
            layerTree.addLayer(QgsProject.instance().mapLayersByName(l_name)[0])

        legend.model().setRootGroup(layerTree)

        legend.setTitle(str(TituloLeyenda))
        legend.setStyleFont(QgsLegendStyle.Title, QFont("Comic Sans MS", 18))
        legend.setStyleFont(QgsLegendStyle.SymbolLabel, QFont("Comic Sans MS", 14))
        layout.addLayoutItem(legend)
        legend.attemptMove(QgsLayoutPoint(15, 10, QgsUnitTypes.LayoutPixels))
        legend.setFrameEnabled(True)
        legend.refresh()

        pdf_path = os.path.join(self.data_path.text(), self.nombre_fichero.text() + "_" + str(TipoAbreviado) + '.png')
        exporter = QgsLayoutExporter(layout)
        exporter.exportToImage(pdf_path, QgsLayoutExporter.ImageExportSettings())
        #Borrar documentos
        QgsProject.instance().removeMapLayer(wLayer)
        del wLayer
        if borrar_centro:
            QgsProject.instance().removeMapLayer(tLayer)
            del tLayer
        if borrar_buffer:
            QgsProject.instance().removeMapLayer(vLayer)
            del vLayer
        if borrar_capa_tasa:
            QgsProject.instance().removeMapLayer(zLayer)
            del zLayer

        #Se refresca el mapa
        iface.mapCanvas().refresh()

class clase_lista_malla250(QWidget):
    def __init__(self,parent=None,nombre="default_name",colores_invertidos=0):
        super().__init__()
        del(parent)
        #self.id=listwidget_capas250.currentRow()
        #self.nombre=listwidget_capas250.item(1).text()
        self.nombre=nombre

        self.widgetLabel = QLabel(self.nombre)
        self.widgetLabel.setFont(QFont('Arial', 10))
        widgetLayout = QHBoxLayout()
        widgetLayout.addWidget(self.widgetLabel)
        widgetLayout.addStretch(1)

        widgetLayout.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(widgetLayout)
        #self.setSizeHint(self.widget_prueba.sizeHint())
        #self.mostrar_item_capa250()

class clase_colores(QListWidgetItem):
    def __init__(self, parent=None, id = 0, color = "#000000", condicion = 0):
        super().__init__()
        del(parent)

        self.id = id
        self.widget=QWidget()
        self.widgetLabel = QLabel("")
        self.widgetLabel.setFont(QFont('Arial', 10))
        self.widgetLabel.setStyleSheet("border: 1px solid black;min-width: 20px;min-height: 20px;background-color: " + str(color))
        self.widgetText = QLineEdit(str(condicion))
        self.widgetText.setFont(QFont('Arial', 10))

        self.widgetLabelLeyenda = QLabel("0-0")
        self.widgetLabelLeyenda.setFont(QFont('Arial', 10))
        widgetLayout = QHBoxLayout()
        widgetLayout.addWidget(self.widgetLabel)
        widgetLayout.addWidget(self.widgetText)
        widgetLayout.addWidget(self.widgetLabelLeyenda)
        widgetLayout.addStretch(1)

        widgetLayout.setSizeConstraint(QLayout.SetFixedSize)
        self.widget.setLayout(widgetLayout)
        self.setSizeHint(self.widget.sizeHint())


""" Script to split a set of source target by the identified language into
respective files """
import argparse
from collections import defaultdict
import os
import spacy
from spacy_cld import LanguageDetector

def load_pairs(src_file, dst_file):
    """ Load sources and targets """
    sources, targets = [], []
    with open(src_file, 'r') as src_fh:
        for line in src_fh:
            sources.append(line.strip())
    with open(dst_file, 'r') as dst_fh:
        for line in dst_fh:
            targets.append(line.strip())
    return sources, targets

def write_lang_pair(paths, sents):
    """ Write a couple of :code:`sents` to :code:`paths` """
    assert len(paths) == len(sents)
    for fname, sentence in zip(paths, sents):
        with open(fname, 'a') as fpath:
            print(sentence, file=fpath)

def lang_path(lang, fname):
    """ Sneak the language identifier into the filename """
    fname, __ext = os.path.splitext(fname)
    return '.'.join([fname, lang])

def main(sources_path, targets_path):
    """ Identify language of (sources, targets) pairs and write them back in
    new files """
    nlp = spacy.load('en')
    language_detector = LanguageDetector()
    nlp.add_pipe(language_detector)

    sources, targets = load_pairs(sources_path, targets_path)
    assert len(sources) == len(targets)
    print("Processing", len(sources), "pairs...")
    lang_counts = defaultdict(int)

    for src_sent, tgt_sent in zip(sources, targets):
        combined_sent = ' '.join([src_sent, tgt_sent])
        doc = nlp(combined_sent)
        for lang in doc._.languages:
            lang_counts[lang] += 1
            lang_sources_path = lang_path(lang, sources_path)
            lang_targets_path = lang_path(lang, targets_path)
            write_lang_pair((lang_sources_path, lang_targets_path),
                            (src_sent, tgt_sent))

    for lang, count in lang_counts.items():
        print("{}: {}".format(lang, count))

    print("Total resulting pairs:", sum(lang_counts.values()))

if __name__ == '__main__':
    PARSER = argparse.ArgumentParser()

    PARSER.add_argument('-s', '--sources', type=str, default='tmp/sources.txt')
    PARSER.add_argument('-t', '--targets', type=str, default='tmp/targets.txt')

    ARGS = PARSER.parse_args()

    main(ARGS.sources, ARGS.targets)


# -*- coding: utf-8 -*-
"""
lesson4_nn.py

Tama skripti sisaltaa luennon4 harjoituksia
- lahimman naapurin analyysit

Created on Tue Nov 13 15:11:30 2018

@author: Suvi Hatunen
"""
from shapely.geometry import Point, MultiPoint
from shapely.ops import nearest_points
import geopandas as gpd

def nearest(row, geom_union, df2, geom1_col='geometry', geom2_col='geometry', ser_column=None):
    #alla fiksu tapa kommentoida def-funktioita, nakyy helpissa
    """
    Finds the closest point from the set of points.

    Parameters
    ----------

    geom_union: shapely.MultiPoint

    """
    # Find geometry that is closest
    nearest = df2[geom2_col] == nearest_points(row[geom1_col], geom_union)[1]

    # get the corresponding value from df2
    value = df2[nearest][ser_column].get_values()[0]

    return value

# datapolut
fp1 = 'L4_data/PKS_suuralue.kml'
fp2 = 'L4_data/addresses.shp'

# driverin aktivointi
gpd.io.file.fiona.drvsupport.supported_drivers['KML'] = 'rw'

# luetaan datat
polys = gpd.read_file(fp1, driver='KML')
src_points = gpd.read_file(fp2)

# unary union
unary_union = src_points.unary_union

# calculate centroif for the polygons
polys['centroid'] = polys.centroid

# find the nearest station for each polygon centroid
polys['nearest_id'] = polys.apply(nearest, geom_union=unary_union, df2=src_points, geom1_col='centroid', ser_column='id', axis=1)


import logging
import datetime
import traceback
import uuid
import decimal

from django.utils import functional

from tulius.core.elastic import indexing

class Handler(logging.Handler):
    def __init__(self, index_name=None, level=logging.NOTSET):
        self._index_name = index_name or '{logger}'
        super().__init__(level=level)

    def get_index_name(self, tstamp, record):
        return self._index_name.format(
            logger=record.name, year=tstamp.year, month=tstamp.month,
            day=tstamp.day
        )

    def emit(self, record: logging.LogRecord) -> None:
        tstamp = datetime.datetime.utcfromtimestamp(record.created)
        message = {
            '_action': 'index',
            '_index': self.get_index_name(tstamp, record),
            '_id': str(uuid.uuid4()),
            '@timestamp': tstamp,
            'message': record.getMessage(),
            'level': record.levelname,
            'logger_name': record.name,
        }
        message.update(self.get_extra_fields(record))
        if record.exc_info:
            message.update(self.get_debug_fields(record))
        indexing.get_indexer().index(message)

    @staticmethod
    def get_extra_fields(record):
        # The list contains all the attributes listed in
        # http://docs.python.org/library/logging.html#logrecord-attributes
        skip_list = (
            'args', 'asctime', 'created', 'exc_info', 'exc_text', 'filename',
            'funcName', 'id', 'levelname', 'levelno', 'lineno', 'module',
            'msecs', 'msecs', 'message', 'msg', 'name', 'pathname', 'process',
            'processName', 'relativeCreated', 'thread', 'threadName', 'extra',
            'stack_info')

        easy_types = (
            str, bool, dict, float, int, list, type(None),
            datetime.datetime, datetime.date, datetime.time,
            datetime.timedelta, decimal.Decimal, uuid.UUID, functional.Promise
        )

        fields = {}

        for key, value in record.__dict__.items():
            if key not in skip_list:
                if isinstance(value, easy_types):
                    fields[key] = value
                else:
                    fields[key] = repr(value)

        return fields

    @staticmethod
    def get_debug_fields(record):
        fields = {
            'lineno': record.lineno,
            'process': record.process,
            'thread_name': record.threadName,
        }
        if record.exc_info:
            fields['stack_trace'] = ''.join(
                traceback.format_exception(*record.exc_info))
        return fields


import argparse
import sys
from pathlib import Path
import json

import torch
from torch.utils.data import DataLoader
from torch.nn.utils.rnn import pad_sequence
import torch.optim as optim
from transformers import AutoTokenizer, AutoModel
from tqdm import tqdm

from dataset import ShinraData, NerDataset, ner_collate_fn
from model import BertForMultilabelNER, create_pooler_matrix

import os

def ner_for_shinradata(model, tokenizer, shinra_dataset, device):
    processed_data = shinra_dataset.ner_inputs
    dataset = NerDataset(processed_data, tokenizer)
    total_preds, _ = predict(model, dataset, device, sent_wise=True)

    shinra_dataset.add_nes_from_iob(total_preds)

    return shinra_dataset

def predict(model, dataset, device, sent_wise=False):
    model.eval()
    dataloader = DataLoader(dataset, batch_size=8, collate_fn=ner_collate_fn)

    total_preds = []
    total_trues = []
    with torch.no_grad():
        for step, inputs in enumerate(dataloader):
            input_ids = inputs["tokens"]
            word_idxs = inputs["word_idxs"]

            labels = inputs["labels"]

            input_ids = pad_sequence([torch.tensor(t) for t in input_ids], padding_value=0, batch_first=True).to(device)
            attention_mask = input_ids > 0
            pooling_matrix = create_pooler_matrix(input_ids, word_idxs, pool_type="head").to(device)

            preds = model.predict(
                input_ids=input_ids,
                attention_mask=attention_mask,
                word_idxs=word_idxs,
                pooling_matrix=pooling_matrix
            )

            total_preds.append(preds)
            # test dataの場合truesは使わないので適当にpredsを入れる
            total_trues.append(labels if labels[0] is not None else preds)

    attr_num = len(total_preds[0])
    total_preds = [[pred for preds in total_preds for pred in preds[attr]] for attr in range(attr_num)]
    total_trues = [[true for trues in total_trues for true in trues[attr]] for attr in range(attr_num)]

    if sent_wise:
        total_preds = [[total_preds[attr][idx] for attr in range(attr_num)] for idx in range(len(total_preds[0]))]
        total_trues = [[total_trues[attr][idx] for attr in range(attr_num)] for idx in range(len(total_trues[0]))]

    return total_preds, total_trues

def parse_arg():
    parser = argparse.ArgumentParser()

    parser.add_argument("--input_path", type=str, help="Specify input path in SHINRA2020")
    parser.add_argument("--model_path", type=str, help="Specify attribute_list path in SHINRA2020")
    parser.add_argument("--output_path", type=str, help="Specify attribute_list path in SHINRA2020")
    parser.add_argument("--cuda", type=int, help="Specify attribute_list path in SHINRA2020")
    args = parser.parse_args()

    return args

if __name__ == "__main__":
    args = parse_arg()

    if torch.cuda.is_available():
        device = f"cuda:{args.cuda}"
    else:
        device = "cpu"

    bert = AutoModel.from_pretrained("cl-tohoku/bert-base-japanese")
    tokenizer = AutoTokenizer.from_pretrained("cl-tohoku/bert-base-japanese")

    input_path = Path(args.input_path)
    assert (input_path / "attributes.txt").exists()
    with open(input_path / "attributes.txt", "r") as f:
        attributes = [attr for attr in f.read().split("\n") if attr != '']

    model = BertForMultilabelNER(bert, len(attributes))
    model.load_state_dict(torch.load(args.model_path))
    model.to(device)

    # dataset = [ShinraData(), ....]
    dataset = ShinraData.from_shinra2020_format(Path(args.input_path))
    # dataset = [d for idx, d in enumerate(dataset) if idx < 20 and d.nes is not None]

    def _post_processing(d):
        d['page_id'] = int(d['page_id'])
        for k1 in ['text_offset', 'html_offset', 'token_offset']:
            for k2 in ['start', 'end']:
                for k3 in ['offset', 'line_id']:
                    try:
                        d[k1][k2][k3] = int(d[k1][k2][k3])
                    except KeyError:
                        pass
        return d

    # dataset = [ner_for_shinradata(model, tokenizer, d, device) for d in dataset]
    with open(args.output_path, "w") as f:
        for data in dataset:
            if data.nes is None:
                processed_data = ner_for_shinradata(model, tokenizer, data, device)
                lst = []
                for ne in processed_data.nes:
                    lst.append(json.dumps(_post_processing(ne), ensure_ascii=False))
                if len(lst) == 0:
                    continue
                f.write("\n".join(lst))
                f.write("\n")


# -*- coding: utf-8 -*-
"""
Created on Sun May 22 11:08:13 2022

@author: vanis
"""

import numpy as np
import os
import glob
import open3d

#A2D2 + Sydney Urban Object
DATA_DIR  = './Urban_Objects_Dataset/'
LABELS = ['4wd ','building', 'bus', 'car', 'pedestrian', 'pillar', 'pole',  \
          'traffic_lights', 'traffic_sign', 'truck','ute','van','curbstone', \
          'Nature object','RD normal street','Sidewalk']

folders = glob.glob(os.path.join(DATA_DIR, "[!README]*"))

print(LABELS)

for i, folder in enumerate(folders):

        print("processing class: {}".format(os.path.basename(folder)))
        folder1 = os.path.basename(folder)
        train_files = glob.glob(os.path.join(folder, "train/*"))
        #print(train_files)
        test_files = glob.glob(os.path.join(folder, "test/*"))

        for f in train_files:
            points = np.load(f,allow_pickle = 'True')
            pc_xyz = points[:, 0:3]
            num_points = len(pc_xyz)
            pcd = open3d.geometry.PointCloud()
            #pcd.colors = o3d.utility.Vector3dVector([1, 0, 0])
            l = [[0,0,0] for j in range(pc_xyz.shape[0])];
            pcd.colors = open3d.utility.Vector3dVector(np.array(l))
            # assign point coordinatesr
            pcd.points = open3d.utility.Vector3dVector(pc_xyz)
            open3d.visualization.draw_geometries([pcd])

        for f in test_files:
            points = np.load(f,allow_pickle = 'True')
            pc_xyz = points[:, 0:3]
            num_points = len(pc_xyz)
            pcd = open3d.geometry.PointCloud()
            #pcd.colors = o3d.utility.Vector3dVector([1, 0, 0])
            l = [[0,0,0] for j in range(pc_xyz.shape[0])];
            pcd.colors = open3d.utility.Vector3dVector(np.array(l))
            # assign point coordinatesr
            pcd.points = open3d.utility.Vector3dVector(pc_xyz)
            open3d.visualization.draw_geometries([pcd])


from collections import defaultdict
from copy import deepcopy
import warnings
from rdkit.Chem.rdMolAlign import CalcRMS, GetBestRMS
import random

from tqdm import tqdm
from terrace import Batch, collate
from typing import Callable, Dict, List, Set, Type
import torch
from torch import nn
from torchmetrics import Metric, SpearmanCorrCoef, Accuracy, AUROC, ROC, Precision, R2Score, MeanSquaredError
from terrace.dataframe import DFRow
from common.pose_transform import add_pose_to_mol

class FullMetric(Metric):
    """ Extension of torchmetrics metrics which also allows us
    to update based on input batches """

    def update(self, x: Batch[DFRow], pred: Batch[DFRow], label: Batch[DFRow]):
        raise NotImplementedError()

    def compute(self):
        raise NotImplementedError

class MetricWrapper(FullMetric):

    def __init__(self, metric_class: Type[Metric], get_y_p: Callable, get_y_t: Callable, *args, **kwargs):
        super().__init__()
        self.metric = metric_class(*args, **kwargs)
        self.get_y_p = get_y_p
        self.get_y_t = get_y_t

    def update(self, x: Batch[DFRow], pred: Batch[DFRow], label: Batch[DFRow]):
        y_pred = self.get_y_p(pred)
        y_true = self.get_y_t(label)
        return self.metric.update(y_pred, y_true)

    def compute(self):
        return self.metric.compute()

def dict_stack(items):
    if isinstance(items, list):
        ex = items[0]
        if isinstance(ex, dict):
            return {key: dict_stack([item[key] for item in items]) for key in ex.keys()}
    return torch.stack(items)

def dict_apply(f, d):
    if isinstance(d, dict):
        return {key: f(val) for key, val in d.items()}
    return f(d)

class PerPocketMetric(FullMetric):
    """ Computes a specific metric for every pocket and returns the
    mean and median values """

    def __init__(self, metric_class: Type[FullMetric], *args, **kwargs):
        """ reduce is either mean or median"""
        super().__init__()
        self.metric_maker = lambda: metric_class(*args, **kwargs)
        self.metric = self.metric_maker()
        self.pocket_metrics = nn.ModuleDict()

    def reset(self):
        self.metric.reset()
        self.pocket_metrics = nn.ModuleDict()

    def update(self, x_b: Batch[DFRow], pred_b: Batch[DFRow], label_b: Batch[DFRow]):
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", category=UserWarning)
            self.metric.update(x_b, pred_b, label_b)
            for x, pred, label in zip(x_b, pred_b, label_b):
                poc_id = x.pocket_id
                xi = collate([x], lazy=True)
                predi = collate([pred], lazy=True)
                labeli = collate([label], lazy=True)
                if poc_id not in self.pocket_metrics:
                    self.pocket_metrics[poc_id] = self.metric_maker().to(self.device)
                self.pocket_metrics[poc_id].update(xi, predi, labeli)

    def pre_compute(self):
        pass

    def compute(self):
        self.pre_compute()
        results = []
        for metric in self.pocket_metrics.values():
            results.append(metric.compute())
        if len(results) == 0:
            return {
                "all": self.metric.compute()
            }
        else:
            results = dict_stack(results)
            return {
                "all": self.metric.compute(),
                "mean": dict_apply(lambda r: r.mean(), results),
                "median": dict_apply(lambda r: r.median(), results)
            }

class PosePerPocketMetric(PerPocketMetric):

    def update(self, x, pred, y):
        if not hasattr(pred, "lig_pose"): return
        super().update(x, pred, y)

# needed because the pickle can't handle lambdas
def get_is_active(b):
    return b.is_active

def get_is_active_score(p):
    return p.is_active_score

def get_activity_score(p):
    return p.activity_score

def get_active_prob(p):
    return p.active_prob

def get_activity(b):
    return b.activity

def identity(b):
    return b

class IsActiveAUC(MetricWrapper):

    def __init__(self):
        super().__init__(AUROC, get_is_active_score, get_is_active, 'binary')

    def reset(self):
        super().reset()

class PerPocketAUC(PerPocketMetric):

    def __init__(self):
        super().__init__(IsActiveAUC)

    def pre_compute(self):
        """ Can't compute AUC for labels that are all active or all inactive"""
        for key, val in list(self.pocket_metrics.items()):
            if True not in val.metric.target or False not in val.metric.target:
                del self.pocket_metrics[key]

class ActivitySpearman(MetricWrapper):

    def __init__(self):
        super().__init__(SpearmanCorrCoef, get_activity_score, get_activity)

class PoseRankAcc(FullMetric):

    def __init__(self, rmsd_cutoff=2.0):
        super().__init__()
        self.rmsd_cutoff = rmsd_cutoff
        self.top_n_correct = defaultdict(int)
        self.total_seen = 0

    def reset(self) -> None:
        self.top_n_correct = defaultdict(int)
        self.total_seen = 0

    def update(self, x, pred, y):
        for pred0, y0 in zip(pred, y):
            # if torch.amax(pred0.pose_scores) < -0.25:
            #     print("skipping")
            #     continue
            # print("doing!")
            poses_correct = y0.pose_rmsds < self.rmsd_cutoff
            correct_sorted = [ x[0].cpu().item() for x in sorted(zip(poses_correct, -pred0.pose_scores, torch.randn_like(pred0.pose_scores)), key=lambda x: x[1:])]
            for n in range(1, len(correct_sorted)+1):
                self.top_n_correct[n] += int(True in correct_sorted[:n])
            self.total_seen += 1

    def compute(self):
        # print("TOTAL: ", self.total_seen)
        ret = {}
        for n, correct in self.top_n_correct.items():
            ret[f"top_{n}"] = correct/self.total_seen
        return ret

def get_rmsds(ligs, pred_pose, true_pose, align=False):
    rms_func = GetBestRMS if align else CalcRMS
    ret = []
    for lig, pred, yt in zip(ligs, pred_pose, true_pose):
        mol1 = deepcopy(lig)
        mol2 = deepcopy(lig)
        add_pose_to_mol(mol2, yt)
        if pred.coord.dim() == 3:
            ret.append([])
            for p in pred.items():
                add_pose_to_mol(mol1, p)
                ret[-1].append(rms_func(mol1, mol2, maxMatches=1000))
        else:
            add_pose_to_mol(mol1, pred)
            # made maxMatches very low for now because it's freezing training
            # with the default value. Perhaps raise later
            ret.append(rms_func(mol1, mol2, maxMatches=1000))
    return torch.asarray(ret, dtype=torch.float32, device=pred_pose[0].coord.device)

class PoseRMSD(FullMetric):

    def __init__(self):
        super().__init__()
        self.add_state("rmsd_sum", default=torch.tensor(0.0))
        self.add_state("total", default=torch.tensor(0))

    def update(self, x, pred, y):
        # if not hasattr(pred, "lig_pose"): return
        rmsds = get_rmsds(x.lig, pred.lig_pose, y.lig_crystal_pose)
        if rmsds.dim() == 2:
            rmsds = rmsds[:,0]
        self.rmsd_sum += rmsds.sum()
        self.total += len(x)

    def compute(self):
        # if self.total == 0:
        #     print("Something is wrong with PoseRMSD metric. I haven't been updated.")
        assert self.total > 0
        return self.rmsd_sum / self.total

class PoseAcc(FullMetric):

    def __init__(self, rmsd_cutoff):
        super().__init__()
        self.rmsd_cutoff = rmsd_cutoff
        self.correct_n = defaultdict(int)
        self.total_n = defaultdict(int)

    def reset(self):
        self.correct_n = defaultdict(int)
        self.total_n = defaultdict(int)

    def update(self, x, pred, y):
        # if not hasattr(pred, "lig_pose"): return
        rmsds = get_rmsds(x.lig, pred.lig_pose, y.lig_crystal_pose)
        if rmsds.dim() == 1:
            rmsds = rmsds.unsqueeze(1)
        correct = (rmsds < self.rmsd_cutoff)
        for n in range(correct.shape[1]):
            self.correct_n[n] += correct[:,:n+1].amax(1).sum()
            self.total_n[n] += len(x)

    def compute(self):
        ret = {}
        for n in self.total_n:
            ret[f"{n+1}"] = self.correct_n[n].float()/self.total_n[n]
        return ret

class CrystalEnergy(FullMetric):

    def __init__(self, rmsd_cutoff):
        super().__init__()
        self.rmsd_cutoff = rmsd_cutoff
        self.add_state("num_local", default=torch.tensor(0))
        self.add_state("num_global", default=torch.tensor(0))
        self.add_state("total", default=torch.tensor(0))

    def update(self, x, pred, y):
        if not hasattr(pred, "crystal_pose"): return
        crystal_rmsds = get_rmsds(x.lig, pred.crystal_pose, y.lig_crystal_pose)
        local = crystal_rmsds < self.rmsd_cutoff
        self.num_local += local.sum()
        # for loc, energy, crys_energy in zip(local, pred.energy, pred.crystal_energy):
        #     if not loc: continue
        #     all_energies = torch.cat((energy, crys_energy.unsqueeze(0)), 0)
        #     if all_energies.min() == crys_energy:
        #         self.num_global += 1
        self.total += len(x)

    def compute(self):
        if self.total == 0: return {}
        return {
            # "global_min": self.num_global.float()/self.total,
            "local_min": self.num_local.float()/self.total
        }

class EnrichmentFactor(FullMetric):

    def __init__(self):
        super().__init__()
        self.scores = []
        self.yts = []

    def update(self, x, pred, y):
        for pred0, y0 in zip(pred, y):
            self.yts.append(y0.is_active)
            self.scores.append(pred0.is_active_score)

    def reset(self):
        super().reset()
        self.yts = []
        self.scores = []

    def compute(self):
        yt, scores = collate(self.yts), collate(self.scores)

        one_percent = round(len(yt)*0.01)
        if one_percent == 0: return {}

        all_pred_and_act = list(zip(scores, yt))
        random.shuffle(all_pred_and_act)
        pred_and_act = sorted(all_pred_and_act, key=lambda x: -x[0])[:one_percent]
        are_active = [ item[1] for item in pred_and_act ]
        tot_actives = sum(yt)
        max_actives = min(tot_actives, one_percent)
        frac_act_chosen = sum(are_active)/len(are_active)
        max_act_frac = max_actives/len(are_active)
        frac_act_in_set = tot_actives/len(yt)
        ef1 = frac_act_chosen/frac_act_in_set
        max_ef1 = max_act_frac/frac_act_in_set
        nef1 = ef1/max_ef1
        return {
            "ef1": ef1,
            "nef1": nef1,
            "total_in_set": len(yt),
            "total_chosen": one_percent,
            "total_actives_chosen": sum(are_active),
            "total_actives_in_set": tot_actives,
        }

class RejectOptionMetric(FullMetric):

    def __init__(self, cfg, metrics):
        super().__init__()
        self.select_fracs = torch.arange(0.05, 1.05, 0.05)
        self.metrics = nn.ModuleDict(metrics)
        self.xs = []
        self.ys = []
        self.preds = []
        self.dummy_param = nn.Parameter(torch.empty(0))

    def update(self, x, pred, y):
        for x0, pred0, y0 in zip(x, pred, y):
            self.xs.append(x0)
            self.ys.append(y0)
            self.preds.append(pred0)

    def reset(self):
        super().reset()
        self.xs = []
        self.ys = []
        self.preds = []

    def compute(self):
        device = self.dummy_param.device
        ret = {}
        x, y, pred = collate(self.xs).to(device), collate(self.ys).to(device), collate(self.preds).to(device)
        select_score = -pred.select_score
        idx = torch.argsort(select_score, dim=0)
        prev_idx = 0
        for frac in self.select_fracs:
            length = int(len(idx)*frac)
            if length == prev_idx: continue
            for index in idx[prev_idx:length]:
                x0 = collate([x[index]])
                y0 = collate([y[index]])
                pred0 = collate([pred[index]])
                for metric in self.metrics.values():
                    metric.update(x0, pred0, y0)
            prev_idx = length

            ret[f"{frac:.2f}"] = {
                key: val.compute() for key, val in self.metrics.items()
            }
        return ret

class ActivityR2(FullMetric):

    def __init__(self):
        super().__init__()
        self.metric = R2Score()

    def update(self, x, pred, y):
        mask = ~torch.isnan(y.activity)
        pred = pred.activity[mask]
        y = y.activity[mask]
        self.metric.update(pred, y)

    def compute(self):
        if self.metric.total < 2:
            return torch.tensor(torch.nan, device=self.metric.sum_error.device)
        return self.metric.compute()

class PerPocketActR2(PerPocketMetric):

    def __init__(self):
        super().__init__(ActivityR2)

    def pre_compute(self):
        """ Can't compute AUC for labels that are all active or all inactive"""
        for key, val in list(self.pocket_metrics.items()):
            if val.metric.total < 2:
                del self.pocket_metrics[key]

def get_single_task_metrics(task: str):
    return {
        "score_activity_class": nn.ModuleDict({
            "auroc": PerPocketAUC()
        }),
        "score_activity_regr": nn.ModuleDict({
            "spearman": PerPocketMetric(ActivitySpearman),
        }),
        "classify_activity": nn.ModuleDict({
            "acc": MetricWrapper(Accuracy, get_active_prob, get_is_active, 'binary'),
            "precision": MetricWrapper(Precision, get_active_prob, get_is_active, 'binary')
        }),
        "score_pose": nn.ModuleDict({
            "acc_2": PoseRankAcc(2.0),
            "acc_5": PoseRankAcc(5.0)
        }),
        "predict_lig_pose": nn.ModuleDict({
            "rmsd": PosePerPocketMetric(PoseRMSD),
            "acc_2": PosePerPocketMetric(PoseAcc, 2.0),
            "acc_5": PosePerPocketMetric(PoseAcc, 5.0),
            # "crystal_2": CrystalEnergy(2.0),
            # "crystal_5": CrystalEnergy(5.0)
        }),
        "predict_activity": nn.ModuleDict({
            "r2": PerPocketActR2(),
        })
    }[task]

def get_metrics(cfg, tasks: List[str], offline=False):
    # filter out those torchmetrics warnings
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore", category=UserWarning)

        ret = nn.ModuleDict({})
        for task in tasks:
            if task == "reject_option": continue
            ret.update(get_single_task_metrics(task))

        if offline and "score_activity_class" in tasks:
            ret.update({"enrichment": EnrichmentFactor()})

        # pretty hacky way of integrating reject option
        # todo: put back. Took out because of OOMing
        if "reject_option" in tasks and offline:
            ret["select"] = RejectOptionMetric(cfg, deepcopy(ret))

    return ret

def reset_metrics(module):
    if isinstance(module, Metric):
        module.reset()


import torch
import torch.nn as nn
import math

from .transformer import build_position_encoding
from .common import ModelInterface
from torch.cuda.amp import autocast

from torchreid.losses import AngleSimpleLinear

__all__ = ['build_q2l']

class GroupWiseLinear(nn.Module):
    def __init__(self, num_class, hidden_dim, use_bias=True):
        super().__init__()
        self.num_class = num_class
        self.hidden_dim = hidden_dim
        self.use_bias = use_bias

        self.weight = nn.Parameter(torch.Tensor(1, num_class, hidden_dim))
        if use_bias:
            self.bias = nn.Parameter(torch.Tensor(1, num_class))
        self.reset_parameters()

    def reset_parameters(self):
        stdv = 1. / math.sqrt(self.weight.size(2))
        for i in range(self.num_class):
            self.weight[0][i].data.uniform_(-stdv, stdv)
        if self.use_bias:
            for i in range(self.num_class):
                self.bias[0][i].data.uniform_(-stdv, stdv)

    def forward(self, x):
        # x: B,K,d
        x = (self.weight * x).sum(-1)
        if self.use_bias:
            x = x + self.bias
        return x

class BackboneWrapper(nn.Module):
    def __init__(self, backbone, position_embedding):
        super().__init__()
        self.backbone = backbone
        self.position_embedding = position_embedding
        self.num_channels = backbone.get_num_features()

    def forward(self, input):
        out = self.backbone(input, return_featuremaps=True)
        pos = self.position_embedding(out).to(out.dtype)
        return [out], [pos]

class Query2Label(ModelInterface):
    def __init__(self,
                backbone,
                transfomer,
                num_classes=80,
                pretrain=False,
                **kwargs):
        """[summary]

        Args:
            backbone ([type]): backbone model.
            transfomer ([type]): transformer model.
            num_classes ([type]): number of classes. (80 for MSCOCO).
        """
        super().__init__(**kwargs)
        self.backbone = backbone
        self.transformer = transfomer
        self.num_class = num_classes
        assert self.loss in ['asl', 'bce', 'am_binary'], "Q2L supports only ASL, BCE pr AM Binary losses"

        hidden_dim = transfomer.get_hidden_dim()
        backbone_features = backbone.num_channels
        self.input_proj = nn.Conv2d(backbone_features, hidden_dim, kernel_size=1)
        self.query_embed = nn.Embedding(num_classes, hidden_dim)
        if self.loss == "am_binary":
            self.fc = AngleSimpleLinear(hidden_dim, num_classes)
        else:
            assert self.loss in ['asl', 'bce']
            self.fc = GroupWiseLinear(num_classes, hidden_dim, use_bias=True)

    def forward(self, input):
        with autocast(enabled=self.mix_precision):
            src, pos = self.backbone(input)
            src, pos = src[-1], pos[-1]

            query_input = self.query_embed.weight
            hs = self.transformer(self.input_proj(src), query_input, pos)[0] # B,K,d
            logits = self.fc(hs[-1])
            if self.similarity_adjustment:
                logits = self.sym_adjust(logits, self.amb_t)

            if not self.training:
                return [logits]

            elif self.loss in ['asl', 'bce', 'am_binary']:
                    out_data = [logits]
            else:
                raise KeyError("Unsupported loss: {}".format(self.loss))

            return tuple(out_data)

    def get_config_optim(self, lrs):
        parameters = [
            {'params': self.backbone.named_parameters()},
            {'params': self.fc.named_parameters()},
            {'params': self.input_proj.parameters(), 'weight_decay': 0.},
            {'params': self.query_embed.parameters(), 'weight_decay': 0.}
        ]
        if isinstance(lrs, list):
            assert len(lrs) == len(parameters)
            for lr, param_dict in zip(lrs, parameters):
                param_dict['lr'] = lr
        else:
            assert isinstance(lrs, float)
            for param_dict in parameters:
                param_dict['lr'] = lrs

        return parameters

def build_q2l(backbone, transformer, hidden_dim=2048, pretrain=False, input_size=448, **kwargs):
    position_emb = build_position_encoding(hidden_dim=hidden_dim, img_size=input_size)
    wrapped_model = BackboneWrapper(backbone, position_emb)
    model = Query2Label(
        backbone=wrapped_model,
        transfomer=transformer,
        pretrain=pretrain,
        **kwargs
    )

    return model