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

data.datasets.power_plants   F

Complexity

Total Complexity 61

Size/Duplication

Total Lines 1395
Duplicated Lines 5.66 %

Importance

Changes 0
Metric Value
wmc 61
eloc 738
dl 79
loc 1395
rs 3.382
c 0
b 0
f 0

15 Functions

Rating   Name   Duplication   Size   Complexity  
A select_target() 0 34 1
A filter_mastr_geometry() 0 55 3
B allocate_other_power_plants() 0 167 4
B assign_bus_id() 66 66 5
B insert_biomass_plants() 0 72 5
A insert_hydro_biomass() 0 26 4
A scale_prox2now() 0 32 3
A create_tables() 0 34 2
B insert_hydro_plants() 0 86 5
B assign_voltage_level() 0 88 4
B get_conventional_power_plants_non_chp() 0 125 2
A discard_not_available_generators() 0 22 1
B assign_voltage_level_by_capacity() 0 20 7
C allocate_conventional_non_chp_power_plants() 0 163 5
D power_plants_status_quo() 0 221 9

1 Method

Rating   Name   Duplication   Size   Complexity  
A PowerPlants.__init__() 0 6 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like data.datasets.power_plants 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
"""The central module containing all code dealing with power plant data.
2
"""
3
4
from pathlib import Path
5
6
from geoalchemy2 import Geometry
7
from shapely.geometry import Point
8
from sqlalchemy import BigInteger, Column, Float, Integer, Sequence, String
9
from sqlalchemy.dialects.postgresql import JSONB
10
from sqlalchemy.ext.declarative import declarative_base
11
from sqlalchemy.orm import sessionmaker
12
import geopandas as gpd
13
import numpy as np
14
import pandas as pd
15
16
from egon.data import db, logger
17
from egon.data.datasets import Dataset, wrapped_partial
18
from egon.data.datasets.mastr import (
19
    WORKING_DIR_MASTR_NEW,
20
    WORKING_DIR_MASTR_OLD,
21
)
22
from egon.data.datasets.power_plants.conventional import (
23
    match_nep_no_chp,
24
    select_nep_power_plants,
25
    select_no_chp_combustion_mastr,
26
)
27
from egon.data.datasets.power_plants.mastr import (
28
    EgonPowerPlantsBiomass,
29
    EgonPowerPlantsHydro,
30
    EgonPowerPlantsPv,
31
    EgonPowerPlantsWind,
32
    import_mastr,
33
)
34
from egon.data.datasets.power_plants.pv_rooftop import pv_rooftop_per_mv_grid
35
from egon.data.datasets.power_plants.pv_rooftop_buildings import (
36
    pv_rooftop_to_buildings,
37
)
38
import egon.data.config
39
import egon.data.datasets.power_plants.assign_weather_data as assign_weather_data  # noqa: E501
40
import egon.data.datasets.power_plants.metadata as pp_metadata
41
import egon.data.datasets.power_plants.pv_ground_mounted as pv_ground_mounted
42
import egon.data.datasets.power_plants.wind_farms as wind_onshore
43
import egon.data.datasets.power_plants.wind_offshore as wind_offshore
44
45
Base = declarative_base()
46
47
48 View Code Duplication
class EgonPowerPlants(Base):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
49
    __tablename__ = "egon_power_plants"
50
    __table_args__ = {"schema": "supply"}
51
    id = Column(BigInteger, Sequence("pp_seq"), primary_key=True)
52
    sources = Column(JSONB)
53
    source_id = Column(JSONB)
54
    carrier = Column(String)
55
    el_capacity = Column(Float)
56
    bus_id = Column(Integer)
57
    voltage_level = Column(Integer)
58
    weather_cell_id = Column(Integer)
59
    scenario = Column(String)
60
    geom = Column(Geometry("POINT", 4326), index=True)
61
62
63
def create_tables():
64
    """Create tables for power plant data
65
    Returns
66
    -------
67
    None.
68
    """
69
70
    # Tables for future scenarios
71
    cfg = egon.data.config.datasets()["power_plants"]
72
    db.execute_sql(f"CREATE SCHEMA IF NOT EXISTS {cfg['target']['schema']};")
73
    engine = db.engine()
74
    db.execute_sql(
75
        f"""DROP TABLE IF EXISTS
76
        {cfg['target']['schema']}.{cfg['target']['table']}"""
77
    )
78
79
    db.execute_sql("""DROP SEQUENCE IF EXISTS pp_seq""")
80
    EgonPowerPlants.__table__.create(bind=engine, checkfirst=True)
81
82
    # Tables for status quo
83
    tables = [
84
        EgonPowerPlantsWind,
85
        EgonPowerPlantsPv,
86
        EgonPowerPlantsBiomass,
87
        EgonPowerPlantsHydro,
88
    ]
89
    for t in tables:
90
        db.execute_sql(
91
            f"""
92
            DROP TABLE IF EXISTS {t.__table_args__['schema']}.
93
            {t.__tablename__} CASCADE;
94
            """
95
        )
96
        t.__table__.create(bind=engine, checkfirst=True)
97
98
99
def scale_prox2now(df, target, level="federal_state"):
100
    """Scale installed capacities linear to status quo power plants
101
102
    Parameters
103
    ----------
104
    df : pandas.DataFrame
105
        Status Quo power plants
106
    target : pandas.Series
107
        Target values for future scenario
108
    level : str, optional
109
        Scale per 'federal_state' or 'country'. The default is 'federal_state'.
110
111
    Returns
112
    -------
113
    df : pandas.DataFrame
114
        Future power plants
115
116
    """
117
    if level == "federal_state":
118
        df.loc[:, "Nettonennleistung"] = (
119
            df.groupby(df.Bundesland)
120
            .Nettonennleistung.apply(lambda grp: grp / grp.sum())
121
            .mul(target[df.Bundesland.values].values)
122
        )
123
    else:
124
        df.loc[:, "Nettonennleistung"] = df.Nettonennleistung * (
125
            target / df.Nettonennleistung.sum()
126
        )
127
128
    df = df[df.Nettonennleistung > 0]
129
130
    return df
131
132
133
def select_target(carrier, scenario):
134
    """Select installed capacity per scenario and carrier
135
136
    Parameters
137
    ----------
138
    carrier : str
139
        Name of energy carrier
140
    scenario : str
141
        Name of scenario
142
143
    Returns
144
    -------
145
    pandas.Series
146
        Target values for carrier and scenario
147
148
    """
149
    cfg = egon.data.config.datasets()["power_plants"]
150
151
    return (
152
        pd.read_sql(
153
            f"""SELECT DISTINCT ON (b.gen)
154
                         REPLACE(REPLACE(b.gen, '-', ''), 'ü', 'ue') as state,
155
                         a.capacity
156
                         FROM {cfg['sources']['capacities']} a,
157
                         {cfg['sources']['geom_federal_states']} b
158
                         WHERE a.nuts = b.nuts
159
                         AND scenario_name = '{scenario}'
160
                         AND carrier = '{carrier}'
161
                         AND b.gen NOT IN ('Baden-Württemberg (Bodensee)',
162
                                           'Bayern (Bodensee)')""",
163
            con=db.engine(),
164
        )
165
        .set_index("state")
166
        .capacity
167
    )
168
169
170
def filter_mastr_geometry(mastr, federal_state=None):
171
    """Filter data from MaStR by geometry
172
173
    Parameters
174
    ----------
175
    mastr : pandas.DataFrame
176
        All power plants listed in MaStR
177
    federal_state : str or None
178
        Name of federal state whoes power plants are returned.
179
        If None, data for Germany is returned
180
181
    Returns
182
    -------
183
    mastr_loc : pandas.DataFrame
184
        Power plants listed in MaStR with geometry inside German boundaries
185
186
    """
187
    cfg = egon.data.config.datasets()["power_plants"]
188
189
    if type(mastr) == pd.core.frame.DataFrame:
190
        # Drop entries without geometry for insert
191
        mastr_loc = mastr[
192
            mastr.Laengengrad.notnull() & mastr.Breitengrad.notnull()
193
        ]
194
195
        # Create geodataframe
196
        mastr_loc = gpd.GeoDataFrame(
197
            mastr_loc,
198
            geometry=gpd.points_from_xy(
199
                mastr_loc.Laengengrad, mastr_loc.Breitengrad, crs=4326
200
            ),
201
        )
202
    else:
203
        mastr_loc = mastr.copy()
204
205
    # Drop entries outside of germany or federal state
206
    if not federal_state:
207
        sql = f"SELECT geometry as geom FROM {cfg['sources']['geom_germany']}"
208
    else:
209
        sql = f"""
210
        SELECT geometry as geom
211
        FROM boundaries.vg250_lan_union
212
        WHERE REPLACE(REPLACE(gen, '-', ''), 'ü', 'ue') = '{federal_state}'"""
213
214
    mastr_loc = (
215
        gpd.sjoin(
216
            gpd.read_postgis(sql, con=db.engine()).to_crs(4326),
217
            mastr_loc,
218
            how="right",
219
        )
220
        .query("index_left==0")
221
        .drop("index_left", axis=1)
222
    )
223
224
    return mastr_loc
225
226
227
def insert_biomass_plants(scenario):
228
    """Insert biomass power plants of future scenario
229
230
    Parameters
231
    ----------
232
    scenario : str
233
        Name of scenario.
234
235
    Returns
236
    -------
237
    None.
238
239
    """
240
    cfg = egon.data.config.datasets()["power_plants"]
241
242
    # import target values
243
    target = select_target("biomass", scenario)
244
245
    # import data for MaStR
246
    mastr = pd.read_csv(
247
        WORKING_DIR_MASTR_OLD / cfg["sources"]["mastr_biomass"]
248
    ).query("EinheitBetriebsstatus=='InBetrieb'")
249
250
    # Drop entries without federal state or 'AusschließlichWirtschaftszone'
251
    mastr = mastr[
252
        mastr.Bundesland.isin(
253
            pd.read_sql(
254
                f"""SELECT DISTINCT ON (gen)
255
        REPLACE(REPLACE(gen, '-', ''), 'ü', 'ue') as states
256
        FROM {cfg['sources']['geom_federal_states']}""",
257
                con=db.engine(),
258
            ).states.values
259
        )
260
    ]
261
262
    # Scaling will be done per federal state in case of eGon2035 scenario.
263
    if scenario == "eGon2035":
264
        level = "federal_state"
265
    else:
266
        level = "country"
267
268
    # Choose only entries with valid geometries inside DE/test mode
269
    mastr_loc = filter_mastr_geometry(mastr).set_geometry("geometry")
270
271
    # Scale capacities to meet target values
272
    mastr_loc = scale_prox2now(mastr_loc, target, level=level)
273
274
    # Assign bus_id
275
    if len(mastr_loc) > 0:
276
        mastr_loc["voltage_level"] = assign_voltage_level(
277
            mastr_loc, cfg, WORKING_DIR_MASTR_OLD
278
        )
279
        mastr_loc = assign_bus_id(mastr_loc, cfg)
280
281
    # Insert entries with location
282
    session = sessionmaker(bind=db.engine())()
283
284
    for i, row in mastr_loc.iterrows():
285
        if not row.ThermischeNutzleistung > 0:
286
            entry = EgonPowerPlants(
287
                sources={"el_capacity": "MaStR scaled with NEP 2021"},
288
                source_id={"MastrNummer": row.EinheitMastrNummer},
289
                carrier="biomass",
290
                el_capacity=row.Nettonennleistung,
291
                scenario=scenario,
292
                bus_id=row.bus_id,
293
                voltage_level=row.voltage_level,
294
                geom=f"SRID=4326;POINT({row.Laengengrad} {row.Breitengrad})",
295
            )
296
            session.add(entry)
297
298
    session.commit()
299
300
301
def insert_hydro_plants(scenario):
302
    """Insert hydro power plants of future scenario.
303
304
    Hydro power plants are diveded into run_of_river and reservoir plants
305
    according to Marktstammdatenregister.
306
    Additional hydro technologies (e.g. turbines inside drinking water
307
    systems) are not considered.
308
309
    Parameters
310
    ----------
311
    scenario : str
312
        Name of scenario.
313
314
    Returns
315
    -------
316
    None.
317
318
    """
319
    cfg = egon.data.config.datasets()["power_plants"]
320
321
    # Map MaStR carriers to eGon carriers
322
    map_carrier = {
323
        "run_of_river": ["Laufwasseranlage"],
324
        "reservoir": ["Speicherwasseranlage"],
325
    }
326
327
    for carrier in map_carrier.keys():
328
        # import target values
329
        target = select_target(carrier, scenario)
330
331
        # import data for MaStR
332
        mastr = pd.read_csv(
333
            WORKING_DIR_MASTR_NEW / cfg["sources"]["mastr_hydro"]
334
        ).query("EinheitBetriebsstatus=='InBetrieb'")
335
336
        # Choose only plants with specific carriers
337
        mastr = mastr[mastr.ArtDerWasserkraftanlage.isin(map_carrier[carrier])]
338
339
        # Drop entries without federal state or 'AusschließlichWirtschaftszone'
340
        mastr = mastr[
341
            mastr.Bundesland.isin(
342
                pd.read_sql(
343
                    f"""SELECT DISTINCT ON (gen)
344
            REPLACE(REPLACE(gen, '-', ''), 'ü', 'ue') as states
345
            FROM {cfg['sources']['geom_federal_states']}""",
346
                    con=db.engine(),
347
                ).states.values
348
            )
349
        ]
350
351
        # Scaling will be done per federal state in case of eGon2035 scenario.
352
        if scenario == "eGon2035":
353
            level = "federal_state"
354
        else:
355
            level = "country"
356
357
        # Scale capacities to meet target values
358
        mastr = scale_prox2now(mastr, target, level=level)
359
360
        # Choose only entries with valid geometries inside DE/test mode
361
        mastr_loc = filter_mastr_geometry(mastr).set_geometry("geometry")
362
        # TODO: Deal with power plants without geometry
363
364
        # Assign bus_id and voltage level
365
        if len(mastr_loc) > 0:
366
            mastr_loc["voltage_level"] = assign_voltage_level(
367
                mastr_loc, cfg, WORKING_DIR_MASTR_NEW
368
            )
369
            mastr_loc = assign_bus_id(mastr_loc, cfg)
370
371
        # Insert entries with location
372
        session = sessionmaker(bind=db.engine())()
373
        for i, row in mastr_loc.iterrows():
374
            entry = EgonPowerPlants(
375
                sources={"el_capacity": "MaStR scaled with NEP 2021"},
376
                source_id={"MastrNummer": row.EinheitMastrNummer},
377
                carrier=carrier,
378
                el_capacity=row.Nettonennleistung,
379
                scenario=scenario,
380
                bus_id=row.bus_id,
381
                voltage_level=row.voltage_level,
382
                geom=f"SRID=4326;POINT({row.Laengengrad} {row.Breitengrad})",
383
            )
384
            session.add(entry)
385
386
        session.commit()
387
388
389
def assign_voltage_level(mastr_loc, cfg, mastr_working_dir):
390
    """Assigns voltage level to power plants.
391
392
    If location data inluding voltage level is available from
393
    Marktstammdatenregister, this is used. Otherwise the voltage level is
394
    assigned according to the electrical capacity.
395
396
    Parameters
397
    ----------
398
    mastr_loc : pandas.DataFrame
399
        Power plants listed in MaStR with geometry inside German boundaries
400
401
    Returns
402
    -------
403
    pandas.DataFrame
404
        Power plants including voltage_level
405
406
    """
407
    mastr_loc["Spannungsebene"] = np.nan
408
    mastr_loc["voltage_level"] = np.nan
409
410
    if "LokationMastrNummer" in mastr_loc.columns:
411
        # Adjust column names to format of MaStR location dataset
412
        if mastr_working_dir == WORKING_DIR_MASTR_OLD:
413
            cols = ["LokationMastrNummer", "Spannungsebene"]
414
        elif mastr_working_dir == WORKING_DIR_MASTR_NEW:
415
            cols = ["MaStRNummer", "Spannungsebene"]
416
        else:
417
            raise ValueError("Invalid MaStR working directory!")
418
419
        location = (
420
            pd.read_csv(
421
                mastr_working_dir / cfg["sources"]["mastr_location"],
422
                usecols=cols,
423
            )
424
            .rename(columns={"MaStRNummer": "LokationMastrNummer"})
425
            .set_index("LokationMastrNummer")
426
        )
427
428
        location = location[~location.index.duplicated(keep="first")]
429
430
        mastr_loc.loc[
431
            mastr_loc[
432
                mastr_loc.LokationMastrNummer.isin(location.index)
433
            ].index,
434
            "Spannungsebene",
435
        ] = location.Spannungsebene[
436
            mastr_loc[
437
                mastr_loc.LokationMastrNummer.isin(location.index)
438
            ].LokationMastrNummer
439
        ].values
440
441
        # Transfer voltage_level as integer from Spanungsebene
442
        map_voltage_levels = pd.Series(
443
            data={
444
                "Höchstspannung": 1,
445
                "Hoechstspannung": 1,
446
                "UmspannungZurHochspannung": 2,
447
                "Hochspannung": 3,
448
                "UmspannungZurMittelspannung": 4,
449
                "Mittelspannung": 5,
450
                "UmspannungZurNiederspannung": 6,
451
                "Niederspannung": 7,
452
            }
453
        )
454
455
        mastr_loc.loc[
456
            mastr_loc[mastr_loc["Spannungsebene"].notnull()].index,
457
            "voltage_level",
458
        ] = map_voltage_levels[
459
            mastr_loc.loc[
460
                mastr_loc[mastr_loc["Spannungsebene"].notnull()].index,
461
                "Spannungsebene",
462
            ].values
463
        ].values
464
465
    else:
466
        print(
467
            "No information about MaStR location available. "
468
            "All voltage levels are assigned using threshold values."
469
        )
470
471
    # If no voltage level is available from mastr, choose level according
472
    # to threshold values
473
474
    mastr_loc.voltage_level = assign_voltage_level_by_capacity(mastr_loc)
475
476
    return mastr_loc.voltage_level
477
478
479
def assign_voltage_level_by_capacity(mastr_loc):
480
    for i, row in mastr_loc[mastr_loc.voltage_level.isnull()].iterrows():
481
        if row.Nettonennleistung > 120:
482
            level = 1
483
        elif row.Nettonennleistung > 20:
484
            level = 3
485
        elif row.Nettonennleistung > 5.5:
486
            level = 4
487
        elif row.Nettonennleistung > 0.2:
488
            level = 5
489
        elif row.Nettonennleistung > 0.1:
490
            level = 6
491
        else:
492
            level = 7
493
494
        mastr_loc.loc[i, "voltage_level"] = level
495
496
    mastr_loc.voltage_level = mastr_loc.voltage_level.astype(int)
497
498
    return mastr_loc.voltage_level
499
500
501 View Code Duplication
def assign_bus_id(power_plants, cfg, drop_missing=False):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
502
    """Assigns bus_ids to power plants according to location and voltage level
503
504
    Parameters
505
    ----------
506
    power_plants : pandas.DataFrame
507
        Power plants including voltage level
508
509
    Returns
510
    -------
511
    power_plants : pandas.DataFrame
512
        Power plants including voltage level and bus_id
513
514
    """
515
516
    mv_grid_districts = db.select_geodataframe(
517
        f"""
518
        SELECT * FROM {cfg['sources']['egon_mv_grid_district']}
519
        """,
520
        epsg=4326,
521
    )
522
523
    ehv_grid_districts = db.select_geodataframe(
524
        f"""
525
        SELECT * FROM {cfg['sources']['ehv_voronoi']}
526
        """,
527
        epsg=4326,
528
    )
529
530
    # Assign power plants in hv and below to hvmv bus
531
    power_plants_hv = power_plants[power_plants.voltage_level >= 3].index
532
    if len(power_plants_hv) > 0:
533
        power_plants.loc[power_plants_hv, "bus_id"] = gpd.sjoin(
534
            power_plants[power_plants.index.isin(power_plants_hv)],
535
            mv_grid_districts,
536
        ).bus_id
537
538
    # Assign power plants in ehv to ehv bus
539
    power_plants_ehv = power_plants[power_plants.voltage_level < 3].index
540
541
    if len(power_plants_ehv) > 0:
542
        ehv_join = gpd.sjoin(
543
            power_plants[power_plants.index.isin(power_plants_ehv)],
544
            ehv_grid_districts,
545
        )
546
547
        if "bus_id_right" in ehv_join.columns:
548
            power_plants.loc[power_plants_ehv, "bus_id"] = gpd.sjoin(
549
                power_plants[power_plants.index.isin(power_plants_ehv)],
550
                ehv_grid_districts,
551
            ).bus_id_right
552
553
        else:
554
            power_plants.loc[power_plants_ehv, "bus_id"] = gpd.sjoin(
555
                power_plants[power_plants.index.isin(power_plants_ehv)],
556
                ehv_grid_districts,
557
            ).bus_id
558
559
    if drop_missing:
560
        power_plants = power_plants[~power_plants.bus_id.isnull()]
561
562
    # Assert that all power plants have a bus_id
563
    assert power_plants.bus_id.notnull().all(), f"""Some power plants are
564
    not attached to a bus: {power_plants[power_plants.bus_id.isnull()]}"""
565
566
    return power_plants
567
568
569
def insert_hydro_biomass():
570
    """Insert hydro and biomass power plants in database
571
572
    Returns
573
    -------
574
    None.
575
576
    """
577
    cfg = egon.data.config.datasets()["power_plants"]
578
    db.execute_sql(
579
        f"""
580
        DELETE FROM {cfg['target']['schema']}.{cfg['target']['table']}
581
        WHERE carrier IN ('biomass', 'reservoir', 'run_of_river')
582
        """
583
    )
584
585
    s = egon.data.config.settings()["egon-data"]["--scenarios"]
586
    scenarios = []
587
    if "eGon2035" in s:
588
        scenarios.append("eGon2035")
589
        insert_biomass_plants("eGon2035")
590
    if "eGon100RE" in s:
591
        scenarios.append("eGon100RE")
592
593
    for scenario in scenarios:
594
        insert_hydro_plants(scenario)
595
596
597
def allocate_conventional_non_chp_power_plants():
598
    # This function is only designed to work for the eGon2035 scenario
599
    if (
600
        "eGon2035"
601
        not in egon.data.config.settings()["egon-data"]["--scenarios"]
602
    ):
603
        return
604
605
    carrier = ["oil", "gas"]
606
607
    cfg = egon.data.config.datasets()["power_plants"]
608
609
    # Delete existing plants in the target table
610
    db.execute_sql(
611
        f"""
612
         DELETE FROM {cfg ['target']['schema']}.{cfg ['target']['table']}
613
         WHERE carrier IN ('gas', 'oil')
614
         AND scenario='eGon2035';
615
         """
616
    )
617
618
    for carrier in carrier:
619
        nep = select_nep_power_plants(carrier)
620
621
        if nep.empty:
622
            print(f"DataFrame from NEP for carrier {carrier} is empty!")
623
624
        else:
625
            mastr = select_no_chp_combustion_mastr(carrier)
626
627
            # Assign voltage level to MaStR
628
            mastr["voltage_level"] = assign_voltage_level(
629
                mastr.rename({"el_capacity": "Nettonennleistung"}, axis=1),
630
                cfg,
631
                WORKING_DIR_MASTR_OLD,
632
            )
633
634
            # Initalize DataFrame for matching power plants
635
            matched = gpd.GeoDataFrame(
636
                columns=[
637
                    "carrier",
638
                    "el_capacity",
639
                    "scenario",
640
                    "geometry",
641
                    "MaStRNummer",
642
                    "source",
643
                    "voltage_level",
644
                ]
645
            )
646
647
            # Match combustion plants of a certain carrier from NEP list
648
            # using PLZ and capacity
649
            matched, mastr, nep = match_nep_no_chp(
650
                nep,
651
                mastr,
652
                matched,
653
                buffer_capacity=0.1,
654
                consider_carrier=False,
655
            )
656
657
            # Match plants from NEP list using city and capacity
658
            matched, mastr, nep = match_nep_no_chp(
659
                nep,
660
                mastr,
661
                matched,
662
                buffer_capacity=0.1,
663
                consider_carrier=False,
664
                consider_location="city",
665
            )
666
667
            # Match plants from NEP list using plz,
668
            # neglecting the capacity
669
            matched, mastr, nep = match_nep_no_chp(
670
                nep,
671
                mastr,
672
                matched,
673
                consider_location="plz",
674
                consider_carrier=False,
675
                consider_capacity=False,
676
            )
677
678
            # Match plants from NEP list using city,
679
            # neglecting the capacity
680
            matched, mastr, nep = match_nep_no_chp(
681
                nep,
682
                mastr,
683
                matched,
684
                consider_location="city",
685
                consider_carrier=False,
686
                consider_capacity=False,
687
            )
688
689
            # Match remaining plants from NEP using the federal state
690
            matched, mastr, nep = match_nep_no_chp(
691
                nep,
692
                mastr,
693
                matched,
694
                buffer_capacity=0.1,
695
                consider_location="federal_state",
696
                consider_carrier=False,
697
            )
698
699
            # Match remaining plants from NEP using the federal state
700
            matched, mastr, nep = match_nep_no_chp(
701
                nep,
702
                mastr,
703
                matched,
704
                buffer_capacity=0.7,
705
                consider_location="federal_state",
706
                consider_carrier=False,
707
            )
708
709
            print(f"{matched.el_capacity.sum()} MW of {carrier} matched")
710
            print(f"{nep.c2035_capacity.sum()} MW of {carrier} not matched")
711
712
            matched.crs = "EPSG:4326"
713
714
            # Assign bus_id
715
            # Load grid district polygons
716
            mv_grid_districts = db.select_geodataframe(
717
                f"""
718
            SELECT * FROM {cfg['sources']['egon_mv_grid_district']}
719
            """,
720
                epsg=4326,
721
            )
722
723
            ehv_grid_districts = db.select_geodataframe(
724
                f"""
725
            SELECT * FROM {cfg['sources']['ehv_voronoi']}
726
            """,
727
                epsg=4326,
728
            )
729
730
            # Perform spatial joins for plants in ehv and hv level seperately
731
            power_plants_hv = gpd.sjoin(
732
                matched[matched.voltage_level >= 3],
733
                mv_grid_districts[["bus_id", "geom"]],
734
                how="left",
735
            ).drop(columns=["index_right"])
736
            power_plants_ehv = gpd.sjoin(
737
                matched[matched.voltage_level < 3],
738
                ehv_grid_districts[["bus_id", "geom"]],
739
                how="left",
740
            ).drop(columns=["index_right"])
741
742
            # Combine both dataframes
743
            power_plants = pd.concat([power_plants_hv, power_plants_ehv])
744
745
            # Insert into target table
746
            session = sessionmaker(bind=db.engine())()
747
            for i, row in power_plants.iterrows():
748
                entry = EgonPowerPlants(
749
                    sources={"el_capacity": row.source},
750
                    source_id={"MastrNummer": row.MaStRNummer},
751
                    carrier=row.carrier,
752
                    el_capacity=row.el_capacity,
753
                    voltage_level=row.voltage_level,
754
                    bus_id=row.bus_id,
755
                    scenario=row.scenario,
756
                    geom=f"SRID=4326;POINT({row.geometry.x} {row.geometry.y})",
757
                )
758
                session.add(entry)
759
            session.commit()
760
761
762
def allocate_other_power_plants():
763
    # This function is only designed to work for the eGon2035 scenario
764
    if (
765
        "eGon2035"
766
        not in egon.data.config.settings()["egon-data"]["--scenarios"]
767
    ):
768
        return
769
770
    # Get configuration
771
    cfg = egon.data.config.datasets()["power_plants"]
772
    boundary = egon.data.config.settings()["egon-data"]["--dataset-boundary"]
773
774
    db.execute_sql(
775
        f"""
776
        DELETE FROM {cfg['target']['schema']}.{cfg['target']['table']}
777
        WHERE carrier ='others'
778
        """
779
    )
780
781
    # Define scenario, carrier 'others' is only present in 'eGon2035'
782
    scenario = "eGon2035"
783
784
    # Select target values for carrier 'others'
785
    target = db.select_dataframe(
786
        f"""
787
        SELECT sum(capacity) as capacity, carrier, scenario_name, nuts
788
            FROM {cfg['sources']['capacities']}
789
            WHERE scenario_name = '{scenario}'
790
            AND carrier = 'others'
791
            GROUP BY carrier, nuts, scenario_name;
792
        """
793
    )
794
795
    # Assign name of federal state
796
797
    map_states = {
798
        "DE1": "BadenWuerttemberg",
799
        "DEA": "NordrheinWestfalen",
800
        "DE7": "Hessen",
801
        "DE4": "Brandenburg",
802
        "DE5": "Bremen",
803
        "DEB": "RheinlandPfalz",
804
        "DEE": "SachsenAnhalt",
805
        "DEF": "SchleswigHolstein",
806
        "DE8": "MecklenburgVorpommern",
807
        "DEG": "Thueringen",
808
        "DE9": "Niedersachsen",
809
        "DED": "Sachsen",
810
        "DE6": "Hamburg",
811
        "DEC": "Saarland",
812
        "DE3": "Berlin",
813
        "DE2": "Bayern",
814
    }
815
816
    target = (
817
        target.replace({"nuts": map_states})
818
        .rename(columns={"nuts": "Bundesland"})
819
        .set_index("Bundesland")
820
    )
821
    target = target.capacity
822
823
    # Select 'non chp' power plants from mastr table
824
    mastr_combustion = select_no_chp_combustion_mastr("others")
825
826
    # Rename columns
827
    mastr_combustion = mastr_combustion.rename(
828
        columns={
829
            "carrier": "Energietraeger",
830
            "plz": "Postleitzahl",
831
            "city": "Ort",
832
            "federal_state": "Bundesland",
833
            "el_capacity": "Nettonennleistung",
834
        }
835
    )
836
837
    # Select power plants representing carrier 'others' from MaStR files
838
    mastr_sludge = pd.read_csv(
839
        WORKING_DIR_MASTR_OLD / cfg["sources"]["mastr_gsgk"]
840
    ).query(
841
        """EinheitBetriebsstatus=='InBetrieb'and Energietraeger=='Klärschlamm'"""  # noqa: E501
842
    )
843
    mastr_geothermal = pd.read_csv(
844
        WORKING_DIR_MASTR_OLD / cfg["sources"]["mastr_gsgk"]
845
    ).query(
846
        "EinheitBetriebsstatus=='InBetrieb' and Energietraeger=='Geothermie' "
847
        "and Technologie == 'ORCOrganicRankineCycleAnlage'"
848
    )
849
850
    mastr_sg = pd.concat([mastr_sludge, mastr_geothermal])
851
852
    # Insert geometry column
853
    mastr_sg = mastr_sg[~(mastr_sg["Laengengrad"].isnull())]
854
    mastr_sg = gpd.GeoDataFrame(
855
        mastr_sg,
856
        geometry=gpd.points_from_xy(
857
            mastr_sg["Laengengrad"], mastr_sg["Breitengrad"], crs=4326
858
        ),
859
    )
860
861
    # Exclude columns which are not essential
862
    mastr_sg = mastr_sg.filter(
863
        [
864
            "EinheitMastrNummer",
865
            "Nettonennleistung",
866
            "geometry",
867
            "Energietraeger",
868
            "Postleitzahl",
869
            "Ort",
870
            "Bundesland",
871
        ],
872
        axis=1,
873
    )
874
    # Rename carrier
875
    mastr_sg.Energietraeger = "others"
876
877
    # Change data type
878
    mastr_sg["Postleitzahl"] = mastr_sg["Postleitzahl"].astype(int)
879
880
    # Capacity in MW
881
    mastr_sg.loc[:, "Nettonennleistung"] *= 1e-3
882
883
    # Merge different sources to one df
884
    mastr_others = pd.concat([mastr_sg, mastr_combustion]).reset_index()
885
886
    # Delete entries outside Schleswig-Holstein for test mode
887
    if boundary == "Schleswig-Holstein":
888
        mastr_others = mastr_others[
889
            mastr_others["Bundesland"] == "SchleswigHolstein"
890
        ]
891
892
    # Scale capacities prox to now to meet target values
893
    mastr_prox = scale_prox2now(mastr_others, target, level="federal_state")
894
895
    # Assign voltage_level based on scaled capacity
896
    mastr_prox["voltage_level"] = np.nan
897
    mastr_prox["voltage_level"] = assign_voltage_level_by_capacity(mastr_prox)
898
899
    # Rename columns
900
    mastr_prox = mastr_prox.rename(
901
        columns={
902
            "Energietraeger": "carrier",
903
            "Postleitzahl": "plz",
904
            "Ort": "city",
905
            "Bundesland": "federal_state",
906
            "Nettonennleistung": "el_capacity",
907
        }
908
    )
909
910
    # Assign bus_id
911
    mastr_prox = assign_bus_id(mastr_prox, cfg)
912
    mastr_prox = mastr_prox.set_crs(4326, allow_override=True)
913
914
    # Insert into target table
915
    session = sessionmaker(bind=db.engine())()
916
    for i, row in mastr_prox.iterrows():
917
        entry = EgonPowerPlants(
918
            sources=row.el_capacity,
919
            source_id={"MastrNummer": row.EinheitMastrNummer},
920
            carrier=row.carrier,
921
            el_capacity=row.el_capacity,
922
            voltage_level=row.voltage_level,
923
            bus_id=row.bus_id,
924
            scenario=scenario,
925
            geom=f"SRID=4326; {row.geometry}",
926
        )
927
        session.add(entry)
928
    session.commit()
929
930
931
def discard_not_available_generators(gen, max_date):
932
    gen["decommissioning_date"] = pd.to_datetime(
933
        gen["decommissioning_date"]
934
    )
935
    gen["commissioning_date"] = pd.to_datetime(gen["commissioning_date"])
936
    # drop plants that are commissioned after the max date
937
    gen = gen[gen["commissioning_date"] < max_date]
938
939
    # drop decommissioned plants while keeping the ones decommissioned
940
    # after the max date
941
    gen.loc[(gen["decommissioning_date"] > max_date), "status"] = (
942
        "InBetrieb"
943
    )
944
945
    gen = gen.loc[
946
        gen["status"].isin(["InBetrieb", "VoruebergehendStillgelegt"])
947
    ]
948
949
    # drop unnecessary columns
950
    gen = gen.drop(columns=["commissioning_date", "decommissioning_date"])
951
952
    return gen
953
954
955
def get_conventional_power_plants_non_chp(scn_name):
956
957
    cfg = egon.data.config.datasets()["power_plants"]
958
    # Write conventional power plants in supply.egon_power_plants
959
    common_columns = [
960
        "EinheitMastrNummer",
961
        "Energietraeger",
962
        "Nettonennleistung",
963
        "Laengengrad",
964
        "Breitengrad",
965
        "Gemeinde",
966
        "Inbetriebnahmedatum",
967
        "EinheitBetriebsstatus",
968
        "DatumEndgueltigeStilllegung",
969
    ]
970
    # import nuclear power plants
971
    nuclear = pd.read_csv(
972
        WORKING_DIR_MASTR_OLD / cfg["sources"]["mastr_nuclear"],
973
        usecols=common_columns,
974
    )
975
    # import combustion power plants
976
    comb = pd.read_csv(
977
        WORKING_DIR_MASTR_OLD / cfg["sources"]["mastr_combustion"],
978
        usecols=common_columns + ["ThermischeNutzleistung"],
979
    )
980
981
    conv = pd.concat([comb, nuclear])
982
983
    conv = conv[
984
        conv.Energietraeger.isin(
985
            [
986
                "Braunkohle",
987
                "Mineralölprodukte",
988
                "Steinkohle",
989
                "Kernenergie",
990
                "Erdgas",
991
            ]
992
        )
993
    ]
994
995
    # drop plants that are decommissioned
996
    conv["DatumEndgueltigeStilllegung"] = pd.to_datetime(
997
        conv["DatumEndgueltigeStilllegung"]
998
    )
999
1000
    # keep plants that were decommissioned after the max date
1001
    conv.loc[
1002
        (
1003
            conv.DatumEndgueltigeStilllegung
1004
            > egon.data.config.datasets()["mastr_new"][f"{scn_name}_date_max"]
1005
        ),
1006
        "EinheitBetriebsstatus",
1007
    ] = "InBetrieb"
1008
1009
    conv = conv.loc[conv.EinheitBetriebsstatus == "InBetrieb"]
1010
1011
    conv = conv.drop(
1012
        columns=["EinheitBetriebsstatus", "DatumEndgueltigeStilllegung"]
1013
    )
1014
1015
    # convert from KW to MW
1016
    conv["Nettonennleistung"] = conv["Nettonennleistung"] / 1000
1017
1018
    # drop generators installed after 2019
1019
    conv["Inbetriebnahmedatum"] = pd.to_datetime(conv["Inbetriebnahmedatum"])
1020
    conv = conv[
1021
        conv["Inbetriebnahmedatum"]
1022
        < egon.data.config.datasets()["mastr_new"][f"{scn_name}_date_max"]
1023
    ]
1024
1025
    conv_cap_chp = (
1026
        conv.groupby("Energietraeger")["Nettonennleistung"].sum() / 1e3
1027
    )
1028
    # drop chp generators
1029
    conv["ThermischeNutzleistung"] = conv["ThermischeNutzleistung"].fillna(0)
1030
    conv = conv[conv.ThermischeNutzleistung == 0]
1031
    conv_cap_no_chp = (
1032
        conv.groupby("Energietraeger")["Nettonennleistung"].sum() / 1e3
1033
    )
1034
1035
    logger.info("Dropped CHP generators in GW")
1036
    logger.info(conv_cap_chp - conv_cap_no_chp)
1037
1038
    # rename carriers
1039
    # rename carriers
1040
    conv["Energietraeger"] = conv["Energietraeger"].replace(
1041
        to_replace={
1042
            "Braunkohle": "lignite",
1043
            "Steinkohle": "coal",
1044
            "Erdgas": "gas",
1045
            "Mineralölprodukte": "oil",
1046
            "Kernenergie": "nuclear",
1047
        }
1048
    )
1049
1050
    # rename columns
1051
    conv.rename(
1052
        columns={
1053
            "EinheitMastrNummer": "gens_id",
1054
            "Energietraeger": "carrier",
1055
            "Nettonennleistung": "capacity",
1056
            "Gemeinde": "location",
1057
        },
1058
        inplace=True,
1059
    )
1060
    conv["bus_id"] = np.nan
1061
    conv["geom"] = gpd.points_from_xy(
1062
        conv.Laengengrad, conv.Breitengrad, crs=4326
1063
    )
1064
    conv.loc[(conv.Laengengrad.isna() | conv.Breitengrad.isna()), "geom"] = (
1065
        Point()
1066
    )
1067
    conv = gpd.GeoDataFrame(conv, geometry="geom")
1068
1069
    # assign voltage level by capacity
1070
    conv["voltage_level"] = np.nan
1071
    conv["voltage_level"] = assign_voltage_level_by_capacity(
1072
        conv.rename(columns={"capacity": "Nettonennleistung"})
1073
    )
1074
    # Add further information
1075
    conv["sources"] = [{"el_capacity": "MaStR"}] * conv.shape[0]
1076
    conv["source_id"] = conv["gens_id"].apply(lambda x: {"MastrNummer": x})
1077
    conv["scenario"] = scn_name
1078
1079
    return conv
1080
1081
1082
def power_plants_status_quo(scn_name="status2019"):
1083
    def fill_missing_bus_and_geom(gens, carrier):
1084
        # drop generators without data to get geometry.
1085
        drop_id = gens[
1086
            (gens.geom.is_empty)
1087
            & ~(gens.location.isin(geom_municipalities.index))
1088
        ].index
1089
        new_geom = gens["capacity"][
1090
            (gens.geom.is_empty)
1091
            & (gens.location.isin(geom_municipalities.index))
1092
        ]
1093
        logger.info(
1094
            f"""{len(drop_id)} {carrier} generator(s) ({int(gens.loc[drop_id, 'capacity']
1095
            .sum())}MW) were drop"""
1096
        )
1097
1098
        logger.info(
1099
            f"""{len(new_geom)} {carrier} generator(s) ({int(new_geom
1100
            .sum())}MW) received a geom based on location
1101
              """
1102
        )
1103
        gens.drop(index=drop_id, inplace=True)
1104
1105
        # assign missing geometries based on location and buses based on geom
1106
1107
        gens["geom"] = gens.apply(
1108
            lambda x: (
1109
                geom_municipalities.at[x["location"], "geom"]
1110
                if x["geom"].is_empty
1111
                else x["geom"]
1112
            ),
1113
            axis=1,
1114
        )
1115
        gens["bus_id"] = gens.sjoin(
1116
            mv_grid_districts[["bus_id", "geom"]], how="left"
1117
        ).bus_id_right.values
1118
1119
        gens = gens.dropna(subset=["bus_id"])
1120
        # convert geom to WKB
1121
        gens["geom"] = gens["geom"].to_wkt()
1122
1123
        return gens
1124
1125
    def convert_master_info(df):
1126
        # Add further information
1127
        df["sources"] = [{"el_capacity": "MaStR"}] * df.shape[0]
1128
        df["source_id"] = df["gens_id"].apply(lambda x: {"MastrNummer": x})
1129
        return df
1130
1131
    def log_insert_capacity(df, tech):
1132
        logger.info(
1133
            f"""
1134
            {len(df)} {tech} generators with a total installed capacity of
1135
            {int(df["el_capacity"].sum())} MW were inserted into the db
1136
              """
1137
        )
1138
1139
    con = db.engine()
1140
    cfg = egon.data.config.datasets()["power_plants"]
1141
1142
    db.execute_sql(
1143
        f"""
1144
        DELETE FROM {cfg['target']['schema']}.{cfg['target']['table']}
1145
        WHERE carrier IN ('wind_onshore', 'solar', 'biomass',
1146
                          'run_of_river', 'reservoir', 'solar_rooftop',
1147
                          'wind_offshore', 'nuclear', 'coal', 'lignite', 'oil',
1148
                          'gas')
1149
        AND scenario = '{scn_name}'
1150
        """
1151
    )
1152
1153
    # import municipalities to assign missing geom and bus_id
1154
    geom_municipalities = gpd.GeoDataFrame.from_postgis(
1155
        """
1156
        SELECT gen, ST_UNION(geometry) as geom
1157
        FROM boundaries.vg250_gem
1158
        GROUP BY gen
1159
        """,
1160
        con,
1161
        geom_col="geom",
1162
    ).set_index("gen")
1163
    geom_municipalities["geom"] = geom_municipalities["geom"].centroid
1164
1165
    mv_grid_districts = gpd.GeoDataFrame.from_postgis(
1166
        f"""
1167
        SELECT * FROM {cfg['sources']['egon_mv_grid_district']}
1168
        """,
1169
        con,
1170
    )
1171
    mv_grid_districts.geom = mv_grid_districts.geom.to_crs(4326)
1172
1173
    # Conventional non CHP
1174
    #  ###################
1175
    conv = get_conventional_power_plants_non_chp(scn_name)
1176
    conv = fill_missing_bus_and_geom(conv, carrier="conventional")
1177
    conv=  conv.rename(columns={"capacity": "el_capacity"})
1178
1179
    # Write into DB
1180
    with db.session_scope() as session:
1181
        session.bulk_insert_mappings(
1182
            EgonPowerPlants,
1183
            conv.to_dict(orient="records"),
1184
        )
1185
1186
    log_insert_capacity(conv, tech="conventional non chp")
1187
1188
    # Hydro Power Plants
1189
    #  ###################
1190
    hydro = gpd.GeoDataFrame.from_postgis(
1191
        f"""SELECT *, city AS location FROM {cfg['sources']['hydro']}
1192
        WHERE plant_type IN ('Laufwasseranlage', 'Speicherwasseranlage')""",
1193
        con,
1194
        geom_col="geom",
1195
    )
1196
1197
    hydro = fill_missing_bus_and_geom(hydro, carrier="hydro")
1198
1199
    hydro = convert_master_info(hydro)
1200
    hydro["carrier"] = hydro["plant_type"].replace(
1201
        to_replace={
1202
            "Laufwasseranlage": "run_of_river",
1203
            "Speicherwasseranlage": "reservoir",
1204
        }
1205
    )
1206
    hydro["scenario"] = scn_name
1207
    hydro = hydro.rename(columns={"capacity": "el_capacity"})
1208
    hydro = hydro.drop(columns="id")
1209
1210
    # Write into DB
1211
    with db.session_scope() as session:
1212
        session.bulk_insert_mappings(
1213
            EgonPowerPlants,
1214
            hydro.to_dict(orient="records"),
1215
        )
1216
1217
    log_insert_capacity(hydro, tech="hydro")
1218
1219
    # Biomass
1220
    #  ###################
1221
    biomass = gpd.GeoDataFrame.from_postgis(
1222
        f"""SELECT *, city AS location FROM {cfg['sources']['biomass']}""",
1223
        con,
1224
        geom_col="geom",
1225
    )
1226
1227
    # drop chp generators
1228
    biomass["th_capacity"] = biomass["th_capacity"].fillna(0)
1229
    biomass = biomass[biomass.th_capacity == 0]
1230
1231
    biomass = fill_missing_bus_and_geom(biomass, carrier="biomass")
1232
1233
    biomass = convert_master_info(biomass)
1234
    biomass["scenario"] = scn_name
1235
    biomass["carrier"] = "biomass"
1236
    biomass = biomass.rename(columns={"capacity": "el_capacity"})
1237
    biomass = biomass.drop(columns="id")
1238
1239
    # Write into DB
1240
    with db.session_scope() as session:
1241
        session.bulk_insert_mappings(
1242
            EgonPowerPlants,
1243
            biomass.to_dict(orient="records"),
1244
        )
1245
1246
    log_insert_capacity(biomass, tech="biomass")
1247
1248
    # Solar
1249
    #  ###################
1250
    solar = gpd.GeoDataFrame.from_postgis(
1251
        f"""SELECT *, city AS location FROM {cfg['sources']['pv']}
1252
        WHERE site_type IN ('Freifläche',
1253
        'Bauliche Anlagen (Hausdach, Gebäude und Fassade)') """,
1254
        con,
1255
        geom_col="geom",
1256
    )
1257
    map_solar = {
1258
        "Freifläche": "solar",
1259
        "Bauliche Anlagen (Hausdach, Gebäude und Fassade)": "solar_rooftop",
1260
    }
1261
    solar["carrier"] = solar["site_type"].replace(to_replace=map_solar)
1262
1263
    solar = fill_missing_bus_and_geom(solar, carrier="solar")
1264
    solar = convert_master_info(solar)
1265
    solar["scenario"] = scn_name
1266
    solar = solar.rename(columns={"capacity": "el_capacity"})
1267
    solar = solar.drop(columns="id")
1268
1269
    # Write into DB
1270
    with db.session_scope() as session:
1271
        session.bulk_insert_mappings(
1272
            EgonPowerPlants,
1273
            solar.to_dict(orient="records"),
1274
        )
1275
1276
    log_insert_capacity(solar, tech="solar")
1277
1278
    # Wind
1279
    #  ###################
1280
    wind_onshore = gpd.GeoDataFrame.from_postgis(
1281
        f"""SELECT *, city AS location FROM {cfg['sources']['wind']}""",
1282
        con,
1283
        geom_col="geom",
1284
    )
1285
1286
    wind_onshore = fill_missing_bus_and_geom(
1287
        wind_onshore, carrier="wind_onshore"
1288
    )
1289
    wind_onshore = convert_master_info(wind_onshore)
1290
    wind_onshore["scenario"] = scn_name
1291
    wind_onshore = wind_onshore.rename(columns={"capacity": "el_capacity"})
1292
    wind_onshore["carrier"] = "wind_onshore"
1293
    wind_onshore = wind_onshore.drop(columns="id")
1294
1295
    # Write into DB
1296
    with db.session_scope() as session:
1297
        session.bulk_insert_mappings(
1298
            EgonPowerPlants,
1299
            wind_onshore.to_dict(orient="records"),
1300
        )
1301
1302
    log_insert_capacity(wind_onshore, tech="wind_onshore")
1303
1304
1305
tasks = (
1306
    create_tables,
1307
    import_mastr,
1308
)
1309
1310
for scn_name in egon.data.config.settings()["egon-data"]["--scenarios"]:
1311
    if "status" in scn_name:
1312
        tasks += (
1313
            wrapped_partial(
1314
                power_plants_status_quo,
1315
                scn_name=scn_name,
1316
                postfix=f"_{scn_name[-4:]}",
1317
            ),
1318
        )
1319
1320
if (
1321
    "eGon2035" in egon.data.config.settings()["egon-data"]["--scenarios"]
1322
    or "eGon100RE" in egon.data.config.settings()["egon-data"]["--scenarios"]
1323
):
1324
    tasks = tasks + (
1325
        insert_hydro_biomass,
1326
        allocate_conventional_non_chp_power_plants,
1327
        allocate_other_power_plants,
1328
        {
1329
            wind_onshore.insert,
1330
            pv_ground_mounted.insert,
1331
            pv_rooftop_per_mv_grid,
1332
        },
1333
    )
1334
1335
tasks = tasks + (
1336
    pv_rooftop_to_buildings,
1337
    wind_offshore.insert,
1338
)
1339
1340
for scn_name in egon.data.config.settings()["egon-data"]["--scenarios"]:
1341
    tasks += (wrapped_partial(assign_weather_data.weatherId_and_busId,
1342
                              scn_name=scn_name,
1343
                              postfix=f"_{scn_name}"
1344
                              ),)
1345
1346
tasks += (pp_metadata.metadata,)
1347
1348
class PowerPlants(Dataset):
1349
    """
1350
    This module creates all electrical generators for different scenarios. It
1351
    also calculates the weather area for each weather dependent generator.
1352
1353
    *Dependencies*
1354
      * :py:class:`Chp <egon.data.datasets.chp.Chp>`
1355
      * :py:class:`CtsElectricityDemand
1356
      <egon.data.datasets.electricity_demand.CtsElectricityDemand>`
1357
      * :py:class:`HouseholdElectricityDemand
1358
      <egon.data.datasets.electricity_demand.HouseholdElectricityDemand>`
1359
      * :py:class:`mastr_data <egon.data.datasets.mastr.mastr_data>`
1360
      * :py:func:`define_mv_grid_districts
1361
      <egon.data.datasets.mv_grid_districts.define_mv_grid_districts>`
1362
      * :py:class:`RePotentialAreas
1363
      <egon.data.datasets.re_potential_areas.RePotentialAreas>`
1364
      * :py:class:`ZensusVg250
1365
      <egon.data.datasets.RenewableFeedin>`
1366
      * :py:class:`ScenarioCapacities
1367
      <egon.data.datasets.scenario_capacities.ScenarioCapacities>`
1368
      * :py:class:`ScenarioParameters
1369
      <egon.data.datasets.scenario_parameters.ScenarioParameters>`
1370
      * :py:func:`Setup <egon.data.datasets.database.setup>`
1371
      * :py:class:`substation_extraction
1372
      <egon.data.datasets.substation.substation_extraction>`
1373
      * :py:class:`Vg250MvGridDistricts
1374
      <egon.data.datasets.Vg250MvGridDistricts>`
1375
      * :py:class:`ZensusMvGridDistricts
1376
      <egon.data.datasets.zensus_mv_grid_districts.ZensusMvGridDistricts>`
1377
1378
    *Resulting tables*
1379
      * :py:class:`supply.egon_power_plants
1380
      <egon.data.datasets.power_plants.EgonPowerPlants>` is filled
1381
1382
    """
1383
1384
    #:
1385
    name: str = "PowerPlants"
1386
    #:
1387
    version: str = "0.0.27"
1388
1389
    def __init__(self, dependencies):
1390
        super().__init__(
1391
            name=self.name,
1392
            version=self.version,
1393
            dependencies=dependencies,
1394
            tasks=tasks,
1395
        )
1396
1397