Come caricare l'output di memoria dall'elaborazione QGIS?


11

Molti algoritmi di elaborazione hanno un'opzione per salvare l'output come memoria. Se eseguito dalla casella degli strumenti, funziona correttamente, perché è possibile selezionare la casella "Apri file di output dopo l'esecuzione dell'algoritmo".

Guardando il codice sorgente per QGIS, il codice per caricare il livello di memoria sembra essere definito nella funzione Postprocessing.handleAlgorithmResults. La funzione utilizza l'accesso a un alg.outputselenco e procede come segue:

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:
                # ... 

Quando esegui algoritmi di elaborazione dalla console, c'è un modo per caricare il layer senza accedere a questo oggetto? posso correre

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

o anche

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

Non riesco comunque a trovare un modo per afferrare l'output risultante.

Risposte:


15

Aaaand l'ho trovato. Usa processing.runandload, che carica il livello di output nel sommario dopo aver eseguito l'algoritmo.

processing.runandload("qgis:intersection", layer1, layer2, "memory:myLayerName")
layer = QgsMapLayerRegistry.instance().mapLayersByName("memory:myLayerName")[0]
# Should do error checking as well, but this works!!

1
Sono incuriosito dalla risposta che hai trovato. Sai se esiste un modo simile per creare un livello di memoria e poter accedervi senza implementare runandload? Spero di fare un po 'di post elaborazione sull'output di elaborazione prima di aggiungerlo alla tela - e mi chiedevo se fosse possibile ...
Katalpa

1
Non riuscivo a trovarne uno in quel momento, per non dire che è impossibile ... Immagino che potresti caricarlo e nasconderlo, se questo aiuta.
Oystein,

Se non riesci a trovare il nome del livello usando QgsMapLayerRegistry.instance().mapLayersByName("memory:myLayerName")[0]questo, prova questo:QgsMapLayerRegistry.instance().mapLayers()
Compagno Che

@Katalpa puoi provare, processing.runalg ("qgis: intersection", layer1, layer2, 'out.shp')
dramma

4

è il modo corretto, è spiegato nella documentazione http://docs.qgis.org/2.14/es/docs/user_manual/processing/console.html

il codice successivo funziona con in memoria tutto tranne l'ultimo che viene caricato

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])

la processing.runalgrestituisce un dizionario in questo caso bu['OUTPUT']. OUTPUTÈ LA CHIAVE e il valore è un percorso temporaneo. Puoi vedere la chiave con processeing.alghelp ("elaborazione del nome") come elaborazione, alghelp ("grass: r.drain")

ritorno

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 questo caso la chiave viene emessa , fai attenzione con le lettere maiuscole che devi scrivere in maiuscolo o senza maiuscolo, in questo caso non maiuscolo.


Si prega di evitare risposte duplicate ( gis.stackexchange.com/a/211730/8104 ), seguendo i criteri di Exchange Stack. Maggiori dettagli: meta.stackexchange.com/q/104227
Aaron

Questo è stato quello che alla fine ha funzionato per me. Le informazioni chiave che mancavano altrove era che è possibile passare il output['OUTPUT']percorso QgsVectorLayercon un provider_namedi "ogr". Questo leggerà nel percorso .shp e creerà un livello in memoria. Questo approccio non aggiunge il livello al registro, quindi non lampeggia nel pannello Livelli.
Nick K9,

Secondo la pagina di manuale a cui fai riferimento, "Il metodo runalg restituisce un dizionario con i nomi di output (quelli mostrati nella descrizione dell'algoritmo) come chiavi e i percorsi dei file di tali output come valori". Quindi questo approccio non sembra usare i livelli di memoria: tutti i risultati intermedi verranno archiviati nel file system.
Håvard Tveite,

0

Non sono sicuro se questo ti aiuterà nel tuo contesto (vuoi eseguire il tuo codice come autonomo o all'interno di QGIS dopo che un algoritmo di elaborazione è terminato?). In quest'ultimo caso, è possibile eseguire una query su oggetti caricati QGsVector-e facilmente QGsRasterlayeresaminando il registro di QGIS MapLayer.

# 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 generale, tutti i layer devono avere una sorgente da qualche parte sul disco rigido anche se il risultato viene appena aggiunto dopo che l'elaborazione ha terminato i suoi calcoli. Se guardi nei metadati dei livelli puoi trovare l'origine effettiva di un livello (se ha origine dall'elaborare normalmente da qualche parte in una cartella temporanea)


La ringrazio per la risposta. Penso che ci sia già una getLayersByNamefunzione per il registro delle mappe, ma voglio eseguire l'algoritmo dalla console da solo, quindi questo non aiuterà davvero (il livello di memoria non viene mai caricato nel registro, è quello che sto cercando di fare) . Ma stai dicendo che non c'è alcun vantaggio nell'usare un output di memoria rispetto al passaggio Nonee alla generazione di un file temporaneo? Sei sicuro di questo?
Oystein,

Noneviene appena superato se non è possibile trovare il livello nel registro. Non crea un file temporaneo e devi comunque verificarlo manualmente. Uso questa funzione per interrogare i livelli caricati all'interno di QGIS. Non posso aiutarti fuori nella console.
Chiurlo

Penso che tu abbia frainteso, stavo parlando del passaggio Nonea processing.runalgcome parametro di output, che credo crei un file di output temporaneo.
Oystein,

FYI: Ho appena trovato di nuovo la funzione QgsMapLayerRegistry, si chiamamapLayersByName
Oystein
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.