package Chart::Bokeh; use strict; use warnings; use utf8; use Exporter 'import'; use vars qw(@EXPORT_OK); @EXPORT_OK = qw(show_plot); use JSON; use Params::Validate qw(:all); use Text::Template; use Module::Load; use Ref::Util; use HTML::Show; our $VERSION = '0.001'; # VERSION # ABSTRACT: Generate html/javascript charts from perl data using javascript library BokehJS sub render_full_html { my %params = @_; my $data = $params{'data'}; my $chart_id = 'bokeh_graph'; my $html; if ( Ref::Util::is_blessed_ref($data) && $data->isa('Chart::Bokeh::Plot') ) { $html = _render_html_wrap( $data->html( div_id => $chart_id ) ); } else { $html = _render_html_wrap( _render_cell( _process_data($data), $chart_id ) ); } return $html; } sub _render_html_wrap { my $body = shift; my $html_begin = <<'HTML_BEGIN';
HTML_BEGIN my $html_end = <<'HTML_END'; HTML_END return $html_begin . $body . $html_end; } sub _render_cell { my $data_string = shift(); my $chart_id = shift(); my $template = <<'TEMPLATE'; TEMPLATE my $template_variables = { data => $data_string, chart_id => $chart_id, }; return Text::Template::fill_in_string( $template, HASH => $template_variables ); } sub _process_data { my $data = shift; my $json_formatter = JSON->new->utf8->allow_blessed(1)->convert_blessed(1); local *PDL::TO_JSON = sub { $_[0]->unpdl }; my $data_string = $json_formatter->encode($data); return $data_string; } my $poc = ' // set up some data var M = 100; var xx = []; var yy = []; var colors = []; var radii = []; for (var y = 0; y <= M; y += 4) \{ for (var x = 0; x <= M; x += 4) \{ xx.push(x); yy.push(y); colors.push(Bokeh.Plotting.color(50+2*x, 30+2*y, 150)); radii.push(Math.random() * 0.4 + 1.7) \} \} // create a data source var source = new Bokeh.ColumnDataSource(\{ data: \{ x: xx, y: yy, radius: radii, colors: colors \} \}); // make the plot and add some tools var tools = "pan,crosshair,wheel_zoom,box_zoom,reset,save"; var p = Bokeh.Plotting.figure(\{ title: "Colorful Scatter", tools: tools \}); // call the circle glyph method to add some circle glyphs var circles = p.circle(\{ field: "x" \}, \{ field: "y" \}, \{ source: source, radius: radii, fill_color: colors, fill_alpha: 0.6, line_color: null \}); // show the plot Bokeh.Plotting.show(p); '; sub show_plot { my @data_to_plot = @_; my $rendered_cells = ""; my $numeric_id = 0; for my $data (@data_to_plot) { my $id = 'chart_' . $numeric_id++; if ( Ref::Util::is_blessed_ref($data) && $data->isa('Chart::Bokeh::Plot') ) { $rendered_cells .= $data->html( div_id => $id ); } else { $rendered_cells .= _render_cell( _process_data($data), $id ); } } my $plot = _render_html_wrap($rendered_cells); HTML::Show::show($plot); } 1; __END__ =pod =encoding utf-8 =head1 NAME Chart::Bokeh - Generate html/javascript charts from perl data using javascript library BokehJS =head1 VERSION version 0.001 =head1 SYNOPSIS use Chart::Bokeh qw(show_plot); my $plot_data = {x => [0..10], y => [map {rand 10} 0..10]}; show_plot($plot_data); =head1 DESCRIPTION Generate html/javascript charts from perl data using javascript library BokehJS. The result is a file that you could see in your favourite browser. The interface is "sub" oriented, but the API is subject to changes. =head1 FUNCTIONS =head2 render_full_html =head3 Parameters =over =item * data: Data to be represented. It could be: =over =item Perl data structure of the json expected by BokehJS: L