Matplotlib-Simple
view release on metacpan or search on metacpan
t/03.coverage.t view on Meta::CPAN
my $py = gen_py(
'plot.type' => 'plot',
data => { L => [ [@xw], [@yv] ] },
title => 'My Title',
xlabel => 'the x',
ylabel => 'the y',
'show.legend' => 0,
'output.file' => outfile('labels.svg'),
);
like( $py, qr/set_title\('My Title'\)/, 'title becomes set_title' );
like( $py, qr/set_xlabel\(/, 'xlabel becomes set_xlabel' );
like( $py, qr/set_ylabel\(/, 'ylabel becomes set_ylabel' );
# hlines and set_xlim pass through as plt-method strings
like(
gen_py(
'plot.type' => 'plot',
data => { L => [ [@xw], [@yv] ] },
hlines => "1, $xw[0], $xw[-1], linestyles = 'dashed'",
set_xlim => "$xw[0], $xw[-1]",
'show.legend' => 0,
'output.file' => outfile('hlines.svg'),
),
qr/hlines\(/, 'hlines passes through to matplotlib'
);
}
# ============================================================================
# 6. set.options (scalar / array / per-key hash) and logscale.
# ============================================================================
{
# scalar set.options on a single line
like( gen_py( 'plot.type' => 'plot', 'show.legend' => 0, data => [ [ 1 .. 5 ], [ 1 .. 5 ] ], 'set.options' => 'color = "red"', 'output.file' => outfile('so.scalar.svg') ),
qr/color = "red"/, 'scalar set.options applied to a single line' );
# scalar set.options broadcast to every line of array data
is( count_matches(
gen_py( 'plot.type' => 'plot', data => [ [ [ 1 .. 3 ], [ 1 .. 3 ] ], [ [ 1 .. 3 ], [ 3, 2, 1 ] ] ], 'set.options' => 'linewidth = 2', 'output.file' => outfile('so.broadcast.svg') ),
qr/linewidth = 2/ ),
2, 'scalar set.options broadcast to all array lines' );
# array set.options is positional
my $pos = gen_py( 'plot.type' => 'plot', data => [ [ [ 1 .. 3 ], [ 1 .. 3 ] ], [ [ 1 .. 3 ], [ 3, 2, 1 ] ] ], 'set.options' => [ 'color = "red"', 'color = "blue"' ], 'output.file' => outfile('so.array.svg') );
like( $pos, qr/color = "red"/, 'array set.options: first line' );
like( $pos, qr/color = "blue"/, 'array set.options: second line' );
# per-key hash set.options on hash data
like(
gen_py( 'plot.type' => 'plot', data => { sinL => [ [@t], [ map { sin $_ } @t ] ] }, 'set.options' => { sinL => 'color = "green"' }, 'show.legend' => 0, 'output.file' => outfile('so.hash.svg') ),
qr/color = "green"/, 'per-key hash set.options applied'
);
# logscale on both axes
like(
gen_py( 'plot.type' => 'scatter', data => { A => [@xw], B => [@yv], Z => [@cx] }, color_key => 'Z', logscale => [ 'x', 'y' ], 'output.file' => outfile('logscale.svg') ),
qr/set_[xy]scale\(\s*["']log["']/, 'logscale => [x,y] sets a log scale'
);
}
# ============================================================================
# 7. add-overlays on a single plot, and twinx.
# ============================================================================
{
# scatter with an overlaid line via "add"; the overlay draws on the same axis
my $py = gen_py(
'plot.type' => 'scatter',
data => { A => [@xw], B => [@yv], Z => [@cx] },
color_key => 'Z',
add => [
{ 'plot.type' => 'plot', 'show.legend' => 0, data => { over => [ [@xw], [@yv] ] } },
],
'output.file' => outfile('add.svg'),
);
like( $py, qr/\.scatter\(/, 'add: base scatter present' );
like( $py, qr/\.plot\(/, 'add: overlaid line present on the same axis' );
# twinx: second line on a twinned y-axis (array form + twinx.args)
my $tw = gen_py(
'plot.type' => 'plot',
data => [ [ [@t], [ map { sin $_ } @t ] ], [ [@t], [ map { exp $_ } @t ] ] ],
'set.options' => [ 'color = "blue"', 'color = "red"' ],
'twinx.args' => { 1 => { ylabel => '"exp", color="red"' } },
'output.file' => outfile('twinx.svg'),
);
like( $tw, qr/twinx\(\)/, 'twinx.args creates a twinned axis' );
}
# ============================================================================
# 8. Subplots (plots array): grid, suptitle, sharex/sharey.
# ============================================================================
{
my $py = gen_py(
suptitle => 'Grid',
sharex => 1,
sharey => 1,
ncols => 2,
plots => [
{ 'plot.type' => 'hist', data => { A => [@g1] }, title => 'a' },
{ 'plot.type' => 'boxplot', data => { B => [@g2] }, title => 'b' },
],
'output.file' => outfile('grid.svg'),
);
like( $py, qr/plt\.subplots\(\s*1\s*,\s*2\b/, 'plots array + ncols=2 makes a 1x2 grid' );
like( $py, qr/suptitle\(/, 'suptitle emitted for the figure' );
like( $py, qr/sharex\s*=\s*1/, 'sharex passed to subplots' );
like( $py, qr/^ax0\.hist\(/m, 'first subplot on ax0' );
like( $py, qr/ax1\.boxplot\(/, 'second subplot on ax1' );
}
# ============================================================================
# 9. The "p" interface under the new (one-element-per-subplot) semantics.
# (t-p-interface.t covers this exhaustively; these keep it wired here too.)
# ============================================================================
{
# flat: two hashes => two subplots (auto grid)
my $flat = gen_py(
p => [ { 'plot.type' => 'hist', data => { A => [@g1] } }, { 'plot.type' => 'hist', data => { B => [@g2] } } ],
'output.file' => outfile('p.flat.svg'),
);
like( $flat, qr/^ax0\.hist\(/m, 'p flat: subplot 0 on ax0' );
like( $flat, qr/^ax1\.hist\(/m, 'p flat: subplot 1 on ax1' );
# mixed: an inner array is one subplot with overlays
my $mixed = gen_py(
p => [
{ 'plot.type' => 'hist', data => { A => [@g1] } },
[ { 'plot.type' => 'hist', data => { B => [@g2] } }, { 'plot.type' => 'hist', data => { C => [@g1] } } ],
],
ncols => 1,
'output.file' => outfile('p.mixed.svg'),
);
is( count_matches( $mixed, qr/^ax1\.hist\(/m ), 2, 'p mixed: inner array overlays two plots on ax1' );
like( $mixed, qr/plt\.subplots\(\s*2\s*,\s*1\b/, 'p mixed: ncols=1 derives a 2x1 grid' );
}
# ============================================================================
# 10. Error branches specific to the helpers.
# ============================================================================
dies_like( sub { plt( 'plot.type' => 'nope', data => { A => 1 }, 'output.file' => outfile('e.svg') ) },
qr/isn't defined|isn't a known plot\.type/, 'unknown plot.type dies' );
dies_like( sub { plt( 'plot.type' => 'imshow', data => { A => [ 0, 1 ], B => [ 0, 3 ] }, 'output.file' => outfile('e.svg') ) },
qr/./, 'imshow rejects a hash (needs a 2-D array)' );
dies_like( sub { plt( data => { A => 1 }, 'plot.type' => 'bar', orientation => 'sideways', 'output.file' => outfile('e.svg') ) },
qr/./, 'bar rejects an undefined option value' );
dies_like( sub { plt( 'plot.type' => 'bar', 'output.file' => outfile('e.svg') ) },
qr/./, 'bar without data dies' );
# ============================================================================
# 12. Additional cold branches: alternate forms of the richer features.
# ============================================================================
{
# wide: hash form with a per-key color hash (array form covered above)
lives_ok_t( sub {
plt( 'plot.type' => 'wide',
data => { Clinical => wide_lines(), HGI => wide_lines() },
color => { Clinical => 'blue', HGI => 'green' },
execute => 0, 'output.file' => outfile('wide.hash.svg') );
}, 'wide accepts a hash of labelled line-sets with a color hash' );
# twinx: hash form with twinx.args keyed by the twinned label
lives_ok_t( sub {
plt( 'plot.type' => 'plot',
data => { sin => [ [@t], [ map { sin $_ } @t ] ], expo => [ [@t], [ map { exp $_ } @t ] ] },
'set.options' => { sin => 'color = "blue"', expo => 'color = "red"' },
'twinx.args' => { expo => { ylabel => '"exp", color="red"' } },
execute => 0, 'output.file' => outfile('twinx.hash.svg') );
}, 'twinx hash form twins on the named key' );
# grouped bar (hash of hashes) with a single scalar color applied to all
lives_ok_t( sub {
plt( 'plot.type' => 'bar',
data => { G1 => { A => 1, B => 2 }, G2 => { A => 3, B => 4 } },
color => 'green',
execute => 0, 'output.file' => outfile('bar.grouped.svg') );
}, 'grouped bar (hash of hashes) with a scalar color' );
# stacked barh
lives_ok_t( sub {
plt( 'plot.type' => 'barh', stacked => 1,
data => { G1 => { A => 1, B => 2 }, G2 => { A => 3, B => 4 } },
execute => 0, 'output.file' => outfile('barh.stacked.svg') );
}, 'stacked barh' );
# colored_table with the full label/mirror/number option set
lives_ok_t( sub {
plt( 'plot.type' => 'colored_table',
data => { %matrix },
cblabel => 'energy',
'col.labels' => [ 'H', 'C', 'N' ],
( run in 0.902 second using v1.01-cache-2.11-cpan-7fcb06a456a )