Smhi-data python-klient publicerad
/ 2023-03-29 / ProjektIFKs pythonbibliotek för att läsa SMHI-data, ifk-smhi
har i dagarna officiellt
släppts i version 0.1.
Som tidigare rapporterats om har föreningen, främst genom dr. Mladen Gibanicas försorg, arbetat med att ta fram ett pythonbibliotek för att på ett enkelt sätt läsa data från SMHIs API. Söndagen den 27 mars släpptes den första officiella versionen, och nu finns version 0.1.1 tillgänglig via paketinstallationsplattformen pypi.
"Vi läser fortfarande de fyra mest kritiska API:na", förklarar dr. Gibanica, "det vill säga MetObs - som läser historisk data från Meteorologiska Observationer, Mesan - som interpolerar fram meterologisk data även där mätdata saknas, MetFcts - som genererar meteorologiska förutsägelser, och Strång - som modellerar solens strålningsintensitet. Det som utvecklats till denna release är framför allt att vi arbetat för att få till enhetliga och lättlästa tabeller som utdata. Dessutom har vi lagt ner mycket möda på att säkerställa kodkvalitén."
Källkoden är tillgänglig under MIT-licens (fritt användande) på Ingenjörsarbete För Klimatets GitHub. Öppna ett ärende där om någonting saknas eller fungerar dåligt så lovar utvecklingsteamet att de ska ta sig an det å det snaraste!
Nedan följer några exempel på hur de olika modulerna kan användas - flera av dessa har modifierats från originalartikeln på mladen.gibanica.net.
Exempel på användning av Metobs
Metobs
är som tidigare nämnts ett verktyg för att läsa ut data från metereologiska
observationer från de väderstationer som SMHI underhåller i landet. För att ta reda
på vilka parametrar som finns att utläsa kan vi använda följande kod:
from smhi.metobs import Parameters, Stations, Periods, Data
parameter = Parameters()
parameter.show
som kommer ge svar:
('1', 'Lufttemperatur', 'momentanvärde, 1 gång/tim')
('2', 'Lufttemperatur', 'medelvärde 1 dygn, 1 gång/dygn, kl 00')
('3', 'Vindriktning', 'medelvärde 10 min, 1 gång/tim')
...
('11', 'Global Irradians (svenska stationer)', 'medelvärde 1 timme, 1 gång/tim')
...
Om vi nu vill veta vilka stationer som har mätvärden för parameter 1
så kör vi:
stations = Stations(parameter, 1)
stations.show
Som kommer att leverera en lista på 968 stationer:
(1, 'Akalla')
(2, 'Högdalen')
(3, 'Sigtuna')
(4, 'Jönköping')
(7, 'Gävle')
...
(71420, 'Göteborg A')
...
(72630, 'Göteborg')
...
Vi tittar på stationen "Göteborg A"
. Vilka perioder finns data tillgängligt för?
periods = Periods(stations, station_name="Göteborg A")
periods.show
listar de tillgängliga perioderna:
corrected-archive
latest-day
latest-hour
latest-months
För att få datan frågar vi slutligen efter den genom:
data = Data(periods)
data.data
detta ger "corrected-archive"
-perioden i en Pandas DataFrame:
Lufttemperatur
1961-01-01 06:00:00 0.8
1961-01-01 12:00:00 1.0
1961-01-01 18:00:00 1.4
1961-01-02 06:00:00 1.8
1961-01-02 12:00:00 2.2
... ...
2022-12-01 02:00:00 2.5
2022-12-01 03:00:00 2.4
2022-12-01 04:00:00 2.3
2022-12-01 05:00:00 2.1
2022-12-01 06:00:00 1.9
[303469 rows x 1 columns]
Observera att de tre senaste månaderna vanligtvis saknas från "corrected-archive"
.
(De finns istället tillgängliga i "latest-months"
). Denna data presenteras med
fördel i en scatter plot.
Här används bara daglig medeltemperatur istället för temperatur per timme för att
begränsa datamängden i denna artikel, se "Plot code details".
Plot code
import plotly.graph_objects as go
data_agg_day = data.data.resample("D").mean()
fig = go.Figure()
fig.add_trace(
go.Scattergl(
x=data_agg_day.index,
y=data_agg_day["Lufttemperatur"],
mode="markers",
name="Göteborg A station"
)
)
fig.update_layout(
title="Lufttemperatur Göteborg A",
xaxis_title="År",
yaxis_title="Lufttemperatur [°C]",
legend={"orientation": "h"},
margin={"l": 0, "r": 0, "b": 80, "t": 100},
paper_bgcolor="rgba(250, 250, 250, 1)",
)
fig.show()
Exempel på användning av Strang
Tänk om vi istället är intresserade av global irradians över Sverige? Hur många
stationer har vi där? Det handlar om parameter 11
från Metobs enligt listan
här ovanför:
stations = Stations(parameter, 11)
stations.show
vilket ger oss:
(53445, 'Lund Sol')
(64565, 'Växjö Sol')
(68545, 'Hoburg Sol')
(71415, 'Göteborg Sol')
(77215, 'Ölands norra udde Sol')
(78645, 'Visby Sol')
(81525, 'Nordkoster Sol')
(86655, 'Norrköping Sol')
(93235, 'Karlstad Sol')
(98735, 'Stockholm Sol')
(99275, 'Svenska Högarna Sol')
(105285, 'Borlänge Sol')
(132165, 'Storlien-Visjövalen Sol')
(134615, 'Östersund Sol')
(140615, 'Umeå Sol')
(147655, 'Gunnarn Sol')
(162015, 'Luleå Sol')
(178985, 'Tarfala Sol')
(180025, 'Kiruna Sol')
Det innebär alltså att det bara finns 19 stationer som mäter global irradians. För att bättre kunna täcka in hela landet kan vi istället använda STRÅNG-API:t, som använder observationer tillsammans med simuleringar för att interpolera fram strålningsdata. Vi kan använda det som:
from smhi.strang import Strang
strang = Strang()
parameters = strang.parameters
vilket listar tillgängliga parametrar:
parameter: 116, info: CIE UV irradiance [mW/m²]
parameter: 117, info: Global irradiance [W/m²]
parameter: 118, info: Direct normal irradiance [W/m²]
parameter: 120, info: PAR [W/m²]
parameter: 121, info: Direct horizontal irradiance [W/m²]
parameter: 122, info: Diffuse irradiance [W/m²]
I detta exempel letar vi alltså efter parameter 117. Låt oss börja med att undersöka vilket som är det första datum för vilket data är tillgängligt:
strang.available_parameters[117].time_from
som ger:
datetime.datetime(1999, 1, 1, 0, 0, tzinfo=tzutc())
Nu kan vi generera ett multi-point-svar från APIt för den dagen aggregerat
daily
:
data = strang.get_multipoint(117, "1999-01-01", "daily")
data
vilket återigen ger en Pandas DataFrame:
lat lon Global irradiance [W/m²] 1999-01-01T00:00:00+00:00 daily
0 74.945244 1.212198 0.0
1 74.910484 1.942287 0.0
2 74.873570 2.669121 0.0
3 74.834520 3.392533 0.0
4 74.793340 4.112356 0.0
... ... ... ...
11827 46.503345 23.264704 1561.9
11828 46.408020 23.516861 1655.8
11829 46.312065 23.768070 1717.9
11830 46.215477 24.018330 1701.7
11831 46.118263 24.267643 1673.6
[11832 rows x 3 columns]
Det är lämpligare att titta på även denna data i figur:
Scatter plot code
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(
go.Scattergl(
x=data["lon"],
y=data["lat"],
mode="markers",
name="Global irradians 1999-01-01",
marker={
"color": data["Global irradiance [W/m²] 1999-01-01T00:00:00+00:00 daily"],
"colorbar": {"title": "[W/m²]"},
},
)
)
fig.update_layout(
title="Global irradians 1999-01-01",
xaxis_title="Longitud",
yaxis_title="Latitud",
legend={"orientation": "h"},
margin={"l": 0, "r": 0, "b": 80, "t": 100},
paper_bgcolor="rgba(250, 250, 250, 1)",
)
fig.update_yaxes(
scaleanchor="x",
scaleratio=1,
)
fig.show()
Exempel på användning av Mesan
Interpolation mellan stationer med hjälp av metereologiska modeller är som vi
sett i exemplet med solstrålningsmätningar ett väldigt bra sätt att få goda lokala
prediktioner av parametrar som endast finns tillgängliga från ett fåtal stationer
i landet. Denna princip finns tillgänglig även för andra parametrar i Mesan-paketet,
där vi på samma sätt som från Strång kan få data antingen över ett område mha
get_multipoint
eller för en specifik position mha get_point
.
from smhi.mesan import Mesan
client = Mesan()
data = client.get_point(57.632973, 11.605914)
Ger oss en pandas dataframe med modelldata för Vinga ute i Göteborgs skärgård för det senaste dygnet, vid denna artikels skrivande sista mars och första april. Parameterbeskrivningar mm finns tillgängligt på SMHIs API-sida. En intressant parameter ute i skärgården är förstås vindhastighet - för att läsa ut byvindhastigheter timme för timme tar vi då:
data["gust"]
Vilket ger:
unit m/s
validTime
2023-03-31 09:00:00+00:00 13.4
2023-03-31 10:00:00+00:00 13.8
2023-03-31 11:00:00+00:00 13.8
2023-03-31 12:00:00+00:00 14.4
2023-03-31 13:00:00+00:00 14.8
2023-03-31 14:00:00+00:00 14.6
2023-03-31 15:00:00+00:00 15.0
2023-03-31 16:00:00+00:00 13.8
2023-03-31 17:00:00+00:00 13.6
2023-03-31 18:00:00+00:00 14.1
2023-03-31 19:00:00+00:00 13.5
2023-03-31 20:00:00+00:00 13.9
2023-03-31 21:00:00+00:00 13.9
2023-03-31 22:00:00+00:00 13.6
2023-03-31 23:00:00+00:00 13.2
2023-04-01 00:00:00+00:00 12.4
2023-04-01 01:00:00+00:00 12.4
2023-04-01 02:00:00+00:00 14.1
2023-04-01 03:00:00+00:00 13.8
2023-04-01 04:00:00+00:00 13.4
2023-04-01 05:00:00+00:00 14.0
2023-04-01 06:00:00+00:00 12.1
2023-04-01 07:00:00+00:00 11.8
2023-04-01 08:00:00+00:00 15.1
Det blåser alltså ute på öarna idag!
Exempel på användning av Metfcts
Hur kommer det då att se ut imorgon? SMHI tillhandahåller även metereologiska
prediktioner från sina modeller, vilka finns tillgängliga i en parallell anropsstruktur
i paketet smhi.metfcts
. För att få en tiodygnsprognos av byvinden ute vid
Vinga skriver vi helt enkelt:
from smhi.metfcts import Metfcts
client = Metfcts()
data = client.get_point(57.632973,11.605914)
data["gust"]
Vilket i skrivande stund ger oss:
unit m/s
validTime
2023-04-01 10:00:00+00:00 13.2
2023-04-01 11:00:00+00:00 12.8
2023-04-01 12:00:00+00:00 12.0
2023-04-01 13:00:00+00:00 11.4
2023-04-01 14:00:00+00:00 11.3
... ...
2023-04-09 00:00:00+00:00 8.5
2023-04-09 12:00:00+00:00 10.2
2023-04-10 00:00:00+00:00 10.3
2023-04-10 12:00:00+00:00 11.0
2023-04-11 00:00:00+00:00 10.0
Och med hjälp av numpy kan vi sluta oss till att den förväntade medelhastigheten på byvindarna under de närmsta tio dagarna är 6.3m/s:
import numpy as np
np.mean(data.gust)
(c) Ingenjörsarbete för Klimatet. För återpublicering kontakta ansvarig utgivare Anders Nord anders.nord@ingenjorsarbeteforklimatet.se.