Group
Extension

Chart-Plotly/lib/Chart/Plotly/Image/Orca.pm

package Chart::Plotly::Image::Orca;

# ABSTRACT: Export static images of Plotly charts using orca

use 5.010;
use strict;
use warnings;

use Config;
use File::Which;
use Path::Tiny;
use File::ShareDir qw(dist_file);
use utf8;

our $VERSION = '0.042';    # VERSION

my $ORCA_COMMAND = 'orca';

# have this in a sub to avoid breaking auto-generated tests like pod-coverage.
sub _plotlyjs {
    state $plotlyjs = dist_file( 'Chart-Plotly', 'plotly.js/plotly.min.js' );
    return $plotlyjs;
}

sub _check_alien {
    my ($force_check) = @_;

    state $has_alien;

    if ( !defined $has_alien or $force_check ) {
        $has_alien = undef;
        eval { require Alien::Plotly::Orca; };
        if ( !$@ and Alien::Plotly::Orca->install_type eq 'share' ) {
            $ENV{PATH} = join( $Config{path_sep}, Alien::Plotly::Orca->bin_dir, $ENV{PATH} );
            $has_alien = 1;
        } else {
            $has_alien = 0;
        }
    }
    return $has_alien;
}

sub orca {
    my %params = @_;

    if ( orca_available() ) {
        my $plot   = $params{plot};
        my $file   = path( $params{file} );
        my $format = $params{format};
        unless ( defined $format ) {
            ($format) = $file =~ /\.([^\.]+)$/;
        }
        my $plotlyjs = $params{plotlyjs} // $params{plotly} // _plotlyjs;

        my $tmp_json = Path::Tiny->tempfile( SUFFIX => '.json' );
        $tmp_json->spew_raw( $plot->to_json_text );

        # For now have to explicitly specify -d as otherwise orca would
        #  not be able to store output to a different path other than cwd.
        # See https://github.com/plotly/orca/issues/101
        my @orca_line = ( $ORCA_COMMAND, 'graph', $tmp_json, '--plotlyjs', $plotlyjs, '-d', $file->parent,
                          '-o', $file->basename, ( $format ? ( '--format', $format ) : () ) );
        for my $arg (qw(mathjax scale width height)) {
            if ( my $val = $params{$arg} ) {
                push @orca_line, ( "--${arg}", $val );
            }
        }
        for my $arg (qw(safe verbose debug)) {
            if ( $params{$arg} ) {
                push @orca_line, "--${arg}";
            }
        }

        my $rc = system(@orca_line);
        return 1 unless ( $rc >> 8 );
    }
    return;
}

sub correct_orca {
    my $orca_help = `$ORCA_COMMAND --help`;
    return ( $orca_help =~ /plotly/i );
}

sub orca_available {
    my ($force_check) = @_;

    state $available;

    if ( !defined $available or $force_check ) {
        $available = undef;
        if ( not _check_alien($force_check)
             and ( not which($ORCA_COMMAND) or not correct_orca() ) )
        {
            die "Orca tool (its 'orca' command) must be installed and in "
              . "PATH in order to export images. "
              . "Either install Alien::Plotly::Orca from CPAN, or install "
              . "it manually (see https://github.com/plotly/orca#installation)";
        }
        $available = 1;
    }
    return $available;
}

sub orca_version {
    my ($force_check) = @_;

    state $version;

    if ( _check_alien($force_check) ) {
        return Alien::Plotly::Orca->version;
    }
    if ( orca_available($force_check) ) {
        $version = `$ORCA_COMMAND --version`;
        chomp($version);
        return $version;
    }
    return;
}

1;

__END__

=pod

=encoding utf-8

=head1 NAME

Chart::Plotly::Image::Orca - Export static images of Plotly charts using orca

=head1 VERSION

version 0.042

=head1 SYNOPSIS

 #!/usr/bin/env perl 
 
 use strict;
 use warnings;
 use utf8;
 
 use Chart::Plotly::Plot;
 use Chart::Plotly::Trace::Scatter;
 use Chart::Plotly::Image::Orca;
 
 my $plot = Chart::Plotly::Plot->new(traces => [ Chart::Plotly::Trace::Scatter->new( x => [ 1 .. 5 ], y => [ 1 .. 5 ] )]);
 
 Chart::Plotly::Image::Orca::orca(plot => $plot, file => "TestOrca.png");

=head1 DESCRIPTION

This module generate static images of Plotly charts without a browser using
L<Orca|https://github.com/plotly/orca>

Orca is an L<Electron|https://electronjs.org/> app that must be installed before
using this module. You can either, 

=over 4

=item *

Install the L<Alien::Plotly::Orca> module from CPAN. Or,

=item *

Install plotly-orca yourself and have a C<orca> command findable via the
C<PATH> env var in your system, see also
L<https://github.com/plotly/orca#installation>.

=back

=head1 FUNCTIONS

=head2 orca

    orca(plot => $plot, file => $file, %rest)

Export L<Chart::Plotly::Plot> as a static image file.

This function is a wrapper over the plotly orca command.
Most of its named parameters are mapped to orca's command line options.
See also the output of C<orca graph --help>.

Returns a true value if the orca command is successful.

=over 4

=item plot

Object to export

=item file

Filename (with or without path) to export

=item format

Sets the output format (png, jpeg, webp, svg, pdf, eps).
By default it's inferred from the specified file name extension.

=item scale

Sets the image scale.

=item width

Sets the image width.

=item height

Sets the image height.

=item plotlyjs

Sets plotlyjs file path. Default is the bundled plotly.min.js file.

=item plotly

This is same as the C<plotlyjs> parameter mentioned above.

=item mathjax

Sets path to MathJax files. Required to export LaTeX characters.

=item safe

Turns on safe mode: where figures likely to make browser window hang
during image generating are skipped.

=item verbose

Turn on verbose logging on stdout.

=item debug

Starts app in debug mode and turn on verbose logs on stdout.

=back

=head2 correct_orca

Checks that orca command available is the plotly image exporter,
as there may be some other different command also named "orca", like
L<https://help.gnome.org/users/orca/stable/>

=head2 orca_available

Checks that orca command is available and the plotly image exporter

=head2 orca_version

Returns the orca version

=head1 BUGS

Please report any bugs or feature requests via github: L<https://github.com/pablrod/p5-Chart-Plotly/issues>

=head1 DISCLAIMER

This is an unofficial Plotly Perl module. Currently I'm not affiliated in any way with Plotly. 
But I think plotly.js is a great library and I want to use it with perl.

If you like plotly.js please consider supporting them purchasing a pro subscription: L<https://plot.ly/products/cloud/>

=head1 SEE ALSO

L<Alien::Plotly::Orca>

=head1 AUTHOR

Pablo Rodríguez González <pablo.rodriguez.gonzalez@gmail.com>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2022 by Pablo Rodríguez González.

This is free software, licensed under:

  The MIT (X11) License

=cut


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.