Completed
Pull Request — master (#2)
by Uwe
03:50
created

scenario_builder.demand.get_heat_profiles_deflex()   C

Complexity

Conditions 10

Size

Total Lines 84
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 43
nop 5
dl 0
loc 84
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
    # add second fuel to first
44
    combine_fuels = cfg.get_dict("combine_heat_fuels")
45
46
    # fuels to be dissolved per region
47
    region_fuels = cfg.get_list("demand_heat", "local_fuels")
48
49
    fn = os.path.join(
50
        cfg.get("paths", "demand"),
51
        "heat_profiles_{year}_{map}".format(year=year, map=deflex_geo.name),
52
    )
53
54
    demand_region = (
55
        demand_heat.get_heat_profiles_by_region(
56
            deflex_geo, year, to_csv=fn, weather_year=weather_year
57
        )
58
        .groupby(level=[0, 1], axis=1)
59
        .sum()
60
    )
61
62
    # Decentralised demand is combined to a nation-wide demand if not part
63
    # of region_fuels.
64
    regions = list(
65
        set(demand_region.columns.get_level_values(0).unique())
66
        - set(separate_regions)
67
    )
68
69
    # If region_fuels is 'all' fetch all fuels to be local.
70
    if "all" in region_fuels:
71
        region_fuels = demand_region.columns.get_level_values(1).unique()
72
73
    for fuel in demand_region.columns.get_level_values(1).unique():
74
        demand_region["DE_demand", fuel] = 0
75
76
    for region in regions:
77
        for f1, f2 in combine_fuels.items():
78
            demand_region[region, f1] += demand_region[region, f2]
79
            demand_region.drop((region, f2), axis=1, inplace=True)
80
        cols = list(set(demand_region[region].columns) - set(region_fuels))
81
        for col in cols:
82
            demand_region["DE_demand", col] += demand_region[region, col]
83
            demand_region.drop((region, col), axis=1, inplace=True)
84
85
    if time_index is not None:
86
        demand_region.index = time_index
87
88
    if not keep_unit:
89
        msg = (
90
            "The unit of the source is 'TJ'. "
91
            "Will be divided by {0} to get 'MWh'."
92
        )
93
        converter = 0.0036
94
        demand_region = demand_region.div(converter)
95
        logging.debug(msg.format(converter))
96
97
    demand_region.sort_index(1, inplace=True)
98
99
    for c in demand_region.columns:
100
        if demand_region[c].sum() == 0:
101
            demand_region.drop(c, axis=1, inplace=True)
102
103
    return demand_region
104
105
106
def scenario_demand(regions, year, name, weather_year=None):
107
    """
108
109
    Parameters
110
    ----------
111
    regions
112
    year
113
    name
114
    weather_year
115
116
    Returns
117
    -------
118
119
    Examples
120
    --------
121
    >>> regions=geometries.deflex_regions(rmap="de21")  # doctest: +SKIP
122
    >>> my_demand=scenario_demand(regions, 2014, "de21")  # doctest: +SKIP
123
    >>> int(my_demand["DE01", "district heating"].sum())  # doctest: +SKIP
124
    18639262
125
    >>> int(my_demand["DE05", "electrical_load"].sum())  # doctest: +SKIP
126
    10069304
127
128
    """
129
    demand_series = scenario_elec_demand(
130
        pd.DataFrame(), regions, year, name, weather_year=weather_year
131
    )
132
    if cfg.get("basic", "heat"):
133
        demand_series = scenario_heat_demand(
134
            demand_series, regions, year, weather_year=weather_year
135
        )
136
    return demand_series
137
138
139
def scenario_heat_demand(table, regions, year, weather_year=None):
140
    """
141
142
    Parameters
143
    ----------
144
    table
145
    regions
146
    year
147
    weather_year
148
149
    Returns
150
    -------
151
152
    """
153
    idx = table.index  # Use the index of the existing time series
154
    table = pd.concat(
155
        [
156
            table,
157
            get_heat_profiles_deflex(
158
                regions, year, idx, weather_year=weather_year
159
            ),
160
        ],
161
        axis=1,
162
    )
163
    return table.sort_index(1)
164
165
166
def scenario_elec_demand(table, regions, year, name, weather_year=None):
167
    """
168
169
    Parameters
170
    ----------
171
    table
172
    regions
173
    year
174
    name
175
    weather_year
176
177
    Returns
178
    -------
179
180
    """
181
    if weather_year is None:
182
        demand_year = year
183
    else:
184
        demand_year = weather_year
185
186
    df = demand_elec.get_entsoe_profile_by_region(
187
        regions, demand_year, name, annual_demand="bmwi"
188
    )
189
    df = pd.concat([df], axis=1, keys=["electrical_load"]).swaplevel(0, 1, 1)
190
    df = df.reset_index(drop=True)
191
    if not calendar.isleap(year) and len(df) > 8760:
192
        df = df.iloc[:8760]
193
    return pd.concat([table, df], axis=1).sort_index(1)
194
195
196
if __name__ == "__main__":
197
    pass
198