Source code for aixweather.imports.TRY

"""
import DWD TRY data
"""

import logging
import re
import random
import pandas as pd

from aixweather.imports.utils_import import MetaData

logger = logging.getLogger(__name__)

def _handle_TRY_type(path: str) -> tuple:
    """
    Determine the TRY format type based on the provided file path.

    Args:
        path (str): The file path to the TRY dataset file.

    Returns:
        tuple: A tuple containing the TRY year (int) and the header row number (int).
    Raises:
        ValueError: If the TRY format cannot be detected through the file name or is not supported.
    """

    ### get type of TRY, i.e. the year of the TRY
    TRY_year = None
    # Header_rows are the rows with general information of the dataset
    # Are skipped until variable declaration
    TRY_file_naming = {
        "TRY2004": {"year": 2004},
        "TRY2010": {"year": 2010},
        "TRY2015": {"year": 2015},
        "TRY2045": {"year": 2045},
    }

    if path.endswith(".dat"):
        for key in TRY_file_naming.keys():
            if key in path:
                TRY_year = TRY_file_naming[key]["year"]
                break
    if TRY_year is None:
        raise ValueError(
            f"TRY format could not be detected through file name,"
            f" expected {[key for key in TRY_file_naming.keys()]} in the file name."
        )
    if TRY_year == 2004 or TRY_year == 2010:
        raise ValueError(f"TRY format {TRY_year} is not supported.")

    if TRY_year == 2015 or TRY_year == 2045:
        with open(path, "r") as file:
            for line_number, line in enumerate(file, start=1):
                if "***" in line:
                    header_row = (
                        line_number - 1 - 1
                    )  # -1 for header above *** and -1 for start to count at 0
                    break

    return TRY_year, header_row


[docs]def load_try_meta_from_file(path: str) -> MetaData: """ Load a TRY file from a specified path and parse the header for metadata. Args: path (str): The file path to the TRY file to be loaded. Returns: MetaData: An object containing the parsed metadata from the TRY file. """ meta = MetaData() TRY_year, header_row = _handle_TRY_type(path) ### load file to python header_lines = [] with open(path, "r") as file: for i, line in enumerate(file): if i >= header_row: break header_lines.append(line) ### read raw meta data # Extract Rechtswert (Easting) rechtswert_line = next( line for line in header_lines if "Rechtswert" in line and ":" in line ) rechtswert = int(re.search(r":\s*(\d+) Meter", rechtswert_line).group(1)) # Extract Hochwert (Northing) hochwert_line = next( line for line in header_lines if "Hochwert" in line and ":" in line ) hochwert = int(re.search(r":\s*(\d+) Meter", hochwert_line).group(1)) # Extract Höhenlage (altitude) hoehenlage_line = next(line for line in header_lines if "Hoehenlage" in line) hoehenlage = int(re.search(r":\s*(\d+) Meter", hoehenlage_line).group(1)) try: import geopandas as gpd from geopy.geocoders import Nominatim from shapely.geometry import Point except ImportError: raise ImportError("Optional dependency 'TRY' not installed. Conversion of longitude and " "latitude not possible and hence no radiation transformation.") ### convert latitude and longitude # Create a GeoDataFrame with the provided coordinates # (using pyproj directly led to wrong calculation) gdf = gpd.GeoDataFrame( {"geometry": [Point(rechtswert, hochwert)]}, crs="EPSG:3034", # Original coordinate system ) # Transform to WGS 84 gdf_wgs84 = gdf.to_crs("EPSG:4326") # get transformed coordinates, Get the longitude (x) and latitude (y) point_wgs84 = gdf_wgs84.geometry.iloc[0] longitude_wgs84 = point_wgs84.x latitude_wgs84 = point_wgs84.y ### try to get city of location # Initialize Nominatim geolocator user_agent = f"aixweather_{str(random.randint(1, 1000))}" geolocator = Nominatim(user_agent=user_agent) # Perform reverse geocoding location = geolocator.reverse((latitude_wgs84, longitude_wgs84)) # If you want specific components like city, state, etc. address = location.raw["address"] if "city" in address: city = address["city"] elif "town" in address: city = address["town"] elif "village" in address: city = address["village"] elif "hamlet" in address: city = address["hamlet"] elif "suburb" in address: city = address["suburb"] elif "locality" in address: city = address["locality"] else: city = meta.station_name meta.station_name = city meta.input_source = f"TRY{TRY_year}" meta.try_year = TRY_year meta.altitude = hoehenlage meta.longitude = longitude_wgs84 meta.latitude = latitude_wgs84 return meta
[docs]def load_try_from_file(path: str) -> pd.DataFrame: """ Import data from a TRY file and convert it into a DataFrame. Args: path (str): The absolute path to the TRY file. Returns: pd.DataFrame: A DataFrame containing the imported data from the TRY file. """ TRY_year, header_row = _handle_TRY_type(path) ### load file to Dataframe weather_df = pd.read_table( filepath_or_buffer=path, header=header_row, sep='\s+', skip_blank_lines=False, encoding="latin", ) # drop first row cause empty weather_df = weather_df.iloc[1:] return weather_df