def calc_ET(self, data, data_type): """Get maximum and minimum temperatures and average radiation and wind speed for the indicated period then calculate the amount of evapotranspiration during the interval. Convert to US units if necessary since this service operates in US unit system.""" # calculate ET only for archive packets if data_type != 'archive': return end_ts = data['dateTime'] start_ts = end_ts - self.et_period interval = self._get_archive_interval(data) try: dbmanager = self.db_binder.get_manager(self.binding) r = dbmanager.getSql( "SELECT" " MAX(outTemp), MIN(outTemp), AVG(radiation), AVG(windSpeed)," " MAX(outHumidity), MIN(outHumidity), MAX(usUnits), MIN(usUnits)" " FROM %s WHERE dateTime>? AND dateTime <=?" % dbmanager.table_name, (start_ts, end_ts)) # Make sure everything is there: if r is None or None in r: data['ET'] = None return # Unpack the results T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r # Check for mixed units if std_unit_min != std_unit_max: syslog.syslog( syslog.LOG_NOTICE, "wxservices: Mixed unit system not allowed in ET calculation" ) data['ET'] = None return std_unit = std_unit_min if std_unit == weewx.METRIC or std_unit == weewx.METRICWX: T_max = CtoF(T_max) T_min = CtoF(T_min) if std_unit == weewx.METRICWX: wind_avg = mps_to_mph(wind_avg) else: wind_avg = kph_to_mph(wind_avg) # Wind height is in meters, so convert it: height_ft = self.wind_height / METER_PER_FOOT ET_rate = weewx.wxformulas.evapotranspiration_US( T_min, T_max, rh_min, rh_max, rad_avg, wind_avg, height_ft, self.latitude, self.longitude, self.altitude_ft, end_ts) # The formula returns inches/hour. We need the total ET over the # archive interval, so multiply by the length of the archive # interval in hours. data[ 'ET'] = ET_rate * interval / 3600.0 if ET_rate is not None else None except ValueError as e: weeutil.weeutil.log_traceback() syslog.syslog( syslog.LOG_ERR, "wxservices: Calculation of evapotranspiration failed: %s" % e) except weedb.DatabaseError: pass
def calc_ET(self, data, data_type): """Get maximum and minimum temperatures and average radiation and wind speed for the indicated period then calculate the amount of evapotranspiration during the interval. Convert to US units if necessary since this service operates in US unit system.""" # calculate ET only for archive packets if data_type != 'archive': return end_ts = data['dateTime'] start_ts = end_ts - self.et_period interval = self._get_archive_interval(data) try: dbmanager = self.db_binder.get_manager(self.binding) r = dbmanager.getSql( "SELECT" " MAX(outTemp), MIN(outTemp), AVG(radiation), AVG(windSpeed)," " MAX(outHumidity), MIN(outHumidity), usUnits" " FROM %s WHERE dateTime>? AND dateTime <=?" % dbmanager.table_name, (start_ts, end_ts)) if r is None: data['ET'] = None return # Unpack the results T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit = r # Check for null values. Null relative humidity is OK. if T_max is None or T_min is None or rad_avg is None or wind_avg is None or std_unit is None: data['ET'] = None return if std_unit == weewx.METRIC or std_unit == weewx.METRICWX: T_max = CtoF(T_max) T_min = CtoF(T_min) if std_unit == weewx.METRICWX: wind_avg = mps_to_mph(wind_avg) else: wind_avg = kph_to_mph(wind_avg) # Rate will be in inches per day ET_rate = weewx.wxformulas.evapotranspiration_US( T_max, T_min, rad_avg, wind_avg, self.wind_height, self.latitude, data['dateTime'], rh_min, rh_max) # Multiply the ET rate by the length of the interval in days. # This will give the total amount of ET during the archive interval. data['ET'] = ET_rate * interval / ( 24 * 3600.0) if ET_rate is not None else None except ValueError, e: weeutil.weeutil.log_traceback() syslog.syslog( syslog.LOG_ERR, "wxservices: Calculation of evapotranspiration failed: %s" % e)
def thw_Metric(t_C, RH, ws_kph): """ Uses the air temperature, relative humidity, and wind speed (THW = temperature-humidity-wind) to calculate a potentially more accurate "felt-air temperature." This is not as accurate, however, as the THSW index, which can only be calculated when solar radiation information is available. It uses `calculate_heat_index` and then applies additional calculations to it using the wind speed. As such, it returns `None` for input temperatures below 70 degrees Fahrenheit. The additional calculations come from web forums rumored to contain the proprietary Davis Instruments THW index formulas. hi is the heat index as calculated by `calculate_heat_index` WS is the wind speed in miles per hour :param temperature: The temperature in degrees Fahrenheit :type temperature: int | long | decimal.Decimal :param relative_humidity: The relative humidity as a percentage (88.2 instead of 0.882) :type relative_humidity: int | long | decimal.Decimal :param wind_speed: The wind speed in miles per hour :type wind_speed: int | long | decimal.Decimal :return: The THW index temperature in degrees Fahrenheit to one decimal place, or `None` if the temperature is less than 70F :rtype: decimal.Decimal """ t_F = CtoF(t_C) hi_F = heatindexF(t_F, RH) WS = kph_to_mph(ws_kph) if not hi_F: return None hi = hi_F - (1.072 * WS) thw_C = FtoC(hi) return round(thw_C, 1) if thw_C is not None else None
def humidexF(t_F, rh): """Calculate the humidex in degree Fahrenheit t_F - temperature in degree Fahrenheit rh - relative humidity [0-100] """ if t_F is None: return None h_C = humidexC(FtoC(t_F), rh) return CtoF(h_C) if h_C is not None else None
def thsw_US(t_F, RH, ws_mph, rahes): if t_F is None or ws_mph is None or RH is None or rahes is None: return None t_C = FtoC(t_F) ws_kph = ws_mph * 1.609344 thsw_C = thsw_Metric(t_C, RH, ws_kph, rahes) thsw_F = CtoF(thsw_C) return round(thsw_F, 1) if thsw_F is not None else None
def sumsimIndex_C(t_C, RH): # Summer Simmer Index-Berechnung # rel. Luftfeuchte RH # temperatur in degree C if t_C is None or RH is None: return None t_F = CtoF(t_C) ssI_F = sumsimIndex_F(t_F, RH) ssI_C = FtoC(ssI_F) return ssI_C if ssI_C is not None else None
def wetbulb_US(t_F, RH, p_inHg): # Wet bulb calculations == Kuehlgrenztemperatur, Feuchtekugeltemperatur # t_F = temperatur degree F # RH = outHumidity # p_inHg = pressure in inHg if t_F is None or RH is None or p_inHg is None: return None t_C = FtoC(t_F) p_mbar = p_inHg / INHG_PER_MBAR wb_C = wetbulb_Metric(t_C, RH, p_mbar) return CtoF(wb_C) if wb_C is not None else None
def deltaT_US(t_F, RH, p_inHg): # deltaT calculations == delta Lufttemperatur # t_F = temperatur degree F # RH = outHumidity # p_inHg = pressure in inHg if t_F is None or RH is None or p_inHg is None: return None t_C = FtoC(t_F) p_mbar = p_inHg / INHG_PER_MBAR deltaT_C = deltaT_Metric(t_C, RH, p_mbar) return CtoF(deltaT_C) if deltaT_C is not None else None
def windchillC(T_C, V_kph): """Wind chill, metric version. T: Temperature in Celsius V: Wind speed in kph Returns wind chill in Celsius""" if T_C is None or V_kph is None: return None T_F = CtoF(T_C) V_mph = 0.621371192 * V_kph WcF = windchillF(T_F, V_mph) return FtoC(WcF) if WcF is not None else None
def windchillMetricWX(T_C, V_mps): """Wind chill, metric version, with wind in mps. T: Temperature in Celsius V: Wind speed in mps Returns wind chill in Celsius""" if T_C is None or V_mps is None: return None T_F = CtoF(T_C) V_mph = 2.237 * V_mps WcF = windchillF(T_F, V_mph) return FtoC(WcF) if WcF is not None else None
def _decodeTemperature(s): # tnnn[C] Indoor Temperature # Tnnn[C] Outdoor Temperature # cTnnn[C] Wind Chill if s[0] == 'c': s = s[1:] isCelsius = (s[-1] == 'C') try: temp = int(s[1:4]) if isCelsius: temp = CtoF(temp) except Exception: logerr("conversion of buffer failed: %s" % s) temp = None return temp
def apptempF(t_F, rh, ws_mph): """Calculate apparent temperature in degree Fahrenheit t_F - temperature in degree Fahrenheit rh - relative humidity [0-100] ws_mph - wind speed in miles per hour """ if t_F is None: return None if rh is None or rh < 0 or rh > 100: return None if ws_mph is None or ws_mph < 0: return None t_C = FtoC(t_F) ws_mps = ws_mph * METER_PER_MILE / 3600.0 at_C = apptempC(t_C, rh, ws_mps) return CtoF(at_C) if at_C is not None else None
def dewpointF(T, R): """Calculate dew point. T: Temperature in Fahrenheit R: Relative humidity in percent. Returns: Dewpoint in Fahrenheit Examples: >>> print "%.1f" % dewpointF(68, 50) 48.7 >>> print "%.1f" % dewpointF(32, 50) 15.5 >>> print "%.1f" % dewpointF(-10, 50) -23.5 """ if T is None or R is None: return None TdC = dewpointC(FtoC(T), R) return CtoF(TdC) if TdC is not None else None
def heatindexC(T_C, R): if T_C is None or R is None: return None T_F = CtoF(T_C) hi_F = heatindexF(T_F, R) return FtoC(hi_F)
def calc_ET(self, key, data, db_manager): """Get maximum and minimum temperatures and average radiation and wind speed for the indicated period then calculate the amount of evapotranspiration during the interval. Convert to US units if necessary since this service operates in US unit system.""" if 'interval' not in data: # This will cause LOOP data not to be processed. raise weewx.CannotCalculate(key) interval = data['interval'] end_ts = data['dateTime'] start_ts = end_ts - self.et_period try: r = db_manager.getSql( "SELECT MAX(outTemp), MIN(outTemp), " "AVG(radiation), AVG(windSpeed), " "MAX(outHumidity), MIN(outHumidity), " "MAX(usUnits), MIN(usUnits) FROM %s WHERE dateTime>? AND dateTime <=?" % db_manager.table_name, (start_ts, end_ts)) except weedb.DatabaseError: return ValueTuple(None, None, None) # Make sure everything is there: if r is None or None in r: return ValueTuple(None, None, None) # Unpack the results T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r # Check for mixed units if std_unit_min != std_unit_max: log.info( "Mixed unit system not allowed in ET calculation. Skipped.") return ValueTuple(None, None, None) std_unit = std_unit_min if std_unit == weewx.METRIC or std_unit == weewx.METRICWX: T_max = CtoF(T_max) T_min = CtoF(T_min) if std_unit == weewx.METRICWX: wind_avg = mps_to_mph(wind_avg) else: wind_avg = kph_to_mph(wind_avg) # Wind height is in meters, so convert it: height_ft = self.wind_height / METER_PER_FOOT # Get altitude in feet altitude_ft = weewx.units.convert(self.altitude_vt, 'foot')[0] try: ET_rate = weewx.wxformulas.evapotranspiration_US( T_min, T_max, rh_min, rh_max, rad_avg, wind_avg, height_ft, self.latitude, self.longitude, altitude_ft, end_ts) except ValueError as e: log.error("Calculation of evapotranspiration failed: %s", e) weeutil.logger.log_traceback(log.error) ET_inch = None else: # The formula returns inches/hour. We need the total ET over the interval, so multiply by the length of the # interval in hours. Remember that 'interval' is actually in minutes. ET_inch = ET_rate * interval / 60.0 if ET_rate is not None else None # Convert back to the unit system of the incoming record: ET = weewx.units.convertStd((ET_inch, 'inch', 'group_rain'), data['usUnits']) return ET
def get_scalar(self, obs_type, data, db_manager, **option_dict): """Calculate ET as a scalar""" if obs_type != 'ET': raise weewx.UnknownType(obs_type) if 'interval' not in data: # This will cause LOOP data not to be processed. raise weewx.CannotCalculate(obs_type) interval = data['interval'] end_ts = data['dateTime'] start_ts = end_ts - self.et_period try: r = db_manager.getSql( "SELECT MAX(outTemp), MIN(outTemp), " "AVG(radiation), AVG(windSpeed), " "MAX(outHumidity), MIN(outHumidity), " "MAX(usUnits), MIN(usUnits) FROM %s " "WHERE dateTime>? AND dateTime <=?" % db_manager.table_name, (start_ts, end_ts)) except weedb.DatabaseError: return ValueTuple(None, None, None) # Make sure everything is there: if r is None or None in r: return ValueTuple(None, None, None) # Unpack the results T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r # Check for mixed units if std_unit_min != std_unit_max: log.info( "Mixed unit system not allowed in ET calculation. Skipped.") return ValueTuple(None, None, None) std_unit = std_unit_min if std_unit == weewx.METRIC or std_unit == weewx.METRICWX: T_max = CtoF(T_max) T_min = CtoF(T_min) if std_unit == weewx.METRICWX: wind_avg = mps_to_mph(wind_avg) else: wind_avg = kph_to_mph(wind_avg) # Wind height is in meters, so convert it: height_ft = self.wind_height / METER_PER_FOOT # Get altitude in feet altitude_ft = weewx.units.convert(self.altitude_vt, 'foot')[0] try: ET_rate = weewx.wxformulas.evapotranspiration_US( T_min, T_max, rh_min, rh_max, rad_avg, wind_avg, height_ft, self.latitude_f, self.longitude_f, altitude_ft, end_ts, self.albedo, self.cn, self.cd) except ValueError as e: log.error("Calculation of evapotranspiration failed: %s", e) weeutil.logger.log_traceback(log.error) ET_inch = None else: # The formula returns inches/hour. We need the total ET over the interval, so multiply # by the length of the interval in hours. Remember that 'interval' is actually in # minutes. ET_inch = ET_rate * interval / 60.0 if ET_rate is not None else None return ValueTuple(ET_inch, 'inch', 'group_rain')
def heatindexC(T_C, R, algorithm='new'): if T_C is None or R is None: return None T_F = CtoF(T_C) hi_F = heatindexF(T_F, R, algorithm) return FtoC(hi_F)