From a612a6c4bfe309bf61f86f4f1026f19823165b00 Mon Sep 17 00:00:00 2001 From: Danijel Schorlemmer <ds@gfz-potsdam.de> Date: Mon, 20 Jun 2022 15:56:58 +0200 Subject: [PATCH] Implement the export function with optional bounding box parameter --- exposurelib/database.py | 123 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/exposurelib/database.py b/exposurelib/database.py index 168e7974..2b2176b8 100644 --- a/exposurelib/database.py +++ b/exposurelib/database.py @@ -21,6 +21,8 @@ import sqlite3 import datetime import csv import glob +import shutil +import os.path from exposurelib.utils import get_geom_of_quadkey from shapely.geometry import box from pygeotile.tile import Tile @@ -394,6 +396,127 @@ class ExposureDatabase(SpatialiteDatabase): self.connection.execute(sql_statement) logger.debug("View %s deleted" % name) + def export(self, export_filepath, bounding_box=None, overwrite=False): + """ + Exports the current database by copying it to the `export_filepath` location. + If a bounding box is given, all entities outside the bounding box including dependent + data values are removed and the database is compacted to save space. + + Args: + export_filepath (str): + Filepath to export the database to. + bounding_box (dictionary, optional): + Dictionary containing the bounding-box coordinates as entries `lon_min`, + `lon_max`, `lat_min`, `lat_max`. + overwrite (boolean, optional): + Flag to allow for overwriting an existing file during export. + """ + + # Checks if writing is possible + if self.database_filepath == export_filepath: + raise FileExistsError("Cannot export database to iself. Exiting ...") + if os.path.exists(export_filepath) and not overwrite: + raise FileExistsError("File %s exists. Exiting ..." % export_filepath) + # Copy current database to new location + shutil.copyfile(self.database_filepath, export_filepath) + if bounding_box is None: + return + + # Open the export database + try: + export_db = ExposureDatabase(export_filepath, self.spatialite_filepath) + export_db.connect(init_spatial_metadata=False) + except Exception: + raise ValueError( + "Exposure database %s cannot be created. Exiting ..." % export_filepath + ) + + # Remove the entities and related datasets outside the bounding box + logger.debug("Removing entities outside of bounding box") + sql_statement = "DELETE FROM Entity " + sql_statement += "WHERE NOT MBRContains(BuildMBR(%f, %f, %f, %f), geom)" % ( + bounding_box["lon_min"], + bounding_box["lat_min"], + bounding_box["lon_max"], + bounding_box["lat_max"], + ) + export_db.cursor.execute(sql_statement) + + logger.debug("Removing tiles outside of bounding box") + sql_statement = """ + DELETE FROM Tile + WHERE quadkey IN + ( + SELECT Tile.quadkey FROM Tile + LEFT JOIN Entity ON Tile.quadkey = Entity.quadkey + WHERE Entity.id IS NULL + ) + """ + export_db.cursor.execute(sql_statement) + + logger.debug("Removing buildings outside of bounding box") + sql_statement = """ + DELETE FROM Building + WHERE osm_id IN + ( + SELECT Building.osm_id FROM Building + LEFT JOIN Entity ON Building.osm_id = Entity.osm_id + WHERE Entity.id IS NULL + ) + """ + export_db.cursor.execute(sql_statement) + + logger.debug("Removing assets outside of bounding box") + sql_statement = """ + DELETE FROM Asset + WHERE entity_id IN + ( + SELECT entity_id FROM Asset + LEFT JOIN Entity ON Asset.entity_id = Entity.id + WHERE Entity.id IS NULL + ) + """ + export_db.cursor.execute(sql_statement) + + logger.debug("Removing unused taxonomy strings") + sql_statement = """ + DELETE FROM Taxonomy + WHERE id IN + ( + SELECT id FROM Taxonomy + LEFT JOIN Asset ON Asset.taxonomy_id = Taxonomy.id + WHERE Asset.taxonomy_id IS NULL + ) + """ + export_db.cursor.execute(sql_statement) + + logger.debug("Removing unused damage assessments") + sql_statement = """ + DELETE FROM DamageAssessment + WHERE entity_id IN + ( + SELECT entity_id FROM DamageAssessment + LEFT JOIN Entity ON DamageAssessment.entity_id = Entity.id + WHERE Entity_id IS NULL + ) + """ + export_db.cursor.execute(sql_statement) + sql_statement = """ + DELETE FROM Damage + WHERE assessment_id IN + ( + SELECT assessment_id FROM Damage + LEFT JOIN DamageAssessment ON DamageAssessment.id = Damage.assessment_id + WHERE DamageAssessment.id IS NULL + ) + """ + export_db.cursor.execute(sql_statement) + + export_db.connection.commit() + logger.debug("Reducing database size") + export_db.connection.execute("VACUUM") + export_db.close() + def insert_tile_entity(self, quadkey): """ Inserts a tile and its geometry to the `Entity` table. A database trigger checks if the -- GitLab