diff --git a/docs/api.rst b/docs/api.rst index d9e7223..d903c9e 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -23,6 +23,7 @@ API Reference fetchers/slovenia fetchers/southafrica fetchers/spain + fetchers/switzerland fetchers/uk_ea fetchers/uk_nrfa - fetchers/usa \ No newline at end of file + fetchers/usa diff --git a/docs/fetchers/switzerland.rst b/docs/fetchers/switzerland.rst new file mode 100644 index 0000000..f71efec --- /dev/null +++ b/docs/fetchers/switzerland.rst @@ -0,0 +1,5 @@ +Switzerland Fetcher +=================== + +.. automodule:: rivretrieve.switzerland + :members: diff --git a/examples/plot_switzerland_historical.py b/examples/plot_switzerland_historical.py new file mode 100644 index 0000000..364bc75 --- /dev/null +++ b/examples/plot_switzerland_historical.py @@ -0,0 +1,39 @@ +import logging + +import matplotlib.pyplot as plt + +from rivretrieve import SwitzerlandFetcher, constants + +logging.basicConfig(level=logging.INFO) + +gauge_id = "2016" +variable = constants.DISCHARGE_DAILY_MEAN +start_date = "2020-01-01" +end_date = "2020-01-31" + +fetcher = SwitzerlandFetcher() +data = fetcher.get_data( + gauge_id=gauge_id, + variable=variable, + start_date=start_date, + end_date=end_date, +) + +if data.empty: + print(f"No data found for gauge {gauge_id}, variable {variable}") +else: + print(data.head()) + print(f"Fetched {len(data)} rows from {data.index.min()} to {data.index.max()}") + + plt.figure(figsize=(12, 6)) + plt.plot(data.index, data[variable], label=f"{gauge_id} - {variable}", linewidth=1.8) + plt.xlabel(constants.TIME_INDEX) + plt.ylabel("Discharge (m3/s)") + plt.title(f"Switzerland historical series for gauge {gauge_id}") + plt.grid(True, alpha=0.3) + plt.legend() + plt.tight_layout() + + output_path = "switzerland_historical_plot.png" + plt.savefig(output_path, dpi=150) + print(f"Saved plot to {output_path}") diff --git a/examples/test_switzerland_fetcher.py b/examples/test_switzerland_fetcher.py new file mode 100644 index 0000000..aebfeb8 --- /dev/null +++ b/examples/test_switzerland_fetcher.py @@ -0,0 +1,36 @@ +import logging + +import matplotlib.pyplot as plt + +from rivretrieve import SwitzerlandFetcher, constants + +logging.basicConfig(level=logging.INFO) + +gauge_id = "2016" +variables = [ + constants.DISCHARGE_DAILY_MEAN, + constants.WATER_TEMPERATURE_DAILY_MEAN, +] +start_date = "2026-02-01" +end_date = "2026-02-07" + +fetcher = SwitzerlandFetcher() + +for variable in variables: + data = fetcher.get_data(gauge_id=gauge_id, variable=variable, start_date=start_date, end_date=end_date) + if data.empty: + print(f"No data found for {gauge_id} ({variable})") + continue + + print(data.head()) + plt.figure(figsize=(12, 6)) + plt.plot(data.index, data[variable], label=f"{gauge_id} - {variable}") + plt.xlabel(constants.TIME_INDEX) + plt.ylabel(variable) + plt.title(f"Switzerland River Data ({gauge_id})") + plt.legend() + plt.grid(True) + plt.tight_layout() + plot_path = f"switzerland_{variable}_plot.png" + plt.savefig(plot_path) + print(f"Plot saved to {plot_path}") diff --git a/rivretrieve/__init__.py b/rivretrieve/__init__.py index ae2e150..4892fbd 100644 --- a/rivretrieve/__init__.py +++ b/rivretrieve/__init__.py @@ -16,6 +16,7 @@ from .slovenia import SloveniaFetcher from .southafrica import SouthAfricaFetcher from .spain import SpainFetcher +from .switzerland import SwitzerlandFetcher from .uk_ea import UKEAFetcher from .uk_nrfa import UKNRFAFetcher from .usa import USAFetcher diff --git a/rivretrieve/cached_site_data/switzerland_sites.csv b/rivretrieve/cached_site_data/switzerland_sites.csv new file mode 100644 index 0000000..ffa7c8d --- /dev/null +++ b/rivretrieve/cached_site_data/switzerland_sites.csv @@ -0,0 +1,247 @@ +gauge_id,station_name,river,latitude,longitude,altitude,area,country,source +2004,Murten,Murtensee,46.9308,7.1169,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2007,Le Pont,Lac de Joux,46.6653,6.324,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2009,Porte du Scex,Rhône,46.3496,6.8886,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2011,Sion,Rhône,46.2191,7.3579,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2014,Schmerikon,Zürichsee,47.2248,8.9401,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2016,Brugg,Aare,47.4825,8.1949,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2017,Zug,Zugersee,47.1679,8.5143,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2018,Mellingen,Reuss,47.421,8.2713,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2019,Brienzwiler,Aare,46.7457,8.092,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2020,Bellinzona,Ticino,46.1938,9.0093,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2021,Ponte Tresa,Lago di Lugano,45.9688,8.8603,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2022,Locarno,Lago Maggiore,46.1636,8.8043,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2023,Ringgenberg,Brienzersee,46.7299,7.9755,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2024,Branson,Rhône,46.1257,7.0913,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2025,Brunnen,Vierwaldstättersee,46.9935,8.6038,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2026,Chillon,Lac Léman,46.4146,6.9277,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2027,St-Prex,Lac Léman,46.4828,6.4611,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2028,"Genève, Sécheron",Lac Léman,46.2186,6.1524,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2029,"Brügg, Aegerten",Aare,47.1221,7.2834,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2030,Thun,Aare,46.7646,7.6118,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2031,Unterägeri,Aegerisee,47.138,8.5918,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2032,Romanshorn,"Bodensee, Obersee",47.5648,9.381,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2033,Ilanz,Vorderrhein,46.7758,9.2064,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2034,"Payerne, Caserne d'aviation",Broye,46.8359,6.9361,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2041,"Oberriet, Blatten",Rhein,47.3069,9.5708,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2043,Berlingen,"Bodensee, Untersee",47.6755,9.0176,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2044,Andelfingen,Thur,47.5965,8.682,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2053,"Martigny, Pont de Rossettan",Drance,46.0977,7.0627,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2056,Seedorf,Reuss,46.8839,8.6206,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2057,Les Brenets,Lac des Brenets,47.0826,6.7086,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2063,Murgenthal,Aare,47.2661,7.8288,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2066,St. Moritz,St. Moritzersee,46.4975,9.8481,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2067,Martina,Inn,46.8858,10.4654,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2068,Riazzino,Ticino,46.1634,8.9103,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2070,Emmenmatt,Emme,46.9544,7.7488,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2071,Emmenmatt (N),Emme,46.9536,7.7516,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2072,Sils Baselgia,Silsersee,46.4344,9.7532,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2073,Silvaplana,Silvaplanersee,46.4601,9.8024,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2074,Brissago,Lago Maggiore,46.1181,8.7109,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2078,Le Prese,Poschiavino,46.2954,10.08,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2079,Le Prese,Canale industriale,46.2947,10.0795,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2081,Pfäffikon,Pfäffikersee,47.364,8.7786,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2082,Greifensee,Greifensee,47.3652,8.6735,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2084,Ingenbohl,Muota,47.0004,8.5987,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2085,Hagneck,Aare,47.0556,7.1844,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2086,Loderio,Brenno,46.3765,8.9694,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2087,Andermatt,Reuss,46.6423,8.5896,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2088,Sarnen,Sarnersee,46.8877,8.2424,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2091,Rheinfelden,Rhein,47.5607,7.7999,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2093,Spiez,Thunersee,46.6967,7.6646,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2097,Meisterschwanden,Hallwilersee,47.2958,8.2203,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2099,Zürich Unterhard,Limmat,47.3906,8.5254,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2101,"Melide, Ferrera",Lago di Lugano,45.9663,8.9489,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2102,Sarnen,Sarner Aa,46.8962,8.2452,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2104,"Weesen, Biäsche",Linth,47.1316,9.0884,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2105,St. Moritzbad,Inn,46.4847,9.8341,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2106,"Münchenstein, Hofmatt",Birs,47.5183,7.6188,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2109,Gsteig,Lütschine,46.6642,7.8715,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2110,"Mühlau, Hünenberg",Reuss,47.2223,8.3961,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2112,Appenzell,Sitter,47.332,9.4106,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2113,Klingnau,Aare,47.5941,8.2251,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2116,Koblenz,Rhein,47.609,8.2343,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2117,"Le Châble, Villette",Drance de Bagnes,46.0807,7.2131,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2118,Murg,Walensee,47.1134,9.21,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2119,Fribourg,Sarine,46.8039,7.169,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2122,"Moutier, La Charrue",Birse,47.284,7.3823,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2125,Frauenthal,Lorze,47.2153,8.425,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2126,Wängi,Murg,47.4963,8.953,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2130,Laufenburg,Rhein (Oberwasser),47.5558,8.0498,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2132,Neftenbach,Töss,47.5188,8.653,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2135,"Bern, Schönau",Aare,46.9331,7.448,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2137,Gelfingen,Baldeggersee,47.2099,8.2664,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2139,St.Margrethen,Rheintaler Binnenkanal,47.4496,9.6553,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2141,Tiefencastel,Albula,46.6625,9.5741,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2143,Rekingen,Rhein,47.5703,8.3298,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2150,Felsenbach,Landquart,46.9746,9.6121,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2151,Oberwil,Simme,46.655,7.4394,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2152,"Luzern, Geissmattbrücke",Reuss,47.054,8.2985,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2154,Grandson,Lac de Neuchâtel,46.8058,6.6424,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2155,"Wiler, Limpachmündung",Emme,47.1601,7.547,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2156,Gerlafingen,Werkkanal,47.1638,7.5543,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2157,Gerlafingen,Strackbach,47.1606,7.5609,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2159,"Belp, Mülimatt",Gürbe,46.8852,7.5017,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2160,"Broc, Château d'en bas",Sarine,46.6028,7.093,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2161,Blatten bei Naters,Massa,46.3856,8.0067,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2167,"Ponte Tresa, Rocchetta",Tresa,45.972,8.8524,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2168,Sempach,Sempachersee,47.1343,8.1892,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2170,"Genève, Bout du Monde",Arve,46.1803,6.1593,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2174,"Chancy, Aux Ripes",Rhône,46.153,5.9707,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2176,Zürich,Sihl,47.3677,8.5262,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2179,"Thörishaus, Sensematt",Sense,46.8883,7.3514,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2181,Halden,Thur,47.5058,9.2115,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2185,Chur,Plessur,46.8597,9.5105,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2187,Salez,Werdenberger Binnenkanal,47.2383,9.5096,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2199,Basel,Wiese,47.5779,7.5955,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2200,Zweilütschinen,Weisse Lütschine,46.6313,7.8997,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2202,Liestal,Ergolz,47.4881,7.7341,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2203,Aigle,Grande Eau,46.3189,6.9709,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2205,"Untersiggenthal, Stilli",Aare,47.5159,8.2347,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2206,"Melera, (Valle Morobbia)",Melera,46.1715,9.083,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2207,Luzern,Vierwaldstättersee,47.0549,8.3198,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2208,"Ligerz, Klein Twann",Bielersee,47.0917,7.1531,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2209,Zürich,Zürichsee,47.3548,8.5505,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2210,Ocourt,Doubs,47.3504,7.0751,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2215,Laupen,Saane,46.9086,7.2344,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2217,"Chancy, Vers Vaux",Rhône,46.1321,5.9563,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2219,Oberried/Lenk,Simme,46.4263,7.4729,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2232,Adelboden,Allenbach,46.486,7.5521,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2239,Punt dal Gall,Spöl,46.6292,10.1947,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2243,"Baden, Limmatpromenade",Limmat,47.4757,8.3094,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2244,Klusmatten,Krummbach,46.2248,8.0154,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2247,Les Brenets,Doubs,47.0844,6.7103,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2251,"Plaffeien, Schwyberg",Rotenbach,46.6864,7.2816,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2252,"Plaffeien, Schwyberg",Schwändlibach,46.6903,7.2863,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2256,Pontresina,Rosegbach,46.4899,9.8981,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2262,Pontresina,Berninabach,46.4864,9.9062,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2263,La Punt-Chamues-ch,Chamuerabach,46.5693,9.9359,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2265,Tarasp,Inn,46.789,10.2786,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2268,Gletsch,Rhône,46.5623,8.3621,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2269,Blatten,Lonza,46.4189,7.8175,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2270,Combe des Sarrasins,Doubs,47.1951,6.878,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2276,Isenthal,Grosstalbach,46.9101,8.561,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2282,"Wasen, Kurzeneialp",Sperbelgraben,47.0158,7.8427,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2283,"Wasen, Riedbad",Rappengraben,47.0163,7.8903,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2288,"Neuhausen, Flurlingerbrücke",Rhein,47.6815,8.6263,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2289,"Basel, Rheinhalle",Rhein,47.5594,7.6167,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2290,St-Sulpice,Areuse,46.9106,6.5589,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2300,"Euthal, Rüti",Minster,47.0806,8.8138,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2303,"Jonschwil, Mühlau",Thur,47.4137,9.0775,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2304,"Zernez, Punt la Drossa",Ova dal Fuorn,46.6551,10.19,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2305,"Herisau, Zellersmühle",Glatt,47.3981,9.2571,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2307,Sonceboz,Suze,47.1968,7.1722,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2308,"Goldach, Bleiche",Goldach,47.4873,9.4715,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2312,"Salmsach, Hungerbühl",Aach,47.5504,9.3572,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2319,Zernez,Ova da Cluozza,46.6932,10.1183,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2321,Pregassona,Cassarate,46.0177,8.9625,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2327,"Davos, Kriegsmatte",Dischmabach,46.7755,9.8773,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2329,San Giacomo di Fraéle,Derivazione Spöl,46.5489,10.2503,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2342,Brig,Saltina,46.3167,7.9868,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2343,"Huttwil, Häberenbad",Langeten,47.1225,7.8282,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2346,Brig,Rhône,46.3174,7.9754,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2347,"Roveredo, Bacino di compenso",Riale di Roggiasca,46.2016,9.1689,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2349,"Chiasso, Ponte di Polenta",Breggia,45.8455,9.0131,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2351,Visp,Vispa,46.2742,7.8817,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2352,"Linthal, Ausgleichsbecken KLL",Linth,46.9164,8.9915,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2353,"Linthal, Wasserrückgabe KLL",Betriebswasser KLL,46.9172,8.9925,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2355,"Davos, Frauenkirch",Landwasser,46.7578,9.7903,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2356,"Cavergno, Pontit",Riale di Calneggia,46.3696,8.5429,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2364,Piotta,Ticino,46.5167,8.6715,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2366,La Rösa,Poschiavino,46.399,10.0672,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2368,"Locarno, Solduno",Maggia,46.1683,8.7736,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2369,Yvonand,Menthue,46.7768,6.7242,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2370,"Le Noirmont, La Goule",Doubs,47.2292,6.9293,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2371,"Le Chenit, Frontière",Orbe,46.5508,6.1535,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2372,"Mollis, Linthbrücke",Linth,47.1011,9.072,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2374,"Mogelsberg, Aachsäge",Necker,47.3642,9.1214,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2378,"Orbe, Le Chalet",Orbe,46.7276,6.5239,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2384,Simplonpass,Bisse kalte Wasser,46.2459,8.0361,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2386,Frauenfeld,Murg,44.89,-0.1617,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2387,Fürstenau,Hinterrhein,46.7151,9.4473,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2392,Rheinau,Rhein (Oberwasser),47.6391,8.6019,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2403,Cinuos - Chel,Inn,46.6355,10.0209,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2404,"Cinuos-chel, Val Torta",Innabl. EKW,46.6431,10.0321,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2409,"Eggiwil, Heidbüel",Emme,46.8712,7.8047,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2410,Ruggell,Liechtensteiner Binnenkanal,47.2434,9.5225,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2412,"Vuippens, Château",Sionge,46.6585,7.0783,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2414,"Mosnang, Rietholz",Rietholzbach,47.3761,9.0123,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2415,Rheinsfelden,Glatt,47.5735,8.4758,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2416,"Hitzkirch, Richensee",Aabach,47.2201,8.2491,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2417,Oberkirch,Suhre,47.1572,8.1154,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2418,Tiefencastel,Julia,46.6604,9.576,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2419,Reckingen,Rhône,46.4695,8.2447,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2420,"Lumino, Sassello",Moesa,46.2231,9.0558,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2426,Mels,Seez,47.0465,9.4182,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2430,"Sumvitg, Encardens",Rein da Sumvitg,46.6499,8.9907,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2432,"Ecublens, Les Bois",Venoge,46.5353,6.5527,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2433,"Allaman, Le Coulet",Aubonne,46.4733,6.4064,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2434,"Olten, Hammermühle",Dünnern,47.3503,7.893,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2436,"Alpnach, Chilch Erli",Chli Schliere,46.9441,8.2766,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2437,"Ecublens, Eschiens",Parimbot,46.6044,6.8129,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2446,"Gampelen, Zihlbrücke",Zihlkanal,47.0211,7.0342,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2447,Sugiez,Canal de la Broye,46.9637,7.1146,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2450,Zofingen,Wigger,47.2835,7.9354,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2457,"Ringgenberg, Goldswil",Aare,46.694,7.8796,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2458,Valangin,Seyon,47.0111,6.9043,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2461,"Magliaso, Ponte",Magliasina,45.982,8.879,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2462,S-Chanf,Inn,46.6157,9.9952,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2467,Gümmenen,Saane,46.9441,7.2429,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2468,"St. Gallen, Bruggen/Au",Sitter,47.4144,9.3275,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2469,Hondrich,Kander,46.6666,7.6711,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2471,"Murgenthal, Walliswil",Murg,47.2523,7.8262,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2473,"Diepoldsau, Rietbrücke",Rhein,47.3831,9.6409,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2474,Buseno,Calancasca,46.2836,9.1182,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2475,"Bignasco, Ponte nuovo",Maggia,46.3383,8.6081,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2477,"Zug, Letzi",Lorze,47.1807,8.502,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2478,"Soyhières, Bois du Treuil",Birse,47.3924,7.396,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2480,Boudry,Areuse,46.949,6.839,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2481,"Buochs, Flugplatz",Engelberger Aa,46.9728,8.4053,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2484,"Lauerz, Chlostermatt",Lauerzersee,47.031,8.5966,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2485,"Boncourt, Frontière",Allaine,47.5008,7.0117,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2486,"Vevey, Coppet",Veveyse,46.4689,6.8485,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2487,"Werthenstein, Chappelboden",Kleine Emme,47.0349,8.0684,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2488,Latterbach,Simme,46.6617,7.5782,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2490,"Dardagny, Les Granges",Allondon,46.2174,5.9985,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2491,"Bürglen, Galgenwäldli",Schächen,46.8709,8.6517,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2492,"Buerglen, EW Altdorf",Dorfbachableitung,46.8758,8.6592,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2493,"Gland, Route Suisse",Promenthouse,46.406,6.2693,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2494,"Pollegio, Campagna",Ticino,46.3593,8.9475,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2497,Nebikon,Luthern,47.1904,7.9738,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2498,Castrisch,Glenner,46.7735,9.2106,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2499,Muotathal,Schlichenden Brünnen,46.9731,8.7843,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2500,Ittigen,Worble,46.9732,7.4781,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2602,Domat/Ems,Rhein,46.8377,9.4561,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2603,Langnau,Ilfis,46.9379,7.7974,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2604,Biberbrugg,Biber,47.1533,8.7209,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2605,"Lavertezzo, Campiöi",Verzasca,46.249,8.8446,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2606,"Genève, Halle de l'Île",Rhône,46.2047,6.1415,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2607,Oberwald,Goneri,46.532,8.3578,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2608,Neuenkirch,Sellenbodenbach,47.113,8.2098,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2609,Einsiedeln,Alp,47.1508,8.7393,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2610,Vicques,Scheulte,47.3482,7.4318,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2612,Lavertezzo,Riale di Pincascia,46.2583,8.8401,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2613,"Weil, Palmrainbrücke",Rhein,47.6014,7.5947,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2615,Basel LHG,Rhein,47.5617,7.5867,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2617,Müstair,Rom,46.6296,10.4532,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2620,Soglio,Mera,46.3332,9.5268,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2623,Oberwald,Rhône,46.5344,8.3494,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2629,Agno,Vedeggio,46.003,8.9117,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2630,Sion,Sionne,46.2305,7.366,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2631,"Hinterrhein, Schiessplatz",Hinterrhein,46.5234,9.1813,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2632,Mühlbach. Trennbauwerk Sand,Mühlbach,46.8453,9.5373,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2634,Emmen,Kleine Emme,47.072,8.2753,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2635,"Einsiedeln, Gross",Grossbach,47.1065,8.7655,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2636,"Muotathal, Hölloch",Hölloch,46.9764,8.7884,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2639,"Martina, Sclamischot",Inn,46.8704,10.4461,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2640,Delémont,Sorne,47.3643,7.351,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2642,"Neuchâtel, Nid-du-Crô",Lac de Neuchâtel,46.9965,6.951,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2643,Montlingen,Rhein,47.3337,9.5947,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2646,"Emdthal, Heustrich",Kander,46.6525,7.6828,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +2650,Chur,Untertorer Mühlbach,46.8473,9.5356,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +4601,Buch,Biber,47.7151,8.7924,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +520,Rämismühle,Töss,47.443,8.8148,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +9020,Bellinzona,Ticino,46.1938,9.0093,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +9632,Chur,Untertorer Mühlbach,46.8473,9.5356,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +A270,Combe des Sarrasins,Doubs,47.1955,6.8782,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU +C384,Simplonpass,Bisse kalte Wasser,46.2459,8.0361,,,Switzerland,Swiss Federal Office for the Environment FOEN / BAFU diff --git a/rivretrieve/switzerland.py b/rivretrieve/switzerland.py new file mode 100644 index 0000000..f285884 --- /dev/null +++ b/rivretrieve/switzerland.py @@ -0,0 +1,354 @@ +"""Fetcher for Swiss river gauge data from the BAFU hydro API.""" + +import logging +from io import StringIO +from typing import Optional + +import numpy as np +import pandas as pd +import requests + +from . import base, constants, utils + +logger = logging.getLogger(__name__) + + +class SwitzerlandFetcher(base.RiverDataFetcher): + """Fetches Swiss river gauge data from the Existenz.ch BAFU hydro API. + + Data source: + https://api.existenz.ch/#hydro + + Supported variables: + - constants.DISCHARGE_DAILY_MEAN (m³/s) + - constants.DISCHARGE_INSTANT (m³/s) + - constants.STAGE_DAILY_MEAN (m) + - constants.STAGE_INSTANT (m) + - constants.WATER_TEMPERATURE_DAILY_MEAN (°C) + - constants.WATER_TEMPERATURE_INSTANT (°C) + + Data description and API: + - see https://api.existenz.ch/docs/apiv1/ + + Terms of use: + - see https://api.existenz.ch + """ + + BASE_URL = "https://api.existenz.ch/apiv1" + METADATA_URL = f"{BASE_URL}/hydro/locations" + INFLUX_URL = "https://influx.konzept.space/api/v2/query?org=api.existenz.ch" + INFLUX_TOKEN = "0yLbh-D7RMe1sX1iIudFel8CcqCI8sVfuRTaliUp56MgE6kub8-nSd05_EJ4zTTKt0lUzw8zcO73zL9QhC3jtA==" + SOURCE = "Swiss Federal Office for the Environment FOEN / BAFU" + COUNTRY = "Switzerland" + MAX_WINDOW_DAYS = 366 + VARIABLE_MAP = { + constants.DISCHARGE_DAILY_MEAN: { + "parameters": ("flow", "flow_ls"), + "preferred": "flow", + "fallback": "flow_ls", + "aggregate_daily": True, + }, + constants.DISCHARGE_INSTANT: { + "parameters": ("flow", "flow_ls"), + "preferred": "flow", + "fallback": "flow_ls", + "aggregate_daily": False, + }, + constants.STAGE_DAILY_MEAN: { + "parameters": ("height_abs", "height"), + "preferred": "height_abs", + "fallback": "height", + "aggregate_daily": True, + }, + constants.STAGE_INSTANT: { + "parameters": ("height_abs", "height"), + "preferred": "height_abs", + "fallback": "height", + "aggregate_daily": False, + }, + constants.WATER_TEMPERATURE_DAILY_MEAN: { + "parameters": ("temperature",), + "preferred": "temperature", + "fallback": None, + "aggregate_daily": True, + }, + constants.WATER_TEMPERATURE_INSTANT: { + "parameters": ("temperature",), + "preferred": "temperature", + "fallback": None, + "aggregate_daily": False, + }, + } + + @staticmethod + def _empty_result(variable: str) -> pd.DataFrame: + """Returns a standardized empty time series result.""" + return pd.DataFrame(columns=[variable], index=pd.DatetimeIndex([], name=constants.TIME_INDEX)) + + @staticmethod + def get_cached_metadata() -> pd.DataFrame: + """Retrieves cached Swiss gauge metadata.""" + return utils.load_cached_metadata_csv("switzerland") + + @staticmethod + def get_available_variables() -> tuple[str, ...]: + return tuple(SwitzerlandFetcher.VARIABLE_MAP.keys()) + + @classmethod + def _split_windows(cls, start_date: str, end_date: str) -> list[tuple[pd.Timestamp, pd.Timestamp]]: + start = pd.Timestamp(start_date) + end = pd.Timestamp(end_date) + if pd.isna(start) or pd.isna(end) or start > end: + return [] + + windows = [] + current = start + while current <= end: + window_end = min(end, current + pd.Timedelta(days=cls.MAX_WINDOW_DAYS - 1)) + windows.append((current, window_end)) + current = window_end + pd.Timedelta(days=1) + return windows + + @staticmethod + def _empty_metadata_frame() -> pd.DataFrame: + columns = [ + constants.GAUGE_ID, + constants.STATION_NAME, + constants.RIVER, + constants.LATITUDE, + constants.LONGITUDE, + constants.ALTITUDE, + constants.AREA, + constants.COUNTRY, + constants.SOURCE, + ] + return pd.DataFrame(columns=columns).set_index(constants.GAUGE_ID) + + def get_metadata(self) -> pd.DataFrame: + """Fetches site metadata for all stations from the hydro locations endpoint. + + Maps the provider response to the standard RivRetrieve metadata columns and + returns a DataFrame indexed by ``constants.GAUGE_ID``. + """ + session = utils.requests_retry_session() + + try: + response = session.get(self.METADATA_URL, timeout=30) + response.raise_for_status() + data = response.json() + except requests.exceptions.RequestException as exc: + logger.error(f"Failed to fetch Swiss metadata: {exc}") + raise + except ValueError as exc: + logger.error(f"Failed to decode Swiss metadata: {exc}") + raise + + payload = data.get("payload", data) if isinstance(data, dict) else data + if not isinstance(payload, dict) or not payload: + return self._empty_metadata_frame() + + rows = [] + for station_key, station in payload.items(): + details = station.get("details", {}) if isinstance(station, dict) else {} + river = details.get("water-body-name") or details.get("water_body_name") + rows.append( + { + constants.GAUGE_ID: str(details.get("id") or station_key).strip(), + constants.STATION_NAME: details.get("name"), + constants.RIVER: river, + constants.LATITUDE: pd.to_numeric(details.get("lat"), errors="coerce"), + constants.LONGITUDE: pd.to_numeric(details.get("lon"), errors="coerce"), + constants.ALTITUDE: np.nan, + constants.AREA: np.nan, + constants.COUNTRY: self.COUNTRY, + constants.SOURCE: self.SOURCE, + } + ) + + if not rows: + return self._empty_metadata_frame() + + df = pd.DataFrame(rows) + df[constants.GAUGE_ID] = df[constants.GAUGE_ID].astype(str).str.strip() + return df.set_index(constants.GAUGE_ID).sort_index() + + @classmethod + def _build_flux_query( + cls, gauge_id: str, parameter_names: tuple[str, ...], start: pd.Timestamp, end: pd.Timestamp + ) -> str: + fields_expr = " or ".join([f'r["_field"] == "{name}"' for name in parameter_names]) + start_str = start.strftime("%Y-%m-%dT00:00:00Z") + stop_str = (end + pd.Timedelta(days=1)).strftime("%Y-%m-%dT00:00:00Z") + return ( + 'from(bucket: "existenzApi")' + f" |> range(start: {start_str}, stop: {stop_str})" + ' |> filter(fn: (r) => r["_measurement"] == "hydro")' + f' |> filter(fn: (r) => r["loc"] == "{gauge_id}")' + f" |> filter(fn: (r) => {fields_expr})" + ) + + def _download_data(self, gauge_id: str, variable: str, start_date: str, end_date: str) -> list[str]: + """Downloads raw CSV responses from the official InfluxDB archive.""" + config = self.VARIABLE_MAP[variable] + windows = self._split_windows(start_date, end_date) + if not windows: + return [] + + session = utils.requests_retry_session() + payloads: list[str] = [] + headers = { + "Authorization": f"Token {self.INFLUX_TOKEN}", + "Accept": "application/csv", + "Content-type": "application/vnd.flux", + } + + for window_start, window_end in windows: + query = self._build_flux_query(gauge_id, config["parameters"], window_start, window_end) + + try: + response = session.post(self.INFLUX_URL, headers=headers, data=query, timeout=60) + response.raise_for_status() + except requests.exceptions.RequestException as exc: + logger.error(f"Failed to fetch Swiss data for {gauge_id}: {exc}") + raise + + if response.text.strip(): + payloads.append(response.text) + + return payloads + + @staticmethod + def _parse_timeseries_payload(payload: str) -> pd.DataFrame: + if not payload.strip(): + return pd.DataFrame(columns=["station_id", "parameter_code", constants.TIME_INDEX, "value"]) + + df = pd.read_csv(StringIO(payload), comment="#") + if df.empty: + return pd.DataFrame(columns=["station_id", "parameter_code", constants.TIME_INDEX, "value"]) + + required_columns = {"_time", "_value", "_field", "loc"} + if not required_columns.issubset(df.columns): + return pd.DataFrame(columns=["station_id", "parameter_code", constants.TIME_INDEX, "value"]) + + result = pd.DataFrame( + { + "station_id": df["loc"].astype(str), + "parameter_code": df["_field"].astype(str), + constants.TIME_INDEX: pd.to_datetime(df["_time"], utc=True, errors="coerce").dt.tz_localize(None), + "value": pd.to_numeric(df["_value"], errors="coerce"), + } + ) + return result.dropna(subset=[constants.TIME_INDEX, "value"]) + + @classmethod + def _parse_timeseries_payloads(cls, payloads: list[str]) -> pd.DataFrame: + frames = [cls._parse_timeseries_payload(payload) for payload in payloads] + frames = [frame for frame in frames if not frame.empty] + if frames: + return pd.concat(frames, ignore_index=True) + return pd.DataFrame(columns=["station_id", "parameter_code", constants.TIME_INDEX, "value"]) + + @staticmethod + def _apply_parameter_preference(df: pd.DataFrame, preferred: str, fallback: Optional[str]) -> pd.DataFrame: + if df.empty or fallback is None: + return df[df["parameter_code"] == preferred] + + rank_map = {preferred: 0, fallback: 1} + result = df.copy() + result["_rank"] = result["parameter_code"].map(rank_map).fillna(99) + result = result.sort_values([constants.TIME_INDEX, "_rank"]) + result = result.drop_duplicates(subset=[constants.TIME_INDEX], keep="first") + return result.drop(columns="_rank") + + @staticmethod + def _convert_units(df: pd.DataFrame) -> pd.DataFrame: + result = df.copy() + result["value"] = pd.to_numeric(result["value"], errors="coerce").astype(float) + flow_ls_mask = result["parameter_code"] == "flow_ls" + result.loc[flow_ls_mask, "value"] = result.loc[flow_ls_mask, "value"] / 1000.0 + return result + + def _parse_data(self, gauge_id: str, raw_data: list[str], variable: str) -> pd.DataFrame: + """Parses raw Swiss API payloads into the standard RivRetrieve layout.""" + if not raw_data: + return self._empty_result(variable) + + config = self.VARIABLE_MAP[variable] + df = self._parse_timeseries_payloads(raw_data) + if df.empty: + return self._empty_result(variable) + df = df[df["station_id"] == str(gauge_id)] + df = df[df["parameter_code"].isin(config["parameters"])] + df = df.dropna(subset=[constants.TIME_INDEX, "value"]) + if df.empty: + return self._empty_result(variable) + + df = self._apply_parameter_preference(df, config["preferred"], config["fallback"]) + df = self._convert_units(df) + df = df.drop_duplicates(subset=[constants.TIME_INDEX], keep="first").sort_values(constants.TIME_INDEX) + + if config["aggregate_daily"]: + df[constants.TIME_INDEX] = df[constants.TIME_INDEX].dt.floor("D") + df = df.groupby(constants.TIME_INDEX, as_index=False)["value"].mean() + else: + df = df[[constants.TIME_INDEX, "value"]] + + df = df.rename(columns={"value": variable}).dropna(subset=[variable]) + return df.set_index(constants.TIME_INDEX).sort_index() + + def get_data( + self, + gauge_id: str, + variable: str, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + ) -> pd.DataFrame: + """Fetches and parses time series data for a specific gauge and variable. + + This method retrieves the requested data from the provider's API or archive, + parses it, and returns it in a standardized pandas DataFrame format. + + Args: + gauge_id: The site-specific identifier for the gauge. + variable: The variable to fetch. Must be one of the strings listed + in the fetcher's ``get_available_variables()`` output. + These are typically defined in ``rivretrieve.constants``. + start_date: Optional start date for the data retrieval in 'YYYY-MM-DD' format. + If None, data is fetched from the earliest available date. + end_date: Optional end date for the data retrieval in 'YYYY-MM-DD' format. + If None, data is fetched up to the latest available date. + + Returns: + pd.DataFrame: A pandas DataFrame indexed by datetime objects + (``constants.TIME_INDEX``) with a single column named after the + requested ``variable``. The DataFrame will be empty if no data is found + for the given parameters. + + Raises: + ValueError: If the requested ``variable`` is not supported by this fetcher. + requests.exceptions.RequestException: If a network error occurs during data download. + Exception: For other unexpected errors during data fetching or parsing. + """ + start_date = utils.format_start_date(start_date) + end_date = utils.format_end_date(end_date) + + if variable not in self.get_available_variables(): + raise ValueError(f"Unsupported variable: {variable}") + + try: + raw_data = self._download_data(gauge_id, variable, start_date, end_date) + df = self._parse_data(gauge_id, raw_data, variable) + except Exception as exc: + logger.error(f"Failed to get data for site {gauge_id}, variable {variable}: {exc}") + return self._empty_result(variable) + + if df.empty: + return self._empty_result(variable) + + start_dt = pd.to_datetime(start_date) + end_dt = pd.to_datetime(end_date) + if "instantaneous" in variable or "hourly" in variable: + end_dt = end_dt + pd.Timedelta(days=1) + return df[(df.index >= start_dt) & (df.index < end_dt)] + + return df[(df.index >= start_dt) & (df.index <= end_dt)] diff --git a/tests/test_data/switzerland_2016_temperature_20200101.csv b/tests/test_data/switzerland_2016_temperature_20200101.csv new file mode 100644 index 0000000..35c07f4 --- /dev/null +++ b/tests/test_data/switzerland_2016_temperature_20200101.csv @@ -0,0 +1,289 @@ +,result,table,_start,_stop,_time,_value,_field,_measurement,loc +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T00:00:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T00:10:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T00:20:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T00:30:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T00:40:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T00:50:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T01:00:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T01:10:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T01:20:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T01:30:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T01:40:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T01:50:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T02:00:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T02:10:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T02:20:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T02:30:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T02:40:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T02:50:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T03:00:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T03:10:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T03:20:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T03:30:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T03:40:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T03:50:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T04:00:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T04:10:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T04:20:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T04:30:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T04:40:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T04:50:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T05:00:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T05:10:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T05:20:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T05:30:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T05:40:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T05:50:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T06:00:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T06:10:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T06:20:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T06:30:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T06:40:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T06:50:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T07:00:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T07:10:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T07:20:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T07:30:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T07:40:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T07:50:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T08:00:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T08:10:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T08:20:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T08:30:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T08:40:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T08:50:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T09:00:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T09:10:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T09:20:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T09:30:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T09:40:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T09:50:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T10:00:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T10:10:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T10:20:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T10:30:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T10:40:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T10:50:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T11:00:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T11:10:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T11:20:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T11:30:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T11:40:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T11:50:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T12:00:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T12:10:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T12:20:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T12:30:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T12:40:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T12:50:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T13:00:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T13:10:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T13:20:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T13:30:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T13:40:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T13:50:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T14:00:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T14:10:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T14:20:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T14:30:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T14:40:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T14:50:00Z,6.77,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T15:00:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T15:10:00Z,6.77,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T15:20:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T15:30:00Z,6.77,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T15:40:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T15:50:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T16:00:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T16:10:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T16:20:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T16:30:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T16:40:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T16:50:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T17:00:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T17:10:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T17:20:00Z,6.76,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T17:30:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T17:40:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T17:50:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T18:00:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T18:10:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T18:20:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T18:30:00Z,6.75,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T18:40:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T18:50:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T19:00:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T19:10:00Z,6.74,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T19:20:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T19:30:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T19:40:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T19:50:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T20:00:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T20:10:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T20:20:00Z,6.73,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T20:30:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T20:40:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T20:50:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T21:00:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T21:10:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T21:20:00Z,6.72,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T21:30:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T21:40:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T21:50:00Z,6.71,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T22:00:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T22:10:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T22:20:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T22:30:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T22:40:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T22:50:00Z,6.7,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T23:00:00Z,6.69,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T23:10:00Z,6.69,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T23:20:00Z,6.69,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T23:30:00Z,6.68,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T23:40:00Z,6.68,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-01T23:50:00Z,6.68,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T00:00:00Z,6.68,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T00:10:00Z,6.67,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T00:20:00Z,6.67,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T00:30:00Z,6.67,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T00:40:00Z,6.67,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T00:50:00Z,6.66,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T01:00:00Z,6.66,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T01:10:00Z,6.66,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T01:20:00Z,6.66,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T01:30:00Z,6.65,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T01:40:00Z,6.65,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T01:50:00Z,6.65,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T02:00:00Z,6.64,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T02:10:00Z,6.64,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T02:20:00Z,6.64,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T02:30:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T02:40:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T02:50:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T03:00:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T03:10:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T03:20:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T03:30:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T03:40:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T03:50:00Z,6.63,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T04:00:00Z,6.62,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T04:10:00Z,6.62,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T04:20:00Z,6.61,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T04:30:00Z,6.61,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T04:40:00Z,6.61,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T04:50:00Z,6.6,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T05:00:00Z,6.6,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T05:10:00Z,6.6,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T05:20:00Z,6.59,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T05:40:00Z,6.59,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T05:50:00Z,6.58,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T06:00:00Z,6.58,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T06:10:00Z,6.58,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T06:20:00Z,6.57,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T06:30:00Z,6.57,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T06:40:00Z,6.57,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T06:50:00Z,6.57,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T07:00:00Z,6.56,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T07:10:00Z,6.56,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T07:20:00Z,6.56,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T07:30:00Z,6.56,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T07:40:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T07:50:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T08:00:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T08:10:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T08:20:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T08:30:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T08:40:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T08:50:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T09:00:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T09:10:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T09:20:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T09:30:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T09:40:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T09:50:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T10:00:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T10:10:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T10:20:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T10:30:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T10:40:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T10:50:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T11:00:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T11:10:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T11:20:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T11:30:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T11:40:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T11:50:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T12:00:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T12:10:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T12:20:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T12:30:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T12:40:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T12:50:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T13:00:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T13:10:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T13:20:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T13:30:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T13:40:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T13:50:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T14:00:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T14:10:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T14:20:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T14:30:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T14:40:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T14:50:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T15:00:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T15:10:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T15:20:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T15:30:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T15:40:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T15:50:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T16:00:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T16:10:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T16:20:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T16:30:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T16:40:00Z,6.55,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T16:50:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T17:00:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T17:10:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T17:20:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T17:30:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T17:40:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T17:50:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T18:00:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T18:10:00Z,6.54,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T18:20:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T18:30:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T18:40:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T18:50:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T19:00:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T19:10:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T19:20:00Z,6.53,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T19:30:00Z,6.52,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T19:40:00Z,6.52,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T19:50:00Z,6.52,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T20:00:00Z,6.52,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T20:10:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T20:20:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T20:30:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T20:40:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T20:50:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T21:00:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T21:10:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T21:20:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T21:30:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T21:40:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T21:50:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T22:00:00Z,6.5,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T22:10:00Z,6.5,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T22:20:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T22:30:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T22:40:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T22:50:00Z,6.5,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T23:00:00Z,6.5,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T23:10:00Z,6.5,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T23:20:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T23:30:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T23:40:00Z,6.51,temperature,hydro,2016 +,_result,0,2020-01-01T00:00:00Z,2020-01-03T00:00:00Z,2020-01-02T23:50:00Z,6.5,temperature,hydro,2016 + diff --git a/tests/test_data/switzerland_2206_discharge_20250101.csv b/tests/test_data/switzerland_2206_discharge_20250101.csv new file mode 100644 index 0000000..a6bbd27 --- /dev/null +++ b/tests/test_data/switzerland_2206_discharge_20250101.csv @@ -0,0 +1,146 @@ +,result,table,_start,_stop,_time,_value,_field,_measurement,loc +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:20:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:40:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:20:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:50:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:10:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:20:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:30:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:00:00Z,14,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:50:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:00:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:10:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:20:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:30:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:40:00Z,15,flow_ls,hydro,2206 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:50:00Z,15,flow_ls,hydro,2206 + diff --git a/tests/test_data/switzerland_2282_stage_20250101.csv b/tests/test_data/switzerland_2282_stage_20250101.csv new file mode 100644 index 0000000..a436885 --- /dev/null +++ b/tests/test_data/switzerland_2282_stage_20250101.csv @@ -0,0 +1,143 @@ +,result,table,_start,_stop,_time,_value,_field,_measurement,loc +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:20:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:30:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:40:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T00:50:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T01:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T02:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T03:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:00:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:10:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:20:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:30:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:40:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T04:50:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:00:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:10:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:20:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:30:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:40:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T05:50:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:00:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:10:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:20:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:30:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:40:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T06:50:00Z,0.162,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:00:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:10:00Z,0.162,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:20:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:30:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:40:00Z,0.162,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T07:50:00Z,0.162,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:00:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:10:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:20:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:30:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:40:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T08:50:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:00:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:10:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:20:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:30:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:40:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T09:50:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:00:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:10:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:20:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:30:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:40:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T10:50:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:00:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:10:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:20:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:30:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:40:00Z,0.161,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T11:50:00Z,0.162,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:00:00Z,0.162,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:10:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:20:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:30:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T12:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:00:00Z,0.163,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T13:50:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:20:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:30:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:40:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T14:50:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:20:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:30:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:40:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T15:50:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:20:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:30:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:40:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T16:50:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:20:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:30:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:40:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T17:50:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:00:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:10:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:20:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:30:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:40:00Z,0.165,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T18:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T19:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T20:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T21:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:20:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T22:50:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:00:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:10:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:30:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:40:00Z,0.164,height_abs,hydro,2282 +,_result,0,2025-01-01T00:00:00Z,2025-01-02T00:00:00Z,2025-01-01T23:50:00Z,0.164,height_abs,hydro,2282 + diff --git a/tests/test_data/switzerland_metadata_locations.json b/tests/test_data/switzerland_metadata_locations.json new file mode 100644 index 0000000..ad089bb --- /dev/null +++ b/tests/test_data/switzerland_metadata_locations.json @@ -0,0 +1 @@ +{"source":"Swiss Federal Office for the Environment FOEN \/ BAFU, Hydrology","apiurl":"https:\/\/api.existenz.ch#hydro","opendata":"https:\/\/opendata.swiss\/en\/dataset\/wassertemperatur-der-flusse","license":"https:\/\/www.bafu.admin.ch\/dam\/bafu\/de\/dokumente\/wasser\/fachinfo-daten\/liefer-nutzungsbedingungen-hydrologische-daten.pdf.download.pdf\/Liefer-%20und%20Nutzungsbedingungen%20hydrologische%20Daten%20BAFU%202020.pdf","payload":{"2004":{"id":1,"name":"2004","details":{"id":"2004","name":"Murten","water-body-name":"Murtensee","water-body-type":"lake","chx":575500,"chy":197790,"lat":46.9308,"lon":7.1169}},"2007":{"id":2,"name":"2007","details":{"id":"2007","name":"Le Pont","water-body-name":"Lac de Joux","water-body-type":"lake","chx":514700,"chy":168840,"lat":46.6653,"lon":6.324}},"2009":{"id":3,"name":"2009","details":{"id":"2009","name":"Porte du Scex","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":557660,"chy":133280,"lat":46.3496,"lon":6.8886}},"2011":{"id":4,"name":"2011","details":{"id":"2011","name":"Sion","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":593770,"chy":118630,"lat":46.2191,"lon":7.3579}},"2014":{"id":5,"name":"2014","details":{"id":"2014","name":"Schmerikon","water-body-name":"Z\u00fcrichsee","water-body-type":"lake","chx":713710,"chy":231515,"lat":47.2248,"lon":8.9401}},"2016":{"id":6,"name":"2016","details":{"id":"2016","name":"Brugg","water-body-name":"Aare","water-body-type":"river","chx":657000,"chy":259360,"lat":47.4825,"lon":8.1949}},"2017":{"id":7,"name":"2017","details":{"id":"2017","name":"Zug","water-body-name":"Zugersee","water-body-type":"lake","chx":681555,"chy":224660,"lat":47.1679,"lon":8.5143}},"2018":{"id":8,"name":"2018","details":{"id":"2018","name":"Mellingen","water-body-name":"Reuss","water-body-type":"river","chx":662830,"chy":252580,"lat":47.421,"lon":8.2713}},"2019":{"id":9,"name":"2019","details":{"id":"2019","name":"Brienzwiler","water-body-name":"Aare","water-body-type":"river","chx":649930,"chy":177380,"lat":46.7457,"lon":8.092}},"2020":{"id":10,"name":"2020","details":{"id":"2020","name":"Bellinzona","water-body-name":"Ticino","water-body-type":"river","chx":721245,"chy":117025,"lat":46.1938,"lon":9.0093}},"2021":{"id":11,"name":"2021","details":{"id":"2021","name":"Ponte Tresa","water-body-name":"Lago di Lugano","water-body-type":"lake","chx":710200,"chy":91800,"lat":45.9688,"lon":8.8603}},"2022":{"id":12,"name":"2022","details":{"id":"2022","name":"Locarno","water-body-name":"Lago Maggiore","water-body-type":"lake","chx":705480,"chy":113380,"lat":46.1636,"lon":8.8043}},"2023":{"id":13,"name":"2023","details":{"id":"2023","name":"Ringgenberg","water-body-name":"Brienzersee","water-body-type":"lake","chx":641040,"chy":175555,"lat":46.7299,"lon":7.9755}},"2024":{"id":14,"name":"2024","details":{"id":"2024","name":"Branson","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":573150,"chy":108300,"lat":46.1257,"lon":7.0913}},"2025":{"id":15,"name":"2025","details":{"id":"2025","name":"Brunnen","water-body-name":"Vierwaldst\u00e4ttersee","water-body-type":"lake","chx":688625,"chy":205370,"lat":46.9935,"lon":8.6038}},"2026":{"id":1425,"name":"2026","details":{"id":"2026","name":"Chillon","water-body-name":"Lac L\u00e9man","water-body-type":"lake","chx":560720,"chy":140490,"lat":46.4146,"lon":6.9277}},"2027":{"id":16,"name":"2027","details":{"id":"2027","name":"St-Prex","water-body-name":"Lac L\u00e9man","water-body-type":"lake","chx":524940,"chy":148410,"lat":46.4828,"lon":6.4611}},"2028":{"id":17,"name":"2028","details":{"id":"2028","name":"Gen\u00e8ve, S\u00e9cheron","water-body-name":"Lac L\u00e9man","water-body-type":"lake","chx":500750,"chy":119390,"lat":46.2186,"lon":6.1524}},"2029":{"id":18,"name":"2029","details":{"id":"2029","name":"Br\u00fcgg, Aegerten","water-body-name":"Aare","water-body-type":"river","chx":588220,"chy":219020,"lat":47.1221,"lon":7.2834}},"2030":{"id":19,"name":"2030","details":{"id":"2030","name":"Thun","water-body-name":"Aare","water-body-type":"river","chx":613230,"chy":179280,"lat":46.7646,"lon":7.6118}},"2031":{"id":20,"name":"2031","details":{"id":"2031","name":"Unter\u00e4geri","water-body-name":"Aegerisee","water-body-type":"lake","chx":687480,"chy":221420,"lat":47.138,"lon":8.5918}},"2032":{"id":21,"name":"2032","details":{"id":"2032","name":"Romanshorn","water-body-name":"Bodensee, Obersee","water-body-type":"lake","chx":746160,"chy":270040,"lat":47.5648,"lon":9.381}},"2033":{"id":22,"name":"2033","details":{"id":"2033","name":"Ilanz","water-body-name":"Vorderrhein","water-body-type":"river","chx":735000,"chy":182030,"lat":46.7758,"lon":9.2064}},"2034":{"id":23,"name":"2034","details":{"id":"2034","name":"Payerne, Caserne d'aviation","water-body-name":"Broye","water-body-type":"river","chx":561660,"chy":187320,"lat":46.8359,"lon":6.9361}},"2041":{"id":24,"name":"2041","details":{"id":"2041","name":"Oberriet, Blatten","water-body-name":"Rhein","water-body-type":"river","chx":761215,"chy":241750,"lat":47.3069,"lon":9.5708}},"2043":{"id":25,"name":"2043","details":{"id":"2043","name":"Berlingen","water-body-name":"Bodensee, Untersee","water-body-type":"lake","chx":718570,"chy":281730,"lat":47.6755,"lon":9.0176}},"2044":{"id":26,"name":"2044","details":{"id":"2044","name":"Andelfingen","water-body-name":"Thur","water-body-type":"river","chx":693510,"chy":272500,"lat":47.5965,"lon":8.682}},"2053":{"id":27,"name":"2053","details":{"id":"2053","name":"Martigny, Pont de Rossettan","water-body-name":"Drance","water-body-type":"river","chx":570930,"chy":105200,"lat":46.0977,"lon":7.0627}},"2056":{"id":28,"name":"2056","details":{"id":"2056","name":"Seedorf","water-body-name":"Reuss","water-body-type":"river","chx":690085,"chy":193210,"lat":46.8839,"lon":8.6206}},"2057":{"id":29,"name":"2057","details":{"id":"2057","name":"Les Brenets","water-body-name":"Lac des Brenets","water-body-type":"lake","chx":544560,"chy":214880,"lat":47.0826,"lon":6.7086}},"2063":{"id":30,"name":"2063","details":{"id":"2063","name":"Murgenthal","water-body-name":"Aare","water-body-type":"river","chx":629530,"chy":235090,"lat":47.2661,"lon":7.8288}},"2066":{"id":31,"name":"2066","details":{"id":"2066","name":"St. Moritz","water-body-name":"St. Moritzersee","water-body-type":"lake","chx":784940,"chy":152420,"lat":46.4975,"lon":9.8481}},"2067":{"id":32,"name":"2067","details":{"id":"2067","name":"Martina","water-body-name":"Inn","water-body-type":"river","chx":830640,"chy":197190,"lat":46.8858,"lon":10.4654}},"2068":{"id":33,"name":"2068","details":{"id":"2068","name":"Riazzino","water-body-name":"Ticino","water-body-type":"river","chx":713670,"chy":113500,"lat":46.1634,"lon":8.9103}},"2070":{"id":34,"name":"2070","details":{"id":"2070","name":"Emmenmatt","water-body-name":"Emme","water-body-type":"river","chx":623610,"chy":200420,"lat":46.9544,"lon":7.7488}},"2071":{"id":35,"name":"2071","details":{"id":2071,"name":"Emmenmatt (N)","water-body-name":"Emme","water-body-type":"river","chx":623820,"chy":200325,"lat":46.9536,"lon":7.7516}},"2072":{"id":36,"name":"2072","details":{"id":"2072","name":"Sils Baselgia","water-body-name":"Silsersee","water-body-type":"lake","chx":777870,"chy":145180,"lat":46.4344,"lon":9.7532}},"2073":{"id":37,"name":"2073","details":{"id":"2073","name":"Silvaplana","water-body-name":"Silvaplanersee","water-body-type":"lake","chx":781560,"chy":148150,"lat":46.4601,"lon":9.8024}},"2074":{"id":38,"name":"2074","details":{"id":"2074","name":"Brissago","water-body-name":"Lago Maggiore","water-body-type":"lake","chx":698350,"chy":108200,"lat":46.1181,"lon":8.7109}},"2078":{"id":39,"name":"2078","details":{"id":"2078","name":"Le Prese","water-body-name":"Poschiavino","water-body-type":"river","chx":803490,"chy":130530,"lat":46.2954,"lon":10.08}},"2079":{"id":40,"name":"2079","details":{"id":"2079","name":"Le Prese","water-body-name":"Canale industriale","water-body-type":"river","chx":803460,"chy":130460,"lat":46.2947,"lon":10.0795}},"2081":{"id":41,"name":"2081","details":{"id":"2081","name":"Pf\u00e4ffikon","water-body-name":"Pf\u00e4ffikersee","water-body-type":"lake","chx":701220,"chy":246775,"lat":47.364,"lon":8.7786}},"2082":{"id":42,"name":"2082","details":{"id":"2082","name":"Greifensee","water-body-name":"Greifensee","water-body-type":"lake","chx":693280,"chy":246775,"lat":47.3652,"lon":8.6735}},"2084":{"id":43,"name":"2084","details":{"id":"2084","name":"Ingenbohl","water-body-name":"Muota","water-body-type":"river","chx":688230,"chy":206140,"lat":47.0004,"lon":8.5987}},"2085":{"id":44,"name":"2085","details":{"id":"2085","name":"Hagneck","water-body-name":"Aare","water-body-type":"river","chx":580680,"chy":211650,"lat":47.0556,"lon":7.1844}},"2086":{"id":45,"name":"2086","details":{"id":"2086","name":"Loderio","water-body-name":"Brenno","water-body-type":"river","chx":717770,"chy":137270,"lat":46.3765,"lon":8.9694}},"2087":{"id":46,"name":"2087","details":{"id":"2087","name":"Andermatt","water-body-name":"Reuss","water-body-type":"river","chx":688120,"chy":166320,"lat":46.6423,"lon":8.5896}},"2088":{"id":47,"name":"2088","details":{"id":"2088","name":"Sarnen","water-body-name":"Sarnersee","water-body-type":"lake","chx":661260,"chy":193270,"lat":46.8877,"lon":8.2424}},"2091":{"id":48,"name":"2091","details":{"id":"2091","name":"Rheinfelden","water-body-name":"Rhein","water-body-type":"river","chx":627190,"chy":267840,"lat":47.5607,"lon":7.7999}},"2093":{"id":49,"name":"2093","details":{"id":"2093","name":"Spiez","water-body-name":"Thunersee","water-body-type":"lake","chx":617280,"chy":171750,"lat":46.6967,"lon":7.6646}},"2097":{"id":50,"name":"2097","details":{"id":"2097","name":"Meisterschwanden","water-body-name":"Hallwilersee","water-body-type":"lake","chx":659125,"chy":238615,"lat":47.2958,"lon":8.2203}},"2099":{"id":51,"name":"2099","details":{"id":"2099","name":"Z\u00fcrich Unterhard","water-body-name":"Limmat","water-body-type":"river","chx":682055,"chy":249430,"lat":47.3906,"lon":8.5254}},"2101":{"id":52,"name":"2101","details":{"id":"2101","name":"Melide, Ferrera","water-body-name":"Lago di Lugano","water-body-type":"lake","chx":717070,"chy":91650,"lat":45.9663,"lon":8.9489}},"2102":{"id":53,"name":"2102","details":{"id":"2102","name":"Sarnen","water-body-name":"Sarner Aa","water-body-type":"river","chx":661460,"chy":194220,"lat":46.8962,"lon":8.2452}},"2104":{"id":54,"name":"2104","details":{"id":"2104","name":"Weesen, Bi\u00e4sche","water-body-name":"Linth","water-body-type":"river","chx":725160,"chy":221380,"lat":47.1316,"lon":9.0884}},"2105":{"id":55,"name":"2105","details":{"id":"2105","name":"St. Moritzbad","water-body-name":"Inn","water-body-type":"river","chx":783910,"chy":150960,"lat":46.4847,"lon":9.8341}},"2106":{"id":56,"name":"2106","details":{"id":"2106","name":"M\u00fcnchenstein, Hofmatt","water-body-name":"Birs","water-body-type":"river","chx":613570,"chy":263080,"lat":47.5183,"lon":7.6188}},"2109":{"id":57,"name":"2109","details":{"id":"2109","name":"Gsteig","water-body-name":"L\u00fctschine","water-body-type":"river","chx":633130,"chy":168200,"lat":46.6642,"lon":7.8715}},"2110":{"id":58,"name":"2110","details":{"id":"2110","name":"M\u00fchlau, H\u00fcnenberg","water-body-name":"Reuss","water-body-type":"river","chx":672520,"chy":230600,"lat":47.2223,"lon":8.3961}},"2112":{"id":59,"name":"2112","details":{"id":"2112","name":"Appenzell","water-body-name":"Sitter","water-body-type":"river","chx":749040,"chy":244220,"lat":47.332,"lon":9.4106}},"2113":{"id":60,"name":"2113","details":{"id":"2113","name":"Klingnau","water-body-name":"Aare","water-body-type":"river","chx":659150,"chy":271790,"lat":47.5941,"lon":8.2251}},"2116":{"id":61,"name":"2116","details":{"id":"2116","name":"Koblenz","water-body-name":"Rhein","water-body-type":"river","chx":659830,"chy":273450,"lat":47.609,"lon":8.2343}},"2117":{"id":62,"name":"2117","details":{"id":"2117","name":"Le Ch\u00e2ble, Villette","water-body-name":"Drance de Bagnes","water-body-type":"river","chx":582550,"chy":103270,"lat":46.0807,"lon":7.2131}},"2118":{"id":63,"name":"2118","details":{"id":"2118","name":"Murg","water-body-name":"Walensee","water-body-type":"lake","chx":734430,"chy":219560,"lat":47.1134,"lon":9.21}},"2119":{"id":64,"name":"2119","details":{"id":"2119","name":"Fribourg","water-body-name":"Sarine","water-body-type":"river","chx":579420,"chy":183670,"lat":46.8039,"lon":7.169}},"2122":{"id":65,"name":"2122","details":{"id":"2122","name":"Moutier, La Charrue","water-body-name":"Birse","water-body-type":"river","chx":595740,"chy":237010,"lat":47.284,"lon":7.3823}},"2125":{"id":66,"name":"2125","details":{"id":"2125","name":"Frauenthal","water-body-name":"Lorze","water-body-type":"river","chx":674715,"chy":229845,"lat":47.2153,"lon":8.425}},"2126":{"id":67,"name":"2126","details":{"id":"2126","name":"W\u00e4ngi","water-body-name":"Murg","water-body-type":"river","chx":714105,"chy":261720,"lat":47.4963,"lon":8.953}},"2130":{"id":68,"name":"2130","details":{"id":"2130","name":"Laufenburg","water-body-name":"Rhein (Oberwasser)","water-body-type":"river","chx":646000,"chy":267410,"lat":47.5558,"lon":8.0498}},"2132":{"id":69,"name":"2132","details":{"id":"2132","name":"Neftenbach","water-body-name":"T\u00f6ss","water-body-type":"river","chx":691461,"chy":263820,"lat":47.5188,"lon":8.653}},"2135":{"id":70,"name":"2135","details":{"id":"2135","name":"Bern, Sch\u00f6nau","water-body-name":"Aare","water-body-type":"river","chx":600710,"chy":198000,"lat":46.9331,"lon":7.448}},"2137":{"id":71,"name":"2137","details":{"id":"2137","name":"Gelfingen","water-body-name":"Baldeggersee","water-body-type":"lake","chx":662710,"chy":229100,"lat":47.2099,"lon":8.2664}},"2139":{"id":72,"name":"2139","details":{"id":"2139","name":"St.Margrethen","water-body-name":"Rheintaler Binnenkanal","water-body-type":"river","chx":767160,"chy":257780,"lat":47.4496,"lon":9.6553}},"2141":{"id":73,"name":"2141","details":{"id":"2141","name":"Tiefencastel","water-body-name":"Albula","water-body-type":"river","chx":763420,"chy":170145,"lat":46.6625,"lon":9.5741}},"2143":{"id":74,"name":"2143","details":{"id":"2143","name":"Rekingen","water-body-name":"Rhein","water-body-type":"river","chx":667060,"chy":269230,"lat":47.5703,"lon":8.3298}},"2150":{"id":75,"name":"2150","details":{"id":"2150","name":"Felsenbach","water-body-name":"Landquart","water-body-type":"river","chx":765365,"chy":204910,"lat":46.9746,"lon":9.6121}},"2151":{"id":76,"name":"2151","details":{"id":"2151","name":"Oberwil","water-body-name":"Simme","water-body-type":"river","chx":600060,"chy":167090,"lat":46.655,"lon":7.4394}},"2152":{"id":77,"name":"2152","details":{"id":"2152","name":"Luzern, Geissmattbr\u00fccke","water-body-name":"Reuss","water-body-type":"river","chx":665330,"chy":211800,"lat":47.054,"lon":8.2985}},"2154":{"id":78,"name":"2154","details":{"id":"2154","name":"Grandson","water-body-name":"Lac de Neuch\u00e2tel","water-body-type":"lake","chx":539220,"chy":184155,"lat":46.8058,"lon":6.6424}},"2155":{"id":79,"name":"2155","details":{"id":"2155","name":"Wiler, Limpachm\u00fcndung","water-body-name":"Emme","water-body-type":"river","chx":608220,"chy":223240,"lat":47.1601,"lon":7.547}},"2156":{"id":80,"name":"2156","details":{"id":"2156","name":"Gerlafingen","water-body-name":"Werkkanal","water-body-type":"river","chx":608770,"chy":223650,"lat":47.1638,"lon":7.5543}},"2157":{"id":81,"name":"2157","details":{"id":"2157","name":"Gerlafingen","water-body-name":"Strackbach","water-body-type":"river","chx":609270,"chy":223300,"lat":47.1606,"lon":7.5609}},"2159":{"id":82,"name":"2159","details":{"id":"2159","name":"Belp, M\u00fclimatt","water-body-name":"G\u00fcrbe","water-body-type":"river","chx":604810,"chy":192680,"lat":46.8852,"lon":7.5017}},"2160":{"id":83,"name":"2160","details":{"id":"2160","name":"Broc, Ch\u00e2teau d'en bas","water-body-name":"Sarine","water-body-type":"river","chx":573520,"chy":161345,"lat":46.6028,"lon":7.093}},"2161":{"id":84,"name":"2161","details":{"id":"2161","name":"Blatten bei Naters","water-body-name":"Massa","water-body-type":"river","chx":643700,"chy":137290,"lat":46.3856,"lon":8.0067}},"2167":{"id":85,"name":"2167","details":{"id":"2167","name":"Ponte Tresa, Rocchetta","water-body-name":"Tresa","water-body-type":"river","chx":709580,"chy":92145,"lat":45.972,"lon":8.8524}},"2168":{"id":86,"name":"2168","details":{"id":"2168","name":"Sempach","water-body-name":"Sempachersee","water-body-type":"lake","chx":656940,"chy":220640,"lat":47.1343,"lon":8.1892}},"2170":{"id":87,"name":"2170","details":{"id":"2170","name":"Gen\u00e8ve, Bout du Monde","water-body-name":"Arve","water-body-type":"river","chx":501220,"chy":115120,"lat":46.1803,"lon":6.1593}},"2174":{"id":88,"name":"2174","details":{"id":"2174","name":"Chancy, Aux Ripes","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":486600,"chy":112340,"lat":46.153,"lon":5.9707}},"2176":{"id":89,"name":"2176","details":{"id":"2176","name":"Z\u00fcrich","water-body-name":"Sihl","water-body-type":"river","chx":682145,"chy":246890,"lat":47.3677,"lon":8.5262}},"2179":{"id":90,"name":"2179","details":{"id":"2179","name":"Th\u00f6rishaus, Sensematt","water-body-name":"Sense","water-body-type":"river","chx":593350,"chy":193020,"lat":46.8883,"lon":7.3514}},"2181":{"id":91,"name":"2181","details":{"id":"2181","name":"Halden","water-body-name":"Thur","water-body-type":"river","chx":733560,"chy":263180,"lat":47.5058,"lon":9.2115}},"2185":{"id":92,"name":"2185","details":{"id":"2185","name":"Chur","water-body-name":"Plessur","water-body-type":"river","chx":757975,"chy":191925,"lat":46.8597,"lon":9.5105}},"2187":{"id":93,"name":"2187","details":{"id":"2187","name":"Salez","water-body-name":"Werdenberger Binnenkanal","water-body-type":"river","chx":756795,"chy":234005,"lat":47.2383,"lon":9.5096}},"2199":{"id":94,"name":"2199","details":{"id":"2199","name":"Basel","water-body-name":"Wiese","water-body-type":"river","chx":611800,"chy":269700,"lat":47.5779,"lon":7.5955}},"2200":{"id":95,"name":"2200","details":{"id":"2200","name":"Zweil\u00fctschinen","water-body-name":"Weisse L\u00fctschine","water-body-type":"river","chx":635310,"chy":164550,"lat":46.6313,"lon":7.8997}},"2202":{"id":96,"name":"2202","details":{"id":"2202","name":"Liestal","water-body-name":"Ergolz","water-body-type":"river","chx":622270,"chy":259750,"lat":47.4881,"lon":7.7341}},"2203":{"id":97,"name":"2203","details":{"id":"2203","name":"Aigle","water-body-name":"Grande Eau","water-body-type":"river","chx":563975,"chy":129825,"lat":46.3189,"lon":6.9709}},"2205":{"id":98,"name":"2205","details":{"id":"2205","name":"Untersiggenthal, Stilli","water-body-name":"Aare","water-body-type":"river","chx":659965,"chy":263100,"lat":47.5159,"lon":8.2347}},"2206":{"id":99,"name":"2206","details":{"id":"2206","name":"Melera, (Valle Morobbia)","water-body-name":"Melera","water-body-type":"river","chx":726988,"chy":114670,"lat":46.1715,"lon":9.083}},"2207":{"id":100,"name":"2207","details":{"id":"2207","name":"Luzern","water-body-name":"Vierwaldst\u00e4ttersee","water-body-type":"lake","chx":666950,"chy":211915,"lat":47.0549,"lon":8.3198}},"2208":{"id":101,"name":"2208","details":{"id":"2208","name":"Ligerz, Klein Twann","water-body-name":"Bielersee","water-body-type":"lake","chx":578320,"chy":215670,"lat":47.0917,"lon":7.1531}},"2209":{"id":102,"name":"2209","details":{"id":"2209","name":"Z\u00fcrich","water-body-name":"Z\u00fcrichsee","water-body-type":"lake","chx":684000,"chy":245475,"lat":47.3548,"lon":8.5505}},"2210":{"id":103,"name":"2210","details":{"id":"2210","name":"Ocourt","water-body-name":"Doubs","water-body-type":"river","chx":572530,"chy":244460,"lat":47.3504,"lon":7.0751}},"2215":{"id":104,"name":"2215","details":{"id":"2215","name":"Laupen","water-body-name":"Saane","water-body-type":"river","chx":584440,"chy":195300,"lat":46.9086,"lon":7.2344}},"2217":{"id":105,"name":"2217","details":{"id":"2217","name":"Chancy, Vers Vaux","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":485440,"chy":110040,"lat":46.1321,"lon":5.9563}},"2219":{"id":106,"name":"2219","details":{"id":"2219","name":"Oberried\/Lenk","water-body-name":"Simme","water-body-type":"river","chx":602630,"chy":141660,"lat":46.4263,"lon":7.4729}},"2232":{"id":107,"name":"2232","details":{"id":"2232","name":"Adelboden","water-body-name":"Allenbach","water-body-type":"river","chx":608710,"chy":148300,"lat":46.486,"lon":7.5521}},"2239":{"id":108,"name":"2239","details":{"id":"2239","name":"Punt dal Gall","water-body-name":"Sp\u00f6l","water-body-type":"river","chx":811020,"chy":167920,"lat":46.6292,"lon":10.1947}},"2243":{"id":109,"name":"2243","details":{"id":"2243","name":"Baden, Limmatpromenade","water-body-name":"Limmat","water-body-type":"river","chx":665640,"chy":258690,"lat":47.4757,"lon":8.3094}},"2244":{"id":110,"name":"2244","details":{"id":"2244","name":"Klusmatten","water-body-name":"Krummbach","water-body-type":"river","chx":644500,"chy":119420,"lat":46.2248,"lon":8.0154}},"2247":{"id":111,"name":"2247","details":{"id":"2247","name":"Les Brenets","water-body-name":"Doubs","water-body-type":"river","chx":544690,"chy":215083,"lat":47.0844,"lon":6.7103}},"2251":{"id":112,"name":"2251","details":{"id":"2251","name":"Plaffeien, Schwyberg","water-body-name":"Rotenbach","water-body-type":"river","chx":587986,"chy":170584,"lat":46.6864,"lon":7.2816}},"2252":{"id":113,"name":"2252","details":{"id":"2252","name":"Plaffeien, Schwyberg","water-body-name":"Schw\u00e4ndlibach","water-body-type":"river","chx":588348,"chy":171022,"lat":46.6903,"lon":7.2863}},"2256":{"id":114,"name":"2256","details":{"id":"2256","name":"Pontresina","water-body-name":"Rosegbach","water-body-type":"river","chx":788810,"chy":151690,"lat":46.4899,"lon":9.8981}},"2262":{"id":115,"name":"2262","details":{"id":"2262","name":"Pontresina","water-body-name":"Berninabach","water-body-type":"river","chx":789440,"chy":151320,"lat":46.4864,"lon":9.9062}},"2263":{"id":116,"name":"2263","details":{"id":"2263","name":"La Punt-Chamues-ch","water-body-name":"Chamuerabach","water-body-type":"river","chx":791430,"chy":160600,"lat":46.5693,"lon":9.9359}},"2265":{"id":117,"name":"2265","details":{"id":"2265","name":"Tarasp","water-body-name":"Inn","water-body-type":"river","chx":816800,"chy":185910,"lat":46.789,"lon":10.2786}},"2268":{"id":118,"name":"2268","details":{"id":"2268","name":"Gletsch","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":670810,"chy":157200,"lat":46.5623,"lon":8.3621}},"2269":{"id":119,"name":"2269","details":{"id":"2269","name":"Blatten","water-body-name":"Lonza","water-body-type":"river","chx":629130,"chy":140910,"lat":46.4189,"lon":7.8175}},"2270":{"id":120,"name":"2270","details":{"id":"2270","name":"Combe des Sarrasins","water-body-name":"Doubs","water-body-type":"river","chx":557513,"chy":227284,"lat":47.1951,"lon":6.878}},"2276":{"id":121,"name":"2276","details":{"id":"2276","name":"Isenthal","water-body-name":"Grosstalbach","water-body-type":"river","chx":685500,"chy":196050,"lat":46.9101,"lon":8.561}},"2282":{"id":122,"name":"2282","details":{"id":"2282","name":"Wasen, Kurzeneialp","water-body-name":"Sperbelgraben","water-body-type":"river","chx":630725,"chy":207270,"lat":47.0158,"lon":7.8427}},"2283":{"id":123,"name":"2283","details":{"id":"2283","name":"Wasen, Riedbad","water-body-name":"Rappengraben","water-body-type":"river","chx":634340,"chy":207350,"lat":47.0163,"lon":7.8903}},"2288":{"id":124,"name":"2288","details":{"id":"2288","name":"Neuhausen, Flurlingerbr\u00fccke","water-body-name":"Rhein","water-body-type":"river","chx":689180,"chy":281880,"lat":47.6815,"lon":8.6263}},"2289":{"id":125,"name":"2289","details":{"id":"2289","name":"Basel, Rheinhalle","water-body-name":"Rhein","water-body-type":"river","chx":613400,"chy":267650,"lat":47.5594,"lon":7.6167}},"2290":{"id":126,"name":"2290","details":{"id":"2290","name":"St-Sulpice","water-body-name":"Areuse","water-body-type":"river","chx":532980,"chy":195880,"lat":46.9106,"lon":6.5589}},"2300":{"id":127,"name":"2300","details":{"id":"2300","name":"Euthal, R\u00fcti","water-body-name":"Minster","water-body-type":"river","chx":704425,"chy":215310,"lat":47.0806,"lon":8.8138}},"2303":{"id":128,"name":"2303","details":{"id":"2303","name":"Jonschwil, M\u00fchlau","water-body-name":"Thur","water-body-type":"river","chx":723675,"chy":252720,"lat":47.4137,"lon":9.0775}},"2304":{"id":129,"name":"2304","details":{"id":"2304","name":"Zernez, Punt la Drossa","water-body-name":"Ova dal Fuorn","water-body-type":"river","chx":810560,"chy":170790,"lat":46.6551,"lon":10.19}},"2305":{"id":130,"name":"2305","details":{"id":"2305","name":"Herisau, Zellersm\u00fchle","water-body-name":"Glatt","water-body-type":"river","chx":737270,"chy":251290,"lat":47.3981,"lon":9.2571}},"2307":{"id":131,"name":"2307","details":{"id":"2307","name":"Sonceboz","water-body-name":"Suze","water-body-type":"river","chx":579810,"chy":227350,"lat":47.1968,"lon":7.1722}},"2308":{"id":132,"name":"2308","details":{"id":"2308","name":"Goldach, Bleiche","water-body-name":"Goldach","water-body-type":"river","chx":753190,"chy":261600,"lat":47.4873,"lon":9.4715}},"2312":{"id":133,"name":"2312","details":{"id":"2312","name":"Salmsach, Hungerb\u00fchl","water-body-name":"Aach","water-body-type":"river","chx":744410,"chy":268400,"lat":47.5504,"lon":9.3572}},"2319":{"id":134,"name":"2319","details":{"id":"2319","name":"Zernez","water-body-name":"Ova da Cluozza","water-body-type":"river","chx":804930,"chy":174830,"lat":46.6932,"lon":10.1183}},"2321":{"id":135,"name":"2321","details":{"id":"2321","name":"Pregassona","water-body-name":"Cassarate","water-body-type":"river","chx":718010,"chy":97380,"lat":46.0177,"lon":8.9625}},"2327":{"id":136,"name":"2327","details":{"id":"2327","name":"Davos, Kriegsmatte","water-body-name":"Dischmabach","water-body-type":"river","chx":786220,"chy":183370,"lat":46.7755,"lon":9.8773}},"2329":{"id":137,"name":"2329","details":{"id":"2329","name":"San Giacomo di Fra\u00e9le","water-body-name":"Derivazione Sp\u00f6l","water-body-type":"river","chx":815600,"chy":159150,"lat":46.5489,"lon":10.2503}},"2342":{"id":138,"name":"2342","details":{"id":"2342","name":"Brig","water-body-name":"Saltina","water-body-type":"river","chx":642220,"chy":129630,"lat":46.3167,"lon":7.9868}},"2343":{"id":139,"name":"2343","details":{"id":"2343","name":"Huttwil, H\u00e4berenbad","water-body-name":"Langeten","water-body-type":"river","chx":629560,"chy":219135,"lat":47.1225,"lon":7.8282}},"2346":{"id":140,"name":"2346","details":{"id":"2346","name":"Brig","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":641340,"chy":129700,"lat":46.3174,"lon":7.9754}},"2347":{"id":141,"name":"2347","details":{"id":"2347","name":"Roveredo, Bacino di compenso","water-body-name":"Riale di Roggiasca","water-body-type":"river","chx":733545,"chy":118160,"lat":46.2016,"lon":9.1689}},"2349":{"id":142,"name":"2349","details":{"id":"2349","name":"Chiasso, Ponte di Polenta","water-body-name":"Breggia","water-body-type":"river","chx":722315,"chy":78320,"lat":45.8455,"lon":9.0131}},"2351":{"id":143,"name":"2351","details":{"id":"2351","name":"Visp","water-body-name":"Vispa","water-body-type":"river","chx":634150,"chy":124850,"lat":46.2742,"lon":7.8817}},"2352":{"id":144,"name":"2352","details":{"id":"2352","name":"Linthal, Ausgleichsbecken KLL","water-body-name":"Linth","water-body-type":"river","chx":718285,"chy":197310,"lat":46.9164,"lon":8.9915}},"2353":{"id":145,"name":"2353","details":{"id":"2353","name":"Linthal, Wasserr\u00fcckgabe KLL","water-body-name":"Betriebswasser KLL","water-body-type":"river","chx":718360,"chy":197409,"lat":46.9172,"lon":8.9925}},"2355":{"id":146,"name":"2355","details":{"id":"2355","name":"Davos, Frauenkirch","water-body-name":"Landwasser","water-body-type":"river","chx":779640,"chy":181200,"lat":46.7578,"lon":9.7903}},"2356":{"id":147,"name":"2356","details":{"id":"2356","name":"Cavergno, Pontit","water-body-name":"Riale di Calneggia","water-body-type":"river","chx":684970,"chy":135960,"lat":46.3696,"lon":8.5429}},"2364":{"id":148,"name":"2364","details":{"id":"2364","name":"Piotta","water-body-name":"Ticino","water-body-type":"river","chx":694610,"chy":152450,"lat":46.5167,"lon":8.6715}},"2366":{"id":149,"name":"2366","details":{"id":"2366","name":"La R\u00f6sa","water-body-name":"Poschiavino","water-body-type":"river","chx":802120,"chy":142010,"lat":46.399,"lon":10.0672}},"2368":{"id":150,"name":"2368","details":{"id":"2368","name":"Locarno, Solduno","water-body-name":"Maggia","water-body-type":"river","chx":703100,"chy":113860,"lat":46.1683,"lon":8.7736}},"2369":{"id":151,"name":"2369","details":{"id":"2369","name":"Yvonand","water-body-name":"Menthue","water-body-type":"river","chx":545440,"chy":180875,"lat":46.7768,"lon":6.7242}},"2370":{"id":152,"name":"2370","details":{"id":"2370","name":"Le Noirmont, La Goule","water-body-name":"Doubs","water-body-type":"river","chx":561430,"chy":231050,"lat":47.2292,"lon":6.9293}},"2371":{"id":153,"name":"2371","details":{"id":"2371","name":"Le Chenit, Fronti\u00e8re","water-body-name":"Orbe","water-body-type":"river","chx":501445,"chy":156305,"lat":46.5508,"lon":6.1535}},"2372":{"id":154,"name":"2372","details":{"id":"2372","name":"Mollis, Linthbr\u00fccke","water-body-name":"Linth","water-body-type":"river","chx":723985,"chy":217965,"lat":47.1011,"lon":9.072}},"2374":{"id":155,"name":"2374","details":{"id":"2374","name":"Mogelsberg, Aachs\u00e4ge","water-body-name":"Necker","water-body-type":"river","chx":727110,"chy":247290,"lat":47.3642,"lon":9.1214}},"2378":{"id":156,"name":"2378","details":{"id":"2378","name":"Orbe, Le Chalet","water-body-name":"Orbe","water-body-type":"river","chx":530080,"chy":175560,"lat":46.7276,"lon":6.5239}},"2384":{"id":157,"name":"2384","details":{"id":"2384","name":"Simplonpass","water-body-name":"Bisse kalte Wasser","water-body-type":"river","chx":646080,"chy":121780,"lat":46.2459,"lon":8.0361}},"2386":{"id":158,"name":"2386","details":{"id":"2386","name":"Frauenfeld","water-body-name":"Murg","water-body-type":"river","chx":0,"chy":0,"lat":44.89,"lon":-0.1617}},"2387":{"id":159,"name":"2387","details":{"id":"2387","name":"F\u00fcrstenau","water-body-name":"Hinterrhein","water-body-type":"river","chx":753570,"chy":175730,"lat":46.7151,"lon":9.4473}},"2392":{"id":160,"name":"2392","details":{"id":"2392","name":"Rheinau","water-body-name":"Rhein (Oberwasser)","water-body-type":"river","chx":687420,"chy":277140,"lat":47.6391,"lon":8.6019}},"2403":{"id":161,"name":"2403","details":{"id":"2403","name":"Cinuos - Chel","water-body-name":"Inn","water-body-type":"river","chx":797700,"chy":168170,"lat":46.6355,"lon":10.0209}},"2404":{"id":1385,"name":"2404","details":{"id":"2404","name":"Cinuos-chel, Val Torta","water-body-name":"Innabl. EKW","water-body-type":"river","chx":798523,"chy":169038,"lat":46.6431,"lon":10.0321}},"2409":{"id":162,"name":"2409","details":{"id":"2409","name":"Eggiwil, Heidb\u00fcel","water-body-name":"Emme","water-body-type":"river","chx":627910,"chy":191180,"lat":46.8712,"lon":7.8047}},"2410":{"id":163,"name":"2410","details":{"id":"2410","name":"Ruggell","water-body-name":"Liechtensteiner Binnenkanal","water-body-type":"river","chx":757751,"chy":234590,"lat":47.2434,"lon":9.5225}},"2412":{"id":164,"name":"2412","details":{"id":"2412","name":"Vuippens, Ch\u00e2teau","water-body-name":"Sionge","water-body-type":"river","chx":572420,"chy":167540,"lat":46.6585,"lon":7.0783}},"2414":{"id":165,"name":"2414","details":{"id":"2414","name":"Mosnang, Rietholz","water-body-name":"Rietholzbach","water-body-type":"river","chx":718840,"chy":248440,"lat":47.3761,"lon":9.0123}},"2415":{"id":166,"name":"2415","details":{"id":"2415","name":"Rheinsfelden","water-body-name":"Glatt","water-body-type":"river","chx":678040,"chy":269720,"lat":47.5735,"lon":8.4758}},"2416":{"id":167,"name":"2416","details":{"id":"2416","name":"Hitzkirch, Richensee","water-body-name":"Aabach","water-body-type":"river","chx":661390,"chy":230220,"lat":47.2201,"lon":8.2491}},"2417":{"id":168,"name":"2417","details":{"id":"2417","name":"Oberkirch","water-body-name":"Suhre","water-body-type":"river","chx":651320,"chy":223140,"lat":47.1572,"lon":8.1154}},"2418":{"id":169,"name":"2418","details":{"id":"2418","name":"Tiefencastel","water-body-name":"Julia","water-body-type":"river","chx":763570,"chy":169910,"lat":46.6604,"lon":9.576}},"2419":{"id":170,"name":"2419","details":{"id":"2419","name":"Reckingen","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":661910,"chy":146780,"lat":46.4695,"lon":8.2447}},"2420":{"id":171,"name":"2420","details":{"id":"2420","name":"Lumino, Sassello","water-body-name":"Moesa","water-body-type":"river","chx":724765,"chy":120360,"lat":46.2231,"lon":9.0558}},"2426":{"id":172,"name":"2426","details":{"id":"2426","name":"Mels","water-body-name":"Seez","water-body-type":"river","chx":750410,"chy":212510,"lat":47.0465,"lon":9.4182}},"2430":{"id":173,"name":"2430","details":{"id":"2430","name":"Sumvitg, Encardens","water-body-name":"Rein da Sumvitg","water-body-type":"river","chx":718810,"chy":167690,"lat":46.6499,"lon":8.9907}},"2432":{"id":174,"name":"2432","details":{"id":"2432","name":"Ecublens, Les Bois","water-body-name":"Venoge","water-body-type":"river","chx":532040,"chy":154160,"lat":46.5353,"lon":6.5527}},"2433":{"id":175,"name":"2433","details":{"id":"2433","name":"Allaman, Le Coulet","water-body-name":"Aubonne","water-body-type":"river","chx":520720,"chy":147410,"lat":46.4733,"lon":6.4064}},"2434":{"id":176,"name":"2434","details":{"id":"2434","name":"Olten, Hammerm\u00fchle","water-body-name":"D\u00fcnnern","water-body-type":"river","chx":634330,"chy":244480,"lat":47.3503,"lon":7.893}},"2436":{"id":177,"name":"2436","details":{"id":"2436","name":"Alpnach, Chilch Erli","water-body-name":"Chli Schliere","water-body-type":"river","chx":663800,"chy":199570,"lat":46.9441,"lon":8.2766}},"2437":{"id":178,"name":"2437","details":{"id":"2437","name":"Ecublens, Eschiens","water-body-name":"Parimbot","water-body-type":"river","chx":552060,"chy":161650,"lat":46.6044,"lon":6.8129}},"2446":{"id":179,"name":"2446","details":{"id":"2446","name":"Gampelen, Zihlbr\u00fccke","water-body-name":"Zihlkanal","water-body-type":"river","chx":569250,"chy":207860,"lat":47.0211,"lon":7.0342}},"2447":{"id":180,"name":"2447","details":{"id":"2447","name":"Sugiez","water-body-name":"Canal de la Broye","water-body-type":"river","chx":575340,"chy":201450,"lat":46.9637,"lon":7.1146}},"2450":{"id":181,"name":"2450","details":{"id":"2450","name":"Zofingen","water-body-name":"Wigger","water-body-type":"river","chx":637580,"chy":237080,"lat":47.2835,"lon":7.9354}},"2457":{"id":182,"name":"2457","details":{"id":"2457","name":"Ringgenberg, Goldswil","water-body-name":"Aare","water-body-type":"river","chx":633730,"chy":171510,"lat":46.694,"lon":7.8796}},"2458":{"id":183,"name":"2458","details":{"id":"2458","name":"Valangin","water-body-name":"Seyon","water-body-type":"river","chx":559370,"chy":206810,"lat":47.0111,"lon":6.9043}},"2461":{"id":184,"name":"2461","details":{"id":"2461","name":"Magliaso, Ponte","water-body-name":"Magliasina","water-body-type":"river","chx":711620,"chy":93290,"lat":45.982,"lon":8.879}},"2462":{"id":185,"name":"2462","details":{"id":"2462","name":"S-Chanf","water-body-name":"Inn","water-body-type":"river","chx":795800,"chy":165910,"lat":46.6157,"lon":9.9952}},"2467":{"id":186,"name":"2467","details":{"id":"2467","name":"G\u00fcmmenen","water-body-name":"Saane","water-body-type":"river","chx":585100,"chy":199240,"lat":46.9441,"lon":7.2429}},"2468":{"id":187,"name":"2468","details":{"id":"2468","name":"St. Gallen, Bruggen\/Au","water-body-name":"Sitter","water-body-type":"river","chx":742540,"chy":253230,"lat":47.4144,"lon":9.3275}},"2469":{"id":188,"name":"2469","details":{"id":"2469","name":"Hondrich","water-body-name":"Kander","water-body-type":"river","chx":617790,"chy":168400,"lat":46.6666,"lon":7.6711}},"2471":{"id":189,"name":"2471","details":{"id":"2471","name":"Murgenthal, Walliswil","water-body-name":"Murg","water-body-type":"river","chx":629340,"chy":233555,"lat":47.2523,"lon":7.8262}},"2473":{"id":190,"name":"2473","details":{"id":"2473","name":"Diepoldsau, Rietbr\u00fccke","water-body-name":"Rhein","water-body-type":"river","chx":766280,"chy":250360,"lat":47.3831,"lon":9.6409}},"2474":{"id":191,"name":"2474","details":{"id":"2474","name":"Buseno","water-body-name":"Calancasca","water-body-type":"river","chx":729440,"chy":127180,"lat":46.2836,"lon":9.1182}},"2475":{"id":192,"name":"2475","details":{"id":"2475","name":"Bignasco, Ponte nuovo","water-body-name":"Maggia","water-body-type":"river","chx":690040,"chy":132550,"lat":46.3383,"lon":8.6081}},"2477":{"id":193,"name":"2477","details":{"id":"2477","name":"Zug, Letzi","water-body-name":"Lorze","water-body-type":"river","chx":680600,"chy":226070,"lat":47.1807,"lon":8.502}},"2478":{"id":194,"name":"2478","details":{"id":"2478","name":"Soyhi\u00e8res, Bois du Treuil","water-body-name":"Birse","water-body-type":"river","chx":596780,"chy":249070,"lat":47.3924,"lon":7.396}},"2480":{"id":195,"name":"2480","details":{"id":"2480","name":"Boudry","water-body-name":"Areuse","water-body-type":"river","chx":554350,"chy":199940,"lat":46.949,"lon":6.839}},"2481":{"id":196,"name":"2481","details":{"id":"2481","name":"Buochs, Flugplatz","water-body-name":"Engelberger Aa","water-body-type":"river","chx":673555,"chy":202870,"lat":46.9728,"lon":8.4053}},"2484":{"id":197,"name":"2484","details":{"id":"2484","name":"Lauerz, Chlostermatt","water-body-name":"Lauerzersee","water-body-type":"lake","chx":688020,"chy":209530,"lat":47.031,"lon":8.5966}},"2485":{"id":198,"name":"2485","details":{"id":"2485","name":"Boncourt, Fronti\u00e8re","water-body-name":"Allaine","water-body-type":"river","chx":567830,"chy":261200,"lat":47.5008,"lon":7.0117}},"2486":{"id":199,"name":"2486","details":{"id":"2486","name":"Vevey, Coppet","water-body-name":"Veveyse","water-body-type":"river","chx":554675,"chy":146565,"lat":46.4689,"lon":6.8485}},"2487":{"id":200,"name":"2487","details":{"id":"2487","name":"Werthenstein, Chappelboden","water-body-name":"Kleine Emme","water-body-type":"river","chx":647870,"chy":209510,"lat":47.0349,"lon":8.0684}},"2488":{"id":201,"name":"2488","details":{"id":"2488","name":"Latterbach","water-body-name":"Simme","water-body-type":"river","chx":610680,"chy":167840,"lat":46.6617,"lon":7.5782}},"2490":{"id":202,"name":"2490","details":{"id":"2490","name":"Dardagny, Les Granges","water-body-name":"Allondon","water-body-type":"river","chx":488880,"chy":119460,"lat":46.2174,"lon":5.9985}},"2491":{"id":203,"name":"2491","details":{"id":"2491","name":"B\u00fcrglen, Galgenw\u00e4ldli","water-body-name":"Sch\u00e4chen","water-body-type":"river","chx":692480,"chy":191800,"lat":46.8709,"lon":8.6517}},"2492":{"id":204,"name":"2492","details":{"id":"2492","name":"Buerglen, EW Altdorf","water-body-name":"Dorfbachableitung","water-body-type":"river","chx":693040,"chy":192350,"lat":46.8758,"lon":8.6592}},"2493":{"id":205,"name":"2493","details":{"id":"2493","name":"Gland, Route Suisse","water-body-name":"Promenthouse","water-body-type":"river","chx":510080,"chy":140080,"lat":46.406,"lon":6.2693}},"2494":{"id":206,"name":"2494","details":{"id":"2494","name":"Pollegio, Campagna","water-body-name":"Ticino","water-body-type":"river","chx":716120,"chy":135330,"lat":46.3593,"lon":8.9475}},"2497":{"id":207,"name":"2497","details":{"id":"2497","name":"Nebikon","water-body-name":"Luthern","water-body-type":"river","chx":640560,"chy":226740,"lat":47.1904,"lon":7.9738}},"2498":{"id":208,"name":"2498","details":{"id":"2498","name":"Castrisch","water-body-name":"Glenner","water-body-type":"river","chx":735330,"chy":181790,"lat":46.7735,"lon":9.2106}},"2499":{"id":209,"name":"2499","details":{"id":"2499","name":"Muotathal","water-body-name":"Schlichenden Br\u00fcnnen","water-body-type":"river","chx":702392,"chy":203328,"lat":46.9731,"lon":8.7843}},"2500":{"id":210,"name":"2500","details":{"id":"2500","name":"Ittigen","water-body-name":"Worble","water-body-type":"river","chx":603005,"chy":202455,"lat":46.9732,"lon":7.4781}},"2602":{"id":211,"name":"2602","details":{"id":"2602","name":"Domat\/Ems","water-body-name":"Rhein","water-body-type":"river","chx":753890,"chy":189370,"lat":46.8377,"lon":9.4561}},"2603":{"id":212,"name":"2603","details":{"id":"2603","name":"Langnau","water-body-name":"Ilfis","water-body-type":"river","chx":627320,"chy":198600,"lat":46.9379,"lon":7.7974}},"2604":{"id":213,"name":"2604","details":{"id":"2604","name":"Biberbrugg","water-body-name":"Biber","water-body-type":"river","chx":697240,"chy":223280,"lat":47.1533,"lon":8.7209}},"2605":{"id":214,"name":"2605","details":{"id":"2605","name":"Lavertezzo, Campi\u00f6i","water-body-name":"Verzasca","water-body-type":"river","chx":708420,"chy":122920,"lat":46.249,"lon":8.8446}},"2606":{"id":215,"name":"2606","details":{"id":"2606","name":"Gen\u00e8ve, Halle de l'\u00cele","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":499890,"chy":117850,"lat":46.2047,"lon":6.1415}},"2607":{"id":216,"name":"2607","details":{"id":"2607","name":"Oberwald","water-body-name":"Goneri","water-body-type":"river","chx":670520,"chy":153830,"lat":46.532,"lon":8.3578}},"2608":{"id":217,"name":"2608","details":{"id":"2608","name":"Neuenkirch","water-body-name":"Sellenbodenbach","water-body-type":"river","chx":658530,"chy":218290,"lat":47.113,"lon":8.2098}},"2609":{"id":218,"name":"2609","details":{"id":"2609","name":"Einsiedeln","water-body-name":"Alp","water-body-type":"river","chx":698640,"chy":223020,"lat":47.1508,"lon":8.7393}},"2610":{"id":219,"name":"2610","details":{"id":"2610","name":"Vicques","water-body-name":"Scheulte","water-body-type":"river","chx":599485,"chy":244150,"lat":47.3482,"lon":7.4318}},"2612":{"id":220,"name":"2612","details":{"id":"2612","name":"Lavertezzo","water-body-name":"Riale di Pincascia","water-body-type":"river","chx":708060,"chy":123950,"lat":46.2583,"lon":8.8401}},"2613":{"id":221,"name":"2613","details":{"id":"2613","name":"Weil, Palmrainbr\u00fccke","water-body-name":"Rhein","water-body-type":"river","chx":611740,"chy":272310,"lat":47.6014,"lon":7.5947}},"2615":{"id":222,"name":"2615","details":{"id":"2615","name":"Basel LHG","water-body-name":"Rhein","water-body-type":"river","chx":611140,"chy":267900,"lat":47.5617,"lon":7.5867}},"2617":{"id":223,"name":"2617","details":{"id":"2617","name":"M\u00fcstair","water-body-name":"Rom","water-body-type":"river","chx":830800,"chy":168700,"lat":46.6296,"lon":10.4532}},"2620":{"id":224,"name":"2620","details":{"id":"2620","name":"Soglio","water-body-name":"Mera","water-body-type":"river","chx":760770,"chy":133450,"lat":46.3332,"lon":9.5268}},"2623":{"id":225,"name":"2623","details":{"id":"2623","name":"Oberwald","water-body-name":"Rh\u00f4ne","water-body-type":"river","chx":669870,"chy":154080,"lat":46.5344,"lon":8.3494}},"2629":{"id":226,"name":"2629","details":{"id":"2629","name":"Agno","water-body-name":"Vedeggio","water-body-type":"river","chx":714110,"chy":95680,"lat":46.003,"lon":8.9117}},"2630":{"id":227,"name":"2630","details":{"id":"2630","name":"Sion","water-body-name":"Sionne","water-body-type":"river","chx":594400,"chy":119900,"lat":46.2305,"lon":7.366}},"2631":{"id":228,"name":"2631","details":{"id":"2631","name":"Hinterrhein, Schiessplatz","water-body-name":"Hinterrhein","water-body-type":"river","chx":733706,"chy":153945,"lat":46.5234,"lon":9.1813}},"2632":{"id":229,"name":"2632","details":{"id":"2632","name":"M\u00fchlbach. Trennbauwerk Sand","water-body-name":"M\u00fchlbach","water-body-type":"river","chx":760059,"chy":190378,"lat":46.8453,"lon":9.5373}},"2634":{"id":230,"name":"2634","details":{"id":"2634","name":"Emmen","water-body-name":"Kleine Emme","water-body-type":"river","chx":663550,"chy":213785,"lat":47.072,"lon":8.2753}},"2635":{"id":231,"name":"2635","details":{"id":"2635","name":"Einsiedeln, Gross","water-body-name":"Grossbach","water-body-type":"river","chx":700710,"chy":218125,"lat":47.1065,"lon":8.7655}},"2636":{"id":232,"name":"2636","details":{"id":"2636","name":"Muotathal, H\u00f6lloch","water-body-name":"H\u00f6lloch","water-body-type":"river","chx":702700,"chy":203700,"lat":46.9764,"lon":8.7884}},"2639":{"id":4427,"name":"2639","details":{"id":"2639","name":"Martina, Sclamischot","water-body-name":"Inn","water-body-type":"river","chx":829232,"chy":195429,"lat":46.8704,"lon":10.4461}},"2640":{"id":233,"name":"2640","details":{"id":"2640","name":"Del\u00e9mont","water-body-name":"Sorne","water-body-type":"river","chx":593380,"chy":245940,"lat":47.3643,"lon":7.351}},"2642":{"id":234,"name":"2642","details":{"id":"2642","name":"Neuch\u00e2tel, Nid-du-Cr\u00f4","water-body-name":"Lac de Neuch\u00e2tel","water-body-type":"lake","chx":562913,"chy":205165,"lat":46.9965,"lon":6.951}},"2643":{"id":1051,"name":"2643","details":{"id":"2643","name":"Montlingen","water-body-name":"Rhein","water-body-type":"river","chx":762945,"chy":244778,"lat":47.3337,"lon":9.5947}},"2646":{"id":1483,"name":"2646","details":{"id":"2646","name":"Emdthal, Heustrich","water-body-name":"Kander","water-body-type":"river","chx":618691,"chy":166833,"lat":46.6525,"lon":7.6828}},"2650":{"id":137470,"name":"2650","details":{"id":"2650","name":"Chur","water-body-name":"Untertorer M\u00fchlbach","water-body-type":"river","chx":759926,"chy":190599,"lat":46.8473,"lon":9.5356}},"4601":{"id":235,"name":"4601","details":{"id":"4601","name":"Buch","water-body-name":"Biber","water-body-type":"river","chx":701590,"chy":285825,"lat":47.7151,"lon":8.7924}},"520":{"id":236,"name":"520","details":{"id":"520","name":"R\u00e4mism\u00fchle","water-body-name":"T\u00f6ss","water-body-type":"river","chx":703795,"chy":255605,"lat":47.443,"lon":8.8148}},"9020":{"id":487,"name":"9020","details":{"id":"9020","name":"Bellinzona","water-body-name":"Ticino","water-body-type":"river","chx":721245,"chy":117025,"lat":46.1938,"lon":9.0093}},"9632":{"id":237,"name":"9632","details":{"id":"9632","name":"Chur","water-body-name":"Untertorer M\u00fchlbach","water-body-type":"river","chx":759926,"chy":190599,"lat":46.8473,"lon":9.5356}},"A270":{"id":516,"name":"A270","details":{"id":"A270","name":"Combe des Sarrasins","water-body-name":"Doubs","water-body-type":"river","chx":557530,"chy":227320,"lat":47.1955,"lon":6.8782}},"C384":{"id":1342,"name":"C384","details":{"id":"C384","name":"Simplonpass","water-body-name":"Bisse kalte Wasser","water-body-type":"river","chx":646080,"chy":121780,"lat":46.2459,"lon":8.0361}}}} \ No newline at end of file diff --git a/tests/test_switzerland.py b/tests/test_switzerland.py new file mode 100644 index 0000000..323baf7 --- /dev/null +++ b/tests/test_switzerland.py @@ -0,0 +1,171 @@ +import json +import os +import unittest +from pathlib import Path +from unittest.mock import MagicMock, patch + +import pandas as pd +from pandas.testing import assert_frame_equal + +from rivretrieve import SwitzerlandFetcher, constants + + +class TestSwitzerlandFetcher(unittest.TestCase): + def setUp(self): + self.fetcher = SwitzerlandFetcher() + self.test_data_dir = Path(os.path.dirname(__file__)) / "test_data" + + def _load_json(self, filename): + with open(self.test_data_dir / filename, "r", encoding="utf-8") as f: + return json.load(f) + + def _load_text(self, filename): + with open(self.test_data_dir / filename, "r", encoding="utf-8") as f: + return f.read() + + @patch("rivretrieve.utils.requests_retry_session") + def test_get_metadata(self, mock_requests_session): + mock_session = MagicMock() + mock_requests_session.return_value = mock_session + + mock_response = MagicMock() + mock_response.json.return_value = self._load_json("switzerland_metadata_locations.json") + mock_response.raise_for_status = MagicMock() + mock_session.get.return_value = mock_response + + result_df = self.fetcher.get_metadata() + + self.assertEqual(len(result_df), 246) + self.assertEqual(result_df.index.name, constants.GAUGE_ID) + self.assertIn("2016", result_df.index) + self.assertIn("2019", result_df.index) + self.assertEqual(result_df.loc["2016", constants.STATION_NAME], "Brugg") + self.assertEqual(result_df.loc["2016", constants.RIVER], "Aare") + self.assertAlmostEqual(result_df.loc["2016", constants.LATITUDE], 47.4825) + self.assertAlmostEqual(result_df.loc["2016", constants.LONGITUDE], 8.1949) + self.assertEqual(result_df.loc["2016", constants.COUNTRY], "Switzerland") + self.assertEqual(result_df.loc["2016", constants.SOURCE], self.fetcher.SOURCE) + mock_session.get.assert_called_once() + args, _ = mock_session.get.call_args + self.assertIn("/hydro/locations", args[0]) + + @patch("rivretrieve.utils.requests_retry_session") + def test_get_data_daily_discharge_uses_archive_and_converts_fallback(self, mock_requests_session): + mock_session = MagicMock() + mock_requests_session.return_value = mock_session + + mock_response = MagicMock() + mock_response.text = self._load_text("switzerland_2206_discharge_20250101.csv") + mock_response.raise_for_status = MagicMock() + mock_session.post.return_value = mock_response + + result_df = self.fetcher.get_data( + gauge_id="2206", + variable=constants.DISCHARGE_DAILY_MEAN, + start_date="2025-01-01", + end_date="2025-01-01", + ) + + expected_df = pd.DataFrame( + { + constants.TIME_INDEX: pd.to_datetime(["2025-01-01"]), + constants.DISCHARGE_DAILY_MEAN: [14.944444 / 1000.0], + } + ).set_index(constants.TIME_INDEX) + + assert_frame_equal(result_df, expected_df) + mock_session.post.assert_called_once() + _, mock_kwargs = mock_session.post.call_args + self.assertIn("/api/v2/query", mock_session.post.call_args.args[0]) + self.assertIn("Token ", mock_kwargs["headers"]["Authorization"]) + query = mock_kwargs["data"] + self.assertIn("range(start: 2025-01-01T00:00:00Z, stop: 2025-01-02T00:00:00Z)", query) + self.assertIn('r["loc"] == "2206"', query) + self.assertIn('r["_field"] == "flow"', query) + self.assertIn('r["_field"] == "flow_ls"', query) + + @patch("rivretrieve.utils.requests_retry_session") + def test_get_data_instant_stage_from_archive_payload(self, mock_requests_session): + mock_session = MagicMock() + mock_requests_session.return_value = mock_session + + mock_response = MagicMock() + mock_response.text = self._load_text("switzerland_2282_stage_20250101.csv") + mock_response.raise_for_status = MagicMock() + mock_session.post.return_value = mock_response + + result_df = self.fetcher.get_data( + gauge_id="2282", + variable=constants.STAGE_INSTANT, + start_date="2025-01-01", + end_date="2025-01-01", + ) + + expected_df = pd.DataFrame( + { + constants.TIME_INDEX: pd.to_datetime(["2025-01-01 00:00:00", "2025-01-01 00:10:00"]), + constants.STAGE_INSTANT: [0.165, 0.165], + } + ).set_index(constants.TIME_INDEX) + + self.assertEqual(len(result_df), 141) + assert_frame_equal(result_df.head(2), expected_df) + mock_session.post.assert_called_once() + query = mock_session.post.call_args.kwargs["data"] + self.assertIn('r["_field"] == "height_abs"', query) + self.assertIn('r["_field"] == "height"', query) + + @patch("rivretrieve.utils.requests_retry_session") + def test_get_data_daily_temperature(self, mock_requests_session): + mock_session = MagicMock() + mock_requests_session.return_value = mock_session + + mock_response = MagicMock() + mock_response.text = self._load_text("switzerland_2016_temperature_20200101.csv") + mock_response.raise_for_status = MagicMock() + mock_session.post.return_value = mock_response + + result_df = self.fetcher.get_data( + gauge_id="2016", + variable=constants.WATER_TEMPERATURE_DAILY_MEAN, + start_date="2020-01-01", + end_date="2020-01-02", + ) + + expected_df = pd.DataFrame( + { + constants.TIME_INDEX: pd.to_datetime(["2020-01-01", "2020-01-02"]), + constants.WATER_TEMPERATURE_DAILY_MEAN: [6.727014, 6.559091], + } + ).set_index(constants.TIME_INDEX) + + assert_frame_equal(result_df, expected_df) + mock_session.post.assert_called_once() + query = mock_session.post.call_args.kwargs["data"] + self.assertIn('r["_field"] == "temperature"', query) + + @patch("rivretrieve.utils.requests_retry_session") + def test_get_data_historical_range_uses_archive_backend(self, mock_requests_session): + mock_session = MagicMock() + mock_requests_session.return_value = mock_session + + mock_response = MagicMock() + mock_response.text = self._load_text("switzerland_2016_temperature_20200101.csv") + mock_response.raise_for_status = MagicMock() + mock_session.post.return_value = mock_response + + self.fetcher.get_data( + gauge_id="2016", + variable=constants.WATER_TEMPERATURE_INSTANT, + start_date="2020-01-01", + end_date="2020-01-02", + ) + + query = mock_session.post.call_args.kwargs["data"] + self.assertIn("range(start: 2020-01-01T00:00:00Z, stop: 2020-01-03T00:00:00Z)", query) + self.assertIn('r["loc"] == "2016"', query) + self.assertIn('r["_field"] == "temperature"', query) + + +if __name__ == "__main__": + unittest.main()