Código fuente para tinamit.envolt.bf.sahysmod._envolt

import os
import shutil
import tempfile
from subprocess import run

import numpy as np
from pkg_resources import resource_filename

from tinamit.config import _
from tinamit.envolt.bf import ModeloBloques
from ._arch_egr import leer_arch_egr
from ._arch_ingr import leer_info_dic_paráms, escribir_desde_dic_paráms
from ._vars import VariablesSAHYSMOD, VarBloqSAHYSMOD


[documentos]class ModeloSAHYSMOD(ModeloBloques): """ Envoltura para modelos SAHYSMOD. """ idioma_orig = 'en' # La lengua de los nombres y descripción de los variables (y NO la del código aquí) def __init__(símismo, archivo, nombre='SAHYSMOD'): símismo.archivo = archivo símismo.direc_trabajo = '' # Directorio vacío para guardar datos de ingresos después símismo.dic_ingr = {} # Buscar la ubicación del modelo SAHYSMOD. símismo.exe_SAHYSMOD = símismo.obt_conf( 'exe', cond=os.path.isfile, mnsj_err=_( '\nDebes especificar la ubicación del ejecutable SAHYSMOD, p. ej.' '\n\tModeloSAHYSMOD.estab_conf("exe", "C:\\Camino\\hacia\\mi\\SAHYSMODConsole.exe")' '\npara poder hacer simulaciones con modelos SAHYSMOD.' '\nSi no instalaste SAHYSMOD, lo puedes conseguir para Linux, Mac o Windows de ' 'https://github.com/julienmalard/sahysmod-sourcecode.' ) ) # Leer el fuente de ingreso símismo.dic_ingr = leer_info_dic_paráms(archivo_fnt=símismo.archivo) variables = VariablesSAHYSMOD(inic=símismo.dic_ingr) # Inicializar la clase pariente. super().__init__(variables=variables, nombre=nombre) # Establecer los variables climáticos. símismo.conectar_var_clima(var='Pp - Rainfall', var_clima='بارش', combin='total', conv=0.001) def iniciar_modelo(símismo, corrida): # Crear un diccionario de trabajo específico a esta corrida. símismo.direc_trabajo = tempfile.mkdtemp('_' + str(hash(corrida))) super().iniciar_modelo(corrida) def avanzar_modelo(símismo, n_ciclos): arch_egreso = os.path.join(símismo.direc_trabajo, 'SAHYSMOD.out') arch_ingreso = os.path.join(símismo.direc_trabajo, 'SAHYSMOD.inp') símismo._verificar_estado_vars() símismo._escribir_archivo_ingr(n_ciclos=n_ciclos, archivo=arch_ingreso) # Limpiar archivos de egresos que podrían estar allí if os.path.isfile(arch_egreso): os.remove(arch_egreso) # Correr la comanda desde la línea de comanda comanda = '"{SAHYSMOD}" "{ingreso}" "{egreso}"'.format( SAHYSMOD=símismo.exe_SAHYSMOD, ingreso=arch_ingreso, egreso=arch_egreso ) run(comanda, cwd=símismo.direc_trabajo) # Verificar que SAHYSMOD generó egresos. if not os.path.isfile(arch_egreso): with open(os.path.join(símismo.direc_trabajo, 'error.lst')) as d: mnsj_sahysmod = d.readlines() raise FileNotFoundError(_( '\n\nEl modelo SAHYSMOD no generó egreso. Esto probablemente quiere decir que tuvo problema interno.' '\n\t¡Diviértete! :)' '\nEl archivo de ingresos está en: {arch}' '\nMensajes de error de SAHYSMOD:' '\n{mnsj}').format(arch=arch_ingreso, mnsj=mnsj_sahysmod)) símismo.leer_egr_modelo(n_ciclos=n_ciclos) def cerrar(símismo): shutil.rmtree(símismo.direc_trabajo) def leer_egr_modelo(símismo, n_ciclos): archivo = os.path.join(símismo.direc_trabajo, 'SAHYSMOD.out') dic_egr = leer_arch_egr( archivo=archivo, años=n_ciclos ) # Convertir códigos de variables a nombres de variables for c, v in dic_egr.items(): try: símismo.variables.cód_a_var(c).poner_vals_paso(v[0]) # v[0] para quitar dimensión de año except KeyError: pass @classmethod def instalado(cls): return cls.obt_conf('exe') is not None def paralelizable(símismo): return True def unidad_tiempo(símismo): return 'mes' @classmethod def prb_egreso(cls): arch = resource_filename(__name__, 'rcrs/prb_egresos.out') return arch, leer_arch_egr @classmethod def prb_ingreso(cls): arch = resource_filename(__name__, 'rcrs/prb_ingresos.inp') def f(a): return VariablesSAHYSMOD(leer_info_dic_paráms(a)) return arch, f @classmethod def prb_simul(cls): return resource_filename(__name__, 'rcrs/prb_ingresos.inp') def _escribir_archivo_ingr(símismo, n_ciclos, archivo): # Establecer el número de años de simulación símismo.dic_ingr['NY'] = n_ciclos # Copiar datos desde el diccionario de ingresos for var in símismo.variables.egresos(): llave = var.cód.replace('#', '').upper() if llave in símismo.dic_ingr: m = símismo.dic_ingr[llave] if isinstance(var, VarBloqSAHYSMOD): val = var.obt_vals_paso() if m.shape == val.shape: m[:] = val else: m[:] = val[-1] else: val = var.obt_val() m[:] = val m[np.isnan(m)] = -1 # Y finalmente, escribir el fuente de valores de ingreso escribir_desde_dic_paráms(dic_paráms=símismo.dic_ingr, archivo_obj=archivo) def _verificar_estado_vars(símismo): # Aquí tenemos que verificar el estado interno de SAHYSMOD porque éste, siendo SAHYSMOD, da mensajes de error # con el mínimo de información posible. a = símismo.variables['Area A - Seasonal fraction area crop A'].obt_vals_paso() b = símismo.variables['Area B - Seasonal fraction area crop B'].obt_vals_paso() fsa = símismo.variables['FsA - Water storage efficiency crop A'].obt_vals_paso() fsb = símismo.variables['FsB - Water storage efficiency crop B'].obt_vals_paso() if np.any(np.logical_and(fsa == -1, a > 0)): raise ValueError(_('Los valores de FsA no pueden faltar en polígonos que tienen superficie con cultivo A.')) if np.any(np.logical_and(fsb == -1, b > 0)): raise ValueError(_('Los valores de FsB no pueden faltar en polígonos que tienen superficie con cultivo B.'))