Created
January 10, 2020 09:45
-
-
Save ottadini/4c7450051ae4895866c3d7c5ba69f28c to your computer and use it in GitHub Desktop.
Error - PyQGIS processing with gdal:gdal2xyz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Expected output example (from grass7:r.out.xyz):
Incomplete output example: