diff --git a/exposurejapan/commercial.py b/exposurejapan/commercial.py index 5fa3456f2db65315fb67a7f31707e838f75e7b06..3599e7fd4706a7e50dc972f26f1bf850d951d8eb 100644 --- a/exposurejapan/commercial.py +++ b/exposurejapan/commercial.py @@ -653,9 +653,9 @@ class CommercialAggregatedExposure(SpatialiteDatabase): building attributes (main usage and basement presence) with type not equals `total` and building numbers of the building attributes (main usage and basement presence) with type `total` by doing a frequency - distribution in query Q with T.total_building and S.sum_building from the + distribution in query Q with `T.total_building` and `S.sum_building` from the joined queries S, T and updates the calculated target_number in the - BuildingNumber table. + `BuildingNumber` table. The query S computes the sum of building numbers grouped by district_id where main usage is not `total` (i.e. main_usage_id != 0) and construction material is @@ -746,9 +746,9 @@ class CommercialAggregatedExposure(SpatialiteDatabase): building attributes (main usage and earthquake resistance code) with type not equals `total` and building numbers of the building attributes (main usage and earthquake resistance code) with type `total` by doing a frequency - distribution in query Q with T.total_building and S.sum_building from the + distribution in query Q with `T.total_building` and `S.sum_building` from the joined queries S, T and updates the calculated target_number in the - BuildingNumber table. + `BuildingNumber` table. The query S computes the sum of building numbers grouped by district_id where main usage is not `total` (i.e. main_usage_id != 0) and construction material is @@ -833,6 +833,99 @@ class CommercialAggregatedExposure(SpatialiteDatabase): "main usage and earthquake resistance code" ) + def calculate_building_numbers_frequency_distributions_for_total_floor_area(self): + """ + Fixes rounding-up errors observed between the sum of building numbers of the + building attributes (main usage and total floor area (in square meters)) with + type not equals `total` and building numbers of the building attributes (main usage + and total floor area (in square meters)) with type `total` by doing a frequency + distribution in query Q with `T.total_building` and `S.sum_building` from the + joined queries S, T and updates the calculated target_number in the + `BuildingNumber` table. + + The query S computes the sum of building numbers grouped by district_id where + main usage is not `total` (i.e. main_usage_id != 0) and construction material is + `unknown` (i.e. construction_material_id = -1) and basement presence is `unknown` + (i.e. basement_presence_id = -1) and earthquake resistance code is `unknown` (i.e. + eq_resistance_code_presence_id = -1) and total floor area (in square meters) range is + not `total` (i.e. total_floor_area_id != 0). + + The query T selects the building numbers when main usage is `total` + (i.e. main_usage_id = 0) and construction material is `unknown` + (i.e. construction_material_id = -1) and basement presence is `unknown` + (i.e. basement_presence_id = -1) and earthquake resistance code is `unknown` (i.e. + eq_resistance_code_presence_id = -1) and total floor area (in square meters) range is + `total` (i.e. total_floor_area_id = 0). + """ + + sql_statement = """ + UPDATE BuildingNumber AS M + SET number_building = Q.target_number + FROM + ( + SELECT B.district_id, B.number_building, + S.sum_building, T.total_building, + B.number_building * T.total_building / S.sum_building AS target_number, + B.main_usage_id, B.construction_material_id, + B.basement_presence_id, B.eq_resistance_code_presence_id, + B.total_floor_area_id + FROM BuildingNumber AS B + INNER JOIN + ( + SELECT district_id, SUM(number_building) AS sum_building + FROM BuildingNumber + WHERE + ( + main_usage_id != 0 + AND construction_material_id = -1 + AND basement_presence_id = -1 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id != 0 + ) + GROUP BY district_id + ) AS S + ON B.district_id = S.district_id + INNER JOIN + ( + SELECT district_id, number_building AS total_building + FROM BuildingNumber + WHERE + ( + main_usage_id = 0 + AND construction_material_id = -1 + AND basement_presence_id = -1 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = 0 + ) + ) AS T + ON B.District_id = T.district_id + WHERE + ( + main_usage_id != 0 + AND construction_material_id = -1 + AND basement_presence_id = -1 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id != 0 + ) + ) AS Q + WHERE + ( + M.district_id = Q.district_id + AND M.main_usage_id = Q.main_usage_id + AND M.construction_material_id = Q.construction_material_id + AND M.basement_presence_id = Q.basement_presence_id + AND M.eq_resistance_code_presence_id = Q.eq_resistance_code_presence_id + AND M.total_floor_area_id = Q.total_floor_area_id + ) + """ + logger.debug(sql_statement) + self.cursor.execute(sql_statement) + self.connection.commit() + logger.info( + "Fixed rounding up errors for building numbers by their " + "main usage and total floor area (in square meters)" + ) + def import_exposure_data( self, building_numbers_main_usage_construction_material_city_filepath, @@ -937,6 +1030,10 @@ class CommercialAggregatedExposure(SpatialiteDatabase): # and earthquake resistance code and update the BuildingNumber table self.calculate_building_numbers_frequency_distributions_for_eq_resistance_code() + # Calculate the frequency distributions of number of buildings by their main usage + # and total floor area (in square meters) and update the BuildingNumber table + self.calculate_building_numbers_frequency_distributions_for_total_floor_area() + # Add the main usage types to the database for main_usage_id, main_usage in enumerate(main_usage_list): self.insert_main_usage(main_usage_id, main_usage)