def estimate_fao56_daily(self, day_of_year, temp_c, temp_c_min, temp_c_max, tdew, elevation, latitude, rh, wind_m_s, atmos_pres): """ Estimate fao56 from weather """ sha = pyeto.sunset_hour_angle(pyeto.deg2rad(latitude), pyeto.sol_dec(day_of_year)) daylight_hours = pyeto.daylight_hours(sha) sunshine_hours = 0.8 * daylight_hours ird = pyeto.inv_rel_dist_earth_sun(day_of_year) et_rad = pyeto.et_rad(pyeto.deg2rad(latitude), pyeto.sol_dec(day_of_year), sha, ird) sol_rad = pyeto.sol_rad_from_sun_hours(daylight_hours, sunshine_hours, et_rad) net_in_sol_rad = pyeto.net_in_sol_rad(sol_rad=sol_rad, albedo=0.23) cs_rad = pyeto.cs_rad(elevation, et_rad) avp = pyeto.avp_from_tdew(tdew) net_out_lw_rad = pyeto.net_out_lw_rad( pyeto.convert.celsius2kelvin(temp_c_min), pyeto.convert.celsius2kelvin(temp_c_max), sol_rad, cs_rad, avp) net_rad = pyeto.net_rad(net_in_sol_rad, net_out_lw_rad) eto = pyeto.fao56_penman_monteith( net_rad=net_rad, t=pyeto.convert.celsius2kelvin(temp_c), ws=wind_m_s, svp=pyeto.svp_from_t(temp_c), avp=avp, delta_svp=pyeto.delta_svp(temp_c), psy=pyeto.psy_const(atmos_pres)) return eto
def calcPET(lat, time, tmin, tmax, tmean): ''' Calculates Potential Evapotranspiration using Hargreaves equation (Hargreaves and Samani, 1985) ''' latrad = pt.deg2rad(lat) #Latitude to radians dayofyear = pd.Series(time).dt.day.values etrad = [] pet = [] # Calculate ET radiation for x in np.nditer(dayofyear): soldec = pt.sol_dec(x) #Solar declination sha = pt.sunset_hour_angle(latrad, soldec) #Sunset hour aingle ird = pt.inv_rel_dist_earth_sun( x) #Inverse relative distance Earth-Sun etrad.append(pt.et_rad(latrad, soldec, sha, ird)) #Extraterrestrial radiation # Calculate PET using hargreaves for x in range(0, len(etrad)): pet.append(pt.hargreaves(tmin[x], tmax[x], tmean[x], etrad[x])) pet = np.array(pet) return (pet)
def thorn(year, latitude, df, model): data = df.loc[df['yil'] == year][model].values # lat = 37 lat = deg2rad(latitude) mmdlh = monthly_mean_daylight_hours(lat, year) evapo = np.array(thornthwaite(data, mmdlh)) return evapo
def thorn_clima(year, latitude, df, model, senario): data = df.loc[(df['Yıl'] == year) & (df['Model'] == model) & (df['Senaryo'] == senario), 'Ortalama_Sıcaklık'].values # lat = 37 if len(data) != 12: data = data[0:12] lat = deg2rad(latitude) mmdlh = monthly_mean_daylight_hours(lat, year) evapo = np.array(thornthwaite(data, mmdlh)) return data, evapo
def main(lat, temp_mean, precip_mean, max_tsmd): '''get evapotranspiration''' # taken from Richards pyeto, see doc in same folder for more informatios pyeto_lat = pyeto.deg2rad(lat) # converts the degree to radians mean_month_list = [temp_mean[i] for i in temp_mean] monthly_mean_daylight = pyeto.monthly_mean_daylight_hours(pyeto_lat) eto = pyeto.thornthwaite(mean_month_list, monthly_mean_daylight) '''make a "month_number" : "evapo" dic''' eto_dict = {} for n,i in enumerate(eto): eto_dict[n+1] = eto[n] print "\nWaterbalance with maximum deficientcy of", max_tsmd acc_TSMD = {} acc_factor = 0 budget = {} '''The following part is still a bit hacky. Two for loops that first calculates the the water buget for every mongth and then starts a second loop to substract the value of the month before from the current month ''' print "month \t rain \t eto \t\t TSMD" for month, rain, etom in zip(range(1,13),precip_mean, eto_dict): TSMD = precip_mean[rain] - ( eto_dict[etom] * 0.75 ) if TSMD <= max_tsmd: TSMD = max_tsmd print month,"\t", precip_mean[rain], "\t", eto_dict[etom],"\t", TSMD budget[month] = TSMD if TSMD < 0 else 0 for month, rain, etom in zip(range(1,13),precip_mean, eto_dict): TSMD = precip_mean[rain] - ( eto_dict[etom] * 0.75 ) if month == 1: acc_TSMD[month] = TSMD + budget[12] else: acc_TSMD[month] = TSMD + budget[month -1] if acc_TSMD[month] > 0 : acc_TSMD[month] = 0 if acc_TSMD[month] < max_tsmd: acc_TSMD[month] = max_tsmd print "\nWater budget" p(budget) print "" return acc_TSMD
def get_evap_i(lat, elev, wind, srad, tmin, tmax, tavg, month): if month == 1: J = 15 else: J = 15 + (month - 1) * 30 latitude = pyeto.deg2rad(lat) atmosphericVapourPressure = pyeto.avp_from_tmin(tmin) saturationVapourPressure = pyeto.svp_from_t(tavg) ird = pyeto.inv_rel_dist_earth_sun(J) solarDeclination = pyeto.sol_dec(J) sha = [pyeto.sunset_hour_angle(l, solarDeclination) for l in latitude] extraterrestrialRad = [ pyeto.et_rad(x, solarDeclination, y, ird) for x, y in zip(latitude, sha) ] clearSkyRad = pyeto.cs_rad(elev, extraterrestrialRad) netInSolRadnet = pyeto.net_in_sol_rad(srad * 0.001, albedo=0.23) netOutSolRadnet = pyeto.net_out_lw_rad(tmin, tmax, srad * 0.001, clearSkyRad, atmosphericVapourPressure) netRadiation = pyeto.net_rad(netInSolRadnet, netOutSolRadnet) tempKelvin = pyeto.celsius2kelvin(tavg) windSpeed2m = pyeto.wind_speed_2m(wind, 10) slopeSvp = pyeto.delta_svp(tavg) atmPressure = pyeto.atm_pressure(elev) psyConstant = pyeto.psy_const(atmPressure) return pyeto.fao56_penman_monteith(netRadiation, tempKelvin, windSpeed2m, saturationVapourPressure, atmosphericVapourPressure, slopeSvp, psyConstant, shf=0.0)
import pandas as pd import numpy as np import os from pyeto import thornthwaite, monthly_mean_daylight_hours, deg2rad os.chdir(r"C:\Users\PC3\Desktop\Hydro") df = pd.read_csv('data.csv') df['Date'] = pd.to_datetime(df['Date']) df['Year'] = df['Date'].dt.year df = df.set_index('Date') df_m = df.resample("M").mean() data = [] lat = deg2rad(41.3) for i in range(2015,2019): mmdlh = monthly_mean_daylight_hours(lat, i) monthly_t = df_m['Temp'][(df_m.Year == i)] PET = thornthwaite(monthly_t.values.tolist(), mmdlh) data.append(PET) print("a")
def calculate_precipitation(self, d): if "rain" in d: self.rain_day = float(d["rain"]) if "snow" in d: self.snow_day = float(d["snow"]) # def calculate_ev_fao56_factor(self, d): dt = d['dt'] factor = 0.0 if dt > d['sunrise']: if dt < d['sunset']: factor = min(float(dt - d['sunrise'])/3600.0, 1.0) else: if dt > d['sunset']: factor = (dt - d['sunrise'])/3600.0 if factor < 1.0: factor = 1.0 - factor return factor #def estimate_fao56_hourly(self, day_of_year, temp_c, tdew, elevation, latitude, rh, wind_m_s, atmos_pres): """ Estimate fao56 from weather """ sha = pyeto.sunset_hour_angle(pyeto.deg2rad(latitude), pyeto.sol_dec(day_of_year)) daylight_hours = pyeto.daylight_hours(sha) sunshine_hours = 0.8 * daylight_hours ird = pyeto.inv_rel_dist_earth_sun(day_of_year) et_rad = pyeto.et_rad(pyeto.deg2rad(latitude), pyeto.sol_dec(day_of_year), sha, ird) sol_rad = pyeto.sol_rad_from_sun_hours(daylight_hours, sunshine_hours, et_rad) net_in_sol_rad = pyeto.net_in_sol_rad(sol_rad=sol_rad, albedo=0.23) cs_rad = pyeto.cs_rad(elevation, et_rad) avp = pyeto.avp_from_tdew(tdew) #not sure if I trust this net_out_lw_rad calculation here! net_out_lw_rad = pyeto.net_out_lw_rad(temp_c-1, temp_c, sol_rad, cs_rad, avp) net_rad = pyeto.net_rad(net_in_sol_rad, net_out_lw_rad) eto = pyeto.fao56_penman_monteith( net_rad=net_rad, t=pyeto.convert.celsius2kelvin(temp_c), ws=wind_m_s, svp=pyeto.svp_from_t(temp_c), avp=avp, delta_svp=pyeto.delta_svp(temp_c), psy=pyeto.psy_const(atmos_pres)) return eto #def calculate_fao56_hourly(self, d): day_of_year = datetime.datetime.now().timetuple().tm_yday T_hr = d['temp'] t_dew = float(d["dew_point"]) pressure = d['pressure'] RH_hr = d['humidity'] u_2 = d['wind_speed'] #print("CALCULATE_FAO56:") #print("T_hr: {}".format(T_hr)) #print("t_dew: {}".format(t_dew)) #print("RH_hr: {}".format(RH_hr)) #print("u_2: {}".format(u_2)) #print("pressure: {}".format(pressure)) fao56 = self.estimate_fao56_hourly(day_of_year, T_hr, t_dew, self.elevation, LAT, RH_hr, u_2, pressure) return fao56
#watering system check for amount of rain. Forever check watering parameters if <10cm then no action if >10cm then initiate watering system # this data should be from nws. import pyeto latitude_deg = 38.01 latitude = pyeto.deg2rad(latitude_deg) day_of_year = 206 tmin = 37 tmax = 53 coastal = True altitude = 147 rh_min = 13 rh_max = 88 ws = 1.3 tmean = pyeto.daily_mean_t(tmin, tmax) atmos_pres = pyeto.atm_pressure(altitude) psy = pyeto.psy_const(atmos_pres) # Humidity svp_tmin = pyeto.svp_from_t(tmin) svp_tmax = pyeto.svp_from_t(tmax) delta_svp = pyeto.delta_svp(tmean) svp = pyeto.mean_svp(tmin, tmax) avp = pyeto.avp_from_rhmin_rhmax(svp_tmin, svp_tmax, rh_min, rh_max)
def get_data_from_WU(): ###array to store the reports wu_weather_reports = [] ## today and last 6 days definition day1 = now - datetime.timedelta(days=6) day2 = now - datetime.timedelta(days=5) day3 = now - datetime.timedelta(days=4) day4 = now - datetime.timedelta(days=3) day5 = now - datetime.timedelta(days=2) day6 = now - datetime.timedelta(days=1) day7 = now #### convert dates to WU required format days = { 'day1': day1.strftime('%Y%m%d'), 'day2': day2.strftime('%Y%m%d'), 'day3': day3.strftime('%Y%m%d'), 'day4': day4.strftime('%Y%m%d'), 'day5': day5.strftime('%Y%m%d'), 'day6': day6.strftime('%Y%m%d'), 'day7': day7.strftime('%Y%m%d') } ### make API wather hisotry call for each day for day in days: url = 'http://api.wunderground.com/api/7c2ab99a0ccee978/history_{0}/q/95316.json'.format( days[day]) headers = {'content-type': 'application/JSON; charset=utf8'} response = requests.get(url, headers=headers) data = json.loads(response.text) #ETo calculation for the day using FAO-56 Penman-Monteith method lat = pyeto.deg2rad(37.585652) altitude = 38 julian_day = datetime.datetime.strptime(days.get(day), '%Y%m%d').timetuple().tm_yday sol_dec = pyeto.sol_dec(julian_day) sha = pyeto.sunset_hour_angle(lat, sol_dec) ird = pyeto.inv_rel_dist_earth_sun(julian_day) ### net radiation calculator net_rad = pyeto.et_rad(lat, sol_dec, sha, ird) temp_c = float(data["history"]["observations"][1]["tempm"]) temp_k = float(data["history"]["observations"][1]["tempi"]) humidity = float(data["history"]["observations"][1]["hum"]) dew_point = float(data["history"]["observations"][1]["dewptm"]) ws = float(data["history"]["observations"][1]["wspdm"]) #actual and saturated vapour pressure in kPH svp = pyeto.svp_from_t(temp_c) avp = pyeto.avp_from_tdew(dew_point) delta_svp = pyeto.delta_svp(temp_c) atm_pressure = pyeto.atm_pressure(altitude) psy = pyeto.psy_const(atm_pressure) #### the ETo plugin retun results in mm, it was converted to inched ETo_in_mm = pyeto.fao56_penman_monteith(net_rad, temp_k, ws, svp, avp, delta_svp, psy, shf=0.0) ETo = ETo_in_mm * 0.039370 ## insert eto value to day weather report data["history"]["observations"][1].update( {"ETo": "{0:.2f}".format(ETo)}) ###add report to report collector array wu_weather_reports.append(data["history"]["observations"][1]) #return all reports return wu_weather_reports
def etp_Thornthwaite(self, anosCalculoETP, inicioPlantioTuple): latitudeRad = deg2rad(self.estacao.latitude) temperaturaMensalAcc = np.array([]).reshape(0, 12) temperaturaDecendioAcc = np.array([]).reshape(12, 3, 0) ETPs = np.zeros([len(anosCalculoETP), 13, 4]) self.anosCalculo = anosCalculoETP # O ETP é calculado anualmente e o resultado final é a média desses cálculos # anosCalculoETP grava os anos selecionados pelo usuário para o cálculo do ETP if anosCalculoETP: for ano in anosCalculoETP: #ano = min(anosCalculoETP) ### Calcula medias mensais e decendiais de temperatura para um ano ### diaAtual = date(ano, 1, 1) temperaturaAcum = 0 temperaturaAcumMes = 0 diasNoDecendio = 0 diasNoMes = 0 temperaturaMensal = [] temperaturaDecendio = np.zeros((12, 3)) #final = date(min(anosCalculoETP)+1, inicioPlantioTuple[0], inicioPlantioTuple[1]) #print(anosCalculoETP) while (diaAtual.year == ano): #while (diaAtual.year in anosCalculoETP) and ((diaAtual)!=final): #print(diaAtual) if not np.isnan( self.dadosMeteorologicos['tmed'][diaAtual]): #print(self.dadosMeteorologicos['tmed'][diaAtual]) temperaturaAcum += self.dadosMeteorologicos['tmed'][ diaAtual] temperaturaAcumMes += self.dadosMeteorologicos['tmed'][ diaAtual] diasNoDecendio += 1 diasNoMes += 1 amanha = diaAtual + timedelta(days=1) #print(temperaturaAcum) if amanha.month != diaAtual.month: #print('trocou mes') #print(amanha.month) if diasNoMes > 0: # Corrigir temperaturas negativas temperaturaMensal.append(temperaturaAcumMes / diasNoMes * (temperaturaAcumMes >= 0)) else: temperaturaMensal.append(25) temperaturaAcumMes = 0 diasNoMes = 0 if amanha.day == 1 or amanha.day == 11 or amanha.day == 21: decendioAtual = calculosDecendiais.converterToDataDecendio( diaAtual) if diasNoDecendio > 0: temperaturaDecendio[ decendioAtual[0] - 1, decendioAtual[1] - 1] = (temperaturaAcum / diasNoDecendio) * (temperaturaAcum >= 0) else: temperaturaDecendio[decendioAtual[0] - 1, decendioAtual[1] - 1] = 25 temperaturaAcum = 0 diasNoDecendio = 0 #print(diaAtual) diaAtual = amanha ########### #print('temp Acumulada e temp Mensal') #print(temperaturaMensalAcc) #print(temperaturaDecendioAcc) temperaturaMensalAcc = np.vstack( (temperaturaMensalAcc, temperaturaMensal)) temperaturaDecendioAcc = np.dstack( (temperaturaDecendioAcc, temperaturaDecendio)) temperaturaMensalMedia = temperaturaMensal temperaturaDecendioMedia = temperaturaDecendio #print(temperaturaMensalAcc) #print(temperaturaDecendioAcc) #print(temperaturaMensalAcc) # Calcula o heat index a partir das temperaturas I = 0.0 for Tai in temperaturaMensalMedia: if Tai / 5.0 > 0.0: I += (Tai / 5.0)**1.514 a = (6.75e-07 * I**3) - (7.71e-05 * I**2) + (1.792e-02 * I) + 0.49239 #print(I) #print(a) horasDeSolAcum = 0 diasNoDecendio = 0 diaAtual = date(ano, 1, 1) while (diaAtual.year == ano): # Calcula o valor dos ETPs decendiais #while diaAtual.year == 2000: sd = sol_dec(int(diaAtual.strftime('%j'))) sha = sunset_hour_angle(latitudeRad, sd) horasDeSolAcum += daylight_hours(sha) idx = anosCalculoETP.index(ano) diasNoDecendio += 1 amanha = diaAtual + timedelta(days=1) if amanha.day == 1 or amanha.day == 11 or amanha.day == 21: horasDeSolMedia = horasDeSolAcum / diasNoDecendio decendioAtual = calculosDecendiais.converterToDataDecendio( diaAtual) #print(idx) #print(decendioAtual) #print(temperaturaDecendioMedia) ETPs[idx][decendioAtual] = 16 * ( horasDeSolMedia / 12.0) * (diasNoDecendio / 30.0) * ( (10.0 * temperaturaDecendioMedia[decendioAtual[0] - 1, decendioAtual[1] - 1] / I)**a) horasDeSolAcum = 0 diasNoDecendio = 0 diaAtual = amanha self.temperaturaMensalMedia = temperaturaMensalAcc return ETPs
def etp_Thornthwaite(self, anosCalculoETP): latitudeRad = deg2rad(self.estacao.latitude) temperaturaMensalAcc = np.array([]).reshape(0, 12) temperaturaDecendioAcc = np.array([]).reshape(12, 3, 0) ETPs = {} # O ETP é calculado anualmente e o resultado final é a média desses cálculos # anosCalculoETP grava os anos selecionados pelo usuário para o cálculo do ETP if anosCalculoETP: for ano in anosCalculoETP: ### Calcula medias mensais e decendiais de temperatura para um ano ### diaAtual = date(ano, 1, 1) temperaturaAcum = 0 temperaturaAcumMes = 0 diasNoDecendio = 0 diasNoMes = 0 temperaturaMensal = [] temperaturaDecendio = np.zeros((12, 3)) while diaAtual.year == ano: if self.dadosMeteorologicos['tmed'][diaAtual] is not None: temperaturaAcum += self.dadosMeteorologicos['tmed'][ diaAtual] temperaturaAcumMes += self.dadosMeteorologicos['tmed'][ diaAtual] diasNoDecendio += 1 diasNoMes += 1 amanha = diaAtual + timedelta(days=1) if amanha.month != diaAtual.month: if diasNoMes > 0: # Corrigir temperaturas negativas temperaturaMensal.append(temperaturaAcumMes / diasNoMes * (temperaturaAcumMes >= 0)) else: temperaturaMensal.append(25) temperaturaAcumMes = 0 diasNoMes = 0 if amanha.day == 1 or amanha.day == 11 or amanha.day == 21: decendioAtual = calculosDecendiais.converterToDataDecendio( diaAtual) if diasNoDecendio > 0: temperaturaDecendio[ decendioAtual[0] - 1, decendioAtual[1] - 1] = (temperaturaAcum / diasNoDecendio) * (temperaturaAcum >= 0) else: temperaturaDecendio[decendioAtual[0] - 1, decendioAtual[1] - 1] = 25 temperaturaAcum = 0 diasNoDecendio = 0 diaAtual = amanha ########### temperaturaMensalAcc = np.vstack( (temperaturaMensalAcc, temperaturaMensal)) temperaturaDecendioAcc = np.dstack( (temperaturaDecendioAcc, temperaturaDecendio)) temperaturaMensalMedia = np.mean(temperaturaMensalAcc, axis=0) temperaturaDecendioMedia = np.mean(temperaturaDecendioAcc, axis=2) # Calcula o heat index a partir das temperaturas self.temperaturaMensalMedia = temperaturaMensalMedia I = 0.0 for Tai in temperaturaMensalMedia: if Tai / 5.0 > 0.0: I += (Tai / 5.0)**1.514 a = (6.75e-07 * I**3) - (7.71e-05 * I**2) + (1.792e-02 * I) + 0.49239 diaAtual = date(2000, 1, 1) horasDeSolAcum = 0 diasNoDecendio = 0 # Calcula o valor dos ETPs decendiais while diaAtual.year == 2000: sd = sol_dec(int(diaAtual.strftime('%j'))) sha = sunset_hour_angle(latitudeRad, sd) horasDeSolAcum += daylight_hours(sha) diasNoDecendio += 1 amanha = diaAtual + timedelta(days=1) if amanha.day == 1 or amanha.day == 11 or amanha.day == 21: horasDeSolMedia = horasDeSolAcum / diasNoDecendio decendioAtual = calculosDecendiais.converterToDataDecendio( diaAtual) ETPs[decendioAtual] = 1.6 * (horasDeSolMedia / 12.0) * ( diasNoDecendio / 30.0) * ( (10.0 * temperaturaDecendioMedia[decendioAtual[0] - 1, decendioAtual[1] - 1] / I)**a) * 10.0 horasDeSolAcum = 0 diasNoDecendio = 0 diaAtual = amanha return ETPs
def exec(self): log.info('[START] {}'.format("exec")) try: if (platform.system() == 'Windows'): # 옵션 설정 sysOpt = { # 시작/종료 시간 'srtDate': '2020-09-01', 'endDate': '2020-09-03' # 경도 최소/최대/간격 , 'lonMin': 0, 'lonMax': 360, 'lonInv': 0.5 # 위도 최소/최대/간격 , 'latMin': -90, 'latMax': 90, 'latInv': 0.5 } else: # 옵션 설정 sysOpt = { # 시작/종료 시간 # 'srtDate': globalVar['srtDate'] # , 'endDate': globalVar['endDate'] } # globalVar['outPath'] = 'F:/Global Temp/aski' modelList = ['MRI-ESM2-0'] for i, modelInfo in enumerate(modelList): log.info("[CHECK] modelInfo : {}".format(modelInfo)) inpFile = '{}/{}/{} ssp585 2015-2100_*.nc'.format( globalVar['inpPath'], serviceName, modelInfo) fileList = sorted(glob.glob(inpFile)) dsData = xr.open_mfdataset(fileList) # dsData = dsData.sel(lon=slice(120, 150), time=slice('2015-01', '2016-12')) # dsData = dsData.sel(lat=slice(50, 50), lon=slice(120, 120), time=slice('2015-01', '2015-12')) # 월별 시간 변환 dsData['time'] = pd.to_datetime(pd.to_datetime( dsData['time'].values).strftime("%Y-%m"), format='%Y-%m') # 단위 설정 dsData['tasmin'].attrs['units'] = 'degC' dsData['tasmax'].attrs['units'] = 'degC' dsData['tas'].attrs['units'] = 'degC' # 단위 환산을 위한 매월 마지막 날 계산 lon1D = dsData['lon'].values lat1D = dsData['lat'].values time1D = dsData['time'].values timeEndMonth = [] timeYear = dsData['time.year'].values timeMonth = dsData['time.month'].values for i in range(0, len(timeYear)): timeEndMonth.append( calendar.monthrange(timeYear[i], timeMonth[i])[1]) latRad1D = pyeto.deg2rad(dsData['lat']) # 2022.08.13 doy 순서 변경 # 시작 순서 1, 32, ... dayOfYear1D = dsData['time.dayofyear'] latRad3D = np.tile( np.transpose(np.tile(latRad1D, (len(lon1D), 1))), (len(time1D), 1, 1)) dayOfYear3D = np.transpose( np.tile(dayOfYear1D, (len(lon1D), len(lat1D), 1))) timeEndMonth3D = np.transpose( np.tile(timeEndMonth, (len(lon1D), len(lat1D), 1))) tmpData = xr.Dataset( { 'timeEndMonth': (('time', 'lat', 'lon'), (timeEndMonth3D).reshape( len(time1D), len(lat1D), len(lon1D))), 'latRad': (('time', 'lat', 'lon'), (latRad3D).reshape( len(time1D), len(lat1D), len(lon1D))) # , 'dayOfYear': (('time', 'lat', 'lon'), (dayOfYear3D).reshape(len(time1D), len(lat1D), len(lon1D))) , 'doy': (('time', 'lat', 'lon'), (dayOfYear3D).reshape( len(time1D), len(lat1D), len(lon1D))) }, coords={ 'lat': lat1D, 'lon': lon1D, 'time': time1D }) # 마지막 순서 31, 59, ... # tmpData['dayOfYear'] = tmpData['doy'] tmpData['dayOfYear'] = tmpData['doy'] + timeEndMonth3D # ******************************************************************************************** # FAO-56 Penman-Monteith 방법 # ******************************************************************************************** # https://pyeto.readthedocs.io/en/latest/fao56_penman_monteith.html 매뉴얼 참조 # 1 W/m2 = 1 J/m2를 기준으로 MJ/day 변환 # dsData['rsdsMJ'] = dsData['rsds'] * 86400 / (10 ** 6) dsData['rsdsMJ'] = dsData['rsds'] * 2592000 / (10**6) # 섭씨 to 켈빈 dsData['tasKel'] = dsData['tas'] + 273.15 dsData['tasminKel'] = dsData['tasmin'] + 273.15 dsData['tasmaxKel'] = dsData['tasmax'] + 273.15 dsData['svp'] = svp_from_t(dsData['tas']) dsData['svpMax'] = svp_from_t(dsData['tasmax']) dsData['svpMin'] = svp_from_t(dsData['tasmin']) tmpData['solDec'] = sol_dec(tmpData['dayOfYear']) tmpData['sha'] = sunset_hour_angle(tmpData['latRad'], tmpData['solDec']) tmpData['dayLightHour'] = daylight_hours(tmpData['sha']) tmpData['ird'] = inv_rel_dist_earth_sun(tmpData['dayOfYear']) # tmpData['etRad'] = et_rad(tmpData['latRad'], tmpData['solDec'], tmpData['sha'], tmpData['ird']) tmpData['etRad'] = dsData['rsdsMJ'] tmpData['csRad'] = fao.cs_rad(altitude=1.5, et_rad=tmpData['etRad']) dsData['deltaSvp'] = delta_svp(dsData['tas']) # 대기 온도 1.5 m 가정 psy = fao.psy_const(atmos_pres=fao.atm_pressure(altitude=15)) dsData['avp'] = fao.avp_from_rhmin_rhmax( dsData['svpMax'], dsData['svpMin'], dsData['hurs'].min(), dsData['hurs'].max()) niSwRad = pyeto.net_in_sol_rad(dsData['rsdsMJ'], albedo=0.23) niLwRad = net_out_lw_rad(dsData['tasminKel'], dsData['tasmaxKel'], dsData['rsdsMJ'], tmpData['csRad'], dsData['avp']) dsData['net_rad'] = fao.net_rad(ni_sw_rad=niSwRad, no_lw_rad=niLwRad) # 2022.08.13 # 상수 # shfData = 0.336 # 이전, 현재 대기온도를 통해 계산 timeList = dsData['time'].values shfDataL1 = xr.Dataset() for i, timeInfo in enumerate(timeList): prevYmd = (pd.to_datetime(timeInfo) + pd.DateOffset(months=-1)).strftime('%Y-%m-%d') nowYmd = pd.to_datetime(timeInfo).strftime('%Y-%m-%d') prevData = dsData['tas'].interp( time=prevYmd, method='nearest', kwargs={'fill_value': 'extrapolate'}) nowData = dsData['tas'].interp( time=nowYmd, method='nearest', kwargs={'fill_value': 'extrapolate'}) shfData = pyeto.monthly_soil_heat_flux2( prevData, nowData).rename('shf') shfData['time'] = pd.to_datetime(timeInfo) if (i == 0): shfDataL1 = shfData else: shfDataL1 = xr.concat([shfDataL1, shfData], dim='time') dsData = xr.merge([dsData, shfDataL1]) # Daily eto # faoRes = fao.fao56_penman_monteith(dsData['net_rad'], dsData['tasKel'], dsData['sfcWind'], dsData['svp'], dsData['avp'], dsData['deltaSvp'], psy, shf = 0) # Monthly eto faoRes = fao.fao56_penman_monteith(dsData['net_rad'], dsData['tasKel'], dsData['sfcWind'], dsData['svp'], dsData['avp'], dsData['deltaSvp'], psy, shf=dsData['shf']) # ******************************************************************************************** # Hargreaves 방법 # ******************************************************************************************** # https://xclim.readthedocs.io/en/stable/indicators_api.html 매뉴얼 참조 # harRes = xclim.indices.potential_evapotranspiration( dsData['tasmin'], dsData['tasmax'], dsData['tas'], dsData['lat'], method='hargreaves85') # 1 kg/m2/s = 86400 mm/day를 기준으로 mm/month 변환 # harResL1 = harRes * 86400.0 * tmpData['timeEndMonth'] # https://pyeto.readthedocs.io/en/latest/thornthwaite.html 매뉴얼 참조 harRes = pyeto.hargreaves(dsData['tasmin'], dsData['tasmax'], dsData['tas'], tmpData['etRad']) harResL1 = harRes # ******************************************************************************************** # Thornthwaite 방법 # ******************************************************************************************** # https://xclim.readthedocs.io/en/stable/indicators_api.html 매뉴얼 참조 # thwRes = xclim.indices.potential_evapotranspiration(dsData['tasmin'], dsData['tasmax'], dsData['tas'], dsData['lat'], method ='thornthwaite48') # 1 kg/m2/s = 86400 mm/day를 기준으로 mm/month 변환 # thwResL1 = thwRes * 86400.0 * tmpData['timeEndMonth'] dsData['tasAdj'] = xr.where((dsData['tas'] >= 0), dsData['tas'], 0) dsData['heatIdx'] = (dsData['tasAdj'] / 5.0)**1.514 sumHeatIdx = dsData['heatIdx'].groupby('time.year').sum( skipna=True) sumHeatIdxData = xr.Dataset() timeList = dsData['time'].values for i, timeInfo in enumerate(timeList): iYear = int(pd.to_datetime(timeInfo).strftime('%Y')) selHeatIdx = sumHeatIdx.sel(year=iYear).rename( {'year': 'time'}) selHeatIdx['time'] = timeInfo if (i == 0): sumHeatIdxData = selHeatIdx else: sumHeatIdxData = xr.concat( [sumHeatIdxData, selHeatIdx], dim='time') # 2022.08.15 # dsData['thwConst'] = (6.75e-07 * dsData['heatIdx'] ** 3) - (7.71e-05 * dsData['heatIdx'] ** 2) + (1.792e-02 * dsData['heatIdx']) + 0.49239 # thwRes = 1.6 * (tmpData['dayLightHour'] / 12.0) * (tmpData['timeEndMonth'] / 30.0) * ((10.0 * dsData['tasAdj'] / dsData['heatIdx']) ** dsData['thwConst']) * 10.0 dsData['thwConst'] = (6.75e-07 * sumHeatIdxData**3) - ( 7.71e-05 * sumHeatIdxData**2) + (1.792e-02 * sumHeatIdxData) + 0.49239 thwRes = 1.6 * (tmpData['dayLightHour'] / 12.0) * (tmpData['timeEndMonth'] / 30.0) * ( (10.0 * dsData['tasAdj'] / sumHeatIdxData) **dsData['thwConst']) * 10.0 # 0보다 작은 경우 0으로 대체 thwRes = xr.where((thwRes >= 0), thwRes, 0) # ******************************************************************************************** # 데이터 병합 # ******************************************************************************************** etoData = xr.Dataset( { 'hargreaves': (('time', 'lat', 'lon'), (harResL1.values).reshape( len(time1D), len(lat1D), len(lon1D))), 'thornthwaite': (('time', 'lat', 'lon'), (thwRes.values).reshape( len(time1D), len(lat1D), len(lon1D))), 'penman-monteith': (('time', 'lat', 'lon'), (faoRes.values).reshape( len(time1D), len(lat1D), len(lon1D))) }, coords={ 'lat': lat1D, 'lon': lon1D, 'time': time1D }) # NetCDF 파일 저장 saveFile = '{}/{}/{}_eto.nc'.format(globalVar['outPath'], serviceName, modelInfo) os.makedirs(os.path.dirname(saveFile), exist_ok=True) etoData.to_netcdf(saveFile) log.info('[CHECK] saveFile : {}'.format(saveFile)) except Exception as e: log.error("Exception : {}".format(e)) raise e finally: log.info('[END] {}'.format("exec"))
def test_deg2rad(self): self.assertEqual(pyeto.deg2rad(0), 0.0) # Test values obtained form online conversion calculator self.assertAlmostEqual(pyeto.deg2rad(-90), -1.5707963268, 10) self.assertAlmostEqual(pyeto.deg2rad(90), 1.5707963268, 10) self.assertAlmostEqual(pyeto.deg2rad(360), 6.2831853072, 10)
def test_monthly_mean_daylight_hours(self): # Test against values for latitude 20 deg N from Bautista et al (2009) # Calibration of the equations of Hargreaves and Thornthwaite to # estimate the potential evapotranspiration in semi-arid and subhumid # tropical climates for regional applications. Atmosfera 22(4), 331- # 348. test_mmdlh = [ 10.9, # Jan 11.3, # Feb 11.9, # Mar 12.5, # Apr 12.9, # May 13.2, # Jun 13.1, # Jul 12.7, # Aug 12.1, # Sep 11.5, # Oct 11.0, # Nov 10.8, # Dec ] mmdlh = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(20.0)) # Values were only quoted to 1 decimal place so check they are accurate # to within 12 minutes (0.2 hours) for m in range(12): self.assertAlmostEqual(mmdlh[m], test_mmdlh[m], delta=0.15) # Test against values for latitude 46 deg N from Mimikou M. and # Baltas E., Technical hydrology, Second edition, NTUA, 2002. # cited in PAPADOPOULOU E., VARANOU E., BALTAS E., DASSAKLIS A., and # MIMIKOU M. (2003) ESTIMATING POTENTIAL EVAPOTRANSPIRATION AND ITS # SPATIAL DISTRIBUTION IN GREECE USING EMPIRICAL METHODS. test_mmdlh = [ 8.9, # Jan 10.1, # Feb 11.6, # Mar 13.3, # Apr 14.7, # May 15.5, # Jun 15.2, # Jul 13.9, # Aug 12.3, # Sep 10.7, # Oct 9.2, # Nov 8.5, # Dec ] mmdlh = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(46.0)) # Values were only quoted to 1 decimal place so check they are accurate # to within 12 minutes (0.2 hours) for m in range(12): self.assertAlmostEqual(mmdlh[m], test_mmdlh[m], delta=0.15) # Test against values obtained for Los Angles, California, # latitude 34 deg 05' N, from # http://aa.usno.navy.mil/data/docs/Dur_OneYear.php latitude = pyeto.deg2rad(34.0833333) la_mmdlh = [ 10.182, # Jan 10.973, # Feb 11.985, # Mar 13.046, # Apr 13.940, # May 14.388, # Jun 14.163, # Jul 13.404, # Aug 12.374, # Sep 11.320, # Oct 10.401, # Nov 9.928, # Dec ] mmdlh = pyeto.monthly_mean_daylight_hours(latitude) # Check that the 2 methods are almost the same (within 15 minutes) for m in range(12): self.assertAlmostEqual(mmdlh[m], la_mmdlh[m], delta=0.25) # Test with year set to a non-leap year non_leap = pyeto.monthly_mean_daylight_hours(latitude, 2015) for m in range(12): self.assertEqual(mmdlh[m], non_leap[m]) # Test with year set to a leap year leap = pyeto.monthly_mean_daylight_hours(latitude, 2016) for m in range(12): if m == 0: self.assertEqual(leap[m], non_leap[m]) elif m == 1: # Feb # Because Feb extends further into year in a leap year it # should have a slightly longer mean day length in northern # hemisphere self.assertGreater(leap[m], non_leap[m]) else: # All months after Feb in a lieap year will be composed of # diffent Julian days (days of the year) compared to a # non-leap year so will have different mean daylengths. self.assertNotEqual(leap[m], non_leap[m]) # Test with bad latitude with self.assertRaises(ValueError): _ = pyeto.monthly_mean_daylight_hours( pyeto.deg2rad(90.01)) with self.assertRaises(ValueError): _ = pyeto.monthly_mean_daylight_hours( pyeto.deg2rad(-90.01)) # Test limits of latitude _ = pyeto.monthly_mean_daylight_hours( pyeto.deg2rad(90.0)) _ = pyeto.monthly_mean_daylight_hours( pyeto.deg2rad(-90.0))
def test_monthly_mean_daylight_hours(self): # Test against values for latitude 20 deg N from Bautista et al (2009) # Calibration of the equations of Hargreaves and Thornthwaite to # estimate the potential evapotranspiration in semi-arid and subhumid # tropical climates for regional applications. Atmosfera 22(4), 331- # 348. test_mmdlh = [ 10.9, # Jan 11.3, # Feb 11.9, # Mar 12.5, # Apr 12.9, # May 13.2, # Jun 13.1, # Jul 12.7, # Aug 12.1, # Sep 11.5, # Oct 11.0, # Nov 10.8, # Dec ] mmdlh = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(20.0)) # Values were only quoted to 1 decimal place so check they are accurate # to within 12 minutes (0.2 hours) for m in range(12): self.assertAlmostEqual(mmdlh[m], test_mmdlh[m], delta=0.15) # Test against values for latitude 46 deg N from Mimikou M. and # Baltas E., Technical hydrology, Second edition, NTUA, 2002. # cited in PAPADOPOULOU E., VARANOU E., BALTAS E., DASSAKLIS A., and # MIMIKOU M. (2003) ESTIMATING POTENTIAL EVAPOTRANSPIRATION AND ITS # SPATIAL DISTRIBUTION IN GREECE USING EMPIRICAL METHODS. test_mmdlh = [ 8.9, # Jan 10.1, # Feb 11.6, # Mar 13.3, # Apr 14.7, # May 15.5, # Jun 15.2, # Jul 13.9, # Aug 12.3, # Sep 10.7, # Oct 9.2, # Nov 8.5, # Dec ] mmdlh = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(46.0)) # Values were only quoted to 1 decimal place so check they are accurate # to within 12 minutes (0.2 hours) for m in range(12): self.assertAlmostEqual(mmdlh[m], test_mmdlh[m], delta=0.15) # Test against values obtained for Los Angles, California, # latitude 34 deg 05' N, from # http://aa.usno.navy.mil/data/docs/Dur_OneYear.php latitude = pyeto.deg2rad(34.0833333) la_mmdlh = [ 10.182, # Jan 10.973, # Feb 11.985, # Mar 13.046, # Apr 13.940, # May 14.388, # Jun 14.163, # Jul 13.404, # Aug 12.374, # Sep 11.320, # Oct 10.401, # Nov 9.928, # Dec ] mmdlh = pyeto.monthly_mean_daylight_hours(latitude) # Check that the 2 methods are almost the same (within 15 minutes) for m in range(12): self.assertAlmostEqual(mmdlh[m], la_mmdlh[m], delta=0.25) # Test with year set to a non-leap year non_leap = pyeto.monthly_mean_daylight_hours(latitude, 2015) for m in range(12): self.assertEqual(mmdlh[m], non_leap[m]) # Test with year set to a leap year leap = pyeto.monthly_mean_daylight_hours(latitude, 2016) for m in range(12): if m == 0: self.assertEqual(leap[m], non_leap[m]) elif m == 1: # Feb # Because Feb extends further into year in a leap year it # should have a slightly longer mean day length in northern # hemisphere self.assertGreater(leap[m], non_leap[m]) else: # All months after Feb in a lieap year will be composed of # diffent Julian days (days of the year) compared to a # non-leap year so will have different mean daylengths. self.assertNotEqual(leap[m], non_leap[m]) # Test with bad latitude with self.assertRaises(ValueError): _ = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(90.01)) with self.assertRaises(ValueError): _ = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(-90.01)) # Test limits of latitude _ = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(90.0)) _ = pyeto.monthly_mean_daylight_hours(pyeto.deg2rad(-90.0))
def get_data_from_WU(): ###array to store the reports wu_weather_reports = [] ## today and last 6 days definition day1 = now - datetime.timedelta(days=6) day2 = now - datetime.timedelta(days=5) day3 = now - datetime.timedelta(days=4) day4 = now - datetime.timedelta(days=3) day5 = now - datetime.timedelta(days=2) day6 = now - datetime.timedelta(days=1) day7 = now #### convert dates to WU required format days = { 'day1': day1.strftime('%Y%m%d'), 'day2': day2.strftime('%Y%m%d'), 'day3': day3.strftime('%Y%m%d'), 'day4': day4.strftime('%Y%m%d'), 'day5': day5.strftime('%Y%m%d'), 'day6': day6.strftime('%Y%m%d'), 'day7': day7.strftime('%Y%m%d') } ### make API wather hisotry call for each day for day in days: url = 'http://api.wunderground.com/api/7c2ab99a0ccee978/history_{0}/q/95316.json'.format(days[day]) headers = {'content-type': 'application/JSON; charset=utf8'} response = requests.get(url, headers=headers) data = json.loads(response.text) #ETo calculation for the day using FAO-56 Penman-Monteith method lat = pyeto.deg2rad(37.585652) altitude = 38 julian_day = datetime.datetime.strptime(days.get(day), '%Y%m%d').timetuple().tm_yday sol_dec = pyeto.sol_dec(julian_day) sha = pyeto.sunset_hour_angle(lat, sol_dec) ird = pyeto.inv_rel_dist_earth_sun(julian_day) ### net radiation calculator net_rad = pyeto.et_rad(lat, sol_dec, sha, ird) temp_c = float(data["history"]["observations"][1]["tempm"]) temp_k = float(data["history"]["observations"][1]["tempi"]) humidity = float(data["history"]["observations"][1]["hum"]) dew_point = float(data["history"]["observations"][1]["dewptm"]) ws = float(data["history"]["observations"][1]["wspdm"]) #actual and saturated vapour pressure in kPH svp = pyeto.svp_from_t(temp_c) avp = pyeto.avp_from_tdew(dew_point) delta_svp = pyeto.delta_svp(temp_c) atm_pressure = pyeto.atm_pressure(altitude) psy = pyeto.psy_const(atm_pressure) #### the ETo plugin retun results in mm, it was converted to inched ETo_in_mm = pyeto.fao56_penman_monteith(net_rad, temp_k, ws, svp, avp, delta_svp, psy, shf=0.0) ETo = ETo_in_mm * 0.039370 ## insert eto value to day weather report data["history"]["observations"][1].update({"ETo": "{0:.2f}".format(ETo)}) ###add report to report collector array wu_weather_reports.append(data["history"]["observations"][1]) #return all reports return wu_weather_reports
def pet(event, context): latitude = event['latitude'] print("Latitude: " + str(latitude)) longitude = event['longitude'] print("Longitude: " + str(longitude)) if latitude is None or longitude is None: print("Unknown lat/lng") return {} if latitude == 0 and longitude == 0: print("Zeroed lat/lng") return {} lat = pyeto.deg2rad(latitude) # convert lat to radians #pass google maps api info mapKey = os.environ['GOOGLE_MAPS_API_KEY'] #pass lat/long and API key variables GOOGLE_MAPS_API = 'https://maps.googleapis.com/maps/api/elevation/json?locations=' + str( latitude) + ',' + str(longitude) + '&key=' + str(mapKey) # Test: curl 'https://maps.googleapis.com/maps/api/elevation/json?locations=29.405708,-82.140176&key=' req = requests.get(GOOGLE_MAPS_API) res = req.json() if res['status'] == 'REQUEST_DENIED': print(f"Error: Google Maps API request denied. {res['error_message']}") return {} results = res["results"] if len(results) == 0: print( f"Error: Google Maps API request returned no results. Status: {res['status']}, Error: {res['error_message']}" ) return {} #print(results) #ELEVATION / ALTITUDE DATA alt = results[0]['elevation'] deviceName = event['deviceName'] print("deviceName: " + str(deviceName)) #set table parameters for sensor data dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['READINGS_TABLE_NAME']) # time parameters current_time = datetime.datetime.now(datetime.timezone.utc) unix_timestamp = current_time.timestamp() # remove decimal when passing in unix timestamp currentTime = int(unix_timestamp) #1440 minutes in a day * 60 seconds #format timestamp to remove float... dayPast = int(unix_timestamp - (1440 * 60)) # let's sample air temperature now tempSample = table.query( ReturnConsumedCapacity='TOTAL', ProjectionExpression="weatherData.temperature", KeyConditionExpression=Key('deviceName').eq(deviceName) & Key('epoch').between(dayPast, currentTime)) tempList = [conversion.obj_to_json(i) for i in tempSample[u'Items']] #print(tempList) day1Temp = [ast.literal_eval(tempList[i]) for i in range(len(tempList))] #print(day1Temp) day1TempFormat = [] for dic in day1Temp: for val in dic.values(): #print(val['temperature']) day1TempFormat.append(val['temperature']) print(day1TempFormat) # calculate temperature avg, min, max for last 24 hrs # convert to Celcius because default from DarkSky is F tempListLength = len(day1TempFormat) print("Temp List Length: " + str(tempListLength)) day1TempAvg = 0 day1TempMin = 0 day1TempMax = 0 if tempListLength != 0: day1TempAvg = round(sum(day1TempFormat) / tempListLength, 2) day1TempAvg = round((day1TempAvg - 32) * (5 / 9), 2) day1TempMin = min(day1TempFormat) day1TempMin = round((day1TempMin - 32) * (5 / 9), 2) day1TempMax = max(day1TempFormat) day1TempMax = round((day1TempMax - 32) * (5 / 9), 2) print("Temp Avg (C): " + str(day1TempAvg)) print("Temp Min (C): " + str(day1TempMin)) print("Temp Max (C): " + str(day1TempMax)) # calculate dew point average dewSample = table.query( ReturnConsumedCapacity='TOTAL', ProjectionExpression="weatherData.dewPoint", KeyConditionExpression=Key('deviceName').eq(deviceName) & Key('epoch').between(dayPast, currentTime)) dewList = [conversion.obj_to_json(i) for i in dewSample[u'Items']] day1Dew = [ast.literal_eval(dewList[i]) for i in range(len(dewList))] day1DewFormat = [] for dic in day1Dew: for val in dic.values(): day1DewFormat.append(val['dewPoint']) #print(day1DewFormat) dewListLength = len(day1DewFormat) print("Dew List Length: " + str(dewListLength)) day1DewAvg = 0 if dewListLength != 0: day1DewAvg = round(sum(day1DewFormat) / dewListLength, 2) # convert F to C (F-32) x 5/9 #AVERAGE ACTUAL DAILY VAPOUR PRESSURE day1DewAvg = round((day1DewAvg - 32) * (5 / 9), 2) print("Dew Point Avg (C): " + str(day1DewAvg)) # dew point is temp at which concentration of water vapour in air at concentration, convert to C down below because DarkSky is F # now calculate wind speed windSample = table.query( ReturnConsumedCapacity='TOTAL', ProjectionExpression="weatherData.windSpeed", KeyConditionExpression=Key('deviceName').eq(deviceName) & Key('epoch').between(dayPast, currentTime)) windList = [conversion.obj_to_json(i) for i in windSample[u'Items']] day1Wind = [ast.literal_eval(windList[i]) for i in range(len(windList))] day1WindFormat = [] for dic in day1Wind: for val in dic.values(): day1WindFormat.append(val['windSpeed']) windListLength = len(day1WindFormat) #print(windListLength) if windListLength <= 0: windListLength = 1 day1windSpeed = round(sum(day1WindFormat) / windListLength, 2) print("Wind Speed (knots): " + str(day1windSpeed)) #HUMIDITY # pull in dewpoint temperature data from DarkSky vaporPressure = fao.avp_from_tdew(day1DewAvg) #SATURATION VAPOUR --> estimated from air temperature satVapor = fao.svp_from_t(day1TempAvg) #SLOPE OF SATURATION VAPOR CURVE satVaporSlope = fao.delta_svp(day1TempAvg) #ATMOSPHERIC PRESSURE atmosphericPressure = fao.atm_pressure(alt) #PSYCHOMETRIC CONSTANT - Eq 8 Allen, 1998 psychroConstant = fao.psy_const(atmosphericPressure) #RADIATION #day of year day_of_year = time.localtime().tm_yday #DAILY NET RADIATION #SOLAR DECLINATION - FAO equation 24 sol_declination = fao.sol_dec(day_of_year) # SUNSET HOUR ANGLE sunsetHourAngle = fao.sunset_hour_angle(lat, sol_declination) #calculate daylight hours daylightHours = fao.daylight_hours(sunsetHourAngle) #inverse rel distance - sun-earth earthSunDist = fao.inv_rel_dist_earth_sun(day_of_year) # ESTIMATED DAILY EXTRATERRESTRIAL RADIATION (top of atmosphere) # Eq 21 (Allen et al 1998) #def et_rad(latitude, sol_dec, sha, ird): extraTerRad = fao.et_rad(lat, sol_declination, sunsetHourAngle, earthSunDist) #ESTIMATED CLEAR SKY RADIATION # Eq 37 Allen et al 1998) clearSkyRad = fao.cs_rad(alt, extraTerRad) #daily min and max temperatures expressed as degrees C grossRadiation = fao.sol_rad_from_t(extraTerRad, clearSkyRad, day1TempMin, day1TempMax, coastal=False) #NET INCOMING SOLAR (shortwave rad) --> FAO equation 38 #albedo is of crop as proporiton of gross incoming solar radiation reflected by surgace --> 0.23 default set by FAO for grass crop #incomingRadiation = net_in_sol_rad(sol_rad, albedo=0.23) netIncomingRad = fao.net_in_sol_rad(grossRadiation, albedo=0.23) #NET OUTGOING LONGWAVE ENERGY leaving earth's surface (Eq 39 in Allen et al 1998) # def net_out_lw_rad(tmin, tmax, sol_rad, cs_rad, avp) netOutgoingRad = fao.net_out_lw_rad(day1TempMin, day1TempMax, grossRadiation, clearSkyRad, vaporPressure) #DAILY NET RADIATION AT CROP SURCACE (assuming grass ref crop) #Eq 40 in Allen et al (1998) dailyNetRadiation = fao.net_rad(netIncomingRad, netOutgoingRad) #convert air temp from C to degrees Kelvin day1TempAvg = day1TempAvg + 273.15 #FAO-56 ENMAN-MONTIETCH EQUATION to estimate reference evapotranspiration (ETo) from short grass reference surface # Eq 6 in Allen et al 1998 #def fao56_penman_monteith(net_rad, t, ws, svp, avp, delta_svp, psy, shf=0.0): penmanMontOutput = round( fao.fao56_penman_monteith(dailyNetRadiation, day1TempAvg, day1windSpeed, satVapor, vaporPressure, satVaporSlope, psychroConstant, shf=0.0), 2) print("Reference ETo [mm/day]: " + str(penmanMontOutput)) # convert from mm/day to in/day pET = round((penmanMontOutput * 0.0393701), 4) if pET <= 0: pET = 0 # now multiply by crop coefficients to find ETc (crop evapotranspiration) ret = {"ETo": pET} try: ETc = None # Default value if missing or error cc = cropET.calculateCropCoef(deviceName) if cc is not None: Kc = cc["KcMAIN"] cropName = cc["cropName"] if Kc is not None: ETc = round((pET * Kc), 4) ret.update({"ETc": ETc, "crop": cropName}) except: traceback.print_exc() return ret
# this data should be from nws. import pyeto latitude_deg = 38.01 latitude = pyeto.deg2rad(latitude_deg) day_of_year = 206 tmin = 37 tmax = 53 coastal = True altitude = 147 rh_min = 13 rh_max = 88 ws = 1.3 tmean = pyeto.daily_mean_t(tmin, tmax) atmos_pres = pyeto.atm_pressure(altitude) psy = pyeto.psy_const(atmos_pres) # Humidity svp_tmin = pyeto.svp_from_t(tmin) svp_tmax = pyeto.svp_from_t(tmax) delta_svp = pyeto.delta_svp(tmean) svp = pyeto.mean_svp(tmin, tmax) avp = pyeto.avp_from_rhmin_rhmax(svp_tmin, svp_tmax, rh_min, rh_max) # Radiation sol_dec = pyeto.sol_dec(day_of_year) sha = pyeto.sunset_hour_angle(latitude, sol_dec) ird = pyeto.inv_rel_dist_earth_sun(day_of_year) et_rad = pyeto.et_rad(latitude, sol_dec, sha, ird) cs_rad = pyeto.cs_rad(altitude, et_rad)
def exec(self): log.info('[START] {}'.format("exec")) try: if (platform.system() == 'Windows'): # 옵션 설정 sysOpt = { # 시작/종료 시간 'srtDate': '2020-09-01', 'endDate': '2020-09-03' # 경도 최소/최대/간격 , 'lonMin': 0, 'lonMax': 360, 'lonInv': 0.5 # 위도 최소/최대/간격 , 'latMin': -90, 'latMax': 90, 'latInv': 0.5 } else: # 옵션 설정 sysOpt = { # 시작/종료 시간 # 'srtDate': globalVar['srtDate'] # , 'endDate': globalVar['endDate'] } # globalVar['outPath'] = 'F:/Global Temp/aski' modelList = ['MRI-ESM2-0'] for i, modelInfo in enumerate(modelList): log.info("[CHECK] modelInfo : {}".format(modelInfo)) inpFile = '{}/{}/{} ssp585 2015-2100_*.nc'.format( globalVar['inpPath'], serviceName, modelInfo) fileList = sorted(glob.glob(inpFile)) dsData = xr.open_mfdataset(fileList) # 월별 시간 변환 dsData['time'] = pd.to_datetime(pd.to_datetime( dsData['time'].values).strftime("%Y-%m"), format='%Y-%m') # 단위 설정 dsData['tasmin'].attrs['units'] = 'degC' dsData['tasmax'].attrs['units'] = 'degC' dsData['tas'].attrs['units'] = 'degC' # 단위 환산을 위한 매월 마지막 날 계산 lon1D = dsData['lon'].values lat1D = dsData['lat'].values time1D = dsData['time'].values timeEndMonth = [] timeYear = dsData['time.year'].values timeMonth = dsData['time.month'].values for i in range(0, len(timeYear)): timeEndMonth.append( calendar.monthrange(timeYear[i], timeMonth[i])[1]) latRad1D = pyeto.deg2rad(dsData['lat']) dayOfYear1D = dsData['time.dayofyear'] latRad3D = np.tile( np.transpose(np.tile(latRad1D, (len(lon1D), 1))), (len(time1D), 1, 1)) dayOfYear3D = np.transpose( np.tile(dayOfYear1D, (len(lon1D), len(lat1D), 1))) timeEndMonth3D = np.transpose( np.tile(timeEndMonth, (len(lon1D), len(lat1D), 1))) tmpData = xr.Dataset( { 'timeEndMonth': (('time', 'lat', 'lon'), (timeEndMonth3D).reshape( len(time1D), len(lat1D), len(lon1D))), 'latRad': (('time', 'lat', 'lon'), (latRad3D).reshape( len(time1D), len(lat1D), len(lon1D))), 'dayOfYear': (('time', 'lat', 'lon'), (dayOfYear3D).reshape( len(time1D), len(lat1D), len(lon1D))) }, coords={ 'lat': lat1D, 'lon': lon1D, 'time': time1D }) # ******************************************************************************************** # Hargreaves 방법 # ******************************************************************************************** # https://xclim.readthedocs.io/en/stable/indicators_api.html 매뉴얼 참조 harRes = xclim.indices.potential_evapotranspiration( dsData['tasmin'], dsData['tasmax'], dsData['tas'], dsData['lat'], method='hargreaves85') # 1 kg/m2/s = 86400 mm/day를 기준으로 mm/month 변환 harResL1 = harRes * 86400.0 * tmpData['timeEndMonth'] # ******************************************************************************************** # Thornthwaite 방법 # ******************************************************************************************** # https://xclim.readthedocs.io/en/stable/indicators_api.html 매뉴얼 참조 thwRes = xclim.indices.potential_evapotranspiration( dsData['tasmin'], dsData['tasmax'], dsData['tas'], dsData['lat'], method='thornthwaite48') # 1 kg/m2/s = 86400 mm/day를 기준으로 mm/month 변환 thwResL1 = thwRes * 86400.0 * tmpData['timeEndMonth'] # ******************************************************************************************** # FAO-56 Penman-Monteith 방법 # ******************************************************************************************** # https://pyeto.readthedocs.io/en/latest/fao56_penman_monteith.html 매뉴얼 참조 # 1 W/m2 = 1 J/m2를 기준으로 MJ/day 변환 dsData['rsdsMJ'] = dsData['rsds'] * 86400 / (10**6) # 섭씨 to 켈빈 dsData['tasKel'] = dsData['tas'] + 273.15 dsData['tasminKel'] = dsData['tasmin'] + 273.15 dsData['tasmaxKel'] = dsData['tasmax'] + 273.15 dsData['svp'] = svp_from_t(dsData['tas']) dsData['svpMax'] = svp_from_t(dsData['tasmax']) dsData['svpMin'] = svp_from_t(dsData['tasmin']) tmpData['solDec'] = sol_dec(tmpData['dayOfYear']) tmpData['sha'] = sunset_hour_angle(tmpData['latRad'], tmpData['solDec']) tmpData['ird'] = inv_rel_dist_earth_sun(tmpData['dayOfYear']) tmpData['etRad'] = et_rad(tmpData['latRad'], tmpData['solDec'], tmpData['sha'], tmpData['ird']) tmpData['csRad'] = fao.cs_rad(altitude=1.5, et_rad=tmpData['etRad']) dsData['deltaSvp'] = delta_svp(dsData['tas']) # 대기 온도 1.5 m 가정 psy = fao.psy_const(atmos_pres=fao.atm_pressure(altitude=15)) dsData['avp'] = fao.avp_from_rhmin_rhmax( dsData['svpMax'], dsData['svpMin'], dsData['hurs'].min(), dsData['hurs'].max()) niSwRad = pyeto.net_in_sol_rad(dsData['rsdsMJ'], albedo=0.23) niLwRad = net_out_lw_rad(dsData['tasminKel'], dsData['tasmaxKel'], dsData['rsdsMJ'], tmpData['csRad'], dsData['avp']) dsData['net_rad'] = fao.net_rad(ni_sw_rad=niSwRad, no_lw_rad=niLwRad) faoRes = fao.fao56_penman_monteith(dsData['net_rad'], dsData['tasKel'], dsData['sfcWind'], dsData['svp'], dsData['avp'], dsData['deltaSvp'], psy, shf=0) # ******************************************************************************************** # 데이터 병합 # ******************************************************************************************** data = xr.Dataset( { 'hargreaves': (('time', 'lat', 'lon'), (harResL1.values).reshape( len(time1D), len(lat1D), len(lon1D))), 'thornthwaite': (('time', 'lat', 'lon'), (thwResL1.values).reshape( len(time1D), len(lat1D), len(lon1D))), 'penman-monteith': (('time', 'lat', 'lon'), (faoRes.values).reshape( len(time1D), len(lat1D), len(lon1D))) }, coords={ 'lat': lat1D, 'lon': lon1D, 'time': time1D }) dataL1 = xr.merge([data, dsData]) # # NetCDF 파일 저장 saveFile = '{}/{}/{}_eto.nc'.format(globalVar['outPath'], serviceName, modelInfo) os.makedirs(os.path.dirname(saveFile), exist_ok=True) dataL1.to_netcdf(saveFile) log.info('[CHECK] saveFile : {}'.format(saveFile)) except Exception as e: log.error("Exception : {}".format(e)) raise e finally: log.info('[END] {}'.format("exec"))
import netCDF4 sys.path.append('/home/pu17449/gitsrc/PyETo') import pyeto inpath = '/home/pu17449/data2/worldclim_precip/' outfile = '/home/pu17449/data2/worldclim_precip/pet_yearmean_v3.nc' #f_tiffout = '/home/pu17449/data2/worldclim_precip/pet_yearmean_v2.tif' # Construct lat and lon arrays (centrepoints) step = 0.25/30. lons = np.arange(-180,180,step)+step/2. lats = np.arange(90,-90,-1*step)-step/2. nlats = len(lats) nlons = len(lons) lats_rad = pyeto.deg2rad(lats) #lat2D = np.repeat(lats_rad[:,np.newaxis],len(lons),axis=1) # Data array to store time/lon slices of PET pet_timeslice = np.zeros([12,nlons],dtype=np.float32) pet = np.zeros([nlons],dtype=np.float32) #yearly mean ############################################################################### # Write output file for modsim: # Follows format of variables needed in 'domain' file for metsim e.g. '/home/bridge/pu17449/src/MetSim/metsim/data/domain.nc' with netCDF4.Dataset(outfile,'w') as f_out: f_out.createDimension('lat',nlats) f_out.createVariable('lat',np.float,('lat')) f_out.variables['lat'].standard_name = "latitude"
VV=pd.read_csv(arch, names=["0"]) arch=esta[i]+"_HR.csv" HR=pd.read_csv(arch, names=["0"]) #Inciacion de los valores de ETo lat=LAT[i] altitude=ALT[i] tmin=[] tmax=[] t=[] rh_mean=[] ws=[] lat=pyeto.deg2rad(lat) day=1 sunshine_hours=[] ETO=[] #Completar los valores de ETo for j in range(0,len(Tmean["0"])): tmin=(Tmin["0"][j]) tmink=pyeto.celsius2kelvin(tmin) tmax=(Tmax["0"][j]) tmaxk=pyeto.celsius2kelvin(tmax) t=(Tmean["0"][j]) tk=pyeto.celsius2kelvin(t) rh_mean=(HR["0"][j]) ws=(VV["0"][j])