7

I have the following piece of code which I execute within QGIS 2.8.6

import processing
import ogr
restrLayer = QgsVectorLayer("/home/usr/Desktop/trial/EligibleAreas_polygons_filtered.shp", "EligibleAreas_polygons_filtered", "ogr")
if not restrLayer.isValid(): 
    print "Restrictions Layer Failed To Load"
QgsMapLayerRegistry.instance().addMapLayer(restrLayer)
cellsize = 1000 
xmin = (restrLayer.extent().xMinimum()) 
xmax = (restrLayer.extent().xMaximum()) 
ymin = (restrLayer.extent().yMinimum()) 
ymax = (restrLayer.extent().yMaximum()) 

extent = str(xmin)+ ',' + str(xmax)+ ',' +str(ymin)+ ',' +str(ymax) 
grid1 = "/home/usr/Desktop/trial/grid1.shp"
processing.runalg('qgis:vectorgrid', extent, cellsize, cellsize, 0, grid1)

and it works fine. When I create a standalone script and try to do the exact same thing outside of QGIS I have the following code:

import qgis
from osgeo import gdal
from osgeo import ogr

from gdalconst import *
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
from qgis.analysis import * 
from qgis.gui import *

import sys
import glob
import re 
import os, fnmatch
import numpy as np
import numpy.ma as ma
import math 

qgisprefix = '/usr'

# configure paths for QGIS 
os.environ['PATH'] = qgisprefix+'/bin'
os.environ['LD_LIBRARY_PATH'] = qgisprefix+'/lib'
sys.path.insert(0, qgisprefix+'/share/qgis/python')
sys.path.insert(1, qgisprefix+'/share/qgis/python/plugins')

# disable QGIS debug messages
os.environ['QGIS_DEBUG'] = '-1'

# configure QGIS paths
QgsApplication.setPrefixPath(qgisprefix, True)

# initalise QGIS (load providers)
QgsApplication.initQgis()

# create a new application object
# without this importing processing causes the following error:
# QPixmap: Must construct a QApplication before a QPaintDevice
app = QgsApplication([], True)

from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *
print Processing.getAlgorithm("qgis:vectorgrid")

#add the restrictions layer 
restrLayer = QgsVectorLayer("/home/usr/Desktop/trial/EligibleAreas_polygons_filtered.shp", "EligibleAreas_polygons_filtered", "ogr")
if not restrLayer.isValid(): 
   print "Restrictions Layer Failed To Load"
QgsMapLayerRegistry.instance().addMapLayer(restrLayer)

cellsize = 1000 

xmin = (restrLayer.extent().xMinimum()) 
xmax = (restrLayer.extent().xMaximum()) 
ymin = (restrLayer.extent().yMinimum()) 
ymax = (restrLayer.extent().yMaximum()) 

extent = str(xmin)+ ',' + str(xmax)+ ',' +str(ymin)+ ',' +str(ymax)  

grid1 = "/home/usr/Desktop/trial/grid1.shp"
processing.runalg('qgis:vectorgrid', extent, cellsize, cellsize, 0, grid1)

I get no output, so no grid1.shp. From print Processing.getAlgorithm("qgis:vectorgrid") I get: ALGORITHM: Vector grid EXTENT <ParameterExtent> STEP_X <ParameterNumber> STEP_Y <ParameterNumber> TYPE <ParameterSelection> OUTPUT <OutputVector>

so the needed algorithm from processing is found but for some reason the output layer is not created. I also checked the extent I get from the standalone script and it is the same as what I have in the python console (so the layer is loaded correctly). What could be the reason why I am not getting an output?

6
  • Probably an editing issue when posting but there's an extra double quotation mark in your 2nd last line: grid1 = ""/home/usr/Desktop/trial/grid1.shp".
    – Joseph
    Commented Jul 25, 2016 at 11:43
  • 1
    Sorry, it was an error when pasting the code. This is not the problem , but thanks anyway. I corrected the code above
    – ELD
    Commented Jul 25, 2016 at 13:43
  • Try replacing your last line processing.runalg('qgis:vectorgrid', extent, cellsize, cellsize, 0, grid1) with general.runalg('qgis:vectorgrid', extent, cellsize, cellsize, 0, grid1)
    – Joseph
    Commented Jul 25, 2016 at 13:46
  • 1
    I get the following error when I do general.runalg(.....): " 'NoneType' object has no attribute 'mapCanvas' See log for more details"
    – ELD
    Commented Jul 25, 2016 at 15:02
  • 2
    Try changing your import ordering according to this post: Why the order of imports matters in a standalone PyQGIS processing script?. In other words, put from PyQt4.QtGui import * and from PyQt4.QtCore import * after from qgis.gui import *. You could also try moving QgsApplication.initQgis() after app = QgsApplication([], True).
    – Joseph
    Commented Jul 25, 2016 at 15:07

1 Answer 1

2

Why it fails

qgis:vectorgrid algorithm is tied to QGIS application because it uses the iface object (see line 76 of the script). It depends on the Coordinate Reference System (CRS) from an existing map canvas. In the error you were getting ('NoneType' object has no attribute 'mapCanvas' See log for more details.) NoneType object is the iface object, which does not exist because QGIS is not running.

In a standalone scenario we don't usually have a map canvas nor an iface object available (although it is certainly possible, see for example this post).

Solution

Fortunately, QGIS offers an analog algorithm to create vector grids, it is called qgis:creategrid (also available in QGIS 2.8). The Create Grid algorithm is much better than qgis:vectorgrid because it doesn't depend on an existing map canvas. Instead, it receives the CRS of the output grid as an additional parameter. You could get such CRS from your restrLayer layer and call the algorithm in this way:

crs = restrLayer.crs().authid()
general.runalg('qgis:creategrid', 1, extent, cellsize, cellsize, crs, grid1 )

NOTE: The parameter 1 corresponds to a rectangular (polygon) grid. An example of the crs parameter may be 'EPSG:3115'.

I have tested the following standalone script using QGIS 2.14.8, I hope it also works for you (QGIS v2.8.6):

# Prepare the environment
import sys
from qgis.core import QgsApplication, QgsVectorLayer, QgsMapLayerRegistry
from PyQt4.QtGui import QApplication
app = QApplication([])
QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()

# Prepare processing framework
sys.path.append('/usr/share/qgis/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import general

restrLayer = QgsVectorLayer("/my/own/data/file.shp", "EligibleAreas_polygons_filtered", "ogr")
if not restrLayer.isValid():
    print "Restrictions Layer Failed To Load"
QgsMapLayerRegistry.instance().addMapLayer(restrLayer)
cellsize = 1000
xmin = (restrLayer.extent().xMinimum())
xmax = (restrLayer.extent().xMaximum())
ymin = (restrLayer.extent().yMinimum())
ymax = (restrLayer.extent().yMaximum())

extent = str(xmin)+ ',' + str(xmax)+ ',' +str(ymin)+ ',' +str(ymax)
grid1 = "/tmp/grid1.shp"
crs = restrLayer.crs().authid()
general.runalg('qgis:creategrid', 1, extent, cellsize, cellsize, crs, grid1 )

# Exit applications
QgsApplication.exitQgis()
QApplication.exit()

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.