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 )