Passed
Pull Request — master (#2)
by Uwe
01:06
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 config as cfg
15
from reegis import demand_elec
16
from reegis import demand_heat
17
18
19
def get_heat_profiles_deflex(
20
    deflex_geo, year, time_index=None, weather_year=None, keep_unit=False
21
):
22
    """
23
24
    Parameters
25
    ----------
26
    year
27
    deflex_geo
28
    time_index
29
    weather_year
30
    keep_unit
31
32
    Returns
33
    -------
34
35
    """
36
    # separate_regions=keep all demand connected to the region
37
    separate_regions = cfg.get_list("creator", "separate_heat_regions")
38
    # Add lower and upper cases to be not case sensitive
39
    separate_regions = [x.upper() for x in separate_regions] + [
40
        x.lower() for x in separate_regions
41
    ]
42
43
    # add second fuel to first
44
    # combine_fuels = cfg.get_dict("combine_heat_fuels")
45
    combine_fuels = {"natural gas": "gas"}
46
47
    # fuels to be dissolved per region
48
    region_fuels = cfg.get_list("creator", "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()) - 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 = "The unit of the source is 'TJ'. " "Will be divided by {0} to get 'MWh'."
90
        converter = 0.0036
91
        demand_region = demand_region.div(converter)
92
        logging.debug(msg.format(converter))
93
94
    demand_region.sort_index(1, inplace=True)
95
96
    for c in demand_region.columns:
97
        if demand_region[c].sum() == 0:
98
            demand_region.drop(c, axis=1, inplace=True)
99
100
    return demand_region
101
102
103
def scenario_demand(regions, year, name, opsd_version=None, weather_year=None):
104
    """
105
106
    Parameters
107
    ----------
108
    regions
109
    year
110
    name
111
    opsd_version
112
    weather_year
113
114
    Returns
115
    -------
116
117
    Examples
118
    --------
119
    >>> from reegis import geometries  # doctest: +SKIP
120
    >>> fs=geometries.get_federal_states_polygon()  # doctest: +SKIP
121
    >>> my_demand=scenario_demand(regions, 2014, "de21")  # doctest: +SKIP
122
    >>> int(my_demand["DE01", "district heating"].sum())  # doctest: +SKIP
123
    18639262
124
    >>> int(my_demand["DE05", "electrical_load"].sum())  # doctest: +SKIP
125
    10069304
126
127
    """
128
    demand_series = scenario_elec_demand(
129
        pd.DataFrame(), regions, year, name, weather_year=weather_year,
130
        version=opsd_version
131
    )
132
    if cfg.get("creator", "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(regions, year, idx, weather_year=weather_year),
158
        ],
159
        axis=1,
160
    )
161
    return table.sort_index(1)
162
163
164
def scenario_elec_demand(table, regions, year, name, version=None, weather_year=None):
165
    """
166
167
    Parameters
168
    ----------
169
    table
170
    regions
171
    year
172
    name
173
    weather_year
174
175
    Returns
176
    -------
177
178
    """
179
    if weather_year is None:
180
        demand_year = year
181
    else:
182
        demand_year = weather_year
183
184
    df = demand_elec.get_entsoe_profile_by_region(
185
        regions, demand_year, name, annual_demand="bmwi", version=version
186
    )
187
    df = pd.concat([df], axis=1, keys=["electrical_load"]).swaplevel(0, 1, 1)
188
    df = df.reset_index(drop=True)
189
    if not calendar.isleap(year) and len(df) > 8760:
190
        df = df.iloc[:8760]
191
    return pd.concat([table, df], axis=1).sort_index(1)
192
193
194
if __name__ == "__main__":
195
    pass
196