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

buildings_with_amenities()   B

Complexity

Conditions 2

Size

Total Lines 72
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
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
    building_id = Column(String, primary_key=True)
59
    cts_peak_load_in_w_2035 = Column(REAL)
60
    cts_peak_load_in_w_2050 = 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
    # Create synthetic buildings for amenites without buildings
619
    df_amenities_without_buildings = amenities_without_buildings()
620
    df_amenities_without_buildings["n_amenities_inside"] = 1
621
    df_synthetic_buildings_with_amenities = create_synthetic_buildings(
622
        df_amenities_without_buildings, points="geom_amenity"
623
    )
624
625
    # TODO write to DB and remove renaming
626
    # write_synthetic_buildings_to_db(df_synthetic_buildings_with_amenities)
627
    write_table_to_postgis(df_synthetic_buildings_with_amenities.rename(
628
        columns={
629
            "zensus_population_id": "cell_id",
630
            "egon_building_id": "id",
631
        }),
632
        OsmBuildingsSynthetic,
633
        drop=False)
634
635
    # Cells without amenities but CTS demand and buildings
636
    df_buildings_without_amenities = buildings_without_amenities()
637
638
    # TODO Fix Adhoc Bugfix duplicated buildings
639
    mask = df_buildings_without_amenities.loc[
640
        df_buildings_without_amenities['id'].isin(
641
            df_buildings_with_amenities['id'])].index
642
    df_buildings_without_amenities = df_buildings_without_amenities.drop(
643
        index=mask).reset_index(drop=True)
644
645
    df_buildings_without_amenities = select_cts_buildings(
646
        df_buildings_without_amenities
647
    )
648
    df_buildings_without_amenities["n_amenities_inside"] = 1
649
650
    # Create synthetic amenities and buildings in cells with only CTS demand
651
    df_cells_with_cts_demand_only = cells_with_cts_demand_only(
652
        df_buildings_without_amenities
653
    )
654
    # Only 1 Amenity per cell
655
    df_cells_with_cts_demand_only["n_amenities_inside"] = 1
656
    # Only 1 Amenity per Building
657
    df_cells_with_cts_demand_only = place_buildings_with_amenities(
658
        df_cells_with_cts_demand_only, amenities=1
659
    )
660
    # Leads to only 1 building per cell
661
    df_synthetic_buildings_without_amenities = (
662
        create_synthetic_buildings(
663
            df_cells_with_cts_demand_only, points="geom_point"
664
        )
665
    )
666
667
    # TODO write to DB and remove renaming
668
    # write_synthetic_buildings_to_db(df_synthetic_buildings_without_amenities)
669
    write_table_to_postgis(df_synthetic_buildings_without_amenities.rename(
670
        columns={
671
            "zensus_population_id": "cell_id",
672
            "egon_building_id": "id",
673
        }),
674
        OsmBuildingsSynthetic,
675
        drop=False)
676
677
    # Concat all buildings
678
    columns = ["zensus_population_id", "id", "geom_building", "n_amenities_inside"]
679
    # columns = ["zensus_population_id", "id", "geom_building", "n_amenities_inside", "table"]
680
    # df_buildings_with_amenities["table"] = "df_buildings_with_amenities"
681
    # df_synthetic_buildings_with_amenities["table"] = "df_synthetic_buildings_with_amenities"
682
    # df_buildings_without_amenities["table"] = "df_buildings_without_amenities"
683
    # df_synthetic_buildings_without_amenities["table"] = "df_synthetic_buildings_without_amenities"
684
685
    df_cts_buildings = pd.concat(
686
        [
687
            df_buildings_with_amenities[columns],
688
            df_synthetic_buildings_with_amenities[columns],
689
            df_buildings_without_amenities[columns],
690
            df_synthetic_buildings_without_amenities[columns],
691
        ],
692
        axis=0,
693
        ignore_index=True,
694
    )
695
    # TODO maybe remove after #772
696
    df_cts_buildings["id"] = df_cts_buildings["id"].astype(int)
697
698
    df_demand_share_2035 = calc_building_demand_profile_share(df_cts_buildings,
699
                                                         scenario="eGon2035")
700
    df_demand_share_100RE = calc_building_demand_profile_share(df_cts_buildings,
701
                                                         scenario="eGon100RE")
702
703
    df_demand_share = pd.concat([df_demand_share_2035, df_demand_share_100RE],
704
                                axis=0, ignore_index=True)
705
706
    # TODO Why are there nonunique ids?
707
    #  needs to be removed as soon as 'id' is unique
708
    df_demand_share = df_demand_share.drop_duplicates(subset="id")
709
710
    write_table_to_postgres(df_demand_share,
711
                            EgonCtsElectricityDemandBuildingShare,
712
                            drop=True)
713
714
    return df_cts_buildings, df_demand_share
715
716
717
def get_peak_load_cts_buildings():
718
719
    df_building_profiles = calc_building_profiles()
720
    df_peak_load = df_building_profiles.max(axis=1)
721
722
    CtsPeakLoads.__table__.drop(bind=engine, checkfirst=True)
723
    CtsPeakLoads.__table__.create(bind=engine, checkfirst=True)
724
725
    # Write peak loads into db
726
    with db.session_scope() as session:
727
        session.bulk_insert_mappings(
728
            CtsPeakLoads,
729
            df_peak_load.to_dict(orient="records"),
730
        )
731
732
733
def delete_synthetic_cts_buildings():
734
    # import db tables
735
    from saio.openstreetmap import osm_buildings_synthetic
736
737
    # cells mit amenities
738
    with db.session_scope() as session:
739
        session.query(
740
            osm_buildings_synthetic
741
        ).filter(
742
            osm_buildings_synthetic.building == 'cts'
743
        ).delete()
744
745
746
class CtsElectricityBuildings(Dataset):
747
    def __init__(self, dependencies):
748
        super().__init__(
749
            name="CtsElectricityBuildings",
750
            version="0.0.0.",
751
            dependencies=dependencies,
752
            tasks=(cts_to_buildings,
753
                   get_peak_load_cts_buildings,
754
                   # get_all_cts_building_profiles,
755
                   ),
756
        )
757