Conditions | 10 |
Total Lines | 107 |
Code Lines | 54 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like data.datasets.storages.home_batteries.allocate_home_batteries_to_buildings() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | """ |
||
84 | def allocate_home_batteries_to_buildings(): |
||
85 | """ |
||
86 | Allocate home battery storage systems to buildings with pv rooftop systems |
||
87 | """ |
||
88 | # get constants |
||
89 | constants = config.datasets()["home_batteries"]["constants"] |
||
90 | scenarios = constants["scenarios"] |
||
91 | cbat_ppv_ratio = constants["cbat_ppv_ratio"] |
||
92 | rtol = constants["rtol"] |
||
93 | max_it = constants["max_it"] |
||
94 | cbat_pbat_ratio = get_cbat_pbat_ratio() |
||
95 | |||
96 | sources = config.datasets()["home_batteries"]["sources"] |
||
97 | |||
98 | df_list = [] |
||
99 | |||
100 | for scenario in scenarios: |
||
101 | # get home battery capacity per mv grid id |
||
102 | sql = f""" |
||
103 | SELECT el_capacity as p_nom_min, bus_id as bus FROM |
||
104 | {sources["storage"]["schema"]} |
||
105 | .{sources["storage"]["table"]} |
||
106 | WHERE carrier = 'home_battery' |
||
107 | AND scenario = '{scenario}'; |
||
108 | """ |
||
109 | |||
110 | home_batteries_df = db.select_dataframe(sql) |
||
111 | |||
112 | home_batteries_df = home_batteries_df.assign( |
||
113 | bat_cap=home_batteries_df.p_nom_min * cbat_pbat_ratio |
||
114 | ) |
||
115 | |||
116 | sql = """ |
||
117 | SELECT building_id, capacity |
||
118 | FROM supply.egon_power_plants_pv_roof_building |
||
119 | WHERE scenario = '{}' |
||
120 | AND bus_id = {} |
||
121 | """ |
||
122 | |||
123 | for bus_id, bat_cap in home_batteries_df[ |
||
124 | ["bus", "bat_cap"] |
||
125 | ].itertuples(index=False): |
||
126 | pv_df = db.select_dataframe(sql.format(scenario, bus_id)) |
||
127 | |||
128 | grid_ratio = bat_cap / pv_df.capacity.sum() |
||
129 | |||
130 | if grid_ratio > cbat_ppv_ratio: |
||
131 | logger.warning( |
||
132 | f"In Grid {bus_id} and scenario {scenario}, the ratio of " |
||
133 | f"home storage capacity to pv rooftop capacity is above 1" |
||
134 | f" ({grid_ratio: g}). The storage capacity of pv rooftop " |
||
135 | f"systems will be high." |
||
136 | ) |
||
137 | |||
138 | if grid_ratio < cbat_ppv_ratio: |
||
139 | random_state = RandomState(seed=bus_id) |
||
140 | |||
141 | n = max(int(len(pv_df) * grid_ratio), 1) |
||
142 | |||
143 | best_df = pv_df.sample(n=n, random_state=random_state) |
||
144 | |||
145 | i = 0 |
||
146 | |||
147 | while ( |
||
148 | not np.isclose(best_df.capacity.sum(), bat_cap, rtol=rtol) |
||
149 | and i < max_it |
||
150 | ): |
||
151 | sample_df = pv_df.sample(n=n, random_state=random_state) |
||
152 | |||
153 | if abs(best_df.capacity.sum() - bat_cap) > abs( |
||
154 | sample_df.capacity.sum() - bat_cap |
||
155 | ): |
||
156 | best_df = sample_df.copy() |
||
157 | |||
158 | i += 1 |
||
159 | |||
160 | if sample_df.capacity.sum() < bat_cap: |
||
161 | n = min(n + 1, len(pv_df)) |
||
162 | else: |
||
163 | n = max(n - 1, 1) |
||
164 | |||
165 | if not np.isclose(best_df.capacity.sum(), bat_cap, rtol=rtol): |
||
166 | logger.warning( |
||
167 | f"No suitable generators could be found in Grid " |
||
168 | f"{bus_id} and scenario {scenario} to achieve the " |
||
169 | f"desired ratio between battery capacity and pv " |
||
170 | f"rooftop capacity. The ratio will be " |
||
171 | f"{bat_cap / best_df.capacity.sum()}." |
||
172 | ) |
||
173 | |||
174 | pv_df = best_df.copy() |
||
175 | |||
176 | bat_df = pv_df.drop(columns=["capacity"]).assign( |
||
177 | capacity=pv_df.capacity / pv_df.capacity.sum() * bat_cap, |
||
178 | p_nom=pv_df.capacity |
||
179 | / pv_df.capacity.sum() |
||
180 | * bat_cap |
||
181 | / cbat_pbat_ratio, |
||
182 | scenario=scenario, |
||
183 | bus_id=bus_id, |
||
184 | ) |
||
185 | |||
186 | df_list.append(bat_df) |
||
187 | |||
188 | create_table(pd.concat(df_list, ignore_index=True)) |
||
189 | |||
190 | add_metadata() |
||
191 | |||
357 |