Local/offline/self-hosted weather forecast?

Well from a very quick browse through, it would appear that we can take the temperature check and do something like:

temp_threshold = 2.1;
temp_threshold = (temp_threshold * ((station_height - sea_level_pressure) * 0.003))
// increase the temperature_threshold by 0.003 per 1hpa for the distance in pressure between sea level and our station height.
if (temp_threshold > 4.5) { temp_threshold = 4.5; }

I need to have a think about the RH part of things.
I also had not scrolled far enough down to see the formula they used.

a = a scaling factor, again not really sure how we use this.
b = 0.7 (from following the links to other research papers)
https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2008GL033295
c = the temperature at which snow or rain probability are equal, but I don’t see how you are supposed to calculate that.

Parameter *a* is a scaling factor, *b* is the slope (scaled by *a* ) around *T* *0.5*, *c* approximately represents the half-frequency temperature *T* *0.5* in °C, and *d* , when different from one, reflects the slight asymmetry in the converged values at large negative and positive temperatures.

Edit: quick followup - looking at the supplementary data tables, where they compared different models to see how well they would match existing recorded data - the Bivariate model had an 88% success rate at predicting the 50% snow-rain frequency. Using:

α = -10.04
β = 1.41
γ = 0.09

So we could maybe look there first?

1 / 1 + e(-10.04 + (1.41 * air_temperature) + (0.09 * rel_humidity))
(if my BODMAS is correct lol 1+e(α+βTs+γRH) )

Though plugging something like this:
1 / (1 + e(-10.04 + 1.41 * 1.2 + 0.09 * 68))
In to Google, returns -0.19 based on an air temperature of 1.2 and a RH of 68%. I’m not entirely sure what we are supposed to do with that result. It does seem that the more likely snow would be, the closer to zero the result becomes. Eg: an RH of 45% would return -0.09 for the same 1.2C air temperature. And if the air temperature was colder say 0.02 then the result is -0.068

Just missing a set of ()

p(snow) = 1 / (1 + e^(-10.04+1.41*air_temperature + 0.09*relative_humidity))

Ah! I was missing the ^ - this level of maths is way outside my comfort zone - but you are correct, with the ^, Google is now returning 0.99 for an RH of 45% at an air temperature of 0.2C, and 0.897 for an air temperature of 0.6C with an RH of 78% that definitely seems better.

I will start running this code when I get back home and start tracking it.
We are in a warm spell at the moment, so I’d love any data you get.
I can give you the equation in Java-script since I will be running it in Node-Red.

function snowProbability(airTemperature, relativeHumidity) {
    let pSnow = 1 / (1 + Math.exp(-10.04 + (1.4147 * airTemperature) + (0.0998 * relativeHumidity)));
    return pSnow;
}
1 Like

OK, I have found a Node Red GSheets contrib.

I have set up NodeRed to check the Tempest data every 15 minutes, and if the Air Temperature is < 4.1, then to write a row to the Google Sheet.

Ok, I got mine up and going and feeding a sensor back to HA for now.
Unfortunately we are in the way to warm for snow at the moment.

For yours, it might be helpful to add the Snow Probability from WeatherFlow2MQTT for comparison.

1st one is your original snow probability that is in the integration.
2nd one is this current testing
Untitled

Oh! I actually didn’t know that it was in there - it’s not something currently available in mine, so I guess my docker image is a bit behind lol. Last created 2 months ago.
Just pulled the latest now.

OK I have added a column for the existing snow probability, that I didn’t even know was there lol.

Are you running the vanilla build or the dev build?

The local current conditions is in a PR and hopefully will land in the next dev build.

If we get good results from this I will do a PR to update Sniw Probability.

What search terms did you use to find that paper?
I did a lot of searching and never found anything like that.

Hey Glenn
I’m running vanilla in a dedicated LXC on Proxmox.

I was actually looking for something about humidity and snow formation, because your code was simply checking for Humidity less than 70% which I suspected was not correct (for me at least) - because we get snow here in the UK with high humidity. We very rarely get snow when the temperature is lower than -0.5C or higher than 1.2C. The Humidity is typically around 75+ % I guess because in my location at least, for any significant snow to fall it must be coming from the North East or the East, which means it’s coming across the North Sea - and thus usually bringing quite a bit of moisture content with it.

High humidity at around 0C makes BIG snow flakes, because they melt as they are falling, but evaporative cooling makes them freeze again, but often joined with other snowflakes that were melting as they were falling.

Because I knew that it certainly snows here at high humidity, I thought there must be a published range somewhere, because there must be a humidity level where it becomes too dry for snow as well?

My Google search was “lowest humidity for snow” which returned - Rain or snow? Humidity, location can make all the difference, new map shows

And as usual the UK Met Office was useful in confirming my suspicion that the UK generally requires a high humidity to receive snowfall - Snow forecasting in the UK - Met Office

Here are some of our upcoming forecasts - so you can see how high the humidity is, and the Snow probability from the High Resolution UK Models.

Monday:

Thursday:

My location height is 154m ASL

Using the existing formula, all these will presumably produce 0% probability because of the humidity being above 70%.

Using the new formula though:

Day Time Model Prediction Formula Prediction Air Temp RH
Sat 19z 25% 14% 2.5C 92%
Sun 0z 30% 10% 2.4C 98%
Sun 18z 38% 43% 1.0C 99%
Mon 15z 86% 53% 1.3C 90%
Mon 21z 95% 97% -0.7C 85%
Tue 6z 0% 98% -0.8C 79%
Thu 0z 80% 93% -0.6C 93%

It’s looking pretty good, I threw Tuesday in there, so you can see that the weather model prediction is obviously other parameters than just the temperature and humidity level, wind direction etc is important for the UK, but wouldn’t really be something you could build in to our code, because it will be different for everyone.

If it was me, I’d probably do something along the lines of (as I have mentioned in the past), taking a 9am snapshot of the Zambretti - or at least an average of the last 3 hours - and then that can be used to determine if precipitation is likely. Obviously if there is no chance for precipitation than the snow probability is 0.

I just noticed I forgot the “e” ~ 2.7
I have to lookup how to do ‘e’ in Java-Script, I just glossed right over that.
I’ll post when I have it corrected.

Math.E = 2.71828 already though?

console.log(Math.exp(1));

returns

2.718281828459045

However:

1 / (1 + Math.exp(-10.04 + (1.41 * -0.06) + (0.09 * 93)));

returns 0.852 in the javascript console and 0.925 in Google.
Even if I follow the brackets exactly the way Google displays them:

1 / (1 + (Math.exp((-10.04) + (1.41 * (-0.06)) + (0.09 * 93))));

Additionally you should be aware although the changes in your code look very small -

function snowProbability(airTemperature, relativeHumidity) {
    let pSnow = 1 / (1 + Math.exp(-10.04 + (1.4147 * airTemperature) + (0.0998 * relativeHumidity)));
    return pSnow;
}

1.4147 and 0.0998 will return a very different result to 1.41 and 0.09:

1 / (1 + (Math.exp((-10.04) + (1.4147 * (-0.06)) + (0.0998 * 93))));

is 0.699

Ok, Math.exp is Euler’s number to the exponent.
It might be too many characters in one calculation; I’ve run into issues where I had to shorten my variable names and also perform calculations on separate lines because it was just too long. Sometimes I have had issues with capital letters…so let’s try this:

    t = airTemperature;
    rh = relativeHumidity;

    stuff = -10.04 + (1.4147 * t) + (0.0998 * rh);
    p_snow = 1 / (1 + Math.exp(stuff));

    return p_snow;

Actually - it turns out it does work with the long line.
It’s just that I was using -0.6 as the air temperature in Google, and -0.06 as the air temperature in the developer console.

I can confirm that:

1 / (1 + (Math.exp((-10.04) + (1.41 * (-0.6)) + (0.09 * 93))));

Returns 0.925 on both Google and the Javascript console

EDIT:
But please remember to fix your constants. 0.0998 instead of 0.09 returns a different result ( 0.832 )

I don’t know how I fat fingered that and did not notice. I did it for air_temperature also…I really need more sleep. Ok, I will fix my Node-Red when I get home. I might do the export to Google docs also, are you manually entering the observation of snow?

Yeah, I will manually observe if there is sleet or snow (or none) and add it to the row when the row is created (my NodeRed flow does the check every 15 minutes and then adds a row if the temperature is below 4.1)

Edit: My post limiting code is now:

if (msg.sdata[2] >= 4.1) {
    // too warm, nothing to do - end
    node.status({fill:"red",shape:"ring",text:"Stopped: Too Warm @ " + msg.sdata[2] });
    return null;
}
if (msg.sdata[2] >= 3.1 && msg.sdata[4] < 0.15) {
    // snow probability is low
    node.status({ fill: "red", shape: "ring", text: "Stopped: Snow Probability is " + parseFloat(msg.sdata[4]).toFixed(2) });
    return null;
}
msg.payload = msg.sdata;
node.status({fill: "green", shape: "ring", text: "Passed: " + msg.sdata[2] + "C, " + parseFloat(msg.sdata[4]).toFixed(2) + "%" });

return msg;

So the spreadsheet won’t update if the temperature is over 4.1 OR the temperature is over 3.1 AND the snow probability is < 0.15 (15%)

Just to try and reduce the amount of junk data we will need to wade through later.

On a separate note from Snow Probability, I have Lightning probability.
I don’t get much lightning in my location, so am open to feedback:

I have it setup to take the inputs in Imperial and convert them to metric. If you have metric inputs then just remove the conversions at the top.

// Probability of Lightning
// for testing in Node-Red (Java-Script) all inputs are Imperial
// function in metric since WeatherFlow2MQTT is best done metric

// Most Likely conditions for Lightning
// humidity range 50-70%
// temperature range 20-30C / 68-86F
// sea level pressure range 1010-1020hPa
// local time 2-3pm and 2-3am

var temperature = (msg.temperature - 32) * (5/9)
var relativeHumidity = msg.humidity
var solarRadiation = msg.sr
var windSpeed = msg.wind_speed * 0.44704
var pressure = msg.sea_press * 33.863886666667
var strikes_1m = msg.light_1m
var strikes_1h = msg.light_1h
var strikes_3h = msg.light_3h
var strikes_day = msg.light_day
var dew_point = (msg.dp - 32)*(5/9)
var cloudy = flow.get('cloudy')
var partly_cloudy = flow.get('part_cloud')

let prob = 0;

// temperature, dew point, and relative humidity check
if (temperature > 30) {
    if (relativeHumidity > 50 && dew_point > 15) {
        prob += 30;
    } else if (relativeHumidity > 30 && dew_point > 10) {
        prob += 20;
    }
}

// solar radiation check
if (solarRadiation > 600) {
    prob += 25
} else if (solarRadiation > 400) {
    prob += 10;
}

// wind speed check
if (windSpeed < 15) {
    prob += 15
}

// pressure check
if (pressure < 1000) {
    prob += 25
} else if (pressure < 1010) {
    prob += 10;
}

// lightning detector check
if (strikes_1m > 1 || strikes_1h > 20 || strikes_3h > 50 || strikes_day > 120) {
    prob += 25
} else if (strikes_1m > 0 || strikes_1h > 10 || strikes_3h > 20 || strikes_day > 50) {
    prob += 10;
}

// cloud coverage check
if (cloudy === 'true' || partly_cloudy === 'true') {
    prob += 25;
}

// Combine inputs into one string
msg.inputs = `temperature: ${msg.temperature}F, relative humidity: ${msg.humidity}%, solar radiation: ${msg.sr}, wind speed: ${msg.wind_speed}mph, pressure: ${msg.sea_press}inHg, strikes_1m: ${msg.light_1m}, strikes_1h: ${msg.light_1h}, strikes_3h: ${msg.light_3h}, strikes_day: ${msg.light_day}, dew_point: ${msg.dp}F, cloudy: ${flow.cloudy}, partly_cloudy: ${flow.part_cloud}`;

msg.light = prob
return msg;

I have notes of things to take into account, which I will update.

https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6921276/
Provides observed conditions where snow fell (New York), but it is a start to adding pressure and wind speed in. Wind direction will probably be nearly impossible to implement without creating a massive lookup table for wind direction to snow; which I think would be well outside the scope.

https://www.ncei.noaa.gov/
Has some history of weather, might be useful in the future.

https://tc.copernicus.org/articles/16/1741/2022/tc-16-1741-2022.pdf
Might be some good info here, this states that sea level pressure does have a strong relationship to snowfall but that it is complex…still deciphering.
This paper mentions that 8 components make up over 90% of snow probability…but I can’t find what those components are in the paper.

Some data points:
Lowest recorded pressure for snowfall is 925hPa
Typically, snowfall occurs at pressures between 995-1015 hPa.

Could you add sea level pressure and zambretti # to your google doc?
Wind speed may not be a bad addition also.
The Zambretti number is probably the least useful, but your comment has me thinking about it.

I’ve added Temp in F and hPa.
There is no point in me adding wind speed, because 1) it is massively wrong, the station is probably too low. and 2) The station in in powersave mode, because Winter in the UK. Because of the lack of Wind readings, Zambretti is also not going to much use right now either.

Also -

I think you need to multiply your result by 100 for snow probability.

I will say that your old way of doing it sees to track very well also.

1 Like

Yeah I do, but I’ve left it alone for now - it’s easy enough to see see it as a percentage value, and I’ve colour coded stuff to make it easier to spot stuff lol