[Xfce4-commits] <xfce4-weather-plugin:master> New value: Apparent temperature (bug #9564).

Harald Judt noreply at xfce.org
Sat Jan 5 12:04:13 CET 2013


Updating branch refs/heads/master
         to 7cd4012fc8b06bf51b0d9c0a93ed576d3dcd63e9 (commit)
       from fefdd9aa5cb81ab57cb74f47dbb0821eb262b24c (commit)

commit 7cd4012fc8b06bf51b0d9c0a93ed576d3dcd63e9
Author: Harald Judt <h.judt at gmx.at>
Date:   Thu Jan 3 15:57:26 2013 +0100

    New value: Apparent temperature (bug #9564).
    
    Apparent temperature, also known as "felt temperature" or "feels like" value
    is a debatable and rather subjective value, as can be deduced from the
    various models available that try to compete for correctness and accuracy.
    
    The different models that are offered by the plugin are collected from
    various sources and/or derived from publicly available specifications,
    the sources are mentioned in the code. Many commercial weather data
    providers use their own proprietary (sometimes patented) models.
    
    * Windchill/Heat index:
      Used in North America, wind chill will be reported for low temperatures
      and heat index for higher ones. At night, heat index will be replaced by
      the Summer Simmer Index.
    
    * Windchill/Humidex:
      The Canadian counterpart, with the wind chill being similar to the
      previous model but with slightly different constraints. Instead of
      the heat index Humidex will be used.
    
    * Steadman:
      This is the model used in Australia, especially adapted for the climate
      of this continent. Maybe in Central Europe too, but then windchill and
      similar values had never gained so much popularity as in the US or Canada,
      so information about its usage is scarce. It can be used for lower and
      higher temperatures, so no extra heat index is required.
    
    * Quayle-Steadman:
      Improvements made to earlier experiments/developments by Steadman in
      1998.
    
    These models are not better or worse than others; Usually it's advised to
    use the model for your country as the formulas have been adapted to account
    for the local climate and resemble what you get presented in the news.
    The main reason for the existence of these models is being able to warn
    about the risk of frostbite and heat strokes. Otherwise, apparent
    temperature is a rather subjective value and both reliability and
    significance are not very high.

 panel-plugin/weather-config.c  |   37 +++++++++++-
 panel-plugin/weather-config.h  |    1 +
 panel-plugin/weather-data.c    |  123 ++++++++++++++++++++++++++++++++++++++++
 panel-plugin/weather-data.h    |    9 +++
 panel-plugin/weather-search.c  |    7 ++
 panel-plugin/weather-summary.c |    5 +-
 panel-plugin/weather.c         |    3 +
 7 files changed, 182 insertions(+), 3 deletions(-)

diff --git a/panel-plugin/weather-config.c b/panel-plugin/weather-config.c
index 489c6a5..8b4b198 100644
--- a/panel-plugin/weather-config.c
+++ b/panel-plugin/weather-config.c
@@ -32,7 +32,7 @@
 #include "weather-scrollbox.h"
 
 #define UPDATE_TIMER_DELAY 7
-#define OPTIONS_N 14
+#define OPTIONS_N 15
 #define BORDER 4
 #define LOC_NAME_MAX_LEN 50
 
@@ -100,6 +100,7 @@ static const labeloption labeloptions[OPTIONS_N] = {
     {N_("Wind direction in degrees (WD)"), WIND_DIRECTION_DEG},
     {N_("Humidity (H)"), HUMIDITY},
     {N_("Dew point (D)"), DEWPOINT},
+    {N_("Apparent temperature (A)"), APPARENT_TEMPERATURE},
     {N_("Low clouds (CL)"), CLOUDS_LOW},
     {N_("Medium clouds (CM)"), CLOUDS_MED},
     {N_("High clouds (CH)"), CLOUDS_HIGH},
@@ -311,6 +312,8 @@ setup_units(xfceweather_dialog *dialog,
     SET_COMBO_VALUE(dialog->combo_unit_windspeed, units->windspeed);
     SET_COMBO_VALUE(dialog->combo_unit_precipitations, units->precipitations);
     SET_COMBO_VALUE(dialog->combo_unit_altitude, units->altitude);
+    SET_COMBO_VALUE(dialog->combo_apparent_temperature,
+                    units->apparent_temperature);
 }
 
 
@@ -624,6 +627,18 @@ combo_unit_temperature_changed(GtkWidget *combo,
 
 
 static void
+combo_apparent_temperature_changed(GtkWidget *combo,
+                                   gpointer user_data)
+{
+    xfceweather_dialog *dialog = (xfceweather_dialog *) user_data;
+    dialog->pd->units->apparent_temperature =
+        gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+    update_scrollbox(dialog->pd, TRUE);
+    update_summary_window(dialog, TRUE);
+}
+
+
+static void
 combo_unit_pressure_changed(GtkWidget *combo,
                             gpointer user_data)
 {
@@ -675,7 +690,7 @@ combo_unit_altitude_changed(GtkWidget *combo,
 static GtkWidget *
 create_units_page(xfceweather_dialog *dialog)
 {
-    GtkWidget *palign, *page, *hbox, *vbox, *label;
+    GtkWidget *palign, *page, *hbox, *vbox, *label, *sep;
     GtkSizeGroup *sg_label;
 
     ADD_PAGE(FALSE);
@@ -740,6 +755,22 @@ create_units_page(xfceweather_dialog *dialog)
                     _("Feet (ft)"));
     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, BORDER);
 
+    /* separator */
+    sep = gtk_hseparator_new();
+    gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, BORDER * 2);
+
+    /* apparent temperature model */
+    hbox = gtk_hbox_new(FALSE, BORDER);
+    ADD_LABEL(_("Apparent te_mperature:"), sg_label);
+    ADD_COMBO(dialog->combo_apparent_temperature);
+    ADD_COMBO_VALUE(dialog->combo_apparent_temperature,
+                    _("Windchill/Heat index"));
+    ADD_COMBO_VALUE(dialog->combo_apparent_temperature,
+                    _("Windchill/Humidex"));
+    ADD_COMBO_VALUE(dialog->combo_apparent_temperature, _("Steadman"));
+    ADD_COMBO_VALUE(dialog->combo_apparent_temperature, _("Quayle-Steadman"));
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, BORDER);
+
     /* initialize widgets with current data */
     if (dialog->pd)
         setup_units(dialog, dialog->pd->units);
@@ -1408,6 +1439,8 @@ setup_notebook_signals(xfceweather_dialog *dialog)
                      G_CALLBACK(combo_unit_precipitations_changed), dialog);
     g_signal_connect(dialog->combo_unit_altitude, "changed",
                      G_CALLBACK(combo_unit_altitude_changed), dialog);
+    g_signal_connect(dialog->combo_apparent_temperature, "changed",
+                     G_CALLBACK(combo_apparent_temperature_changed), dialog);
 
     /* appearance page */
     g_signal_connect(dialog->combo_icon_theme, "changed",
diff --git a/panel-plugin/weather-config.h b/panel-plugin/weather-config.h
index 6dadd85..a1d0d6d 100644
--- a/panel-plugin/weather-config.h
+++ b/panel-plugin/weather-config.h
@@ -47,6 +47,7 @@ typedef struct {
     GtkWidget *combo_unit_windspeed;
     GtkWidget *combo_unit_precipitations;
     GtkWidget *combo_unit_altitude;
+    GtkWidget *combo_apparent_temperature;
 
     /* appearance page */
     GtkWidget *combo_icon_theme;
diff --git a/panel-plugin/weather-data.c b/panel-plugin/weather-data.c
index 26d4446..5984794 100644
--- a/panel-plugin/weather-data.c
+++ b/panel-plugin/weather-data.c
@@ -165,6 +165,121 @@ calc_dewpoint(const xml_location *loc)
 }
 
 
+/* Calculate felt air temperature, using the chosen model. */
+static gdouble
+calc_apparent_temperature(const xml_location *loc,
+                          const apparent_temp_models model,
+                          const gboolean night_time)
+{
+    gdouble temp = string_to_double(loc->temperature_value, 0);
+    gdouble windspeed = string_to_double(loc->wind_speed_mps, 0);
+    gdouble humidity = string_to_double(loc->humidity_value, 0);
+    gdouble dp, e;
+
+    switch (model) {
+    case WINDCHILL_HEATINDEX:
+        /* If temperature is lower than 10 °C, use wind chill index,
+           if above 26.7°C use the heat index / Summer Simmer Index. */
+
+        /* wind chill is only defined for wind speeds above 3.0 mph */
+        windspeed *= 3.6;
+        if (windspeed < 4.828032)
+            return temp;
+
+        /* Wind chill, source:
+           http://www.nws.noaa.gov/os/windchill/index.shtml */
+        if (temp <= 10.0)
+            return 13.12 + 0.6215 * temp - 11.37 * pow(windspeed, 0.16)
+                + 0.3965 * temp * pow(windspeed, 0.16);
+
+        if (temp >= 26.7 || (night_time && temp >= 22.0)) {
+            /* humidity needs to be higher than 40% for a valid result */
+            if (humidity < 40)
+                return temp;
+
+            temp = temp * 9.0 / 5.0 + 32.0;  /* both models use Fahrenheit */
+            if (!night_time)
+                /* Heat index, source:
+                   Lans P. Rothfusz. "The Heat Index 'Equation' (or, More
+                   Than You Ever Wanted to Know About Heat Index)",
+                   Scientific Services Division (NWS Southern Region
+                   Headquarters), 1 July 1990.
+                   http://www.srh.noaa.gov/images/ffc/pdf/ta_htindx.PDF
+                */
+                return ((-42.379
+                         + 2.04901523 * temp
+                         + 10.14333127 * humidity
+                         - 0.22475541 * temp * humidity
+                         - 0.00683783 * temp * temp
+                         - 0.05481717 * humidity * humidity
+                         + 0.00122874 * temp * temp * humidity
+                         + 0.00085282 * temp * humidity * humidity
+                         - 0.00000199 * temp * temp * humidity * humidity)
+                        - 32.0) * 5.0 / 9.0;   /* convert back to Celsius */
+            else
+                /* Summer Simmer Index, sources:
+                   http://www.summersimmer.com/home.htm
+                   http://www.gorhamschaffler.com/humidity_formulas.htm */
+                return ((1.98 * (temp - (0.55 - 0.0055 * humidity)
+                                 * (temp - 58)) - 56.83)
+                        - 32.0) * 5.0 / 9.0;   /* convert back to Celsius */
+        }
+
+        /* otherwise simply return the temperature */
+        return temp;
+
+    case WINDCHILL_HUMIDEX:
+        /* If temperature is equal or lower than 0 °C, use wind chill index,
+           if above 20.0 °C use humidex. Source:
+           http://www.weatheroffice.gc.ca/mainmenu/faq_e.html */
+
+        /* wind chill is only defined for wind speeds above 2.0 km/h */
+        windspeed *= 3.6;
+        if (windspeed < 2.0)
+            return temp;
+
+        if (temp <= 0)
+            /* wind chill, source:
+               http://www.nws.noaa.gov/os/windchill/index.shtml */
+            return 13.12 + 0.6215 * temp - 11.37 * pow(windspeed, 0.16)
+                + 0.3965 * temp * pow(windspeed, 0.16);
+
+        if (temp >= 20.0) {
+            /* Canadian humidex, source:
+               http://www.weatheroffice.gc.ca/mainmenu/faq_e.html#weather6 */
+            dp = calc_dewpoint(loc);
+
+            /* dew point needs to be above a certain limit for
+               valid results, see
+               http://www.weatheroffice.gc.ca/mainmenu/faq_e.html#weather5 */
+            if (dp < 0)
+                return temp;
+
+            /* dew point needs to be converted to Kelvin (easy job ;-) */
+            e = 6.11 * exp(5417.7530 * (1/273.16 - 1/(dp + 273.15)));
+            return temp + 0.5555 * (e - 10.0);
+        }
+        return temp;
+
+    case STEADMAN:
+        /* Australians use a different formula. Source:
+           http://www.bom.gov.au/info/thermal_stress/#atapproximation */
+        e = humidity / 100 * 6.105 * exp(17.27 * temp / (237.7 + temp));
+        return temp + 0.33 * e - 0.7 * windspeed - 4.0;
+
+    case QUAYLE_STEADMAN:
+        /* R. G. Quayle, R. G. Steadman: The Steadman wind chill: an
+           improvement over present scales. In: Weather and
+           Forecasting. 13, 1998, S. 1187–1193 */
+        windspeed *= 3.6;
+        if (windspeed < 4.828032)
+            return temp;
+        return 1.41 - 1.162 * windspeed + 0.980 * temp
+            + 0.0124 * windspeed * windspeed + 0.0185 * windspeed * temp;
+    }
+}
+
+
 gchar *
 get_data(const xml_time *timeslice,
          const units_config *units,
@@ -256,6 +371,13 @@ get_data(const xml_time *timeslice,
             val = val * 9.0 / 5.0 + 32.0;
         return g_strdup_printf(ROUND_TO_INT("%.1f"), val);
 
+    case APPARENT_TEMPERATURE:
+        val = calc_apparent_temperature(loc, units->apparent_temperature,
+                                        night_time);
+        if (units->temperature == FAHRENHEIT)
+            val = val * 9.0 / 5.0 + 32.0;
+        return g_strdup_printf(ROUND_TO_INT("%.1f"), val);
+
     case CLOUDS_LOW:
         return LOCALE_DOUBLE(loc->clouds_percent[CLOUDS_PERC_LOW],
                              ROUND_TO_INT("%.1f"));
@@ -301,6 +423,7 @@ get_unit(const units_config *units,
         return (units->altitude == FEET) ? _("ft") : _("m");
     case TEMPERATURE:
     case DEWPOINT:
+    case APPARENT_TEMPERATURE:
         return (units->temperature == FAHRENHEIT) ? _("°F") : _("°C");
     case PRESSURE:
         switch (units->pressure) {
diff --git a/panel-plugin/weather-data.h b/panel-plugin/weather-data.h
index 4902fa8..a6a0982 100644
--- a/panel-plugin/weather-data.h
+++ b/panel-plugin/weather-data.h
@@ -33,6 +33,7 @@ typedef enum {
     WIND_DIRECTION_DEG,
     HUMIDITY,
     DEWPOINT,
+    APPARENT_TEMPERATURE,
     CLOUDS_LOW,
     CLOUDS_MED,
     CLOUDS_HIGH,
@@ -73,6 +74,13 @@ typedef enum {
 } units_altitude;
 
 typedef enum {
+    WINDCHILL_HEATINDEX,
+    WINDCHILL_HUMIDEX,
+    STEADMAN,
+    QUAYLE_STEADMAN
+} apparent_temp_models;
+
+typedef enum {
     MORNING,
     AFTERNOON,
     EVENING,
@@ -81,6 +89,7 @@ typedef enum {
 
 typedef struct {
     gint temperature;
+    gint apparent_temperature;
     gint pressure;
     gint windspeed;
     gint precipitations;
diff --git a/panel-plugin/weather-search.c b/panel-plugin/weather-search.c
index d4b18fa..2abdeb2 100644
--- a/panel-plugin/weather-search.c
+++ b/panel-plugin/weather-search.c
@@ -353,6 +353,13 @@ get_preferred_units(const gchar *country_code)
     if (!strcmp(country_code, "RU"))          /* Russian Federation */
         units->pressure = TORR;
 
+    if (!strcmp(country_code, "US"))          /* United States */
+        units->apparent_temperature = WINDCHILL_HEATINDEX;
+    else if (!strcmp(country_code, "CA"))     /* Canada */
+        units->apparent_temperature = WINDCHILL_HUMIDEX;
+    else if (!strcmp(country_code, "AU"))     /* Australia */
+        units->apparent_temperature = STEADMAN;
+
     return units;
 }
 
diff --git a/panel-plugin/weather-summary.c b/panel-plugin/weather-summary.c
index 8cef55b..ea4d0e1 100644
--- a/panel-plugin/weather-summary.c
+++ b/panel-plugin/weather-summary.c
@@ -421,6 +421,7 @@ create_summary_tab(plugin_data *data)
     APPEND_BTEXT(_("\nTemperatures\n"));
     APPEND_TEXT_ITEM(_("Temperature"), TEMPERATURE);
     APPEND_TEXT_ITEM(_("Dew point"), DEWPOINT);
+    APPEND_TEXT_ITEM(_("Apparent temperature"), APPARENT_TEMPERATURE);
 
     /* wind */
     APPEND_BTEXT(_("\nWind\n"));
@@ -548,7 +549,9 @@ forecast_cell_get_tooltip_text(plugin_data *data,
     g_free(value);
 
     g_string_append(text, _("<b>Temperatures</b>\n"));
-    APPEND_TOOLTIP_ITEM(_("Dew point:\t\t\t%s%s%s\n\n"), DEWPOINT);
+    APPEND_TOOLTIP_ITEM(_("Dew point:\t\t\t%s%s%s\n"), DEWPOINT);
+    APPEND_TOOLTIP_ITEM(_("Apparent temperature:\t%s%s%s\n\n"),
+                        APPARENT_TEMPERATURE);
 
     g_string_append(text, _("<b>Atmosphere</b>\n"));
     APPEND_TOOLTIP_ITEM(_("Pressure:\t%s%s%s\n"), PRESSURE);
diff --git a/panel-plugin/weather.c b/panel-plugin/weather.c
index 498161a..b313dad 100644
--- a/panel-plugin/weather.c
+++ b/panel-plugin/weather.c
@@ -137,6 +137,9 @@ make_label(const plugin_data *data,
     case DEWPOINT:
         lbl = _("D");
         break;
+    case APPARENT_TEMPERATURE:
+        lbl = _("A");
+        break;
     case CLOUDS_LOW:
         lbl = _("CL");
         break;


More information about the Xfce4-commits mailing list