Passed
Pull Request — dev (#1181)
by
unknown
05:34
created

data.datasets.gas_areas.create_voronoi()   B

Complexity

Conditions 4

Size

Total Lines 87
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 38
dl 0
loc 87
rs 8.968
c 0
b 0
f 0
cc 4
nop 2

How to fix   Long Method   

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:

1
"""
2
The central module containing code to create CH4 and H2 voronoi polygons
3
4
"""
5
import datetime
6
import json
7
import pandas as pd
8
9
from geoalchemy2.types import Geometry
10
from sqlalchemy import BigInteger, Column, Text
11
from sqlalchemy.ext.declarative import declarative_base
12
13
from egon.data import db, config
14
from egon.data.datasets import Dataset, wrapped_partial
15
from egon.data.datasets.generate_voronoi import get_voronoi_geodataframe
16
from egon.data.metadata import (
17
    context,
18
    contributors,
19
    license_egon_data_odbl,
20
    meta_metadata,
21
    sources,
22
)
23
24
25
Base = declarative_base()
26
27
28
class EgonPfHvGasVoronoi(Base):
29
    """
30
    Class definition of table grid.egon_gas_voronoi
31
    """
32
33
34
    source_list = [
35
        sources()["openstreetmap"],
36
        sources()["SciGRID_gas"],
37
        sources()["bgr_inspeeds_data_bundle"],
38
    ]
39
    meta = {
40
        "name": "grid.egon_gas_voronoi",
41
        "title": "Gas voronoi areas",
42
        "id": "WILL_BE_SET_AT_PUBLICATION",
43
        "description": "H2 and CH4 voronoi cells",
44
        "language": ["en-EN"],
45
        "publicationDate": datetime.date.today().isoformat(),
46
        "context": context(),
47
        "spatial": {
48
            "location": None,
49
            "extent": "Germany",
50
            "resolution": None,
51
        },
52
        "sources": source_list,
53
        "licenses": [license_egon_data_odbl()],
54
        "contributors": contributors(["fw"]),
55
        "resources": [
56
            {
57
                "profile": "tabular-data-resource",
58
                "name": "grid.egon_gas_voronoi",
59
                "path": None,
60
                "format": "PostgreSQL",
61
                "encoding": "UTF-8",
62
                "schema": {
63
                    "fields": [
64
                        {
65
                            "name": "scn_name",
66
                            "description": "Name of the scenario",
67
                            "type": "str",
68
                            "unit": None,
69
                        },
70
                        {
71
                            "name": "bus_id",
72
                            "description": "Unique identifier",
73
                            "type": "integer",
74
                            "unit": None,
75
                        },
76
                        {
77
                            "name": "carrier",
78
                            "description": "Carrier of the voronoi cell",
79
                            "type": "str",
80
                            "unit": None,
81
                        },
82
                        {
83
                            "name": "geom",
84
                            "description": "Voronoi cell geometry",
85
                            "type": "Geometry(Polygon, 4326)",
86
                            "unit": None,
87
                        },
88
                    ],
89
                    "primaryKey": ["scn_name", "bus_id"],
90
                    "foreignKeys": [],
91
                },
92
                "dialect": {"delimiter": None, "decimalSeparator": "."},
93
            }
94
        ],
95
        "metaMetadata": meta_metadata(),
96
    }
97
    # Create json dump
98
    meta_json = "'" + json.dumps(meta, indent=4, ensure_ascii=False) + "'"
99
100
    __tablename__ = "egon_gas_voronoi"
101
    __table_args__ = {
102
        "schema": "grid",
103
        "comment": meta_json,
104
    }
105
106
    #: Name of the scenario
107
    scn_name = Column(Text, primary_key=True, nullable=False)
108
    #: Bus of the corresponding area
109
    bus_id = Column(BigInteger, primary_key=True, nullable=False)
110
    #: Gas carrier of the voronoi area ("CH4", "H2" or "H2_saltcavern")
111
    carrier = Column(Text)
112
    #: Geometry of the corresponding area
113
    geom = Column(Geometry("GEOMETRY", 4326))
114
115
116
def create_gas_voronoi_table():
117
    """
118
    Create gas voronoi table
119
    """
120
    engine = db.engine()
121
    EgonPfHvGasVoronoi.__table__.drop(bind=engine, checkfirst=True)
122
    EgonPfHvGasVoronoi.__table__.create(bind=engine, checkfirst=True)
123
124
125
def voronoi_egon2035():
126
    """
127
    Create voronoi polygons for all gas carriers in eGon2035 scenario
128
    """
129
    for carrier in ["CH4", "H2", "H2_saltcavern"]:
130
        create_voronoi("eGon2035", carrier)
131
132
133
def voronoi_egon100RE():
134
    """
135
    Create voronoi polygons for all gas carriers in eGon100RE scenario
136
    """
137
    for carrier in ["CH4", "H2", "H2_saltcavern"]:
138
        create_voronoi("eGon100RE", carrier)
139
140
141
def voronoi_status(scn_name):
142
    """
143
    Create voronoi polygons for all gas carriers in status_x scenario
144
    """
145
    for carrier in ["CH4"]:
146
        create_voronoi(scn_name, carrier)
147
148
149
def create_voronoi(scn_name, carrier):
150
    """
151
    Create voronoi polygons for specified carrier in specified scenario.
152
153
    Parameters
154
    ----------
155
    scn_name : str
156
        Name of the scenario
157
    carrier : str
158
        Name of the carrier
159
    """
160
161
    engine = db.engine()
162
163
    table_exist = (
164
        len(
165
            pd.read_sql(
166
                """
167
    SELECT *
168
    FROM information_schema.tables
169
    WHERE table_schema = 'grid'
170
        AND table_name = 'egon_gas_voronoi'
171
    LIMIT 1;
172
        """,
173
                engine,
174
            )
175
        )
176
        > 0
177
    )
178
179
    if not table_exist:
180
        create_gas_voronoi_table()
181
182
    boundary = db.select_geodataframe(
183
        """
184
            SELECT id, geometry
185
            FROM boundaries.vg250_sta_union;
186
        """,
187
        geom_col="geometry",
188
    ).to_crs(epsg=4326)
189
190
    db.execute_sql(
191
        f"""
192
        DELETE FROM grid.egon_gas_voronoi
193
        WHERE "carrier" = '{carrier}' and "scn_name" = '{scn_name}';
194
        """
195
    )
196
197
    buses = db.select_geodataframe(
198
        f"""
199
            SELECT bus_id, geom
200
            FROM grid.egon_etrago_bus
201
            WHERE scn_name = '{scn_name}'
202
            AND country = 'DE'
203
            AND carrier = '{carrier}';
204
        """,
205
    ).to_crs(epsg=4326)
206
207
    if len(buses) == 0:
208
        return
209
210
    # generate voronois
211
    # For some scenarios it is defined that there is only 1 bus (e.g. gas). It
212
    # means that there will be just 1 voronoi covering the entire german
213
    # territory. For other scenarios with more buses, voronois are calculated.
214
    if len(buses) == 1:
215
        gdf = buses.copy()
216
        gdf.at[0, "geom"] = boundary.at[0, "geometry"]
217
    else:
218
        buses["x"] = buses.geometry.x
219
        buses["y"] = buses.geometry.y
220
        gdf = get_voronoi_geodataframe(buses, boundary.geometry.iloc[0])
221
        gdf.rename_geometry("geom", inplace=True)
222
        gdf.drop(columns=["id"], inplace=True)
223
224
    # set scn_name and carrier
225
    gdf["scn_name"] = scn_name
226
    gdf["carrier"] = carrier
227
228
    # Insert data to db
229
    gdf.set_crs(epsg=4326).to_postgis(
230
        f"egon_gas_voronoi",
231
        engine,
232
        schema="grid",
233
        index=False,
234
        if_exists="append",
235
        dtype={"geom": Geometry},
236
    )
237
238
239
class GasAreas(Dataset):
240
    """Create the gas voronoi table and the gas voronoi areas
241
242
    *Dependencies*
243
      * :py:class:`EtragoSetup <egon.data.datasets.etrago_setup.EtragoSetup>`
244
      * :py:class:`HydrogenBusEtrago <egon.data.datasets.hydrogen_etrago.HydrogenBusEtrago>`
245
      * :py:class:`Vg250 <egon.data.datasets.vg250.Vg250>`
246
      * :py:class:`GasNodesAndPipes <egon.data.datasets.gas_grid.GasNodesAndPipes>`
247
248
    *Resulting tables*
249
      * :py:class:`EgonPfHvGasVoronoi <EgonPfHvGasVoronoi>`
250
251
    """
252
253
    #:
254
    name: str = "GasAreas"
255
    #:
256
    version: str = "0.0.3"
257
258
    tasks = (create_gas_voronoi_table,)
259
    extra_dependencies = ()
260
261
    if "eGon2035" in config.settings()["egon-data"]["--scenarios"]:
262
        tasks = tasks + (voronoi_egon2035,)
263
264
    if "eGon100RE" in config.settings()["egon-data"]["--scenarios"]:
265
        tasks = tasks + (voronoi_egon100RE,)
266
        extra_dependencies = extra_dependencies + ("insert_h2_grid",)
267
268
    for scn_name in config.settings()["egon-data"]["--scenarios"]:
269
        if "status" in scn_name:
270
            tasks += (wrapped_partial(
271
                voronoi_status, scn_name=scn_name, postfix=f"_{scn_name[-4:]}"
272
            ),)
273
274
    def __init__(self, dependencies):
275
        super().__init__(
276
            name=self.name,
277
            version=self.version,
278
            dependencies=dependencies,
279
            tasks=self.tasks,
280
        )
281