7

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
  • Try replacing processing.run with processing.runAndLoadResults.
    – Joseph
    Apr 23, 2018 at 14:24
  • nope, already tried. It works in single scripts but not in Processing plugin scripts
    – matteo
    Apr 23, 2018 at 14:40

2 Answers 2

6

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)
1
  • thanks! I missed that! Did you make some experiments with the method that will be available in 3.2 (QgsProcessingLayerPostProcessorInterface)?
    – matteo
    Apr 23, 2018 at 16:43
1

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(), ""))
1
  • 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())) Apr 6, 2023 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.