Passed
Push — dev ( 61186e...53ad2a )
by
unknown
01:58 queued 14s
created

data.datasets.power_plants.create_tables()   A

Complexity

Conditions 1

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nop 0
dl 0
loc 17
rs 10
c 0
b 0
f 0
1
"""The central module containing all code dealing with power plant data.
2
"""
3
from geoalchemy2 import Geometry
4
from sqlalchemy import (
5
    BigInteger,
6
    Boolean,
7
    Column,
8
    Float,
9
    Integer,
10
    Sequence,
11
    String,
12
)
13
from sqlalchemy.dialects.postgresql import JSONB
14
from sqlalchemy.ext.declarative import declarative_base
15
from sqlalchemy.orm import sessionmaker
16
import geopandas as gpd
17
import numpy as np
18
import pandas as pd
19
20
from egon.data import db
21
from egon.data.datasets import Dataset
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.pv_rooftop import pv_rooftop_per_mv_grid
28
import egon.data.config
29
import egon.data.datasets.power_plants.assign_weather_data as assign_weather_data
30
import egon.data.datasets.power_plants.pv_ground_mounted as pv_ground_mounted
31
import egon.data.datasets.power_plants.wind_farms as wind_onshore
32
import egon.data.datasets.power_plants.wind_offshore as wind_offshore
33
34
Base = declarative_base()
35
36
37 View Code Duplication
class EgonPowerPlants(Base):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
38
    __tablename__ = "egon_power_plants"
39
    __table_args__ = {"schema": "supply"}
40
    id = Column(BigInteger, Sequence("pp_seq"), primary_key=True)
41
    sources = Column(JSONB)
42
    source_id = Column(JSONB)
43
    carrier = Column(String)
44
    el_capacity = Column(Float)
45
    bus_id = Column(Integer)
46
    voltage_level = Column(Integer)
47
    weather_cell_id = Column(Integer)
48
    scenario = Column(String)
49
    geom = Column(Geometry("POINT", 4326))
50
51
52
class PowerPlants(Dataset):
53
    def __init__(self, dependencies):
54
        super().__init__(
55
            name="PowerPlants",
56
            version="0.0.10",
57
            dependencies=dependencies,
58
            tasks=(
59
                create_tables,
60
                insert_hydro_biomass,
61
                allocate_conventional_non_chp_power_plants,
62
                allocate_other_power_plants,
63
                {
64
                    wind_onshore.insert,
65
                    pv_ground_mounted.insert,
66
                    pv_rooftop_per_mv_grid,
67
                },
68
                wind_offshore.insert,
69
                assign_weather_data.weatherId_and_busId,
70
            ),
71
        )
72
73
74
def create_tables():
75
    """Create tables for power plant data
76
    Returns
77
    -------
78
    None.
79
    """
80
81
    cfg = egon.data.config.datasets()["power_plants"]
82
    db.execute_sql(f"CREATE SCHEMA IF NOT EXISTS {cfg['target']['schema']};")
83
    engine = db.engine()
84
    db.execute_sql(
85
        f"""DROP TABLE IF EXISTS
86
        {cfg['target']['schema']}.{cfg['target']['table']}"""
87
    )
88
89
    db.execute_sql("""DROP SEQUENCE IF EXISTS pp_seq""")
90
    EgonPowerPlants.__table__.create(bind=engine, checkfirst=True)
91
92
93
def scale_prox2now(df, target, level="federal_state"):
94
    """Scale installed capacities linear to status quo power plants
95
96
    Parameters
97
    ----------
98
    df : pandas.DataFrame
99
        Status Quo power plants
100
    target : pandas.Series
101
        Target values for future scenario
102
    level : str, optional
103
        Scale per 'federal_state' or 'country'. The default is 'federal_state'.
104
105
    Returns
106
    -------
107
    df : pandas.DataFrame
108
        Future power plants
109
110
    """
111
112
    if level == "federal_state":
113
        df.loc[:, "Nettonennleistung"] = (
114
            df.groupby(df.Bundesland)
115
            .Nettonennleistung.apply(lambda grp: grp / grp.sum())
116
            .mul(target[df.Bundesland.values].values)
117
        )
118
    else:
119
        df.loc[:, "Nettonennleistung"] = df.Nettonennleistung.apply(
120
            lambda x: x / x.sum()
121
        ).mul(target.values)
122
123
    df = df[df.Nettonennleistung > 0]
124
125
    return df
126
127
128
def select_target(carrier, scenario):
129
    """Select installed capacity per scenario and carrier
130
131
    Parameters
132
    ----------
133
    carrier : str
134
        Name of energy carrier
135
    scenario : str
136
        Name of scenario
137
138
    Returns
139
    -------
140
    pandas.Series
141
        Target values for carrier and scenario
142
143
    """
144
    cfg = egon.data.config.datasets()["power_plants"]
145
146
    return (
147
        pd.read_sql(
148
            f"""SELECT DISTINCT ON (b.gen)
149
                         REPLACE(REPLACE(b.gen, '-', ''), 'ü', 'ue') as state,
150
                         a.capacity
151
                         FROM {cfg['sources']['capacities']} a,
152
                         {cfg['sources']['geom_federal_states']} b
153
                         WHERE a.nuts = b.nuts
154
                         AND scenario_name = '{scenario}'
155
                         AND carrier = '{carrier}'
156
                         AND b.gen NOT IN ('Baden-Württemberg (Bodensee)',
157
                                           'Bayern (Bodensee)')""",
158
            con=db.engine(),
159
        )
160
        .set_index("state")
161
        .capacity
162
    )
163
164
165
def filter_mastr_geometry(mastr, federal_state=None):
166
    """Filter data from MaStR by geometry
167
168
    Parameters
169
    ----------
170
    mastr : pandas.DataFrame
171
        All power plants listed in MaStR
172
    federal_state : str or None
173
        Name of federal state whoes power plants are returned.
174
        If None, data for Germany is returned
175
176
    Returns
177
    -------
178
    mastr_loc : pandas.DataFrame
179
        Power plants listed in MaStR with geometry inside German boundaries
180
181
    """
182
    cfg = egon.data.config.datasets()["power_plants"]
183
184
    if type(mastr) == pd.core.frame.DataFrame:
185
        # Drop entries without geometry for insert
186
        mastr_loc = mastr[
187
            mastr.Laengengrad.notnull() & mastr.Breitengrad.notnull()
188
        ]
189
190
        # Create geodataframe
191
        mastr_loc = gpd.GeoDataFrame(
192
            mastr_loc,
193
            geometry=gpd.points_from_xy(
194
                mastr_loc.Laengengrad, mastr_loc.Breitengrad, crs=4326
195
            ),
196
        )
197
    else:
198
        mastr_loc = mastr.copy()
199
200
    # Drop entries outside of germany or federal state
201
    if not federal_state:
202
        sql = f"SELECT geometry as geom FROM {cfg['sources']['geom_germany']}"
203
    else:
204
        sql = f"""
205
        SELECT geometry as geom
206
        FROM boundaries.vg250_lan_union
207
        WHERE REPLACE(REPLACE(gen, '-', ''), 'ü', 'ue') = '{federal_state}'"""
208
209
    mastr_loc = (
210
        gpd.sjoin(
211
            gpd.read_postgis(sql, con=db.engine()).to_crs(4326),
212
            mastr_loc,
213
            how="right",
214
        )
215
        .query("index_left==0")
216
        .drop("index_left", axis=1)
217
    )
218
219
    return mastr_loc
220
221
222
def insert_biomass_plants(scenario):
223
    """Insert biomass power plants of future scenario
224
225
    Parameters
226
    ----------
227
    scenario : str
228
        Name of scenario.
229
230
    Returns
231
    -------
232
    None.
233
234
    """
235
    cfg = egon.data.config.datasets()["power_plants"]
236
237
    # import target values from NEP 2021, scneario C 2035
238
    target = select_target("biomass", scenario)
239
240
    # import data for MaStR
241
    mastr = pd.read_csv(cfg["sources"]["mastr_biomass"]).query(
242
        "EinheitBetriebsstatus=='InBetrieb'"
243
    )
244
245
    # Drop entries without federal state or 'AusschließlichWirtschaftszone'
246
    mastr = mastr[
247
        mastr.Bundesland.isin(
248
            pd.read_sql(
249
                f"""SELECT DISTINCT ON (gen)
250
        REPLACE(REPLACE(gen, '-', ''), 'ü', 'ue') as states
251
        FROM {cfg['sources']['geom_federal_states']}""",
252
                con=db.engine(),
253
            ).states.values
254
        )
255
    ]
256
257
    # Scaling will be done per federal state in case of eGon2035 scenario.
258
    if scenario == "eGon2035":
259
        level = "federal_state"
260
    else:
261
        level = "country"
262
263
    # Choose only entries with valid geometries inside DE/test mode
264
    mastr_loc = filter_mastr_geometry(mastr).set_geometry("geometry")
265
266
    # Scale capacities to meet target values
267
    mastr_loc = scale_prox2now(mastr_loc, target, level=level)
268
269
    # Assign bus_id
270
    if len(mastr_loc) > 0:
271
        mastr_loc["voltage_level"] = assign_voltage_level(mastr_loc, cfg)
272
        mastr_loc = assign_bus_id(mastr_loc, cfg)
273
274
    # Insert entries with location
275
    session = sessionmaker(bind=db.engine())()
276
277
    for i, row in mastr_loc.iterrows():
278
        if not row.ThermischeNutzleistung > 0:
279
            entry = EgonPowerPlants(
280
                sources={"el_capacity": "MaStR scaled with NEP 2021"},
281
                source_id={"MastrNummer": row.EinheitMastrNummer},
282
                carrier="biomass",
283
                el_capacity=row.Nettonennleistung,
284
                scenario=scenario,
285
                bus_id=row.bus_id,
286
                voltage_level=row.voltage_level,
287
                geom=f"SRID=4326;POINT({row.Laengengrad} {row.Breitengrad})",
288
            )
289
            session.add(entry)
290
291
    session.commit()
292
293
294
def insert_hydro_plants(scenario):
295
    """Insert hydro power plants of future scenario.
296
297
    Hydro power plants are diveded into run_of_river and reservoir plants
298
    according to Marktstammdatenregister.
299
    Additional hydro technologies (e.g. turbines inside drinking water
300
    systems) are not considered.
301
302
    Parameters
303
    ----------
304
    scenario : str
305
        Name of scenario.
306
307
    Returns
308
    -------
309
    None.
310
311
    """
312
    cfg = egon.data.config.datasets()["power_plants"]
313
314
    # Map MaStR carriers to eGon carriers
315
    map_carrier = {
316
        "run_of_river": ["Laufwasseranlage"],
317
        "reservoir": ["Speicherwasseranlage"],
318
    }
319
320
    for carrier in map_carrier.keys():
321
322
        # import target values
323
        target = select_target(carrier, scenario)
324
325
        # import data for MaStR
326
        mastr = pd.read_csv(cfg["sources"]["mastr_hydro"]).query(
327
            "EinheitBetriebsstatus=='InBetrieb'"
328
        )
329
330
        # Choose only plants with specific carriers
331
        mastr = mastr[mastr.ArtDerWasserkraftanlage.isin(map_carrier[carrier])]
332
333
        # Drop entries without federal state or 'AusschließlichWirtschaftszone'
334
        mastr = mastr[
335
            mastr.Bundesland.isin(
336
                pd.read_sql(
337
                    f"""SELECT DISTINCT ON (gen)
338
            REPLACE(REPLACE(gen, '-', ''), 'ü', 'ue') as states
339
            FROM {cfg['sources']['geom_federal_states']}""",
340
                    con=db.engine(),
341
                ).states.values
342
            )
343
        ]
344
345
        # Scaling will be done per federal state in case of eGon2035 scenario.
346
        if scenario == "eGon2035":
347
            level = "federal_state"
348
        else:
349
            level = "country"
350
351
        # Scale capacities to meet target values
352
        mastr = scale_prox2now(mastr, target, level=level)
353
354
        # Choose only entries with valid geometries inside DE/test mode
355
        mastr_loc = filter_mastr_geometry(mastr).set_geometry("geometry")
356
        # TODO: Deal with power plants without geometry
357
358
        # Assign bus_id and voltage level
359
        if len(mastr_loc) > 0:
360
            mastr_loc["voltage_level"] = assign_voltage_level(mastr_loc, cfg)
361
            mastr_loc = assign_bus_id(mastr_loc, cfg)
362
363
        # Insert entries with location
364
        session = sessionmaker(bind=db.engine())()
365
        for i, row in mastr_loc.iterrows():
366
            entry = EgonPowerPlants(
367
                sources={"el_capacity": "MaStR scaled with NEP 2021"},
368
                source_id={"MastrNummer": row.EinheitMastrNummer},
369
                carrier=carrier,
370
                el_capacity=row.Nettonennleistung,
371
                scenario=scenario,
372
                bus_id=row.bus_id,
373
                voltage_level=row.voltage_level,
374
                geom=f"SRID=4326;POINT({row.Laengengrad} {row.Breitengrad})",
375
            )
376
            session.add(entry)
377
378
        session.commit()
379
380
381
def assign_voltage_level(mastr_loc, cfg):
382
    """Assigns voltage level to power plants.
383
384
    If location data inluding voltage level is available from
385
    Marktstammdatenregister, this is used. Otherwise the voltage level is
386
    assigned according to the electrical capacity.
387
388
    Parameters
389
    ----------
390
    mastr_loc : pandas.DataFrame
391
        Power plants listed in MaStR with geometry inside German boundaries
392
393
    Returns
394
    -------
395
    pandas.DataFrame
396
        Power plants including voltage_level
397
398
    """
399
    mastr_loc["Spannungsebene"] = np.nan
400
    mastr_loc["voltage_level"] = np.nan
401
402
    if "LokationMastrNummer" in mastr_loc.columns:
403
        location = pd.read_csv(
404
            cfg["sources"]["mastr_location"],
405
            usecols=["LokationMastrNummer", "Spannungsebene"],
406
        ).set_index("LokationMastrNummer")
407
408
        location = location[~location.index.duplicated(keep="first")]
409
410
        mastr_loc.loc[
411
            mastr_loc[
412
                mastr_loc.LokationMastrNummer.isin(location.index)
413
            ].index,
414
            "Spannungsebene",
415
        ] = location.Spannungsebene[
416
            mastr_loc[
417
                mastr_loc.LokationMastrNummer.isin(location.index)
418
            ].LokationMastrNummer
419
        ].values
420
421
        # Transfer voltage_level as integer from Spanungsebene
422
        map_voltage_levels = pd.Series(
423
            data={
424
                "Höchstspannung": 1,
425
                "Hoechstspannung": 1,
426
                "UmspannungZurHochspannung": 2,
427
                "Hochspannung": 3,
428
                "UmspannungZurMittelspannung": 4,
429
                "Mittelspannung": 5,
430
                "UmspannungZurNiederspannung": 6,
431
                "Niederspannung": 7,
432
            }
433
        )
434
435
        mastr_loc.loc[
436
            mastr_loc[mastr_loc["Spannungsebene"].notnull()].index,
437
            "voltage_level",
438
        ] = map_voltage_levels[
439
            mastr_loc.loc[
440
                mastr_loc[mastr_loc["Spannungsebene"].notnull()].index,
441
                "Spannungsebene",
442
            ].values
443
        ].values
444
445
    else:
446
        print(
447
            "No information about MaStR location available. "
448
            "All voltage levels are assigned using threshold values."
449
        )
450
451
    # If no voltage level is available from mastr, choose level according
452
    # to threshold values
453
454
    mastr_loc.voltage_level = assign_voltage_level_by_capacity(mastr_loc)
455
456
    return mastr_loc.voltage_level
457
458
459
def assign_voltage_level_by_capacity(mastr_loc):
460
461
    for i, row in mastr_loc[mastr_loc.voltage_level.isnull()].iterrows():
462
463
        if row.Nettonennleistung > 120:
464
            level = 1
465
        elif row.Nettonennleistung > 20:
466
            level = 3
467
        elif row.Nettonennleistung > 5.5:
468
            level = 4
469
        elif row.Nettonennleistung > 0.2:
470
            level = 5
471
        elif row.Nettonennleistung > 0.1:
472
            level = 6
473
        else:
474
            level = 7
475
476
        mastr_loc.loc[i, "voltage_level"] = level
477
478
    mastr_loc.voltage_level = mastr_loc.voltage_level.astype(int)
479
480
    return mastr_loc.voltage_level
481
482
483
def assign_bus_id(power_plants, cfg):
484
    """Assigns bus_ids to power plants according to location and voltage level
485
486
    Parameters
487
    ----------
488
    power_plants : pandas.DataFrame
489
        Power plants including voltage level
490
491
    Returns
492
    -------
493
    power_plants : pandas.DataFrame
494
        Power plants including voltage level and bus_id
495
496
    """
497
498
    mv_grid_districts = db.select_geodataframe(
499
        f"""
500
        SELECT * FROM {cfg['sources']['egon_mv_grid_district']}
501
        """,
502
        epsg=4326,
503
    )
504
505
    ehv_grid_districts = db.select_geodataframe(
506
        f"""
507
        SELECT * FROM {cfg['sources']['ehv_voronoi']}
508
        """,
509
        epsg=4326,
510
    )
511
512
    # Assign power plants in hv and below to hvmv bus
513
    power_plants_hv = power_plants[power_plants.voltage_level >= 3].index
514
    if len(power_plants_hv) > 0:
515
        power_plants.loc[power_plants_hv, "bus_id"] = gpd.sjoin(
516
            power_plants[power_plants.index.isin(power_plants_hv)],
517
            mv_grid_districts,
518
        ).bus_id
519
520
    # Assign power plants in ehv to ehv bus
521
    power_plants_ehv = power_plants[power_plants.voltage_level < 3].index
522
523
    if len(power_plants_ehv) > 0:
524
        ehv_join = gpd.sjoin(
525
            power_plants[power_plants.index.isin(power_plants_ehv)],
526
            ehv_grid_districts,
527
        )
528
529
        if "bus_id_right" in ehv_join.columns:
530
            power_plants.loc[power_plants_ehv, "bus_id"] = gpd.sjoin(
531
                power_plants[power_plants.index.isin(power_plants_ehv)],
532
                ehv_grid_districts,
533
            ).bus_id_right
534
535
        else:
536
            power_plants.loc[power_plants_ehv, "bus_id"] = gpd.sjoin(
537
                power_plants[power_plants.index.isin(power_plants_ehv)],
538
                ehv_grid_districts,
539
            ).bus_id
540
541
    # Assert that all power plants have a bus_id
542
    assert power_plants.bus_id.notnull().all(), f"""Some power plants are
543
    not attached to a bus: {power_plants[power_plants.bus_id.isnull()]}"""
544
545
    return power_plants
546
547
548
def insert_hydro_biomass():
549
    """Insert hydro and biomass power plants in database
550
551
    Returns
552
    -------
553
    None.
554
555
    """
556
    cfg = egon.data.config.datasets()["power_plants"]
557
    db.execute_sql(
558
        f"""
559
        DELETE FROM {cfg['target']['schema']}.{cfg['target']['table']}
560
        WHERE carrier IN ('biomass', 'reservoir', 'run_of_river')
561
        """
562
    )
563
564
    for scenario in ["eGon2035"]:
565
        insert_biomass_plants(scenario)
566
        insert_hydro_plants(scenario)
567
568
569
def allocate_conventional_non_chp_power_plants():
570
571
    carrier = ["oil", "gas"]
572
573
    cfg = egon.data.config.datasets()["power_plants"]
574
575
    # Delete existing plants in the target table
576
    db.execute_sql(
577
        f"""
578
         DELETE FROM {cfg ['target']['schema']}.{cfg ['target']['table']}
579
         WHERE carrier IN ('gas', 'oil')
580
         AND scenario='eGon2035';
581
         """
582
    )
583
584
    for carrier in carrier:
585
586
        nep = select_nep_power_plants(carrier)
587
588
        if nep.empty:
589
            print(f"DataFrame from NEP for carrier {carrier} is empty!")
590
591
        else:
592
593
            mastr = select_no_chp_combustion_mastr(carrier)
594
595
            # Assign voltage level to MaStR
596
            mastr["voltage_level"] = assign_voltage_level(
597
                mastr.rename({"el_capacity": "Nettonennleistung"}, axis=1), cfg
598
            )
599
600
            # Initalize DataFrame for matching power plants
601
            matched = gpd.GeoDataFrame(
602
                columns=[
603
                    "carrier",
604
                    "el_capacity",
605
                    "scenario",
606
                    "geometry",
607
                    "MaStRNummer",
608
                    "source",
609
                    "voltage_level",
610
                ]
611
            )
612
613
            # Match combustion plants of a certain carrier from NEP list
614
            # using PLZ and capacity
615
            matched, mastr, nep = match_nep_no_chp(
616
                nep,
617
                mastr,
618
                matched,
619
                buffer_capacity=0.1,
620
                consider_carrier=False,
621
            )
622
623
            # Match plants from NEP list using city and capacity
624
            matched, mastr, nep = match_nep_no_chp(
625
                nep,
626
                mastr,
627
                matched,
628
                buffer_capacity=0.1,
629
                consider_carrier=False,
630
                consider_location="city",
631
            )
632
633
            # Match plants from NEP list using plz,
634
            # neglecting the capacity
635
            matched, mastr, nep = match_nep_no_chp(
636
                nep,
637
                mastr,
638
                matched,
639
                consider_location="plz",
640
                consider_carrier=False,
641
                consider_capacity=False,
642
            )
643
644
            # Match plants from NEP list using city,
645
            # neglecting the capacity
646
            matched, mastr, nep = match_nep_no_chp(
647
                nep,
648
                mastr,
649
                matched,
650
                consider_location="city",
651
                consider_carrier=False,
652
                consider_capacity=False,
653
            )
654
655
            # Match remaining plants from NEP using the federal state
656
            matched, mastr, nep = match_nep_no_chp(
657
                nep,
658
                mastr,
659
                matched,
660
                buffer_capacity=0.1,
661
                consider_location="federal_state",
662
                consider_carrier=False,
663
            )
664
665
            # Match remaining plants from NEP using the federal state
666
            matched, mastr, nep = match_nep_no_chp(
667
                nep,
668
                mastr,
669
                matched,
670
                buffer_capacity=0.7,
671
                consider_location="federal_state",
672
                consider_carrier=False,
673
            )
674
675
            print(f"{matched.el_capacity.sum()} MW of {carrier} matched")
676
            print(f"{nep.c2035_capacity.sum()} MW of {carrier} not matched")
677
678
            matched.crs = "EPSG:4326"
679
680
            # Assign bus_id
681
            # Load grid district polygons
682
            mv_grid_districts = db.select_geodataframe(
683
                f"""
684
            SELECT * FROM {cfg['sources']['egon_mv_grid_district']}
685
            """,
686
                epsg=4326,
687
            )
688
689
            ehv_grid_districts = db.select_geodataframe(
690
                f"""
691
            SELECT * FROM {cfg['sources']['ehv_voronoi']}
692
            """,
693
                epsg=4326,
694
            )
695
696
            # Perform spatial joins for plants in ehv and hv level seperately
697
            power_plants_hv = gpd.sjoin(
698
                matched[matched.voltage_level >= 3],
699
                mv_grid_districts[["bus_id", "geom"]],
700
                how="left",
701
            ).drop(columns=["index_right"])
702
            power_plants_ehv = gpd.sjoin(
703
                matched[matched.voltage_level < 3],
704
                ehv_grid_districts[["bus_id", "geom"]],
705
                how="left",
706
            ).drop(columns=["index_right"])
707
708
            # Combine both dataframes
709
            power_plants = pd.concat([power_plants_hv, power_plants_ehv])
710
711
            # Insert into target table
712
            session = sessionmaker(bind=db.engine())()
713
            for i, row in power_plants.iterrows():
714
                entry = EgonPowerPlants(
715
                    sources={"el_capacity": row.source},
716
                    source_id={"MastrNummer": row.MaStRNummer},
717
                    carrier=row.carrier,
718
                    el_capacity=row.el_capacity,
719
                    voltage_level=row.voltage_level,
720
                    bus_id=row.bus_id,
721
                    scenario=row.scenario,
722
                    geom=f"SRID=4326;POINT({row.geometry.x} {row.geometry.y})",
723
                )
724
                session.add(entry)
725
            session.commit()
726
727
728
def allocate_other_power_plants():
729
730
    # Get configuration
731
    cfg = egon.data.config.datasets()["power_plants"]
732
    boundary = egon.data.config.settings()["egon-data"]["--dataset-boundary"]
733
734
    db.execute_sql(
735
        f"""
736
        DELETE FROM {cfg['target']['schema']}.{cfg['target']['table']}
737
        WHERE carrier ='others'
738
        """
739
    )
740
741
    # Define scenario, carrier 'others' is only present in 'eGon2035'
742
    scenario = "eGon2035"
743
744
    # Select target values for carrier 'others'
745
    target = db.select_dataframe(
746
        f"""
747
        SELECT sum(capacity) as capacity, carrier, scenario_name, nuts
748
            FROM {cfg['sources']['capacities']}
749
            WHERE scenario_name = '{scenario}'
750
            AND carrier = 'others'
751
            GROUP BY carrier, nuts, scenario_name;
752
        """
753
    )
754
755
    # Assign name of federal state
756
757
    map_states = {
758
        "DE1": "BadenWuerttemberg",
759
        "DEA": "NordrheinWestfalen",
760
        "DE7": "Hessen",
761
        "DE4": "Brandenburg",
762
        "DE5": "Bremen",
763
        "DEB": "RheinlandPfalz",
764
        "DEE": "SachsenAnhalt",
765
        "DEF": "SchleswigHolstein",
766
        "DE8": "MecklenburgVorpommern",
767
        "DEG": "Thueringen",
768
        "DE9": "Niedersachsen",
769
        "DED": "Sachsen",
770
        "DE6": "Hamburg",
771
        "DEC": "Saarland",
772
        "DE3": "Berlin",
773
        "DE2": "Bayern",
774
    }
775
776
    target = (
777
        target.replace({"nuts": map_states})
778
        .rename(columns={"nuts": "Bundesland"})
779
        .set_index("Bundesland")
780
    )
781
    target = target.capacity
782
783
    # Select 'non chp' power plants from mastr table
784
    mastr_combustion = select_no_chp_combustion_mastr("others")
785
786
    # Rename columns
787
    mastr_combustion = mastr_combustion.rename(
788
        columns={
789
            "carrier": "Energietraeger",
790
            "plz": "Postleitzahl",
791
            "city": "Ort",
792
            "federal_state": "Bundesland",
793
            "el_capacity": "Nettonennleistung",
794
        }
795
    )
796
797
    # Select power plants representing carrier 'others' from MaStR files
798
    mastr_sludge = pd.read_csv(cfg["sources"]["mastr_gsgk"]).query(
799
        """EinheitBetriebsstatus=='InBetrieb'and Energietraeger=='Klaerschlamm'"""
800
    )
801
    mastr_geothermal = pd.read_csv(cfg["sources"]["mastr_gsgk"]).query(
802
        """EinheitBetriebsstatus=='InBetrieb' and Energietraeger=='Geothermie' and Technologie == 'ORCOrganicRankineCycleAnlage'"""
803
    )
804
805
    mastr_sg = mastr_sludge.append(mastr_geothermal)
806
807
    # Insert geometry column
808
    mastr_sg = mastr_sg[~(mastr_sg["Laengengrad"].isnull())]
809
    mastr_sg = gpd.GeoDataFrame(
810
        mastr_sg,
811
        geometry=gpd.points_from_xy(
812
            mastr_sg["Laengengrad"], mastr_sg["Breitengrad"], crs=4326
813
        ),
814
    )
815
816
    # Exclude columns which are not essential
817
    mastr_sg = mastr_sg.filter(
818
        [
819
            "EinheitMastrNummer",
820
            "Nettonennleistung",
821
            "geometry",
822
            "Energietraeger",
823
            "Postleitzahl",
824
            "Ort",
825
            "Bundesland",
826
        ],
827
        axis=1,
828
    )
829
    # Rename carrier
830
    mastr_sg.Energietraeger = "others"
831
832
    # Change data type
833
    mastr_sg["Postleitzahl"] = mastr_sg["Postleitzahl"].astype(int)
834
835
    # Capacity in MW
836
    mastr_sg.loc[:, "Nettonennleistung"] *= 1e-3
837
838
    # Merge different sources to one df
839
    mastr_others = mastr_sg.append(mastr_combustion).reset_index()
840
841
    # Delete entries outside Schleswig-Holstein for test mode
842
    if boundary == "Schleswig-Holstein":
843
        mastr_others = mastr_others[
844
            mastr_others["Bundesland"] == "SchleswigHolstein"
845
        ]
846
847
    # Scale capacities prox to now to meet target values
848
    mastr_prox = scale_prox2now(mastr_others, target, level="federal_state")
849
850
    # Assign voltage_level based on scaled capacity
851
    mastr_prox["voltage_level"] = np.nan
852
    mastr_prox["voltage_level"] = assign_voltage_level_by_capacity(mastr_prox)
853
854
    # Rename columns
855
    mastr_prox = mastr_prox.rename(
856
        columns={
857
            "Energietraeger": "carrier",
858
            "Postleitzahl": "plz",
859
            "Ort": "city",
860
            "Bundesland": "federal_state",
861
            "Nettonennleistung": "el_capacity",
862
        }
863
    )
864
865
    # Assign bus_id
866
    mastr_prox = assign_bus_id(mastr_prox, cfg)
867
    mastr_prox = mastr_prox.set_crs(4326, allow_override=True)
868
869
    # Insert into target table
870
    session = sessionmaker(bind=db.engine())()
871
    for i, row in mastr_prox.iterrows():
872
        entry = EgonPowerPlants(
873
            sources=row.el_capacity,
874
            source_id={"MastrNummer": row.EinheitMastrNummer},
875
            carrier=row.carrier,
876
            el_capacity=row.el_capacity,
877
            voltage_level=row.voltage_level,
878
            bus_id=row.bus_id,
879
            scenario=scenario,
880
            geom=f"SRID=4326; {row.geometry}",
881
        )
882
        session.add(entry)
883
    session.commit()
884