Adding this here as a working example of doing this via the QgsProcessingLayerPostProcessorInterface class. As described here, to set post processors to multiple output layers it is necessary to store references to the created QgsProcessingLayerPostProcessorInterface instances with class-level scope e.g. in a dictionary declared as an instance attribute of the QgsProcessingAlgorithm sub-class.
from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingParameterField
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingUtils
from qgis.core import QgsProcessingContext
from qgis.core import QgsProcessingLayerPostProcessorInterface
from qgis.core import QgsRasterLayer
import processing
class Group_output_layers(QgsProcessingAlgorithm):
post_processors = {}
def name(self):
return 'group_output_layers'
def displayName(self):
return 'group_output_layers'
def group(self):
return 'Models'
def groupId(self):
return 'Models'
def createInstance(self):
return Group_output_layers()
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterVectorLayer('Inputpolygons', 'Input_polygons', types=[QgsProcessing.TypeVectorPolygon], defaultValue=None))
self.addParameter(QgsProcessingParameterField('Burnfields', 'Burn_fields', type=0, parentLayerParameterName='Inputpolygons', allowMultiple=True, defaultToAllFields=True,))
def processAlgorithm(self, parameters, context, feedback):
results = {}
outputs = {}
in_layer = self.parameterAsVectorLayer(parameters, 'Inputpolygons', context)
fields = self.parameterAsFields(parameters, 'Burnfields', context)
for index, field in enumerate(fields):
if feedback.isCanceled():
break
# Rasterize
alg_params = {
'BURN': 0,
'DATA_TYPE': 5,
'EXTENT': in_layer.extent(),
'EXTRA': '',
'FIELD': field,
'INIT': None,
'INPUT': parameters['Inputpolygons'],
'INVERT': False,
'NODATA': -9999,
'OPTIONS': '',
'UNITS': 1,
'HEIGHT': 90,
'WIDTH': 90,
'OUTPUT': 'TEMPORARY_OUTPUT',
}
outputs[f'Outlayer{field}'] = processing.run('gdal:rasterize',
alg_params,
is_child_algorithm=True,
context=context,
feedback=feedback)
results[f'Rasterized_{field}'] = outputs[f'Outlayer{field}']['OUTPUT']
for result_name, lyr_id in results.items():
context.addLayerToLoadOnCompletion(lyr_id, QgsProcessingContext.LayerDetails(result_name, context.project(), result_name))
self.post_processors[lyr_id] = GroupRasterPostProcessor.create()
context.layerToLoadOnCompletionDetails(lyr_id).setPostProcessor(self.post_processors[lyr_id])
return results
class GroupRasterPostProcessor(QgsProcessingLayerPostProcessorInterface):
instance = None
group_name = 'group1'
def postProcessLayer(self, layer, context, feedback):
if not isinstance(layer, QgsRasterLayer):
return
project = context.project()
root_group = project.layerTreeRoot()
if not root_group.findGroup(self.group_name):
root_group.insertGroup(0, self.group_name)
group1 = root_group.findGroup(self.group_name)
lyr_node = root_group.findLayer(layer.id())
if lyr_node:
node_clone = lyr_node.clone()
group1.addChildNode(node_clone)
lyr_node.parent().removeChildNode(lyr_node)
# Hack to work around sip bug!
@staticmethod
def create() -> 'GroupRasterPostProcessor':
"""
Returns a new instance of the post processor, keeping a reference to the sip
wrapper so that sip doesn't get confused with the Python subclass and call
the base wrapper implementation instead...
"""
GroupRasterPostProcessor.instance = GroupRasterPostProcessor()
return GroupRasterPostProcessor.instance
References & Acknowledgements:
Nyall Dawson for the post processor example adapted here.
https://github.com/qgis/QGIS/issues/47533
Set display name of vector layer in processing script
Results group nameoption inQGIS --> Settings --> Options --> Processing, which you can use to get all results from processing algorithms to a group in the Layers panel. See https://docs.qgis.org/testing/en/docs/user_manual/processing/configuration.html – Germán Carrillo Nov 22 '21 at 01:48QgsProcessingLayerPostProcessorInterfaceand move it to the group in itspostProcessLayer()method. – bugmenot123 Apr 06 '23 at 22:40