Coverage for aixweather/transformation_to_core_data/TRY.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-12-31 11:58 +0000

1import pandas as pd 

2import datetime as dt 

3 

4from aixweather import definitions 

5from aixweather.imports.utils_import import MetaData 

6from aixweather.transformation_functions import auxiliary, time_observation_transformations, variable_transformations, \ 

7 pass_through_handling, unit_conversions 

8 

9 

10class TRYFormat: 

11 """ 

12 Information on TRY 2015 and 2045 format 

13 

14 Format info: 

15 key = raw data point name 

16 core_name = corresponding name matching the format_core_data 

17 time_of_meas_shift = desired 30min shifting+interpolation to convert a value that is e.g. the 

18 "average of preceding hour" to "indicated time" (prec2ind). 

19 unit = unit of the raw data following the naming convention of format_core_data 

20 

21 All changes here automatically change the calculations. 

22 Exception: unit conversions have to be added manually. 

23 

24 checked by Martin Rätz (08.08.2023) 

25 

26 https://www.bbsr.bund.de/BBSR/DE/forschung/programme/zb/Auftragsforschung/5EnergieKlimaBauen/2013/testreferenzjahre/try-handbuch.pdf;jsessionid=9F928CDB6862224B04073332C2B1B620.live21301?__blob=publicationFile&v=1 

27 Der erste Eintrag im Datensatz bezieht sich auf den 1. Januar 01 Uhr MEZ und 

28 der letzte Eintrag auf den 31. Dezember 24 Uhr MEZ. Also UTC+1. 

29 The data is in MEZ or UTC+1 the whole year, which was specified by DWD upon request. 

30 """ 

31 

32 @classmethod 

33 def import_format(cls): 

34 return { 

35 "t": {"core_name": "DryBulbTemp", "time_of_meas_shift": "prec2ind", "unit": "degC"}, 

36 "p": {"core_name": "AtmPressure", "time_of_meas_shift": None, "unit": "hPa"}, 

37 "WR": {"core_name": "WindDir", "time_of_meas_shift": None, "unit": "deg"}, 

38 "WG": {"core_name": "WindSpeed", "time_of_meas_shift": None, "unit": "m/s"}, 

39 "N": {"core_name": "TotalSkyCover", "time_of_meas_shift": None, "unit": "1eigth"}, 

40 # 'x', 

41 "RF": {"core_name": "RelHum", "time_of_meas_shift": "prec2ind", "unit": "percent"}, 

42 "B": {"core_name": "DirHorRad", "time_of_meas_shift": "prec2ind", "unit": "Wh/m2"}, 

43 "D": {"core_name": "DiffHorRad", "time_of_meas_shift": "prec2ind", "unit": "Wh/m2"}, 

44 "A": {"core_name": "HorInfra", "time_of_meas_shift": None, "unit": "Wh/m2"}, 

45 # 'E', 

46 } 

47 

48 

49def TRY_to_core_data(df_import: pd.DataFrame, meta: MetaData) -> pd.DataFrame: 

50 """ 

51 Transform imported TRY data of the formats 2015 and 2045 into the core data format. 

52 

53 Args: 

54 df_import (pd.DataFrame): The DataFrame containing imported TRY weather data. 

55 meta (MetaData): Metadata associated with the data. 

56 

57 Returns: 

58 pd.DataFrame: The transformed DataFrame in the core data format. 

59 """ 

60 format_TRY_15_45 = TRYFormat.import_format() 

61 

62 ### evaluate correctness of format 

63 auxiliary.evaluate_transformations( 

64 core_format=definitions.format_core_data, other_format=format_TRY_15_45 

65 ) 

66 

67 def TRY_to_datetimeindex(df, meta: MetaData): 

68 # set index to datetime 

69 # returns datetime objects 

70 df["MM"] = df["MM"].astype(int) 

71 df["DD"] = df["DD"].astype(int) 

72 df["HH"] = df["HH"].astype(int) 

73 time_index = df.apply( 

74 lambda row: dt.datetime(int(meta.try_year), row.MM, row.DD, row.HH - int(1.0)), 

75 axis=1, 

76 ) 

77 # data is shifted by -1 H to satisfy pandas timestamp 

78 # hours in pandas only between 0 and 23, in TRY between 1 and 24 

79 # converts to pandas timestamps if desired 

80 df.index = pd.to_datetime(time_index) 

81 # data is shifted back to original to start: back to 

82 # 2017-01-01 01:00:00 instead of the temporary 2017-01-01 00:00:00 

83 df = df.shift(periods=1, freq="h", axis=0) 

84 

85 return df 

86 

87 ### preprocessing raw data for further operations 

88 df = df_import.copy() 

89 df = TRY_to_datetimeindex(df, meta) 

90 # Resample the DataFrame to make the DatetimeIndex complete and monotonic 

91 df = df.resample('h').asfreq() 

92 # rename available variables to core data format 

93 df = auxiliary.rename_columns(df, format_TRY_15_45) 

94 

95 ### convert timezone to UTC+0 

96 df = df.shift(periods=-1, freq="h", axis=0) 

97 

98 ### shift and interpolate data forward 30mins or backward -30mins 

99 df_no_shift = df.copy() 

100 df = time_observation_transformations.shift_time_by_dict(format_TRY_15_45, df) 

101 

102 def transform_TRY(df): 

103 # drop unnecessary variables 

104 df = auxiliary.force_data_variable_convention(df, definitions.format_core_data) 

105 ### convert units 

106 df["TotalSkyCover"] = unit_conversions.eigth_to_tenth(df["TotalSkyCover"]) 

107 df["AtmPressure"] = unit_conversions.hPa_to_Pa(df["AtmPressure"]) 

108 ### impute missing variables from other available ones 

109 df, calc_overview = variable_transformations.variable_transform_all(df, meta) 

110 return df, calc_overview 

111 

112 df, meta.executed_transformations = transform_TRY(df) 

113 

114 ### add unshifted data for possible later direct use (pass-through), 

115 ### to avoid back and forth interpolating 

116 df = pass_through_handling.create_pass_through_variables( 

117 df_shifted=df, 

118 df_no_shift=df_no_shift, 

119 format=format_TRY_15_45, 

120 transform_func=transform_TRY, 

121 meta=meta, 

122 ) 

123 

124 return df