diff --git a/exposurejapan/commercial.py b/exposurejapan/commercial.py index f6ee85f8740a7242276260619d2ff829f6bef407..c2feb4a05d7bc4da2d991199893be0adff78c08f 100644 --- a/exposurejapan/commercial.py +++ b/exposurejapan/commercial.py @@ -566,17 +566,17 @@ class CommercialAggregatedExposure(SpatialiteDatabase): 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). + not `total` (i.e. construction_material_id != 0) 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 + `unknown` (i.e. total_floor_area_id = -1). 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). + (i.e. construction_material_id = 0) 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 + `unknown` (i.e. total_floor_area_id = -1). """ sql_statement = """ @@ -593,32 +593,30 @@ class CommercialAggregatedExposure(SpatialiteDatabase): FROM BuildingNumber AS B INNER JOIN ( - SELECT district_id, - SUM(number_building) AS sum_building + 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 + AND basement_presence_id = -1 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = -1 ) GROUP BY district_id ) AS S ON B.district_id = S.district_id INNER JOIN ( - SELECT district_id, - number_building AS total_building + 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 + AND basement_presence_id = -1 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = -1 ) ) AS T ON B.District_id = T.district_id @@ -626,9 +624,9 @@ class CommercialAggregatedExposure(SpatialiteDatabase): ( 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 + AND basement_presence_id = -1 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = -1 ) ) AS Q WHERE @@ -649,6 +647,99 @@ class CommercialAggregatedExposure(SpatialiteDatabase): "main usage and construction material" ) + def calculate_building_numbers_frequency_distributions_for_basement_presence(self): + """ + Fixes rounding-up errors observed between the sum of building numbers of the + 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 + 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 not `total` + (i.e. basement_presence_id != 0) and earthquake resistance code is `unknown` (i.e. + eq_resistance_code_presence_id = -1) and total floor area (in square meters) range is + `unknown` (i.e. total_floor_area_id = -1). + + 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 `total` + (i.e. basement_presence_id = 0) and earthquake resistance code is `unknown` (i.e. + eq_resistance_code_presence_id = -1) and total floor area (in square meters) range is + `unknown` (i.e. total_floor_area_id = -1). + """ + + 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 != 0 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = -1 + ) + 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 = 0 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = -1 + ) + ) AS T + ON B.District_id = T.district_id + WHERE + ( + main_usage_id != 0 + AND construction_material_id = -1 + AND basement_presence_id != 0 + AND eq_resistance_code_presence_id = -1 + AND total_floor_area_id = -1 + ) + ) 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 basement presence" + ) + def import_exposure_data( self, building_numbers_main_usage_construction_material_city_filepath, @@ -745,6 +836,10 @@ class CommercialAggregatedExposure(SpatialiteDatabase): # and construction material and update the BuildingNumber table self.calculate_building_numbers_frequency_distributions_for_construction_material() + # Calculate the frequency distributions of number of buildings by their main usage + # and basement presence and update the BuildingNumber table + self.calculate_building_numbers_frequency_distributions_for_basement_presence() + # 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)