import matta
# we do this to load the required libraries when viewing on NBViewer
matta.init_javascript(path='https://rawgit.com/carnby/matta/master/matta/libs')

"""
Explanation: matta - Introduction: Let's <del>Make</del> Scaffold a Barchart
By @carnby
Introduction
Probably you have seen the barchart example by Mike Bostock. It is here. In this notebook I explain how to use matta to implement this barchart.
Why use matta?
One thing is to have an example of a visualization, and another one is to have a reusable implementation. Reusable implementations are not about having a specific function to draw. In my opinion, they are about an entire context where you can easily use your visualization with other datasets.
How do we do it?
In this notebook we see the basic scaffolding done by matta to reproduce the example chart to visualize a pandas DataFrame. By being able to use a DataFrame, we can forget about converting the dataset to the specific layout the visualization designer had in mind, and instead, you can focus on converting to a DataFrame (which will probably be very, very easy)
Let's begin.
Initial Setup
Here we load matta. 
If you see the README, you will notice that you can install matta's javascript and css into your IPython profile. In this way you do not need to issue a init_javascript call. It is here just for demonstration - if you use a core matta visualization and export the notebook to NBViewer, you will need to execute it, to allow your visitor's browser to load the required js/css files.
If you installed matta into your profile, then using the function will do no harm - it detects that matta was loaded and does nothing.
End of explanation
"""


import pandas as pd

df = pd.read_csv('http://bl.ocks.org/mbostock/raw/3885304/964f9100166627a89c7e6c23ce8128f5aefd5510/data.tsv', delimiter='\t')
df.head()

"""
Explanation: Data
Mike's example loads a TSV (Tab Separated Values) file with letter frequency. We can load directly into a pandas DataFrame.
End of explanation
"""


barchart = matta.import_visualization('skeleton')

barchart(dataframe=df, x='letter', y='frequency', rotate_label=False, bar_color='purple')

"""
Explanation: Sketching the Visualization
First, let's sketch the visualization by defining what are its options and code.
The visualization options or arguments are contained in a dictionary. Note that the dictionary contains a subdictionary named variables. Those variables will be exposed as methods of the scaffolded visualization, and are available in code as _variable_name.
Note also the data dictionary. It indicates that the visualization receives a pandas DataFrame. This dataframe is available internally as the _data_dataframe variable.
This is the visualization code. Note that is almost a copy-and-paste version of the original example. We just renamed the variables to _variable_name and used other auxiliary variables like _vis_width which are exposed by matta.
Note that the code is not strictly javascript. Actually, the file is expected to be a jinja2 template.
We save this template as barchart.js, as barchart_args['visualization_js'] points to it.
skeleton/__init__.py
python
VISUALIZATION_CONFIG = {
    'requirements': ['d3'],
    'visualization_name': 'barchart',
    'visualization_js': './barchart.js',
    'figure_id': None,
    'container_type': 'svg',
    'data': {
        'dataframe': None,
    },
    'options': {
        'background_color': None,
        'x_axis': True,
        'y_axis': True,
    },
    'variables': {
        'width': 960,
        'height': 500,
        'padding': {'left': 30, 'top': 20, 'right': 30, 'bottom': 30},
        'x': 'x',
        'y': 'y',
        'y_axis_ticks': 10,
        'color': 'steelblue',
        'y_label': None,
        'rotate_label': True,
    },
}
skeleton/template.js
```javascript
var x = d3.scale.ordinal()
    .rangeRoundBands([0, _vis_width], .1);
var y = d3.scale.linear()
    .range([_vis_height, 0]);
if (_y_label == null) {
    _y_label = _y;
}
x.domain(_data_dataframe.map(function(d) { return d[_x]; }));
y.domain([0, d3.max(_data_dataframe, function(d) { return d[_y]; })]);
{% if options.x_axis %}
    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");
container.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + _vis_height + ")")
    .call(xAxis);

{% endif %}
{% if options.y_axis %}
    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");
if (_y_axis_ticks != null) {
    yAxis.ticks(_y_axis_ticks);
}

var y_label = container.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text");

if (_rotate_label) {
    y_label.attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end");
} else {
    y_label
    .attr("y", 6)
        .attr('x', 12)
    .attr("dy", ".71em")
    .style("text-anchor", "start");
}

y_label.text(_y_label);

{% endif %}
// NOTE: this is needed for the internal color scale manager.
_bar_color_update_scale_func(_data_dataframe);
var bar = container.selectAll(".bar")
    .data(_data_dataframe);
bar.enter().append('rect').classed('bar', true);
bar.exit().remove();
bar.attr("x", function(d) { return x(d[_x]); })
    .attr("width", x.rangeBand())
    .attr("y", function(d) { return y(d[_y]); })
    .attr("height", function(d) { return _vis_height - y(d[_y]); })
    .attr('fill', _bar_color);
```
This is the actual matta code to display the visualization in the notebook. 
Importing the Visualization
End of explanation
"""


barchart(dataframe=df, x='letter', y='frequency', rotate_label=False, 
         bar_color={'value': 'letter', 'palette': 'cubehelix', 'n_colors': df.shape[0], 'scale': 'ordinal'})

"""
Explanation: Note that the keyword arguments are keys from the VISUALIZATION_CONFIG dictionary. If you use a keyword argument not present in the dictionary, an Exception will be raised.
Remember that in the visualization configuration we had a "colorables" section. The colorable bar_color was specified as "purple" in the previous chart, but we can also make it dynamic by specifying a source column from the dataframe, a color palette and a scale type:
End of explanation
"""


barchart(x='letter', y='frequency').scaffold(filename='./scaffolded_barchart.js')

"""
Explanation: Visualization Scaffolding
The next step is to scaffold a reusable visualization. Actually, the code is very similar:
End of explanation
"""


from matta import dump_data
dump_data(df, './data.json')

"""
Explanation: What this does is to create a file named scaffolded_barchart.js which contains a reusable visualization. All variables declared in the arguments dictionary are available as property methods. The values specified when defining the arguments or when scaffolding will serve as defaults, but everything is changeable. Note that we did not specify a DataFrame this time!
Testing the Visualization
To test the visualization, we will serialize the DataFrame and then display an IFrame with the visualization using a very simple template (which we, again, copied from the original source by Mike).
matta includes a dump_data function that calls a JSON serializer under the hoods. This serializer is able to handle DataFrames and other typical python data structures.
End of explanation
"""


