diff --git a/exposurejapan/commercial.py b/exposurejapan/commercial.py index 17a1f91229560e5daf7d40a70840eaff025ee724..c3e394a83fa9e327a50a43636d220be085363dcb 100644 --- a/exposurejapan/commercial.py +++ b/exposurejapan/commercial.py @@ -496,7 +496,7 @@ class CommercialAggregatedExposure(SpatialiteDatabase): district_id = district_id_result[0] # Get ID of main usage - main_usage_id = add_element_and_get_index(row["main_usage"], main_usage_list) + main_usage_id = add_element_and_get_index(row["main_usage_status"], main_usage_list) # Get ID of construction material if row["construction_material"] == "Unknown": @@ -554,6 +554,101 @@ class CommercialAggregatedExposure(SpatialiteDatabase): self.connection.commit() logger.info("Building numbers added") + def calculate_building_numbers_frequency_distributions_for_construction_material(self): + """ + Fixes rounding-up errors observed between the sum of building numbers of the + building attributes (main usage and construction material) with type not equals + `total` and building numbers of the building attributes (main usage and + construction material) 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 + not `total` (i.e. construction_material_id != 0) and basement presence is `total` + (i.e. basement_presence_id = 0) and earthquake resistance code is `total` (i.e. + eq_resistance_code_presence_id = 0) and total floor area (in square meters) range is + `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 `total` + (i.e. construction_material_id = 0) and basement presence is `total` + (i.e. basement_presence_id = 0) and earthquake resistance code is `total` (i.e. + eq_resistance_code_presence_id = 0) 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 != 0 + AND basement_presence_id = 0 + AND eq_resistance_code_presence_id = 0 + 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 = 0 + AND basement_presence_id = 0 + AND eq_resistance_code_presence_id = 0 + AND total_floor_area_id = 0 + ) + ) AS T + ON B.District_id = T.district_id + WHERE + ( + main_usage_id != 0 + AND construction_material_id != 0 + AND basement_presence_id = 0 + AND eq_resistance_code_presence_id = 0 + 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.basement_presence_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 construction material" + ) + def import_exposure_data( self, building_numbers_main_usage_construction_material_city_filepath, @@ -646,6 +741,10 @@ class CommercialAggregatedExposure(SpatialiteDatabase): total_floor_area_list, ) + # Calculate the frequency distributions of number of buildings by their main usage + # and construction material and update the BuildingNumber table + self.calculate_building_numbers_frequency_distributions_for_construction_material() + # 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)