17

Many processing algorithms have an option to save output as memory. If ran from toolbox, this works fine, because you can tick the "Open output file after running algorithm" box.

Looking at the source code for QGIS, the code for loading the memory layer seems to be defined in the function Postprocessing.handleAlgorithmResults. The function uses access to an alg.outputs list, and does the following:

for out in alg.outputs:
    progress.setPercentage(100 * i / float(len(alg.outputs)))
    if out.hidden or not out.open:
        continue
    if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
        try:
            if out.value.startswith('memory:'):
                layer = out.memoryLayer                                # NOTE!!
                QgsMapLayerRegistry.instance().addMapLayers([layer])   # NOTE!!
            else:
                # ... 

When you run processing algorithms from the console, is there a way to load the layer without access to this object? I can run

processing.runalg("qgis:intersection", layer1, layer2, "memory:")

or even

processing.runalg("qgis:intersection", layer1, layer2, "memory:myLayerName")

I can however not find a way to grab the resulting output.

3 Answers 3

18

Aaaand I found it. Use processing.runandload, which loads the output layer into the table of contents after running the algorithm.

processing.runandload("qgis:intersection", layer1, layer2, "memory:myLayerName")
layer = QgsMapLayerRegistry.instance().mapLayersByName("memory:myLayerName")[0]
# Should do error checking as well, but this works!!
4
  • 1
    I am intrigued by the answer you found. Do you know if there is a similar means of creating a memory layer - and being able to access it without implementing runandload? I hope to do some post processing on the processing output before adding it to the canvas - and wondered if such is even possible...
    – Katalpa
    Commented Apr 1, 2015 at 14:07
  • 1
    I couldn't find one at the time, not to say that it's impossible... I guess you could load it and hide it, if that helps.
    – user23603
    Commented Apr 9, 2015 at 15:14
  • If you can't find layer name using QgsMapLayerRegistry.instance().mapLayersByName("memory:myLayerName")[0] try this: QgsMapLayerRegistry.instance().mapLayers() Commented Dec 22, 2017 at 12:49
  • @Katalpa you can try, processing.runalg("qgis:intersection", layer1, layer2,'out.shp')
    – drama
    Commented Feb 22, 2018 at 12:25
4

it is the correct way, it's explained in the documentation http://docs.qgis.org/2.14/es/docs/user_manual/processing/console.html

the next code work with in memory all except the last that it is load

MDT=path/mdt.tif
drain=processing.runalg("grass:r.drain",MDT,"",(pun),False,False,False,"%f,%f,%f,%f"% (xmin, xmax, ymin, ymax),0,-1,0.00100,None)
vect=processing.runalg("grass:r.to.vect",drain['output'],0,False,"%f,%f,%f,%f"% (xmin, xmax, ymin, ymax),0,None)
bu=processing.runalg("qgis:fixeddistancebuffer",vect['output'],Metros_afecta,1,False,None)
buf=bu['OUTPUT']
bufe= QgsVectorLayer(buf,"area", "ogr")
#the last load the layer 
QgsMapLayerRegistry.instance().addMapLayers([bufe])

the processing.runalg returns a dictionary in this case bu['OUTPUT']. OUTPUT IS THE KEY, and the value is a temp path. You can see the key with processeing.alghelp("name processing") as processing,alghelp("grass:r.drain")

return

processing.alghelp("grass:r.drain")
ALGORITHM: r.drain - Traces a flow through an elevation model on a raster map.
input <ParameterRaster>
coordinate <ParameterString>
vector_points <ParameterMultipleInput>
-c <ParameterBoolean>
-a <ParameterBoolean>
-n <ParameterBoolean>
GRASS_REGION_PARAMETER <ParameterExtent>
GRASS_REGION_CELLSIZE_PARAMETER <ParameterNumber>
GRASS_SNAP_TOLERANCE_PARAMETER <ParameterNumber>
GRASS_MIN_AREA_PARAMETER <ParameterNumber>
output <OutputRaster>

in this case the key is output , take care with capital letters you must write in capital or without capital, in this case not capital.

3
  • Please avoid duplicate answers (gis.stackexchange.com/a/211730/8104), following Stack Exchange policy. More details: meta.stackexchange.com/q/104227
    – Aaron
    Commented Sep 23, 2016 at 1:57
  • This was the one that ultimately worked for me. The key info that was missing elsewhere was that you can pass the output['OUTPUT'] path to QgsVectorLayer with a provider_name of "ogr". This will read in the .shp path and create an in-memory layer. This approach doesn't add the layer to the registry, so it doesn't flash in the Layers Panel.
    – Nick K9
    Commented Nov 6, 2017 at 21:01
  • According to the manual page you reference, "The runalg method returns a dictionary with the output names (the ones shown in the algorithm description) as keys and the file paths of those outputs as values." So this approach does not seem to use memory layers - all intermediate results will be stored in the file system. Commented Nov 18, 2017 at 22:06
1

I am not sure if this will help you in your context (do you want to run your code as standalone or within QGIS after a processing algoritm finished?). If its the latter you could easily query loaded QGsVector- and QGsRasterlayer objects by looking into the QGIS MapLayer registry.

# General function to retrieve a layer with a given name
def getLayerByName( layerName ):
  layerMap = QgsMapLayerRegistry.instance().mapLayers()
  for name, layer in layerMap.iteritems():
    if layer.name() == layerName:
        if layer.isValid():
          return layer
        else:
          return None

In general all layers must have a source somewhere on the harddrive even if the result is just added after a processing-alg finishes its calculations. If you look into the layers metadata you can find the actual source of a layer (if its originating from processing its normally somewhere in a temporary folder)

4
  • Thank you for your answer. I think there already is a getLayersByName function for the map registry, but I want to run the algorithm from console myself, so this won't really help (the memory layer is never loaded into the registry, that's what I'm trying to do). But are you saying that there is no advantage to using a memory output compared to passing None and generating a temp file? Are you sure about that?
    – user23603
    Commented Nov 6, 2013 at 11:10
  • None is just passed if the layer can not be found in the registry. It doesn't create a tempfile and you need to check for it manually anyway. I use this function to query loaded layers within QGIS. Can't help you outside in the console.
    – Curlew
    Commented Nov 6, 2013 at 11:34
  • I think you misunderstood, I was talking about passing None to processing.runalg as the output parameter, which I believe creates a temp output file.
    – user23603
    Commented Nov 6, 2013 at 11:37
  • FYI: Just came across the QgsMapLayerRegistry function again, it's called mapLayersByName
    – user23603
    Commented Nov 7, 2013 at 13:18

Your Answer

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