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

data.datasets.power_plants   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 1378
Duplicated Lines 5.73 %

Importance

Changes 0
Metric Value
wmc 58
eloc 732
dl 79
loc 1378
rs 4.428
c 0
b 0
f 0

14 Functions

Rating   Name   Duplication   Size   Complexity  
B allocate_other_power_plants() 0 160 3
B assign_bus_id() 66 66 5
B insert_biomass_plants() 0 72 5
A insert_hydro_biomass() 0 19 2
A scale_prox2now() 0 33 4
A create_tables() 0 34 2
B insert_hydro_plants() 0 86 5
A select_target() 0 34 1
B assign_voltage_level() 0 88 4
A filter_mastr_geometry() 0 55 3
B get_conventional_power_plants_non_chp() 0 125 2
B assign_voltage_level_by_capacity() 0 20 7
B allocate_conventional_non_chp_power_plants() 0 156 4
D power_plants_status_quo() 0 221 9

1 Method

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