In this post I'll describe how to get geographical data from AMPL and display it in IPython using an interactive Google Chart. I'll use a simple map coloring problem implemented with AMPL constraint programming extensions.
First install the ampl
extension for IPython also known as iampl if you haven't done this already. The extension is now available in the Python Package Index so you can use standard Python tools such as pip
or easy_install
to install it. See the installation instructions for details.
Once the extension is installed you can load it in IPython:
In [1]:
%load_ext ampl
Now it is possible to write AMPL code directly in an IPython notebook using the %%ampl
magic. The followng code declares a small map coloring model, provides some data and solves it with Gecode (you can download the AMPL driver for Gecode from the AMPL repository on Google Code):
In [2]:
%%ampl
param NumColors;
set Countries;
set Neighbors within {Countries, Countries};
var color{Countries} integer >= 1 <= NumColors;
s.t. different_colors{(c1, c2) in Neighbors}:
(color[c1] != color[c2]);
data;
param NumColors := 4;
set Countries := Belgium Denmark France Germany Luxembourg Netherlands;
set Neighbors :=
Belgium France
Belgium Germany
Belgium Netherlands
Belgium Luxembourg
Denmark Germany
France Germany
France Luxembourg
Germany Luxembourg
Germany Netherlands;
option solver gecode;
solve;
After evaluating the above code, AMPL objects become available in IPython and can be used as regular Python objects. For example, a collection of variables color
, which maps country names to their colors can be accessed similarly to Python's dict
:
In [3]:
print(color)
Now let's use Google Charts to display a colored map. GeoChart
is a simple helper function which takes two positional arguments, a list of column names for the data table and a dictionary containing the data itself. It also takes arbitrary keyword arguments which are mapped to chart options. See the GeoChart documentation for the list of available options.
In [4]:
from ampl.gchart import GeoChart
GeoChart(['Country', 'Color'], color, region=150, legend=False, height=500,
colorAxis={'colors': ['#ff9900', '#3366cc', '#109618', '#dc3912']})
Out[4]:
Here's the full implementation of the GeoChart
function from the ampl.gchart
package included in the distribution:
def GeoChart(keys, data, **kwargs):
table = "{},\n".format(keys)
for i in data:
table += "['{}', {}],\n".format(i, data[i])
options = ""
for arg, value in kwargs.iteritems():
if isinstance(value, bool):
value = 'true' if value else 'false'
elif isinstance(value, dict):
items = ""
for k, v in value.iteritems():
items += "{}: {},".format(k, v)
value = "{{{}}}".format(items)
options += "{}:{},\n".format(arg, value)
return Javascript("""
container.show();
function draw() {{
var chart = new google.visualization.GeoChart(element[0]);
chart.draw(google.visualization.arrayToDataTable([{}]), {{{}}});
}}
google.load('visualization', '1.0', {{'callback': draw, 'packages':['geochart']}});
""".format(table, options), lib="https://www.google.com/jsapi")
As you can see the implementation is very simple, all it does is converting the data and options passed as arguments into JavaScript and returning the result as a Javascript object that is processed by IPython. In fact, you could construct the Javascript object directly but it would be much less convenient.
With little effort it is possible to create similar wrappers for other types of charts from the Google Chart library or even different Javascript libraries.