Repository: napjon/krisk

Issue:
Set Style for y and x axis

Discussion:
codecov-io: ## [Current coverage](https://codecov.io/gh/napjon/krisk/pull/47?src=pr) is 93.40% (diff: 100%)
> Merging [#47](https://codecov.io/gh/napjon/krisk/pull/47?src=pr) into [0.2-develop](https://codecov.io/gh/napjon/krisk/branch/0.2-develop?src=pr) will increase coverage by **0.31%**

```diff
@@           0.2-develop        #47   diff @@
=============================================
  Files               10          9     -1   
  Lines              333        349    +16   
  Methods              0          0          
  Messages             0          0          
  Branches            48         49     +1   
=============================================
+ Hits               310        326    +16   
  Misses              14         14          
  Partials             9          9          
```

> Powered by [Codecov](https://codecov.io?src=pr). Last update [f873a68...37ff13d](https://codecov.io/gh/napjon/krisk/compare/f873a68da47b99677a73ebea2d92698db482a6d0...37ff13d06b37388e99685b3af43d00c8ff0eb429?src=pr)

Patch:
diff --git a/krisk/chart.py b/krisk/chart.py
index b5d17a1..beb692d 100644
--- a/krisk/chart.py
+++ b/krisk/chart.py
@@ -3,20 +3,37 @@
 import uuid
 import json
 from copy import deepcopy
-from krisk.template import *
 from krisk.connections import get_paths
 from IPython.display import Javascript
-from krisk.util import get_content
-
+from krisk.util import get_content, join_current_dir
+
+JS_TEMPLATE_PATH = 'static/krisk.js'
+EVENT_TEMPLATE_PATH = 'static/on_event.js'
+HTML_TEMPLATE_PATH = 'static/template.html'
+
+APPEND_ELEMENT = """
+$('#{id}').attr('id','{id}'+'_old');
+element.append('<div id="{id}" style="width: {width}px;height:{height}px;"></div>');"""
+
+OPTION_TEMPLATE = {
+    'title': {
+        'text': ''
+    },
+    'tooltip': {'axisPointer': {'type': ''}},
+    'legend': {
+        'data': []
+    },
+    'xAxis': {
+        'data': []
+    },
+    'yAxis': {},
+    'series': []
+}
 
 
 class Chart(object):
     """Chart Object"""
 
-    JS_TEMPLATE_PATH = 'static/krisk.js'
-    EVENT_TEMPLATE_PATH = 'static/on_event.js'
-
-
     def __init__(self, **kwargs):
         """Constructor"""
         # Currently, there are three type of data structure.
@@ -363,6 +380,65 @@ class Chart(object):
             'yAxis'], self.option['xAxis']
         return self
 
+    def _set_label_axes(self, xy, **kwargs):
+        """Set label axes name and other customization"""
+        assert xy in ['x','y']
+        self.option[xy + 'Axis'].update(**kwargs)
+        return self
+
+    def set_xlabel(self, name, axis_position='middle', axis_gap=30, rotation=0, font_size=16):
+        """Set x-axis label and other type of customization.
+
+        Parameters
+        ----------
+        name: the label of axes
+        axis_position: {start, middle, end}, default middle
+            horizontal alignment of label. start will position the label at leftmost position
+        axis_gap: int default 30
+            vertical alignment position of label. zero start from x-axis and going further away
+        rotation: int default 0
+            the rotation of the label
+        font_size: int default 16
+            the font size of the label
+
+        Return
+        ------
+        Chart object
+        """
+        label_kwargs = dict(name=name,
+                            nameLocation=axis_position,
+                            nameGap=axis_gap,
+                            nameTextStyle={'fontSize':font_size},
+                            nameRotate=rotation)
+        return self._set_label_axes('x', **label_kwargs)
+
+    def set_ylabel(self, name, axis_position='middle', axis_gap=30, rotation=90, font_size=16):
+        """Set y-axis label and other type of customization.
+        
+        Parameters
+        ----------
+        name: the label of axes
+        axis_position: {start, middle, end}, default middle
+            vertical alignment of label. start will position the label at bottom position
+        axis_gap: int default 30
+            horizontal alignment position of label. zero start from y-axis and going further 
+            away
+        rotation: int default 90
+            the rotation of the label
+        font_size: int default 16
+            the font size of the label
+
+        Return
+        ------
+        Chart object
+        """
+        label_kwargs = dict(name=name,
+                            nameLocation=axis_position,
+                            nameGap=axis_gap,
+                            nameTextStyle={'fontSize':font_size},
+                            nameRotate=rotation)
+        return self._set_label_axes('y', **label_kwargs)
+
     # ------------------------------------------------------------------------------------------------
     # Events
     def on_event(self, event, handler):
@@ -436,8 +512,8 @@ class Chart(object):
     def _get_resync_option_strings(self, option):
         """Resync Chart option"""
 
-        js_template = get_content(self.JS_TEMPLATE_PATH)
-        event_template = get_content(self.EVENT_TEMPLATE_PATH)
+        js_template = get_content(JS_TEMPLATE_PATH)
+        event_template = get_content(EVENT_TEMPLATE_PATH)
 
         events = [event_template.format(
             event=e, function=self._events[e]) for e in self._events]
@@ -474,4 +550,12 @@ class Chart(object):
     def to_html(self, path):
         "Save full html file"
         # TODO: Optional add open new tab as soon as it save the html file
-        save_html(self._repr_javascript_(), path)
+        from jinja2 import Template
+
+        script = self._repr_javascript_()
+        script = script.replace('element', '$("body")')
+
+        html_template = Template(get_content(HTML_TEMPLATE_PATH))
+        html_content = html_template.render(SCRIPT=script)
+        with open(path, 'w') as f:
+            f.write(html_content)
diff --git a/krisk/plot/make_chart.py b/krisk/plot/make_chart.py
index ce77d49..ea90926 100644
--- a/krisk/plot/make_chart.py
+++ b/krisk/plot/make_chart.py
@@ -39,6 +39,10 @@ def make_chart(df, **kwargs):
     chart = Chart(**kwargs)
     chart._kwargs_chart_['data_columns'] = df.columns
 
+    chart.set_xlabel(kwargs['x'])
+    if kwargs.get('y', None):
+        chart.set_ylabel(kwargs['y'])
+
     if kwargs['type'] in ['bar', 'line', 'hist']:
         set_bar_line_chart(chart, df, **kwargs)
 
diff --git a/krisk/template.py b/krisk/template.py
deleted file mode 100644
index b1b2e19..0000000
--- a/krisk/template.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from krisk.util import join_current_dir
-
-
-def save_html(script, path):
-
-    from jinja2 import Template
-
-    html_template = open(join_current_dir('static/template.html'), 'r')
-    script = script.replace('element', '$("body")')
-    f = open(path, 'w')
-    f.write(Template(html_template.read()).render(SCRIPT=script))
-    f.close()
-    html_template.close()
-
-
-APPEND_ELEMENT = """
-$('#{id}').attr('id','{id}'+'_old');
-element.append('<div id="{id}" style="width: {width}px;height:{height}px;"></div>');"""
-
-OPTION_TEMPLATE = {
-    'title': {
-        'text': ''
-    },
-    'tooltip': {'axisPointer': {'type': ''}},
-    'legend': {
-        'data': []
-    },
-    'xAxis': {
-        'data': []
-    },
-    'yAxis': {},
-    'series': []
-}


Test patch:
diff --git a/krisk/tests/conftest.py b/krisk/tests/conftest.py
index 4d132f1..bbf3e2e 100644
--- a/krisk/tests/conftest.py
+++ b/krisk/tests/conftest.py
@@ -21,6 +21,14 @@ def gapminder():
         DATA_DIR + '/gapminderDataFiveYear.txt', sep='\t').groupby(
             ['year', 'continent'], as_index=False).first())
 
+@pytest.fixture(scope="module")
+def decl_chart():
+    "Declarative Chart"
+    from krisk.chart import Chart
+    chart = Chart()
+    chart.option['series'] = [{'data': [10, 3, 7, 4, 5], 'name': 'continent', 'type': 'bar'}]
+    chart.option['xAxis'] =  {'data': ['Americas', 'Asia', 'Africa', 'Oceania', 'Europe']}
+    return chart
 
 @pytest.fixture
 def gap_chart(gapminder):
diff --git a/krisk/tests/test_chart.py b/krisk/tests/test_chart.py
index 88c1d9f..9376e6f 100644
--- a/krisk/tests/test_chart.py
+++ b/krisk/tests/test_chart.py
@@ -48,3 +48,19 @@ def test_color(bar_simple):
         background='green', palette=['purple']).get_option()
     assert colored['backgroundColor'] == 'green'
     assert colored['color'] == ['purple']
+
+def test_label_axes(decl_chart):
+    decl_chart.set_xlabel('xlabel')
+    decl_chart.set_ylabel('ylabel')
+    assert decl_chart.option['xAxis'] == {'data': ['Americas', 'Asia', 'Africa', 'Oceania', 'Europe'],
+                                            'name': 'xlabel',
+                                            'nameGap': 30,
+                                            'nameLocation': 'middle',
+                                            'nameRotate': 0,
+                                            'nameTextStyle': {'fontSize': 16}}
+
+    assert decl_chart.option['yAxis'] == {'name': 'ylabel',
+                                           'nameGap': 30,
+                                           'nameLocation': 'middle',
+                                           'nameRotate': 90,
+                                           'nameTextStyle': {'fontSize': 16}}
\ No newline at end of file
diff --git a/krisk/tests/test_plot.py b/krisk/tests/test_plot.py
index 08cf413..ebbd7f5 100644
--- a/krisk/tests/test_plot.py
+++ b/krisk/tests/test_plot.py
@@ -5,6 +5,16 @@ DATA_DIR = 'krisk/tests/data'
 
 read_option_tests = lambda f: json.load(open(DATA_DIR + '/' + f, 'r'))
 
+
+# Will delete this in 0.3, https://github.com/napjon/krisk/issues/46
+def remove_name_label(chart):
+    remove_key = lambda s,prefix: dict(filter(lambda t: not t[0].startswith(prefix),
+                             chart.option[s].items()))
+    chart.option['xAxis'] = remove_key('xAxis', 'name')
+    chart.option['yAxis'] = remove_key('yAxis', 'name')
+    return chart
+
+
 def test_bar(gapminder):
 
     #Bar
@@ -16,12 +26,12 @@ def test_bar(gapminder):
                how='mean',
                stacked=True,
                annotate=True)
-    assert p.get_option() == true_option
+    assert remove_name_label(p).get_option() == true_option
 
     #Bar with x-axis and category
     true_option = read_option_tests('bar_x_c.json')
     p = kk.bar(gapminder,'year',c='continent',stacked=True)
-    assert p.get_option() == true_option
+    assert remove_name_label(p).get_option() == true_option
 
 
     # Bar Annotate All
@@ -33,10 +43,10 @@ def test_bar(gapminder):
                how='mean',
                stacked=True,
                annotate='all')
-    assert p.get_option() == true_option
+    assert remove_name_label(p).get_option() == true_option
 
     p = kk.bar(gapminder,'continent',y='gdpPercap',how='mean')
-    assert p.get_option() == {'legend': {'data': []},
+    assert remove_name_label(p).get_option() == {'legend': {'data': []},
                              'series': [{'data': [4426.026, 8955.554, 802.675, 3255.367, 19980.596],
                                'name': 'continent',
                                'type': 'bar'}],
@@ -48,10 +58,10 @@ def test_bar(gapminder):
 def test_trendline(gapminder):
 
     p = kk.bar(gapminder,'year',how='mean',y='pop',trendline=True)
-    assert p.get_option() == read_option_tests('bar_year_pop_mean_trendline.json')
+    assert remove_name_label(p).get_option() == read_option_tests('bar_year_pop_mean_trendline.json')
 
     p = kk.bar(gapminder,'year',how='mean',y='pop',trendline=True,c='continent',stacked=True)
-    assert p.get_option() == read_option_tests('bar_year_pop_mean_continent_trendline.json')
+    assert remove_name_label(p).get_option() == read_option_tests('bar_year_pop_mean_continent_trendline.json')
 
     try:
         kk.bar(gapminder,'year',how='mean',y='pop',trendline=True,c='continent')
@@ -71,7 +81,7 @@ def test_line(gapminder):
         area=True,
         annotate='all')
 
-    assert p.get_option() == true_option
+    assert remove_name_label(p).get_option() == true_option
 
 def test_smooth_line(gapminder):
 
@@ -91,14 +101,14 @@ def test_full_bar_line(gapminder):
 
     true_option = read_option_tests('full_bar_line.json')
 
-    assert bar.option == line.option == true_option
+    assert remove_name_label(bar).option == remove_name_label(line).option == true_option
 
 
 def test_hist(gapminder):
 
     true_option  = read_option_tests('hist_x.json')
     p = kk.hist(gapminder,'lifeExp',bins=10)
-    assert p.get_option() == true_option
+    assert remove_name_label(p).get_option() == true_option
 
 
     true_option = read_option_tests('hist.json')
@@ -110,12 +120,13 @@ def test_hist(gapminder):
         normed=True,
         stacked=True)
 
-    assert p.get_option() == true_option
+    assert remove_name_label(p).get_option() == true_option
 
 
 def test_density(gapminder):
 
-    option = kk.hist(gapminder,'lifeExp',density=True).get_option()
+    chart1 = kk.hist(gapminder,'lifeExp',density=True)
+    option = remove_name_label(chart1).get_option()
 
     assert option['series'][0]['data'] == [0, 4, 2, 7, 2, 2, 3, 5, 13, 16, 6]
     assert option['series'][-1] == {'data': [0, 4, 2, 7, 2, 2, 3, 5, 13, 16, 6, 0],
@@ -127,7 +138,8 @@ def test_density(gapminder):
                                'data': [0, 28, 34, 39, 44, 49, 55, 60, 65, 70, 75, 81, 0]}
 
     true_option = read_option_tests('hist_lifeExp_b10_continent_density.json')
-    option2 = kk.hist(gapminder,'lifeExp',bins=10,c='continent',stacked=True,density=True).get_option()
+    chart = kk.hist(gapminder,'lifeExp',bins=10,c='continent',stacked=True,density=True)
+    option2 = remove_name_label(chart).get_option()
     assert true_option == option2
 
     try: