Latest news will appear here soon.

Tag: en_gb

Wrangling hundreds of GPS files with DuckDB, QGIS & Trajectools

The last time I preprocessed the whole GeoLife dataset, I loaded it into PostGIS. Today, I want to share a new workflow that creates a (Geo)Parquet file and that is much faster.

The dataset (GeoLife)

“This GPS trajectory dataset was collected in (Microsoft Research Asia) Geolife project by 182 users in a period of over three years (from April 2007 to August 2012). A GPS trajectory of this dataset is represented by a sequence of time-stamped points, each of which contains the information of latitude, longitude and altitude. This dataset contains 17,621 trajectories with a total distance of about 1.2 million kilometers and a total duration of 48,000+ hours. These trajectories were recorded by different GPS loggers and GPS-phones, and have a variety of sampling rates. 91 percent of the trajectories are logged in a dense representation, e.g. every 1~5 seconds or every 5~10 meters per point.”

The GeoLife GPS Trajectories download contains 182 directories full of .plt files:

Basically, CSV files with a custom header:

Creating the (Geo)Parquet using DuckDB

DuckDB installation

Following the official instructions, installation is straightforward:

curl https://install.duckdb.org | sh

From there, I’ve been using the GUI which we can launch using:

duckdb -ui

The spatial extension is a DuckDB core extension, so it’s readily available. We can create a spatial db with:

ATTACH IF NOT EXISTS ':memory:' AS memory;
INSTALL spatial;
LOAD spatial;

Reading a spatial file is as simple as:

SELECT * 
FROM '/home/anita/Documents/Codeberg/trajectools/sample_data/geolife.gpkg'

thanks to the GDAL integration.

But today, we want to do to get a bit more involved …

DuckDB SQL magic

The issues we need to solve are:

  1. Read all CSV files from all subdirectories
  2. Parse the CSV, ignoring the first couple of lines, while assigning proper column names
  3. Assign the CSV file name as the trajectory ID (because there is no ID in the original files)
  4. Create point geometries that will work with our GeoParquet file
  5. Create proper datetimes from the separate date and time fields

Luckily, DuckDB’s read_csv function comes with the necessary features built-in. Putting it all together:

CREATE OR REPLACE TABLE geolife AS 
SELECT 
  parse_filename(filename, true) as vehicle_id, 
  strptime(date||' '||time, '%c') as t, 
  ST_Point(lon, lat) as geometry -- do NOT use ST_MakePoint
FROM read_csv('/home/anita/Documents/Geodata/Geolife/Geolife Trajectories 1.3/Data/*/*/*.plt',
    skip=6,
    filename = true, 
    columns = {
        'lat': 'DOUBLE', 
        'lon': 'DOUBLE', 
        'ignore': 'INT', 
        'alt': 'DOUBLE', 
        'epoch': 'DOUBLE', 
        'date': 'VARCHAR',
        'time': 'VARCHAR'
    });

It’s blazingly fast:

I haven’t tested reading directly from ZIP archives yet, but there seems to be a community extension (zipfs) for this exact purpose.

Ready to QGIS

GeoParquet files can be drag-n-dropped into QGIS:

I’m running QGIS 3.42.1-Münster from conda-forge on Linux Mint.

Yes, it takes a while to render all 25 million points … But you know what? It get’s really snappy once we zoom in closer, e.g. to the situation in Germany:

Let’s have a closer look at what’s going on here.

Trajectools time

Selecting the 9,438 points in this extent, let’s compute movement metrics (speed & direction) and create trajectory lines:

Looks like we have some high-speed sections in there (with those red > 100 km/h streaks):

When we zoom in to Darmstadt and enable the trajectories layer, we can see each individual trip. Looks like car trips on the highway and walks through the city:

That looks like quite the long round trip:

Let’s see where they might have stopped to have a break:

If I had to guess, I’d say they stayed at the Best Western:

Conclusion

DuckDB has been great for this ETL workflow. I didn’t use much of its geospatial capabilities here but I was pleasantly surprised how smooth the GeoParquet creation process has been. Geometries are handled without any special magic and are recognized by QGIS. Same with the timestamps. All ready for more heavy spatiotemporal analysis with Trajectools.

If you haven’t tried DuckDB or GeoParquet yet, give it a try, particularly if you’re collaborating with data scientists from other domains and want to exchange data.

Learn More

[Blog] Best practices for user management in Mergin Maps

Avoid login sharing in Mergin Maps to stay secure, maintain project integrity, and unlock full workspace features with flexible user roles.
Learn More

[Case Study] Ensuring regulatory compliance for water distribution in Portugal

Discover how EDIA uses Mergin Maps and QGIS to digitize environmental compliance surveys across 130k+ hectares with reliable, offline-capable tools.
Learn More

[Case Study] Involving communities in conservation through citizen science

Discover how the Green Giants project by VERDE engages local communities in conserving Portugal’s native forests through citizen science. Using Mergin Maps and QGIS, volunteers have mapped over 15,000 monumental trees, fostering collaboration, knowledge-sharing, and biodiversity protection.
Learn More

How we build Mergin Maps to run on your phone

Learn how Mergin Maps runs QGIS on mobile devices using 126+ C++ libraries. Discover our journey from custom bash scripts to vcpkg dependency management, making mobile GIS development more accessible for the community.
Learn More

[Blog] Create professional survey reports using QGIS Print Layout after field data collection

Learn how to turn Mergin Maps field data into professional QGIS reports using maps, tables, photos, and Atlas automation for stakeholder-ready results.
Learn More

QChat as it never was

Reasons and technical explanations for the redesign of QChat, the system for chatting with peers in QGIS.
Learn More

QField 3.7 “Haida Gwaii”: Polishing a great experience

For QField 3.7, we opted for a shorter development cycle that focused on polishing preexisting functionalities from feature form editor widgets improvement through to better nearby Bluetooth device discovery. Of course, we couldn’t help ourselves and still packed in some nice functionality that we thought deserved to reach QField’s growing community as soon as possible.

Main highlights

One of the most interesting new functionalities from this development cycle has been the ability to stamp details on photos taken by QField’s in-app camera. A basic version of this has been supported for a while now; this new version offers flexible customisation of details stamping onto photos, including changing the font size, colour, and horizontal position, as well as providing users with the ability to completely change the details via expression-driven templates and add image overlays onto the photo.

The custom details stamping configuration lives within project files, allowing for individual projects to drive styling and details. The configuration interface is provided by QFieldSync and can be found in the project properties dialog by switching to the QField panel when setting up projects in QGIS:

The other significant addition in this release is the new plugin manager’s Available Plugins tab, which offers a curated list of plugins that can easily be installed with a single tap. The list makes it much easier to discover plugin-delivered functionalities such as online routing, geocoding searches, and much more.

The plugin manager can also alert users of available updates for their installed plugins, ensuring that crucial bug fixes and improvements are easily delivered. When a new version is released, users can update via a single tap. We are looking into the possibility of enabling automated plugin upgrades soon.

Long-time users of QField are probably aware of a nifty feature that allowed individual project layers to be locked, and for that lock to be driven by a data-defined property expression. For this new version, we’ve supercharged the layer lock functionality by breaking it down into four distinct vector layer permissions that can be disabled: i) feature addition, ii) attribute editing, iii) geometry editing, and iv) feature deletion. These permissions can be disabled by activating a checkbox or conditionality turned on via a data-defined property expression.

The disabling of permissions using a data-defined property expression allows for interesting scenarios when paired with QField-driven expression context variables such as the user name of a logged-in QFieldCloud account (@cloud_username), GNSS positioning (@gnss_coordinate) and more. Users can easily restrict permissions based on the user interacting with a cloud project, or form advanced geofencing-like rules based on location, time of the day, etc. For more details on available variables, read this page on QField’s growing documentation site.

Improvements all around

As mentioned above, this version focused on polishing preexisting functionality. Noteworthy improvements include:

  • support for multiple column display as well as the ability to filter value relation lists;
  • support for reversing the sorting order of the relationship editor’s children lists;
  • smoother scanning process to discover nearby Bluetooth devices when adding external GNSS devices; and
  • support for feature identification against vector tile layers (give that a try with the new OpenStreetMap shortbread vector tiles!).

Finally, life for QFieldCloud users has improved with the support for resuming large file downloads when fetching a cloud project, eliminating the need to restart from scratch after an interruption due to poor connectivity. In addition, users will notice a new notification badge on the top-left main menu button, indicating that a cloud project has pending changes ready to be pushed to the server.

We hope you enjoy this new version as much as we do delivering it to you. Happy field mapping!

Learn More

QField 3.7 “Haida Gwaii”: Polishing a great experience

For QField 3.7, we opted for a shorter development cycle that focused on polishing preexisting functionalities from feature form editor widgets improvement through to better nearby Bluetooth device discovery. Of course, we couldn’t help ourselves and still packed in some nice functionality that we thought deserved to reach QField’s growing community as soon as possible.

Main highlights

One of the most interesting new functionalities from this development cycle has been the ability to stamp details on photos taken by QField’s in-app camera. A basic version of this has been supported for a while now; this new version offers flexible customisation of details stamping onto photos, including changing the font size, colour, and horizontal position, as well as providing users with the ability to completely change the details via expression-driven templates and add image overlays onto the photo.

The custom details stamping configuration lives within project files, allowing for individual projects to drive styling and details. The configuration interface is provided by QFieldSync and can be found in the project properties dialog by switching to the QField panel when setting up projects in QGIS:

The other significant addition in this release is the new plugin manager’s Available Plugins tab, which offers a curated list of plugins that can easily be installed with a single tap. The list makes it much easier to discover plugin-delivered functionalities such as online routing, geocoding searches, and much more.

The plugin manager can also alert users of available updates for their installed plugins, ensuring that crucial bug fixes and improvements are easily delivered. When a new version is released, users can update via a single tap. We are looking into the possibility of enabling automated plugin upgrades soon.

Long-time users of QField are probably aware of a nifty feature that allowed individual project layers to be locked, and for that lock to be driven by a data-defined property expression. For this new version, we’ve supercharged the layer lock functionality by breaking it down into four distinct vector layer permissions that can be disabled: i) feature addition, ii) attribute editing, iii) geometry editing, and iv) feature deletion. These permissions can be disabled by activating a checkbox or conditionality turned on via a data-defined property expression.

The disabling of permissions using a data-defined property expression allows for interesting scenarios when paired with QField-driven expression context variables such as the user name of a logged-in QFieldCloud account (@cloud_username), GNSS positioning (@gnss_coordinate) and more. Users can easily restrict permissions based on the user interacting with a cloud project, or form advanced geofencing-like rules based on location, time of the day, etc. For more details on available variables, read this page on QField’s growing documentation site .

Improvements all around

As mentioned above, this version focused on polishing preexisting functionality. Noteworthy improvements include:

  • support for multiple column display as well as the ability to filter value relation lists;
  • support for reversing the sorting order of the relationship editor’s children lists;
  • smoother scanning process to discover nearby Bluetooth devices when adding external GNSS devices; and
  • support for feature identification against vector tile layers (give that a try with the new OpenStreetMap shortbread vector tiles!).

Finally, life for QFieldCloud users has improved with the support for resuming large file downloads when fetching a cloud project, eliminating the need to restart from scratch after an interruption due to poor connectivity. In addition, users will notice a new notification badge on the top-left main menu button, indicating that a cloud project has pending changes ready to be pushed to the server.

We hope you enjoy this new version as much as we do delivering it to you. Happy field mapping!

Learn More