Beispiel #1
0
    def verificar_avanzar(cls, n_pasos=3):
        try:
            arch_ref = cls.refs_prb_avanzar()
            arch_inic = cls.refs_prb_vals_inic()[0]
        except NotImplementedError:
            return

        mod = cls(archivo=arch_inic)
        res = mod.simular(t_final=n_pasos)

        try:
            ref = xr.Dataset.from_dict(cargar_json(arch_ref))
        except FileNotFoundError:
            avisar(
                _('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                  '\nmodelo sí esté simulando correctamente. Lo generaremos con base en el los valores'
                  '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                  '\n\t"{}"'
                  '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                  '\ncomprobar la función de simulación de modelo.').format(
                      arch_ref))

            guardar_json(res.to_dict(), arch=arch_ref)

            ref = res

        xr.testing.assert_equal(ref, res)
Beispiel #2
0
    def cargar_ref_avanzar(cls, arch_ref, res):
        """

        Parameters
        ----------
        arch_ref :
        res : xr.DataSet

        Returns
        -------

        """
        try:
            return xr.Dataset.from_dict(cargar_json(arch_ref))
        except FileNotFoundError:
            avisar(
                _('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                  '\nmodelo sí esté simulando correctamente. Lo generaremos con base en el los valores'
                  '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                  '\n\t"{}"'
                  '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                  '\ncomprobar la función de simulación de modelo.').format(
                      arch_ref))

            guardar_json(res.to_dict(), arch=arch_ref)

            return res
Beispiel #3
0
    def verificar_inic_dic_vals(cls):
        try:
            arch_inic, arch_ref = cls.refs_prb_vals_inic()
        except NotImplementedError:
            return

        mod = cls(arch_inic)

        try:
            ref = cargar_json(arch_ref)
        except FileNotFoundError:
            avisar(
                _('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                  '\nmodelo sí esté leyendo bien los datos iniciales. Lo generaremos con base en el los valores'
                  '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                  '\n\t"{}"'
                  '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                  '\ncomprobar la función de lectura de datos iniciales.').
                format(arch_ref))
            d_vals = copiar_profundo(mod.variables)
            for d_v in d_vals.values():
                if isinstance(d_v['val'], np.ndarray):
                    d_v['val'] = d_v['val'].tolist()
            guardar_json(d_vals, arch=arch_ref)

            ref = d_vals

        for var in mod.variables:
            npt.assert_equal(ref[var]['val'],
                             mod.obt_val_actual_var(var),
                             err_msg=var)
Beispiel #4
0
def obt_val_config(llave, cond=None, mnsj_err=None, respaldo=None):
    if not isinstance(respaldo, list):
        respaldo = [respaldo]

    try:
        conf, ll = _resolver_conf_anidado(llave)
        val = conf[ll]

        if cond is None:
            return val
        else:
            if cond(val):
                return val
            else:
                for a in respaldo:
                    if a is not None and cond(a):
                        return a
                if mnsj_err is not None:
                    avisar(mnsj_err)
                return

    except KeyError:
        val = None
        if cond is None:
            val = respaldo[0]
        else:
            for a in respaldo:
                if a is not None and cond(a):
                    val = a
        if val is None and mnsj_err is not None:
            avisar(mnsj_err)
        return val
Beispiel #5
0
def _descargar_whl(nombre, v_py, sis, b):
    print('Descargando paquete "{}"...'.format(nombre))
    llave = url = None

    repositorios = {
        'id_google': 'https://drive.google.com/uc?export=download&id={}',
        'id_dropbox': 'https://www.dropbox.com/s/{}?dl=1'
    }

    for r, u in repositorios.items():
        try:
            llave = info_paquetes[nombre][v_py][sis][b][r]  # type: str
        except KeyError:
            pass
        if llave is not None:
            url = u.format(llave)
            break

    if url is None:
        avisar('No existe descarga para paquete {} en {} bits.'.format(
            nombre, bits))
        return False

    nombre_archivo = info_paquetes[nombre]['formato_archivo']
    urllib.request.urlretrieve(url,
                               os.path.join(directorio_móds, nombre_archivo))

    return True
Beispiel #6
0
    def agregar_modelo(símismo, modelo):
        """
        Esta función agrega un modelo al SuperConectado. Una vez que dos modelos estén agregados, se pueden conectar
        y simular juntos.

        :param modelo: El modelo para agregar.
        :type modelo: tinamit.Modelo.Modelo

        """

        # Si ya se conectó otro modelo con el mismo nombre, avisarlo al usuario.
        if modelo.nombre in símismo.modelos:
            avisar(_('El modelo {} ya existe. El nuevo modelo reemplazará el modelo anterior.').format(modelo.nombre))

        # Agregar el nuevo modelo al diccionario de modelos.
        símismo.modelos[modelo.nombre] = modelo

        # Ahora, tenemos que agregar los variables del modelo agregado al diccionaro de variables de este modelo
        # también. Se prefija el nombre del modelo al nombre de su variable para evitar posibilidades de nombres
        # desduplicados.
        for var in modelo.variables:
            nombre_var = '{mod}_{var}'.format(var=var, mod=modelo.nombre)
            símismo.variables[nombre_var] = modelo.variables[var]

        # Actualizar la unidad de tiempo del modelo
        símismo.unidad_tiempo()
Beispiel #7
0
    def desconectar_vars(símismo, var_fuente, modelo_fuente, modelo_recip=None, var_recip=None):
        """
        Esta función desconecta variables.

        :param var_fuente: El variable fuente de la conexión.
        :type var_fuente: str

        :param modelo_fuente: El modelo fuente de la conexión.
        :type modelo_fuente: str

        """

        # Verificar parámetros
        if modelo_recip is None and var_recip is not None:
            avisar(_('`var_recip` sin `modelo_recip` será ignorado en la función '
                     '`SuperConectado.desconectar_vars()`.'))

        # Buscar la conexión correspondiente...
        for n, conex in enumerate(símismo.conexiones):
            # Para cada conexión existente...
            if conex['modelo_fuente'] == modelo_fuente and conex['var_fuente'] == var_fuente:
                # Si el modelo y variable fuente corresponden...

                # Identificar si el modelo recipiente corresponde también.
                quitar = False
                if modelo_recip is None:
                    quitar = True
                else:
                    if modelo_recip == conex['modelo_recip']:
                        if var_recip is None or var_recip == conex['var_recip']:
                            quitar = True

                # Si corresponde todo, quitar la conexión.
                if quitar:
                    símismo.conexiones.pop(n)
Beispiel #8
0
    def verificar_leer_egr(cls):
        try:
            arch_egr, arch_ref = cls.refs_prb_leer_egr()
        except NotImplementedError:
            return

        egr = cls.leer_arch_resultados(arch_egr)

        try:
            ref = cargar_json(arch_ref)
        except FileNotFoundError:
            avisar(
                _('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                  '\nmodelo sí esté leyendo bien los archivos de egresos. Lo generaremos con base en el los valores'
                  '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                  '\n\t"{}"'
                  '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                  '\ncomprobar la función de lectura de egresos.').format(
                      arch_ref))
            for var, val in egr.items():
                if isinstance(val, np.ndarray):
                    egr[var] = val.tolist()
            guardar_json(egr, arch=arch_ref)

            ref = egr

        for var in ref:
            npt.assert_equal(ref[var], egr[var], err_msg=var)
Beispiel #9
0
    def obt_info_parcelas(símismo, parc):
        """
        Devuelve información de una parcela o lista de parcelas.

        :param parc: La(s) parcela(s) de interés.
        :type parc: str | list[str]

        :return: Un diccionario con información de cada parcela.
        :rtype: dict
        """

        if not isinstance(parc, list):
            parc = [parc]

        parc = [str(x) for x in parc]

        nombres = símismo.datos['Parcelas']['Nombres']  # type: list
        superficies = símismo.datos['Parcelas']['Superficies']  # type: list
        polígonos = símismo.datos['Parcelas']['Polígonos']  # type: list

        dic_info = {}
        for p in parc:
            if p not in nombres:
                avisar('Parcela "{}" no tiene datos en experimento "{}".'.format(p, símismo.nombre))
                continue
            índ_p = nombres.index(p)
            dic_info[p] = {
                'Superficie': superficies[índ_p] if superficies is not None else None,
                'Polígonos': polígonos[índ_p] if superficies is not None else None
            }

        return dic_info
Beispiel #10
0
        def verificar_entero(factor, l_unids):

            if not np.array_equal(factor.astype(int), factor):
                # Si todos los factores no son números enteros, tendremos que aproximar.
                avisar('Las unidades de tiempo de los dos modelos ({}) no tienen denominator común. '
                       'Se aproximará la conversión.'.format(', '.join(l_unids)))

            np.round(factor, out=factor)
Beispiel #11
0
def instalar_requísitos():
    print('Instalando paquetes requísitos...')

    lista_paquetes = []

    if np is None:
        lista_paquetes.append('numpy')

    if matplotlib is None:
        lista_paquetes.append('matplotlib')

    if estad is None:
        lista_paquetes.append('scipy')

    if pymc is None:
        lista_paquetes.append('pymc')

    if len(lista_paquetes):

        if not os.path.exists(directorio_móds):
            os.makedirs(directorio_móds)
            dir_creado = True
        else:
            dir_creado = False

        # Actualizar Pip
        _actualizar_pip()

        # Instalar cada paquete necesario
        for paq in lista_paquetes:
            _instalar_whl(paq)

        if dir_creado:
            shutil.rmtree('Módulos')

    # Verificar que todo esté bien:
    try:
        import numpy as _
        import scipy as _
        import pymc as _
        import matplotlib as _
    except ImportError:
        _ = None
        pass

    try:
        import scipy.stats as _
        _.norm()
        print(
            '¡Todo bien! Los paquetes Python necesarios han sido instalados.')

    except ImportError:
        _ = None
        avisar(
            '¡Error! Por experencia personal, probablemente es porque no instalaste la versión del'
            '"Microsoft C++ 2015 redistributable" {}.\n'
            'Lo puedes conseguir de "https://www.microsoft.com/es-ES/download/details.aspx?id=48145".'
            .format('x86' if bits == '32' else 'x64'))
Beispiel #12
0
    def _act_vals_clima(símismo, n_paso, f):
        """
        Actualiza los variables climáticos, según la estación.

        :param n_paso: El número de pasos para avanzar
        :type n_paso: int
        :param f: La fecha actual.
        :type f: ft.datetime | ft.date

        """

        # Si avanzamos por más que un año, perderemos la precisión del clima
        if n_paso > 12:
            avisar('El paso es superior a 1 año (12 meses). Las predicciones climáticas perderán su precisión.')

        # Solamante hay que cambiar los datos si es el principio de un nuevo año.
        if símismo.mes == 0 and símismo.estación == 0:

            # La lista de variables climáticos
            vars_clima = list(símismo.vars_clima)
            nombres_extrn = [d['nombre_extrn'] for d in símismo.vars_clima.values()]

            # La lista de maneras de combinar los valores diarios
            combins = [d['combin'] for d in símismo.vars_clima.values()]

            # La lista de factores de conversiones de variables de clima
            convs = [d['conv'] for d in símismo.vars_clima.values()]

            # La fecha inicial
            f_inic = f

            for e, dur in enumerate(símismo.dur_estaciones):
                # Para cada estación...

                # La fecha final
                f_final = f_inic + deltarelativo(months=+dur)

                # Calcular los datos
                datos = símismo.lugar.comb_datos(vars_clima=nombres_extrn, combin=combins,
                                                 f_inic=f_inic, f_final=f_final)

                # Aplicar los valores de variables calculados
                for i, var in enumerate(vars_clima):
                    # Para cada variable en la lista de clima...

                    # El nombre oficial del variable de clima
                    var_clima = nombres_extrn[i]

                    # El factor de conversión
                    conv = convs[i]

                    # Guardar el valor para esta estación
                    símismo.datos_internos[var][e, ...] = datos[var_clima] * conv

                # Avanzar la fecha
                f_inic = f_final
Beispiel #13
0
    def _estab_mod_extern(símismo, modelo):
        if isinstance(modelo, str):

            if not os.path.isfile(modelo):
                raise ValueError(_('El archivo "{}" no existe... :(').format(modelo))

            if os.path.splitext(modelo)[1] != '.py':
                raise ValueError(_('El archivo "{}" no parece ser un archivo Python.').format(modelo))

            dir_mod, nombre_mod = os.path.split(modelo)
            sys.path.append(dir_mod)
            módulo = importar_mod(os.path.splitext(nombre_mod)[0])

            candidatos = inspect.getmembers(módulo, inspect.isclass)
            cands_final = {}
            for nmb, obj in candidatos:
                if callable(obj):
                    try:
                        obj = obj()
                    except BaseException:
                        continue
                if isinstance(obj, ModeloBF):
                    cands_final[nmb] = obj

            if len(cands_final) == 0:
                raise AttributeError(_('El fuente especificado ("{}") no contiene subclase de "ModeloBF".')
                                     .format(modelo))
            elif len(cands_final) == 1:
                símismo.modelo = cands_final[list(cands_final)[0]]
            else:
                try:
                    símismo.modelo = cands_final['Envoltura']
                except KeyError:
                    elegido = list(cands_final)[0]
                    símismo.modelo = elegido
                    avisar(_('Había más que una instancia de "ModeloBF" en el fuente "{}", '
                             'y ninguna se llamaba "Envoltura". Tomaremos "{}" como la envoltura '
                             'y esperaremos que funcione. Si no te parece, asegúrate que la definición de clase u el'
                             'objeto correcto se llame "Envoltura".').format(modelo, elegido))

        else:
            if callable(modelo):
                modelo = modelo()

            if isinstance(modelo, ModeloBF):
                símismo.modelo = modelo
            else:
                raise TypeError(_('El parámetro "modelo" debe ser o una instancia o subclase de "ModeloBF", o un '
                                  'fuente Python que contiene uno.'))

        # Crear el vínculo
        símismo.variables = símismo.modelo.variables
        símismo.vars_saliendo = símismo.modelo.vars_saliendo
        símismo.vars_clima = símismo.modelo.vars_clima
        símismo.archivo = símismo.modelo.archivo
Beispiel #14
0
    def simular(símismo, t_final=None, t_inic=None, paso=1, nombre_corrida='Corrida Tinamït',
                vals_inic=None, vals_extern=None, bd=None, lugar_clima=None, clima=None, vars_interés=None, guardar=True):
        """
        Simula el modelo :class:`~tinamit.Conectado.SuperConectado`.

        :param t_final: El tiempo final de la simulación.
        :type t_final: int

        :param paso: El paso (intervalo de intercambio de valores entre los dos submodelos).
        :type paso: int

        :param nombre_corrida: El nombre de la corrida.  El valor automático es ``Corrida Tinamit``.
        :type nombre_corrida: str

        :param t_inic: La fecha inicial de la simulación. Necesaria para simulaciones con cambios climáticos.
        :type t_inic: ft.datetime | ft.date | int | str

        :param lugar_clima: El lugares de la simulación.
        :type lugar_clima: Lugar

        :param tcr: El escenario climático según el sistema de la IPCC (``2.6``, ``4.5``, ``6.0``, o ``8.5``). ``0`` da
          el clima histórico.
        :type tcr: str | float | int

        :param recalc_clima: Si quieres recalcular los datos climáticos, si ya existen.
        :type recalc_clima: bool

        :param clima: Si es una simulación de cambios climáticos o no.
        :type clima: bool

        """

        vals_inic = símismo._frmt_dic_vars(vals_inic)

        # ¡No se puede simular con menos de un modelo!
        if len(símismo.modelos) < 1:
            raise ValueError(_('Hay que conectar submodelos antes de empezar una simulación.'))

        # Si no estamos seguro de la conversión de unidades de tiempo, decirlo aquí.
        if símismo.conv_tiempo_dudoso:
            l_unids = [m.unidad_tiempo() for m in símismo.modelos.values()]
            avisar(_('No se pudo inferir la conversión de unidades de tiempo entre {}.\n'
                     'Especificarla con la función .estab_conv_tiempo().\n'
                     'Por el momento pusimos el factor de conversión a 1, pero probablemente no es lo que quieres.')
                   .format(', '.join(l_unids)))

        # Todo el restode la simulación se hace como en la clase pariente
        return super().simular(
            t_final=t_final, t_inic=t_inic, paso=paso, nombre_corrida=nombre_corrida,
            vals_inic=vals_inic, vals_extern=vals_extern, bd=bd,
            lugar_clima=lugar_clima, clima=clima, vars_interés=vars_interés, guardar=guardar
        )
Beispiel #15
0
    def _verificar(símismo):
        v_f = símismo.var_fuente
        v_r = símismo.var_recip

        if v_f.dims != v_r.dims:
            raise ValueError(
                _('Dimensiones incompatibles entre variables "{}" {} y "{}" {}.'
                  ).format(v_f, v_f.dims, v_r, v_r.dims))

        if not _líms_compat(símismo.var_fuente.líms, símismo.var_recip.líms):
            avisar(
                _('Límites potencialmente incompatibles entre variables "{}" y "{}".'
                  ).format(símismo.var_fuente, símismo.var_recip))
Beispiel #16
0
    def superficies(símismo, parc):
        """
        Devuelve las superficies de unas parcelas de interés.

        :param parc: La(s) parcela(s) de interés.
        :type parc: str | list[str]

        :return: Un vector de superficies de las parcelas.
        :rtype: np.ndarray
        """

        # Asegurar el formato de las parcelas
        if not isinstance(parc, list):
            parc = [parc]

        n_parc = len(parc)  # El número de parcelas

        # Una matriz vacía para las superficies
        superficies = np.empty(n_parc)

        # El nombre de las superficies en este experimento
        nombres = símismo.datos['Parcelas']['Nombres']  # type: list

        # Si no hay superficies en este experimento, establecer un valor de 1 ha automáticamente y avisarle al usuario.
        if símismo.datos['Parcelas']['Superficies'] is None:
            avisar('Tamaños de parcelas no especificados. Se supondrá un tamaño de 1 ha.')
            superficies[:] = 1

        else:
            # Si al contrario tenemos datos de superficies...

            for i, p in enumerate(parc):
                # Para cada parcela de interés...

                # Intentar leer sus datos de superficie
                try:
                    índ_p = nombres.index(p)  # Puede causar un ValueError aquí...
                    sfc = símismo.datos['Parcelas']['Superficies'][índ_p]
                    if sfc == np.nan:
                        raise ValueError  # ...¡o aquí!
                    else:
                        superficies[i] = sfc

                except ValueError:
                    # Si no funcionó, darle un valor de 1 ha y avisarle al usuario
                    avisar('Tamaño de parcela no especificado para parcela "{}". Se supondrá un tamaño de 1 ha.'
                           .format(p))
                    superficies[i] = 1

        # Devolver el vector de superficies.
        return superficies
Beispiel #17
0
    def simular_grupo(símismo, ops_grupo, nombre='Tinamït', paralelo=False):
        """
        Efectua un grupo de simulaciones. Muy útil para accelerar corridas múltiples.

        Parameters
        ----------
        ops_grupo: PlantillaOpsSimulGrupo
            Las opciones de simulación en grupo.
        nombre: str
            El nombre de la simulación.
        paralelo: bool
            Si se simula en paralelo o no. Si el modelo no soporte corridas en paralelo, se ignorará este argumento.

        Returns
        -------
        ResultadosGrupo
        """

        if paralelo and not símismo.paralelizable():
            avisar(
                _('\nEl modelo no se identifica como paralelizable. Para evitar el riesgo'
                  '\nde errores de paralelización, correremos las corridas como simulaciones secuenciales '
                  '\nnormales. '
                  '\nSi tu modelo sí es paralelizable, crear un método nombrado `.paralelizable()` '
                  '\nque devuelve ``True`` en tu clase de modelo para activar la paralelización.'
                  ))
            paralelo = False

        res_grupo = ResultadosGrupo(nombre)
        if paralelo:
            l_trabajos = []
            copia_mod = pickle.dumps(símismo)  # Una copia de este modelo.

            # Crear la lista de información necesaria para las simulaciones en paralelo...
            for ops in ops_grupo:
                l_trabajos.append((copia_mod, ops))

            # Hacer las corridas en paralelo
            with Reserva() as r:
                res_paralelo = r.map(_correr_modelo, l_trabajos)
            for res in res_paralelo:
                res_grupo[str(res)] = res

        else:
            for ops in ops_grupo:
                res = símismo.simular(**ops)
                res_grupo[str(res)] = res

        return res_grupo
Beispiel #18
0
    def cargar_ref_ejemplo_vals_inic(símismo):
        if not os.path.isfile(símismo.dic_prb_datos_inic):
            avisar(_('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                     '\nmodelo sí esté leyendo bien los datos iniciales. Lo generaremos con base en el los valores'
                     '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                     '\n\t"{}"'
                     '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                     '\ncomprobar la función de lectura de datos iniciales.').format(símismo.dic_prb_datos_inic))
            d_vals = copiar_profundo(símismo.variables)
            for d_v in d_vals.values():
                if isinstance(d_v['val'], np.ndarray):
                    d_v['val'] = d_v['val'].tolist()
            guardar_json(d_vals, arch=símismo.dic_prb_datos_inic)

        return cargar_json(símismo.dic_prb_datos_inic)
Beispiel #19
0
    def agregar_frm_regiones(símismo, archivo, col_id, escala_geog=None):
        """

        :param archivo:
        :type archivo:
        :param col_id:
        :type col_id:
        :return:
        :rtype:
        """
        af = sf.Reader(archivo)

        attrs = af.fields[1:]
        nombres_attr = [field[0] for field in attrs]

        try:
            ids = np.array([
                x.record[nombres_attr.index(col_id)]
                for x in af.shapeRecords()
            ],
                           dtype=str)
        except ValueError:
            raise ValueError(
                _('La columna "{}" no existe en la base de datos.').format(
                    col_id))
        if escala_geog is None:

            ids_no_existen = [
                id_ for id_ in ids if str(id_) not in símismo.cód_a_lugar
            ]
            if len(ids_no_existen):
                avisar(
                    _('Las formas con id "{}" no se encuentran en la geografía actual.'
                      ).format(ids_no_existen))
            escls_ids = set(
                símismo.obt_escala_región(id_) for id_ in ids
                if id_ not in ids_no_existen)
            if len(escls_ids) > 1:
                raise ValueError
            elif len(escls_ids) == 1:
                if escala_geog is None:
                    escala_geog = list(escls_ids)[0]
            else:
                if escala_geog is None:
                    escala_geog = 'Automática'

        símismo.formas_reg[escala_geog] = {'af': af, 'ids': ids}
Beispiel #20
0
    def desconectar_vars(símismo,
                         var_fuente,
                         modelo_fuente,
                         modelo_recip=None,
                         var_recip=None):
        """
        Esta función desconecta variables.

        Parameters
        ----------
        var_fuente : str
             El variable fuente de la conexión.
        modelo_fuente : str | Modelo
            El modelo fuente de la conexión.
        modelo_recip : str | Modelo
            El modelo recipiente. Si no se especifica, se quitarán todas conexiones con el variable y modelo fuente.
        var_recip : str
            El variable recipiente. Si no se especifica, se quitarán todas conexiones con el variable y modelo fuente
            y el modelo recipiente especificado. Sin efecto si `modelo_recip` es ``None``.

        """

        # Verificar parámetros
        if modelo_recip is None and var_recip is not None:
            avisar(
                _('`var_recip` sin `modelo_recip` será ignorado en la función '
                  '`SuperConectado.desconectar_vars()`.'))

        # Verificar los nombres de modelos
        modelo_fuente = símismo._verificar_nombre_submodelo(modelo_fuente)
        modelo_recip = símismo._verificar_nombre_submodelo(modelo_recip)

        # Buscar la conexión correspondiente...
        for n, conex in enumerate(símismo.conexiones):
            # Para cada conexión existente...
            if conex['modelo_fuente'] == modelo_fuente and conex[
                    'var_fuente'] == var_fuente:
                # Si el modelo y variable fuente corresponden...

                # Identificar si el modelo recipiente corresponde también.
                if modelo_recip is None:
                    símismo.conexiones.pop(n)
                else:
                    if modelo_recip == conex['modelo_recip']:
                        if var_recip is None or var_recip == conex['var_recip']:
                            símismo.conexiones.pop(n)
Beispiel #21
0
def valid_archivo(archivo):
    direc, nombre = os.path.split(archivo)
    disco, direc = os.path.splitdrive(direc)

    direc = pathvalidate.sanitize_file_path(direc, replacement_text='_')
    nombre = pathvalidate.sanitize_filename(nombre, replacement_text='_')

    if len(direc) >= 260:
        raise ValueError(
            'El archivo siguiente queda demasiado largo...\n\t{}'.format(
                archivo))

    if len(direc) + len(nombre) > 260:
        avisar(
            'Cortamos el nombre "{}" por ser demasiado largo'.format(nombre))
        nombre = nombre[:len(direc) - 260]

    return os.path.join(disco, direc, nombre)
Beispiel #22
0
def _interpolar_xr(m, fechas=None):
    if fechas is not None:
        raise ValueError
    interpolado = m.unstack().interpolate(limit_area='inside').stack()
    if len(interpolado.dropna()):
        return interpolado
    avisar('Extrapolando por falta de datos.')
    return m.unstack().interpolate().stack()

    if m.sizes[_('fecha')] > 1:

        m = m.interpolate_na(_('fecha')).fillna(m)
        if fechas is not None:
            fechas = [fechas] if not isinstance(fechas,
                                                (tuple, list)) else fechas
            m = m.interp({_('fecha'): pd.DatetimeIndex(fechas)}).fillna(m)
    m = m.dropna(_('lugar'), how='all')
    return m.stack(n=[_('lugar'), _('fecha')])
Beispiel #23
0
    def cargar_ref_ejemplo_egr(símismo):
        if not os.path.isfile(símismo.dic_prb_egr):
            avisar(_('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                     '\nmodelo sí esté leyendo bien los egresos de modelos. Lo generaremos con base en el los valores'
                     '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                     '\n\t"{}"'
                     '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                     '\ncomprobar la función de lectura de egresos.').format(símismo.dic_prb_egr))
            d_egr = símismo.leer_archivo_egr(n_años_egr=1, archivo=símismo.prb_arch_egr)
            for var, val in d_egr.items():
                if isinstance(val, np.ndarray):
                    d_egr[var] = val.tolist()

            guardar_json(d_egr, arch=símismo.dic_prb_egr)

        d_egr = cargar_json(símismo.dic_prb_egr)

        return d_egr
Beispiel #24
0
    def unidad_tiempo(símismo):

        unids = list({m.unidad_tiempo() for m in símismo.modelos})
        factores_conv = [1]
        factores_conv[0] = 1
        for u in unids[1:]:
            # Intentar convertir la unidad del submodelo a la unidad de base
            factores_conv.append(convertir(de=unids[0], a=u))
        factores_conv = np.array(factores_conv)
        factores_conv = np.divide(factores_conv, factores_conv.min())

        facts_conv_ent = np.round(factores_conv)
        if not np.array_equal(facts_conv_ent, factores_conv):
            # Si todos los factores no son números enteros, tendremos que aproximar.
            avisar(
                _('Las unidades de tiempo de los modelos ({}) no tienen denominator común. Se aproximará la '
                  'conversión.').format(', '.join(unids)))

        return next(u for u, c in zip(unids, factores_conv) if c == 1)
Beispiel #25
0
    def cargar_ref_vals_inic(cls, arch_ref, mod):

        try:
            return cargar_json(arch_ref)
        except FileNotFoundError:
            avisar(
                _('\nNo encontramos diccionario con los valores corectos de referencia para comprobar que el'
                  '\nmodelo sí esté leyendo bien los datos iniciales. Lo generaremos con base en el los valores'
                  '\nactualmente leídos por el modelo. Asegúrate que los valores generados en'
                  '\n\t"{}"'
                  '\nestén correctos, y si no lo son, bórralo. En el futuro, se empleará este fuente para '
                  '\ncomprobar la función de lectura de datos iniciales.').
                format(arch_ref))
            d_vals = copiar_profundo(mod.variables)
            for d_v in d_vals.values():
                if isinstance(d_v['val'], np.ndarray):
                    d_v['val'] = d_v['val'].tolist()
            guardar_json(d_vals, arch=arch_ref)

            return d_vals
Beispiel #26
0
def guardar_archivo(arch, contenido):
    """
    Guarda un documento de manera segura, sin riesgo de corrumpir el archivo existente si se interrumpe el proceso.

    Parameters
    ----------
    arch : str
        El archivo que hay que escribir.
    contenido : str
        El contenido deseado del archivo.

    """

    with tempfile.NamedTemporaryFile('w', encoding='UTF-8',
                                     delete=False) as temp:
        # Escribimos primero a un fuente temporario para evitar de corrumpir nuestro fuente principal si el programa
        # se interrumpe durante la operación.
        temp.write(contenido)

        # Crear el directorio, si necesario
        direc = os.path.split(arch)[0]
        if len(direc) and not os.path.isdir(direc):  # pragma: sin cobertura
            os.makedirs(os.path.split(arch)[0])

    # Después de haber escrito el fuente, ya podemos cambiar el nombre sin riesgo.
    try:

        if os.path.splitdrive(temp.name)[0] == os.path.splitdrive(arch)[0]:
            os.replace(temp.name, arch)
        else:
            # En casos de documentos en distintos discos, debemos emplear `shutil` en vez.
            shutil.move(temp.name, arch)

    except (PermissionError, FileNotFoundError,
            OSError):  # pragma: sin cobertura
        # Necesario en el caso de corridas en paralelo en Windows. Sin este, la reimportación de Tinamït ocasionada
        # por varias corridas paralelas al mismo tiempo puede causar que el mismo documento se escriba por dos procesos
        # al mismo tiempo, el cual trava el sistema.
        avisar(arch)
Beispiel #27
0
    def obt_conf(cls, llave, auto=None, cond=None, mnsj_err=None):
        """
        Obtiene un valor de configuración de la subclase de modelo.
        
        Parameters
        ----------
        llave: str
            El parámetro de configuración.
        auto: str or int or float or list or bool or dict
            Un valor automático a aplicar si no se encuentra en el diccionario de configuración.
        cond:
            Una condición para validar el valor; si no pasa la condición, se tratará como valor que falta.
        mnsj_err:
            Un mensaje de aviso para devolver al usuario si no se encuentra el valor.

        Returns
        -------
        str, int, float, list, bool, dict
            El valor de configuración
        """

        auto = auto or []
        if isinstance(auto, str):
            auto = [auto]

        try:
            op = conf_mods[cls.__name__][llave]
            if cond is None or cond(op):
                return op
        except KeyError:
            pass

        for op in auto:
            if cond is None or cond(op):
                conf_mods[cls.__name__, llave] = op
                return op

        if mnsj_err:
            avisar(mnsj_err)
Beispiel #28
0
def _resolv_conv(unid_1, unid_2, conv):
    if conv is None:
        # Si no se especificó factor de conversión...

        mensaje = _(
            'No se pudo identificar una conversión automática entre {} y {}. '
            'Se está suponiendo un factor de conversión de 1.').format(
                unid_1, unid_2)
        if unid_1 is None or unid_2 is None:
            conv = 1
            if not (unid_1 is unid_2 is None):
                avisar(mensaje)

        else:
            # Intentar hacer una conversión automática.
            try:
                conv = convertir(de=unid_1, a=unid_2)
            except ValueError:
                # Si eso no funcionó, suponer una conversión de 1.
                conv = 1
                avisar(mensaje)

    return conv
Beispiel #29
0
def _extraer_de_archivo(archivo):
    if not os.path.isfile(archivo):
        raise FileNotFoundError(
            _('El archivo siguiente no existe... :(\n\t{}').format(archivo))

    if os.path.splitext(archivo)[1] != '.py':
        raise ValueError(
            _('El archivo siguiente no parece ser un archivo Python.').format(
                archivo))

    dir_mod, nombre_mod = os.path.split(archivo)
    sys.path.append(dir_mod)
    módulo = importar_mod(os.path.splitext(nombre_mod)[0])
    instancias = {
        nmb: cls
        for nmb, cls in inspect.getmembers(módulo,
                                           lambda x: isinstance(x, ModeloBF))
    }
    clases = {
        nmb: cls
        for nmb, cls in inspect.getmembers(
            módulo, lambda x: (inspect.isclass(x) and issubclass(x, ModeloBF)))
    }
    if instancias:
        if 'Envoltura' in instancias:
            return instancias['Envoltura']
        return list(instancias.values())[0]

    potenciales = {}
    errores = {}
    for nmb, cls in clases.items():
        # noinspection PyBroadException
        try:
            potenciales[nmb] = cls()
        except NotImplementedError:
            continue
        except Exception:
            errores[nmb] = traceback.format_exc()
            continue

    if len(potenciales) == 1:
        return list(potenciales.values())[0]
    elif 'Envoltura' in potenciales:
        return potenciales['Envoltura']
    elif potenciales:
        nmb_elegida = list(potenciales)[0]
        avisar(
            _('\nHabía más de una instancia de "ModeloBF" en el fuente'
              '\n\t{}'
              '\n...y ninguna se llamaba "Envoltura". Tomaremos "{}" como la envoltura'
              '\ny esperaremos que funcione. Si no te parece, asegúrate que la definición de clase o el'
              '\nobjeto correcto se llame "Envoltura".').format(
                  archivo, nmb_elegida))
        return potenciales[nmb_elegida]

    raise AttributeError(
        _('El archivo especificado: \n\t{}\nno contiene subclase o instancia de "EnvolturaBF" utilizable. '
          '\nErrores encontrados:{}').format(
              archivo, ''.join([
                  '\n\n\t{}: \n{}'.format(nmb, e)
                  for nmb, e in errores.items()
              ])))
Beispiel #30
0
            var_mu_trans = var_mu * fac
            var_s_trans = var_s * fac
            var_0 = pm3.Uniform(name='0', lower=0, upper=10)
            l = [pm3.Uniform(name='z_{}'.format(i), lower=1, upper=2) for i in range(100)]


            @as_op(itypes=[tt.dscalar, tt.dscalar, tt.dscalar], otypes=[tt.dscalar, tt.dscalar])
            def func_todo(mu=var_mu_trans, s=var_s_trans, _=l):
                a = [x / 10000 for x in _]
                return mu, s


            obs = pm3.Normal(name='obs', mu=func_todo[0], sd=func_todo[1], observed=datos)

            if adaptivo:
                avisar('Método de paso establecido automáticamente.')

            t = pm3.sample(draws=n_iter)
    else:
        from Matemáticas.Variables import VarPyMC3

        var_mu = VarPyMC3('mu', 'Uniforme', {'ubic': 0, 'escl': 10 * fac})
        var_s = VarPyMC3('sigma', 'Gamma', {'a': 1, 'ubic': 0, 'escl': 10 * fac})
        var_0 = VarPyMC3('0', 'Uniforme', {'ubic': 0, 'escl': 10})
        l_0 = [VarPyMC3('z_{}'.format(i), 'Normal', {'ubic': 1, 'escl': 2}) for i in range(100)]
        l_vars = [v.var for v in l_0]

        # Unas pruebitas de variables generados a base de densidad y de límites. No afectan el modelo prueba aquí.
        l_pruebas_extr = [
            # VarPyMC2.de_densidad(nombre='prueba_uni', dens=0.8, líms_dens=(-3, 4), líms=(-5, 5), cont=True),
            # VarPyMC2.de_densidad(nombre='prueba_uni2', dens=1, líms_dens=(-3, 4), líms=(-5, 5), cont=True),
Beispiel #31
0
    def de_traza(cls, trz, permitidas):

        # Un diccionario para guardar el mejor ajuste
        mejor_ajuste = dict(prms={}, tipo='', p=0.0)

        dists_potenciales = [x for x in dists_potenciales if x in cls.dists_disp()]

        # Verificar que todavia queden distribuciones para considerar.
        if len(dists_potenciales) == 0:
            raise ValueError('Ninguna de las distribuciones especificadas es apropiada para el tipo de distribución.')

        # Para cada distribución potencial para representar a nuestros datos...
        for nombre_dist in dists_potenciales:

            # El diccionario de la distribución
            dic_dist = Ds.dists[nombre_dist]

            # El máximo y el mínimo de la distribución
            mín_dist, máx_dist = dic_dist['límites']

            # Verificar que los límites del parámetro y de la distribución sean compatibles
            lím_igual = (((mín_dist == mín_parám == -np.inf) or
                          (not np.isinf(mín_dist) and not np.isinf(mín_parám))) and
                         ((máx_dist == máx_parám == np.inf) or
                          (not np.isinf(máx_dist) and not np.isinf(máx_parám))))

            # Si son compatibles...
            if lím_igual:

                if mín_parám == -np.inf and máx_parám != np.inf:
                    inv = True
                else:
                    inv = False

                # Restringimos las posibilidades para las distribuciones a ajustar, si necesario
                if np.isinf(mín_parám):

                    if np.isinf(máx_parám):
                        # Para el caso de un parámetro sín límites teoréticos (-inf, inf), no hay restricciones en la
                        # distribución.
                        restric = {}

                    else:
                        raise ValueError('No debería ser posible llegar hasta este error.')
                else:

                    if np.isinf(máx_parám):
                        # En el caso [R, inf), limitamos el valor inferior de la distribución al límite inferior del
                        # parámetro
                        restric = {'floc': mín_parám}

                    else:
                        # En el caso [R, R], limitamos los valores inferiores y superiores de la distribución.
                        if nombre_dist == 'Uniforme' or nombre_dist == 'Beta':
                            restric = {'floc': mín_parám, 'fscale': máx_parám - mín_parám}
                        elif nombre_dist == 'NormalTrunc':
                            restric = {'floc': (máx_parám + mín_parám) / 2}
                        elif nombre_dist == 'VonMises':
                            restric = {'floc': mín_parám + mat.pi, 'fscale': máx_parám - mín_parám}
                        else:
                            raise ValueError(nombre_dist)

                # Ajustar los parámetros de la distribución SciPy para caber con los datos.
                if nombre_dist == 'Uniforme':
                    # Para distribuciones uniformes, no hay nada que calibrar.
                    prms = {'ubic': restric['floc'], 'escl': restric['fscale']}
                else:
                    try:
                        tupla_prms = dic_dist['scipy'].fit(datos, **restric)
                        l_prms = dic_dist['paráms']
                        prms = {p: v for p, v in zip(l_prms, tupla_prms)}
                    except:
                        prms = None

                if prms is not None:
                    # Medir el ajuste de la distribución
                    prms_scipy = prms.copy()
                    prms_scipy['loc'] = prms_scipy.pop('ubic')
                    prms_scipy['scale'] = prms_scipy.pop('escl')
                    p = estad.kstest(rvs=datos, cdf=dic_dist['scipy'](**prms_scipy).cdf)[1]

                    # Si el ajuste es mejor que el mejor ajuste anterior...
                    if p > mejor_ajuste['p'] or mejor_ajuste['tipo'] == '':
                        # Guardarlo
                        mejor_ajuste['p'] = p
                        mejor_ajuste['prms'] = prms
                        mejor_ajuste['tipo'] = nombre_dist

                        # Inversar la distribución sinecesario
                        if inv and 'escl' in prms:
                            prms['escl'] = -prms['escl']

        # Si no logramos un buen aujste, avisar al usuario.
        if mejor_ajuste['p'] <= 0.10:
            avisar('El ajuste de la mejor distribución quedó muy mal (p = %f).' % round(mejor_ajuste['p'], 4))
            # Para hacer: ¿Permitir transformaciones adicionales a los datos?

        # Devolver la distribución con el mejor ajuste, tanto como el valor de su ajuste.
        resultado = {'dist': VarSciPy(tipo_dist=mejor_ajuste['tipo'], paráms=mejor_ajuste['prms']),
                     'nombre': mejor_ajuste['tipo'],
                     'prms': mejor_ajuste['prms'],
                     'p': mejor_ajuste['p']}

        return resultado
Beispiel #32
0
 def obt_vals(símismo, n):
     reemplazar = n > len(símismo.trz)
     if reemplazar:
         avisar('Repitiendo valores porque se pidieron más repeticiones que hay disponibles.')
     return np.random.choice(símismo.trz, n, replace=reemplazar, p=símismo.pesos)