File Coverage

blib/lib/Chart/Plotly.pm
Criterion Covered Total %
statement 70 103 67.9
branch 7 24 29.1
condition 3 14 21.4
subroutine 21 25 84.0
pod 6 6 100.0
total 107 172 62.2


line stmt bran cond sub pod time code
1              
2             use strict;
3 6     6   82683 use warnings;
  6         12  
  6         150  
4 6     6   26 use utf8;
  6         12  
  6         137  
5 6     6   24  
  6         11  
  6         29  
6             use Exporter 'import';
7 6     6   127 use vars qw(@EXPORT_OK);
  6         17  
  6         198  
8 6     6   27 @EXPORT_OK = qw(show_plot);
  6         32  
  6         303  
9              
10             use JSON;
11 6     6   1161 use Params::Validate qw(:all);
  6         19149  
  6         40  
12 6     6   3639 use Text::Template;
  6         25708  
  6         848  
13 6     6   4261 use Module::Load;
  6         18738  
  6         257  
14 6     6   2707 use Ref::Util;
  6         5604  
  6         35  
15 6     6   2561 use HTML::Show;
  6         7993  
  6         255  
16 6     6   2360 use UUID::Tiny ':std';
  6         60441  
  6         168  
17 6     6   1286 use File::ShareDir;
  6         22145  
  6         954  
18 6     6   2247 use Path::Tiny;
  6         85091  
  6         227  
19 6     6   44  
  6         10  
  6         4650  
20             our $VERSION = '0.042'; # VERSION
21              
22             # ABSTRACT: Generate html/javascript charts from perl data using javascript library plotly.js
23              
24             ## no critic
25             my %params = validate( @_, { data => { type => ARRAYREF | OBJECT }, } );
26             ## use critic
27 0     0 1 0  
28             my $data = $params{'data'};
29             my $chart_id = create_uuid_as_string(UUID_TIME);
30 0         0 my $html;
31 0         0 if ( Ref::Util::is_blessed_ref($data) && $data->isa('Chart::Plotly::Plot') ) {
32 0         0 $html = _render_html_wrap( $data->html( div_id => $chart_id ) );
33 0 0 0     0 } else {
34 0         0 $html = _render_html_wrap( _render_cell( _process_data($data), $chart_id ) );
35             }
36 0         0 return $html;
37             }
38 0         0  
39             my $body = shift;
40             my $html_begin = <<'HTML_BEGIN';
41             <!DOCTYPE html>
42 0     0   0 <head>
43 0         0 <meta charset="utf-8" />
44             </head>
45             <body>
46             HTML_BEGIN
47             my $html_end = <<'HTML_END';
48             </body>
49             </html>
50 0         0 HTML_END
51             return $html_begin . $body . $html_end;
52             }
53              
54 0         0 my $data_string = shift();
55             my $chart_id = shift() // create_uuid_as_string(UUID_TIME);
56             my $layout = shift();
57             my $config = shift();
58 1     1   2 my $extra = shift() // { load_plotly_using_script_tag => 1 };
59 1   33     3 if ( defined $layout ) {
60 1         2 $layout = "," . $layout;
61 1         3 }
62 1   50     3 if ( defined $config ) {
63 1 50       3 $config = "," . $config;
64 1         3 }
65             my $load_plotly = _load_plotly( ${$extra}{'load_plotly_using_script_tag'} );
66 1 50       4 my $template = <<'TEMPLATE';
67 1         3 <div id="{$chart_id}"></div>
68             {$load_plotly}
69 1         3 <script>
  1         4  
70 1         2 Plotly.{$plotlyjs_plot_function}(document.getElementById('{$chart_id}'),{$data} {$layout} {$config});
71             </script>
72             TEMPLATE
73              
74             my $template_variables = { data => $data_string,
75             chart_id => $chart_id,
76             load_plotly => $load_plotly,
77             plotlyjs_plot_function => plotlyjs_plot_function(),
78 1 50       12 defined $layout ? ( layout => $layout ) : (),
    50          
79             defined $config ? ( config => $config ) : (),
80             };
81             return Text::Template::fill_in_string( $template, HASH => $template_variables );
82             }
83              
84             my $data = shift;
85 1         8 my $json_formatter = JSON->new->allow_blessed(1)->convert_blessed(1);
86             local *PDL::TO_JSON = sub { $_[0]->unpdl };
87             if ( Ref::Util::is_blessed_ref($data) ) {
88             my $adapter_name = 'Chart::Plotly::Adapter::' . ref $data;
89 6     6   14 eval {
90 6         51 load $adapter_name;
91 6     2   34 my $adapter = $adapter_name->new( data => $data );
  2         138  
92 6 50       17 $data = $adapter->traces();
93 0         0 };
94 0         0 if ($@) {
95 0         0 warn 'Cannot load adapter: ' . $adapter_name . '. ' . $@;
96 0         0 }
97 0         0 }
98             my $data_string = $json_formatter->encode($data);
99 0 0       0 return $data_string;
100 0         0 }
101              
102             my $how_to_load = shift;
103 6         40 if ($how_to_load) {
104 6         78 if ( $how_to_load eq "1" || $how_to_load eq 'cdn' ) {
105             return '<script src="https://cdn.plot.ly/plotly-' . plotlyjs_version() . '.min.js"></script>';
106             } elsif ( $how_to_load eq 'embed' ) {
107             my $minified_plotly = File::ShareDir::dist_file( 'Chart-Plotly', 'plotly.js/plotly.min.js' );
108 1     1   2 return '<script>' . Path::Tiny::path($minified_plotly)->slurp . '</script>';
109 1 50       4 } elsif ( $how_to_load eq 'module_dist' ) {
110 1 50 33     5 my $minified_plotly = File::ShareDir::dist_file( 'Chart-Plotly', 'plotly.js/plotly.min.js' );
    0          
    0          
111 1         3 return '<script src="file://' . $minified_plotly . '"></script>';
112             }
113 0         0 } else {
114 0         0 return '';
115             }
116 0         0 }
117 0         0  
118             my @data_to_plot = @_;
119              
120 0         0 my $rendered_cells = "";
121             for my $data (@data_to_plot) {
122             my $id = create_uuid_as_string(UUID_TIME);
123             if ( Ref::Util::is_blessed_ref($data) && $data->isa('Chart::Plotly::Plot') ) {
124             $rendered_cells .= $data->html( div_id => $id );
125 0     0 1 0 } else {
126             $rendered_cells .= _render_cell( _process_data($data), $id );
127 0         0 }
128 0         0 }
129 0         0 return _render_html_wrap($rendered_cells);
130 0 0 0     0 }
131 0         0  
132             HTML::Show::show( html_plot(@_) );
133 0         0 }
134              
135             return '2.14.0'; # plotlyjs_version_tag
136 0         0 }
137              
138             return 'react';
139             }
140 0     0 1 0  
141             return qw(div data layout config);
142             }
143              
144 1     1 1 5 1;
145              
146              
147             =pod
148 3     3 1 19  
149             =encoding utf-8
150              
151             =head1 NAME
152 1     1 1 5  
153             Chart::Plotly - Generate html/javascript charts from perl data using javascript library plotly.js
154              
155             =head1 VERSION
156              
157             version 0.042
158              
159             =head1 SYNOPSIS
160              
161             use Chart::Plotly 'show_plot';
162            
163             my $data = { x => [ 1 .. 10 ],
164             mode => 'markers',
165             type => 'scatter'
166             };
167             $data->{'y'} = [ map { rand 10 } @{ $data->{'x'} } ];
168            
169             show_plot([$data]);
170            
171             use aliased 'Chart::Plotly::Trace::Scattergl';
172            
173             my $big_array = [ 1 .. 10000 ];
174             my $scattergl = Scattergl->new( x => $big_array, y => [ map { rand 100 } @$big_array ] );
175            
176             show_plot([$scattergl]);
177              
178             use Chart::Plotly qw(show_plot);
179             use PDL;
180            
181             use aliased 'Chart::Plotly::Trace::Surface';
182            
183             my $size = 25;
184             my $x = ( xvals zeroes $size+ 1, $size + 1 ) / $size;
185             my $y = ( yvals zeroes $size+ 1, $size + 1 ) / $size;
186             my $z = 0.5 + 0.5 * ( sin( $x * 6.3 ) * sin( $y * 6.3 ) )**3; # Bumps
187            
188             my $surface = Surface->new( x => $x, y => $y, z => $z );
189            
190             show_plot([$surface]);
191            
192             use PDL::Math;
193            
194             my $bessel_size = 50;
195             my $bessel = Surface->new(
196             x => xvals($bessel_size),
197             y => xvals($bessel_size),
198             z => bessj0( rvals( zeroes( $bessel_size, $bessel_size ) ) / 2 )
199             );
200            
201             show_plot([$bessel]);
202              
203             =head1 DESCRIPTION
204              
205             Generate html/javascript charts from perl data using javascript library plotly.js. The result
206             is a file that you could see in your favourite browser.
207              
208             =for markdown [![Build Status](https://travis-ci.org/pablrod/p5-Chart-Plotly.png?branch=master)](https://travis-ci.org/pablrod/p5-Chart-Plotly)
209             [![Build status](https://ci.appveyor.com/api/projects/status/wbur95v3sjk4mv6d/branch/master?svg=true)](https://ci.appveyor.com/project/pablrod/p5-chart-plotly/branch/master)
210              
211             Example screenshot of plot generated with examples/anscombe.pl:
212              
213             =for HTML <p>
214             <img src="https://raw.githubusercontent.com/pablrod/p5-Chart-Plotly/master/examples/anscombe.png" alt="Anscombe's quartet plotted with plotly">
215             </p>
216              
217             =for markdown ![Anscombe's quartet plotted with plotly](https://raw.githubusercontent.com/pablrod/p5-Chart-Plotly/master/examples/anscombe.png)
218              
219             Example screenshot of plots generated with examples/traces/*.pl:
220              
221             =for HTML <p>
222             <img src="https://raw.githubusercontent.com/pablrod/p5-Chart-Plotly/master/examples/montage_all_traces.png" alt="Montage of all examples">
223             </p>
224              
225             =for markdown ![Montage of all examples](https://raw.githubusercontent.com/pablrod/p5-Chart-Plotly/master/examples/montage_all_traces.png)
226              
227             The API is subject to changes.
228              
229             =head1 FUNCTIONS
230              
231             =head2 render_full_html
232              
233             =head3 Parameters
234              
235             =over
236              
237             =item * data:
238              
239             Data to be represented. It could be:
240              
241             =over
242              
243             =item Perl data structure of the json expected by plotly.js: L<http://plot.ly/javascript/reference/> (this data would be serialized to JSON)
244              
245             =item Array ref of objects of type Chart::Plotly::Trace::*
246              
247             =item Anything that could be serialized to JSON with the json expected by plotly.js
248              
249             =item Object that could be adapted using Chart::Plotly::Adapter::*
250              
251             =back
252              
253             =back
254              
255             =head2 html_plot
256              
257             Return the html for the plot or plots
258              
259             =head3 Parameters
260              
261             Data to be represented. The format is the same as the parameter data in render_full_html. Accepts multiple traces/plots/objects.
262              
263             =head2 show_plot
264              
265             Opens the plot or plots in a browser locally
266              
267             =head3 Parameters
268              
269             Data to be represented. The format is the same as the parameter data in render_full_html. Accepts multiple traces/plots/objects.
270              
271             =head2 plotlyjs_version
272              
273             Returns the version of plotly.js using in this version of the perl module as a string
274              
275             =head2 plotlyjs_plot_function
276              
277             Returns the name of function of plotly.js used in this version of the perl module to draw plots
278              
279             =head2 plotlyjs_plot_function_parameters
280              
281             Returns the function parameters of the function of plotly.js used in this version of the perl module to draw plots as a list of strings
282              
283             =head1 BUGS
284              
285             Please report any bugs or feature requests via github: L<https://github.com/pablrod/p5-Chart-Plotly/issues>
286              
287             =head1 DISCLAIMER
288              
289             This is an unofficial Plotly Perl module. Currently I'm not affiliated in any way with Plotly.
290             But I think plotly.js is a great library and I want to use it with perl.
291              
292             If you like plotly.js please consider supporting them purchasing a pro subscription: L<https://plot.ly/products/cloud/>
293              
294             =head1 AUTHOR
295              
296             Pablo Rodríguez González <pablo.rodriguez.gonzalez@gmail.com>
297              
298             =head1 COPYRIGHT AND LICENSE
299              
300             This software is Copyright (c) 2022 by Pablo Rodríguez González.
301              
302             This is free software, licensed under:
303              
304             The MIT (X11) License
305              
306             =head1 CONTRIBUTORS
307              
308             =for stopwords Roy Storey stphnlyd weatherwax
309              
310             =over 4
311              
312             =item *
313              
314             Roy Storey <kiwiroy@users.noreply.github.com>
315              
316             =item *
317              
318             stphnlyd <stephanloyd9@gmail.com>
319              
320             =item *
321              
322             weatherwax <s.g.lobo@hotmail.com>
323              
324             =back
325              
326             =cut