There are lots of ways to figure out where you’re going in Calgary. You can use a general-purpose map service like Google Maps or Apple Maps, one of the City of Calgary’s single-purpose mobile apps (e.g. Pathways and Bikeways), 511AB, or even that paper map that you forgot is in your glovebox. However, all of these options have issues:
- Generalised maps aren’t suited to Calgary’s unique features. For example, Google Maps will always tell users to walk along the sidewalks downtown, even if the Plus 15 is faster (and warmer).
- The City of Calgary’s apps target a specific task (e.g. finding bike paths), forcing users to download multiple apps if they want to get around in multiple ways. The current apps have received a rather mixed response from Calgarians (the Bikeways and Pathways app is sitting at 1.8/5 stars as of writing), and there is no official Plus 15 map for mobile or web (the closest thing is a PDF of the Plus 15, optimised for print).
- 511AB is built purely for driving, and only includes resources from the government of Alberta, meaning it misses out on a wealth of information available from the City of Calgary.
With this in mind, and with the City of Calgary considering the development of yet another map app specifically for the Plus 15, I decided to make a single mobile friendly map that would aid Calgarians in getting around on foot, by bike, and by car.
Early Stages: the Jupyter Prototype and Codeacross
In the days leading up to the CivicTechYYC Codeacross hackathon, I slapped together a quick proof of concept for what I imagined Omnimap could be. It was written using Folium, and needs to be re-executed manually to update the map. It also dumps a single, monolithic HTML file with everything inside, due to the nature of Folium.
A the beginning of Codeacross, I presented my idea (presentation below) and got a small team together to brainstorm ideas. You can see a few screenshots of the pre-hackathon map in the presentation.
During the hackathon, my team and I came up with a number of potential features and enhancement, and I even managed to squeeze a couple into the proof of concept. Here’s the map by the end of the event:
The Leaflet Rewrite
Of course, a Jupyter notebook that slowly plops out 20MB HTML files is not exactly what I’d call a production-ready web app. The next step was to rebuild Omnimap from the ground up using proper Leaflet and JS. One of the design decisions I made from the very beginning of this rewrite was to build almost all the overlays on top of the excellent Leaflet Realtime plugin. This means that all data sources that could reasonably be considered “live” data are updated in real time, making Omnimap a functional live dashboard. As of the time of writing, every overlay layer in Omnimap is a Leaflet Realtime layer.
I also decided that if all possible, all data sources read by the client should be proper GeoJSON. To that end, I wrote a small Python module to generate GeoJSON strings for all sources that do not already provide it, which can then be integrated into pretty much any Python web server (I’m using Flask). This means that if, in the future, another frontend were to be developed (for example, a native mobile turn-by-turn app), integrating all of the data sources from the webapp should be fairly simple.
91 commits, 600+ lines of JS, and a bit of CSS later, and Omnimap is now in a fairly usable state. It has plenty of information from both the City of Calgary and the Government of Alberta, navigation for driving, biking, and walking, and is designed to work across almost all device form factors. Loading the entire page, including the basemap, without cache, requires only 1.4MB of data. That’s less than 10 seconds on first load with a 3G connection.
The Public Release
I am now proud to say that Omnimap is ready for public eyes. Feel free to try it yourself at python.ryan.hattie.codes/omnimap.