/ data_loader.py
data_loader.py
 1  import requests
 2  import json
 3  import logging
 4  from typing import Tuple, Dict, Any
 5  from config import APP_CONFIG, RIVERS, METRICS
 6  
 7  logger = logging.getLogger(__name__)
 8  
 9  def load_plot(station_id: str, title: str, plot_type: str = "temperature") -> Tuple[Dict, Dict]:
10      """
11      Load plot data from hydrodaten.admin.ch
12      
13      Args:
14          station_id: Station ID (e.g., "2135")
15          title: Plot title
16          plot_type: Either "temperature" or "flow"
17      
18      Returns:
19          Tuple of (plot_data, latest_values)
20      """
21      # Validate plot_type first
22      if plot_type not in METRICS:
23          raise ValueError(f"Invalid plot_type: {plot_type}. Must be one of {list(METRICS.keys())}")
24      
25      try:
26          # Build URL based on plot type
27          if plot_type == "temperature":
28              url = f"{APP_CONFIG['DATA_BASE_URL']}{APP_CONFIG['TEMPERATURE_ENDPOINT']}".format(station_id=station_id)
29          else:
30              url = f"{APP_CONFIG['DATA_BASE_URL']}{APP_CONFIG['FLOW_ENDPOINT']}".format(station_id=station_id)
31          
32          logger.debug(f"Fetching data from URL: {url}")
33          response = requests.get(url, timeout=10)
34          response.raise_for_status()
35          data = response.json()
36          
37          # Add hover info for all data series in the plot
38          for series in data["plot"]["data"]:
39              if "hoverinfo" in series:
40                  series["hoverinfo"] = "x+y+name"
41          
42          # Extract latest measurements
43          latest_values = {}
44          if plot_type == "temperature":
45              # Get the latest temperature value
46              if data["plot"]["data"] and len(data["plot"]["data"]) > 0:
47                  temp_data = data["plot"]["data"][0]
48                  if (
49                      "x" in temp_data
50                      and "y" in temp_data
51                      and len(temp_data["x"]) > 0
52                      and len(temp_data["y"]) > 0
53                  ):
54                      latest_values["value"] = temp_data["y"][-1]
55                      latest_values["time"] = temp_data["x"][-1]
56                      latest_values["unit"] = "°C"
57          else:
58              # For flow plots, there are usually multiple data series (flow and water level)
59              values = {}
60              for series in data["plot"]["data"]:
61                  if (
62                      "x" in series
63                      and "y" in series
64                      and len(series["x"]) > 0
65                      and len(series["y"]) > 0
66                  ):
67                      if "name" in series:
68                          name = series["name"]
69                          if "Abfluss" in name:
70                              values["flow"] = {
71                                  "value": series["y"][-1],
72                                  "time": series["x"][-1],
73                                  "unit": "m³/s",
74                              }
75                          elif "Wasserstand" in name or "Pegel" in name:
76                              values["level"] = {
77                                  "value": series["y"][-1],
78                                  "time": series["x"][-1],
79                                  "unit": "m",
80                              }
81              latest_values = values
82  
83          # Update the layout title with proper Dash format
84          data["plot"]["layout"]["title"] = {"text": title, "font": {"size": 24}}
85          return data["plot"], latest_values
86      
87      except requests.exceptions.RequestException as e:
88          logger.error(f"Request failed for station {station_id}: {str(e)}")
89          return {}, {}
90      except json.JSONDecodeError as e:
91          logger.error(f"JSON parsing error for station {station_id}: {str(e)}")
92          return {}, {}
93      except Exception as e:
94          logger.error(f"Unexpected error for station {station_id}: {str(e)}")
95          return {}, {}