Skip to content

Instantly share code, notes, and snippets.

@ottadini
Created January 10, 2020 09:45
Show Gist options
  • Save ottadini/4c7450051ae4895866c3d7c5ba69f28c to your computer and use it in GitHub Desktop.
Save ottadini/4c7450051ae4895866c3d7c5ba69f28c to your computer and use it in GitHub Desktop.
Error - PyQGIS processing with gdal:gdal2xyz
'''
Constants for use in processing scripts
For Windows paths use the raw string formatter, e.g.
# my_path = r"C:\"
'''
# Will be different in QGIS install vs OSGEO4W install
QGIS_PLUGINS_PATH = r"C:\OSGeo4W64\apps\qgis\python\plugins"
WORKING_RASTER = "IslandOfKahoolawe.sdat"
WORKING_RASTER_PATH = r"C:\Users\Public\Documents"
'''
LS-Factor
Calculation of slope length (LS) factor as used by the Universal Soil Loss
Equation (USLE), based on slope and specific catchment area (SCA, as substitute
for slope length).
Requires SLOPE and CATCHMENT AREA ("FLOW.sdat" below) rasters to be prepared.
'''
import os
import sys
import shutil
from datetime import datetime
from constants import (
QGIS_PLUGINS_PATH,
WORKING_RASTER,
WORKING_RASTER_PATH
)
from qgis.core import (
QgsApplication,
QgsRasterLayer,
QgsProcessingFeedback
)
# I don't know why this has to be done in the script and not just as part of the ENV settings.
sys.path.append(QGIS_PLUGINS_PATH)
#-------------------------------------------------------------
# start QGIS processing application
print("::: Initialising PyQGIS")
qgs = QgsApplication([], False)
qgs.initQgis()
import processing
from processing.core.Processing import Processing
Processing.initialize()
# -------------------------------------------------------------
# -------------------------------------------------------------
# root dir:
root_dir = os.path.abspath(WORKING_RASTER_PATH)
# working dir for intermediate files
working_path = os.path.join(root_dir, "Working")
# output dir for the set of XYZ outputs from morphometry analyses
output_path = os.path.join(root_dir, 'Outputs')
xyz_path = os.path.join(output_path, "xyz")
# -------------------------------------------------------------
def log_timestamp():
'''formatted timestamp for console log'''
return datetime.now().strftime('%Y-%m-%d %X')
def progress_changed(progress):
'''A function to return Processing feedback to the console'''
print(progress)
def write2xyz(feature_layer, parent_name, provider='saga'):
'''Writes raster feature to an XYZ file (no headers)
INPUTS:
feature_layer: a QgsRasterLayer object to write out to XYZ.
parent_name: the display name of the source raster.
provider: the provider of the algorithm that generated the
QgsRasterLayer, e.g., saga, qgis, gdal.
'''
xyz_file = os.path.join(xyz_path, parent_name, provider + '_' + feature_layer.name() + '.xyz')
gdal_parameters = {
'INPUT': feature_layer, # this is a QgsRasterLayer object
'CSV': False,
'OUTPUT': xyz_file,
'BAND': 1
}
gdal_result = processing.run('gdal:gdal2xyz', parameters = gdal_parameters)
return gdal_result['OUTPUT']
# Read in raster layer
raster_file = os.path.join(working_path, WORKING_RASTER)
raster_layer = QgsRasterLayer(raster_file, baseName = os.path.splitext(os.path.basename(raster_file))[0], providerType = 'gdal')
# create the output dir if necessary
if not os.path.isdir(os.path.join(xyz_path, raster_layer.name())):
os.makedirs(os.path.join(xyz_path, raster_layer.name()))
parameters = {
'SLOPE':'C:/Users/Public/Documents/SLOPE.sdat',
'AREA':'C:/Users/Public/Documents/FLOW.sdat',
'CONV':0,
'METHOD':2,
'EROSIVITY':0,
'STABILITY':0,
'LS':'TEMPORARY_OUTPUT'
}
# Set feedback to update the user with progress
feedback = QgsProcessingFeedback()
feedback.progressChanged.connect(progress_changed)
result = processing.run("saga:lsfactor", parameters = parameters, feedback = feedback)
if result is None or result['LS'] == '':
print(f"!!! Failed to process {raster_layer.name()}!")
qgs.exitQgis()
exit()
# save to xyz
# only interested in the LS Factor result
feature_layer = QgsRasterLayer(result['LS'], 'LSFactor', 'gdal')
result_file = write2xyz(feature_layer, raster_layer.name(), 'saga')
qgs.exitQgis()
# write out the headers to match the output XYZ file
header_file = os.path.join(xyz_path, raster_layer.name(), "saga_LSFactor_header.xyz")
with open(header_file, 'w') as f:
f.write('X Y LSFACTOR\n') # make sure to add a newline at the end
# append the results to the header file
with open(header_file, 'ab') as hfile:
with open(result_file, 'rb') as rfile:
shutil.copyfileobj(rfile, hfile)
copy_result = shutil.copyfile(header_file, result_file) # writes over the result file
if copy_result == result_file:
os.remove(header_file)
@ottadini
Copy link
Author

ottadini commented Jan 10, 2020

Expected output example (from grass7:r.out.xyz):

image

Incomplete output example:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment