0

I am trying to make hub lines between two vector files. I succeed manually to do that (in QGIS 3.0) and in a PyQGIS 2.18. But my code doesn't work in PyQGIS 3.0. Here it is:

output = '/home/user/Desktop'
grid = QgsVectorLayer('/home/Desktop/grid.shp',
                             "cells", "ogr")

sys.path.append('/usr/share/qgis/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()
import processing

processing.algorithmHelp("qgis:hublines")
processing.run('qgis:hublines', grid, 'Province', cities, 'Province', output)

With line processing.algorithmHelp I get that hub lines doesn't exist. But it does in qgis 3.0. Also, I tried to see the list of algorithms name with processing.alglist(), but without success.

UPDATE: I tried now with 'native:hublines' like underdark said. And now I can find algorithm, but it still doesn't work and I dont have error message. Here is my new code:

output = '/home/user/Desktop/output.shp'
cities = QgsVectorLayer('path to the cities',
                             "cities", "ogr")
grid_data = QgsVectorLayer('path to the grid',"grid", "ogr")

sys.path.append('/usr/share/qgis/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()
import processing

QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())

processing.algorithmHelp("native:hublines")
params = {
    'HUBS': grid_data,
    'HUB_FIELD': 'Province',
    'SPOKES': cities,
    'SPOKE_FIELD': 'Province',
    'OUTPUT': output
}

processing.run('native:hublines', params)
  • Did you read this post already? gis.stackexchange.com/questions/279874/… – Germán Carrillo Jul 1 '18 at 16:13
  • Yes, I did, but still, I cant find hublines. :/ – Neven Jul 1 '18 at 18:08
  • When I type processing.algorithmHelp("qgis:hublines") I get: Algorithm "qgis:hublines" not found But it does exist in qgis 3.0 and this code work in pyqgis 2.0. So, I suppose that is renamed or something. But I can find it. :/ – Neven Jul 1 '18 at 18:16
  • In the dev version it's "native:hublines" – underdark Jul 1 '18 at 19:56
  • Thank you for the tip. But still, it doesn't work. I edited my question. – Neven Jul 1 '18 at 21:46
3

You already have a working script, so I'll make this answer more of a troubleshooting workflow for getting an algorithm to work in pyqgis (in a standalone QGIS application). As you will see from the steps, the process is to make sure it works in the simplest case and add to the complexity in each step.

1. Make sure the algorithm works

Run the algorithm from the Processing Toolbox. Read the documentation and make sure that it produces the expected results from the input data you intend to use. Testing in Processing Toolbox Working algorithm

2. Check the help file for the algorithm

Open the Python Console (Ctrl+Alt+P) and run processing.algorithmHelp("<algorithm ID>") to check the algorithm help file. You can get the algorithm help file from the Processing Toolbox history panel (Ctrl+Alt+H) - it would be the most recently run algorithm. In this case you would run processing.algorithmHelp("native:hublines"). Take note of the input and output parameters, and their accepted data types. From the help file you can see that the HUBS and SPOKES input parameters can be either a str for layer source or a QgsVectorLayer (among other options). HUB_FIELD and SPOKE_FIELD can be either a str or QgsProperty. OUTPUT can be various things, including a str for 'destination vector file'. Note that it does not list a destination directory as an output option.

3. Check that it works from the Python Console

First I'll usually just copy the algorithm instruction from the Processing Toolbox history into the Python Console and make as few changes as possible to get it to run. In this case the instruction is:

processing.run("native:hublines",{
    'HUBS':'C:/GIS/hublines/hubs.shp',
    'HUB_FIELD':'id',
    'HUB_FIELDS'[],
    'SPOKES':'C:/GIS/hublines/spokes.shp',
    'SPOKE_FIELD':'hubId',
    'SPOKE_FIELDS':[],
    'OUTPUT':'memory:'
    })

There are a couple of things to check. Firstly, if you're in Windows, python often has problems with the path. It's safest to check that the paths use forward slash (/), not backslash (\). In this case they do, so that's fine. You can actually run the command as is, and it will work, but you won't be able to check the output. You could either add the output to a variable and load that as a layer, or send the output to a file and check that. In your example you were doing the latter, so we'll take that approach. We know from the previous step that a path to an output shapefile is an acceptable output parameter, so our instruction becomes:

processing.run("native:hublines",{
    'HUBS':'C:/GIS/hublines/hubs.shp',
    'HUB_FIELD':'id',
    'HUB_FIELDS'[],
    'SPOKES':'C:/GIS/hublines/spokes.shp',
    'SPOKE_FIELD':'hubId',
    'SPOKE_FIELDS':[],
    'OUTPUT':'C:/GIS/hublines/output.shp'
    })

If you run this and check the output directory, you should see output.shp. You can load this in QGIS and check that it is what you expect. If you get errors at this stage, check the error message in the Python Console for clues as to what the problem could be, and be sure to also check the Processing log (make sure that it's enabled with View > Panels > Log Messages).

Processing log

4. Generalise to suit your needs

Now you can generalise your to meet the broader needs of your script/standalone program. You might need your inputs to be added via a file picker, or to be in a different format. Now that you know you have a working base instruction, you can make the necessary changes, one at a time so that you can isolate any errors that crop up. You could move this to a script or standalone program, but I find it's still safer to test this in the Python Console. So your final instructions might be:

output = 'C:/GIS/hublines/output.shp'
hubFile = 'C:/GIS/hublines/hubs.shp'
spokeFile = 'C:/GIS/hublines/spokes.shp'
hubs = QgsVectorLayer(hubFile, "hubs", "ogr")
spokes = QgsVectorLayer(spokeFile, "spokes", "ogr")
params = {
    'HUBS':hubs,
    'HUB_FIELD':'id',
    'SPOKES':spokes,
    'SPOKE_FIELD':'hubId',
    'OUTPUT': output
    }
result = processing.run("native:hublines", params)

5. Add additional code to get it to work in your standalone application

Only at this point should you move your code into a standalone application. This question has some great advice on what is required to get it working in standalone mode:

Using QGIS3 Processing algorithms from standalone PyQGIS scripts (outside of GUI)

I haven't tested this in standalone mode, so I won't show what the final code would be, but hopefully this helps with the workflow to get there.

  • I think its really large and detailed answer and it would help a lot of people. Thank you, man, once again. Greetings. :) – Neven Jul 3 '18 at 10:51

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.