def require_input(self): """Ensure input files are entered in dialog exist. :raises: ImportDialogError - when one or all of the input files are empty """ database_name = self.database.text() host_name = self.host.text() port_number = self.port.text() user_name = self.user_name.text() password = self.password.text() network_table = self.network_table.text() catchment_table = self.catchment_table.text() contour_interval = self.contour_interval.text() if database_name and host_name and port_number and \ user_name and password and network_table and \ catchment_table: return display_warning_message_box( self, self.tr('Error'), self.tr('Input cannot be empty.')) raise ImportDialogError()
def clear_network_cache(connection, cursor, arguments, dialog): """Clear a network cache if exists :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: sql = """DROP VIEW IF EXISTS network_cache""" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box( dialog, "Error", "Error in clearing network view")
def clear_network_cache(connection, cursor, arguments, dialog): """Clear a network cache if exists :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: sql = """DROP VIEW IF EXISTS network_cache""" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box(dialog, "Error", "Error in clearing network view")
def create_routable_network(connection, cursor, arguments, dialog): """Create routable network using the network view with the nodes. This takes long time to complete. :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: sql = """CREATE TABLE IF NOT EXISTS routable_network AS SELECT a.*, b.id as start_id, c.id as end_id FROM network_cache AS a JOIN nodes AS b ON a.pgr_startpoint = b.the_geom JOIN nodes AS c ON a.pgr_endpoint = c.the_geom """ sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box(dialog, "Error", "Error in creating routable network")
def create_network_view(connection, cursor, arguments, dialog): """Create network view, to improve performance of queries using it :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ clear_network_cache(connection, cursor, arguments, dialog) try: sql = """ CREATE OR REPLACE VIEW network_cache as SELECT *, pgr_startpoint(%(network_geom)s), pgr_endpoint(%(network_geom)s) FROM %(network_table)s """ % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box(dialog, "Error", "Error in creating network view")
def prepare_drivetimes_table(connection, cursor, arguments, dialog): """ :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog :param progress_percentage: the percentage of progress bar :type progress_percentage: int """ try: sql = """ DROP TABLE IF EXISTS catchment_final""" sql = clean_query(sql) cursor.execute(sql) connection.commit() sql = """ CREATE TABLE IF NOT EXISTS catchment_final AS SELECT id, the_geom, min (cost) AS %s FROM catchment_with_cost GROUP By id, the_geom """ % "drivetime" sql = clean_query(sql) cursor.execute(sql) connection.commit() sql = """DROP TABLE IF EXISTS catchment_final_no_null""" sql = clean_query(sql) cursor.execute(sql) connection.commit() sql = """ CREATE TABLE catchment_final_no_null AS SELECT *, (drivetime * 60) AS minutes FROM catchment_final WHERE %s IS NOT NULL """ % "drivetime" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box(dialog, "Error", "Error in preparing drivetimes table")
def create_routable_network(connection, cursor, arguments, dialog): """Create routable network using the network view with the nodes. This takes long time to complete. :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: sql = """CREATE TABLE IF NOT EXISTS routable_network AS SELECT a.*, b.id as start_id, c.id as end_id FROM network_cache AS a JOIN nodes AS b ON a.pgr_startpoint = b.the_geom JOIN nodes AS c ON a.pgr_endpoint = c.the_geom """ sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box( dialog, "Error", "Error in creating routable network")
def create_network_view(connection, cursor, arguments, dialog): """Create network view, to improve performance of queries using it :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ clear_network_cache(connection, cursor, arguments, dialog) try: sql = """ CREATE OR REPLACE VIEW network_cache as SELECT *, pgr_startpoint(%(network_geom)s), pgr_endpoint(%(network_geom)s) FROM %(network_table)s """ % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box( dialog, "Error", "Error in creating network view")
def load_isochrone_map(self, base_path): """Load the isochrone map in the qgis :param base_path: Output path where layers are :type base_path:str """ if not os.path.exists(base_path): message = self.tr("Error, failed to load the isochrone map") raise FileMissingError(message) else: for layer in os.listdir(base_path): layer_name = QFileInfo(layer).baseName if file.endswith(".asc"): self.iface.addRasterLayer(file, layer_name) continue elif file.endswith(".shp"): self.iface.addVectorLayer(file, layer_name, 'ogr') continue else: continue canvas_srid = self.canvas.mapRenderer().destinationCrs().srsid() on_the_fly_projection = self.canvas.hasCrsTransformEnabled() if canvas_srid != 4326 and not on_the_fly_projection: if Qgis.QGIS_VERSION_INT >= 20400: self.canvas.setCrsTransformEnabled(True) else: display_warning_message_box( self.iface, self.tr('Enable \'on the fly\''), self.tr( 'Your current projection is different than EPSG:4326.' 'You should enable \'on the fly\' to display ' 'correctly the isochrone map'))
def accept(self): """Create an isochrone map and display it in QGIS.""" error_dialog_title = self.tr("Error") try: self.save_state() self.require_input() database_name = self.database.text() host_name = self.host.text() port_number = self.port.text() user_name = self.user_name.text() password = self.password.text() network_table = self.network_table.text() network_geom = self.network_geom_column.text() network_id_column = self.network_id_column.text() catchment_geom = self.catchment_geom_column.text() catchment_table = self.catchment_table.text() catchment_id_column = self.catchment_id_column.text() contour_interval = self.contour_interval.text() if self.style.isChecked(): style_checked = True else: style_checked = False isochrone( database_name, host_name, port_number, user_name, password, network_table, network_geom, network_id_column, catchment_table, catchment_geom, catchment_id_column, style_checked, contour_interval, self, self.progress_dialog) self.done(QDialog.Accepted) except ImportDialogError as exception: display_warning_message_box( self, error_dialog_title, exception.message) pass except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box( self, error_dialog_title, exception.message) pass finally: dialog_title = self.tr("Success")
def update_catchment(connection, cursor, arguments, dialog): """Calculating the nearest nodes to the catchment areas, these nodes will be used in accessibility calculations. :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: update_catchment_table(connection, cursor, arguments, dialog) sql = """ALTER TABLE %(catchment_table)s ADD COLUMN the_nearest_node integer; CREATE TABLE IF NOT EXISTS temp AS SELECT a.gid, b.id, min(a.dist) FROM (SELECT %(catchment_table)s.%(catchment_id)s as gid, min(st_distance( %(catchment_table)s.%(catchment_geom)s, nodes.the_geom)) AS dist FROM %(catchment_table)s, nodes GROUP BY %(catchment_table)s.%(catchment_id)s) AS a, (SELECT %(catchment_table)s.%(catchment_id)s as gid, nodes.id, st_distance( %(catchment_table)s.%(catchment_geom)s, nodes.the_geom) AS dist FROM %(catchment_table)s, nodes) AS b WHERE a.dist = b. dist AND a.gid = b.gid GROUP BY a.gid, b.id; """ % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() populate_catchment_table(connection, cursor, arguments, dialog) except Exception as exception: display_warning_message_box(dialog, "Error", "Error in updating catchment table")
def generate_drivetimes_contour(raster_layer, interval, parent_dialog): """Create drive times contour :param raster_layer: Interpolated raster layer with drivetimes :type raster_layer: QgsRasterLayer :param interval: drivetimes interval :type interval: int :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :returns layer: Vector layer with contour drivetimes :rtype layer: QgsVectorLayer """ drivetime_layer = None try: Processing.initialize() Processing.updateAlgsList() output_vector = processing.runalg( 'gdalogr:contour', raster_layer, interval, 'minutes', None, '[temporary_file]') drivetime_layer = QgsVectorLayer( output_vector['OUTPUT_VECTOR'], 'time(min)', 'ogr') except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ') return drivetime_layer
def update_catchment(connection, cursor, arguments, dialog): """Calculating the nearest nodes to the catchment areas, these nodes will be used in accessibility calculations. :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: update_catchment_table(connection, cursor, arguments, dialog) sql = """ALTER TABLE %(catchment_table)s ADD COLUMN the_nearest_node integer; CREATE TABLE IF NOT EXISTS temp AS SELECT a.gid, b.id, min(a.dist) FROM (SELECT %(catchment_table)s.%(catchment_id)s as gid, min(st_distance( %(catchment_table)s.%(catchment_geom)s, nodes.the_geom)) AS dist FROM %(catchment_table)s, nodes GROUP BY %(catchment_table)s.%(catchment_id)s) AS a, (SELECT %(catchment_table)s.%(catchment_id)s as gid, nodes.id, st_distance( %(catchment_table)s.%(catchment_geom)s, nodes.the_geom) AS dist FROM %(catchment_table)s, nodes) AS b WHERE a.dist = b. dist AND a.gid = b.gid GROUP BY a.gid, b.id; """ % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() populate_catchment_table(connection, cursor, arguments, dialog) except Exception as exception: display_warning_message_box( dialog, "Error", "Error in updating catchment table")
def create_network_view( connection, cursor, arguments, dialog, progress_dialog): """Create network view, to improve performance of queries using it :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog :param progress_dialog: Progress dialog :type progress_dialog: Qdialog """ progress_dialog.setValue(0) label_text = tr("Creating network view table") progress_dialog.setLabelText(label_text) drop_network_cache(connection, cursor, arguments, dialog) try: sql = """ CREATE OR REPLACE VIEW network_cache as SELECT *, pgr_startpoint(%(network_geom)s), pgr_endpoint(%(network_geom)s) FROM %(network_table)s """ % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: message = "Error in creating network view \n {}". \ format(str(exception)) display_warning_message_box( dialog, "Error", message ) raise IsochroneDBError
def create_nodes(connection, cursor, arguments, dialog): """Create network nodes, this will help in creating a sql routable network table :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: drop_table(connection, cursor, "nodes") sql = """CREATE TABLE IF NOT EXISTS nodes AS SELECT row_number() OVER (ORDER BY foo.p)::integer AS id, foo.p AS the_geom FROM ( SELECT DISTINCT network_cache.pgr_startpoint AS p FROM network_cache UNION SELECT DISTINCT network_cache.pgr_endpoint AS p FROM network_cache ) foo GROUP BY foo.p""" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: message = "Error in creating network nodes \n {}". \ format(str(exception)) display_warning_message_box( dialog, "Error", message ) raise IsochroneDBError
def generate_drivetimes_contour(raster_layer, interval, parent_dialog): """Create drive times contour :param raster_layer: Interpolated raster layer with drivetimes :type raster_layer: QgsRasterLayer :param interval: drivetimes interval :type interval: int :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :returns layer: Vector layer with contour drivetimes :rtype layer: QgsVectorLayer """ drivetime_layer = None try: Processing.initialize() Processing.updateAlgsList() output_vector = processing.runalg('gdalogr:contour', raster_layer, interval, 'minutes', None, '[temporary_file]') drivetime_layer = QgsVectorLayer(output_vector['OUTPUT_VECTOR'], 'time(min)', 'ogr') except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr('Error'), parent_dialog.tr('Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ') return drivetime_layer
def create_nodes(connection, cursor, arguments, dialog): """Create network nodes, this will help in creating a sql routable network table :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog """ try: sql = """CREATE TABLE IF NOT EXISTS nodes AS SELECT row_number() OVER (ORDER BY foo.p)::integer AS id, foo.p AS the_geom FROM ( SELECT DISTINCT network_cache.pgr_startpoint AS p FROM network_cache UNION SELECT DISTINCT network_cache.pgr_endpoint AS p FROM network_cache ) foo GROUP BY foo.p""" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box( dialog, "Error", "Error in creating network nodes")
def load_isochrone_map(self, base_path): """Load the isochrone map in the qgis :param base_path: Output path where layers are :type base_path:str """ if not os.path.exists(base_path): message = self.tr("Error, failed to load the isochrone map") raise FileMissingError(message) else: for layer in os.listdir(base_path): layer_name = QFileInfo(layer).baseName if file.endswith(".asc"): self.iface.addRasterLayer(file, layer_name) continue elif file.endswith(".shp"): self.iface.addVectorLayer(file, layer_name, 'ogr') continue else: continue canvas_srid = self.canvas.mapRenderer().destinationCrs().srsid() on_the_fly_projection = self.canvas.hasCrsTransformEnabled() if canvas_srid != 4326 and not on_the_fly_projection: if QGis.QGIS_VERSION_INT >= 20400: self.canvas.setCrsTransformEnabled(True) else: display_warning_message_box( self.iface, self.tr('Enable \'on the fly\''), self.tr( 'Your current projection is different than EPSG:4326.' 'You should enable \'on the fly\' to display ' 'correctly the isochrone map') )
def prepare_map_style( uri, progress_percentage, contour_interval, progress_dialog, temp_layer, parent_dialog, args): """Prepare map style if user requested for it :param uri: Identifier for the final layer table :type uri: QgsDataSourceUri :param progress_percentage: Progress percentage. :type progress_percentage: int :param contour_interval: Drivetime interval. :type contour_interval: int :param progress_dialog: Dialog for progress. :type progress_dialog: QDialog :param temp_layer: Temporary result layer. :type temp_layer: QgsVectorLayer :param parent_dialog: Isochrone parent dialog. :type parent_dialog: QDialog :param args: Database tables arguments :type args: {} """ progress_percentage += 1 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Exporting and preparing isochrone map") progress_dialog.setLabelText(label_text) if progress_dialog.wasCanceled(): return # TODO implement style creation logic # Run interpolation on the final file (currently using IDW) raster_file = idw_interpolation(temp_layer, parent_dialog) # Generate drivetimes contour try: drivetime_layer = generate_drivetimes_contour( raster_file, contour_interval, parent_dialog) # Load all the required layers load_map_layers(uri, parent_dialog, drivetime_layer, args) except Exception as exception: message = 'Error generating drivetimes \n {}'. \ format(str(exception)) display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr( message ) ) raise IsochroneMapStyleError progress_percentage += 4 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Done, loading isochrone map") progress_dialog.setLabelText(label_text) if progress_dialog.wasCanceled(): return
def calculate_drivetimes( connection, cursor, arguments, dialog, progress_percentage): """ :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog :param progress_percentage: the percentage of progress bar :type progress_percentage: int :returns Progress percentage :rtype int """ index = 0 try: rows = query_nearest_nodes(connection, cursor, arguments, dialog) # Convert unique column to integer as required by # the pgr_dijkstra function sql = """ALTER TABLE routable_network ALTER COLUMN %(network_id)s SET DATA TYPE int4""" % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() for row in rows: # This step is 45% of all steps so calculating # percentage of each increment accordingly percentage = ((index + 1) / len(rows)) * 45 percentage = round(percentage, 0) catchment_id = row[0] arguments["catchment_current_id"] = catchment_id if index == 0: sql = """ CREATE TABLE IF NOT EXISTS catchment_with_cost AS SELECT id, the_geom, (SELECT sum(cost) FROM ( SELECT * FROM pgr_dijkstra(' SELECT %(network_id)s AS id, start_id::int4 AS source, end_id::int4 AS target, cost::float8 AS cost FROM routable_network', %(catchment_current_id)s, id, false, false)) AS foo ) AS cost FROM nodes;""" % arguments sql = clean_query(sql) cursor.execute(sql) else: sql = """ INSERT INTO catchment_with_cost ( SELECT id, the_geom, (SELECT sum(cost) FROM ( SELECT * FROM pgr_dijkstra(' SELECT %(network_id)s AS id, start_id::int4 AS source, end_id::int4 AS target, cost::float8 AS cost FROM routable_network', %(catchment_current_id)s, id, false, false)) AS foo ) AS cost FROM nodes);""" % arguments sql = clean_query(sql) cursor.execute(sql) index += 1 connection.commit() progress_percentage += percentage if dialog: dialog.setValue(progress_percentage) label_text = tr( str(index) + " catchment area(s) out of " + str(len(rows)) + " is(are) done") dialog.setLabelText(label_text) if dialog: label_text = tr("Preparing all the catchment areas table") dialog.setLabelText(label_text) except Exception as exception: display_warning_message_box( dialog, "Error", "Error in calculating drivetimes") return progress_percentage
def idw_interpolation(layer, parent_dialog): """Run interpolation using inverse distance weight algorithm :param layer: Vector layer with drivetimes :type layer: QgsVectorLayer :param parent_dialog: A dialog for showing progress. :type parent_dialog: QProgressDialog :returns raster_layer: Interpolated raster layer with drivetimes :rtype raster_layer: QgsRasterLayer """ raster_layer = None try: Processing.initialize() # Create temporary file temp_output_file = tempfile.NamedTemporaryFile() temp_output_file_path = temp_output_file.name + '.tif' saved_layer = save_layer(layer) params = {'INPUT': saved_layer.dataProvider().dataSourceUri(), 'Z_FIELD': 'minutes', 'POWER': 2, 'SMOOTHING': 0, 'RADIUS_1': 0, 'RADIUS_2': 0, 'ANGLE': 0, 'MAX_POINTS': 0, 'MIN_POINTS': 0, 'NODATA': 0, 'DATA_TYPE': 5, 'OUTPUT': temp_output_file_path } output_raster = processing.run( 'gdal:gridinversedistance', params ) output_file = output_raster['OUTPUT'] # retrieving the raster output , styling it and load it in Qgis raster_layer = QgsRasterLayer(output_file, 'styled map') raster_layer = style_raster_layer(raster_layer, parent_dialog) QgsProject.instance().addMapLayer(raster_layer) # TODO use stored static style instead of dynamic one?? # map_style = resources_path( # 'styles', # 'qgis', # 'map.qml') # raster_layer.loadNamedStyle(map_style) # # raster_layer.triggerRepaint() except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList if parent_dialog: message = 'Error loading isochrone map,'\ 'please check if you have processing '\ 'plugin installed \n'.\ format(str(exception)) display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr(message)) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ') raise IsochroneMapStyleError return raster_layer
def style_raster_layer(raster_layer, parent_dialog): """Style interpolated raster layer :param raster_layer: Interpolated raster layer :type raster_layer: QgsRasterLayer :param parent_dialog: A dialog for showing progress. :type parent_dialog: QProgressDialog :returns raster_layer: Styled interpolated raster layer :rtype raster_layer: QgsRasterLayer """ if raster_layer: if raster_layer.isValid(): color_shader = QgsColorRampShader() color_shader.setColorRampType(QgsColorRampShader.Interpolated) colors = { 'deep_green': '#1a9641', 'light_green': '#a6d96a', 'pale_yellow': '#ffffc0', 'light_red': '#fdae61', 'red': '#d7191c' } provider = raster_layer.dataProvider() stats = provider.bandStatistics( 1, QgsRasterBandStats.All, raster_layer.extent(), 0) values = {} if stats: min = stats.minimumValue max = stats.maximumValue stat_range = max - min add = stat_range / 4 values[0] = min value = min for index in range(1, 4): value += add values[index] = value values[4] = max else: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error loading isochrone map' ' Problem indexing the isochrones map')) color_list = [ QgsColorRampShader.ColorRampItem( values[0], QColor(colors['deep_green'])), QgsColorRampShader.ColorRampItem( values[1], QColor(colors['light_green'])), QgsColorRampShader.ColorRampItem( values[2], QColor(colors['pale_yellow'])), QgsColorRampShader.ColorRampItem( values[3], QColor(colors['light_red'])), QgsColorRampShader.ColorRampItem( values[4], QColor(colors['red'])) ] color_shader.setColorRampItemList(color_list) raster_shader = QgsRasterShader() raster_shader.setRasterShaderFunction(color_shader) renderer = QgsSingleBandPseudoColorRenderer( raster_layer.dataProvider(), 1, raster_shader) raster_layer.setRenderer(renderer) raster_layer.triggerRepaint() else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Problem'), parent_dialog.tr('Problem styling the isochrone map')) else: display_warning_message_box( parent_dialog, 'Problem', 'Problem styling the isochrone map') else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error loading isochrone map ' 'Could not load interpolated file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load interpolated file!') return raster_layer
def generate_drivetimes_contour(raster_layer, interval, parent_dialog): """Create drive times contour :param raster_layer: Interpolated raster layer with drivetimes :type raster_layer: QgsRasterLayer :param interval: drivetimes interval :type interval: int :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :returns layer: Vector layer with contour drivetimes :rtype layer: QgsVectorLayer """ drivetime_layer = None try: Processing.initialize() temp_output_file = tempfile.NamedTemporaryFile() temp_output_file_path = temp_output_file.name + '.shp' params = { 'INPUT': raster_layer, 'INTERVAL': interval, 'FIELD_NAME': 'minutes', 'CREATE_3D': False, 'IGNORE_NODATA': False, 'NODATA': 0, 'BAND': 1, 'OUTPUT': temp_output_file_path } output_vector = processing.run( 'gdal:contour', params ) drivetime_layer = QgsVectorLayer( output_vector['OUTPUT'], 'time(min)', 'ogr') except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList if parent_dialog: message = 'Error loading isochrone map,' \ 'please check if you have processing ' \ 'plugin installed \n'. \ format(str(exception)) display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr(message)) else: message = 'Error loading isochrone map,'\ 'please check if you have processing '\ 'plugin installed \n'.\ format(str(exception)) display_warning_message_box( parent_dialog, 'Error', message) raise IsochroneMapStyleError return drivetime_layer
def prepare_drivetimes_table(connection, cursor, arguments, dialog): """ :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog :param progress_percentage: the percentage of progress bar :type progress_percentage: int """ try: drop_table(connection, cursor, "catchment_final") sql = """ CREATE TABLE IF NOT EXISTS catchment_final AS SELECT id, the_geom, min (cost) AS %s FROM catchment_with_cost GROUP By id, the_geom """ % "drivetime" sql = clean_query(sql) cursor.execute(sql) connection.commit() # drop_table(connection, cursor, "catchment_final_mid") # TODO find best approach of getting max_hours # use these hours incase catchment is unreachable # maximum_time = max_drivetime( # connection, # cursor) # # max_hours = maximum_time + maximum_time * 0.05 # # sql = """ CREATE TABLE catchment_final_mid AS # SELECT *, coalesce(drivetime, %f) as valid_drivetime # FROM catchment_final # """ % max_hours # sql = clean_query(sql) # cursor.execute(sql) # connection.commit() drop_table(connection, cursor, "catchment_final_no_null") sql = """ CREATE TABLE catchment_final_no_null AS SELECT *, (drivetime * 60) AS minutes FROM catchment_final WHERE %s IS NOT NULL """ % "drivetime" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: message = "Error in preparing drivetimes table \n {}". \ format(str(exception)) display_warning_message_box( dialog, "Error", message ) raise IsochroneDBError
def load_map_layers(uri, parent_dialog, drivetime_layer, args): """Style map layers and load them in Qgis :param uri: Connection to the database :type uri: QgsDataSourceURI :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :param drivetime_layer: A layer containing drivetimes :type drivetime_layer: QgsVectorLayer :param args: List containing database parameters :type args: {} """ uri.setDataSource( args['network_schema'], args['network_table'], args['network_geom']) network_layer = QgsVectorLayer( uri.uri(), "network", "postgres") uri.setDataSource( args['catchment_schema'], args['catchment_table'], args['catchment_geom']) catchment_layer = QgsVectorLayer( uri.uri(), "catchment", "postgres") # Style the tin, contour and network drivetime_style = resources_path( 'styles', 'qgis', 'drivetimes.qml') drivetime_layer.loadNamedStyle(drivetime_style) network_style = resources_path( 'styles', 'qgis', 'network.qml') network_layer.loadNamedStyle(network_style) catchment_style = resources_path( 'styles', 'qgis', 'catchment.qml') catchment_layer.loadNamedStyle(catchment_style) if drivetime_layer.isValid(): QgsMapLayerRegistry.instance().addMapLayers( [drivetime_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( "Error"), parent_dialog.tr('Error loading isochrone map ' 'Could not load drivetimes file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load drivetimes file!') if network_layer.isValid(): QgsMapLayerRegistry.instance().addMapLayers( [network_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( "Error"), parent_dialog.tr('Error loading isochrone map ' 'Could not load network file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load network file!') if catchment_layer.isValid(): QgsMapLayerRegistry.instance().addMapLayers( [catchment_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( "Error"), parent_dialog.tr('Error loading isochrone map ' 'Could not load catchment file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load catchment file!')
def calculate_drivetimes(connection, cursor, arguments, dialog, progress_percentage): """ :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog :param progress_percentage: the percentage of progress bar :type progress_percentage: int :returns Progress percentage :rtype int """ index = 0 try: rows = query_nearest_nodes(connection, cursor, arguments, dialog) # Convert unique column to integer as required by # the pgr_dijkstra function sql = """ALTER TABLE routable_network ALTER COLUMN %(network_id)s SET DATA TYPE int4""" % arguments sql = clean_query(sql) cursor.execute(sql) connection.commit() for row in rows: # This step is 45% of all steps so calculating # percentage of each increment accordingly percentage = ((index + 1) / len(rows)) * 45 percentage = round(percentage, 0) catchment_id = row[0] arguments["catchment_current_id"] = catchment_id if index == 0: sql = """ CREATE TABLE IF NOT EXISTS catchment_with_cost AS SELECT id, the_geom, (SELECT sum(cost) FROM ( SELECT * FROM pgr_dijkstra(' SELECT %(network_id)s AS id, start_id::int4 AS source, end_id::int4 AS target, cost::float8 AS cost FROM routable_network', %(catchment_current_id)s, id, false, false)) AS foo ) AS cost FROM nodes;""" % arguments sql = clean_query(sql) cursor.execute(sql) else: sql = """ INSERT INTO catchment_with_cost ( SELECT id, the_geom, (SELECT sum(cost) FROM ( SELECT * FROM pgr_dijkstra(' SELECT %(network_id)s AS id, start_id::int4 AS source, end_id::int4 AS target, cost::float8 AS cost FROM routable_network', %(catchment_current_id)s, id, false, false)) AS foo ) AS cost FROM nodes);""" % arguments sql = clean_query(sql) cursor.execute(sql) index += 1 connection.commit() progress_percentage += percentage if dialog: dialog.setValue(progress_percentage) label_text = tr( str(index) + " catchment area(s) out of " + str(len(rows)) + " is(are) done") dialog.setLabelText(label_text) if dialog: label_text = tr("Preparing all the catchment areas table") dialog.setLabelText(label_text) except Exception as exception: display_warning_message_box(dialog, "Error", "Error in calculating drivetimes") return progress_percentage
def isochrone( database_name, host_name, port_number, user_name, password, network, network_geom, network_id_column, catchment, catchment_geom, catchment_id_column, style_checked, contour_interval, parent_dialog, progress_dialog=None): """Contains main logic on creating isochrone map :param database_name: Database name :type database_name: str :param host_name: Database host :type host_name: str :param port_number: Port number for the host :type port_number: str :param user_name: Username for connection with database :type user_name: str :param password: Password :type password: str :param network: Schema and Table containing the network. :type network: str :param network_geom: Geometry column in network. :type network_geom: str :param network_id_column: Id column in network. :type network_id_column: str :param catchment: Schema and Table containing catchment areas. :type catchment: str :param catchment_geom: Geometry column in catchment. :type catchment_geom: str :param catchment_id_column: Id column in catchment. :type catchment_id_column: str :param style_checked: Value for either to create a map style or not. :type style_checked: boolean :param contour_interval: Interval between contour, if contour will be generated :type contour_interval: int :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :param progress_dialog: A progess dialog . :type progress_dialog: QProgressDialog :returns layer_name: temporary path of the isochrones map layer :rtype layer_name: str """ # Import files into database, have tables # connect to database # add the files get the tables name connection = psycopg2.connect( "dbname='" + str(database_name) + "' " "user='******' " "host='" + str(host_name) + "' " "password='******' ") curr = connection.cursor() # Create nodes from network if progress_dialog: progress_dialog.show() # Infinite progress bar when the server is fetching data. # The progress bar will be updated with the file size later. progress_dialog.setMinimum(0) progress_dialog.setMaximum(100) label_text = tr("Creating network nodes table") progress_dialog.setLabelText(label_text) progress_dialog.setValue(0) network_array = network.split('.') network_table = str(network_array[1]) network_schema = network_array[0] catchment = catchment.split('.') catchment_table = catchment[1] catchment_schema = catchment[0] if not network_geom: network_geom = "geom" if not catchment_geom: catchment_geom = "geom" arguments = {} arguments["network_table"] = network_table arguments["network_geom"] = network_geom arguments["network_id"] = network_id_column arguments["catchment_table"] = catchment_table arguments["catchment_geom"] = catchment_geom arguments["catchment_id"] = catchment_id_column arguments["database_name"] = database_name arguments["port_number"] = port_number create_network_view(connection, curr, arguments, parent_dialog) create_nodes(connection, curr, arguments, parent_dialog) # Create routable network progress_percentage = 10 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Creating a routable network table") progress_dialog.setLabelText(label_text) create_routable_network(connection, curr, arguments, parent_dialog) # Find nearest nodes from the catchments progress_percentage = 30 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Preparing the catchment table") progress_dialog.setLabelText(label_text) update_catchment(connection, curr, arguments, parent_dialog) # Calculate drivetime for the nearest nodes progress_percentage = 50 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Calculating drivetime for each catchment area") progress_dialog.setLabelText(label_text) progress_percentage = calculate_drivetimes( connection, curr, arguments, progress_dialog, progress_percentage) prepare_drivetimes_table(connection, curr, arguments, parent_dialog) uri = QgsDataSourceURI() # set host name, port, database name, username and password uri.setConnection( host_name, port_number, database_name, user_name, password) # set database schema, table name, geometry column and optionally # subset (WHERE clause) uri.setDataSource( network_schema, "catchment_final_no_null", "the_geom") # Export table as shapefile layer = QgsVectorLayer(uri.uri(), "isochrones", "ogr") temp_layer = QgsVectorLayer(uri.uri(), "isochrones", "postgres") QgsMapLayerRegistry.instance().addMapLayers([temp_layer]) if iface: iface.mapCanvas().refresh() layer_name = temp_layer.dataProvider().dataSourceUri() if style_checked: progress_percentage += 1 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Exporting and preparing isochrone map") progress_dialog.setLabelText(label_text) # TODO implement style creation logic # Run interpolation on the final file (currently using IDW) raster_file = idw_interpolation(layer, parent_dialog) # Generate drivetimes contour try: drivetime_layer = generate_drivetimes_contour( raster_file, contour_interval, parent_dialog) # Load all the required layers args = {} args['network_schema'] = network_schema args['network_table'] = network_table args['network_geom'] = network_geom args['catchment_schema'] = catchment_schema args['catchment_table'] = catchment_table args['catchment_geom'] = catchment_geom load_map_layers(uri, parent_dialog, drivetime_layer, args) except Exception as exception: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error generating drivetimes')) progress_percentage += 4 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Done loading isochrone map") progress_dialog.setLabelText(label_text) if progress_dialog: progress_dialog.setValue(100) progress_dialog.done(QDialog.Accepted) return layer_name
def idw_interpolation(layer, parent_dialog): """Run interpolation using inverse distance weight algorithm :param layer: Vector layer with drivetimes :type layer: QgsVectorLayer :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :returns raster_layer: Interpolated raster layer with drivetimes :rtype raster_layer: QgsRasterLayer """ raster_layer = None try: Processing.initialize() Processing.updateAlgsList() output_raster = processing.runalg('gdalogr:gridinvdist', layer, 'minutes', 2, 0, 0, 0, 0, 0, 0, 0, 5, "[temporary file]") output_file = output_raster['OUTPUT'] file_info = QFileInfo(output_file) base_name = file_info.baseName() # retrieving the raster output , styling it and load it in Qgis raster_layer = QgsRasterLayer(output_file, base_name) except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr('Error'), parent_dialog.tr('Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ') if raster_layer: if raster_layer.isValid(): color_shader = QgsColorRampShader() color_shader.setColorRampType(QgsColorRampShader.INTERPOLATED) colors = { 'deep_green': '#1a9641', 'light_green': '#a6d96a', 'pale_yellow': '#ffffc0', 'light_red': '#fdae61', 'red': '#d7191c' } provider = raster_layer.dataProvider() stats = provider.bandStatistics(1, QgsRasterBandStats.All, raster_layer.extent(), 0) values = {} if stats: min = stats.minimumValue max = stats.maximumValue stat_range = max - min add = stat_range / 4 values[0] = min value = min for index in range(1, 4): value += add values[index] = value values[4] = max else: display_warning_message_box( parent_dialog, parent_dialog.tr('Error'), parent_dialog.tr('Error loading isochrone map' ' Problem indexing the isochrones map')) color_list = [ QgsColorRampShader.ColorRampItem(values[0], QColor(colors['deep_green'])), QgsColorRampShader.ColorRampItem(values[1], QColor( colors['light_green'])), QgsColorRampShader.ColorRampItem(values[2], QColor( colors['pale_yellow'])), QgsColorRampShader.ColorRampItem(values[3], QColor(colors['light_red'])), QgsColorRampShader.ColorRampItem(values[4], QColor(colors['red'])) ] color_shader.setColorRampItemList(color_list) raster_shader = QgsRasterShader() raster_shader.setRasterShaderFunction(color_shader) renderer = QgsSingleBandPseudoColorRenderer( raster_layer.dataProvider(), 1, raster_shader) raster_layer.setRenderer(renderer) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr('Problem'), parent_dialog.tr('Problem styling the isochrone map')) else: display_warning_message_box( parent_dialog, 'Problem', 'Problem styling the isochrone map') QgsMapLayerRegistry.instance().addMapLayers([raster_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr('Error'), parent_dialog.tr('Error loading isochrone map ' 'Could not load interpolated file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load interpolated file!') return raster_layer
def load_map_layers(uri, parent_dialog, drivetime_layer, args): """Style map layers and load them in Qgis :param uri: Connection to the database :type uri: QgsDataSourceURI :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :param drivetime_layer: A layer containing drivetimes :type drivetime_layer: QgsVectorLayer :param args: List containing database parameters :type args: {} """ uri.setDataSource(args['network_schema'], args['network_table'], args['network_geom']) network_layer = QgsVectorLayer(uri.uri(), "network", "postgres") uri.setDataSource(args['catchment_schema'], args['catchment_table'], args['catchment_geom']) catchment_layer = QgsVectorLayer(uri.uri(), "catchment", "postgres") # Style the tin, contour and network drivetime_style = resources_path('styles', 'qgis', 'drivetimes.qml') drivetime_layer.loadNamedStyle(drivetime_style) network_style = resources_path('styles', 'qgis', 'network.qml') network_layer.loadNamedStyle(network_style) catchment_style = resources_path('styles', 'qgis', 'catchment.qml') catchment_layer.loadNamedStyle(catchment_style) if drivetime_layer.isValid(): QgsMapLayerRegistry.instance().addMapLayers([drivetime_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr("Error"), parent_dialog.tr('Error loading isochrone map ' 'Could not load drivetimes file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load drivetimes file!') if network_layer.isValid(): QgsMapLayerRegistry.instance().addMapLayers([network_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr("Error"), parent_dialog.tr('Error loading isochrone map ' 'Could not load network file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load network file!') if catchment_layer.isValid(): QgsMapLayerRegistry.instance().addMapLayers([catchment_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr("Error"), parent_dialog.tr('Error loading isochrone map ' 'Could not load catchment file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load catchment file!')
def prepare_drivetimes_table(connection, cursor, arguments, dialog): """ :param connection: Database connection :type connection: :param cursor: Database connection cursor :type cursor: :param arguments: List of required parameters in querying the database :type arguments: {} :param dialog: Dialog attached to this method :type dialog: Qdialog :param progress_percentage: the percentage of progress bar :type progress_percentage: int """ try: sql = """ DROP TABLE IF EXISTS catchment_final""" sql = clean_query(sql) cursor.execute(sql) connection.commit() sql = """ CREATE TABLE IF NOT EXISTS catchment_final AS SELECT id, the_geom, min (cost) AS %s FROM catchment_with_cost GROUP By id, the_geom """ % "drivetime" sql = clean_query(sql) cursor.execute(sql) connection.commit() sql = """DROP TABLE IF EXISTS catchment_final_no_null""" sql = clean_query(sql) cursor.execute(sql) connection.commit() sql = """ CREATE TABLE catchment_final_no_null AS SELECT *, (drivetime * 60) AS minutes FROM catchment_final WHERE %s IS NOT NULL """ % "drivetime" sql = clean_query(sql) cursor.execute(sql) connection.commit() except Exception as exception: display_warning_message_box( dialog, "Error", "Error in preparing drivetimes table")
def idw_interpolation(layer, parent_dialog): """Run interpolation using inverse distance weight algorithm :param layer: Vector layer with drivetimes :type layer: QgsVectorLayer :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :returns raster_layer: Interpolated raster layer with drivetimes :rtype raster_layer: QgsRasterLayer """ raster_layer = None try: Processing.initialize() Processing.updateAlgsList() output_raster = processing.runalg( 'gdalogr:gridinvdist', layer, 'minutes', 2, 0, 0, 0, 0, 0, 0, 0, 5, "[temporary file]") output_file = output_raster['OUTPUT'] file_info = QFileInfo(output_file) base_name = file_info.baseName() # retrieving the raster output , styling it and load it in Qgis raster_layer = QgsRasterLayer(output_file, base_name) except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map,' 'please check if you have processing ' 'plugin installed ') if raster_layer: if raster_layer.isValid(): color_shader = QgsColorRampShader() color_shader.setColorRampType(QgsColorRampShader.INTERPOLATED) colors = { 'deep_green': '#1a9641', 'light_green': '#a6d96a', 'pale_yellow': '#ffffc0', 'light_red': '#fdae61', 'red': '#d7191c' } provider = raster_layer.dataProvider() stats = provider.bandStatistics( 1, QgsRasterBandStats.All, raster_layer.extent(), 0) values = {} if stats: min = stats.minimumValue max = stats.maximumValue stat_range = max - min add = stat_range / 4 values[0] = min value = min for index in range(1, 4): value += add values[index] = value values[4] = max else: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error loading isochrone map' ' Problem indexing the isochrones map')) color_list = [ QgsColorRampShader.ColorRampItem( values[0], QColor(colors['deep_green'])), QgsColorRampShader.ColorRampItem( values[1], QColor(colors['light_green'])), QgsColorRampShader.ColorRampItem( values[2], QColor(colors['pale_yellow'])), QgsColorRampShader.ColorRampItem( values[3], QColor(colors['light_red'])), QgsColorRampShader.ColorRampItem( values[4], QColor(colors['red'])) ] color_shader.setColorRampItemList(color_list) raster_shader = QgsRasterShader() raster_shader.setRasterShaderFunction(color_shader) renderer = QgsSingleBandPseudoColorRenderer( raster_layer.dataProvider(), 1, raster_shader) raster_layer.setRenderer(renderer) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Problem'), parent_dialog.tr('Problem styling the isochrone map')) else: display_warning_message_box( parent_dialog, 'Problem', 'Problem styling the isochrone map') QgsMapLayerRegistry.instance().addMapLayers([raster_layer]) else: if parent_dialog: display_warning_message_box( parent_dialog, parent_dialog.tr( 'Error'), parent_dialog.tr('Error loading isochrone map ' 'Could not load interpolated file!')) else: display_warning_message_box( parent_dialog, 'Error', 'Error loading isochrone map ' 'Could not load interpolated file!') return raster_layer
def isochrone(database_name, host_name, port_number, user_name, password, network, network_geom, network_id_column, catchment, catchment_geom, catchment_id_column, style_checked, contour_interval, parent_dialog, progress_dialog=None): """Contains main logic on creating isochrone map :param database_name: Database name :type database_name: str :param host_name: Database host :type host_name: str :param port_number: Port number for the host :type port_number: str :param user_name: Username for connection with database :type user_name: str :param password: Password :type password: str :param network: Schema and Table containing the network. :type network: str :param network_geom: Geometry column in network. :type network_geom: str :param network_id_column: Id column in network. :type network_id_column: str :param catchment: Schema and Table containing catchment areas. :type catchment: str :param catchment_geom: Geometry column in catchment. :type catchment_geom: str :param catchment_id_column: Id column in catchment. :type catchment_id_column: str :param style_checked: Value for either to create a map style or not. :type style_checked: boolean :param contour_interval: Interval between contour, if contour will be generated :type contour_interval: int :param parent_dialog: A dialog that called this function. :type parent_dialog: QProgressDialog :param progress_dialog: A progess dialog . :type progress_dialog: QProgressDialog :returns layer_name: temporary path of the isochrones map layer :rtype layer_name: str """ # Import files into database, have tables # connect to database # add the files get the tables name connection = psycopg2.connect("dbname='" + str(database_name) + "' " "user='******' " "host='" + str(host_name) + "' " "password='******' ") curr = connection.cursor() # Create nodes from network if progress_dialog: progress_dialog.show() # Infinite progress bar when the server is fetching data. # The progress bar will be updated with the file size later. progress_dialog.setMinimum(0) progress_dialog.setMaximum(100) label_text = tr("Creating network nodes table") progress_dialog.setLabelText(label_text) progress_dialog.setValue(0) network_array = network.split('.') network_table = str(network_array[1]) network_schema = network_array[0] catchment = catchment.split('.') catchment_table = catchment[1] catchment_schema = catchment[0] if not network_geom: network_geom = "geom" if not catchment_geom: catchment_geom = "geom" arguments = {} arguments["network_table"] = network_table arguments["network_geom"] = network_geom arguments["network_id"] = network_id_column arguments["catchment_table"] = catchment_table arguments["catchment_geom"] = catchment_geom arguments["catchment_id"] = catchment_id_column arguments["database_name"] = database_name arguments["port_number"] = port_number create_network_view(connection, curr, arguments, parent_dialog) create_nodes(connection, curr, arguments, parent_dialog) # Create routable network progress_percentage = 10 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Creating a routable network table") progress_dialog.setLabelText(label_text) create_routable_network(connection, curr, arguments, parent_dialog) # Find nearest nodes from the catchments progress_percentage = 30 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Preparing the catchment table") progress_dialog.setLabelText(label_text) update_catchment(connection, curr, arguments, parent_dialog) # Calculate drivetime for the nearest nodes progress_percentage = 50 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Calculating drivetime for each catchment area") progress_dialog.setLabelText(label_text) progress_percentage = calculate_drivetimes(connection, curr, arguments, progress_dialog, progress_percentage) prepare_drivetimes_table(connection, curr, arguments, parent_dialog) uri = QgsDataSourceURI() # set host name, port, database name, username and password uri.setConnection(host_name, port_number, database_name, user_name, password) # set database schema, table name, geometry column and optionally # subset (WHERE clause) uri.setDataSource(network_schema, "catchment_final_no_null", "the_geom") # Export table as shapefile layer = QgsVectorLayer(uri.uri(), "isochrones", "ogr") temp_layer = QgsVectorLayer(uri.uri(), "isochrones", "postgres") QgsMapLayerRegistry.instance().addMapLayers([temp_layer]) if iface: iface.mapCanvas().refresh() layer_name = temp_layer.dataProvider().dataSourceUri() if style_checked: progress_percentage += 1 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Exporting and preparing isochrone map") progress_dialog.setLabelText(label_text) # TODO implement style creation logic # Run interpolation on the final file (currently using IDW) raster_file = idw_interpolation(layer, parent_dialog) # Generate drivetimes contour try: drivetime_layer = generate_drivetimes_contour( raster_file, contour_interval, parent_dialog) # Load all the required layers args = {} args['network_schema'] = network_schema args['network_table'] = network_table args['network_geom'] = network_geom args['catchment_schema'] = catchment_schema args['catchment_table'] = catchment_table args['catchment_geom'] = catchment_geom load_map_layers(uri, parent_dialog, drivetime_layer, args) except Exception as exception: display_warning_message_box( parent_dialog, parent_dialog.tr('Error'), parent_dialog.tr('Error generating drivetimes')) progress_percentage += 4 if progress_dialog: progress_dialog.setValue(progress_percentage) label_text = tr("Done loading isochrone map") progress_dialog.setLabelText(label_text) if progress_dialog: progress_dialog.setValue(100) progress_dialog.done(QDialog.Accepted) return layer_name