Passed
Pull Request — dev (#826)
by
unknown
01:57
created

calc_building_profiles()   B

Complexity

Conditions 7

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 27
rs 8
c 0
b 0
f 0
cc 7
nop 3
1
from geoalchemy2.shape import to_shape
2
from sqlalchemy import Column, Float, Integer, String, func, REAL
3
from sqlalchemy.ext.declarative import declarative_base
4
import geopandas as gpd
5
import numpy as np
6
import pandas as pd
7
8
from egon.data import db
9
from egon.data.datasets import Dataset
10
from egon.data.datasets.electricity_demand import (
11
    EgonDemandRegioZensusElectricity,
12
)
13
from egon.data.datasets.electricity_demand.temporal import calc_load_curves_cts
14
from egon.data.datasets.electricity_demand_timeseries.hh_buildings import (
15
    OsmBuildingsSynthetic,
16
)
17
from egon.data.datasets.electricity_demand_timeseries.tools import (
18
    random_ints_until_sum,
19
    random_point_in_square,
20
    specific_int_until_sum,
21
    write_table_to_postgis,
22
    write_table_to_postgres,
23
)
24
from egon.data.datasets.zensus_mv_grid_districts import MapZensusGridDistricts
25
from egon.data.datasets.zensus_vg250 import DestatisZensusPopulationPerHa
26
from egon.data.datasets.electricity_demand import EgonDemandRegioZensusElectricity
27
import egon.data.config
28
29
engine = db.engine()
30
Base = declarative_base()
31
32
data_config = egon.data.config.datasets()
33
RANDOM_SEED = egon.data.config.settings()["egon-data"]["--random-seed"]
34
35
import saio
36
37
# import db tables
38
saio.register_schema("openstreetmap", engine=engine)
39
saio.register_schema("society", engine=engine)
40
saio.register_schema("demand", engine=engine)
41
saio.register_schema("boundaries", engine=engine)
42
43
44
class EgonCtsElectricityDemandBuildingShare(Base):
45
    __tablename__ = "egon_cts_electricity_demand_building_share"
46
    __table_args__ = {"schema": "demand"}
47
48
    id = Column(Integer, primary_key=True)
49
    scenario = Column(String, primary_key=True)
50
    bus_id = Column(Integer, index=True)
51
    profile_share = Column(Float)
52
53
54
class CtsPeakLoads(Base):
55
    __tablename__ = "egon_cts_peak_loads"
56
    __table_args__ = {"schema": "demand"}
57
58
    id = Column(String, primary_key=True)
59
    cts_peak_load_in_w_2035 = Column(REAL)
60
    cts_peak_load_in_w_100RE = Column(REAL)
61
62
63
def amenities_without_buildings():
64
    """
65
66
    Returns
67
    -------
68
    pd.DataFrame
69
        Table of amenities without buildings
70
71
    """
72
    from saio.openstreetmap import osm_amenities_not_in_buildings_filtered
73
74
    with db.session_scope() as session:
75
        cells_query = (
76
            session.query(
77
                DestatisZensusPopulationPerHa.id.label(
78
                    "zensus_population_id"
79
                ),
80
                # TODO can be used for square around amenity
81
                #  (1 geom_amenity: 1 geom_building)
82
                #  not unique amenity_ids yet
83
                osm_amenities_not_in_buildings_filtered.geom_amenity,
84
                osm_amenities_not_in_buildings_filtered.egon_amenity_id,
85
                # EgonDemandRegioZensusElectricity.demand,
86
                # # TODO can be used to generate n random buildings
87
                # # (n amenities : 1 randombuilding)
88
                # func.count(
89
                #     osm_amenities_not_in_buildings_filtered.egon_amenity_id
90
                # ).label("n_amenities_inside"),
91
                # DestatisZensusPopulationPerHa.geom,
92
            )
93
            .filter(
94
                func.st_within(
95
                    osm_amenities_not_in_buildings_filtered.geom_amenity,
96
                    DestatisZensusPopulationPerHa.geom,
97
                )
98
            )
99
            .filter(
100
                DestatisZensusPopulationPerHa.id
101
                == EgonDemandRegioZensusElectricity.zensus_population_id
102
            )
103
            .filter(
104
                EgonDemandRegioZensusElectricity.sector == "service",
105
                EgonDemandRegioZensusElectricity.scenario == "eGon2035"
106
                #         ).group_by(
107
                #             EgonDemandRegioZensusElectricity.zensus_population_id,
108
                #             DestatisZensusPopulationPerHa.geom,
109
            )
110
        )
111
    # # TODO can be used to generate n random buildings
112
    # df_cells_with_amenities_not_in_buildings = gpd.read_postgis(
113
    #     cells_query.statement, cells_query.session.bind, geom_col="geom"
114
    # )
115
    #
116
117
    # # TODO can be used for square around amenity
118
    df_synthetic_buildings_for_amenities = gpd.read_postgis(
119
        cells_query.statement,
120
        cells_query.session.bind,
121
        geom_col="geom_amenity",
122
    )
123
    return df_synthetic_buildings_for_amenities
124
125
126
def place_buildings_with_amenities(df, amenities=None, max_amenities=None):
127
    """
128
    Building centers are placed randomly within census cells.
129
    The Number of buildings is derived from n_amenity_inside, the selected
130
    method and number of amenities per building.
131
    """
132
    if isinstance(max_amenities, int):
133
        # amount of amenities is randomly generated within bounds (max_amenities,
134
        # amenities per cell)
135
        df["n_amenities_inside"] = df["n_amenities_inside"].apply(
136
            random_ints_until_sum, args=[max_amenities]
137
        )
138
    if isinstance(amenities, int):
139
        # Specific amount of amenities per building
140
        df["n_amenities_inside"] = df["n_amenities_inside"].apply(
141
            specific_int_until_sum, args=[amenities]
142
        )
143
144
    # Unnest each building
145
    df = df.explode(column="n_amenities_inside")
146
147
    # building count per cell
148
    df["building_count"] = df.groupby(["zensus_population_id"]).cumcount() + 1
149
150
    # generate random synthetic buildings
151
    edge_length = 5
152
    # create random points within census cells
153
    points = random_point_in_square(geom=df["geom"], tol=edge_length / 2)
154
155
    df.reset_index(drop=True, inplace=True)
156
    # Store center of polygon
157
    df["geom_point"] = points
158
    # Drop geometry of census cell
159
    df = df.drop(columns=["geom"])
160
161
    return df
162
163
164
def create_synthetic_buildings(df, points=None, crs="EPSG:3035"):
165
    """
166
    Synthetic buildings are generated around points.
167
    """
168
169
    if isinstance(points, str) and points in df.columns:
170
        points = df[points]
171
    elif isinstance(points, gpd.GeoSeries):
172
        pass
173
    else:
174
        raise ValueError("Points are of the wrong type")
175
176
    # Create building using a square around point
177
    edge_length = 5
178
    df["geom_building"] = points.buffer(distance=edge_length / 2, cap_style=3)
179
180
    if "geom_point" not in df.columns:
181
        df["geom_point"] = df["geom_building"].centroid
182
183
    # TODO Check CRS
184
    df = gpd.GeoDataFrame(
185
        df,
186
        crs=crs,
187
        geometry="geom_building",
188
    )
189
190
    # TODO remove after implementation of egon_building_id
191
    df.rename(columns={"id": "egon_building_id"}, inplace=True)
192
193
    # get max number of building ids from synthetic residential table
194
    with db.session_scope() as session:
195
        max_synth_residential_id = session.execute(
196
            func.max(OsmBuildingsSynthetic.id)
197
        ).scalar()
198
    max_synth_residential_id = int(max_synth_residential_id)
199
200
    # create sequential ids
201
    df["egon_building_id"] = range(
202
        max_synth_residential_id + 1,
203
        max_synth_residential_id + df.shape[0] + 1,
204
    )
205
206
    df["area"] = df["geom_building"].area
207
    # set building type of synthetic building
208
    df["building"] = "cts"
209
    # TODO remove in #772
210
    df = df.rename(
211
        columns={
212
            # "zensus_population_id": "cell_id",
213
            "egon_building_id": "id",
214
        }
215
    )
216
    return df
217
218
219
def buildings_with_amenities():
220
    """"""
221
222
    from saio.boundaries import egon_map_zensus_buildings_filtered_all
223
    from saio.openstreetmap import osm_buildings_filtered_with_amenities
224
225
    with db.session_scope() as session:
226
        cells_query = (
227
            session.query(
228
                osm_buildings_filtered_with_amenities.id.label(
229
                    "egon_building_id"
230
                ),
231
                osm_buildings_filtered_with_amenities.building,
232
                osm_buildings_filtered_with_amenities.n_amenities_inside,
233
                osm_buildings_filtered_with_amenities.area,
234
                osm_buildings_filtered_with_amenities.geom_building,
235
                osm_buildings_filtered_with_amenities.geom_point,
236
                egon_map_zensus_buildings_filtered_all.zensus_population_id,
237
            )
238
            .filter(
239
                osm_buildings_filtered_with_amenities.id
240
                == egon_map_zensus_buildings_filtered_all.id
241
            )
242
            .filter(
243
                EgonDemandRegioZensusElectricity.zensus_population_id
244
                == egon_map_zensus_buildings_filtered_all.zensus_population_id
245
            )
246
            .filter(
247
                EgonDemandRegioZensusElectricity.sector == "service",
248
                EgonDemandRegioZensusElectricity.scenario == "eGon2035",
249
            )
250
        )
251
    df_amenities_in_buildings = pd.read_sql(
252
        cells_query.statement, cells_query.session.bind, index_col=None
253
    )
254
255
    # TODO necessary?
256
    df_amenities_in_buildings["geom_building"] = df_amenities_in_buildings[
257
        "geom_building"
258
    ].apply(to_shape)
259
    df_amenities_in_buildings["geom_point"] = df_amenities_in_buildings[
260
        "geom_point"
261
    ].apply(to_shape)
262
263
    # # Count amenities per building
264
    # df_amenities_in_buildings["n_amenities_inside"] = 1
265
    # df_amenities_in_buildings[
266
    #     "n_amenities_inside"
267
    # ] = df_amenities_in_buildings.groupby("egon_building_id")[
268
    #     "n_amenities_inside"
269
    # ].transform(
270
    #     "sum"
271
    # )
272
273
    # # Only keep one building for multiple amenities
274
    # df_amenities_in_buildings = df_amenities_in_buildings.drop_duplicates(
275
    #     "egon_building_id"
276
    # )
277
    # df_amenities_in_buildings["building"] = "cts"
278
    # TODO maybe remove later
279
    df_amenities_in_buildings.sort_values("egon_building_id").reset_index(
280
        drop=True, inplace=True
281
    )
282
    df_amenities_in_buildings.rename(
283
        columns={
284
            # "zensus_population_id": "cell_id",
285
            "egon_building_id": "id"
286
        },
287
        inplace=True,
288
    )
289
290
    return df_amenities_in_buildings
291
292
293
# TODO maybe replace with tools.write_table_to_db
294
def write_synthetic_buildings_to_db(df_synthetic_buildings):
295
    """"""
296
    if "geom_point" not in df_synthetic_buildings.columns:
297
        df_synthetic_buildings["geom_point"] = df_synthetic_buildings[
298
            "geom_building"
299
        ].centroid
300
301
    df_synthetic_buildings = df_synthetic_buildings.rename(
302
        columns={
303
            "zensus_population_id": "cell_id",
304
            "egon_building_id": "id",
305
        }
306
    )
307
    # Only take existing columns
308
    columns = [
309
        column.key for column in OsmBuildingsSynthetic.__table__.columns
310
    ]
311
    df_synthetic_buildings = df_synthetic_buildings.loc[:, columns]
312
313
    dtypes = {i: OsmBuildingsSynthetic.__table__.columns[i].type for i in OsmBuildingsSynthetic.__table__.columns.keys()}
314
315
    # Write new buildings incl coord into db
316
    df_synthetic_buildings.to_postgis(
317
        name=OsmBuildingsSynthetic.__tablename__,
318
        con=engine,
319
        if_exists="append",
320
        # schema="openstreetmap",
321
        schema=OsmBuildingsSynthetic.__table_args__["schema"],
322
        # dtype={
323
        #     "id": OsmBuildingsSynthetic.id.type,
324
        #     "cell_id": OsmBuildingsSynthetic.cell_id.type,
325
        #     "geom_building": OsmBuildingsSynthetic.geom_building.type,
326
        #     "geom_point": OsmBuildingsSynthetic.geom_point.type,
327
        #     "n_amenities_inside": OsmBuildingsSynthetic.n_amenities_inside.type,
328
        #     "building": OsmBuildingsSynthetic.building.type,
329
        #     "area": OsmBuildingsSynthetic.area.type,
330
        # },
331
        dtype=dtypes,
332
    )
333
334
335
def buildings_without_amenities():
336
    """ """
337
    from saio.boundaries import egon_map_zensus_buildings_filtered_all
338
    from saio.openstreetmap import (
339
        osm_amenities_not_in_buildings_filtered,
340
        osm_amenities_shops_filtered,
341
        osm_buildings_filtered,
342
        osm_buildings_synthetic,
343
    )
344
    # buildings_filtered in cts-demand-cells without amenities
345
    with db.session_scope() as session:
346
347
        # Synthetic Buildings
348
        q_synth_buildings = session.query(
349
            osm_buildings_synthetic.cell_id.cast(Integer).label(
350
                "zensus_population_id"
351
            ),
352
            osm_buildings_synthetic.id.cast(Integer).label("id"),
353
            osm_buildings_synthetic.area.label("area"),
354
            osm_buildings_synthetic.geom_building.label("geom_building"),
355
            osm_buildings_synthetic.geom_point.label("geom_point"),
356
        )
357
358
        # Buildings filtered
359
        q_buildings_filtered = session.query(
360
            egon_map_zensus_buildings_filtered_all.zensus_population_id,
361
            osm_buildings_filtered.id,
362
            osm_buildings_filtered.area,
363
            osm_buildings_filtered.geom_building,
364
            osm_buildings_filtered.geom_point,
365
        ).filter(
366
            osm_buildings_filtered.id
367
            == egon_map_zensus_buildings_filtered_all.id
368
        )
369
370
        # Amenities + zensus_population_id
371
        q_amenities = (
372
            session.query(
373
                DestatisZensusPopulationPerHa.id.label(
374
                    "zensus_population_id"
375
                ),
376
            )
377
            .filter(
378
                func.st_within(
379
                    osm_amenities_shops_filtered.geom_amenity,
380
                    DestatisZensusPopulationPerHa.geom,
381
                )
382
            )
383
            .distinct(DestatisZensusPopulationPerHa.id)
384
        )
385
386
        # Cells with CTS demand but without amenities
387
        q_cts_without_amenities = (
388
            session.query(
389
                EgonDemandRegioZensusElectricity.zensus_population_id,
390
            )
391
            .filter(
392
                EgonDemandRegioZensusElectricity.sector == "service",
393
                EgonDemandRegioZensusElectricity.scenario == "eGon2035",
394
            )
395
            .filter(
396
                EgonDemandRegioZensusElectricity.zensus_population_id.notin_(
397
                    q_amenities
398
                )
399
            )
400
            .distinct()
401
        )
402
403
        # Buildings filtered + synthetic buildings residential in
404
        # cells with CTS demand but without amenities
405
        cells_query = q_synth_buildings.union(q_buildings_filtered).filter(
406
            egon_map_zensus_buildings_filtered_all.zensus_population_id.in_(
407
                q_cts_without_amenities
408
            )
409
        )
410
411
    # df_buildings_without_amenities = pd.read_sql(
412
    #     cells_query.statement, cells_query.session.bind, index_col=None)
413
    df_buildings_without_amenities = gpd.read_postgis(
414
        cells_query.statement,
415
        cells_query.session.bind,
416
        geom_col="geom_building",
417
    )
418
419
    df_buildings_without_amenities = df_buildings_without_amenities.rename(
420
        columns={
421
            # "zensus_population_id": "cell_id",
422
            "egon_building_id": "id",
423
        }
424
    )
425
426
    return df_buildings_without_amenities
427
428
429
def select_cts_buildings(df_buildings_without_amenities):
430
    """ """
431
    # TODO Adapt method
432
    # Select one building each cell
433
    # take the first
434
    df_buildings_with_cts_demand = (
435
        df_buildings_without_amenities.drop_duplicates(
436
            # subset="cell_id", keep="first"
437
            subset="zensus_population_id", keep="first"
438
        ).reset_index(drop=True)
439
    )
440
    df_buildings_with_cts_demand["n_amenities_inside"] = 1
441
    df_buildings_with_cts_demand["building"] = "cts"
442
443
    return df_buildings_with_cts_demand
444
445
446
def cells_with_cts_demand_only(df_buildings_without_amenities):
447
    """"""
448
    from saio.openstreetmap import osm_amenities_shops_filtered
449
    # cells mit amenities
450
    with db.session_scope() as session:
451
        sub_query = (
452
            session.query(
453
                DestatisZensusPopulationPerHa.id.label(
454
                    "zensus_population_id"
455
                ),
456
            )
457
            .filter(
458
                func.st_within(
459
                    osm_amenities_shops_filtered.geom_amenity,
460
                    DestatisZensusPopulationPerHa.geom,
461
                )
462
            )
463
            .distinct(DestatisZensusPopulationPerHa.id)
464
        )
465
466
        cells_query = (
467
            session.query(
468
                EgonDemandRegioZensusElectricity.zensus_population_id,
469
                EgonDemandRegioZensusElectricity.scenario,
470
                EgonDemandRegioZensusElectricity.sector,
471
                EgonDemandRegioZensusElectricity.demand,
472
                DestatisZensusPopulationPerHa.geom,
473
            )
474
            .filter(
475
                EgonDemandRegioZensusElectricity.sector == "service",
476
                EgonDemandRegioZensusElectricity.scenario == "eGon2035",
477
            )
478
            .filter(
479
                EgonDemandRegioZensusElectricity.zensus_population_id.notin_(
480
                    sub_query
481
                )
482
            )
483
            .filter(
484
                EgonDemandRegioZensusElectricity.zensus_population_id
485
                == DestatisZensusPopulationPerHa.id
486
            )
487
        )
488
489
    df_cts_cell_without_amenities = gpd.read_postgis(
490
        cells_query.statement,
491
        cells_query.session.bind,
492
        geom_col="geom",
493
        index_col=None,
494
    )
495
496
    # TODO maybe remove
497
    df_buildings_without_amenities = df_buildings_without_amenities.rename(
498
        columns={"cell_id": "zensus_population_id"}
499
    )
500
501
    # Census cells with only cts demand
502
    df_cells_only_cts_demand = df_cts_cell_without_amenities.loc[
503
        ~df_cts_cell_without_amenities["zensus_population_id"].isin(
504
            df_buildings_without_amenities["zensus_population_id"].unique()
505
        )
506
    ]
507
508
    df_cells_only_cts_demand.reset_index(drop=True, inplace=True)
509
510
    return df_cells_only_cts_demand
511
512
513
def calc_census_cell_share(scenario="eGon2035"):
514
    """"""
515
516
    with db.session_scope() as session:
517
        cells_query = (
518
            session.query(
519
                EgonDemandRegioZensusElectricity, MapZensusGridDistricts.bus_id
520
            )
521
            .filter(EgonDemandRegioZensusElectricity.sector == "service")
522
            .filter(EgonDemandRegioZensusElectricity.scenario == scenario)
523
            .filter(
524
                EgonDemandRegioZensusElectricity.zensus_population_id
525
                == MapZensusGridDistricts.zensus_population_id
526
            )
527
        )
528
529
    df_demand_regio_electricity_demand = pd.read_sql(
530
        cells_query.statement,
531
        cells_query.session.bind,
532
        index_col="zensus_population_id",
533
    )
534
535
    # get demand share of cell per bus
536
    # share ist für scenarios identisch
537
    df_census_share = df_demand_regio_electricity_demand[
538
        "demand"
539
    ] / df_demand_regio_electricity_demand.groupby("bus_id")[
540
        "demand"
541
    ].transform(
542
        "sum"
543
    )
544
    df_census_share = df_census_share.rename("cell_share")
545
546
    df_census_share = pd.concat(
547
        [df_census_share, df_demand_regio_electricity_demand[["bus_id", "scenario"]]], axis=1
548
    )
549
550
    df_census_share.reset_index(inplace=True)
551
    return df_census_share
552
553
554
def calc_building_demand_profile_share(df_cts_buildings, scenario="eGon2035"):
555
    """
556
    Share of cts electricity demand profile per bus for every selected building
557
    """
558
559
    def calc_building_amenity_share(df_cts_buildings):
560
        """"""
561
        df_building_amenity_share = 1 / df_cts_buildings.groupby(
562
            "zensus_population_id")["n_amenities_inside"].transform("sum")
563
        df_building_amenity_share = pd.concat(
564
            [
565
                df_building_amenity_share.rename("building_amenity_share"),
566
                df_cts_buildings[["zensus_population_id", "id"]],
567
            ],
568
            axis=1,
569
        )
570
        return df_building_amenity_share
571
572
    df_building_amenity_share = calc_building_amenity_share(df_cts_buildings)
573
574
    df_census_cell_share = calc_census_cell_share(scenario)
575
576
    df_demand_share = pd.merge(left=df_building_amenity_share, right=df_census_cell_share,
577
                               left_on="zensus_population_id", right_on="zensus_population_id")
578
    df_demand_share["profile_share"] = df_demand_share["building_amenity_share"].multiply(
579
        df_demand_share["cell_share"])
580
581
    return df_demand_share[["id", "bus_id", "scenario", "profile_share"]]
582
583
584
def calc_building_profiles(df_demand_share=None, egon_building_id=None, scenario="eGon2035"):
585
    """
586
587
    """
588
589
    if not isinstance(df_demand_share, pd.DataFrame):
590
        with db.session_scope() as session:
591
            cells_query = session.query(EgonCtsElectricityDemandBuildingShare)
592
593
        df_demand_share = pd.read_sql(
594
            cells_query.statement, cells_query.session.bind, index_col=None)
595
596
    df_cts_profiles = calc_load_curves_cts(scenario)
597
598
    # Only calculate selected building profile if egon_building_id is given
599
    if isinstance(egon_building_id, int) and egon_building_id in df_demand_share["id"]:
600
        df_demand_share = df_demand_share.loc[
601
            df_demand_share["id"] == egon_building_id]
602
603
    df_building_profiles = pd.DataFrame()
604
    for bus_id, df in df_demand_share.groupby('bus_id'):
605
        shares = df.set_index("id", drop=True)["profile_share"]
606
        profile = df_cts_profiles.loc[:, bus_id]
607
        building_profiles = profile.apply(lambda x: x * shares)
0 ignored issues
show
introduced by
The variable shares does not seem to be defined in case the for loop on line 604 is not entered. Are you sure this can never be the case?
Loading history...
608
        df_building_profiles = pd.concat([df_building_profiles, building_profiles], axis=1)
609
610
    return df_building_profiles
611
612
613
def cts_to_buildings():
614
    """"""
615
    # Buildings with amenities
616
    df_buildings_with_amenities = buildings_with_amenities()
617
618
    # Remove synthetic CTS buildings if existing
619
    delete_synthetic_cts_buildings()
620
    # Create synthetic buildings for amenites without buildings
621
    df_amenities_without_buildings = amenities_without_buildings()
622
    df_amenities_without_buildings["n_amenities_inside"] = 1
623
    df_synthetic_buildings_with_amenities = create_synthetic_buildings(
624
        df_amenities_without_buildings, points="geom_amenity"
625
    )
626
627
    # TODO write to DB and remove renaming
628
    # write_synthetic_buildings_to_db(df_synthetic_buildings_with_amenities)
629
    write_table_to_postgis(df_synthetic_buildings_with_amenities.rename(
630
        columns={
631
            "zensus_population_id": "cell_id",
632
            "egon_building_id": "id",
633
        }),
634
        OsmBuildingsSynthetic,
635
        drop=False)
636
637
    # Cells without amenities but CTS demand and buildings
638
    df_buildings_without_amenities = buildings_without_amenities()
639
640
    # TODO Fix Adhoc Bugfix duplicated buildings
641
    mask = df_buildings_without_amenities.loc[
642
        df_buildings_without_amenities['id'].isin(
643
            df_buildings_with_amenities['id'])].index
644
    df_buildings_without_amenities = df_buildings_without_amenities.drop(
645
        index=mask).reset_index(drop=True)
646
647
    df_buildings_without_amenities = select_cts_buildings(
648
        df_buildings_without_amenities
649
    )
650
    df_buildings_without_amenities["n_amenities_inside"] = 1
651
652
    # Create synthetic amenities and buildings in cells with only CTS demand
653
    df_cells_with_cts_demand_only = cells_with_cts_demand_only(
654
        df_buildings_without_amenities
655
    )
656
    # Only 1 Amenity per cell
657
    df_cells_with_cts_demand_only["n_amenities_inside"] = 1
658
    # Only 1 Amenity per Building
659
    df_cells_with_cts_demand_only = place_buildings_with_amenities(
660
        df_cells_with_cts_demand_only, amenities=1
661
    )
662
    # Leads to only 1 building per cell
663
    df_synthetic_buildings_without_amenities = (
664
        create_synthetic_buildings(
665
            df_cells_with_cts_demand_only, points="geom_point"
666
        )
667
    )
668
669
    # TODO write to DB and remove renaming
670
    # write_synthetic_buildings_to_db(df_synthetic_buildings_without_amenities)
671
    write_table_to_postgis(df_synthetic_buildings_without_amenities.rename(
672
        columns={
673
            "zensus_population_id": "cell_id",
674
            "egon_building_id": "id",
675
        }),
676
        OsmBuildingsSynthetic,
677
        drop=False)
678
679
    # Concat all buildings
680
    columns = ["zensus_population_id", "id", "geom_building", "n_amenities_inside"]
681
    # columns = ["zensus_population_id", "id", "geom_building", "n_amenities_inside", "table"]
682
    # df_buildings_with_amenities["table"] = "df_buildings_with_amenities"
683
    # df_synthetic_buildings_with_amenities["table"] = "df_synthetic_buildings_with_amenities"
684
    # df_buildings_without_amenities["table"] = "df_buildings_without_amenities"
685
    # df_synthetic_buildings_without_amenities["table"] = "df_synthetic_buildings_without_amenities"
686
687
    df_cts_buildings = pd.concat(
688
        [
689
            df_buildings_with_amenities[columns],
690
            df_synthetic_buildings_with_amenities[columns],
691
            df_buildings_without_amenities[columns],
692
            df_synthetic_buildings_without_amenities[columns],
693
        ],
694
        axis=0,
695
        ignore_index=True,
696
    )
697
    # TODO maybe remove after #772
698
    df_cts_buildings["id"] = df_cts_buildings["id"].astype(int)
699
700
    df_demand_share_2035 = calc_building_demand_profile_share(df_cts_buildings,
701
                                                         scenario="eGon2035")
702
    df_demand_share_100RE = calc_building_demand_profile_share(df_cts_buildings,
703
                                                         scenario="eGon100RE")
704
705
    df_demand_share = pd.concat([df_demand_share_2035, df_demand_share_100RE],
706
                                axis=0, ignore_index=True)
707
708
    # TODO Why are there nonunique ids?
709
    #  needs to be removed as soon as 'id' is unique
710
    df_demand_share = df_demand_share.drop_duplicates(subset="id")
711
712
    write_table_to_postgres(df_demand_share,
713
                            EgonCtsElectricityDemandBuildingShare,
714
                            drop=True)
715
716
    return df_cts_buildings, df_demand_share
717
718
719
def get_peak_load_cts_buildings():
720
721
    # TODO Check units, maybe MwH?
722
    df_building_profiles = calc_building_profiles(scenario="eGon2035")
723
    df_peak_load_2035 = df_building_profiles.max(axis=0).rename(
724
        "cts_peak_load_in_w_2035")
725
    df_building_profiles = calc_building_profiles(scenario="eGon2035")
726
    df_peak_load_100RE = df_building_profiles.max(axis=0).rename(
727
        "cts_peak_load_in_w_100RE")
728
    df_peak_load = pd.concat([df_peak_load_2035, df_peak_load_100RE],
729
                             axis=1).reset_index()
730
731
    CtsPeakLoads.__table__.drop(bind=engine, checkfirst=True)
732
    CtsPeakLoads.__table__.create(bind=engine, checkfirst=True)
733
734
    # Write peak loads into db
735
    with db.session_scope() as session:
736
        session.bulk_insert_mappings(
737
            CtsPeakLoads,
738
            df_peak_load.to_dict(orient="records"),
739
        )
740
741
742
def delete_synthetic_cts_buildings():
743
    # import db tables
744
    from saio.openstreetmap import osm_buildings_synthetic
745
746
    # cells mit amenities
747
    with db.session_scope() as session:
748
        session.query(
749
            osm_buildings_synthetic
750
        ).filter(
751
            osm_buildings_synthetic.building == 'cts'
752
        ).delete()
753
754
755
class CtsElectricityBuildings(Dataset):
756
    def __init__(self, dependencies):
757
        super().__init__(
758
            name="CtsElectricityBuildings",
759
            version="0.0.0.",
760
            dependencies=dependencies,
761
            tasks=(cts_to_buildings,
762
                   get_peak_load_cts_buildings,
763
                   # get_all_cts_building_profiles,
764
                   ),
765
        )
766