4

The ability to write and run cross platform scripts for QGIS using python is OUTSTANDING! However, when I try to run the SAGA:MERGESHAPESLAYERS algorithm from a python script it works fine in windows but returns no output shape when I run it in ubuntu. I'm running QGIS 2.4 on ubuntu.

I'm confident that I DO have SAGA 2.1 on the ubuntu system because I can successfully run the convex hull algorithm.

To illustrate the issue I have written the following scripts. The first of which creates a few of shape files in the temp directory then the second attempts to apply the aforementioned SAGA algorithms. You should be able to easilty cut and paste the scripts into the QGIS python console in order to illustrate the issue.

First script which creates a few shape files in the temp directory:

#BUILD EXAMPLE SHAPE FILES TO ILLUSTRATE THE ISSUE
from qgis import core
from qgis.utils import iface
import os
import tempfile
import sys
epsg=4326
my_crs =core.QgsCoordinateReferenceSystem(epsg,core.QgsCoordinateReferenceSystem.EpsgCrsId)
iface.mapCanvas().mapRenderer().setDestinationCrs(my_crs)
vlayer01=QgsVectorLayer("Polygon?crs=epsg:"+str(epsg)+"&field=id:integer&field=name:string(20)&index=yes","polygon_01","memory")
bbl_dp = vlayer01.dataProvider()
vlayer01.startEditing()
feature_01_01 = QgsFeature()
feature_01_01.setGeometry(QgsGeometry.fromPolygon(\
[[QgsPoint(0,100),QgsPoint(0,110), QgsPoint(10,110),QgsPoint(10,100)]]))
feature_01_02 = QgsFeature()
feature_01_02.setGeometry(QgsGeometry.fromPolygon(\
[[QgsPoint(-10,100),QgsPoint(-10,110), QgsPoint(-20,110),QgsPoint(-20,100)]]))
(res, outFeats) = vlayer01.dataProvider().addFeatures([feature_01_01,feature_01_02])
vlayer01.commitChanges()
QgsMapLayerRegistry.instance().addMapLayer(vlayer01)
vlayer01_path=os.path.join(tempfile.gettempdir(),"vlayer_01.shp")
write_error = \
QgsVectorFileWriter.writeAsVectorFormat(vlayer01, \
vlayer01_path, "system", \
QgsCoordinateReferenceSystem(epsg), \
"ESRI Shapefile")
vlayer02=QgsVectorLayer("Polygon?crs=epsg:"+str(epsg)+"&field=id:integer&field=name:string(20)&index=yes","polygon_02","memory")
bbl_dp = vlayer02.dataProvider()
vlayer02.startEditing()
feature_02_01 = QgsFeature()
feature_02_01.setGeometry(QgsGeometry.fromPolygon(\
[[QgsPoint(20,110),QgsPoint(20,120), QgsPoint(30,120),QgsPoint(30,110)]]))
(res, outFeats) = vlayer02.dataProvider().addFeatures([feature_02_01])
vlayer02.commitChanges()
QgsMapLayerRegistry.instance().addMapLayer(vlayer02)
vlayer02_path=os.path.join(tempfile.gettempdir(),"vlayer_02.shp")
write_error = \
QgsVectorFileWriter.writeAsVectorFormat(vlayer02, \
vlayer02_path, "system", \
QgsCoordinateReferenceSystem(epsg), \
"ESRI Shapefile")
vlayer03=QgsVectorLayer("Polygon?crs=epsg:"+str(epsg)+"&field=id:integer&field=name:string(20)&index=yes","polygon_03","memory")
bbl_dp = vlayer03.dataProvider()
vlayer03.startEditing()
feature_03_01 = QgsFeature()
feature_03_01.setGeometry(QgsGeometry.fromPolygon(\
[[QgsPoint(3,103),QgsPoint(3,113), QgsPoint(13,113),QgsPoint(13,103)]]))
(res, outFeats) = vlayer03.dataProvider().addFeatures([feature_03_01])
vlayer03.commitChanges()
QgsMapLayerRegistry.instance().addMapLayer(vlayer03)
vlayer03_path=os.path.join(tempfile.gettempdir(),"vlayer_03.shp")
write_error = \
QgsVectorFileWriter.writeAsVectorFormat(vlayer03, \
vlayer03_path, "system", \
QgsCoordinateReferenceSystem(epsg), \
"ESRI Shapefile")
qgis.utils.iface.setActiveLayer(vlayer01)
qgis.utils.iface.zoomToActiveLayer()

Second script which addresses the issue

###SAGA PROCESSING ALGORITHM ISSUE STARTS HERE###
import processing
alg_list=[]
alg_list.append("qgis:mergevectorlayers")
alg_list.append("saga:mergeshapeslayers")
alg_list.append("saga:convexhull")
for alg in alg_list:
    if alg=="saga:convexhull":
        SHAPES=vlayer01_path
        POLYPOINTS=0
        HULLS=os.path.join(tempfile.gettempdir(),"output_saga_convexhull.shp")
        BOXES=""
        processing_result=processing.runalg(alg,SHAPES,POLYPOINTS,HULLS,BOXES)
        print alg+" was "+str(processing_result)
        resultlayer = QgsVectorLayer(HULLS, "saga:convexhull", "ogr")
        QgsMapLayerRegistry.instance().addMapLayer(resultlayer)
        qgis.utils.iface.setActiveLayer(resultlayer)
        qgis.utils.iface.zoomToActiveLayer()
    if alg=="saga:mergeshapeslayers":
        MAIN=vlayer01_path
        LAYERS=vlayer02_path+";"+vlayer03_path
        OUT=os.path.join(tempfile.gettempdir(),"output_saga_mergeshapeslayers.shp")
        processing_result=processing.runalg(alg,MAIN,LAYERS,OUT)
        print alg+" was "+str(processing_result)
        resultlayer = QgsVectorLayer(OUT, "saga:mergeshapeslayers", "ogr")
        QgsMapLayerRegistry.instance().addMapLayer(resultlayer)
        qgis.utils.iface.setActiveLayer(resultlayer)
        qgis.utils.iface.zoomToActiveLayer()
    if alg=="qgis:mergevectorlayers":
        LAYER1=vlayer01_path
        LAYER2=vlayer02_path
        SAVENAME=os.path.join(tempfile.gettempdir(),"output_qgis_mergevectorlayers.shp")
        processing_result=processing.runalg(alg,LAYER1,LAYER2,SAVENAME)
        print alg+" was "+str(processing_result)
        resultlayer = QgsVectorLayer(SAVENAME, "qgis:mergevectorlayers", "ogr")
        QgsMapLayerRegistry.instance().addMapLayer(resultlayer)
        qgis.utils.iface.setActiveLayer(resultlayer)
        qgis.utils.iface.zoomToActiveLayer()

The merge algorithm works only in windows and the convex hull algorithm works in both windows and ubuntu. I'd really like the SAGA:MERGESHAPESLAYERS algorithm to work cross platform as intended.

Thanks for looking!

  • Is that script intendend to run inside or outside (standalone) of QGIS GUI? As far as I know, it was not possible to call QGIS processing tools from outside QGIS (see question here: gis.stackexchange.com/questions/71820/…). I would be very happy to learn that this has changed. – Martin Oct 20 '14 at 6:45
  • Oops I used the word "standalone" without realizing it was jargon. Edited. – Mr Purple Oct 20 '14 at 7:23
  • Maybe an issue of backslash vs forward slash: gis.stackexchange.com/questions/34631/… – AndreJ Oct 20 '14 at 7:49
  • I don't thinks it's a path 'slash' issue. I use os.path.join to build my paths. In any case, it wouldn't explain why the convex-hulls algorithm works but the merge doesn't. Well that's my code. I can't speak for the QGIS Ubuntu implementation of each the SAGA algorithms. – Mr Purple Oct 20 '14 at 7:55
  • 1
    In Processing -> Options, General you can activate to keep the dialogue open. – AndreJ Oct 20 '14 at 8:15
1

I may have found why the call to SAGA:MERGESHAPESLAYERS is not working in ubuntu from QGis

Regardless of my 2.0.8 syntax setting QGis generates the following line of shell script

shapes_tools "Merge Shapes Layers" -MAIN "/tmp/vlayer_01.shp" -LAYERS "/tmp/vlayer_01.shp;/tmp/vlayer_02.shp" -OUT "/tmp/output.shp"

When run it generates the following error:

Unknown option 'MAIN'

and further down the error log I note:

Usage: saga_cmd shapes_tools 0

Which is the "Create New Layer" tool and has no 'MAIN" input. When I enter the following line directly into my shell:

saga_cmd shapes_tools

I note that in my version of SAGA (2.1.2) I see no "Merge Shapes Layers" tool. Thus the request for a "Merge Shapes Tool" appears to be defaulting to tool no. 0 The "Create New Shape Layer" tool.

There does appear to be a merge tool, but it's called "Merge Layers" not "Merge Shapes Layers"

So my solution (in ubuntu - which uses SAGA 2.1.2) is going to have to be to first determine if I have SAGA version 2.1.2 or higher then manually prepare and call the "Merge Layers" tool.

Here's my work around (working in my ubuntu).The shell commands will probably need tweaking to work in windows. If I find myself in windows I'll fix that up too.

#REPLACE YOUR PREVIOUSLY WORKING
#processing_result=processing.runalg("saga:mergeshapeslayers",MAIN,LAYERS,OUT)

#WITH NOW WORKING (IN UBUNTU)
import subprocess
from subprocess import Popen, PIPE
from distutils.version import StrictVersion
p = Popen(["saga_cmd", '-v'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
saga_version=output[14:].rstrip()
if StrictVersion(saga_version) >= StrictVersion('2.1.2'):
    INPUT=MAIN+";"+LAYERS
    MERGED=OUT
    p = Popen(["saga_cmd", "shapes_tools","2","-INPUT",INPUT,"-MERGED",MERGED], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    output, err = p.communicate(b"input data that is passed to subprocess' stdin")
    rc = p.returncode
else:
    processing_result=processing.runalg("saga:mergeshapeslayers",MAIN,LAYERS,OUT)

Honestly, I hope I'm wrong but if not, hopefully QGis can be patched to correctly generate scripts for this powerful algorithm ASAP.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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