Passed
Pull Request — master (#2)
by Uwe
03:35
created

scenario_builder.demand.get_heat_profiles_deflex()   C

Complexity

Conditions 10

Size

Total Lines 85
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 43
nop 5
dl 0
loc 85
rs 5.9999
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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:

Complexity

Complex classes like scenario_builder.demand.get_heat_profiles_deflex() 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
"""Create a basic scenario from the internal data structure.
2
3
SPDX-FileCopyrightText: 2016-2019 Uwe Krien <[email protected]>
4
5
SPDX-License-Identifier: MIT
6
"""
7
8
9
import calendar
10
import logging
11
import os
12
13
import pandas as pd
14
from reegis import demand_elec
15
from reegis import demand_heat
16
17
from scenario_builder import config as cfg
18
19
20
def get_heat_profiles_deflex(
21
    deflex_geo, year, time_index=None, weather_year=None, keep_unit=False
22
):
23
    """
24
25
    Parameters
26
    ----------
27
    year
28
    deflex_geo
29
    time_index
30
    weather_year
31
    keep_unit
32
33
    Returns
34
    -------
35
36
    """
37
    # separate_regions=keep all demand connected to the region
38
    separate_regions = cfg.get_list("demand_heat", "separate_heat_regions")
39
    # Add lower and upper cases to be not case sensitive
40
    separate_regions = [x.upper() for x in separate_regions] + [
41
        x.lower() for x in separate_regions
42
    ]
43
44
    # add second fuel to first
45
    combine_fuels = cfg.get_dict("combine_heat_fuels")
46
47
    # fuels to be dissolved per region
48
    region_fuels = cfg.get_list("demand_heat", "local_fuels")
49
50
    fn = os.path.join(
51
        cfg.get("paths", "demand"),
52
        "heat_profiles_{year}_{map}".format(year=year, map=deflex_geo.name),
53
    )
54
55
    demand_region = (
56
        demand_heat.get_heat_profiles_by_region(
57
            deflex_geo, year, to_csv=fn, weather_year=weather_year
58
        )
59
        .groupby(level=[0, 1], axis=1)
60
        .sum()
61
    )
62
63
    # Decentralised demand is combined to a nation-wide demand if not part
64
    # of region_fuels.
65
    regions = list(
66
        set(demand_region.columns.get_level_values(0).unique())
67
        - set(separate_regions)
68
    )
69
70
    # If region_fuels is 'all' fetch all fuels to be local.
71
    if "all" in region_fuels:
72
        region_fuels = demand_region.columns.get_level_values(1).unique()
73
74
    for fuel in demand_region.columns.get_level_values(1).unique():
75
        demand_region["DE_demand", fuel] = 0
76
77
    for region in regions:
78
        for f1, f2 in combine_fuels.items():
79
            demand_region[region, f1] += demand_region[region, f2]
80
            demand_region.drop((region, f2), axis=1, inplace=True)
81
        cols = list(set(demand_region[region].columns) - set(region_fuels))
82
        for col in cols:
83
            demand_region["DE_demand", col] += demand_region[region, col]
84
            demand_region.drop((region, col), axis=1, inplace=True)
85
86
    if time_index is not None:
87
        demand_region.index = time_index
88
89
    if not keep_unit:
90
        msg = (
91
            "The unit of the source is 'TJ'. "
92
            "Will be divided by {0} to get 'MWh'."
93
        )
94
        converter = 0.0036
95
        demand_region = demand_region.div(converter)
96
        logging.debug(msg.format(converter))
97
98
    demand_region.sort_index(1, inplace=True)
99
100
    for c in demand_region.columns:
101
        if demand_region[c].sum() == 0:
102
            demand_region.drop(c, axis=1, inplace=True)
103
104
    return demand_region
105
106
107
def scenario_demand(regions, year, name, weather_year=None):
108
    """
109
110
    Parameters
111
    ----------
112
    regions
113
    year
114
    name
115
    weather_year
116
117
    Returns
118
    -------
119
120
    Examples
121
    --------
122
    >>> from reegis import geometries  # doctest: +SKIP
123
    >>> fs=geometries.get_federal_states_polygon()  # doctest: +SKIP
124
    >>> my_demand=scenario_demand(regions, 2014, "de21")  # doctest: +SKIP
125
    >>> int(my_demand["DE01", "district heating"].sum())  # doctest: +SKIP
126
    18639262
127
    >>> int(my_demand["DE05", "electrical_load"].sum())  # doctest: +SKIP
128
    10069304
129
130
    """
131
    demand_series = scenario_elec_demand(
132
        pd.DataFrame(), regions, year, name, weather_year=weather_year
133
    )
134
    if cfg.get("basic", "heat"):
135
        demand_series = scenario_heat_demand(
136
            demand_series, regions, year, weather_year=weather_year
137
        )
138
    return demand_series
139
140
141
def scenario_heat_demand(table, regions, year, weather_year=None):
142
    """
143
144
    Parameters
145
    ----------
146
    table
147
    regions
148
    year
149
    weather_year
150
151
    Returns
152
    -------
153
154
    """
155
    idx = table.index  # Use the index of the existing time series
156
    table = pd.concat(
157
        [
158
            table,
159
            get_heat_profiles_deflex(
160
                regions, year, idx, weather_year=weather_year
161
            ),
162
        ],
163
        axis=1,
164
    )
165
    return table.sort_index(1)
166
167
168
def scenario_elec_demand(table, regions, year, name, weather_year=None):
169
    """
170
171
    Parameters
172
    ----------
173
    table
174
    regions
175
    year
176
    name
177
    weather_year
178
179
    Returns
180
    -------
181
182
    """
183
    if weather_year is None:
184
        demand_year = year
185
    else:
186
        demand_year = weather_year
187
188
    df = demand_elec.get_entsoe_profile_by_region(
189
        regions, demand_year, name, annual_demand="bmwi"
190
    )
191
    df = pd.concat([df], axis=1, keys=["electrical_load"]).swaplevel(0, 1, 1)
192
    df = df.reset_index(drop=True)
193
    if not calendar.isleap(year) and len(df) > 8760:
194
        df = df.iloc[:8760]
195
    return pd.concat([table, df], axis=1).sort_index(1)
196
197
198
if __name__ == "__main__":
199
    pass
200