Blog d’Anita Graser

https://anitagraser.com

  • My favorite new recipe in QGIS Map Design 2nd ed 10 novembre 2018
    If you follow me on Twitter, you have probably already heard that the ebook of “QGIS Map Design 2nd Edition” has now been published and we are expecting the print version to be up for sale later this month. Gretchen Peterson and I – together with our editor Gary Sherman (yes, that Gary Sherman!) – have been working hard to provide you with tons of new and improved map design workflows and many many completely new maps. By Gretchen’s count, this edition contains 23 new maps, so it’s very hard to pick a favorite! Like the 1st edition, we provide increasingly advanced recipes in three chapters, each focusing on either layer styling, labeling, or creating print layouts. If I had to pick a favorite, I’d have to go with “Mastering Rotated Maps”, one of the advanced recipes in the print layouts chapter. It looks deceptively simple but it combines a variety of great QGIS features and clever ideas to design a map that provides information on multiple levels of detail. Besides the name inspiring rotated map items, this design combines map overviews map themes graduated lines and polygons a rotated north arrow fancy leader lines all in one: “QGIS Map Design 2nd Edition” provides how-to instru …
  • Geocoding with Geopy 11 septembre 2018

    Need to geocode some addresses? Here’s a five-lines-of-code solution based on “An A-Z of useful Python tricks” by Peter Gleeson:

    from geopy import GoogleV3
    place = "Krems an der Donau"
    location = GoogleV3().geocode(place)
    print(location.address)
    print("POINT({},{})".format(location.latitude,location.longitude))
    

    For more info, check out geopy:

    geopy is a Python 2 and 3 client for several popular geocoding web services.
    geopy includes geocoder classes for the OpenStreetMap Nominatim, ESRI ArcGIS, Google Geocoding API (V3), Baidu Maps, Bing Maps API, Yandex, IGN France, GeoNames, Pelias, geocode.earth, OpenMapQuest, PickPoint, What3Words, OpenCage, SmartyStreets, GeocodeFarm, and Here geocoder services.

  • Plotting GPS Trajectories with error ellipses using Time Manager 4 septembre 2018
    This is a guest post by Time Manager collaborator and Python expert, Ariadni-Karolina Alexiou. Today we’re going to look at how to visualize the error bounds of a GPS trace in time. The goal is to do an in-depth visual exploration using QGIS and Time Manager in order to learn more about the data we have. The Data We have a file that contains GPS locations of an object in time, which has been created by a GPS tracker. The tracker also keeps track of the error covariance matrix for each point in time, that is, what confidence it has in the measurements it gives. Here is what the file looks like: Error Covariance Matrix What are those sd* fields? According to the manual: The estimated standard deviations of the solution assuming a priori error model and error parameters by the positioning options. What it basically means is that the real GPS location will be located no further than three standard deviations across north and east from the measured location, most of (99.7%) the time. A way to represent this visually is to create an ellipse that maps this area of where the real location can be. An ellipse can be uniquely defined from the lengths of the segments a and b and its rotation a …
  • Movement data in GIS #15: writing a PL/pgSQL stop detection function for PostGIS trajectories 19 juillet 2018
    Do you sometimes start writing an SQL query and around at line 50 you get the feeling that it might be getting out of hand? If so, it might be useful to start breaking it down into smaller chunks and wrap those up into custom functions. Never done that? Don’t despair! There’s an excellent PL/pgSQL tutorial on postgresqltutorial.com to get you started. To get an idea of the basic structure of a PL/pgSQL function and to proof that PostGIS datatypes work just fine in this context, here’s a basic function that takes a trajectory geometry and outputs its duration, i.e. the difference between its last and first timestamp: CREATE OR REPLACE FUNCTION AG_Duration(traj geometry) RETURNS numeric LANGUAGE ‘plpgsql’ AS $BODY$ BEGIN RETURN ST_M(ST_EndPoint(traj))-ST_M(ST_StartPoint(traj)); END; $BODY$; My end goal for this exercise was to implement a function that takes a trajectory and outputs the stops along this trajectory. Commonly, a stop is defined as a long stay within an area with a small radius. This leads us to the following definition: CREATE OR REPLACE FUNCTION AG_DetectStops( traj geometry, max_size numeric, min_duration numeric) RETURNS TABLE(sequence integer, geom geometry) — imp …
  • Movement data in GIS #14: updates from GI_Forum 2018 9 juillet 2018
    Last week, I traveled to Salzburg to attend the 30th AGIT conference and co-located English-speaking GI_Forum. Like in previous year, there were a lot of mobility and transportation research related presentations. Here are my personal highlights: This year’s keynotes touched on a wide range of issues, from Sandeep Singhal (Google Cloud Storage) who – when I asked about the big table queries he showed – stated that they are not using a spatial index but are rather brute-forcing their way through massive data sets, to Laxmi Ramasubramanian @nycplanner (Hunter College City University of New York) who cautioned against tech arrogance and tendency to ignore expertise from other fields such as urban planning: Next up: Sandeep Singhal Director, @Google Cloud Storage #GIForum2018 pic.twitter.com/fiRL9TUNpr — Anita Graser (@underdarkGIS) July 4, 2018 https://platform.twitter.com/widgets.js One issue that Laxmi particularly highlighted was the fact that many local communities are fighting excessive traffic caused by apps like Waze that suggest shortcuts through residential neighborhoods. Just because we can do something with (mobility) data, doesn’t necessarily mean that we should! L. Ramasu …
  • PyQGIS for non-programmers 6 juin 2018
    If you’re are following me on Twitter, you’ve certainly already read that I’m working on PyQGIS 101 a tutorial to help GIS users to get started with Python programming for QGIS. I’ve been toying around with the idea of a PyQGIS intro for non-programmers without all the boring parts of vanilla Python tutorials. Not sure how far this will go, but it’s a start: https://t.co/nbO5tm2ZW9 — Anita Graser (@underdarkGIS) May 31, 2018 https://platform.twitter.com/widgets.js I’ve often been asked to recommend Python tutorials for beginners and I’ve been surprised how difficult it can be to find an engaging tutorial for Python 3 that does not assume that the reader already knows all kinds of programming concepts. It’s been a while since I started programming, but I do teach QGIS and Python programming for QGIS to university students and therefore have some ideas of which concepts are challenging. Nonetheless, it’s well possible that I overlook something that is not self explanatory. If you’re using PyQGIS 101 and find that some points could use further explanations, please leave a comment on the corresponding page. PyQGIS 101 is a work in progress. I’d appreciate any feedback, particularly fro …
  • Scalable spatial vector data processing 18 mai 2018
    Working with movement data analysis, I’ve banged my head against performance issues every once in a while. For example, PostgreSQL – and therefore PostGIS – run queries in a single thread of execution. This is now changing, with more and more functionality being parallelized. PostgreSQL version 9.6 (released on 2016-09-29) included important steps towards parallelization, including parallel execution of sequential scans, joins and aggregates. Still, there is no parallel processing in PostGIS so far (but it is under development as described by Paul Ramsey in his posts “Parallel PostGIS II” and “PostGIS Scaling” from late 2017). At the FOSS4G2016 in Bonn, I had the pleasure to chat with Shoaib Burq who ran the “An intro to Apache PySpark for Big Data GeoAnalysis” workshop. Back home, I downloaded the workshop material and gave it a try but since I wanted a scalable system for storing, analyzing, and visualizing spatial data, it didn’t really seem to fit the bill. Around one year ago, my search grew more serious since we needed a solution that would support our research group’s new projects where we expected to work with billions of location records (timestamped points and associated …
  • Movement data in GIS #13: timestamp labels for trajectories 9 mai 2018
    In Movement data in GIS #2: visualization I mentioned that it should be possible to label trajectory segments without having to break the original trajectory feature. While it’s not a straightforward process, it is indeed possible to create timestamp labels at desired intervals: The main point here is that we cannot use regular labels because there would be only one label for the whole trajectory feature. Instead, we are using a marker line with a font marker: By default, font markers only display one character from a given font but by using expressions we can make it display longer text, including datetime strings: If you want to have a label at every node of the trajectory, the expression looks like this: format_date( to_datetime(‘1970-01-01T00:00:00Z’)+to_interval( m(start_point(geometry_n( segments_to_lines( $geometry ), @geometry_part_num) ))||’ seconds’ ), ‘HH:mm:ss’ ) You probably remember those parts of the expression that extract the m value from previous posts. Note that – compared to 2016 – it is now necessary to add the segments_to_lines() function. The m value (which stores time as seconds since Unix epoch) is then converted to datetime and finally formatted to only sh …
  • Movement data in GIS #12: why you should be using PostGIS trajectories 16 avril 2018
    In short: both writing trajectory queries as well as executing them is considerably faster using PostGIS trajectories (as LinestringM) rather than the commonly used point-based approach. Here are a couple of examples to give you an impression of the differences. Spoiler alert! Trajectory queries are up to 500 times faster than comparable point-based queries. A quick look at indexing In both cases, we have indexed the tracker id, geometry, and time columns to speed up query processing. The trajectory table has 3 indexes gist (time_range) gist (track gist_geometry_ops_nd) btree (tracker) The point-based table has 4 indexes gist (pt) btree (trajectory_id) btree (tracker) btree (t) Length First, let’s see how to determine trajectory length for all observed moving objects (identified by a tracker id). Using the point-based approach, we first need to ensure that the points are in the correct temporal order, create the lines, and finally sum up their length: WITH ordered AS ( SELECT trajectory_id, tracker, t, pt FROM geolife.trajectory_pt ORDER BY t ), tmp AS ( SELECT trajectory_id, tracker, st_makeline(pt) traj FROM ordered GROUP BY trajectory_id, tracker ) SELECT tracker, round(sum(ST_L …
  • Optional parameters in QGIS Processing scripts & models 1 avril 2018
    Remember the good old times when all parameters in Processing were mandatory? Inputs and outputs are fixed, and optional parameters or outputs are not supported. [Graser & Olaya, 2015] Since QGIS 2.14, this is no longer the case. Scripts, as well as models, can now have optional parameters. Here is how for QGIS 3: When defining a Processing script parameter, the parameter’s constructor takes a boolean flag indicating whether the parameter should be optional. It’s false by default: class qgis.core.QgsProcessingParameterNumber( name: str, description: str =  »,  type: QgsProcessingParameterNumber.Type = QgsProcessingParameterNumber.Integer,  defaultValue: Any = None,  optional: bool = False,  minValue: float = -DBL_MAX+1, maxValue: float = DBL_MAX) (Source: http://python.qgis.org/api/core/Processing/QgsProcessingParameterNumber.html) One standard tool that uses optional parameters is Add autoincremental field: From Python, this algorithm can be called with or without the optional parameters: When building a model, an optional input can be assigned to the optional parameter. To create an optional input, make sure to deactivate the mandatory checkbox at the bottom of the input parameter …