diff --git a/exposurelib/database.py b/exposurelib/database.py index ca9bad8441c137c91ec8079af5d5bab72ffa5777..ed960d0d94935f7148601ef24a6e0bf2d1dcf0cb 100644 --- a/exposurelib/database.py +++ b/exposurelib/database.py @@ -60,6 +60,8 @@ class ExposureDatabase(SpatiaLiteDatabase): Assessment : Stores damage- and loss-assessment metadata Damage : Stores damage values DamageState : Stores damage-state names + BuildingLoss : Stores monetary loss values of buildings + HumanLoss : Stores number of fatalities AssessmentSource: Stores damage- and loss-assessment source names """ @@ -97,7 +99,7 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement += 'THEN RAISE(ABORT, "Error: row exists") END; ' sql_statement += "END;" self.connection.execute(sql_statement) - logger.debug("Table Entity created") + logger.debug("Table `Entity` created") # Create table Asset sql_statement = "CREATE TABLE Asset (" @@ -107,7 +109,7 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement += "structural REAL, " sql_statement += "night REAL)" self.connection.execute(sql_statement) - logger.debug("Table Asset created") + logger.debug("Table `Asset` created") # Create table Building sql_statement = "CREATE TABLE Building (" @@ -119,7 +121,7 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement = "SELECT AddGeometryColumn('Building', 'geom', 4326, " sql_statement += "'MULTIPOLYGON', 'XY')" self.connection.execute(sql_statement) - logger.debug("Table Building created") + logger.debug("Table `Building` created") # Create table Tile sql_statement = "CREATE TABLE Tile (" @@ -131,14 +133,14 @@ class ExposureDatabase(SpatiaLiteDatabase): self.connection.execute(sql_statement) sql_statement = "SELECT AddGeometryColumn('Tile', 'geom', 4326, 'MULTIPOLYGON', 'XY')" self.connection.execute(sql_statement) - logger.debug("Table Tile created") + logger.debug("Table `Tile` created") # Create table Taxonomy sql_statement = "CREATE TABLE Taxonomy (" sql_statement += "id INTEGER PRIMARY KEY AUTOINCREMENT, " sql_statement += "taxonomy_string TEXT)" self.connection.execute(sql_statement) - logger.debug("Table Taxonomy created") + logger.debug("Table `Taxonomy` created") # Create table Assessment sql_statement = "CREATE TABLE Assessment (" @@ -148,7 +150,7 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement += "date INTEGER, " sql_statement += "comment TEXT)" self.connection.execute(sql_statement) - logger.debug("Table Assessment created") + logger.debug("Table `Assessment` created") # Create table Damage sql_statement = "CREATE TABLE Damage (" @@ -156,7 +158,7 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement += "damage_state_id INTEGER, " sql_statement += "damage_probability REAL)" self.connection.execute(sql_statement) - logger.debug("Table Damage created") + logger.debug("Table `Damage` created") # Create table DamageState sql_statement = "CREATE TABLE DamageState (" @@ -165,7 +167,21 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement += "damage_state_name TEXT, " sql_statement += "UNIQUE(damage_scale_name, damage_state_name))" self.connection.execute(sql_statement) - logger.debug("Table DamageState created") + logger.debug("Table `DamageState` created") + + # Create table BuildingLoss + sql_statement = "CREATE TABLE BuildingLoss (" + sql_statement += "assessment_id INTEGER, " + sql_statement += "loss_structural REAL) " + self.connection.execute(sql_statement) + logger.debug("Table `BuildingLoss` created") + + # Create table HumanLoss + sql_statement = "CREATE TABLE HumanLoss (" + sql_statement += "assessment_id INTEGER, " + sql_statement += "fatality_night REAL)" + self.connection.execute(sql_statement) + logger.debug("Table `HumanLoss` created") # Create table AssessmentSource sql_statement = "CREATE TABLE AssessmentSource (" @@ -175,7 +191,7 @@ class ExposureDatabase(SpatiaLiteDatabase): sql_statement += "comment TEXT, " sql_statement += "UNIQUE(name))" self.connection.execute(sql_statement) - logger.debug("Table AssessmentSource created") + logger.debug("Table `AssessmentSource` created") def create_damage_view( self, view_name, entity, assessment_source_id, damage_state_id=None, overwrite=True @@ -691,7 +707,7 @@ class ExposureDatabase(SpatiaLiteDatabase): Args: assessment_id (int): - ID of the damage or loss assessment (corresponds to `Assessment.id`) + ID of the damage assessment (corresponds to `Assessment.id`) damage_state_id (int): ID of the damage state(corresponds to `DamageState.id`) damage_probability (float): @@ -752,12 +768,44 @@ class ExposureDatabase(SpatiaLiteDatabase): result = self.cursor.fetchone() if not result: logger.debug( - "Dataset for %s, %s in DamageState does not exist" + "Dataset for %s, %s in `DamageState` does not exist" % (damage_scale_name, damage_state_name) ) return None return result[0] + def insert_building_loss(self, assessment_id, loss_structural): + """ + Inserts building-related loss values into the `BuildingLoss` table. + + Args: + assessment_id (int): + ID of the loss assessment (corresponding to `Assessment.id`) + loss_structural (float): + The monetary structural loss value + """ + + sql_statement = "INSERT INTO BuildingLoss " + sql_statement += "(assessment_id, loss_structural) " + sql_statement += "VALUES (%d, %f)" % (assessment_id, loss_structural) + self.cursor.execute(sql_statement) + + def insert_human_loss(self, assessment_id, fatality_night): + """ + Inserts human-related loss values into the `HumanLoss` table. + + Args: + assessment_id (int): + ID of the loss assessment (corresponding to `Assessment.id`) + fatality_night (float): + Number of fatalities at night + """ + + sql_statement = "INSERT INTO HumanLoss " + sql_statement += "(assessment_id, fatality_night) " + sql_statement += "VALUES (%d, %f)" % (assessment_id, fatality_night) + self.cursor.execute(sql_statement) + def insert_assessment_source(self, name, method, comment=""): """ Inserts a damage- or loss-assessment source into the `AssessmentSource` table. @@ -799,7 +847,7 @@ class ExposureDatabase(SpatiaLiteDatabase): self.cursor.execute(sql_statement) result = self.cursor.fetchone() if not result: - logger.debug("Dataset for %s in AssessmentSource does not exist" % name) + logger.debug("Dataset for %s in `AssessmentSource` does not exist" % name) return None return result[0] @@ -834,6 +882,56 @@ class ExposureDatabase(SpatiaLiteDatabase): for idx, damage in enumerate(damage_values): self.insert_damage(assessment_id, damage_ids[idx], damage) + def insert_complete_building_loss_assessment( + self, entity_id, assessment_source_id, loss_structural, date=None, comment="" + ): + """ + Inserts a complete loss assessment into the database. It creates the entry in + `Assessment` and all entries in `BuildingLoss` table. + + Args: + entity_id (int): + ID of the entity + assessment_source_id (int): + ID of the assessment source + loss_structural (float): + The monetary structural loss value + date (int): + Unix timestamp (seconds since 1970-01-01 00:00:00 UTC) of the assessment + comment (str): + Optional comment + """ + + assessment_id = self.insert_assessment( + entity_id, assessment_source_id, date=date, comment=comment + ) + self.insert_building_loss(assessment_id, loss_structural) + + def insert_complete_human_loss_assessment( + self, entity_id, assessment_source_id, fatality_night, date=None, comment="" + ): + """ + Inserts a complete loss assessment into the database. It creates the entry in + `Assessment` and all entries in `HumanLoss` table. + + Args: + entity_id (int): + ID of the entity + assessment_source_id (int): + ID of the assessment source + fatality_night (float): + Number of fatalities at night + date (int): + Unix timestamp (seconds since 1970-01-01 00:00:00 UTC) of the assessment + comment (str): + Optional comment + """ + + assessment_id = self.insert_assessment( + entity_id, assessment_source_id, date=date, comment=comment + ) + self.insert_human_loss(assessment_id, fatality_night) + def get_quadkey_and_geom(self, osm_id): """ Retrieves the `quadkey` and geometry of a building with `osm_id`