I have a weird problem. I'm writing a Processing standalone plugin in QGIS 3 (current master, 3.1).
In the main algorithm I have to create some intermediate layers (mostly raster) with GRASS and SAGA provider, no problem so far. For example here the snippet of r.watershed
:
viewshed = processing.run('grass7:r.viewshed', {
'input': raster,
'coordinates': coordStr,
'observer_elevation': 0,
'target_elevation': 0,
'max_distance': Visibility_Distance,
'refraction_coeff': 0.14286,
'memory': 500,
'-c':False,
'-r':False,
'-b':False,
'-e':False,
'output':os.path.join(Results, 'my_output.tif'),
'GRASS_REGION_PARAMETER': tr_extent,
'GRASS_REGION_CELLSIZE_PARAMETER':0,
'GRASS_RASTER_FORMAT_OPT':'',
'GRASS_RASTER_FORMAT_META':''
})
but then I cannot load the resulting layer in the legend, even if it is correctly created and I can load it by hand.
Here what I'm trying to do:
view = QgsRasterLayer(viewshed['output'], 'my_output','gdal')
QgsProject.instance().addMapLayer(view)
I don't get any error from the console.
The exact same syntax works in a single script written in the Python editor of QGIS.
Any clue?
2 Answers 2
I used that way to change layer order while processing. As I know, normally you can't add layer to legend while processing in QGIS 3 unlike QGIS 2.
Try that. But it's risky according to this post.
# add this method to your algorithm class.
def flags(self):
return super().flags() | QgsProcessingAlgorithm.FlagNoThreading
and
# add last two lines (feedback and context parameters) to your 'run' method
viewshed = processing.run('grass7:r.viewshed', {
'input': raster,
'coordinates': coordStr,
'observer_elevation': 0,
'target_elevation': 0,
'max_distance': Visibility_Distance,
'refraction_coeff': 0.14286,
'memory': 500,
'-c':False,
'-r':False,
'-b':False,
'-e':False,
'output':os.path.join(Results, 'my_output.tif'),
'GRASS_REGION_PARAMETER': tr_extent,
'GRASS_REGION_CELLSIZE_PARAMETER':0,
'GRASS_RASTER_FORMAT_OPT':'',
'GRASS_RASTER_FORMAT_META':''
},
feedback=feedback, # without these two lines
context=context) # QGIS may crash
# And then, try to add layer to map.
view = QgsRasterLayer(viewshed['output'], 'my_output','gdal')
QgsProject.instance().addMapLayer(view)
-
thanks! I missed that! Did you make some experiments with the method that will be available in 3.2 (QgsProcessingLayerPostProcessorInterface)?matteo– matteo2018年04月23日 16:43:22 +00:00Commented Apr 23, 2018 at 16:43
You can also do it without having to run your script inside the main thread, which works but may not be ideal.
# And then, try to add layer to map.
view = QgsRasterLayer(viewshed['output'], 'my_output','gdal')
context.temporaryLayerStore().addMapLayer(view)
context.addLayerToLoadOnCompletion(view.id(), QgsProcessingContext.LayerDetails("", QgsProject.instance(), ""))
-
Just the line seems to be enough for me, no need for a QgsRasterLayer instance or adding it to the store:
context.addLayerToLoadOnCompletion(visibility_viewshed["OUTPUT"], QgsProcessingContext.LayerDetails("", QgsProject.instance()))
bugmenot123– bugmenot1232023年04月06日 16:31:18 +00:00Commented Apr 6, 2023 at 16:31
processing.run
withprocessing.runAndLoadResults
.