diff options
author | Keith Bostic <keith@wiredtiger.com> | 2015-02-06 12:44:49 +0000 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2015-02-06 12:44:49 +0000 |
commit | f499b8edcdaa71d9f5964b946f8aa443658664e6 (patch) | |
tree | d6c94c387cae20aeecd3fd09eb52af4924f73ffb /tools | |
parent | 850ef3b0333b446bc6cf2103bc0fc189e91b679e (diff) | |
download | mongo-f499b8edcdaa71d9f5964b946f8aa443658664e6.tar.gz |
Add wtperf_stats back into the tree.
Diffstat (limited to 'tools')
20 files changed, 2351 insertions, 0 deletions
diff --git a/tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS b/tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS new file mode 100644 index 00000000000..17d06bec646 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS @@ -0,0 +1,16 @@ +areski (Areski Belaid) +shrenik (Shrenik Patel) +DZPM (David Arcos) +goulu (Philippe Guglielmetti) +jordanvg +RodrigoPrior (Rodrigo Prior) +DanMeakin +nzjrs (John Stowers) +RaD (Ruslan Popov) +cmorgan (Chris Morgan) +imom0 +kbsali (Kevin Saliou) +zebulon2 +bevanj +frewie +agorrod diff --git a/tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt b/tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt new file mode 100644 index 00000000000..1add6249e57 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt @@ -0,0 +1,24 @@ +The MIT License (MIT) + +Python-nvd3 + +Copyright (c) 2013 Arezqui Belaid <areski@gmail.com> and other contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py b/tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py new file mode 100644 index 00000000000..52cbf168ddc --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py @@ -0,0 +1,547 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from optparse import OptionParser +from string import Template +import json + +template_content_nvd3 = """ +$container +$jschart +""" + +template_page_nvd3 = """ +<!DOCTYPE html> +<html lang="en"> +<head> +$header +</head> +<body> +%s +</body> +""" % template_content_nvd3 + + +def stab(tab=1): + """ + create space tabulation + """ + return ' ' * 4 * tab + + +class NVD3Chart: + """ + NVD3Chart Base class + + **Attributes**: + + * ``axislist`` - All X, Y axis list + * ``charttooltip_dateformat`` - date fromat for tooltip if x-axis is in date format + * ``charttooltip`` - Custom tooltip string + * ``color_category`` - Defien color category (eg. category10, category20, category20c) + * ``color_list`` - used by pieChart (eg. ['red', 'blue', 'orange']) + * ``container`` - Place for graph + * ``containerheader`` - Header for javascript code + * ``count`` - chart count + * ``custom_tooltip_flag`` - False / True + * ``d3_select_extra`` - + * ``date_flag`` - x-axis contain date format or not + * ``dateformat`` - see https://github.com/mbostock/d3/wiki/Time-Formatting + * ``header_css`` - False / True + * ``header_js`` - Custom tooltip string + * ``height`` - Set graph height + * ``htmlcontent`` - Contain the htmloutput + * ``htmlheader`` - Contain the html header + * ``jschart`` - Javascript code as string + * ``margin_bottom`` - set the bottom margin + * ``margin_left`` - set the left margin + * ``margin_right`` - set the right margin + * ``margin_top`` - set the top margin + * ``model`` - set the model (ex. pieChart, LineWithFocusChart, MultiBarChart) + * ``resize`` - False / True + * ``series`` - Series are list of data that will be plotted + * ``stacked`` - False / True + * ``style`` - Special style + * ``template_page_nvd3`` - template variable + * ``width`` - Set graph width + * ``x_axis_date`` - False / True + * ``show_legend`` - False / True + * ``show_labels`` - False / True + * ``assets_directory`` directory holding the assets (./bower_components/) + """ + count = 0 + dateformat = '%x' + series = [] + axislist = {} + style = '' + htmlcontent = '' + htmlheader = '' + height = None + width = None + margin_bottom = None + margin_left = None + margin_right = None + margin_top = None + model = '' + d3_select_extra = '' + x_axis_date = False + resize = False + stacked = False + template_page_nvd3 = None + container = None + containerheader = '' + jschart = None + custom_tooltip_flag = False + date_flag = False + charttooltip = '' + tooltip_condition_string = '' + color_category = 'category10' # category10, category20, category20c + color_list = [] # for pie chart + tag_script_js = True + charttooltip_dateformat = None + x_axis_format = '' + show_legend = True + show_labels = True + assets_directory = './bower_components/' + + def __init__(self, **kwargs): + """ + Constructor + """ + #set the model + self.model = self.__class__.__name__ + + #Init Data + self.series = [] + self.axislist = {} + self.template_page_nvd3 = Template(template_page_nvd3) + self.template_content_nvd3 = Template(template_content_nvd3) + self.charttooltip_dateformat = '%d %b %Y' + + self.name = kwargs.get('name', self.model) + self.jquery_on_ready = kwargs.get('jquery_on_ready', False) + self.color_category = kwargs.get('color_category', None) + self.color_list = kwargs.get('color_list', None) + self.margin_bottom = kwargs.get('margin_bottom', 20) + self.margin_left = kwargs.get('margin_left', 60) + self.margin_right = kwargs.get('margin_right', 60) + self.margin_top = kwargs.get('margin_top', 30) + self.stacked = kwargs.get('stacked', False) + self.resize = kwargs.get('resize', False) + self.show_legend = kwargs.get('show_legend', True) + self.show_labels = kwargs.get('show_labels', True) + self.tag_script_js = kwargs.get('tag_script_js', True) + self.chart_attr = kwargs.get("chart_attr", {}) + self.assets_directory = kwargs.get('assets_directory', './bower_components/') + + #CDN http://cdnjs.com/libraries/nvd3/ needs to make sure it's up to date + self.header_css = [ + '<link href="%s" rel="stylesheet">\n' % h for h in + ( + self.assets_directory + 'nvd3/src/nv.d3.css', + ) + ] + + self.header_js = [ + '<script src="%s"></script>\n' % h for h in + ( + self.assets_directory + 'd3/d3.min.js', + self.assets_directory + 'nvd3/nv.d3.min.js' + ) + ] + + def add_serie(self, y, x, name=None, extra={}, **kwargs): + """ + add serie - Series are list of data that will be plotted + y {1, 2, 3, 4, 5} / x {1, 2, 3, 4, 5} + + **Attributes**: + + * ``name`` - set Serie name + * ``x`` - x-axis data + * ``y`` - y-axis data + + kwargs: + + * ``shape`` - for scatterChart, you can set different shapes (circle, triangle etc...) + * ``size`` - for scatterChart, you can set size of different shapes + * ``type`` - for multiChart, type should be bar + * ``bar`` - to display bars in Chart + * ``color_list`` - define list of colors which will be used by pieChart + * ``color`` - set axis color + * ``disabled`` - + + extra: + + * ``tooltip`` - set tooltip flag + * ``date_format`` - set date_format for tooltip if x-axis is in date format + + """ + if not name: + name = "Serie %d" % (len(self.series) + 1) + + # For scatterChart shape & size fields are added in serie + if 'shape' in kwargs or 'size' in kwargs: + csize = kwargs.get('size', 1) + cshape = kwargs.get('shape', 'circle') + + serie = [{ + 'x': x[i], + 'y': y, + 'shape': cshape, + 'size': csize[i] if isinstance(csize, list) else csize + } for i, y in enumerate(y)] + else: + if self.model == 'pieChart': + serie = [{'label': x[i], 'value': y} for i, y in enumerate(y)] + elif self.model == 'linePlusBarWithFocusChart': + serie = [[x[i], y] for i, y in enumerate(y)] + else: + serie = [{'x': x[i], 'y': y} for i, y in enumerate(y)] + + data_keyvalue = {'values': serie, 'key': name} + + #multiChart + #Histogram type='bar' for the series + if 'type' in kwargs and kwargs['type']: + data_keyvalue['type'] = kwargs['type'] + + if self.model == 'pieChart': + if 'color_list' in extra and extra['color_list']: + self.color_list = extra['color_list'] + + #Define on which Y axis the serie is related + #a chart can have 2 Y axis, left and right, by default only one Y Axis is used + if 'yaxis' in kwargs and kwargs['yaxis']: + data_keyvalue['yAxis'] = kwargs['yaxis'] + else: + if self.model != 'pieChart' and self.model != 'linePlusBarWithFocusChart': + data_keyvalue['yAxis'] = '1' + + if 'bar' in kwargs and kwargs['bar']: + data_keyvalue['bar'] = 'true' + + if 'disabled' in kwargs and kwargs['disabled']: + data_keyvalue['disabled'] = 'true' + + if 'color' in extra and extra['color']: + data_keyvalue['color'] = extra['color'] + + if extra.get('date_format'): + self.charttooltip_dateformat = extra['date_format'] + + if extra.get('tooltip'): + self.custom_tooltip_flag = True + + if self.model != 'pieChart': + _start = extra['tooltip']['y_start'] + _end = extra['tooltip']['y_end'] + _start = ("'" + str(_start) + "' + ") if _start else '' + _end = (" + '" + str(_end) + "'") if _end else '' + + if self.model == 'linePlusBarChart' or self.model == 'linePlusBarWithFocusChart': + self.tooltip_condition_string += stab(3) + "if(key.indexOf('" + name + "') > -1 ){\n" +\ + stab(4) + "var y = " + _start + " String(graph.point.y) " + _end + ";\n" +\ + stab(3) + "}\n" + elif self.model == 'cumulativeLineChart': + self.tooltip_condition_string += stab(3) + "if(key == '" + name + "'){\n" +\ + stab(4) + "var y = " + _start + " String(e) " + _end + ";\n" +\ + stab(3) + "}\n" + else: + self.tooltip_condition_string += stab(3) + "if(key == '" + name + "'){\n" +\ + stab(4) + "var y = " + _start + " String(graph.point.y) " + _end + ";\n" +\ + stab(3) + "}\n" + + if self.model == 'pieChart': + _start = extra['tooltip']['y_start'] + _end = extra['tooltip']['y_end'] + _start = ("'" + str(_start) + "' + ") if _start else '' + _end = (" + '" + str(_end) + "'") if _end else '' + self.tooltip_condition_string += \ + "var y = " + _start + " String(y) " + _end + ";\n" + + self.series.append(data_keyvalue) + + def set_graph_height(self, height): + """Set Graph height""" + self.height = str(height) + + def set_graph_width(self, width): + """Set Graph width""" + self.width = str(width) + + def set_containerheader(self, containerheader): + """Set containerheader""" + self.containerheader = containerheader + + def set_date_flag(self, date_flag=False): + """Set date falg""" + self.date_flag = date_flag + + def set_custom_tooltip_flag(self, custom_tooltip_flag): + """Set custom_tooltip_flag & date_flag""" + self.custom_tooltip_flag = custom_tooltip_flag + + def __str__(self): + """return htmlcontent""" + self.buildhtml() + return self.htmlcontent + + def buildcontent(self): + """Build HTML content only, no header or body tags. To be useful this + will usually require the attribute `juqery_on_ready` to be set which + will wrap the js in $(function(){<regular_js>};) + """ + self.buildcontainer() + self.buildjschart() + self.htmlcontent = self.template_content_nvd3.substitute(container=self.container, + jschart=self.jschart) + + def buildhtml(self): + """Build the HTML page + Create the htmlheader with css / js + Create html page + Add Js code for nvd3 + """ + self.buildhtmlheader() + self.buildcontainer() + self.buildjschart() + + self.htmlcontent = self.template_page_nvd3.substitute(header=self.htmlheader, + container=self.container, + jschart=self.jschart) + + def buildhtmlheader(self): + """generate HTML header content""" + self.htmlheader = '' + for css in self.header_css: + self.htmlheader += css + for js in self.header_js: + self.htmlheader += js + + def buildcontainer(self): + """generate HTML div""" + self.container = self.containerheader + #Create SVG div with style + if self.width: + if self.width[-1] != '%': + self.style += 'width:%spx;' % self.width + else: + self.style += 'width:%s;' % self.width + if self.height: + if self.height[-1] != '%': + self.style += 'height:%spx;' % self.height + else: + self.style += 'height:%s;' % self.height + if self.style: + self.style = 'style="%s"' % self.style + + self.container += '<div id="%s"><svg %s></svg></div>\n' % (self.name, self.style) + + def build_custom_tooltip(self): + """generate custom tooltip for the chart""" + if self.custom_tooltip_flag: + if not self.date_flag: + if self.model == 'pieChart': + self.charttooltip = stab(2) + "chart.tooltipContent(function(key, y, e, graph) {\n" + \ + stab(3) + "var x = String(key);\n" +\ + stab(3) + self.tooltip_condition_string +\ + stab(3) + "tooltip_str = '<center><b>'+x+'</b></center>' + y;\n" +\ + stab(3) + "return tooltip_str;\n" + \ + stab(2) + "});\n" + else: + self.charttooltip = stab(2) + "chart.tooltipContent(function(key, y, e, graph) {\n" + \ + stab(3) + "var x = String(graph.point.x);\n" +\ + stab(3) + "var y = String(graph.point.y);\n" +\ + self.tooltip_condition_string +\ + stab(3) + "tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;\n" +\ + stab(3) + "return tooltip_str;\n" + \ + stab(2) + "});\n" + else: + self.charttooltip = stab(2) + "chart.tooltipContent(function(key, y, e, graph) {\n" + \ + stab(3) + "var x = d3.time.format('%s')(new Date(parseInt(graph.point.x)));\n" \ + % self.charttooltip_dateformat +\ + stab(3) + "var y = String(graph.point.y);\n" +\ + self.tooltip_condition_string +\ + stab(3) + "tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x;\n" +\ + stab(3) + "return tooltip_str;\n" + \ + stab(2) + "});\n" + + def buildjschart(self): + """generate javascript code for the chart""" + + self.jschart = '' + if self.tag_script_js: + self.jschart += '\n<script>\n' + + self.jschart += stab() + + if self.jquery_on_ready: + self.jschart += '$(function(){' + + self.jschart += 'nv.addGraph(function() {\n' + + self.jschart += stab(2) + 'var chart = nv.models.%s();\n' % self.model + + if self.model != 'pieChart' and not self.color_list: + if self.color_category: + self.jschart += stab(2) + 'chart.color(d3.scale.%s().range());\n' % self.color_category + + if self.stacked: + self.jschart += stab(2) + "chart.stacked(true);" + + self.jschart += stab(2) + \ + 'chart.margin({top: %s, right: %s, bottom: %s, left: %s})\n' % \ + (self.margin_top, self.margin_right, \ + self.margin_bottom, self.margin_left) + + """ + We want now to loop through all the defined Axis and add: + chart.y2Axis + .tickFormat(function(d) { return '$' + d3.format(',.2f')(d) }); + """ + if self.model != 'pieChart': + for axis_name, a in list(self.axislist.items()): + self.jschart += stab(2) + "chart.%s\n" % axis_name + for attr, value in list(a.items()): + self.jschart += stab(3) + ".%s(%s);\n" % (attr, value) + + if self.width: + self.d3_select_extra += ".attr('width', %s)\n" % self.width + if self.height: + self.d3_select_extra += ".attr('height', %s)\n" % self.height + + if self.model == 'pieChart': + datum = "data_%s[0].values" % self.name + else: + datum = "data_%s" % self.name + + # add custom tooltip string in jschart + # default condition (if build_custom_tooltip is not called explicitly with date_flag=True) + if self.tooltip_condition_string == '': + self.tooltip_condition_string = 'var y = String(graph.point.y);\n' + + self.build_custom_tooltip() + self.jschart += self.charttooltip + + # the shape attribute in kwargs is not applied when + # not allowing other shapes to be rendered + if self.model == 'scatterChart': + self.jschart += 'chart.scatter.onlyCircles(false);' + + if self.model != 'discreteBarChart': + if self.show_legend: + self.jschart += stab(2) + "chart.showLegend(true);\n" + else: + self.jschart += stab(2) + "chart.showLegend(false);\n" + + #showLabels only supported in pieChart + if self.model == 'pieChart': + if self.show_labels: + self.jschart += stab(2) + "chart.showLabels(true);\n" + else: + self.jschart += stab(2) + "chart.showLabels(false);\n" + + # add custom chart attributes + for attr, value in self.chart_attr.items(): + self.jschart += stab(2) + "chart.%s(%s);\n" % (attr, value) + + #Inject data to D3 + self.jschart += stab(2) + "d3.select('#%s svg')\n" % self.name + \ + stab(3) + ".datum(%s)\n" % datum + \ + stab(3) + ".transition().duration(500)\n" + \ + stab(3) + self.d3_select_extra + \ + stab(3) + ".call(chart);\n\n" + + if self.resize: + self.jschart += stab(1) + "nv.utils.windowResize(chart.update);\n" + self.jschart += stab(1) + "return chart;\n});" + + if self.jquery_on_ready: + self.jschart += "\n});" + + #Include data + series_js = json.dumps(self.series) + + if self.model == 'linePlusBarWithFocusChart': + append_to_data = ".map(function(series) {" + \ + "series.values = series.values.map(function(d) { return {x: d[0], y: d[1] } });" + \ + "return series; })" + self.jschart += """data_%s=%s%s;\n""" % (self.name, series_js, append_to_data) + else: + self.jschart += """data_%s=%s;\n""" % (self.name, series_js) + + if self.tag_script_js: + self.jschart += "</script>" + + def create_x_axis(self, name, label=None, format=None, date=False, custom_format=False): + """ + Create X-axis + """ + axis = {} + if custom_format and format: + axis['tickFormat'] = format + else: + if format: + if format == 'AM_PM': + axis['tickFormat'] = "function(d) { return get_am_pm(parseInt(d)); }" + else: + axis['tickFormat'] = "d3.format(',%s')" % format + + if label: + axis['axisLabel'] = label + + #date format : see https://github.com/mbostock/d3/wiki/Time-Formatting + if date: + self.dateformat = format + axis['tickFormat'] = "function(d) { return d3.time.format('%s')(new Date(parseInt(d))) }\n" % self.dateformat + #flag is the x Axis is a date + if name[0] == 'x': + self.x_axis_date = True + + #Add new axis to list of axis + self.axislist[name] = axis + + def create_y_axis(self, name, label=None, format=None, custom_format=False): + """ + Create Y-axis + """ + axis = {} + + if custom_format and format: + axis['tickFormat'] = format + else: + if format: + axis['tickFormat'] = "d3.format(',%s')" % format + + if label: + axis['axisLabel'] = label + + #Add new axis to list of axis + self.axislist[name] = axis + + +def _main(): + """ + Parse options and process commands + """ + # Parse arguments + usage = "usage: nvd3.py [options]" + parser = OptionParser(usage=usage, version="python-nvd3 - Charts generator with nvd3.js and d3.js") + parser.add_option("-q", "--quiet", + action="store_false", dest="verbose", default=True, + help="don't print messages to stdout") + + (options, args) = parser.parse_args() + + +if __name__ == '__main__': + _main() diff --git a/tools/wtperf_stats/3rdparty/nvd3/README.rst b/tools/wtperf_stats/3rdparty/nvd3/README.rst new file mode 100644 index 00000000000..31a04d958cc --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/README.rst @@ -0,0 +1,134 @@ +Python Wrapper for NVD3 - It's time for beautiful charts +======================================================== + +:Description: Python-nvd3 is a wrapper for NVD3 graph library +:nvd3: NVD3 http://nvd3.org/ +:d3: Data-Driven Documents http://d3js.org/ + + +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js offers you. + + +.. image:: https://www.travis-ci.org/areski/python-nvd3.png?branch=master + + +Installation +------------ + +Install, upgrade and uninstall python-nvd3 with these commands:: + + $ pip install python-nvd3 + $ pip install --upgrade python-nvd3 + $ pip uninstall python-nvd3 + + +Dependecies +----------- + +D3 and NvD3 can be installed through bower (which itself can be installed through npm). See http://bower.io/ and https://npmjs.org for further information. +To install bower globally execute:: + + $ npm install -g bower + +Note : you might prefer to save your npm dependencies locally in a ``package.json`` file. + +Then in the directory where you will use python-nvd3, just execute the following commands:: + + $ bower install d3#3.3.8 + $ bower install nvd3#1.1.12-beta + +This will create a directory "bower_components" where d3 & nvd3 will be saved. + +Note : you might prefer to save your bower dependencies locally in a ``bower.json`` file. You can also configure the directory where your bower dependencies will be saved adding a ``.bowerrc`` file in your project root directory. + + +Usage +----- + +After installation use python-nvd3 as follows :: + + from nvd3 import pieChart + + #Open File to write the D3 Graph + output_file = open('test-nvd3.html', 'w') + + type = 'pieChart' + chart = pieChart(name=type, color_category='category20c', height=450, width=450) + chart.set_containerheader("\n\n<h2>" + type + "</h2>\n\n") + + #Create the keys + xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] + ydata = [3, 4, 0, 1, 5, 7, 3] + + #Add the serie + extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} + chart.add_serie(y=ydata, x=xdata, extra=extra_serie) + chart.buildhtml() + output_file.write(chart.htmlcontent) + + #close Html file + output_file.close() + + +See the file examples.py for more samples. + + +Live demo of NVD3 +----------------- + +See a live demo on jsfiddle : http://jsfiddle.net/areski/z4zuH/3/ + + +Supported nvd3 charts +--------------------- + +Charts list: + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/lineWithFocusChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/lineChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/multiBarChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/pieChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/stackedAreaChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/multiBarHorizontalChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/linePlusBarChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/cumulativeLineChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/discreteBarChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/scatterChart.png + +.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/linePlusBarWithFocusChart.png + + +Documentation +------------- + +Documentation is available on 'Read the Docs': +http://python-nvd3.readthedocs.org + + +Changelog +--------- + +Changelog summary : https://github.com/areski/python-nvd3/blob/master/CHANGELOG.rst + + +Do you like Django? +------------------- + +There is also a django wrapper for nvd3 available: +https://github.com/areski/django-nvd3 + + +License +------- + +Python-nvd3 is licensed under MIT, see `MIT-LICENSE.txt`. diff --git a/tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README b/tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README new file mode 100644 index 00000000000..e9eb0a8b081 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README @@ -0,0 +1,20 @@ +This is a pre-build python-nvd3 library. It was built from the +Git repository: +https://github.com/areski/python-nvd3 + +Based on revision: +commit deb12255fa61f0ff3fa4b41699e0ef8e62fbd4a6 +Author: Areski Belaid <areski@gmail.com> +Date: Mon Feb 10 15:27:20 2014 +0100 + +Using Python 2.7.5 + +To reproduce run: + +$ cd wiredtiger/tools/third_party +$ git clone https://github.com/areski/python-nvd3 +$ cd python-nvd3 +$ git checkout deb12255 +$ python27 setup.py build +$ cp build/lib/nvd3/* nvd3/ + diff --git a/tools/wtperf_stats/3rdparty/nvd3/__init__.py b/tools/wtperf_stats/3rdparty/nvd3/__init__.py new file mode 100644 index 00000000000..72bb4608230 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +__version__ = '0.11.0' # edit also docs/source/conf.py +__all__ = ['lineChart', 'pieChart', 'lineWithFocusChart', + 'stackedAreaChart', 'multiBarHorizontalChart', + 'linePlusBarChart', 'cumulativeLineChart', + 'scatterChart', 'discreteBarChart', 'multiBarChart', + 'linePlusBarWithFocusChart'] + + +from .lineChart import lineChart +from .pieChart import pieChart +from .lineWithFocusChart import lineWithFocusChart +from .stackedAreaChart import stackedAreaChart +from .multiBarHorizontalChart import multiBarHorizontalChart +from .linePlusBarChart import linePlusBarChart +from .cumulativeLineChart import cumulativeLineChart +from .scatterChart import scatterChart +from .discreteBarChart import discreteBarChart +from .multiBarChart import multiBarChart +from .linePlusBarWithFocusChart import linePlusBarWithFocusChart diff --git a/tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py b/tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py new file mode 100644 index 00000000000..3ffbc66127c --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class cumulativeLineChart(NVD3Chart): + """ + A cumulative line chart is used when you have one important grouping representing + an ordered set of data and one value to show, summed over time. + + .. image:: ../_static/screenshot/cumulativeLineChart.png + + Python example:: + + from nvd3 import cumulativeLineChart + chart = cumulativeLineChart(name='cumulativeLineChart', x_is_date=True) + xdata = [1365026400000000, 1365026500000000, 1365026600000000] + ydata = [-6, 5, -1] + y2data = [36, 55, 11] + + extra_serie = {"tooltip": {"y_start": "There are ", "y_end": " calls"}} + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) + + extra_serie = {"tooltip": {"y_start": "", "y_end": " mins"}} + chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_lineWithFocusChart = [ + { + "key" : "Serie 1", + "values" : [ + { "x" : "1365026400000000", + "y" : -6 + }, + { "x" : "1365026500000000", + "y" : -5 + }, + { "x" : "1365026600000000", + "y" : -1 + }, + ], + }, + { + "key" : "Serie 2", + "values" : [ + { "x" : "1365026400000000", + "y" : 34 + }, + { "x" : "1365026500000000", + "y" : 56 + }, + { "x" : "1365026600000000", + "y" : 32 + }, + ], + } + ] + + nv.addGraph(function() { + var chart = nv.models.cumulativeLineChart(); + + chart.xAxis + .tickFormat(function(d) { return d3.time.format('%d %b %Y')(new Date(d)) }); + chart.y1Axis + .tickFormat(d3.format('.1%')); + chart.tooltipContent(function(key, y, e, graph) { + var x = d3.time.format('%d %b %Y')(new Date(parseInt(graph.point.x))); + var y = String(graph.point.y); + if(key == 'Serie 1'){ + var y = 'There are ' + String(e) + ' calls'; + } + if(key == 'Serie 2'){ + var y = String(e) + ' mins'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x; + return tooltip_str; + }); + d3.select('#cumulativeLineChart svg') + .datum(data_linePlusBarChart) + .transition().duration(500) + .attr('height', 350) + .call(chart); + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', '%d %b %Y'), + date=True) + self.set_custom_tooltip_flag(True) + else: + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f')) + + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.1%')) + + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py b/tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py new file mode 100644 index 00000000000..a16c32a9265 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class discreteBarChart(NVD3Chart): + """ + A discrete bar chart or bar graph is a chart with rectangular bars with + lengths proportional to the values that they represent. + + .. image:: ../_static/screenshot/discreteBarChart.png + + Python example:: + + from nvd3 import discreteBarChart + chart = discreteBarChart(name='discreteBarChart', height=400, width=400) + + xdata = ["A", "B", "C", "D", "E"] + ydata = [3, 4, 0, -3, 5, 7] + + extra_serie = {"tooltip": {"y_start": "", "y_end": " balls"}} + chart.add_serie(y=ydata, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data = [{ key: "Cumulative Return", + values: [ + { + "label": "A", + "value" : 10 + }, + { + "label": "B", + "value" : 0 + }, + { + "label": "C", + "value" : -3 + }, + ] + }] + + nv.addGraph(function() { + var chart = nv.models.discreteBarChart() + .x(function(d) { return d.label }) + .y(function(d) { return d.value }) + .showLabels(true); + chart.tooltipContent(function(key, y, e, graph) { + var x = String(graph.point.x); + var y = String(graph.point.y); + if(key == 'Serie 1'){ + var y = String(graph.point.y) + ' balls'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x; + return tooltip_str; + }); + d3.select("#div_id") + .datum(data) + .transition() + .duration(1200) + .call(chart); + + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + self.name = kwargs.get('name', 'discreteBarChart') + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', "%d %b %Y %H %S"), + date=True) + else: + self.create_x_axis('xAxis', format=None) + + self.set_custom_tooltip_flag(True) + + # must have a specified height, otherwise it superimposes both charts + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/lineChart.py b/tools/wtperf_stats/3rdparty/nvd3/lineChart.py new file mode 100644 index 00000000000..b0dc1796863 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/lineChart.py @@ -0,0 +1,111 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart, stab + + +class lineChart(NVD3Chart): + """ + A line chart or line graph is a type of chart which displays information + as a series of data points connected by straight line segments. + + .. image:: ../_static/screenshot/lineChart.png + + Python example:: + + from nvd3 import lineChart + chart = lineChart(name='lineChart', height=400, width=400, x_is_date=True, x_axis_format="%d %b %Y %H") + xdata = [1365026400000000, 1365026500000000, 1365026600000000] + ydata = [-6, 5, -1] + + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"}, + "date_format": "%d %b %Y %H:%S"} + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_lineChart = [{ + "key" : "Serie 1", + "values" : [ + { "x" : "1365026400000000", + "y" : -6 + }, + { "x" : "1365026500000000", + "y" : -5 + }, + { "x" : "1365026600000000", + "y" : -1 + }, + ], + "yAxis" : "1" + }] + + nv.addGraph(function() { + var chart = nv.models.lineChart(); + chart.xAxis + .tickFormat(function(d) { return d3.time.format('%d %b %y %H')(new Date(d)) }); + chart.yAxis + .tickFormat(d3.format(',.2f')); + chart.tooltipContent(function(key, y, e, graph) { + var x = d3.time.format('%d %b %Y %H:%S')(new Date(parseInt(graph.point.x))); + var y = String(graph.point.y); + if(key == 'Serie 1'){ + var y = 'There is ' + String(graph.point.y) + ' calls'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x; + return tooltip_str; + }); + d3.select('#lineChart svg') + .datum(data_lineChart) + .transition() + .duration(500) + .call(chart); + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', '%d %b %Y'), + date=True) + self.set_custom_tooltip_flag(True) + else: + if kwargs.get('x_axis_format') == 'AM_PM': + self.x_axis_format = format = 'AM_PM' + else: + format = kwargs.get('x_axis_format', 'r') + self.create_x_axis('xAxis', format=format) + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.02f')) + + # must have a specified height, otherwise it superimposes both chars + self.set_graph_height(height) + if width: + self.set_graph_width(width) + + def buildjschart(self): + NVD3Chart.buildjschart(self) + am_pm_js = '' + if self.x_axis_format == 'AM_PM': + am_pm_js += stab(2) + "function get_am_pm(d){\n" + am_pm_js += stab(3) + "if(d > 12){ d = d - 12; return (String(d) + 'PM');}\n" + am_pm_js += stab(3) + "else{ return (String(d) + 'AM');}\n" + am_pm_js += stab(2) + "};\n" + + start_js = self.jschart.find('nv.addGraph') + replace_index = start_js + if start_js > 0: + self.jschart = self.jschart[:replace_index] + am_pm_js + self.jschart[replace_index:] diff --git a/tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py new file mode 100644 index 00000000000..b4b3ca139b0 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py @@ -0,0 +1,125 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class linePlusBarChart(NVD3Chart): + """ + A linePlusBarChart Chart is a type of chart which displays information + as a series of data points connected by straight line segments + and with some series with rectangular bars with lengths proportional + to the values that they represent + + .. image:: ../_static/screenshot/linePlusBarChart.png + + Python example:: + + from nvd3 import linePlusBarChart + chart = linePlusBarChart(name='linePlusBarChart', x_is_date=True, x_axis_format="%d %b %Y") + + xdata = [1365026400000000, 1365026500000000, 1365026600000000] + ydata = [-6, 5, -1] + y2data = [36, 55, 11] + + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"}, + "date_format": "%d %b %Y %H:%S" } + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) + + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " min"}} + chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_lineWithFocusChart = [ + { + "key" : "Serie 1", + "bar": "true", + "values" : [ + { "x" : "1365026400000000", + "y" : -6 + }, + { "x" : "1365026500000000", + "y" : -5 + }, + { "x" : "1365026600000000", + "y" : -1 + }, + ], + }, + { + "key" : "Serie 2", + "values" : [ + { "x" : "1365026400000000", + "y" : 34 + }, + { "x" : "1365026500000000", + "y" : 56 + }, + { "x" : "1365026600000000", + "y" : 32 + }, + ], + } + ] + + nv.addGraph(function() { + var chart = nv.models.linePlusBarChart(); + + chart.xAxis + .tickFormat(function(d) { return d3.time.format('%d %b %Y')(new Date(d)) }); + chart.y1Axis + .tickFormat(d3.format(',f')); + chart.y2Axis + .tickFormat(function(d) { return '$' + d3.format(',f')(d) }); + chart.tooltipContent(function(key, y, e, graph) { + var x = d3.time.format('%d %b %Y %H:%S')(new Date(parseInt(graph.point.x))); + var y = String(graph.point.y); + if(key.indexOf('Serie 1') > -1 ){ + var y = '$ ' + String(graph.point.y) ; + } + if(key.indexOf('Serie 2') > -1 ){ + var y = String(graph.point.y) + ' min'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x; + return tooltip_str; + }); + d3.select('#linePlusBarChart svg') + .datum(data_linePlusBarChart) + .transition().duration(500) + .attr('height', 350) + .call(chart); + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', '%d %b %Y %H %S'), + date=True) + self.set_custom_tooltip_flag(True) + else: + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f')) + + self.create_y_axis('y1Axis', format="f") + self.create_y_axis('y2Axis', format="function(d) { return d3.format(',f')(d) }", custom_format=True) + + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py new file mode 100644 index 00000000000..6067b7a5bbb --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py @@ -0,0 +1,153 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart, stab + + +class linePlusBarWithFocusChart(NVD3Chart): + """ + A linePlusBarWithFocusChart Chart is a type of chart which displays information + as a series of data points connected by straight line segments + and with some series with rectangular bars with lengths proportional + to the values that they represent + + .. image:: ../_static/screenshot/linePlusBarWithFocusChart.png + + Python example:: + + from nvd3 import linePlusBarWithFocusChart + chart = linePlusBarWithFocusChart(name='linePlusBarChart', x_is_date=True, x_axis_format="%d %b %Y") + + xdata = [1365026400000000, 1365026500000000, 1365026600000000] + ydata = [-6, 5, -1] + y2data = [36, 55, 11] + kwargs = {} + kwargs['bar'] = True + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"}, + "date_format": "%d %b %Y %H:%S" } + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie, **kwargs) + + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " min"}} + chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_linePlusBarWithFocusChart = [ + { + "key" : "Quantity" , + "bar": true, + "values" : [ [ 1136005200000 , 1271000.0] , [ 1138683600000 , 1271000.0] , ] + }, + { + "key" : "Price" , + "values" : [ [ 1136005200000 , 71.89] , [ 1138683600000 , 75.51]] + } + ].map(function(series) { + series.values = series.values.map(function(d) { return {x: d[0], y: d[1] } }); + return series; + }); + + nv.addGraph(function() { + var chart = nv.models.linePlusBarWithFocusChart() + .margin({top: 30, right: 60, bottom: 50, left: 70}) + .x(function(d,i) { return i }) + .color(d3.scale.category10().range()); + + chart.xAxis.tickFormat(function(d) { + + var dx = testdata[0].values[d] && testdata[0].values[d].x || 0; + if (dx > 0) { + return d3.time.format('%x')(new Date(dx)) + } + return null; + }); + + chart.x2Axis.tickFormat(function(d) { + var dx = testdata[0].values[d] && testdata[0].values[d].x || 0; + return d3.time.format('%x')(new Date(dx)) + }); + + chart.y1Axis.tickFormat(d3.format(',f')); + + chart.y3Axis.tickFormat(d3.format(',f')); + + chart.y2Axis.tickFormat(function(d) { return '$' + d3.format(',.2f')(d) }); + + chart.y4Axis.tickFormat(function(d) { return '$' + d3.format(',.2f')(d) }); + + chart.bars.forceY([0]); + chart.bars2.forceY([0]); + //chart.lines.forceY([0]); + nv.log(testdata); + d3.select('#linePlusBarWithFocusChart svg') + .datum(testdata) + .call(chart); + + nv.utils.windowResize(chart.update); + + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + + with_focus_chart_1 = """function(d) { + var dx = data_%s[0].values[d] && data_%s[0].values[d].x || 0; + if (dx > 0) { return d3.time.format('%s')(new Date(dx)) } + return null; + }""" % (self.name, self.name, kwargs.get('x_axis_format', '%d %b %Y %H %S')) + self.create_x_axis('xAxis', format=with_focus_chart_1, date=False, custom_format=True) + + with_focus_chart_2 = """function(d) { + var dx = data_%s[0].values[d] && data_%s[0].values[d].x || 0; + return d3.time.format('%s')(new Date(dx)); + }""" % (self.name, self.name, kwargs.get('x_axis_format', '%d %b %Y %H %S')) + + self.create_x_axis('x2Axis', format=with_focus_chart_2, date=False, custom_format=True) + + self.set_custom_tooltip_flag(True) + else: + self.create_x_axis('xAxis', format=".2f") + + self.create_y_axis('y1Axis', format="f") + self.create_y_axis('y3Axis', format="f") + + self.create_y_axis('y2Axis', format="function(d) { return d3.format(',.2f')(d) }", custom_format=True) + + self.create_y_axis('y4Axis', format="function(d) { return d3.format(',.2f')(d) }", custom_format=True) + + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) + + def buildjschart(self): + NVD3Chart.buildjschart(self) + + string_jschart = '\n' + stab(2) + 'chart.margin({top: 30, right: 60, bottom: 50, left: 70})\n' + \ + stab(3) + '.x(function(d,i) { return i });\n' + if self.width: + string_jschart += stab(2) + 'chart.width(%s);\n' % self.width + if self.height: + string_jschart += stab(2) + 'chart.height(%s);\n' % self.height + + start_index = self.jschart.find('.linePlusBarWithFocusChart();') + string_len = len('.linePlusBarWithFocusChart();') + replace_index = start_index + string_len + if start_index > 0: + self.jschart = self.jschart[:replace_index] + string_jschart + self.jschart[replace_index:] diff --git a/tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py b/tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py new file mode 100644 index 00000000000..4a6cd778551 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class lineWithFocusChart(NVD3Chart): + """ + A lineWithFocusChart or line graph is a type of chart which displays information + as a series of data points connected by straight line segments. + The lineWithFocusChart provide a smaller chart that act as a selector, + this is very useful if you want to zoom on a specific time period. + + .. image:: ../_static/screenshot/lineWithFocusChart.png + + Python example:: + + from nvd3 import lineWithFocusChart + chart = lineWithFocusChart(name='lineWithFocusChart', x_is_date=True, x_axis_format="%d %b %Y") + xdata = [1365026400000000, 1365026500000000, 1365026600000000] + ydata = [-6, 5, -1] + + extra_serie = {"tooltip": {"y_start": "", "y_end": " ext"}, + "date_format": "%d %b %Y"} + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_lineWithFocusChart = [{ "key" : "Serie 1", + "values" : [ + { "x" : "1365026400000000", + "y" : -6 + }, + { "x" : "1365026500000000", + "y" : -5 + }, + { "x" : "1365026600000000", + "y" : -1 + }, + ], + "yAxis" : "1" + }] + + nv.addGraph(function() { + var chart = nv.models.lineWithFocusChart(); + chart.yAxis + .tickFormat(d3.format(',.2f')); + chart.y2Axis + .tickFormat(d3.format(',.2f')); + chart.xAxis + .tickFormat(function(d) { return d3.time.format('%d %b %y')(new Date(d)) }); + chart.x2Axis + .tickFormat(function(d) { return d3.time.format('%d %b %y')(new Date(d)) }); + chart.tooltipContent(function(key, y, e, graph) { + var x = d3.time.format('%d %b %Y')(new Date(parseInt(graph.point.x))); + var y = String(graph.point.y); + if(key == 'serie 1'){ + var y = 'There is ' + String(graph.point.y) + ' calls'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x; + return tooltip_str; + }); + d3.select('#lineWithFocusChart svg') + .datum(data_lineWithFocusChart) + .transition() + .duration(500) + .call(chart); + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '%d %b %Y %H %S'), date=True) + self.create_x_axis('x2Axis', format=kwargs.get('x_axis_format', '%d %b %Y %H %S'), date=True) + self.set_custom_tooltip_flag(True) + else: + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f')) + self.create_x_axis('x2Axis', format=kwargs.get('x_axis_format', '.2f')) + + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f')) + self.create_y_axis('y2Axis', format=kwargs.get('y_axis_format', '.2f')) + + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py b/tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py new file mode 100644 index 00000000000..991f0f48174 --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class multiBarChart(NVD3Chart): + """ + A multiple bar graph contains comparisons of two or more categories or bars. + One axis represents a quantity and the other axis identifies a specific feature + about the categories. Reading a multiple bar graph includes looking at extremes + (tallest/longest vs. shortest) in each grouping. + + .. image:: ../_static/screenshot/multiBarChart.png + + Python example:: + + from nvd3 import multiBarChart + chart = multiBarChart(name='multiBarChart', height=400, width=400) + xdata = [0, 1, 3, 4] + ydata = [6, 12, 9, 16] + + extra_serie = {"tooltip": {"y_start": "", "y_end": " balls"}} + chart.add_serie(name="Serie 1", y=ydata, x=xdata) + chart.buildhtml() + + Javascript generated:: + + data_MultiBarChart = [{ "key" : "Serie 1", + "values" : [ + { "x" : 0 + "y" : 6 + }, + { "x" : 1, + "y" : 12 + }, + { "x" : 3, + "y" : 9 + }, + ], + "yAxis" : "1" + }] + + nv.addGraph(function() { + var chart = nv.models.multiBarChart(); + chart.xAxis + .tickFormat(d3.format(',.2f')); + chart.yAxis + .tickFormat(d3.format(',.2f')); + chart.tooltipContent(function(key, y, e, graph) { + var x = String(graph.point.x); + var y = String(graph.point.y); + if(key == 'Serie 1'){ + var y = String(graph.point.y) + ' balls'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x; + return tooltip_str; + }); + d3.select('#MultiBarChart svg') + .datum(data_MultiBarChart) + .transition() + .duration(500) + .call(chart); + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', '%d %b %Y'), + date=True) + self.set_custom_tooltip_flag(True) + else: + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f')) + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f')) + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py b/tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py new file mode 100644 index 00000000000..8f2c8dbaaee --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py @@ -0,0 +1,104 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class multiBarHorizontalChart(NVD3Chart): + """ + A multiple horizontal bar graph contains comparisons of two or more categories or bars. + + .. image:: ../_static/screenshot/multiBarHorizontalChart.png + + Python example:: + + from nvd3 import multiBarHorizontalChart + chart = multiBarHorizontalChart(name='multiBarHorizontalChart', height=400, width=400) + xdata = [-14, -7, 7, 14] + ydata = [-6, 5, -1, 9] + y2data = [-23, -6, -32, 9] + + extra_serie = {"tooltip": {"y_start": "", "y_end": " balls"}} + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) + + extra_serie = {"tooltip": {"y_start": "", "y_end": " calls"}} + chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_lineChart = [ { "key" : "Serie 1", + "values" : [ { "x" : 0, + "y" : -2 + }, + { "x" : 1, + "y" : 4 + }, + { "x" : 2, + "y" : -7 + }, + ], + "yAxis" : "1" + }, + { "key" : "Serie 2", + "values" : [ { "x" : 0, + "y" : -4 + }, + { "x" : 1, + "y" : 8 + }, + { "x" : 2, + "y" : -14 + }, + ], + "yAxis" : "1" + } + ] + + nv.addGraph(function() { + var chart = nv.models.multiBarHorizontalChart(); + chart.xAxis + .tickFormat(d3.format(',.2f')); + chart.yAxis + .tickFormat(d3.format(',.2f')); + chart.tooltipContent(function(key, y, e, graph) { + var x = String(graph.point.x); + var y = String(graph.point.y); + if(key == 'Serie 1'){ + var y = String(graph.point.y) + ' balls'; + } + if(key == 'Serie 2'){ + var y = String(graph.point.y) + ' calls'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x; + return tooltip_str; + }); + d3.select('#multiBarHorizontalChart svg') + .datum(data_multiBarHorizontalChart) + .transition().duration(500) + .attr('height', 350) + .call(chart); + + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f')) + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f')) + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/pieChart.py b/tools/wtperf_stats/3rdparty/nvd3/pieChart.py new file mode 100644 index 00000000000..5c542bd8d3c --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/pieChart.py @@ -0,0 +1,125 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart, stab + + +class pieChart(NVD3Chart): + """ + A pie chart (or a circle graph) is a circular chart divided into sectors, + illustrating numerical proportion. In chart, the arc length of each sector + is proportional to the quantity it represents. + + .. image:: ../_static/screenshot/pieChart.png + + Python example:: + + from nvd3 import pieChart + chart = pieChart(name='pieChart', color_category='category20c', height=400, width=400) + + xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] + ydata = [3, 4, 0, 1, 5, 7, 3] + + extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} + chart.add_serie(y=ydata, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data = [{ key: "Cumulative Return", + values: [ + { + "label": "One", + "value" : 29.765957771107 + }, + { + "label": "Two", + "value" : 0 + }, + { + "label": "Three", + "value" : 32.807804682612 + }, + ] + }] + + nv.addGraph(function() { + var chart = nv.models.pieChart() + .x(function(d) { return d.label }) + .y(function(d) { return d.value }) + .showLabels(true); + + chart.color(d3.scale.category20c().range()); + + chart.tooltipContent(function(key, y, e, graph) { + var x = String(key); + var y = String(y) + ' cal'; + tooltip_str = '<center><b>'+x+'</b></center>' + y; + return tooltip_str; + }); + + d3.select("#div_id") + .datum(data) + .transition() + .duration(1200) + .call(chart); + + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + self.create_x_axis('xAxis', format=None) + self.create_y_axis('yAxis', format=None) + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) + + def buildjschart(self): + NVD3Chart.buildjschart(self) + + color_js = '' + if self.color_list: + color_js += "var mycolor = new Array();\n" + color_count = 0 + for i in self.color_list: + color_js += stab(2) + "mycolor[" + str(color_count) + "] = '" + i + "';\n" + color_count = int(color_count) + 1 + + # add mycolor var in js before nv.addGraph starts + if self.color_list: + start_js = self.jschart.find('nv.addGraph') + #start_js_len = len('nv.addGraph') + replace_index = start_js + if start_js > 0: + self.jschart = self.jschart[:replace_index] + color_js + self.jschart[replace_index:] + + pie_jschart = '\n' + stab(2) + 'chart.x(function(d) { return d.label })\n' + \ + stab(3) + '.y(function(d) { return d.value });\n' + if self.width: + pie_jschart += stab(2) + 'chart.width(%s);\n' % self.width + if self.height: + pie_jschart += stab(2) + 'chart.height(%s);\n' % self.height + + # add custom colors for pieChart + if self.color_list and color_js: + pie_jschart += stab(2) + 'chart.color(mycolor);\n' + + start_index = self.jschart.find('.pieChart();') + string_len = len('.pieChart();') + replace_index = start_index + string_len + if start_index > 0: + self.jschart = self.jschart[:replace_index] + pie_jschart + self.jschart[replace_index:] diff --git a/tools/wtperf_stats/3rdparty/nvd3/scatterChart.py b/tools/wtperf_stats/3rdparty/nvd3/scatterChart.py new file mode 100644 index 00000000000..74e1e08475f --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/scatterChart.py @@ -0,0 +1,137 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart, stab + + +class scatterChart(NVD3Chart): + """ + A scatter plot or scattergraph is a type of mathematical diagram using Cartesian + coordinates to display values for two variables for a set of data. + The data is displayed as a collection of points, each having the value of one variable + determining the position on the horizontal axis and the value of the other variable + determining the position on the vertical axis. + + .. image:: ../_static/screenshot/scatterChart.png + + Python example:: + + from nvd3 import scatterChart + chart = scatterChart(name='scatterChart', height=400, width=400) + xdata = [3, 4, 0, -3, 5, 7] + ydata = [-1, 2, 3, 3, 15, 2] + ydata = [1, -2, 4, 7, -5, 3] + + kwargs1 = {'shape': 'circle', 'size': '1'} + kwargs2 = {'shape': 'cross', 'size': '10'} + + extra_serie = {"tooltip": {"y_start": "", "y_end": " call"}} + chart.add_serie(name="series 1", y=ydata, x=xdata, extra=extra_serie, **kwargs1) + + extra_serie = {"tooltip": {"y_start": "", "y_end": " min"}} + chart.add_serie(name="series 2", y=ydata, x=xdata, extra=extra_serie, **kwargs2) + chart.buildhtml() + + Javascript generated:: + + data = [{ key: "series 1", + values: [ + { + "x": 2, + "y": 10, + "shape": "circle" + }, + { + "x": -2, + "y" : 0, + "shape": "circle" + }, + { + "x": 5, + "y" : -3, + "shape": "circle" + }, + ] + }, + { key: "series 2", + values: [ + { + "x": 4, + "y": 10, + "shape": "cross" + }, + { + "x": 4, + "y" : 0, + "shape": "cross" + }, + { + "x": 3, + "y" : -3, + "shape": "cross" + }, + ] + }] + + nv.addGraph(function() { + var chart = nv.models.scatterChart() + .showLabels(true); + + chart.showDistX(true); + chart.showDistY(true); + + chart.tooltipContent(function(key, y, e, graph) { + var x = String(graph.point.x); + var y = String(graph.point.y); + if(key == 'serie 1'){ + var y = String(graph.point.y) + ' calls'; + } + if(key == 'serie 2'){ + var y = String(graph.point.y) + ' min'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x; + return tooltip_str; + }); + + d3.select("#div_id") + .datum(data) + .transition() + .duration(1200) + .call(chart); + + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.02f')) + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.02f')) + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) + + def buildjschart(self): + NVD3Chart.buildjschart(self) + + scatter_jschart = '\n' + stab(3) + '.showDistX(true)\n' + \ + stab(3) + '.showDistY(true)\n' + \ + stab(3) + '.color(d3.scale.category10().range())' + + start_index = self.jschart.find('.scatterChart()') + string_len = len('.scatterChart()') + replace_index = start_index + string_len + if start_index > 0: + self.jschart = self.jschart[:replace_index] + scatter_jschart + self.jschart[replace_index:] diff --git a/tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py b/tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py new file mode 100644 index 00000000000..9913929f4cf --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart + + +class stackedAreaChart(NVD3Chart): + """ + The stacked area chart is identical to the area chart, except the areas are stacked + on top of each other, rather than overlapping. This can make the chart much easier to read. + + .. image:: ../_static/screenshot/stackedAreaChart.png + + Python example:: + + from nvd3 import stackedAreaChart + chart = stackedAreaChart(name='stackedAreaChart', height=400, width=400) + + xdata = [100, 101, 102, 103, 104, 105, 106,] + ydata = [6, 11, 12, 7, 11, 10, 11] + ydata2 = [8, 20, 16, 12, 20, 28, 28] + + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " min"}} + chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) + chart.add_serie(name="Serie 2", y=ydata2, x=xdata, extra=extra_serie) + chart.buildhtml() + + Javascript generated:: + + data_stackedAreaChart = [{ + "values":[ + { + "y":9, + "x":100 + }, + { + "y":5, + "x":101 + }, + ], + "key":"Serie 1", + "yAxis":"1" + }, + { + "values":[ + { + "y":18, + "x":100 + }, + { + "y":10, + "x":101 + }, + ], + "key":"Serie 2", + "yAxis":"1" + } + ] + + nv.addGraph(function() { + var chart = nv.models.stackedAreaChart(); + chart.xAxis + .tickFormat(d3.format(',.2f')); + chart.yAxis + .tickFormat(d3.format(',.2f')); + chart.tooltipContent(function(key, y, e, graph) { + var x = String(graph.point.x); + var y = String(graph.point.y); + if(key == 'serie 1'){ + var y = 'There is ' + String(graph.point.y) + ' min'; + } + if(key == 'serie 2'){ + var y = 'There is ' + String(graph.point.y) + ' min'; + } + tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x; + return tooltip_str; + }); + d3.select('#stackedAreaChart svg') + .datum(data_stackedAreaChart) + .transition() + .duration(500) + .call(chart); + return chart; + }); + """ + def __init__(self, **kwargs): + NVD3Chart.__init__(self, **kwargs) + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', '%d %b %Y'), + date=True) + self.set_custom_tooltip_flag(True) + else: + self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f')) + self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f')) + # must have a specified height, otherwise it superimposes both chars + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/tools/wtperf_stats/3rdparty/nvd3/translator.py b/tools/wtperf_stats/3rdparty/nvd3/translator.py new file mode 100644 index 00000000000..ffde2c2a1ce --- /dev/null +++ b/tools/wtperf_stats/3rdparty/nvd3/translator.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + + +class Tag(object): + """Tag class""" + + def __init__(self, content=None): + self.content = content + self.attrs = ' '.join(['%s="%s"' % (attr, value) + for attr, value in self.attrs]) + + def __str__(self): + return '<%s%s>\n %s\n</%s>' % (self.name, + ' ' + self.attrs if self.attrs else '', + self.content, + self.name) + + +class ScriptTag(Tag): + name = 'script' + attrs = (('type', 'text/javascript'),) + + +class AnonymousFunction(object): + def __init__(self, arguments, content): + self.arguments = arguments + self.content = content + + def __str__(self): + return 'function(%s) { %s }' % (self.arguments, self.content) + + +class Function(object): + + def __init__(self, name): + self.name = name + self._calls = [] + + def __str__(self): + operations = [self.name] + operations.extend(str(call) for call in self._calls) + return '%s' % ('.'.join(operations),) + + def __getattr__(self, attr): + self._calls.append(attr) + return self + + def __call__(self, *args): + if not args: + self._calls[-1] = self._calls[-1] + '()' + else: + arguments = ','.join([str(arg) for arg in args]) + self._calls[-1] = self._calls[-1] + '(%s)' % (arguments,) + return self + + +class Assignment(object): + + def __init__(self, key, value, scoped=True): + self.key = key + self.value = value + self.scoped = scoped + + def __str__(self): + return '%s%s = %s;' % ('var ' if self.scoped else '', self.key, self.value) + + +def indent(func): + # TODO: Add indents to function str + return str(func) diff --git a/tools/wtperf_stats/wt_nvd3_util.py b/tools/wtperf_stats/wt_nvd3_util.py new file mode 100644 index 00000000000..fe058d25c1d --- /dev/null +++ b/tools/wtperf_stats/wt_nvd3_util.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Public Domain 2008-2014 WiredTiger, Inc. +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +import os, sys +from datetime import datetime + +tool_dir = os.path.split(sys.argv[0])[0] +# Make sure Python finds the NVD3 in our third party directory, to +# avoid compatability issues +sys.path.append(os.path.join(tool_dir, "3rdparty")) + +try: + from nvd3 import lineChart +except ImportError: + print >>sys.stderr, "Could not import nvd3. It should be installed locally." + sys.exit(-1) + +# Add a multiChart type so we can overlay line graphs +class multiChart(lineChart): + def __init__(self, **kwargs): + lineChart.__init__(self, **kwargs) + + # Fix the axes + del self.axislist['yAxis'] + self.create_y_axis('yAxis1', format=kwargs.get('y_axis_format', '.02f')) + self.create_y_axis('yAxis2', format=kwargs.get('y_axis_format', '.02f')) + +TIMEFMT = "%b %d %H:%M:%S" + +thisyear = datetime.today().year +def parsetime(s): + return datetime.strptime(s, TIMEFMT).replace(year=thisyear) + diff --git a/tools/wtperf_stats/wtperf_stats.py b/tools/wtperf_stats/wtperf_stats.py new file mode 100644 index 00000000000..f87ca2d3254 --- /dev/null +++ b/tools/wtperf_stats/wtperf_stats.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +# +# Public Domain 2008-2014 WiredTiger, Inc. +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +import os, csv, operator, sys +from time import mktime + +tool_dir = os.path.split(sys.argv[0])[0] +sys.path.append(tool_dir) + +try: + from wt_nvd3_util import multiChart, parsetime +except ImportError: + print >>sys.stderr, "Could not import wt_nvd3_util.py, it should be\ + in the same directory as %s" % sys.argv[0] + sys.exit(-1) + +def timesort(s): + # Sort the timestr via its parsetime() value so that the year gets + # added and it properly sorts. Times are only %b %d %H:%M:%S and + # may improperly sort if the data crosses a month boundary. + t = operator.itemgetter('#time') + timestr = t(s) + return parsetime(timestr) + +# Fixup the names and values in a dictionary read in from a csv file. One +# field must be "#time" - which is used to calculate the interval. +# Input is a dictionary, output is a list of dictionaries with a single entry. +def munge_dict(values_dict, abstime): + sorted_values = sorted(values_dict, key=timesort) + start_time = parsetime(sorted_values[0]['#time']) + + ret = [] + for v in sorted_values: + if abstime: + # Build the time series, milliseconds since the epoch + v['#time'] = int(mktime(parsetime(v['#time']).timetuple())) * 1000 + else: + # Build the time series as seconds since the start of the data + v['#time'] = (parsetime(v['#time']) - start_time).seconds + next_val = {} + for title, value in v.items(): + if title.find('uS') != -1: + title = title.replace('uS', 'ms') + value = float(value) / 1000 + if title == 'totalsec': + value = 0 + if title == 'checkpoints' and value == 'N': + value = 0 + elif title.find('time') != -1: + title = 'time' + elif title.find('latency') == -1 and \ + title.find('checkpoints') == -1: + title = title + ' (thousands)' + value = float(value) / 1000 + next_val[title] = value + ret.append(next_val) + + # After building the series, eliminate constants + d0 = ret[0] + for t0, v0 in d0.items(): + skip = True + for d in ret: + v = d[t0] + if v != v0: + skip = False + break + if skip: + for dicts in ret: + del dicts[t0] + + return ret + +def addPlotsToChart(chart, graph_data, wtstat_chart = False): + # Extract the times - they are the same for all lines. + times = [] + for v in graph_data: + times.append(v['time']) + + # Add a line to the graph for each field in the CSV file in alphabetical + # order, so the key is sorted. + for field in sorted(graph_data[0].keys()): + if field == 'time': + continue + # Split the latency and non-latency measurements onto different scales + axis = "1" + if not wtstat_chart and field.find('latency') == -1: + axis="2" + ydata = [] + for v in graph_data: + ydata.append(v[field]) + chart.add_serie(x=times, y=ydata, name=field, type="line", yaxis=axis) + +# Input parameters are a chart populated with WiredTiger statistics and +# the directory where the wtperf monitor file can be found. +def addPlotsToStatsChart(chart, dirname, abstime): + fname = os.path.join(dirname, 'monitor') + try: + with open(fname, 'rb') as csvfile: + reader = csv.DictReader(csvfile) + # Transform the data into something NVD3 can digest + graph_data = munge_dict(reader, abstime) + except IOError: + print >>sys.stderr, "Could not open wtperf monitor file." + sys.exit(-1) + addPlotsToChart(chart, graph_data, 1) + +def main(): + # Parse the command line + import argparse + + parser = argparse.ArgumentParser(description='Create graphs from WiredTiger statistics.') + parser.add_argument('--abstime', action='store_true', + help='use absolute time on the x axis') + parser.add_argument('--output', '-o', metavar='file', + default='wtperf_stats.html', help='HTML output file') + parser.add_argument('files', metavar='file', nargs='+', + help='input monitor file generated by WiredTiger wtperf application') + args = parser.parse_args() + + output_file = open(args.output, 'w') + + if len(args.files) != 1: + print 'Script currently only supports a single monitor file' + exit (1) + + chart_extra = {} + # Add in the x axis if the user wants time. + if args.abstime: + chart_extra['x_axis_format'] = '%H:%M:%S' + + for f in args.files: + with open(f, 'rb') as csvfile: + reader = csv.DictReader(csvfile) + # Transform the data into something NVD3 can digest + graph_data = munge_dict(reader, args.abstime) + + chart = multiChart(name='wtperf', + height=450 + 10*len(graph_data[0].keys()), + resize=True, + x_is_date=args.abstime, + assets_directory='http://source.wiredtiger.com/graphs/', + **chart_extra) + + addPlotsToChart(chart, graph_data) + + chart.buildhtml() + output_file.write(chart.htmlcontent) + output_file.close() + +if __name__ == '__main__': + main() + |