Map visualizations are more complicated than standard charts because you’re actually visualizing two distinct types of data: yes, you still have your quantitative data that you want to visualize but you also have to provide Highcharts Maps for Python with the map data on which your quantitative data should be visualized.
How you supply your map data to Highcharts Maps for Python is a very important question because it can have significant performance implications for your code. Map data can be very verbose, and as such it can take a relatively time on the wire. For this reason, Highcharts Maps for Python lets you choose where your map data actually gets loaded: in your Python code, or in the JavaScript code produced by Highcharts Maps for Python.
Tip
Best practice: Because map data can be verbose and relatively large on the wire, we typically prefer to load it asynchronously in the JavaScript code produced by Highcharts Maps for Python. We’ll only load it synchronously in Python if our use case really calls for it (for example, programmatic creation of charts for download).
Applying Map Data
If you load your map data synchronously in your Python code, you’ll configure your map data using a MapData
instance. If you load your map data asynchronously in your JavaScript code, then in Python you’ll set your configuration up using an AsyncMapData
instance.
In both cases, you can apply your map data to either the Chart instance as a whole using the Chart
instance’s .set_map_data()
method, or to a specific series instance using that series instance’s .set_map_data()
method. The syntax for this method is the same, whether you’re using AsyncMapData
or MapData
. Assuming your Chart
instance is called my_chart
and your map data is in a variable called my_map_data
you just call:
# Set the chart’s map data, configured to load asynchronously my_chart.set_map_data(my_map_data)
And that’s it! Highcharts Maps for Python offers some convenience capabilities as well. For example, if you pass the .set_map_data()
method a URL, Highcharts Maps for Python will automatically convert that to an AsyncMapData
instance that will download your map data from that URL.
Configuring Your AsyncMapData
While setting up asynchronous map data can be as simple as supplying a URL to the .set_map_data()
method, there are often situations where it can prove more complicated. For example, what if to access your map data you need to provide authentication credentials? Or what if you need to download a bunch of map data, but only use a subset of that map data in your visualization? Highcharts Maps for Python has you covered: The AsyncMapData
class offers you a wide range of configuration options.
Authentication Credentials and Fetch Configuration
Highcharts Maps for Python gives you complete control over how your JavaScript code fetches your map data. When creating your AsyncMapData
instance, you can supply a fetch_config
property which configures how the JavaScript fetch()
call is executed.
The fetch_config
property accepts a FetchConfiguration
instance. In a typical use case, you would use the FetchConfiguration
’s credentials
and header
properties to supply authentication credentials with your request. Let’s imagine you are using Bearer authentication. You would set your AsyncMapData
instance up as follows:
from highcharts_maps.options.series.data.map_data import AsyncMapData from highcharts_maps.utility_classes.fetch_configuration import FetchConfiguration # Set the chart’ s map data, configured to load asynchronously my_fetch_config = FetchConfiguration(headers = { 'Authorization’: ' Bearer ' }) my_map_data = AsyncMapData(url = 'https://www.my-map-data-url.dev/map-data.topo.json', fetch_config = my_fetch_config)
And that’s it! By default, the AsyncMapData
uses the HTTP GET method to download your map data, but if you need to use a different HTTP method (like POST or something similar) you can easily override the default using the fetch_config
properties.
Using Selector Functions for Subsets of Map Data
Sometimes, you want to use only a subset of your map data in your data visualization. For example, you might want to show a map inset with more granular detail, or your geometry may contain multiple areas but your user is only interested in one, or perhaps you want to optimize your client-side performance by having your user download geometries once to cache them locally, and then rapidly switch between areas that are visualized. Highcharts Maps for Python allows you to do that by defining the .selector
property on your AsyncMapData
instance.
The .selector
property lets you define a JavaScript callback function which receives one argument: topology
, which retrieves the map data downloaded from your AsyncMapData
instance’s .url
property. Your JavaScript function can then perform whatever manipulations it needs to on the originally-downloaded topology. This can include selecting a subset of geometries from it, or even modifying the geometries that have been received. It’s entirely up to you – provided that when all of your function’s work is done, it returns a single JSON (or GeoJSON, or TopoJSON) object with a new set of geometries that your chart will then visualize.
But how do you define a JavaScript function in Python? Using Highcharts Maps for Python, that is pretty simple: you create a CallbackFunction
instance and supply it to the .selector
property.
There are two ways to do this. The easiest way is to pass your JavaScript function as a string to the selector
keyword argument when creating your AsyncMapData
instance. Highcharts Maps for Python will automatically take that string and convert it to a CallbackFunction
instance:
from highcharts_maps.options.series.data.map_data import AsyncMapData from highcharts_maps.utility_classes.fetch_configuration import FetchConfiguration # Set the chart’ s map data, configured to load asynchronously my_map_data = AsyncMapData(url = 'https://www.my-map-data-url.dev/map-data.topo.json', selector = "" "function (topology) { ... return newTopology; } "" ")
As you can see, in the example above we’re just passing a JavaScript function as a string to the selector
argument. That function takes one argument: topology
(the name matters) and it returns one object (its name does not matter, but we called it newTopology just to differentiate).
Tip
Best practice: When supplying JavaScript code as strings to Highcharts Maps for Python, we recommend that you wrap the string in three double quotes, rather than a more conventional single quote, or even the sometimes seen double-quote. This is because by wrapping your string in three double quotes you will likely be able to avoid any escape characters in your JavaScript, making it much more readable and maintainable.
We find that this approach is the easiest way to do it, since Highcharts Maps for Python does the heavy lifting for you. But if you want to create a CallbackFunction instance manually, you can do so as well:
from highcharts_maps.options.series.data.map_data import AsyncMapData from highcharts_maps.utility_classes.javascript_functions import CallbackFunction # Define your CallbackFunction instance my_selector = CallbackFunction(arguments = ['topology'], body = "" " ... return newTopology; "" ") # Set the chart’ s map data, configured to load asynchronously my_map_data = AsyncMapData(url = 'https://www.my-map-data-url.dev/map-data.topo.json', selector = my_selector)
The code above is equivalent to the first code sample provided – just in this case we are manually creating a CallbackFunction
instance.
And that’s it! You’ve now got your map visualizations loading and managing your geographies asynchronously in your client-side environment.
Visualizing Your Visualizations
Now when you call your Chart
instance’s .to_js_literal()
method, Highcharts Maps for Python will generate several JavaScript statements:
- The first will issue an asynchronous
fetch()
call to download your map geometry. - The second will – if your
AsyncMapData
instance is using aselector
function – run your selector function on the downloaded map data. - And the last one will actually visualize your chart, supplying the relevant map data to it as configured.
And that’s it!
More Resources
The above tutorial is just a really simple example of how you can create rich visualizations with just a handful of method calls using Highcharts for Python. But the library offers so much more! We recommend you take a look at the following additional resources which you may find useful:
Comments
There are no comments on this post
Want to leave a comment?
Comments are moderated. They will publish only if they add to the discussion in a constructive way. Please be polite.