Passed
Pull Request — master (#2)
by Uwe
01:11
created

scenario_builder.demand.get_heat_profiles_deflex()   C

Complexity

Conditions 10

Size

Total Lines 82
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 41
nop 5
dl 0
loc 82
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("creator", "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
    combine_fuels = {"natural gas": "gas"}
47
48
    # fuels to be dissolved per region
49
    region_fuels = cfg.get_list("creator", "local_fuels")
50
51
    fn = os.path.join(
52
        cfg.get("paths", "demand"),
53
        "heat_profiles_{year}_{map}".format(year=year, map=deflex_geo.name),
54
    )
55
56
    demand_region = (
57
        demand_heat.get_heat_profiles_by_region(
58
            deflex_geo, year, to_csv=fn, weather_year=weather_year
59
        )
60
        .groupby(level=[0, 1], axis=1)
61
        .sum()
62
    )
63
64
    # Decentralised demand is combined to a nation-wide demand if not part
65
    # of region_fuels.
66
    regions = list(
67
        set(demand_region.columns.get_level_values(0).unique()) - 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 = "The unit of the source is 'TJ'. " "Will be divided by {0} to get 'MWh'."
91
        converter = 0.0036
92
        demand_region = demand_region.div(converter)
93
        logging.debug(msg.format(converter))
94
95
    demand_region.sort_index(1, inplace=True)
96
97
    for c in demand_region.columns:
98
        if demand_region[c].sum() == 0:
99
            demand_region.drop(c, axis=1, inplace=True)
100
101
    return demand_region
102
103
104
def scenario_demand(regions, year, name, opsd_version=None, weather_year=None):
105
    """
106
107
    Parameters
108
    ----------
109
    regions
110
    year
111
    name
112
    opsd_version
113
    weather_year
114
115
    Returns
116
    -------
117
118
    Examples
119
    --------
120
    >>> from reegis import geometries  # doctest: +SKIP
121
    >>> fs=geometries.get_federal_states_polygon()  # 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
        version=opsd_version
132
    )
133
    if cfg.get("creator", "heat"):
134
        demand_series = scenario_heat_demand(
135
            demand_series, regions, year, weather_year=weather_year
136
        )
137
    return demand_series
138
139
140
def scenario_heat_demand(table, regions, year, weather_year=None):
141
    """
142
143
    Parameters
144
    ----------
145
    table
146
    regions
147
    year
148
    weather_year
149
150
    Returns
151
    -------
152
153
    """
154
    idx = table.index  # Use the index of the existing time series
155
    table = pd.concat(
156
        [
157
            table,
158
            get_heat_profiles_deflex(regions, year, idx, weather_year=weather_year),
159
        ],
160
        axis=1,
161
    )
162
    return table.sort_index(1)
163
164
165
def scenario_elec_demand(table, regions, year, name, version=None, weather_year=None):
166
    """
167
168
    Parameters
169
    ----------
170
    table
171
    regions
172
    year
173
    name
174
    weather_year
175
176
    Returns
177
    -------
178
179
    """
180
    if weather_year is None:
181
        demand_year = year
182
    else:
183
        demand_year = weather_year
184
185
    df = demand_elec.get_entsoe_profile_by_region(
186
        regions, demand_year, name, annual_demand="bmwi", version=version
187
    )
188
    df = pd.concat([df], axis=1, keys=["electrical_load"]).swaplevel(0, 1, 1)
189
    df = df.reset_index(drop=True)
190
    if not calendar.isleap(year) and len(df) > 8760:
191
        df = df.iloc[:8760]
192
    return pd.concat([table, df], axis=1).sort_index(1)
193
194
195
if __name__ == "__main__":
196
    pass
197