<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Spatial Galaxy]]></title>
  <link href="http://spatialgalaxy.net//atom.xml" rel="self"/>
  <link href="http://spatialgalaxy.net//"/>
  <updated>2013-04-17T08:12:06-08:00</updated>
  <id>http://spatialgalaxy.net//</id>
  <author>
    <name><![CDATA[Gary Sherman]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[QGIS Back in the Day]]></title>
    <link href="http://spatialgalaxy.net//2013/04/17/qgis-back-in-the-day/"/>
    <updated>2013-04-17T07:50:00-08:00</updated>
    <id>http://spatialgalaxy.net//2013/04/17/qgis-back-in-the-day</id>
    <content type="html"><![CDATA[<p>Do you remember this?</p>
<img alt="QGIS of Yesteryear" src="http://spatialgalaxy.net//images/qgis_0.0.5.png" />
<p>If so, you&#8217;ve been using QGIS a <em>long</em> time&#8230;</p>
<ul class="simple">
<li>OGR and PostGIS support</li>
<li>No raster support</li>
<li>Three widgets on the Symbology tab</li>
<li>No symbology in the legend</li>
</ul>
<p>But you could use it handily on a 640x480 display.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[New Version of the QGIS Script Runner Plugin]]></title>
    <link href="http://spatialgalaxy.net//2013/03/18/new-version-of-the-qgis-script-runner-plugin/"/>
    <updated>2013-03-18T19:47:00-08:00</updated>
    <id>http://spatialgalaxy.net//2013/03/18/new-version-of-the-qgis-script-runner-plugin</id>
    <content type="html"><![CDATA[<p>The Script Runner plugin allows you to manage and execute a collection of scripts in QGIS to automate tasks and perform custom processing.</p>

<p><img src="http://spatialgalaxy.net//images/script_runner_06.png" alt="Script_Runner" /></p>

<p>Version 0.6 of Script Runner has been released and includes these changes:</p>

<!-- more -->


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


<p>For a basic introduction to Script Runner see this post: <a href="http://spatialgalaxy.net//2012/01/29/script-runner-a-plugin-to-run-python-scripts-in-qgis">Script Runner: A Plugin to Run Python Scripts in QGIS</a></p>

<h3>Working with Scripts</h3>

<h4>Adding Scripts</h4>

<p>To run a script, you must add it to Script Runner using the <code>Add Script</code> 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.</p>

<h4>Running a Script</h4>

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

<h4>Remove a Script</h4>

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

<h4>Script Information</h4>

<p>Clicking the <code>Info</code> 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.</p>

<p><em>At version 0.6 the <code>Info</code> tool is only needed if you have disabled automatic display of info/source (see <a href="#preferences">Preferences</a>).</em></p>

<h4>Viewing the Source</h4>

<p>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.</p>

<h3>New Features</h3>

<p>Version 0.6 implements a number of new features.</p>

<h4>Passing Arguments to a Script</h4>

<p>You can pass arguments to your script using keywords. Your <em>run_script</em> function must have two arguments:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>  <span class="k">def</span> <span class="nf">run_script</span><span class="p">(</span><span class="n">iface</span><span class="p">,</span> <span class="o">**</span><span class="n">args</span><span class="p">):</span>
</span></code></pre></td></tr></table></div></figure>


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

<p><img src="http://spatialgalaxy.net//images/argument_dialog.png" alt="Argument_dialog" /></p>

<p>All strings must be quoted and multiple arguments should be separated by a comma.</p>

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

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>  <span class="n">my_path</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="s">&#39;path&#39;</span><span class="p">]</span>
</span><span class='line'>  <span class="n">my_buffer_size</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="s">&#39;buffer_size&#39;</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


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

<p><img src="http://spatialgalaxy.net//images/scripts_with_args.png" alt="arg_scripts" /></p>

<p>See <a href="#passing_arguments">Passing Arguments</a> for a complete example.</p>

<h4>Output Console</h4>

<p>All <code>print</code> 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.</p>

<p>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 <code>Clear Console</code> tool. There is also an option in Preferences to clear the console each time a script is run.</p>

<h4>Logging to Disk</h4>

<p>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.</p>

<h4>Editing a Script</h4>

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

<p><a id="preferences"></a></p>

<h4>Preferences</h4>

<p>The Preferences dialog allows you to set the following options:</p>

<p><img src="http://spatialgalaxy.net//images/sr_preferences_dialog.png" alt="Script_Runner_Preferences" /></p>

<h3>Script Examples</h3>

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

<h4>Simple Script</h4>

<p>This simple script contains only a <em>run_script</em> function:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="sd">&quot;&quot;&quot; Load a layer and change the fill color to red. &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">PyQt4.QtCore</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">PyQt4.QtGui</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">qgis.core</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">qgis.gui</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">run_script</span><span class="p">(</span><span class="n">iface</span><span class="p">):</span>
</span><span class='line'>        <span class="n">mapreg</span> <span class="o">=</span> <span class="n">QgsMapLayerRegistry</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span>
</span><span class='line'>        <span class="n">mapreg</span><span class="o">.</span><span class="n">removeAllMapLayers</span><span class="p">()</span>
</span><span class='line'>        <span class="n">wb</span> <span class="o">=</span> <span class="n">QgsVectorLayer</span><span class="p">(</span><span class="s">&#39;/data/world_borders.shp&#39;</span><span class="p">,</span> <span class="s">&#39;world_borders&#39;</span><span class="p">,</span> <span class="s">&#39;ogr&#39;</span><span class="p">)</span>
</span><span class='line'>        <span class="n">mapreg</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span><span class="o">.</span><span class="n">addMapLayer</span><span class="p">(</span><span class="n">wb</span><span class="p">)</span>
</span><span class='line'>        <span class="n">renderer</span> <span class="o">=</span> <span class="n">wb</span><span class="o">.</span><span class="n">rendererV2</span><span class="p">()</span>
</span><span class='line'>        <span class="n">symb</span> <span class="o">=</span> <span class="n">renderer</span><span class="o">.</span><span class="n">symbol</span><span class="p">()</span>
</span><span class='line'>        <span class="n">symb</span><span class="o">.</span><span class="n">setColor</span><span class="p">(</span><span class="n">QColor</span><span class="p">(</span><span class="n">Qt</span><span class="o">.</span><span class="n">red</span><span class="p">))</span>
</span><span class='line'>        <span class="n">wb</span><span class="o">.</span><span class="n">setCacheImage</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
</span><span class='line'>        <span class="n">wb</span><span class="o">.</span><span class="n">triggerRepaint</span><span class="p">()</span>
</span><span class='line'>        <span class="n">iface</span><span class="o">.</span><span class="n">refreshLegend</span><span class="p">(</span><span class="n">wb</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


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

<h4>A Script with a Class</h4>

<p>This script uses a class that is initialized from the <em>run_script</em> function to load some layers:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="sd">&quot;&quot;&quot;Load all shapefiles in a given directory.  &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">glob</span> <span class="kn">import</span> <span class="n">glob</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">path</span>
</span><span class='line'>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">qgis.core</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">qgis.gui</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">import</span> <span class="nn">qgis.utils</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">class</span> <span class="nc">Loader</span><span class="p">:</span>
</span><span class='line'>        <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">iface</span><span class="p">):</span>
</span><span class='line'>            <span class="sd">&quot;&quot;&quot;Initialize using the qgis.utils.iface</span>
</span><span class='line'><span class="sd">            object passed from the console.</span>
</span><span class='line'><span class="sd">            &quot;&quot;&quot;</span>
</span><span class='line'>
</span><span class='line'>            <span class="bp">self</span><span class="o">.</span><span class="n">iface</span> <span class="o">=</span> <span class="n">qgis</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">iface</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">def</span> <span class="nf">load_shapefiles</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shp_path</span><span class="p">):</span>
</span><span class='line'>            <span class="sd">&quot;&quot;&quot;Load all shapefiles found in shp_path&quot;&quot;&quot;</span>
</span><span class='line'>            <span class="k">print</span> <span class="s">&quot;Loading shapes from </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">shp_path</span><span class="p">,</span> <span class="s">&quot;*.shp&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">shps</span> <span class="o">=</span> <span class="n">glob</span><span class="p">(</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">shp_path</span><span class="p">,</span> <span class="s">&quot;*.shp&quot;</span><span class="p">))</span>
</span><span class='line'>            <span class="k">for</span> <span class="n">shp</span> <span class="ow">in</span> <span class="n">shps</span><span class="p">:</span>
</span><span class='line'>                <span class="p">(</span><span class="n">shpdir</span><span class="p">,</span> <span class="n">shpfile</span><span class="p">)</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">shp</span><span class="p">)</span>
</span><span class='line'>                <span class="k">print</span> <span class="s">&quot;Loading </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">shpfile</span>
</span><span class='line'>                <span class="n">lyr</span> <span class="o">=</span> <span class="n">QgsVectorLayer</span><span class="p">(</span><span class="n">shp</span><span class="p">,</span> <span class="n">shpfile</span><span class="p">,</span> <span class="s">&#39;ogr&#39;</span><span class="p">)</span>
</span><span class='line'>                <span class="n">QgsMapLayerRegistry</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span><span class="o">.</span><span class="n">addMapLayer</span><span class="p">(</span><span class="n">lyr</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">run_script</span><span class="p">(</span><span class="n">iface</span><span class="p">):</span>
</span><span class='line'>        <span class="n">ldr</span> <span class="o">=</span> <span class="n">Loader</span><span class="p">(</span><span class="n">iface</span><span class="p">)</span>
</span><span class='line'>        <span class="k">print</span> <span class="s">&quot;Loading all shapefiles in /qgis_sample_data/vmap0_shapefiles&quot;</span>
</span><span class='line'>        <span class="n">ldr</span><span class="o">.</span><span class="n">load_shapefiles</span><span class="p">(</span><span class="s">&#39;/qgis_sample_data/vmap0_shapefiles&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>In this example, the <em>run_script</em> function creates an instance (<code>ldr</code>) of a
class named <em>Loader</em> that is defined in the same source file. It then calls a
method in the <em>Loader</em> class named <em>load_shapefiles</em> to do something
useful&#8212;in this case, load all the shapefiles in a specified directory.</p>

<p><a id="passing_arguments"></a></p>

<h4>Passing Arguments</h4>

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

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="sd">&quot;&quot;&quot;Load all shapefiles in a given directory.&quot;&quot;&quot;</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">glob</span> <span class="kn">import</span> <span class="n">glob</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">path</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">qgis.core</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">qgis.gui</span> <span class="kn">import</span> <span class="o">*</span>
</span><span class='line'>    <span class="kn">import</span> <span class="nn">qgis.utils</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    <span class="k">class</span> <span class="nc">Loader</span><span class="p">:</span>
</span><span class='line'>        <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">iface</span><span class="p">):</span>
</span><span class='line'>            <span class="sd">&quot;&quot;&quot;Initialize using the qgis.utils.iface </span>
</span><span class='line'><span class="sd">            object passed from the console.</span>
</span><span class='line'><span class="sd"> </span>
</span><span class='line'><span class="sd">            &quot;&quot;&quot;</span>
</span><span class='line'>            <span class="bp">self</span><span class="o">.</span><span class="n">iface</span> <span class="o">=</span> <span class="n">qgis</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">iface</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">def</span> <span class="nf">load_shapefiles</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shp_path</span><span class="p">):</span>
</span><span class='line'>            <span class="sd">&quot;&quot;&quot;Load all shapefiles found in shp_path&quot;&quot;&quot;</span>
</span><span class='line'>            <span class="k">print</span> <span class="s">&quot;Loading shapes from </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">shp_path</span><span class="p">,</span> <span class="s">&quot;*.shp&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">shps</span> <span class="o">=</span> <span class="n">glob</span><span class="p">(</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">shp_path</span><span class="p">,</span> <span class="s">&quot;*.shp&quot;</span><span class="p">))</span>
</span><span class='line'>            <span class="k">for</span> <span class="n">shp</span> <span class="ow">in</span> <span class="n">shps</span><span class="p">:</span>
</span><span class='line'>                <span class="p">(</span><span class="n">shpdir</span><span class="p">,</span> <span class="n">shpfile</span><span class="p">)</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">shp</span><span class="p">)</span>
</span><span class='line'>                <span class="k">print</span> <span class="s">&quot;Loading </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">shpfile</span>
</span><span class='line'>                <span class="n">lyr</span> <span class="o">=</span> <span class="n">QgsVectorLayer</span><span class="p">(</span><span class="n">shp</span><span class="p">,</span> <span class="n">shpfile</span><span class="p">,</span> <span class="s">&#39;ogr&#39;</span><span class="p">)</span>
</span><span class='line'>                <span class="n">QgsMapLayerRegistry</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span><span class="o">.</span><span class="n">addMapLayer</span><span class="p">(</span><span class="n">lyr</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">run_script</span><span class="p">(</span><span class="n">iface</span><span class="p">,</span> <span class="o">**</span><span class="n">args</span><span class="p">):</span>
</span><span class='line'>        <span class="n">ldr</span> <span class="o">=</span> <span class="n">Loader</span><span class="p">(</span><span class="n">iface</span><span class="p">)</span>
</span><span class='line'>        <span class="k">print</span> <span class="s">&quot;Loading all shapefiles in </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">args</span><span class="p">[</span><span class="s">&#39;path&#39;</span><span class="p">]</span>
</span><span class='line'>        <span class="n">ldr</span><span class="o">.</span><span class="n">load_shapefiles</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="s">&#39;path&#39;</span><span class="p">])</span>
</span></code></pre></td></tr></table></div></figure>


<p>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.</p>

<h2>Final Word</h2>

<p>The script examples are minimalistic&#8212;they don&#8217;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&#8217;t take the scripts as examples of complete, solid code.</p>

<p>Comments on this post are welcome, as are bug reports. The link to the <a href="http://hub.qgis.org/projects/scriptrunner">bug tracker</a> for Script Runner can be found in the <em>About</em> box, along with the link to the code repository and my email address.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Littering Your Python Path: The Road to Destruction]]></title>
    <link href="http://spatialgalaxy.net//2012/12/05/littering-your-python-path-the-road-to-destruction/"/>
    <updated>2012-12-05T16:59:00-09:00</updated>
    <id>http://spatialgalaxy.net//2012/12/05/littering-your-python-path-the-road-to-destruction</id>
    <content type="html"><![CDATA[<p><em>Well not quite destruction, but a bit of hair pulling&#8230;</em></p>

<p>While working on an update to the <a href="http://hub.qgis.org/projects/plugin-builder">Plugin Builder</a>, I encountered a small problem.
The <em>Plugin Builder</em> 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.</p>

<p>Using <tt>grep</tt> on all the source files revealed no instance of 1.8.3 in any file.</p>

<!-- more -->


<p>The title of this post has probably already given you the answer&#8212;I had on old version of the plugin in my Python path. The old plugin was getting picked up first when QGIS loaded.</p>

<p>Here&#8217;s what happened:</p>

<p>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.</p>

<p>The other pitfall you can encounter is if you use the
<tt>QGIS_PLUGINPATH</tt>  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.</p>

<p>The moral of the story:</p>

<p><em>Don&#8217;t stash old plugins in .qgis/python or you may send yourself down the wrong path&#8230;</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Gains a Gold Sponsor]]></title>
    <link href="http://spatialgalaxy.net//2012/10/04/qgis-gains-a-gold-sponsor/"/>
    <updated>2012-10-04T05:55:00-08:00</updated>
    <id>http://spatialgalaxy.net//2012/10/04/qgis-gains-a-gold-sponsor</id>
    <content type="html"><![CDATA[<p>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.</p>

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

<p>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).</p>

<p>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.</p>

<p>For more information on sponsorship levels, please see the <a href="http://www.qgis.org/en/sponsorship.html">QGIS Sponsorship page</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Is Ten Years Old]]></title>
    <link href="http://spatialgalaxy.net//2012/07/18/qgis-is-ten-years-old/"/>
    <updated>2012-07-18T15:08:00-08:00</updated>
    <id>http://spatialgalaxy.net//2012/07/18/qgis-is-ten-years-old</id>
    <content type="html"><![CDATA[<p>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 &#8220;release early and release often,&#8221; I announced it on Freshmeat and waited.</p>

<p>Slowly it began to attract attention&#8212;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.</p>

<p>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.</p>

<p>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.</p>

<p>I founded QGIS; the community built it. Here&#8217;s to many more successful years as one of the leading open source GIS projects.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[What's New in QGIS Plugins]]></title>
    <link href="http://spatialgalaxy.net//2012/04/16/whats-new-in-qgis-plugins/"/>
    <updated>2012-04-16T12:12:00-08:00</updated>
    <id>http://spatialgalaxy.net//2012/04/16/whats-new-in-qgis-plugins</id>
    <content type="html"><![CDATA[<p>Here&#8217;s a summary of recent additions and updates to plugins in the <a href="http://plugins.qgis.org/plugins">QGIS repository</a>.</p>

<ul>
<li><a href="http://plugins.qgis.org/plugins/FlowMapper">FlowMapper</a> (0.1.1) -  Generates flow lines between discreet nodes for depicting spatial interaction data (e.g. migration).</li>
<li><a href="http://plugins.qgis.org/plugins/QueryByExample">Query By Example</a> (0.2) - Select features by location.</li>
<li><a href="http://plugins.qgis.org/plugins/itembrowser">Item Browser</a> (1.6.0) - Browse a multiple selection with auto-zooming to feature and an option to open feature form.</li>
<li><a href="http://plugins.qgis.org/plugins/customlauncher">Custom Launcher</a> (1.1.0) - Customize your own actions to launch your preferred apps or commands within QGIS.</li>
<li><a href="http://plugins.qgis.org/plugins/profiletool">Profile Tool</a> (3.3.1) - Plots terrain profile</li>
<li><a href="http://plugins.qgis.org/plugins/qsearch">qSearch </a> (1.3.0) -  Produces a friendly interface to perform and save searches in a layer.</li>
<li><a href="http://plugins.qgis.org/plugins/quickfinder">Quick Finder</a> (1.0.0) - Dockable dialog to find a feature by its ID in a layer.</li>
<li><a href="http://plugins.qgis.org/plugins/sextante">SEXTANTE</a> (1.0.3) - <a href="http://sextantegis.com">SEXTANTE</a> for QGIS</li>
<li><a href="http://plugins.qgis.org/plugins/linkit">Link It</a> (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&#8217;s ID in the appropriate field defined by the user. This plugin requires ItemBrowser.</li>
<li><a href="http://plugins.qgis.org/plugins/QuickMultiAttributeEdit">QuickMultiAttributeEdit</a> (0.8) - QuickMultiAttributeEdit plugin provides a very quick and handy way to update a feature for the selected attributes into the current/active layer.</li>
</ul>


<!-- more -->


<h2>Installing Plugins</h2>

<p>To install any of these plugins:</p>

<ol>
<li>Open the Python plugin installer: Plugins->Fetch Python Plugins</li>
<li>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.</li>
<li>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</li>
<li>Some plugins may be flagged experimental. Make sure you have allowed experimental plugins on the Options tab of the plugin installer</li>
<li>Click on the Plugins tab</li>
<li>Select the desired plugin from the list and click Install</li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Plugin of the Week: qNote]]></title>
    <link href="http://spatialgalaxy.net//2012/04/06/plugin-of-the-week-qnote/"/>
    <updated>2012-04-06T08:59:00-08:00</updated>
    <id>http://spatialgalaxy.net//2012/04/06/plugin-of-the-week-qnote</id>
    <content type="html"><![CDATA[<p>This week we look at a newly arrived plugin named <em>qNote</em>. 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 <em>qNote</em> panel.</p>

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

<ul>
<li>Content of the project</li>
<li>Purpose</li>
<li>Area of interest</li>
<li>Where the data came from</li>
<li>Who created the project</li>
</ul>


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

<!-- more -->


<p>Here is a screenshot showing <em>qNote</em> in action:</p>

<p><img src="http://spatialgalaxy.net//images/qnote_snapshot.png" alt="qNote Plugin" /></p>

<h2>Installing the Plugin</h2>

<p>To install the plugin:</p>

<ol>
<li>Open the Python plugin installer: Plugins->Fetch Python Plugins</li>
<li>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.</li>
<li>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</li>
<li><em>qNote</em> is currently flagged experimental. Make sure you have allowed
experimental plugins on the Options tab of the plugin installer</li>
<li>Click on the Plugins tab</li>
<li>Enter qNote in the Filter box</li>
<li>Select the qNote plugin and click Install</li>
</ol>


<p>You can control the visiblity of the <em>qNote</em> panel from the View->Panels
menu.</p>

<p>The README for the plugin can be viewed on the <a href="https://github.com/p0cisk/qNote/blob/master/README.rst"><em>qNote</em> GitHub page</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Getting Support for QGIS]]></title>
    <link href="http://spatialgalaxy.net//2012/04/05/getting-support-for-qgis/"/>
    <updated>2012-04-05T07:02:00-08:00</updated>
    <id>http://spatialgalaxy.net//2012/04/05/getting-support-for-qgis</id>
    <content type="html"><![CDATA[<p>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.</p>

<!-- more -->


<h2>Home Page</h2>

<p><a href="http://qgis.org/en/community.html"><img src="http://spatialgalaxy.net//images/need_help.png" align="right"/></a>
The <a href="http://QGIS.org">QGIS home page</a> 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.</p>

<p>To quickly see links to all the resources,
click the <em>Need Help?</em> button on the home page. You&#8217;ll find links to:</p>

<ul>
<li>User Manual</li>
<li>Wiki</li>
<li>Mailing Lists</li>
<li>StackExchange</li>
</ul>


<h2>StackExchange</h2>

<p><a href="http://gis.stackexchange.com/questions/tagged/qgis"><img src="http://spatialgalaxy.net//images/stackexchange_header.png" align ="right"/></a>
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 <em>qgis</em> keyword, otherwise use an appropriate tag.</p>

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

<p>Also, make sure you <strong>flag the question as answered</strong> once you receive a satisfactory response.</p>

<h2>Mailing Lists</h2>

<p><a href="http://www.qgis.org/en/community/mailing-lists.html"><img src="http://spatialgalaxy.net//images/email_large.png" align="right"/></a>
The QGIS project maintains a number of mailing lists. For most people, the two of interest are <em>qgis-user</em> and <em>qgis-developer</em>:</p>

<ul>
<li><p><strong>qgis-user</strong>:
  Use this list for discussion of QGIS in general, as well as specific questions regarding its installation and use.</p></li>
<li><p><strong>qgis-developer</strong>: 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&#8217;ll find this list useful.</p></li>
</ul>


<p>If you just want to browse or search the mailing lists without subscribing,
they are available on
<a href="http://osgeo-org.1560.n6.nabble.com/Quantum-GIS-f4099105.html">Nabble</a>.</p>

<h2>IRC</h2>

<p><a href="http://freenode.net/using_the_network.shtml"><img src="http://spatialgalaxy.net//images/irc_protocol.png" align="right"/></a>
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 <em>#qgis</em> channel on irc.freenode.net.</p>

<p>To use IRC, you&#8217;ll need a <a href="https://duckduckgo.com/?q=irc+clients">client application</a> for your computer, tablet, or smartphone.</p>

<p>Here are a couple of guidelines for using the <em>#qgis</em> channel:</p>

<ol>
<li>If you have a question, don&#8217;t ask if you can ask, just state your question</li>
<li>If no one responds, it&#8217;s not because they hate you or think you are a dullard, but are busy or don&#8217;t know the answer to your question</li>
</ol>


<p>The QGIS IRC community is very friendly and helpful. Give it a try.</p>

<h2>Search the Internet</h2>

<p>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.</p>

<p>In addition to your favorite search engine, try <a href="https://duckduckgo.com/">DuckDuckGo</a> for more targeted search results.</p>

<h2>Shameless Plug</h2>

<p>If you need a good introduction to open source GIS applications, tools, and scripting, take a look at <a href="http://geospatialdesktop.com">my book</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Forum Is Closed---What Do You Think?]]></title>
    <link href="http://spatialgalaxy.net//2012/03/31/qgis-forum-is-closed-what-do-you-think/"/>
    <updated>2012-03-31T08:35:22-08:00</updated>
    <id>http://spatialgalaxy.net//2012/03/31/qgis-forum-is-closed-what-do-you-think</id>
    <content type="html"><![CDATA[<p>The forum (<a href="http://forum.qgis.org">http://forum.qgis.org</a>) has been closed for new registrations and marked read-only. Users have been encouraged to use <a href="http://gis.stackexchange.com/">http://gis.stackexchange.com</a> instead.</p>

<p>If you have an thoughts on the closure, good, bad, or otherwise, please comment.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Script Runner: A Plugin to Run Python Scripts in QGIS]]></title>
    <link href="http://spatialgalaxy.net//2012/01/29/script-runner-a-plugin-to-run-python-scripts-in-qgis/"/>
    <updated>2012-01-29T00:00:00-09:00</updated>
    <id>http://spatialgalaxy.net//2012/01/29/script-runner-a-plugin-to-run-python-scripts-in-qgis</id>
    <content type="html"><![CDATA[<p>Following up on my last post, <a href="http://spatialgalaxy.net//2012/01/27/qgis-running-scripts-in-the-python-console/" title="QGIS: Running Scripts in the Python Console"><em>Running Scripts in the Python Console</em></a>, I created a plugin to simplify running scripts:</p>

<!-- more -->


<p><a href="http://spatialgalaxy.net/2012/01/29/script-runner-a-plugin-to-run-python-scripts-in-qgis/script_runner1/" rel="attachment wp-att-808"><img src="http://spatialgalaxy.net/wp-content/script_runner1.png" alt="" title="script_runner1" width="714" height="558" class="aligncenter size-full wp-image-808" /></a></p>

<p>The <em>Script Runner</em> 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:</p>

<p><a href="http://spatialgalaxy.net/2012/01/29/script-runner-a-plugin-to-run-python-scripts-in-qgis/script_runner2/" rel="attachment wp-att-817"><img src="http://spatialgalaxy.net/wp-content/script_runner2.png" alt="" title="script_runner2" width="714" height="558" class="aligncenter size-full wp-image-817" /></a></p>

<p>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:</p>

<h3>Requirements</h3>


<p>
    In order for Script Runner to execute your script you must define a <em>run_script</em> 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 <em>run_script</em> function.  You don&#8217;t have to use the iface object in your script but your <em>run_script</em> function must accept it as an argument.  
</p>


<p>
Here is an example of a simple <em>run_script</em> function:

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="k">def</span> <span class="nf">run_script</span><span class="p">(</span><span class="n">iface</span><span class="p">):</span>
</span><span class='line'>        <span class="n">ldr</span> <span class="o">=</span> <span class="n">Loader</span><span class="p">(</span><span class="n">iface</span><span class="p">)</span>
</span><span class='line'>        <span class="n">ldr</span><span class="o">.</span><span class="n">load_shapefiles</span><span class="p">(</span><span class="s">&#39;/vmap0_shapefiles&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>

   <p>
   In this example, the <em>run_script</em> 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&#8212;in this case, load all the shapefiles in a specified directory.
   </p>
   <p>
   Alternatively, you could choose not to use classes and just do everything within the <em>run_script</em> 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 <em>run_script</em> function. If not, Script Runner won&#8217;t load your script.
   </p>
   <h3>Working with Scripts</h3>
   <p>
   To run a script, you must add it to Script Runner using the <em>Add Script</em> 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 <em>Remove Script</em> tool. This just removes it from the list; it does nothing to the script file on disk.
   </p>
   <p>
   Once you have a script loaded, you can click the <em>Script Info</em> 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.  </p>
   <p> 
   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.
   </p>

<h3>Installing the Plugin</h3>
To install the plugin:
<ol>
    <li>Open the Python plugin installer: Plugins->Fetch Python Plugins</li>
    <li>Check to see if you have the new Official repository in your list of plugins by clicking on  <em>Repositories</em> tab. The URL is http://plugins.qgis.org/plugins/plugins.xml.</li>
    <li>If you have it, skip to step 5. If the new repository isn&#8217;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</li>
    <li>Click on the <em>Plugins</em> tab</li>
    <li>Enter scriptrunner in the Filter box</li>
    <li>Select the ScriptRunner plugin and click Install</li>
</ol>

ScriptRunner adds an entry to the Plugins menu as well as a tool on the Plugins toolbar: <img style="vertical-align:middle" src="http://spatialgalaxy.net/wp-content/icon.png" alt="" title="icon" width="32" height="32" align="absmiddle" size-full wp-image-844" /> 
<p>
Click it and you are off and running.
</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS: Running Scripts in the Python Console]]></title>
    <link href="http://spatialgalaxy.net//2012/01/27/qgis-running-scripts-in-the-python-console/"/>
    <updated>2012-01-27T08:10:51-09:00</updated>
    <id>http://spatialgalaxy.net//2012/01/27/qgis-running-scripts-in-the-python-console</id>
    <content type="html"><![CDATA[<p>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.<a href="#fn1">[1]</a> Until it does, this post
illustrates a way you can create a script and run it from the console.</p>

<!-- more -->


<p>There are a couple of requirements to run a script in the console:</p>

<ol>
<li><p>The script must be in your PYTHONPATH</p></li>
<li><p>Just like a QGIS plugin, the script needs a reference to <em>qgis.utils.iface</em></p></li>
</ol>


<h3>Setting up the Environment</h3>

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

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


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

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="kn">import</span> <span class="nn">sys</span>
</span><span class='line'>    <span class="n">sys</span><span class="o">.</span><span class="n">path</span>
</span></code></pre></td></tr></table></div></figure>


<p>While you could use the <em>.qgis\python</em> 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 <em>Environment Variables</em> page in your system properties:</p>

<p><a href="http://spatialgalaxy.net/2012/01/27/qgis-running-scripts-in-the-python-console/python_path_win/"><img src="http://spatialgalaxy.net/wp-content/python_path_win.png" alt="" /></a></p>

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

<pre><code>export PYTHONPATH=$PYTHONPATH:/home/gsherman/qgis_scripts
</code></pre>

<h3>Writing the Script</h3>

<p>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:</p>

<ol>
<li><p>Write a simple script with a function that accepts <em>qgis.utils.iface</em> as an argument, along with a path to the shapefiles</p></li>
<li><p>Create a Python class that uses an <strong>init</strong> method to store a reference to the <em>iface</em> object and then add methods to do the work</p></li>
</ol>


<p>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 <em>iface</em> object each time.</p>

<p>The script looks like this:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="c">#!/usr/bin/env Python</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;Load all shapefiles in a given directory.</span>
</span><span class='line'><span class="sd">      This script (loader.py) runs from the QGIS Python console.</span>
</span><span class='line'><span class="sd">      From the console, use:</span>
</span><span class='line'><span class="sd">        from loader import Loader</span>
</span><span class='line'><span class="sd">        ldr = Loader(qgis.utils.iface)</span>
</span><span class='line'><span class="sd">        ldr.load_shapefiles(&#39;/my/path/to/shapefile/directory&#39;)</span>
</span><span class='line'><span class="sd">    </span>
</span><span class='line'><span class="sd">      &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">glob</span> <span class="kn">import</span> <span class="n">glob</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">path</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">class</span> <span class="nc">Loader</span><span class="p">:</span>
</span><span class='line'>        <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">iface</span><span class="p">):</span>
</span><span class='line'>            <span class="sd">&quot;&quot;&quot;Initialize using the qgis.utils.iface </span>
</span><span class='line'><span class="sd">            object passed from the console.</span>
</span><span class='line'><span class="sd">            </span>
</span><span class='line'><span class="sd">            &quot;&quot;&quot;</span>
</span><span class='line'>            <span class="bp">self</span><span class="o">.</span><span class="n">iface</span> <span class="o">=</span> <span class="n">iface</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">def</span> <span class="nf">load_shapefiles</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shp_path</span><span class="p">):</span>
</span><span class='line'>            <span class="sd">&quot;&quot;&quot;Load all shapefiles found in shp_path&quot;&quot;&quot;</span>
</span><span class='line'>            <span class="k">print</span> <span class="s">&quot;Loading shapes from </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">shp_path</span><span class="p">,</span> <span class="s">&quot;*.shp&quot;</span><span class="p">)</span>
</span><span class='line'>            <span class="n">shps</span> <span class="o">=</span> <span class="n">glob</span><span class="p">(</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">shp_path</span><span class="p">,</span> <span class="s">&quot;*.shp&quot;</span><span class="p">))</span>
</span><span class='line'>            <span class="k">for</span> <span class="n">shp</span> <span class="ow">in</span> <span class="n">shps</span><span class="p">:</span>
</span><span class='line'>                <span class="p">(</span><span class="n">shpdir</span><span class="p">,</span> <span class="n">shpfile</span><span class="p">)</span> <span class="o">=</span> <span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">shp</span><span class="p">)</span>
</span><span class='line'>                <span class="bp">self</span><span class="o">.</span><span class="n">iface</span><span class="o">.</span><span class="n">addVectorLayer</span><span class="p">(</span><span class="n">shp</span><span class="p">,</span> <span class="n">shpfile</span><span class="p">,</span> <span class="s">&#39;ogr&#39;</span> <span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Running the Script</h3>

<p>To open the console use the <em>Plugins->Python Console</em> menu item.</p>

<p>The comment at the head of the script explains how to use it.</p>

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

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="kn">from</span> <span class="nn">loader</span> <span class="kn">import</span> <span class="n">Loader</span>
</span></code></pre></td></tr></table></div></figure>


<p>We then create an instance of <em>Loader</em>, passing it the reference to the <em>iface</em> object:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="n">ldr</span> <span class="o">=</span> <span class="n">Loader</span><span class="p">(</span><span class="n">qgis</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">iface</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>This creates the <em>Loader</em> object and calls the <strong>init</strong> method to initialize things.</p>

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

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="n">ldr</span><span class="o">.</span><span class="n">load_shapefiles</span><span class="p">(</span><span class="s">&#39;/home/gsherman/qgis_sample_data/vmap0_shapefiles&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


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

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

<p><a href="http://spatialgalaxy.net/2012/01/27/qgis-running-scripts-in-the-python-console/console_loading_of_shps/"><img src="http://spatialgalaxy.net/wp-content/console_loading_of_shps-1024x720.png" alt="" /></a></p>

<h3>Some Notes</h3>

<ul>
<li><p>When testing a script in the console you may need to reload it as you make changes. This can be done using <em>reload</em> and the name of the module. In our example, <em>reload(loader)</em> does the trick.</p></li>
<li><p>You can add more methods to your class to do additional tasks</p></li>
<li><p>You can create a &#8220;driver&#8221; script that accepts the <em>iface</em> object and then initializes additional classes to do more complex tasks</p></li>
</ul>


<p><a name="fn1">[1]</a>. I have plans on the drawing board to implement this feature.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using the QGIS Raster Calculator]]></title>
    <link href="http://spatialgalaxy.net//2012/01/25/using-the-qgis-raster-calculator/"/>
    <updated>2012-01-25T09:12:44-09:00</updated>
    <id>http://spatialgalaxy.net//2012/01/25/using-the-qgis-raster-calculator</id>
    <content type="html"><![CDATA[<p>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:</p>

<ul>
<li><p>Mathematical (+, -, *, /)</p></li>
<li><p>Trigonometric (sin, cos, tan, asin, acos, atan)</p></li>
<li><p>Comparison (&lt;, >, =, &lt;=, >=)</p></li>
<li><p>Logical (AND, OR)</p></li>
</ul>


<!-- more -->


<p>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:</p>

<p><a href="http://spatialgalaxy.net/2012/01/25/using-the-qgis-raster-calculator/raster_calc_dialog/"><img src="http://spatialgalaxy.net/wp-content/raster_calc_dialog.png" alt="" /></a></p>

<p>Let&#8217;s look a few examples.</p>

<h3>Simple Mathematical Calculation</h3>

<p>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:</p>

<ol>
<li><p>Bring up the raster calculator</p></li>
<li><p>Double click on ancc6@1 in the raster bands list to add it to the expression</p></li>
<li><p>Double click the multiplication operator (*)</p></li>
<li><p>In the expression box, type in the conversion factor for meters to feet: 3.28</p></li>
</ol>


<p>This gives us the following expression:</p>

<p><code>ancc6@1 * 3.28</code></p>

<p>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 <em>Add result to project</em> box checked the output raster will be added to QGIS once the calculations are done.</p>

<p>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.</p>

<h3>Using a Mask</h3>

<p>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.</p>

<p>The expression looks like this:</p>

<p><code>(my_raster@1 &gt;= 0) * my_raster@1</code></p>

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

<p>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.</p>

<h3>Simulating a Rise in Seal Level</h3>

<p>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.</p>

<p>The expression to raise sea level by 100 meters is:</p>

<p><code>ancc6@1 &gt; 100</code></p>

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

<p><a href="http://spatialgalaxy.net/2012/01/25/using-the-qgis-raster-calculator/raster_raise_sea_level_mask/"><img src="http://spatialgalaxy.net/wp-content/raster_raise_sea_level_mask-1024x720.png" alt="" /></a></p>

<p>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:</p>

<p><a href="http://spatialgalaxy.net/2012/01/25/using-the-qgis-raster-calculator/raster_raise_sea_level_overlay/"><img src="http://spatialgalaxy.net/wp-content/raster_raise_sea_level_overlay-1024x720.png" alt="" /></a></p>

<p>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.</p>

<p>The raster calculator is a powerful tool. Check it out and see how you might use it in your analysis and map making.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Plugin of the Week: OpenLayers]]></title>
    <link href="http://spatialgalaxy.net//2012/01/14/qgis-plugin-of-the-week-openlayers/"/>
    <updated>2012-01-14T08:28:14-09:00</updated>
    <id>http://spatialgalaxy.net//2012/01/14/qgis-plugin-of-the-week-openlayers</id>
    <content type="html"><![CDATA[<p>This week we look at the <a href="http://hub.qgis.org/projects/openlayers">OpenLayers plugin</a> for QGIS. This plugin allows you to add a number of image services to your map canvas:</p>

<ul>
<li>Google

<ul>
<li>Physical</li>
<li>Streets</li>
<li>Hybrid</li>
<li>Satellite</li>
</ul>
</li>
<li>OpenStreetMap</li>
<li>Yahoo

<ul>
<li>Street</li>
<li>Hybrid</li>
<li>Satellite</li>
</ul>
</li>
<li>Bing

<ul>
<li>Road</li>
<li>Aerial</li>
<li>Aerial with labels</li>
</ul>
</li>
</ul>


<!-- more -->


<p></p>

<h3>Installing the Plugin</h3>

<p>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 <em>OpenLayers Plugin</em> 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.</p>

<h3>Using the Plugin</h3>

<p>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.</p>

<p>To add one of the services you have two choices; you can pick the service from the <em>Plugins->OpenLayers plugin</em> menu or you can use the <em>OpenLayers Overview</em>. The Overview opens a new panel that allows you to choose a service from a drop-down list. Click the <em>Enable map</em> 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 <em>Add map</em> button.</p>

<p>In the screenshot below we have enabled the Overview panel, added the world boundaries layer<a href="#fn1">[1]</a>, zoomed to an area of interest, and added the Google terrain (physical) data:</p>

<p><a href="http://spatialgalaxy.net/2012/01/14/qgis-plugin-of-the-week-openlayers/openlayers_plugin/"><img src="http://spatialgalaxy.net/wp-content/openlayers_plugin-1024x720.png" alt="" /></a></p>

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

<p><a name="fn1">[1]</a> You can get the world boundaries layer from the <a href="http://geospatialdesktop.com/data">Geospatial Desktop</a> sample data set.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Plugin of the Week: Profile]]></title>
    <link href="http://spatialgalaxy.net//2012/01/06/qgis-plugin-of-the-week-profile/"/>
    <updated>2012-01-06T09:58:07-09:00</updated>
    <id>http://spatialgalaxy.net//2012/01/06/qgis-plugin-of-the-week-profile</id>
    <content type="html"><![CDATA[<p>This week we take a look at a how to plot a terrain profile using the Profile plugin. The plugin can be used with any raster format supported by QGIS. You can can display profiles from up to three rasters at once, allowing you to compare the results. To illustrate, we&#8217;ll create a simple profile using a DEM of a 1:63,360 quadrangle in Alaska.</p>

<!-- more -->


<h3>Installing the Plugin</h3>

<p>The Profile 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 <em>profile</em> in the Filter box, then select
Profile from the list. Once it&#8217;s highlighted, click the <em>Install plugin</em>
button. This will download the plugin from the repository, install it, and load
it into QGIS.<a href="#fn1">[1]</a></p>

<h3>Using the Plugin</h3>

<p>Here we have loaded the DEM as well as a raster (DRG) of the topography for the same quadrangle and zoomed in a bit to an area of interest:</p>

<p><a href="http://spatialgalaxy.net/2012/01/06/qgis-plugin-of-the-week-profile/qgis_profile_data-2/"><img src="http://spatialgalaxy.net/wp-content/qgis_profile_data1.png" alt="" /></a></p>

<p>The yellow line has been added to indicate where we will take the profile. While the Profile plugin allows you to interactively select the profile line it doesn&#8217;t display the line on the map.</p>

<p>To create a profile, first make sure the raster you want to profile is selected in the layer list, then activate the plugin from the Plugins toolbar by clicking on it. The cursor becomes a cross that you use to create the profile line: click at the start point, move to the end and click again. Once you have created the profile line, the plugin pops up the result:</p>

<p><a href="http://spatialgalaxy.net/2012/01/06/qgis-plugin-of-the-week-profile/qgis_profile_result1/"><img src="http://spatialgalaxy.net/wp-content/qgis_profile_result1.png" alt="" /></a></p>

<p>The profile is taken from the northeast towards the southwest, based on where we clicked first. You can change the exaggeration of the profile by using the slider on the left. The X axis shows the distance along the profile line in map units and the Y axis shows the cell values from the raster&#8212;in this case, elevation in meters.</p>

<p>You can save the result as a PDF or SVG using the buttons at the bottom of the dialog.</p>

<p>The Statistics tab displays some information for the raster layer and the profile line:</p>

<p><a href="http://spatialgalaxy.net/2012/01/06/qgis-plugin-of-the-week-profile/qgis_profile_statistics/"><img src="http://spatialgalaxy.net/wp-content/qgis_profile_statistics.png" alt="" /></a></p>

<p>If we had additional rasters loaded, we could use the Setup tab to add them to the profile analysis. This would display the results using the colors specified for each layer and we could compare them on the Profile tab.</p>

<p><a href="http://spatialgalaxy.net/2012/01/06/qgis-plugin-of-the-week-profile/qgis_profile_setup/"><img src="http://spatialgalaxy.net/wp-content/qgis_profile_setup.png" alt="" /></a></p>

<p>This is just one of several QGIS plugins that deal with profiles. You can check out the rest of them using the Python Plugin installer.</p>

<p><a name="fn1">[1]</a> The Profile plugin requires the Python module for QWT5. If you don&#8217;t have this installed, a warning will be displayed during the installation process.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Plugin of the Week: Points to Paths]]></title>
    <link href="http://spatialgalaxy.net//2011/12/30/qgis-plugin-of-the-week-points-to-paths/"/>
    <updated>2011-12-30T09:43:58-09:00</updated>
    <id>http://spatialgalaxy.net//2011/12/30/qgis-plugin-of-the-week-points-to-paths</id>
    <content type="html"><![CDATA[<p>This week we highlight the <em>Points to Paths</em> plugin, a handy way to convert a series of points into line features. This plugin lets you &#8220;connect the dots&#8221; based on an common attribute and a sequence field. The attribute field determines which points should be grouped together into a line. The sequence field determines the order in which the points will connected. The output from this plugin is a shapefile.</p>

<!-- more -->


<p>Let&#8217;s take a look at some example data. Here we have some fictional wildlife tracking data for two moose. The tracking data is in shapefile format, but you can use any vector format supported by QGIS. The tracking data is symbolized by our two animals: Moose1 and Moose2:</p>

<p><a href="http://spatialgalaxy.net/2011/12/30/qgis-plugin-of-the-week-points-to-paths/moose_tracks_points/"><img src="http://spatialgalaxy.net/wp-content/moose_tracks_points.png" alt="" /></a></p>

<p>The <em>moose_tracks</em> layer has an animal tracking id field (animal_tid) and a sequence field (id). This is all we need to convert the individual observations into a line feature that represents the animals path.</p>

<h3>Installing the Plugin</h3>

<p>The Points to Paths 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 <em>points to</em> in the Filter box, then select Points to Paths from the list. Once it&#8217;s highlighted, click the <em>Install plugin</em> button. This will download the plugin from the repository, install it, and load it into QGIS.</p>

<h3>Using the Plugin</h3>

<p>Let&#8217;s convert the tracking data to paths. To get started, choose Plugins->Points to Paths from the menu or click on the Points to Paths tool on the Plugin toolbar. This brings up the PointsToPaths dialog box where we specify the paramaters needed to create the paths. Below is the completed dialog for our moose tracks:</p>

<p><a href="http://spatialgalaxy.net/2011/12/30/qgis-plugin-of-the-week-points-to-paths/moose_tracks_dialog/"><img src="http://spatialgalaxy.net/wp-content/moose_tracks_dialog.png" alt="" /></a></p>

<p>The first drop-down box contains a list of the vector layers loaded in QGIS&#8212;in our case we have just one: <em>moose_tracks</em>. For the group field drop-down we chose the field that contains the tracking identifier for each animal. This determines which points will be selected and grouped to form an individual line. The point order field drop-down specifies the field that contains the ordering for the observations. In this case, the id field is incremented with each observation and can be used to construct the paths. We don&#8217;t have a date/time field in this data, but your observations may be sequenced in this way. The Python date format field allows you to specify a format string so the plugin can determine how to sequence your points based on date/time.</p>

<p>The last thing we need to specify is the output shapefile. You can do this by typing in the full path to a new shapefile or by using the Browse button.</p>

<p>With these options set, clicking the OK button will create the new shapefile containing the paths created from our point observations. Once the shapefile is created, the plugin gives you the option to add the new shapefile directly to QGIS.</p>

<h3>The Result</h3>

<p>The result of our simple example are shown below:</p>

<p><a href="http://spatialgalaxy.net/2011/12/30/qgis-plugin-of-the-week-points-to-paths/moose_tracks_result/"><img src="http://spatialgalaxy.net/wp-content/moose_tracks_result.png" alt="" /></a></p>

<p>We symbolized the individual tracks using the Categorized renderer on the Style tab of the vector properties dialog. You can see we now have a track for each animal. The attribute table created by the plugin contains the following fields:</p>

<ul>
<li><p>group - the name of the animal taken from the field we chose as the group field</p></li>
<li><p>begin - the value of the first point order field used to create the path</p></li>
<li><p>end - the value of the last point order field used to create the path</p></li>
</ul>


<p>In our data, <em>group</em> contains the animal name, <em>begin</em> the value of the lowest id field for animal, and <em>end</em> contains the greatest id value. In a more typical data set, begin and end would contain the start and end date/time values for the observation. Labeling the observation points with our sequence field or date/time values would allow us to determine the direction of movement.</p>

<p>If you have point data that represent a movement of an object, this plugin is a great way to convert it into a path that can be used for visualization, analysis, or map composition.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Plugin of the Week: Time Manager]]></title>
    <link href="http://spatialgalaxy.net//2011/12/23/qgis-plugin-of-the-week-time-manager/"/>
    <updated>2011-12-23T10:26:26-09:00</updated>
    <id>http://spatialgalaxy.net//2011/12/23/qgis-plugin-of-the-week-time-manager</id>
    <content type="html"><![CDATA[<p>QGIS has a lot of plugins, including over 180 that have been contributed by users. If you aren&#8217;t using plugins, you are missing out on a lot that QGIS has to offer. I&#8217;m starting what I hope to be a regular feature: <em>Plugin of the Week</em>. This week we&#8217;ll take a look at <a href="http://www.geofrogger.net/trac/wiki">Time Manager</a>.</p>

<p><a href="http://spatialgalaxy.net/2011/12/23/qgis-plugin-of-the-week-time-manager/time_manager_pyqgis-3/"><img src="http://spatialgalaxy.net/wp-content/time_manager_pyqgis2-1024x591.png" alt="Time Manger and QGIS Users" /></a>
Time Manager lets you browse spatial data that has a temporal component. Essentially this includes anything that changes location through time. Examples include:</p>

<ul>
<li>Wildlife tracking</li>
<li>Vehicles</li>
<li>Storm centers</li>
<li>QGIS users</li>
</ul>


<!-- more -->


<h3>Data Preparation</h3>

<p>Expanding on our last post about <a href="http://spatialgalaxy.net/2011/12/19/qgis-users-around-the-world/">QGIS Users Around the World</a>, we&#8217;ll use Time Manager to watch access to the QGIS Python plugin repository through time. If you refer to the previous post, you&#8217;ll see that all the IP addresses contacting the repository were extracted from the web server log and geocoded to get the approximate geographic coordinates. To use Time Manager all we need is the time for each access to the repository.</p>

<p>A important part (for our purpose) of the web server log entry looks like this:</p>

<pre><code>192.168.1.2 - - [23/Oct/2011:21:17:54 +0000] "GET /repo/contributed HTTP/1.1" 200 256
</code></pre>

<p>Time Manager supports date/time in the following formats:</p>

<ul>
<li><p>YYYY-MM-DD HH:MM:SS</p></li>
<li><p>YYYY-MM-DD HH:MM</p></li>
<li><p>YYYY-MM-DD</p></li>
</ul>


<p>As you can see, this doesn&#8217;t work with the format in the web server log.</p>

<p>The geocoding process created a file containing IP address, country, city (where available), latitude and longitude. This file is used to create a Python dictionary to look up locations by IP address. Using this file and a bit of Python, the web server log entries were converted into a CSV file containing:</p>

<pre><code>ip,date_time,country,latitude,longitude
192.168.1.2,2011-10-23 21:13:53,United States,61.2149,-149.258
192.168.1.2,2011-10-23 21:14:22,United States,61.2149,-149.258
192.168.1.2,2011-10-23 21:17:54,United States,61.2149,-149.258
192.168.1.2,2011-10-23 21:18:04,United States,61.2149,-149.258
...
</code></pre>

<p>The CSV file was first converted to a shapefile using the QGIS Delimited Text plugin. Performance with Time Manager was somewhat slow using a shapefile containing 134,171 locations. The shapefile was imported into a SpatiaLite database (you can do this using ogr2ogr or the SpatiaLite GUI).</p>

<h2>Using Time Manager</h2>

<p>To display the progression of access to the repository (and thus users of
QGIS), we first have to have the Time Manager plugin installed.<a href="fn1">[1]</a> Once
installed, we enable it using the Plugin Manger.</p>

<p>As you can see from the screenshot above, Time Manager installs a new panel in QGIS that sits below the map canvas. You can set a number of options by clicking Settings; the most important being the layer to use in the visualization. For the QGIS users, we use the <em>time_manager_req</em> layer that was created from the web server logs. With the location and date/time data in the proper format, you can click the &#8220;Play&#8221; button to start the display. For each time interval, the plugin selects the appropriate entries and displays a frame for the duration specified in the settings.</p>

<p>You can use the time slider to move around or move the time interval forward or backward using the buttons on each end of the slider.</p>

<p>A really nice feature is the ability to export to video. At present this saves
a PNG file and world file for each time interval. You can then use another
software package to combine these to create a video animation of the time
sequence. Once solution is to use <em>mencoder</em><a href="#fn1">[1]</a>:</p>

<pre><code>mencoder "mf://*.PNG" -mf fps=10 -o output.avi -ovc lavc -lavcopts vcodec=mpeg4
</code></pre>

<p>Putting all this together gives us the following visualization of QGIS user activity from October 23 through December 19, 2011:</p>

<iframe width="560" height="315" src="http://www.youtube.com/embed/iwJImIhYyxQ" frameborder="0" allowfullscreen></iframe>


<p>You can see the &#8220;wave&#8221; of activity progress from east to west as the daylight hours come and go.</p>

<h3>Summary</h3>

<p>If you have spatial data with a date or time component, the Time Manager plugin provides a convenient way to visualize the temporal relationships.</p>

<p><a name="fn1">[1]</a> <a href="http://www.geofrogger.net/trac/wiki">http://www.geofrogger.net/trac/wiki</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[QGIS Users Around the World]]></title>
    <link href="http://spatialgalaxy.net//2011/12/19/qgis-users-around-the-world/"/>
    <updated>2011-12-19T08:21:09-09:00</updated>
    <id>http://spatialgalaxy.net//2011/12/19/qgis-users-around-the-world</id>
    <content type="html"><![CDATA[<p>One of the difficult things to track in the open source world is the number of people who actually use your software. In the proprietary commercial world you have licenses, invoices, and so forth. In the case of QGIS, we can track the total number of downloads from qgis.org, but this doesn&#8217;t represent the total installed base. It is impossible to accurately determine the actual number of people using QGIS, but we can get an approximation of the number and where they are in the world.</p>

<!-- more -->


<p>The analysis was done using the log files from the QGIS contributed repository:</p>

<ul>
<li><p>The IP address of each entry that retrieved the plugin list from the server represents one or more users&#8212;these IPs were collected into a unique list</p></li>
<li><p>Using a Python script, each IP address in the log was geocoded to get the approximate latitude and longitude of the user</p></li>
<li><p>The IP address, country, latitude, and longitude were written to a CSV file</p></li>
<li><p>The CSV file was converted to a Spatialite layer to create the map of users</p></li>
</ul>


<p><a href="http://spatialgalaxy.net/2011/12/19/qgis-users-around-the-world/qgis_users/"><img src="http://spatialgalaxy.net/wp-content/qgis_users-1024x633.png" alt="" /></a></p>

<p>The map represents 35,603 unique IP addresses of users that accessed the repository between October 23, 2011 and December 17, 2011.</p>

<p>The geocoding process varies in precision&#8212;some IPs are located to the city level while others only return a general location for the country.</p>

<p>Some assumptions and observations:</p>

<ul>
<li><p>Most (maybe all) users make use of Python plugins and therefore access the contributed repository at some point</p></li>
<li><p>Country-level points (blue) on the map represent more than one user</p></li>
<li><p>Some points represent organizations that use a single IP for all users accessing the Internet. These points will represent more than one user</p></li>
<li><p>Some users may access the repository from more than one IP address</p></li>
</ul>


<p>So how many people use QGIS? At the very minimum, 35,000. We know that the downloads of just the Windows version exceeded 100,000. Given that there are 7,183 IP addresses that are generalized to a country location, we can safely assume that the number of actual users is much higher than that.</p>

<p>Considering the number of points that represent an organization and those that represent a country location, I think we can safely assume that the number of QGIS users easily exceeds 100,000 worldwide.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using git With Multiple QGIS Branches]]></title>
    <link href="http://spatialgalaxy.net//2011/11/14/using-git-with-multiple-qgis-branches/"/>
    <updated>2011-11-14T09:03:15-09:00</updated>
    <id>http://spatialgalaxy.net//2011/11/14/using-git-with-multiple-qgis-branches</id>
    <content type="html"><![CDATA[<p>This post is for those of you that build QGIS on a regular basis and want to keep up with everything going on in the current release branches (1.7.2 and 1.8) as well as the master branch that will eventually become version 2.0.</p>

<p>While you can do all your work in one clone, this method has a couple of advantages, at the expense of a bit of disk space:</p>

<ol>
<li>Quicker compiles compared to branch switching, especially if you are using ccache</li>
<li>Less likelihood of making a merge mess when switching branches</li>
</ol>


<!-- more -->


<p>The basic steps are:</p>

<ol>
<li>Login to github and clone the QGIS repository (<a href="https://github.com/qgis/Quantum-GIS">https://github.com/qgis/Quantum-GIS</a>)</li>
<li>Create a working copy of your github clone on your machine</li>
<li>Add a reference to the upstream repository</li>
<li>Fetch and merge (if required) from the upstream repository</li>
<li>Create a new clone for the branch by cloning the working copy created in step 2</li>
<li>Change to the branch clone directory</li>
<li>Add the upstream remote</li>
<li>Fetch from upstream</li>
<li>Create the tracking branch</li>
<li>Checkout the branch</li>
</ol>


<p>It&#8217;s simpler than it sounds&#8212;the following steps should work on any platform and assume you have already created your own clone of the QGIS repository on github.</p>

<p>First make a directory for development, change to it, and fetch a copy of your clone of QGIS from github (this will take a while):</p>

<pre><code>gsherman@dork:~$ mkdir qgis_dev
gsherman@dork:~$ cd qgis_dev
gsherman@dork:~/qgis_dev$ git clone git@github.com:g-sherman/Quantum-GIS.git
Cloning into Quantum-GIS...
remote: Counting objects: 183812, done.
remote: Compressing objects: 100% (42255/42255), done.
remote: Total 183812 (delta 140627), reused 183281 (delta 140221)
Receiving objects: 100% (183812/183812), 240.80 MiB | 1.19 MiB/s, done.
Resolving deltas: 100% (140627/140627), done.
</code></pre>

<p>Now change to your new clone directory and add the upstream repository (the QGIS repo on github):</p>

<pre><code>gsherman@dork:~/qgis_dev$ cd Quantum-GIS/
gsherman@dork:~/qgis_dev/Quantum-GIS$ git remote add upstream git@github.com:qgis/Quantum-GIS.git
</code></pre>

<p>We can then list our config to see that the remote was added:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS$ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=git@github.com:g-sherman/Quantum-GIS.git
branch.master.remote=origin
branch.master.merge=refs/heads/master
remote.upstream.url=git@github.com:qgis/Quantum-GIS.git
remote.upstream.fetch=+refs/heads/*:refs/remotes/upstream/*
</code></pre>

<p>Then we do a fetch from the QGIS repo to make sure things are up to date:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS$ git fetch upstream
</code></pre>

<p>If your clone of the QGIS repository on github is not brand new, you should do a merge before proceeding:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS$ git merge upstream/master
</code></pre>

<p>Now we can create a new clone for the 1.7.2 branch using our local master:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS$ cd ..
gsherman@dork:~/qgis_dev$ git clone ./Quantum-GIS Quantum-GIS-1_7_2
Cloning into Quantum-GIS-1_7_2...
done.
</code></pre>

<p>Now we need to add the remote for the main QGIS repository:</p>

<pre><code>gsherman@dork:~/qgis_dev$ cd Quantum-GIS-1_7_2/
gsherman@dork:~/qgis_dev/Quantum-GIS-1_7_2$ git remote add upstream git@github.com:qgis/Quantum-GIS.git
</code></pre>

<p>The next step is to fetch from upstream to make sure we have references to the branches:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS-1_7_2$ git fetch upstream
 * [new branch]      dev-threading -&gt; upstream/dev-threading
 * [new branch]      master     -&gt; upstream/master
 * [new branch]      release-0_0_11 -&gt; upstream/release-0_0_11
 * [new branch]      release-0_0_12 -&gt; upstream/release-0_0_12
 ...
 * [new branch]      release-1_7_1 -&gt; upstream/release-1_7_1
 * [new branch]      release-1_7_2 -&gt; upstream/release-1_7_2
 * [new branch]      release-1_8 -&gt; upstream/release-1_8
</code></pre>

<p>Now we create the branch to track the release of interest&#8212;in this case 1.7.2:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS-1_7_2$ git branch --track release-1_7_2 upstream/release-1_7_2
Branch release-1_7_2 set up to track remote branch release-1_7_2 from upstream.
</code></pre>

<p>The last step is to check out the branch which should go pretty quick:</p>

<pre><code>gsherman@dork:~/qgis_dev/Quantum-GIS-1_7_2$ git checkout release-1_7_2
Checking out files: 100% (1809/1809), done.
Switched to branch 'release-1_7_2'
</code></pre>

<p>You are now ready to build the 1.7.2 release branch. Repeat the process for any other branches you want to track.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using the QGIS Plugin Builder]]></title>
    <link href="http://spatialgalaxy.net//2011/10/27/using-the-qgis-plugin-builder/"/>
    <updated>2011-10-27T07:14:55-08:00</updated>
    <id>http://spatialgalaxy.net//2011/10/27/using-the-qgis-plugin-builder</id>
    <content type="html"><![CDATA[<p>The Plugin Builder allows you to quickly create a skeleton Python plugin by generating all that boring boilerplate that every plugin requires.</p>

<p>Here is a short video showing how to create, compile, and install a new plugin.</p>

<iframe width="420" height="315" src="http://www.youtube.com/embed/eWNEcJYnkPQ" frameborder="0" allowfullscreen></iframe>


<p>For more information, see <a href="http://www.qgisworkshop.org/html/index.html">QGIS Workshop Documentation</a> and the <a href="http://www.qgis.org/pyqgis-cookbook">PyQGIS Cookbook</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Search QGIS IRC Logs]]></title>
    <link href="http://spatialgalaxy.net//2011/09/24/search-qgis-irc-logs/"/>
    <updated>2011-09-24T08:13:20-08:00</updated>
    <id>http://spatialgalaxy.net//2011/09/24/search-qgis-irc-logs</id>
    <content type="html"><![CDATA[<p>I added a simple feature that allows you to search the IRC logs from #qgis back to May 10, 2006.</p>

<p>The search is case sensitive and will return a list of all matches. Not too smart but it will get you close to what you want.</p>

<p>See the link at <a href="http://irclogs.geoapt.com/qgis">http://irclogs.geoapt.com/qgis</a></p>
]]></content>
  </entry>
  
</feed>
