QGIS Planet

Getting Paths with PyQGIS

When writing plugins or scripts it is often necessary to get information about the paths QGIS is using. For example, if we are writing a plugin that uses Python templates to create output based on user actions, we need to know the path to our installed plugin so we can find the templates. Fortunately the API provides an easy way to get at the information; here are a few examples:

  • QgsApplication.pluginPath(): location of core plugins
  • QgsApplication.prefixPath(): location where QGIS is installed
  • QgsApplication.qgisSettingsDirPath(): location of user settings
  • QgsApplication.iconsPath(): location of icons used in QGIS

We can get a summary of some paths used in QGIS using showSettings:

print QgsApplication.showSettings()
Application state:
QGIS_PREFIX_PATH env var:
Prefix:               /dev1/apps/qgis
Plugin Path:          /dev1/apps/qgis/lib/qgis/plugins
Package Data Path:    /dev1/apps/qgis/share/qgis
Active Theme Name:    default
Active Theme Path:    :/images/themes/default/
Default Theme Path:   :/images/themes/default/
SVG Search Paths:     /dev1/apps/qgis/share/qgis/svg/
                      /home/gsherman/.qgis2//svg/
User DB Path: /dev1/apps/qgis/share/qgis/resources/qgis.db

These paths are from my development install of QGIS on a Linux box; yours will be different.

The showSettings method is not really useful in a script or plugin since it returns a string containing line returns and tab characters. It’s mainly useful for debugging and development.

From within a plugin, you can get its path using

1
2
3
import os

plugin_path = os.path.dirname(os.path.realpath(__file__))

From the PyQGIS Programmers Guide

Welcome to New QGIS PSC Members

Nominations for the QGIS PSC closed at 00:00 UTC on August 25, 2013 [1].

With only one nominee for each role, the PSC unanimously moved to accept each without election.

The QGIS PSC welcomes new members Anita Graser, Richard Duivenvoorde, and Jürgen Fischer.

The PSC is now composed of:

  • Chair - Gary Sherman
  • Community Advisor - Otto Dassau
  • Design Advisor - Anita Graser
  • Financial and Marketing Advisor - Paolo Cavallini
  • Infrastructure Manager - Richard Duivenvoorde
  • Release Manager - Jürgen Fischer
  • Technical Advisor - Marco Hugentobler
  • Testing/QA Manager - Tim Sutton

The new PSC members begin their terms immediately.

[1] http://hub.qgis.org/projects/quantum-gis/wiki/Call_for_Nominations_August_2013

QGIS PSC Call for Nominations

The QGIS Project Steering Committee (PSC) has announced a call for nominations to fill three vacant positions:

  • Design Advisor
  • Infrastructure Manager
  • Release Manager

Nominations are open until August 24, 2013. For details on the PSC, vacancies, and how to nominate someone, see:

http://hub.qgis.org/projects/quantum-gis/wiki/Call_for_Nominations_August_2013

QGIS Back in the Day

Do you remember this?

QGIS of Yesteryear

If so, you’ve been using QGIS a long time…

  • OGR and PostGIS support
  • No raster support
  • Three widgets on the Symbology tab
  • No symbology in the legend

But you could use it handily on a 640x480 display.

New Version of the QGIS Script Runner Plugin

The Script Runner plugin allows you to manage and execute a collection of scripts in QGIS to automate tasks and perform custom processing.

Script_Runner

Version 0.6 of Script Runner has been released and includes these changes:

  • Arguments can be passed to a script using keyword arguments
  • Script output is logged to the Script Runner window
  • Script output can be logged to disk
  • Preferences dialog allows control of output and logging options
  • Exceptions in scripts are displayed without interfering with console/logging output
  • Context menu (right-click) to access script functions
  • Edit script function uses system default editor or one you specify in preferences

For a basic introduction to Script Runner see this post: Script Runner: A Plugin to Run Python Scripts in QGIS

Working with Scripts

Adding Scripts

To run a script, you must add it to Script Runner using the Add Script tool on the toolbar. Select the script from the file dialog to add it to a list in the left panel. The list of scripts is persisted between uses of QGIS.

Running a Script

To run a script, select it from your list of scripts and click the Run tool. Output from the script will be displayed in the Script Runner console

Remove a Script

You can remove a script by selecting it from the list and clicking the Remove Script tool. This just removes it from the list; it does nothing to the script file on disk.

Script Information

Clicking the Info tool will populate the Info and Source tabs in the panel on the right. The Info tab contains the docstring from your module and then a list of the classes, methods, and functions found in the script. Having a proper docstring at the head of your script will help you determine the purpose of script.

At version 0.6 the Info tool is only needed if you have disabled automatic display of info/source (see Preferences).

Viewing the Source

You can view the source of the script on the Source tab. This allows you to quickly confirm that you are using the right script and it does what you think it will.

New Features

Version 0.6 implements a number of new features.

Passing Arguments to a Script

You can pass arguments to your script using keywords. Your run_script function must have two arguments:

1
  def run_script(iface, **args):

Running your script is done using the Run script with arguments tool. This prompts you to enter your argument(s) in a key=value format:

Argument_dialog

All strings must be quoted and multiple arguments should be separated by a comma.

When your script is run, the arguments are contained in args, which is a Python dict. In the example above, you could access them like this:

1
2
  my_path = args['path']
  my_buffer_size = args['buffer_size']

Scripts that accept keyword arguments are displayed in the list with two asterisks appended to their name:

arg_scripts

See Passing Arguments for a complete example.

Output Console

All print statements in your script will be directed to the Script Runner console. In addition, any tracebacks from exceptions will be displayed there, as well as in a popup dialog.

Printing messages to the console can be useful for both development and status updates in long running scripts. You can clear the console using the Clear Console tool. There is also an option in Preferences to clear the console each time a script is run.

Logging to Disk

You can choose to log everything that goes to the output console to disk. Use the Preferences dialog to setup the directory where the scriptrunner.log will be written.

Editing a Script

You can open the selected script in an external editor by right-clicking on it and choosing Edit script in external editor from the popup menu. The default system editor for .py files will be used to open the script. In Preferences, you can specify a different editor by entering the full path to the executable.

Preferences

The Preferences dialog allows you to set the following options:

Script_Runner_Preferences

Script Examples

Here are three script examples: a simple script that has only a run_script function, one that uses a Python class, and one that passes keyword arguments.

Simple Script

This simple script contains only a run_script function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    """ Load a layer and change the fill color to red. """
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from qgis.core import *
    from qgis.gui import *


    def run_script(iface):
        mapreg = QgsMapLayerRegistry.instance()
        mapreg.removeAllMapLayers()
        wb = QgsVectorLayer('/data/world_borders.shp', 'world_borders', 'ogr')
        mapreg.instance().addMapLayer(wb)
        renderer = wb.rendererV2()
        symb = renderer.symbol()
        symb.setColor(QColor(Qt.red))
        wb.setCacheImage(None)
        wb.triggerRepaint()
        iface.refreshLegend(wb)

When executed by Script Runner, the script removes any layers currently on the map, then loads the world_borders shapefile, sets its fill color to red, and updates the map canvas and the legend. The run_script function does all the work. You could expand this script by adding additional functions that are called from run_script.

A Script with a Class

This script uses a class that is initialized from the run_script function to load some layers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    """Load all shapefiles in a given directory.  """
    from glob import glob
    from os import path

    from qgis.core import *
    from qgis.gui import *
    import qgis.utils

    class Loader:
        def __init__(self, iface):
            """Initialize using the qgis.utils.iface
            object passed from the console.
            """

            self.iface = qgis.utils.iface

        def load_shapefiles(self, shp_path):
            """Load all shapefiles found in shp_path"""
            print "Loading shapes from %s" % path.join(shp_path, "*.shp")
            shps = glob(path.join(shp_path, "*.shp"))
            for shp in shps:
                (shpdir, shpfile) = path.split(shp)
                print "Loading %s" % shpfile
                lyr = QgsVectorLayer(shp, shpfile, 'ogr')
                QgsMapLayerRegistry.instance().addMapLayer(lyr)

    def run_script(iface):
        ldr = Loader(iface)
        print "Loading all shapefiles in /qgis_sample_data/vmap0_shapefiles"
        ldr.load_shapefiles('/qgis_sample_data/vmap0_shapefiles')

In this example, the run_script function creates an instance (ldr) of a class named Loader that is defined in the same source file. It then calls a method in the Loader class named load_shapefiles to do something useful—in this case, load all the shapefiles in a specified directory.

Passing Arguments

This script illustrates passing an argument (a path) to load all shapefiles in a directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    """Load all shapefiles in a given directory."""
    from glob import glob
    from os import path
    from qgis.core import *
    from qgis.gui import *
    import qgis.utils


    class Loader:
        def __init__(self, iface):
            """Initialize using the qgis.utils.iface 
            object passed from the console.
 
            """
            self.iface = qgis.utils.iface

        def load_shapefiles(self, shp_path):
            """Load all shapefiles found in shp_path"""
            print "Loading shapes from %s" % path.join(shp_path, "*.shp")
            shps = glob(path.join(shp_path, "*.shp"))
            for shp in shps:
                (shpdir, shpfile) = path.split(shp)
                print "Loading %s" % shpfile
                lyr = QgsVectorLayer(shp, shpfile, 'ogr')
                QgsMapLayerRegistry.instance().addMapLayer(lyr)

    def run_script(iface, **args):
        ldr = Loader(iface)
        print "Loading all shapefiles in %s" % args['path']
        ldr.load_shapefiles(args['path'])

Lines 29 and 30 illustrate using the passed argument to print a message to the console and call the method to add the shapefiles to the map.

Final Word

The script examples are minimalistic—they don’t do error checking in a number of places, such as checking to see if a QgsVectorLayer is valid or if needed arguments were actually passed to the script. Don’t take the scripts as examples of complete, solid code.

Comments on this post are welcome, as are bug reports. The link to the bug tracker for Script Runner can be found in the About box, along with the link to the code repository and my email address.

Littering Your Python Path: The Road to Destruction

Well not quite destruction, but a bit of hair pulling…

While working on an update to the Plugin Builder, I encountered a small problem. The Plugin Builder displays the version number in the title bar of its main window. After bumping the version number to 1.8.4 in all the requisite places, it still showed 1.8.3 when testing.

Using grep on all the source files revealed no instance of 1.8.3 in any file.

The title of this post has probably already given you the answer—I had on old version of the plugin in my Python path. The old plugin was getting picked up first when QGIS loaded.

Here’s what happened:

I previously had the old version in my plugin directory (~/.qgis/python/plugins), but moved it up one level so I could test the new one. It turns out this directory is also in the Python path when you load QGIS, a fact that escaped my attention. Using the Python Console in QGIS to display the path revealed the problem. Once I moved the version 1.8.3 plugin out of the way, my new version happily loaded.

The other pitfall you can encounter is if you use the QGIS_PLUGINPATH environment variable during your development. This allows you to specify another directory QGIS will also search for plugins. If you have multiple versions of the same plugin in any of these directories you may be setting yourself up for conflict.

The moral of the story:

Don’t stash old plugins in .qgis/python or you may send yourself down the wrong path…

QGIS Gains a Gold Sponsor

The Quantum GIS (QGIS) project is happy to announce that the Asia Air Survey Co., Ltd (AAS), a Japanese international consulting company, has become a Gold Sponsor. AAS has committed to providing 9,000 EUR (~$11,000 US) each of three years, beginning in November 2012.

The AAS sponsorship is yet another indication that QGIS is a mature and stable project which continues to provide innovative open source GIS software.

The QGIS Project Steering Committee (PSC) wishes to thank AAS for their continuing commitment. These funds will help further the development of QGIS, in part by allowing face to face developer meetings and code sprints (also known as hackfests).

The QGIS project has always relied on volunteers and community involvement. If your organization would like to become a sponsor, please contact the Finances and Marketing Manager: cavallini[at]faunalia.it.

For more information on sponsorship levels, please see the QGIS Sponsorship page.

QGIS Is Ten Years Old

It was ten years ago, on July 19, 2002, that QGIS was officially unveiled. That first release was primitive, supporting only PostGIS layers and having little in the way of navigation controls. Invoking the open source mantra of “release early and release often,” I announced it on Freshmeat and waited.

Slowly it began to attract attention—not all of it positive. Some questioned why I was starting a new open source GIS project when there were others I could join. Others were interested in signing up to help. In those early days, getting one or two messages a week on the one and only mailing list was exciting. It was a slow start, but as more people joined the project, QGIS began to grow exponentially.

Over the years, we added support for additional vector formats, rasters, on the fly projection, map composition, Python scripting, and more features than I can possibly list.

Today QGIS is used all over the world, in a myriad of disciplines. If you find QGIS useful, please consider supporting the project through direct involvement or a sponsorship.

I founded QGIS; the community built it. Here’s to many more successful years as one of the leading open source GIS projects.

what's new in qgis plugins

Here’s a summary of recent additions and updates to plugins in the QGIS repository.

  • FlowMapper (0.1.1) - Generates flow lines between discreet nodes for depicting spatial interaction data (e.g. migration).
  • Query By Example (0.2) - Select features by location.
  • Item Browser (1.6.0) - Browse a multiple selection with auto-zooming to feature and an option to open feature form.
  • Custom Launcher (1.1.0) - Customize your own actions to launch your preferred apps or commands within QGIS.
  • Profile Tool (3.3.1) - Plots terrain profile
  • qSearch (1.3.0) - Produces a friendly interface to perform and save searches in a layer.
  • Quick Finder (1.0.0) - Dockable dialog to find a feature by its ID in a layer.
  • SEXTANTE (1.0.3) - SEXTANTE for QGIS
  • Link It (1.1.1) - Link It is a QGIS plugin to link a feature to another. By clicking on map, the plugin will then automatically save the feature’s ID in the appropriate field defined by the user. This plugin requires ItemBrowser.
  • QuickMultiAttributeEdit (0.8) - QuickMultiAttributeEdit plugin provides a very quick and handy way to update a feature for the selected attributes into the current/active layer.

Installing Plugins

To install any of these plugins:

  1. Open the Python plugin installer: Plugins->Fetch Python Plugins
  2. Check to see if you have the new Official repository in your list of plugins by clicking on Repositories tab. The URL is http://plugins.QGIS.org/plugins/plugins.xml.
  3. If the new repository isn’t in the list, add it by clicking the Add button. Give it a name and insert the URL http://plugins.QGIS.org/plugins/plugins.xml
  4. Some plugins may be flagged experimental. Make sure you have allowed experimental plugins on the Options tab of the plugin installer
  5. Click on the Plugins tab
  6. Select the desired plugin from the list and click Install

QGIS Plugin of the Week: qNote

This week we look at a newly arrived plugin named qNote. This plugin allows you to create a note and store it in a QGIS project file. When the project is loaded, the note is restored and can be viewed in the qNote panel.

This little plugin provides a way to attach metadata to a project. Things you might want to include in a note are:

  • Content of the project
  • Purpose
  • Area of interest
  • Where the data came from
  • Who created the project

This information can be helpful when sharing a project or when you forget what you did six months after the fact.

Here is a screenshot showing qNote in action:

qNote Plugin

Installing the Plugin

To install the plugin:

  1. Open the Python plugin installer: Plugins->Fetch Python Plugins
  2. Check to see if you have the new Official repository in your list of plugins by clicking on Repositories tab. The URL is http://plugins.qgis.org/plugins/plugins.xml.
  3. If you have it, skip to step 6. If the new repository isn’t in the list, add it by clicking the Add button. Give it a name and insert the URL http://plugins.qgis.org/plugins/plugins.xml
  4. qNote is currently flagged experimental. Make sure you have allowed experimental plugins on the Options tab of the plugin installer
  5. Click on the Plugins tab
  6. Enter qNote in the Filter box
  7. Select the qNote plugin and click Install

You can control the visiblity of the qNote panel from the View->Panels menu.

The README for the plugin can be viewed on the qNote GitHub page.

Getting Support for QGIS

The QGIS project has a number of support channels. Like many open source projects, these are loosely coupled. Recently the forum was made read-only and this has prompted a number of questions and concerns about how to receive support. This post outlines the ways in which you can get your questions answered.

Home Page

The QGIS home page has links to all the documentation and community resources. The navigation panel on the left has links to both the Community resources and the manual.

To quickly see links to all the resources, click the Need Help? button on the home page. You’ll find links to:

  • User Manual
  • Wiki
  • Mailing Lists
  • StackExchange

StackExchange

GIS StackExchange allows you to ask questions and get answers from a wide range of users and experts in the GIS realm. If you have a question specific to QGIS, tag it with the qgis keyword, otherwise use an appropriate tag.

Since StackExchange is question-based, you should not ask multiple questions in a single posting.

Also, make sure you flag the question as answered once you receive a satisfactory response.

Mailing Lists

The QGIS project maintains a number of mailing lists. For most people, the two of interest are qgis-user and qgis-developer:

  • qgis-user: Use this list for discussion of QGIS in general, as well as specific questions regarding its installation and use.

  • qgis-developer: Used for discussion of development issues, plans, and features. If you plan to contribute code or patches to the project or write your own Python plugins, you’ll find this list useful.

If you just want to browse or search the mailing lists without subscribing, they are available on Nabble.

IRC

IRC (Internet Relay Chat) is a method of communication used widely by open source communities. On any given day you will find both developers, contributors, and users monitoring the #qgis channel on irc.freenode.net.

To use IRC, you’ll need a client application for your computer, tablet, or smartphone.

Here are a couple of guidelines for using the #qgis channel:

  1. If you have a question, don’t ask if you can ask, just state your question
  2. If no one responds, it’s not because they hate you or think you are a dullard, but are busy or don’t know the answer to your question

The QGIS IRC community is very friendly and helpful. Give it a try.

Search the Internet

All of the web resources for the QGIS project are indexed by search engines. Searching for your specific question can often lead you to the answer you are looking for, whether it be in a blog, on a mailing list, or the QGIS web site itself.

In addition to your favorite search engine, try DuckDuckGo for more targeted search results.

Shameless Plug

If you need a good introduction to open source GIS applications, tools, and scripting, take a look at my book.

QGIS Forum Is Closed—What Do You Think?

The forum (http://forum.qgis.org) has been closed for new registrations and marked read-only. Users have been encouraged to use http://gis.stackexchange.com instead.

If you have an thoughts on the closure, good, bad, or otherwise, please comment.

QGIS Forum Is Closed---What Do You Think?

The forum (http://forum.qgis.org) has been closed for new registrations and marked read-only. Users have been encouraged to use http://gis.stackexchange.com instead.

If you have an thoughts on the closure, good, bad, or otherwise, please comment.

Script Runner: A Plugin to Run Python Scripts in QGIS

Following up on my last post, Running Scripts in the Python Console, I created a plugin to simplify running scripts:

The Script Runner plugin allows you to add your scripts to a list so they are readily available. You can then run them to automate QGIS tasks and have full access to the PyQGIS API. In addition, you can view information about the classes, methods, and functions in your module as well as browse the source:

In order for your script to work with ScriptRunner it has to implement a single function as an entry point. Here is some additional information from the Help tab of the plugin:

Requirements

In order for Script Runner to execute your script you must define a run_script function that accepts a single argument. This is the standard entry point used by Script Runner. A reference to the qgis.utils.iface object will be passed to your run_script function. You don’t have to use the iface object in your script but your run_script function must accept it as an argument.

Here is an example of a simple run_script function:

    def run_script(iface):
        ldr = Loader(iface)
        ldr.load_shapefiles('/vmap0_shapefiles')

In this example, the run_script creates an instance (ldr) of a class named Loader that is defined in the same source file. It then calls a method in the Loader class named load_shapefiles to do something useful—in this case, load all the shapefiles in a specified directory.

Alternatively, you could choose not to use classes and just do everything within the run_script function, including having it call functions in the same script or others you might import. The important thing is to be sure you have defined a run_script function. If not, Script Runner won’t load your script.

Working with Scripts

To run a script, you must add it to Script Runner using the Add Script tool on the toolbar. This will add it to a list in the left panel. This list of scripts is persisted between uses of QGIS. You can remove a script using the Remove Script tool. This just removes it from the list; it does nothing to the script file on disk.

Once you have a script loaded, you can click the Script Info tool to populate the Info and Source tabs in the panel on the right. The Info tab contains the docstring from your module and then a list of the classes, methods, and functions found in the script. Having a proper docstring at the head of your script will help you determine the puprose of script.

You can view the source of the script on the Source tab. This allows you to quickly confirm that you are using the right script and it does what you think it will.

Installing the Plugin

To install the plugin:

  1. Open the Python plugin installer: Plugins->Fetch Python Plugins
  2. Check to see if you have the new Official repository in your list of plugins by clicking on Repositories tab. The URL is http://plugins.qgis.org/plugins/plugins.xml.
  3. If you have it, skip to step 5. If the new repository isn’t in the list, add it by clicking the Add button. Give it a name and insert the URL http://plugins.qgis.org/plugins/plugins.xml
  4. Click on the Plugins tab
  5. Enter scriptrunner in the Filter box
  6. Select the ScriptRunner plugin and click Install

ScriptRunner adds an entry to the Plugins menu as well as a tool on the Plugins toolbar: . Click it and you are off and running.

Script Runner: A Plugin to Run Python Scripts in QGIS

Following up on my last post, Running Scripts in the Python Console, I created a plugin to simplify running scripts:

The Script Runner plugin allows you to add your scripts to a list so they are readily available. You can then run them to automate QGIS tasks and have full access to the PyQGIS API. In addition, you can view information about the classes, methods, and functions in your module as well as browse the source:

In order for your script to work with ScriptRunner it has to implement a single function as an entry point. Here is some additional information from the Help tab of the plugin:

Requirements

In order for Script Runner to execute your script you must define a run_script function that accepts a single argument. This is the standard entry point used by Script Runner. A reference to the qgis.utils.iface object will be passed to your run_script function. You don’t have to use the iface object in your script but your run_script function must accept it as an argument.

Here is an example of a simple run_script function:

1
2
3
    def run_script(iface):
        ldr = Loader(iface)
        ldr.load_shapefiles('/vmap0_shapefiles')

In this example, the run_script creates an instance (ldr) of a class named Loader that is defined in the same source file. It then calls a method in the Loader class named load_shapefiles to do something useful—in this case, load all the shapefiles in a specified directory.

Alternatively, you could choose not to use classes and just do everything within the run_script function, including having it call functions in the same script or others you might import. The important thing is to be sure you have defined a run_script function. If not, Script Runner won’t load your script.

Working with Scripts

To run a script, you must add it to Script Runner using the Add Script tool on the toolbar. This will add it to a list in the left panel. This list of scripts is persisted between uses of QGIS. You can remove a script using the Remove Script tool. This just removes it from the list; it does nothing to the script file on disk.

Once you have a script loaded, you can click the Script Info tool to populate the Info and Source tabs in the panel on the right. The Info tab contains the docstring from your module and then a list of the classes, methods, and functions found in the script. Having a proper docstring at the head of your script will help you determine the puprose of script.

You can view the source of the script on the Source tab. This allows you to quickly confirm that you are using the right script and it does what you think it will.

Installing the Plugin

To install the plugin:
  1. Open the Python plugin installer: Plugins->Fetch Python Plugins
  2. Check to see if you have the new Official repository in your list of plugins by clicking on Repositories tab. The URL is http://plugins.qgis.org/plugins/plugins.xml.
  3. If you have it, skip to step 5. If the new repository isn’t in the list, add it by clicking the Add button. Give it a name and insert the URL http://plugins.qgis.org/plugins/plugins.xml
  4. Click on the Plugins tab
  5. Enter scriptrunner in the Filter box
  6. Select the ScriptRunner plugin and click Install

ScriptRunner adds an entry to the Plugins menu as well as a tool on the Plugins toolbar:

Click it and you are off and running.

QGIS: Running Scripts in the Python Console

The QGIS Python console is great for doing one-off tasks or experimenting with the API. Sometimes you might want to automate a task using a script, and do it without writing a full blown plugin. Currently QGIS does not have a way to load an arbitrary Python script and run it.[1] Until it does, this post illustrates a way you can create a script and run it from the console.

There are a couple of requirements to run a script in the console:

  1. The script must be in your PYTHONPATH

  2. Just like a QGIS plugin, the script needs a reference to qgis.utils.iface

Setting up the Environment

By default, the Python path includes the .qgis/python directory. The location depends on your platform:

  • Windows: in your home directory under .qgis\python. For example, C:\Documents and Settings\gsherman.qgis\python

  • Linux and OS X: $HOME/.qgis/python

To see what is in your PYTHONPATH you can do the following in QGIS Python console:

1
2
    import sys
    sys.path

While you could use the .qgis\python directory for your custom scripts, a better way is to create a directory specifically for that purpose and add that directory to the PYTHONPATH environment variable. On Windows you can do this using the Environment Variables page in your system properties:

On Linux or OS X, you can add it to your .bash_profile, .profile, or other login script in your home directory:

export PYTHONPATH=$PYTHONPATH:/home/gsherman/qgis_scripts

Writing the Script

With the environment set, we can create scripts to automate QGIS tasks and run them from the console. For this example, we will use a simple script to load all shapefiles in a specified directory. There are a couple of ways to do this:

  1. Write a simple script with a function that accepts qgis.utils.iface as an argument, along with a path to the shapefiles

  2. Create a Python class that uses an init method to store a reference to the iface object and then add methods to do the work

We will use the latter approach because it is more flexible and allows us to initialize once and then call methods without having to pass the iface object each time.

The script looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    #!/usr/bin/env Python
    """Load all shapefiles in a given directory.
      This script (loader.py) runs from the QGIS Python console.
      From the console, use:
        from loader import Loader
        ldr = Loader(qgis.utils.iface)
        ldr.load_shapefiles('/my/path/to/shapefile/directory')
    
      """
    from glob import glob
    from os import path

    class Loader:
        def __init__(self, iface):
            """Initialize using the qgis.utils.iface 
            object passed from the console.
            
            """
            self.iface = iface

        def load_shapefiles(self, shp_path):
            """Load all shapefiles found in shp_path"""
            print "Loading shapes from %s" % path.join(shp_path, "*.shp")
            shps = glob(path.join(shp_path, "*.shp"))
            for shp in shps:
                (shpdir, shpfile) = path.split(shp)
                self.iface.addVectorLayer(shp, shpfile, 'ogr' )

Running the Script

To open the console use the Plugins->Python Console menu item.

The comment at the head of the script explains how to use it.

First we import the Loader class from the script file (named loader.py). This script resides in the qgis_scripts directory that is our PYTHONPATH.

1
    from loader import Loader

We then create an instance of Loader, passing it the reference to the iface object:

1
    ldr = Loader(qgis.utils.iface)

This creates the Loader object and calls the init method to initialize things.

Once we have an instance of Loader we can load all the shapefiles in a directory by calling the load_shapefiles method, passing it the full path to the directory containing the shapefiles:

1
    ldr.load_shapefiles('/home/gsherman/qgis_sample_data/vmap0_shapefiles')

The load_shapefiles method uses the path to get a list of all the shapefiles and then adds them to QGIS using addVectorLayer.

Here is the result, rendered in the random colors and order that the shapefiles were loaded:

Some Notes

  • When testing a script in the console you may need to reload it as you make changes. This can be done using reload and the name of the module. In our example, reload(loader) does the trick.

  • You can add more methods to your class to do additional tasks

  • You can create a “driver” script that accepts the iface object and then initializes additional classes to do more complex tasks

[1]. I have plans on the drawing board to implement this feature.

QGIS: Running Scripts in the Python Console

The QGIS Python console is great for doing one-off tasks or experimenting with the API. Sometimes you might want to automate a task using a script, and do it without writing a full blown plugin. Currently QGIS does not have a way to load an arbitrary Python script and run it1. Until it does, this post illustrates a way you can create a script and run it from the console.

There are a couple of requirements to run a script in the console:

  1. The script must be in your PYTHONPATH
  2. Just like a QGIS plugin, the script needs a reference to qgis.utils.iface

Setting up the Environment

By default, the Python path includes the .qgis/python directory. The location depends on your platform:

  • Windows: in your home directory under .qgis\python. For example, C:\Documents and Settings\gsherman\.qgis\python
  • Linux and OS X: $HOME/.qgis/python

To see what is in your PYTHONPATH you can do the following in QGIS Python console:

import sys
sys.path

While you could use the .qgis\python directory for your custom scripts, a better way is to create a directory specifically for that purpose and add that directory to the PYTHONPATH environment variable. On Windows you can do this using the Environment Variables page in your system properties:

On Linux or OS X, you can add it to your .bash_profile, .profile, or other login script in your home directory:

export PYTHONPATH=$PYTHONPATH:/home/gsherman/qgis_scripts

Writing the Script

With the environment set, we can create scripts to automate QGIS tasks and run them from the console. For this example, we will use a simple script to load all shapefiles in a specified directory. There are a couple of ways to do this:

  1. Write a simple script with a function that accepts qgis.utils.iface as an argument, along with a path to the shapefiles
  2. Create a Python class that uses an __init__ method to store a reference to the iface object and then add methods to do the work

We will use the latter approach because it is more flexible and allows us to initialize once and then call methods without having to pass the iface object each time.

The script looks like this:

#!/usr/bin/env Python
"""Load all shapefiles in a given directory.
  This script (loader.py) runs from the QGIS Python console.
  From the console, use:
    from loader import Loader
    ldr = Loader(qgis.utils.iface)
    ldr.load_shapefiles('/my/path/to/shapefile/directory')
 
  """
from glob import glob
from os import path
 
class Loader:
    def __init__(self, iface):
        """Initialize using the qgis.utils.iface 
        object passed from the console.
 
        """
        self.iface = iface
 
    def load_shapefiles(self, shp_path):
        """Load all shapefiles found in shp_path"""
        print "Loading shapes from %s" % path.join(shp_path, "*.shp")
        shps = glob(path.join(shp_path, "*.shp"))
        for shp in shps:
            (shpdir, shpfile) = path.split(shp)
            self.iface.addVectorLayer(shp, shpfile, 'ogr' )

Running the Script

To open the console use the Plugins->Python Console menu item.

The comment at the head of the script explains how to use it.

First we import the Loader class from the script file (named loader.py). This script resides in the qgis_scripts directory that is our PYTHONPATH.

from loader import Loader

We then create an instance of Loader, passing it the reference to the iface object:

ldr = Loader(qgis.utils.iface)

This creates the Loader object and calls the __init__ method to initialize things.

Once we have an instance of Loader we can load all the shapefiles in a directory by calling the load_shapefiles method, passing it the full path to the directory containing the shapefiles:

ldr.load_shapefiles('/home/gsherman/qgis_sample_data/vmap0_shapefiles')

The load_shapefiles method uses the path to get a list of all the shapefiles and then adds them to QGIS using addVectorLayer.

Here is the result, rendered in the random colors and order that the shapefiles were loaded:

Some Notes

  • When testing a script in the console you may need to reload it as you make changes. This can be done using reload and the name of the module. In our example, reload(loader) does the trick.
  • You can add more methods to your class to do additional tasks
  • You can create a “driver” script that accepts the iface object and then initializes additional classes to do more complex tasks

1. I have plans on the drawing board to implement this feature.

Using the QGIS Raster Calculator

The raster calculator allows you to perform mathematical operations on each cell in a raster. This can be useful for converting and manipulating your rasters. Operators include:

  • Mathematical (+, -, *, /)
  • Trigonometric (sin, cos, tan, asin, acos, atan)
  • Comparison (<, >, =, <=, >=)
  • Logical (AND, OR)

To perform operations on a raster or rasters, they must be loaded in QGIS. The raster calculator is accessed from the Raster menu and brings up the dialog:

Let’s look a few examples.

Simple Mathematical Calculation

Doing a simple calculation is easy. In this example we have a Digital Elevation Model (ancc6) loaded in QGIS. The DEM contains elevations for a 1:63,360 quadrangle in Alaska. The coordinate system is geographic and the elevation value in each cell is in meters. If we wanted to create a raster with elevation in feet, we can use these steps to create the expression:

  1. Bring up the raster calculator
  2. Double click on ancc6@1 in the raster bands list to add it to the expression
  3. Double click the multiplication operator (*)
  4. In the expression box, type in the conversion factor for meters to feet: 3.28

This gives us the following expression:

ancc6@1 * 3.28

To complete the process, we specify a name for the output raster and the format we want to use. When you click OK, the operation will be performed and the new raster created, giving us a GeoTIFF with cell values in feet. If you leave the Add result to project box checked the output raster will be added to QGIS once the calculations are done.

If you only want to operate on a portion of a raster, you can use the extent setting to limit the area included in the calculation.

Using a Mask

Sometimes you might want to mask out part of a raster. An example might be one where you have elevations ranging from below sea level to mountain tops. If you are only interested in elevations above sea level, you can use the raster calculator to create a mask and apply it to your raster all in one step.

The expression looks like this:

(my_raster@1 >= 0) * my_raster@1

The first part of the expression in parentheses effectively says: for every cell greater than or equal to zero, set its value to 1, otherwise set it to 0. This creates the mask on the fly.

In the second part of the expression, we multiply our raster (my_raster@1) by the mask values. This sets every cell with an elevation less than zero to zero. When you click OK, the calculator will create a new raster with the mask applied.

Simulating a Rise in Seal Level

Using the raster calculator and a mask we can visually simulate a rise in sea level. To do this we simply create the mask and overlay it on the DEM or perhaps a DRG (topographic) raster.

The expression to raise sea level by 100 meters is:

ancc6@1 > 100

The output raster contains cells with either a 0 (black) or 1 (while) value:

The black areas represent everything below an elevation of 100 meters, effectively illustrating a sea level rise. When we combine this with a suitable background we can demonstrate the results:

We added the DRG for the quadrangle and overlaid it with the mask layer. Setting the transparency to 70% allows the DRG to be seen, illustrating the effect of raising sea level.

The raster calculator is a powerful tool. Check it out and see how you might use it in your analysis and map making.

Using the QGIS Raster Calculator

The raster calculator allows you to perform mathematical operations on each cell in a raster. This can be useful for converting and manipulating your rasters. Operators include:

  • Mathematical (+, -, *, /)

  • Trigonometric (sin, cos, tan, asin, acos, atan)

  • Comparison (<, >, =, <=, >=)

  • Logical (AND, OR)

To perform operations on a raster or rasters, they must be loaded in QGIS. The raster calculator is accessed from the Raster menu and brings up the dialog:

Let’s look a few examples.

Simple Mathematical Calculation

Doing a simple calculation is easy. In this example we have a Digital Elevation Model (ancc6) loaded in QGIS. The DEM contains elevations for a 1:63,360 quadrangle in Alaska. The coordinate system is geographic and the elevation value in each cell is in meters. If we wanted to create a raster with elevation in feet, we can use these steps to create the expression:

  1. Bring up the raster calculator

  2. Double click on ancc6@1 in the raster bands list to add it to the expression

  3. Double click the multiplication operator (*)

  4. In the expression box, type in the conversion factor for meters to feet: 3.28

This gives us the following expression:

ancc6@1 * 3.28

To complete the process, we specify a name for the output raster and the format we want to use. When you click OK, the operation will be performed and the new raster created, giving us a GeoTIFF with cell values in feet. If you leave the Add result to project box checked the output raster will be added to QGIS once the calculations are done.

If you only want to operate on a portion of a raster, you can use the extent setting to limit the area included in the calculation.

Using a Mask

Sometimes you might want to mask out part of a raster. An example might be one where you have elevations ranging from below sea level to mountain tops. If you are only interested in elevations above sea level, you can use the raster calculator to create a mask and apply it to your raster all in one step.

The expression looks like this:

(my_raster@1 >= 0) * my_raster@1

The first part of the expression in parentheses effectively says: for every cell greater than or equal to zero, set its value to 1, otherwise set it to 0. This creates the mask on the fly.

In the second part of the expression, we multiply our raster (my_raster@1) by the mask values. This sets every cell with an elevation less than zero to zero. When you click OK, the calculator will create a new raster with the mask applied.

Simulating a Rise in Seal Level

Using the raster calculator and a mask we can visually simulate a rise in sea level. To do this we simply create the mask and overlay it on the DEM or perhaps a DRG (topographic) raster.

The expression to raise sea level by 100 meters is:

ancc6@1 > 100

The output raster contains cells with either a 0 (black) or 1 (while) value:

The black areas represent everything below an elevation of 100 meters, effectively illustrating a sea level rise. When we combine this with a suitable background we can demonstrate the results:

We added the DRG for the quadrangle and overlaid it with the mask layer. Setting the transparency to 70% allows the DRG to be seen, illustrating the effect of raising sea level.

The raster calculator is a powerful tool. Check it out and see how you might use it in your analysis and map making.

QGIS Plugin of the Week: OpenLayers

This week we look at the OpenLayers plugin for QGIS. This plugin allows you to add a number of image services to your map canvas:

  • Google
    • Physical
    • Streets
    • Hybrid
    • Satellite
  • OpenStreetMap
  • Yahoo
    • Street
    • Hybrid
    • Satellite
  • Bing
    • Road
    • Aerial
    • Aerial with labels

Installing the Plugin

The OpenLayers plugin is installed like all other Python plugins. From the the Plugins menu in QGIS, choose Fetch Python Plugins. This brings up the plugin installer. To find the plugin, enter openlayers in the Filter box, then select OpenLayers Plugin from the list. Once it’s highlighted, click the Install plugin button. This will download the plugin from the repository, install it, and load it into QGIS.

Using the Plugin

The OpenLayers Plugin uses your view extent to fetch the data from the service you choose. For this reason you should load at least one of your own layers first. Since each of the services are expecting a request in latitude/longitude your layer either has to be geographic or you must enable on the fly projection.

To add one of the services you have two choices; you can pick the service from the Plugins->OpenLayers plugin menu or you can use the OpenLayers Overview. The Overview opens a new panel that allows you to choose a service from a drop-down list. Click the Enable map checkbox to enable the drop-down list and preview the service you want to add. If you are happy with what you see, you can add it to the map by clicking the Add map button.

In the screenshot below we have enabled the Overview panel, added the world boundaries layer[1], zoomed to an area of interest, and added the Google terrain (physical) data:

You can add as many services as you want, previewing them using the OpenLayers Overview panel.

[1] You can get the world boundaries layer from the Geospatial Desktop sample data set.

Back to Top

Sustaining Members