Commit 8d35f9e5 authored by Cecilia Nievas's avatar Cecilia Nievas
Browse files

Added feature to retrieve number of buildings, dwellings, people, costs

parent da77eb51
Pipeline #29863 passed with stage
in 2 minutes and 13 seconds
......@@ -50,6 +50,8 @@ class AggregatedExposureModel(abc.ABC):
self.boundary_filename_pattern (str):
Pattern of the names of the geodata files that contain the boundaries of the
exposure entities of the input aggregated exposure model.
self.currency (str):
Currency used in the AggregatedExposureModel to express building replacement costs.
"""
def __init__(self, configuration):
......@@ -65,6 +67,7 @@ class AggregatedExposureModel(abc.ABC):
self.exposure_entities = None
self.filename_pattern = None
self.boundary_filename_pattern = None
self.currency = None
def retrieve_exposure_entities(self, configuration):
"""This function retrieves the exposure entities for which an input aggregated exposure
......@@ -200,6 +203,10 @@ class ExposureModelESRM20(AggregatedExposureModel):
Relative path to the metadata .xlsx file.
CSVs (str):
Relative path to the folder that contains the CSV files per exposure entity.
self.csv_column_names
Names of columns of interest in the CSV files.
self.currency (str):
Currency used in ESRM20 to express building replacement costs.
self.exposure_entities (dictionary of ExposureEntity):
Dictionary of instances of ExposureEntity objects, each of which represent an
exposure entity where the input aggregated exposure model is defined. See
......@@ -240,6 +247,24 @@ class ExposureModelESRM20(AggregatedExposureModel):
"metadata": "sources/European_Exposure_Model_Data_Inputs_Sources.xlsx",
"CSVs": "_exposure_models",
}
self.csv_column_names = {
"Buildings": "BUILDINGS",
"Dwellings": "DWELLINGS",
"People": {
"Census": "OCCUPANTS_PER_ASSET",
"Day": "OCCUPANTS_PER_ASSET_DAY",
"Night": "OCCUPANTS_PER_ASSET_NIGHT",
"Transit": "OCCUPANTS_PER_ASSET_TRANSIT",
"Average": "OCCUPANTS_PER_ASSET_AVERAGE",
},
"Cost": {
"Total": "TOTAL_REPL_COST_EUR",
"Structural": "COST_STRUCTURAL_EUR",
"Non-Structural": "COST_NONSTRUCTURAL_EUR",
"Contents": "COST_CONTENTS_EUR",
},
}
self.currency = "EUR"
self.exposure_entities = self.retrieve_exposure_entities(configuration)
def retrieve_exposure_entities(self, configuration):
......@@ -382,14 +407,14 @@ class ExposureModelESRM20(AggregatedExposureModel):
"""
# Read names of data units from ESRM20's CSV files
target_column_name = "ID_%s" % (
id_column_name_data = "ID_%s" % (
str(
self.exposure_entities[exposure_entity_name].occupancy_cases[occupancy_case][
"data_units_level"
]
)
)
datatypes = {target_column_name: str}
datatypes = {id_column_name_data: str}
data_table = self._read_data_table(
configuration,
self.exposure_entities[exposure_entity_name],
......@@ -397,12 +422,12 @@ class ExposureModelESRM20(AggregatedExposureModel):
datatypes,
)
try:
data_units_names = list(data_table[target_column_name].unique())
data_units_ids = list(data_table[id_column_name_data].unique())
except KeyError:
data_units_names = []
data_units_ids = []
logger.critical(
"Error while retrieving 'data_units_names' of %s, %s: column `%s` not found"
% (exposure_entity_name, occupancy_case, target_column_name)
"Error while retrieving 'data_units_ids' of %s, %s: column `%s` not found"
% (exposure_entity_name, occupancy_case, id_column_name_data)
)
# Read geometries of data units from ESRM20's boundary files
......@@ -410,7 +435,7 @@ class ExposureModelESRM20(AggregatedExposureModel):
"data_units"
] = {}
target_column_name = "ID_%s" % (
id_column_name_geometries = "ID_%s" % (
self.exposure_entities[exposure_entity_name].occupancy_cases[occupancy_case][
self.boundary_filename_pattern["first"]
]
......@@ -422,10 +447,26 @@ class ExposureModelESRM20(AggregatedExposureModel):
datatypes,
)
for data_unit_name in data_units_names:
# Retrieve total number of buildings, dwellings, people and cost
results = self._retrieve_totals_all_data_units(
data_table, id_column_name_data, data_units_ids, exposure_entity_name
)
total_buildings, total_dwellings, total_people, total_cost = results
for data_unit_id in data_units_ids:
self.exposure_entities[exposure_entity_name].occupancy_cases[occupancy_case][
"data_units"
][data_unit_name] = DataUnit(data_unit_name, geometries_table, target_column_name)
][data_unit_id] = DataUnit(
data_unit_id,
geometries_table,
id_column_name_geometries,
total_buildings[data_unit_id],
total_dwellings[data_unit_id],
total_people[data_unit_id],
total_cost[data_unit_id],
self.currency,
)
return
def _map_data_units_types(self, original_description):
......@@ -584,3 +625,119 @@ class ExposureModelESRM20(AggregatedExposureModel):
)
return geometries_table
def _retrieve_totals_all_data_units(
self, data_table, ids_column_name, data_units_ids, exposure_entity_name
):
"""This function retrieves from data_table the total numbers of buildings, dwellings,
people and replacement costs in each data unit enumerated in data_units_ids.
Args:
data_table (Pandas DataFrame):
DataFrame with all contents of the ESRM20 CSV file for a specific
ExposureEntity and occupancy_case.
ids_column_name (str):
Name of the column of data_table where the data unit IDs are found.
data_units_ids (list of str):
List of IDs of data units assumed to be found in column ids_column_name of
data_table.
exposure_entity_name (str):
Name of the ExposureEntity to which data_units_ids belong.
Returns:
total_buildings (dict):
Dictionary containing the total number of buildings per data unit. The keys of
the dictionary are the data_units_ids. The values of total_buildings[key] are
floats.
total_dwellings (dict):
Dictionary containing the total number of dwellings per data unit. The keys of
the dictionary are the data_units_ids. The values of total_dwellings[key] are
floats.
total_people (dict):
Dictionary containing the total number of people per data unit. The keys of the
dictionary are the data_units_ids. The values of total_people[key] are
dictionaries themselves containing the following:
Census (float):
Total number of people expected to be inside all buildings in the
DataUnit obtained from distributing the census population to the
buildings, without consideration of the time of the day or distribution
of the population across different economic/educational/recreational
activities.
Day (float):
Total number of people expected to be inside all buildings in the
DataUnit during the day (approx. 10 am to 6 pm).
Night (float):
Total number of people expected to be inside all buildings in the
DataUnit during the night (approx. 10 pm to 6 am).
Transit (float):
Total number of people expected to be inside all buildings in the
DataUnit during transit times (approx. 6 am to 10 am and 6 pm to 10 pm).
Average (float):
Average total number of people expected to be inside all buildings in
the DataUnit at an undefined time of the day (average of Day, Night and
Transit).
total_cost (dict):
Dictionary containing the monetary value of all the buildings per data unit
(cost of total_buildings). The keys of the dictionary are the data_units_ids.
The values of total_cost[key] are dictionaries themselves containing the
following:
Total (float):
Total replacement cost of all buildings, including structural and
non-structural components, as well as contents.
Structural (float):
Replacement cost of the structural components of all buildings.
Non-Structural (float):
Replacement cost of the non-structural components of all buildings.
Contents (float):
Replacement cost of the contents of all buildings.
"""
totals_of_data_units = {
"Buildings": {},
"Dwellings": {},
"People": {}, # Sub-keys will be retrieved from self.csv_column_names
"Cost": {}, # Sub-keys will be retrieved from self.csv_column_names
}
for data_unit_id in data_units_ids:
which = numpy.where(data_table[ids_column_name].values == data_unit_id)[0]
for parameter in totals_of_data_units.keys():
# Link this parameter with a column of data_table
aux_val = self.csv_column_names[parameter]
if isinstance(aux_val, str): # Buildings, dwellings
column = aux_val
totals_of_data_units[parameter][data_unit_id] = (
data_table[column].values[which].sum()
)
if isinstance(aux_val, dict): # People, cost
totals_of_data_units[parameter][data_unit_id] = {}
sub_dictionary = aux_val
for key in sub_dictionary.keys():
column = self.csv_column_names[parameter][key]
totals_of_data_units[parameter][data_unit_id][key] = (
data_table[column].values[which].sum()
)
total_buildings = totals_of_data_units["Buildings"]
total_dwellings = totals_of_data_units["Dwellings"]
total_people = totals_of_data_units["People"]
total_cost = totals_of_data_units["Cost"]
# Check consistency of costs
for data_unit_id in data_units_ids:
total_cost_difference = abs(
total_cost[data_unit_id]["Total"]
- (
total_cost[data_unit_id]["Structural"]
+ total_cost[data_unit_id]["Non-Structural"]
+ total_cost[data_unit_id]["Contents"]
)
)
if total_cost_difference > 1e-5:
logger.warning(
"Data Unit with ID %s of Exposure Entity '%s': The sum of structural, "
"non-structural and components' costs does not match the total cost."
% (data_unit_id, exposure_entity_name)
)
return total_buildings, total_dwellings, total_people, total_cost
......@@ -21,6 +21,21 @@ import numpy
logger = logging.getLogger()
_TOTAL_PEOPLE_DEFAULT = {
"Census": None,
"Day": None,
"Night": None,
"Transit": None,
"Average": None,
}
_TOTAL_COST_DEFAULT = {
"Total": None,
"Structural": None,
"Non-Structural": None,
"Contents": None,
}
class DataUnit:
"""This class represents the smallest geographical unit of an ExposureEntity, that is, the
......@@ -32,6 +47,45 @@ class DataUnit:
ID of the DataUnit (e.g. ID of the administrative unit it represents).
self.geometry (Shapely polygon):
Geometry of the data unit.
self.total_buildings (float):
Total number of buildings in the DataUnit.
self.total_dwellings (float):
Total number of dwellings in the DataUnit.
self.total_people (dict):
Dictionary with the total number of people in the DataUnit. The keys of the
dictionary are:
Census (float):
Total number of people expected to be inside all buildings in the DataUnit
obtained from distributing the census population to the buildings, without
consideration of the time of the day or distribution of the population
across different economic/educational/recreational activities.
Day (float):
Total number of people expected to be inside all buildings in the DataUnit
during the day (approx. 10 am to 6 pm).
Night (float):
Total number of people expected to be inside all buildings in the DataUnit
during the night (approx. 10 pm to 6 am).
Transit (float):
Total number of people expected to be inside all buildings in the DataUnit
during transit times (approx. 6 am to 10 am and 6 pm to 10 pm).
Average (float):
Average total number of people expected to be inside all buildings in the
DataUnit at an undefined time of the day (average of Day, Night and
Transit).
self.total_cost (dict):
Dictionary with the monetary value of all the buildings in the DataUnit (cost of
self.total_buildings). The keys of the dictionary are:
Total (float):
Total replacement cost of all buildings, including structural and
non-structural components, as well as contents.
Structural (float):
Replacement cost of the structural components of all buildings.
Non-Structural (float):
Replacement cost of the non-structural components of all buildings.
Contents (float):
Replacement cost of the contents of all buildings.
self.currency (str):
Currency used in self.total_cost to express building replacement costs.
self.data_unit_tiles (GeoPandas GeoDataFrame):
Definition of the data-unit tiles associated with the data unit. It is filled in by
ExposureEntity.create_data_unit_tiles(), processing all the data units associated
......@@ -43,7 +97,17 @@ class DataUnit:
Geometry of the data-unit tile.
"""
def __init__(self, dataunit_id, geometries_table, target_column_name):
def __init__(
self,
dataunit_id,
geometries_table,
target_column_name,
total_buildings=None,
total_dwellings=None,
total_people=_TOTAL_PEOPLE_DEFAULT,
total_cost=_TOTAL_COST_DEFAULT,
currency=None,
):
"""
Args:
dataunit_id (str):
......@@ -58,11 +122,43 @@ class DataUnit:
Geometry.
target_column_name (str):
Name of the column in which the ID of the Data Unit will be sought.
total_buildings (float):
Total number of buildings in the DataUnit.
total_dwellings (float):
Total number of dwellings in the DataUnit.
total_people (dict of floats):
Dictionary with the total number of people in the DataUnit. The keys should be:
Census, Day, Night, Transit, Average. See definitions in the description of
DataUnit.total_people.
total_cost (dict of floats):
Dictionary with the monetary value of all the buildings in the DataUnit (cost of
total_buildings). The keys should be: Total, Structural, Non-Structural,
Contents. See definitions in the description of DataUnit.total_cost.
currency (str):
Currency used in total_cost to express building replacement costs.
"""
# Check that the keys of total_people are the expected ones
assert "Census" in total_people.keys()
assert "Day" in total_people.keys()
assert "Night" in total_people.keys()
assert "Transit" in total_people.keys()
assert "Average" in total_people.keys()
# Check that the keys of total_cost are the expected ones
assert "Total" in total_cost.keys()
assert "Structural" in total_cost.keys()
assert "Non-Structural" in total_cost.keys()
assert "Contents" in total_cost.keys()
self.id = dataunit_id
self.geometry = self.get_data_unit_geometry(geometries_table, target_column_name)
self.data_unit_tiles = None
self.total_buildings = total_buildings
self.total_dwellings = total_dwellings
self.total_people = total_people
self.total_cost = total_cost
self.currency = currency
def get_data_unit_geometry(self, geometries_table, target_column_name):
"""This function retrieves the geometry of the data unit, by reading it from
......
lon,lat,taxonomy,number,ID_1
20.1,47.3,A,35.2,Unit_X
20.1,47.3,B,12.7,Unit_X
20.1,47.3,C,8.9,Unit_X
20.1,47.3,C,5.7,Unit_X
19.8,47.4,A,25.6,Unit_Y
19.8,47.4,A,7.9,Unit_Y
19.8,47.4,B,23.5,Unit_Y
20.4,46.9,A,40.2,Unit_Z
20.4,46.9,B,16.3,Unit_Z
20.4,46.9,C,33.4,Unit_Z
lon,lat,taxonomy,BUILDINGS,ID_1,DWELLINGS,TOTAL_REPL_COST_EUR,COST_STRUCTURAL_EUR,COST_NONSTRUCTURAL_EUR,COST_CONTENTS_EUR,OCCUPANTS_PER_ASSET,OCCUPANTS_PER_ASSET_DAY,OCCUPANTS_PER_ASSET_NIGHT,OCCUPANTS_PER_ASSET_TRANSIT,OCCUPANTS_PER_ASSET_AVERAGE
20.1,47.3,A,35.2,Unit_X,35.2,316800000,126720000,63360000,126720000,1056,844.8,105.6,211.2,387.2
20.1,47.3,B,12.7,Unit_X,12.7,114300000,45720000,22860000,45720000,381,304.8,38.1,76.2,139.7
20.1,47.3,C,8.9,Unit_X,8.9,80100000,32040000,16020000,32040000,267,213.6,26.7,53.4,97.9
20.1,47.3,C,5.7,Unit_X,5.7,51300000,20520000,10260000,20520000,171,136.8,17.1,34.2,62.7
19.8,47.4,A,25.6,Unit_Y,25.6,230400000,92160000,46080000,92160000,768,614.4,76.8,153.6,281.6
19.8,47.4,A,7.9,Unit_Y,7.9,71100000,28440000,14220000,28440000,237,189.6,23.7,47.4,86.9
19.8,47.4,B,23.5,Unit_Y,23.5,211500000,84600000,42300000,84600000,705,564,70.5,141,258.5
20.4,46.9,A,40.2,Unit_Z,40.2,361800000,144720000,72360000,144720000,1206,964.8,120.6,241.2,442.2
20.4,46.9,B,16.3,Unit_Z,16.3,146700000,58680000,29340000,58680000,489,391.2,48.9,97.8,179.3
20.4,46.9,C,33.4,Unit_Z,33.4,300600000,120240000,60120000,120240000,1002,801.6,100.2,200.4,367.4
lon,lat,taxonomy,number,ID_1
20.1,47.3,A,35.2,Unit_1
20.1,47.3,B,12.7,Unit_1
20.1,47.3,C,8.9,Unit_1
20.1,47.3,C,5.7,Unit_1
19.8,47.4,A,25.6,Unit_2
19.8,47.4,A,7.9,Unit_2
19.8,47.4,B,23.5,Unit_2
20.4,46.9,A,40.2,Unit_3
20.4,46.9,B,16.3,Unit_3
20.4,46.9,C,33.4,Unit_3
lon,lat,taxonomy,BUILDINGS,ID_1,DWELLINGS,TOTAL_REPL_COST_EUR,COST_STRUCTURAL_EUR,COST_NONSTRUCTURAL_EUR,COST_CONTENTS_EUR,OCCUPANTS_PER_ASSET,OCCUPANTS_PER_ASSET_DAY,OCCUPANTS_PER_ASSET_NIGHT,OCCUPANTS_PER_ASSET_TRANSIT,OCCUPANTS_PER_ASSET_AVERAGE
20.1,47.3,A,35.2,Unit_1,105.6,158400000,79200000,47520000,31680000,264,39.6,184.8,52.8,92.4
20.1,47.3,B,12.7,Unit_1,38.1,57150000,28575000,17145000,11430000,95.25,14.2875,66.675,19.05,33.3375
20.1,47.3,C,8.9,Unit_1,26.7,40050000,20025000,12015000,8010000,66.75,10.0125,46.725,13.35,23.3625
20.1,47.3,C,5.7,Unit_1,17.1,25650000,12825000,7695000,5130000,42.75,6.4125,29.925,8.55,14.9625
19.8,47.4,A,25.6,Unit_2,76.8,115200000,57600000,34560000,23040000,192,28.8,134.4,38.4,67.2
19.8,47.4,A,7.9,Unit_2,23.7,35550000,17775000,10665000,7110000,59.25,8.8875,41.475,11.85,20.7375
19.8,47.4,B,23.5,Unit_2,70.5,105750000,52875000,31725000,21150000,176.25,26.4375,123.375,35.25,61.6875
20.4,46.9,A,40.2,Unit_3,120.6,180900000,90450000,54270000,36180000,301.5,45.225,211.05,60.3,105.525
20.4,46.9,B,16.3,Unit_3,48.9,73350000,36675000,22005000,14670000,122.25,18.3375,85.575,24.45,42.7875
20.4,46.9,C,33.4,Unit_3,100.2,150300000,75150000,45090000,30060000,250.5,37.575,175.35,50.1,87.675
lon,lat,taxonomy,number,ID_2
20.6,46.8,A,38.72,Unit_A
20.6,46.8,B,13.97,Unit_A
20.6,46.8,B,9.79,Unit_A
20.6,46.8,C,6.27,Unit_A
20.3,46.9,A,28.16,Unit_B
20.3,46.9,C,8.69,Unit_B
20.3,46.9,C,25.85,Unit_B
20.9,46.4,A,44.22,Unit_C
20.9,46.4,B,17.93,Unit_C
20.9,46.4,C,36.74,Unit_C
lon,lat,taxonomy,BUILDINGS,ID_2,DWELLINGS,TOTAL_REPL_COST_EUR,COST_STRUCTURAL_EUR,COST_NONSTRUCTURAL_EUR,COST_CONTENTS_EUR,OCCUPANTS_PER_ASSET,OCCUPANTS_PER_ASSET_DAY,OCCUPANTS_PER_ASSET_NIGHT,OCCUPANTS_PER_ASSET_TRANSIT,OCCUPANTS_PER_ASSET_AVERAGE
20.6,46.8,A,38.72,Unit_A,38.72,348480000,139392000,69696000,139392000,1161.6,929.28,116.16,232.32,425.92
20.6,46.8,B,13.97,Unit_A,13.97,125730000,50292000,25146000,50292000,419.1,335.28,41.91,83.82,153.67
20.6,46.8,B,9.79,Unit_A,9.79,88110000,35244000,17622000,35244000,293.7,234.96,29.37,58.74,107.69
20.6,46.8,C,6.27,Unit_A,6.27,56430000,22572000,11286000,22572000,188.1,150.48,18.81,37.62,68.97
20.3,46.9,A,28.16,Unit_B,28.16,253440000,101376000,50688000,101376000,844.8,675.84,84.48,168.96,309.76
20.3,46.9,C,8.69,Unit_B,8.69,78210000,31284000,15642000,31284000,260.7,208.56,26.07,52.14,95.59
20.3,46.9,C,25.85,Unit_B,25.85,232650000,93060000,46530000,93060000,775.5,620.4,77.55,155.1,284.35
20.9,46.4,A,44.22,Unit_C,44.22,397980000,159192000,79596000,159192000,1326.6,1061.28,132.66,265.32,486.42
20.9,46.4,B,17.93,Unit_C,17.93,161370000,64548000,32274000,64548000,537.9,430.32,53.79,107.58,197.23
20.9,46.4,C,36.74,Unit_C,36.74,330660000,132264000,66132000,132264000,1102.2,881.76,110.22,220.44,404.14
lon,lat,taxonomy,number,ID_1
20.6,46.8,A,38.72,Unit_1
20.6,46.8,B,13.97,Unit_1
20.6,46.8,B,9.79,Unit_1
20.6,46.8,C,6.27,Unit_1
20.3,46.9,A,28.16,Unit_2
20.3,46.9,C,8.69,Unit_2
20.3,46.9,C,25.85,Unit_2
20.9,46.4,A,44.22,Unit_3
20.9,46.4,B,17.93,Unit_3
20.9,46.4,C,36.74,Unit_3
lon,lat,taxonomy,BUILDINGS,ID_1,DWELLINGS,TOTAL_REPL_COST_EUR,COST_STRUCTURAL_EUR,COST_NONSTRUCTURAL_EUR,COST_CONTENTS_EUR,OCCUPANTS_PER_ASSET,OCCUPANTS_PER_ASSET_DAY,OCCUPANTS_PER_ASSET_NIGHT,OCCUPANTS_PER_ASSET_TRANSIT,OCCUPANTS_PER_ASSET_AVERAGE
20.6,46.8,A,38.72,Unit_1,116.16,174240000,87120000,52272000,34848000,290.4,43.56,203.28,58.08,101.64
20.6,46.8,B,13.97,Unit_1,41.91,62865000,31432500,18859500,12573000,104.775,15.71625,73.3425,20.955,36.67125
20.6,46.8,B,9.79,Unit_1,29.37,44055000,22027500,13216500,8811000,73.425,11.01375,51.3975,14.685,25.69875
20.6,46.8,C,6.27,Unit_1,18.81,28215000,14107500,8464500,5643000,47.025,7.05375,32.9175,9.405,16.45875
20.3,46.9,A,28.16,Unit_2,84.48,126720000,63360000,38016000,25344000,211.2,31.68,147.84,42.24,73.92
20.3,46.9,C,8.69,Unit_2,26.07,39105000,19552500,11731500,7821000,65.175,9.77625,45.6225,13.035,22.81125
20.3,46.9,C,25.85,Unit_2,77.55,116325000,58162500,34897500,23265000,193.875,29.08125,135.7125,38.775,67.85625
20.9,46.4,A,44.22,Unit_3,132.66,198990000,99495000,59697000,39798000,331.65,49.7475,232.155,66.33,116.0775
20.9,46.4,B,17.93,Unit_3,53.79,80685000,40342500,24205500,16137000,134.475,20.17125,94.1325,26.895,47.06625
20.9,46.4,C,36.74,Unit_3,110.22,165330000,82665000,49599000,33066000,275.55,41.3325,192.885,55.11,96.4425
Col_0,Col_1,Col_2,Col_3,Col_4,Col_5,Col_6,Col_7,Col_8,Col_9,Col_10,Col_11,Col_12,Col_13
entity_names,occupancy_names,Data_Unit_ID,total_buildings,total_dwellings,total_people,total_people,total_people,total_people,total_people,total_cost,total_cost,total_cost,total_cost
entity_names,occupancy_names,Data_Unit_ID,total_buildings,total_dwellings,Census,Day,Night,Transit,Average,Total,Structural,Non-Structural,Contents
Entity_1,residential,Unit_1,62.5,187.5,468.75,70.3125,328.125,93.75,164.0625,281250000,140625000,84375000,56250000
Entity_1,residential,Unit_2,57,171,427.5,64.125,299.25,85.5,149.625,256500000,128250000,76950000,51300000
Entity_1,residential,Unit_3,89.9,269.7,674.25,101.1375,471.975,134.85,235.9875,404550000,202275000,121365000,80910000
Entity_1,commercial,Unit_X,62.5,62.5,1875,1500,187.5,375,687.5,562500000,225000000,112500000,225000000
Entity_1,commercial,Unit_Y,57,57,1710,1368,171,342,627,513000000,205200000,102600000,205200000
Entity_1,commercial,Unit_Z,89.9,89.9,2697,2157.6,269.7,539.4,988.9,809100000,323640000,161820000,323640000
Entity_2,commercial,Unit_A,68.75,68.75,2062.5,1650,206.25,412.5,756.25,618750000,247500000,123750000,247500000
Entity_2,commercial,Unit_B,62.7,62.7,1881,1504.8,188.1,376.2,689.7,564300000,225720000,112860000,225720000
Entity_2,commercial,Unit_C,98.89,98.89,2966.7,2373.36,296.67,593.34,1087.79,890010000,356004000,178002000,356004000
......@@ -200,6 +200,14 @@ def test_ExposureModelESRM20():
sep=",",
dtype={"LonW": str, "LonE": str, "LatN": str, "LatS": str},
)
expected_results_totals = pandas.read_csv(
os.path.join(
os.path.dirname(__file__),
"data",
"expected_results_test_ExposureModelESRM20.csv",
),
sep=",",
)
for i in range(len(entity_names)):
# Check number of data units
......@@ -208,6 +216,7 @@ def test_ExposureModelESRM20():
.occupancy_cases[occupancy_names[i]]["data_units"]
.keys()
) == len(unit_ids[i])
# Check names of data units
for unit_id in unit_ids[i]:
assert (
......@@ -216,6 +225,7 @@ def test_ExposureModelESRM20():
occupancy_names[i]
]["data_units"]
)
# Check bounds of the geometries of data units
for unit_id in unit_ids[i]:
geometry = (
......@@ -236,6 +246,56 @@ def test_ExposureModelESRM20():
assert "{:.2f}".format(returned_lat_n) == expected_lat_n
assert "{:.2f}".format(returned_lat_s) == expected_lat_s
# Rows of expected_results_totals associated with this entity and occupancy
rows_entity_occupancy = numpy.where(
numpy.logical_and(
expected_results_totals["Col_0"].values == entity_names[i],
expected_results_totals["Col_1"].values == occupancy_names[i],
)
)[0]
# Check total numbers of buildings, dwellings, people and costs per data unit
for unit_id in unit_ids[i]:
returned_data_unit = returned_aem.exposure_entities[
entity_names[i]
].occupancy_cases[occupancy_names[i]]["data_units"][unit_id]
# Row of expected_results_totals associated with this data-unit ID
# (within rows_entity_occupancy)
row_data_unit = numpy.where(
expected_results_totals["Col_2"].values[rows_entity_occupancy] == unit_id
)[0][0]
for col_pos, col_name in enumerate(expected_results_totals.columns):
if col_name == "Col_0" or col_name == "Col_1" or col_name == "Col_2":
continue
# pylint: disable=unsubscriptable-object
attr_name = expected_results_totals[col_name].values[0]
returned_attr_val = getattr(returned_data_unit, attr_name)
if isinstance(returned_attr_val, float):
difference_returned_expected = abs(
returned_attr_val
- float(
expected_results_totals[col_name].values[rows_entity_occupancy][
row_data_unit
]
)
)
if isinstance(returned_attr_val, dict):
sub_attr_name = expected_results_totals[col_name].values[1]
difference_returned_expected = abs(
returned_attr_val[sub_attr_name]
- float(
expected_results_totals[col_name].values[rows_entity_occupancy][
row_data_unit
]
)
)
assert difference_returned_expected < 1e-5
assert (
"data_units"
not in returned_aem.exposure_entities["Entity_1"].occupancy_cases["industrial"]
......
......@@ -19,6 +19,7 @@
import logging
import geopandas
import shapely
import pytest
from pyproj import CRS
from gdeimporter.dataunit import DataUnit
......@@ -34,16 +35,72 @@ def test_DataUnit():
shapely.geometry.Polygon([(22.5, 13.7), (28.3, 14.2), (25.1, 16.7)]),
]
geometry = geopandas.GeoSeries(geometries)
total_buildings = [1500.0, 740.6]
total_dwellings = [3000.0, 1851.5]
currency = "EUR"
aux_data = {target_column_name: unit_ids, "geometry": geometry}
geometries_table = geopandas.GeoDataFrame(aux_data)
geometries_table.crs = CRS("epsg:4326")
for i in range(len(unit_ids)):
returned_data_unit = DataUnit(unit_ids[i], geometries_table, target_column_name)
returned_data_unit = DataUnit(
unit_ids[i],
geometries_table,
target_column_name,
total_buildings=total_buildings[i],
total_dwellings=total_dwellings[i],
currency=currency,
)
assert returned_data_unit.id == unit_ids[i]
assert returned_data_unit.geometry == geometries[i]
assert returned_data_unit.total_buildings == total_buildings[i]
assert returned_data_unit.total_dwellings == total_dwellings[i]
assert returned_data_unit.currency == currency
# Test case in which the ID is not found
returned_data_unit = DataUnit("something", geometries_table, target_column_name)
assert returned_data_unit.id == "something"
assert returned_data_unit.geometry is None