| Conditions | 10 |
| Total Lines | 105 |
| Code Lines | 53 |
| 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 | from loguru import logger |
||
| 36 | def allocate_home_batteries_to_buildings(): |
||
| 37 | """ |
||
| 38 | Allocate home battery storage systems to buildings with pv rooftop systems |
||
| 39 | """ |
||
| 40 | # get constants |
||
| 41 | constants = config.datasets()["home_batteries"]["constants"] |
||
| 42 | scenarios = constants["scenarios"] |
||
| 43 | cbat_ppv_ratio = constants["cbat_ppv_ratio"] |
||
| 44 | rtol = constants["rtol"] |
||
| 45 | max_it = constants["max_it"] |
||
| 46 | cbat_pbat_ratio = get_cbat_pbat_ratio() |
||
| 47 | |||
| 48 | sources = config.datasets()["home_batteries"]["sources"] |
||
| 49 | |||
| 50 | df_list = [] |
||
| 51 | |||
| 52 | for scenario in scenarios: |
||
| 53 | # get home battery capacity per mv grid id |
||
| 54 | sql = f""" |
||
| 55 | SELECT el_capacity as p_nom_min, bus_id as bus FROM |
||
| 56 | {sources["storage"]["schema"]} |
||
| 57 | .{sources["storage"]["table"]} |
||
| 58 | WHERE carrier = 'home_battery' |
||
| 59 | AND scenario = '{scenario}'; |
||
| 60 | """ |
||
| 61 | |||
| 62 | home_batteries_df = db.select_dataframe(sql) |
||
| 63 | |||
| 64 | home_batteries_df = home_batteries_df.assign( |
||
| 65 | bat_cap=home_batteries_df.p_nom_min * cbat_pbat_ratio |
||
| 66 | ) |
||
| 67 | |||
| 68 | sql = """ |
||
| 69 | SELECT building_id, capacity |
||
| 70 | FROM supply.egon_power_plants_pv_roof_building |
||
| 71 | WHERE scenario = '{}' |
||
| 72 | AND bus_id = {} |
||
| 73 | """ |
||
| 74 | |||
| 75 | for bus_id, bat_cap in home_batteries_df[ |
||
| 76 | ["bus", "bat_cap"] |
||
| 77 | ].itertuples(index=False): |
||
| 78 | pv_df = db.select_dataframe(sql.format(scenario, bus_id)) |
||
| 79 | |||
| 80 | grid_ratio = bat_cap / pv_df.capacity.sum() |
||
| 81 | |||
| 82 | if grid_ratio > cbat_ppv_ratio: |
||
| 83 | logger.warning( |
||
| 84 | f"In Grid {bus_id} and scenario {scenario}, the ratio of " |
||
| 85 | f"home storage capacity to pv rooftop capacity is above 1" |
||
| 86 | f" ({grid_ratio: g}). The storage capacity of pv rooftop " |
||
| 87 | f"systems will be high." |
||
| 88 | ) |
||
| 89 | |||
| 90 | if grid_ratio < cbat_ppv_ratio: |
||
| 91 | random_state = RandomState(seed=bus_id) |
||
| 92 | |||
| 93 | n = max(int(len(pv_df) * grid_ratio), 1) |
||
| 94 | |||
| 95 | best_df = pv_df.sample(n=n, random_state=random_state) |
||
| 96 | |||
| 97 | i = 0 |
||
| 98 | |||
| 99 | while ( |
||
| 100 | not np.isclose(best_df.capacity.sum(), bat_cap, rtol=rtol) |
||
| 101 | and i < max_it |
||
| 102 | ): |
||
| 103 | sample_df = pv_df.sample(n=n, random_state=random_state) |
||
| 104 | |||
| 105 | if abs(best_df.capacity.sum() - bat_cap) > abs( |
||
| 106 | sample_df.capacity.sum() - bat_cap |
||
| 107 | ): |
||
| 108 | best_df = sample_df.copy() |
||
| 109 | |||
| 110 | i += 1 |
||
| 111 | |||
| 112 | if sample_df.capacity.sum() < bat_cap: |
||
| 113 | n = min(n + 1, len(pv_df)) |
||
| 114 | else: |
||
| 115 | n = max(n - 1, 1) |
||
| 116 | |||
| 117 | if not np.isclose(best_df.capacity.sum(), bat_cap, rtol=rtol): |
||
| 118 | logger.warning( |
||
| 119 | f"No suitable generators could be found in Grid " |
||
| 120 | f"{bus_id} and scenario {scenario} to achieve the " |
||
| 121 | f"desired ratio between battery capacity and pv " |
||
| 122 | f"rooftop capacity. The ratio will be " |
||
| 123 | f"{bat_cap / best_df.capacity.sum()}." |
||
| 124 | ) |
||
| 125 | |||
| 126 | pv_df = best_df.copy() |
||
| 127 | |||
| 128 | bat_df = pv_df.drop(columns=["capacity"]).assign( |
||
| 129 | capacity=pv_df.capacity / pv_df.capacity.sum() * bat_cap, |
||
| 130 | p_nom=pv_df.capacity |
||
| 131 | / pv_df.capacity.sum() |
||
| 132 | * bat_cap |
||
| 133 | / cbat_pbat_ratio, |
||
| 134 | scenario=scenario, |
||
| 135 | bus_id=bus_id, |
||
| 136 | ) |
||
| 137 | |||
| 138 | df_list.append(bat_df) |
||
| 139 | |||
| 140 | create_table(pd.concat(df_list, ignore_index=True)) |
||
| 141 | |||
| 171 |