File Coverage

blib/lib/PGPLOT/Device.pm
Criterion Covered Total %
statement 13 111 11.7
branch 1 64 1.5
condition 0 6 0.0
subroutine 5 19 26.3
pod 11 11 100.0
total 30 211 14.2


line stmt bran cond sub pod time code
1             package PGPLOT::Device;
2              
3             # ABSTRACT: autogenerate PGPLOT device names
4              
5 1     1   45834 use strict;
  1         10  
  1         23  
6 1     1   4 use warnings;
  1         2  
  1         1059  
7              
8             our $VERSION = '0.09';
9              
10              
11             our %Default = (
12             device => 'xs',
13             );
14              
15             our $ephemeral = qr{^xw$};
16             our $NDevices;
17             our %PGDevice;
18             our %DevMap;
19              
20              
21             #pod =method new
22             #pod
23             #pod $dev = PGPLOT::Device->new( $spec, \%opts );
24             #pod
25             #pod This constructs a new object. B<$spec> is the PGPLOT device
26             #pod specification, with the following allowed representations:
27             #pod
28             #pod =over
29             #pod
30             #pod =item I
31             #pod
32             #pod This results in the default PGPLOT behavior for the device.
33             #pod
34             #pod =item I
35             #pod
36             #pod N is an integer. This resolves to a constant output device. Usually
37             #pod I is C or C.
38             #pod
39             #pod =item I<+N/device>
40             #pod
41             #pod N is an integer. This will create a device which
42             #pod autoincrements. Usually I is C or C.
43             #pod
44             #pod =item I
45             #pod
46             #pod I is an output file name. Its format is as described in
47             #pod L. An extension will be automatically added, if
48             #pod required.
49             #pod
50             #pod =back
51             #pod
52             #pod The C<%opts> hash is available to pass other options to the
53             #pod constructor. These are:
54             #pod
55             #pod =over
56             #pod
57             #pod =item vars
58             #pod
59             #pod This is a hashref containing values to be interpolated into filenames.
60             #pod B dereferences the hashref at interpolation time, so
61             #pod will track any changes made by the application. For example:
62             #pod
63             #pod my %vars;
64             #pod $dev = PGPLOT::Device->new( "foo${a}${b}/ps",
65             #pod { vars => \%vars } );
66             #pod
67             #pod $vars{a} = 3;
68             #pod $vars{b} = 4;
69             #pod
70             #pod print $dev->next, "\n";
71             #pod
72             #pod will result in C. Additionally, if the values are scalar
73             #pod references, they will be dereferenced. This way the application is
74             #pod not forced to use a hash for its internal use:
75             #pod
76             #pod my ( $a, $b );
77             #pod my %vars = ( a => \$a, b => \$b )
78             #pod
79             #pod $dev = PGPLOT::Device->new( "foo${a}${b}/ps",
80             #pod { vars => \%vars } );
81             #pod
82             #pod $a = 3;
83             #pod $b = 4;
84             #pod print $dev->next, "\n";
85             #pod
86             #pod will also result in C.
87             #pod
88             #pod =back
89             #pod
90             #pod =cut
91              
92             sub new
93             {
94 1     1 1 75 my $class = shift;
95              
96 1         4 _class_init();
97              
98 0         0 my $self = { devn => 1,
99             last => undef,
100             vars => {} };
101 0         0 bless $self, $class;
102              
103 0         0 $self->_initialize(@_);
104              
105             # need to keep track of whether there was an initial prefix
106 0         0 $self->{init_prefix} = defined $self->{prefix};
107              
108 0         0 $self;
109             }
110              
111             sub _class_init
112             {
113 1 50   1   5 return if $NDevices;
114              
115 1         178 require PGPLOT;
116 0           PGPLOT::pgqndt( $NDevices );
117              
118 0           my @devices;
119              
120 0           for my $didx ( 1..$NDevices )
121             {
122 0           my ( $type, $tlen, $descr, $dlen, $inter );
123 0           PGPLOT::pgqdt( $didx, $type, $tlen, $descr, $dlen, $inter );
124 0           $type =~ s{/}{};
125 0           $PGDevice{lc $type} =
126             { idx => $didx,
127             type => lc($type),
128             tlen => $tlen,
129             descr => $descr,
130             dlen => $dlen,
131             inter => $inter,
132             };
133              
134 0           push @devices, lc $type;
135             }
136              
137 0           require Text::Abbrev;
138 0           Text::Abbrev::abbrev( \%DevMap, @devices );
139             }
140              
141              
142             sub _initialize
143             {
144 0 0   0     my $opts = 'HASH' eq ref $_[-1] ? pop @_ : {};
145              
146 0           my ( $self, $spec ) = @_;
147              
148 0 0         my %spec = defined $spec ? $self->_parse_spec($spec) : ();
149              
150             # don't allow an override to change the device
151 0 0         delete $spec{device} if defined $self->{device};
152              
153             # don't allow an override to change an initial prefix
154 0 0         delete $spec{prefix} if $self->{init_prefix};
155              
156             # fill the object
157 0           $self->{$_} = $spec{$_} for keys %spec;
158              
159 0 0         unless ( defined $self->{device} )
160             {
161 0           $self->{device} = $Default{device};
162 0           $self->{devinfo} = $PGDevice{$DevMap{$Default{device}}};
163             }
164              
165 0 0         if ( exists $opts->{vars} )
166             {
167 0           require Carp;
168             Carp::croak( "vars attribute must be a hash\n" )
169 0 0         unless 'HASH' eq ref $opts->{vars};
170              
171 0           $self->{vars} = $opts->{vars};
172             }
173              
174              
175 0   0       $self->{ask} = $self->is_interactive && $self->is_const;
176              
177              
178 0           $self;
179             }
180              
181             #pod =method override
182             #pod
183             #pod $dev->override( $filename, \%opts );
184             #pod
185             #pod This method is used to override the initial values of C<$filename>
186             #pod passed to the B method for non-interactive devices. This
187             #pod allows the user control over the interactive device, but gives
188             #pod the application more control over hardcopy destinations.
189             #pod
190             #pod Note that B<$filename> may include a PGPLOT device specification,
191             #pod which will override any specified earlier, but this is frowned upon.
192             #pod
193             #pod It takes the same options as does the B method.
194             #pod
195             #pod =cut
196              
197             sub override
198             {
199 0     0 1   my $self = shift;
200              
201 0 0         if ( ! $self->is_interactive() )
202             {
203 0           $self->_initialize(@_);
204             }
205              
206 0           $self;
207             }
208              
209             #pod =method devn
210             #pod
211             #pod $devn = $dev->devn;
212             #pod $dev->devn( $new_value);
213             #pod
214             #pod This is an accessor which retrieves and/or sets the device number for
215             #pod interactive devices.
216             #pod
217             #pod =cut
218              
219             sub devn
220             {
221 0     0 1   my $self = shift;
222 0           my $old = $self->{devn};
223 0 0         $self->{devn} = shift if @_;
224              
225 0           $old;
226             }
227              
228             #pod =method ask
229             #pod
230             #pod if ( $device->ask ) { .. }
231             #pod
232             #pod This is true if the device is interactive and constant, so that
233             #pod new plots erase old plots. This can be used with the B
234             #pod PGPLOT subroutine to ensure that the user will see all of the plots.
235             #pod See L.
236             #pod
237             #pod =cut
238              
239 0     0 1   sub ask { $_[0]->{ask} };
240              
241              
242             sub _parse_spec
243             {
244 0     0     my ( $self, $spec ) = @_;
245 0           my ( $prefix, $device );
246 0           my %spec;
247              
248              
249             # split into prefix and /device. set to prefix only, if no match,
250             # as that'll be the case if no device was specified.
251 0 0         $prefix = $spec
252             if 0 == ( ( $prefix, $device ) = $spec =~ m{(.*)/([^/]+)$} );
253              
254              
255             # be careful that a multi-directory path (dir/prefix) doesn't get
256             # translated into file/device. If /prefix looks like a real PGPLOT
257             # device, this will fail horribly.
258              
259             # if there's already a device, discard /device if it looks like
260             # a PGPLOT device, else append it to prefix.
261              
262             # if there's not already a device, /device had better look like
263             # a PGPLOT device.
264              
265 0 0 0       if ( defined $device && ! exists $DevMap{lc $device} )
266             {
267 0 0         if ( defined $self->{device} )
268             {
269 0           $prefix .= '/' . $device;
270 0           undef $device;
271             }
272              
273             # no pre-existing device. make sure that the device is a real one
274             else
275             {
276 0           require Carp;
277 0           Carp::croak( "unknown PGPLOT device: $device\n" );
278             }
279             }
280              
281             # if device isn't defined, use the existing one for the object
282 0 0         $spec{device} = defined $device ? lc($device) : $self->{device};
283 0           $spec{devinfo} = $PGDevice{$DevMap{$spec{device}}};
284 0           $spec{prefix} = $prefix;
285              
286 0 0         if ( $prefix )
287             {
288             # numeric (possibly autoincrement)
289 0 0         if ( $prefix =~ /^([+])?(\d+)?$/ )
    0          
290             {
291 0 0         $spec{devn} = defined $2 ? $2 : 1;
292              
293             # if +, autoincrement device number
294             # we use interpolation to handle this case
295 0 0         $spec{prefix} = defined $1 ? '${devn}' : $2;
296             }
297              
298             elsif ( defined $spec{device} )
299             {
300 0 0         if ( ! $spec{devinfo}{inter} )
301             {
302             my $ext = ($spec{device} =~ m{^v?c?(ps)$}i) ?
303 0 0         ".$1" : '.' . $spec{device};
304              
305             # make sure the appropriate suffix is in there
306 0           $prefix =~ s/${ext}$//;
307 0           $prefix .= $ext;
308 0           $spec{prefix} = $prefix;
309             }
310              
311             # we've got a situation here. an interactive device with a nonparseable
312             # prefix. better bail
313             else
314             {
315 0           require Carp;
316 0           Carp::croak( "error: interactive device with unparseable prefix: $spec\n" );
317             }
318             }
319             }
320              
321             # only defined keys get through. makes it easier to override
322             # things
323             delete $spec{$_}
324 0 0         for grep { ! defined $spec{$_} || '' eq $spec{$_} } keys %spec;
  0            
325              
326 0           %spec;
327             }
328              
329             #pod =method next
330             #pod
331             #pod $dev_str = $dev->next;
332             #pod
333             #pod This method is the basis for the automatic updating of the device
334             #pod specification when the object is used as a string. If desired it may
335             #pod be used directly. It will return the next device specification. It
336             #pod increments the device number.
337             #pod
338             #pod =cut
339              
340             sub next
341             {
342 0     0 1   my $self = shift;
343              
344 0           $self->{last} = $self->_stringify;
345 0           $self->{devn}++;
346 0           $self->{last};
347             }
348              
349             #pod =method current
350             #pod
351             #pod $dev_str = $dev->current;
352             #pod
353             #pod This returns the device string which would be generated in the current
354             #pod environment. It does not alter the environment.
355             #pod
356             #pod =cut
357              
358             sub current
359             {
360 0     0 1   my $self = shift;
361              
362 0           $self->_stringify;
363             }
364              
365             #pod =method last
366             #pod
367             #pod $dev_str = $dev->current;
368             #pod
369             #pod This returns the last generated device string. It does not alter the
370             #pod environment.
371             #pod
372             #pod =cut
373              
374             sub last
375             {
376 0     0 1   my $self = shift;
377 0           $self->{last};
378             }
379              
380             sub _compare
381             {
382 0     0     my ( $self, $other, $reverse ) = @_;
383              
384 0 0         $reverse ? $other cmp $self->_stringify : $self->_stringify cmp $other;
385             }
386              
387             #pod =method is_const
388             #pod
389             #pod if ( $dev->is_const ) { ... }
390             #pod
391             #pod This method returns true if the device specification does not
392             #pod interpolate any variables or device numbers.
393             #pod
394             #pod =cut
395              
396             sub is_const
397             {
398 0     0 1   my $self = shift;
399             defined $self->{prefix} ?
400 0 0         ($self->_stringify eq $self->{prefix} . '/' . $self->{device}) : 1;
401             }
402              
403             #pod =method would_change
404             #pod
405             #pod if ( $dev->would_change ) { ... }
406             #pod
407             #pod This method returns true if the last generated device specification
408             #pod would differ from one generated with the current environment. It
409             #pod returns true if no device specification has yet been generated.
410             #pod
411             #pod It does not change the current environment.
412             #pod
413             #pod =cut
414              
415             sub would_change
416             {
417 0     0 1   my $self = shift;
418              
419 0 0         return defined $self->{last} ? $self->_stringify ne $self->{last} : 1;
420             }
421              
422             #pod =method is_interactive
423             #pod
424             #pod if ( $dev->is_interactive ) { ... }
425             #pod
426             #pod This method returns true if the device is an interactive device.
427             #pod
428             #pod =cut
429              
430             sub is_interactive
431             {
432 0     0 1   my $self = shift;
433              
434 0           $self->{devinfo}{inter};
435             }
436              
437             #pod =method is_ephemeral
438             #pod
439             #pod if ( $dev->is_ephemeral ) { ... }
440             #pod
441             #pod This method returns true if the plot display will disappear if the
442             #pod device is closed (e.g., the C device ).
443             #pod
444             #pod =cut
445              
446             sub is_ephemeral
447             {
448 0     0 1   my $self = shift;
449 0           $self->{device} =~ /$ephemeral/;
450             }
451              
452              
453             sub _stringify
454             {
455 0     0     my $self = shift;
456              
457             # handle interpolated values
458 0 0         my $prefix = defined $self->{prefix} ? $self->{prefix} : '';
459              
460             # get calling package
461              
462 0           my ( $fmt, $val );
463              
464             ## no critic ( ProhibitNoStrict );
465 1     1   7 no strict 'refs';
  1         1  
  1         215  
466 0           my $pkg = (caller(1))[0];
467 0           1 while
468             $prefix =~
469             s/ \$\{ (\w+) (?::([^\}]+))? } /
470 0 0         $fmt = defined $2 ? $2 : '%s';
471              
472             $val =
473              
474             # special: device id
475             $1 eq 'devn' ? $self->{devn} :
476              
477             # part of the user passed set of variables?
478             exists $self->{vars}{$1} ?
479              
480             # dereference it if it's a scalar ref, else use it directly
481             ( 'SCALAR' eq ref $self->{vars}{$1} ?
482 0           ${$self->{vars}{$1}} : $self->{vars}{$1} ) :
483              
484             # is it in the parent package?
485 0 0         defined ${*{"${pkg}::$1"}{SCALAR}} ? ${*{"${pkg}::$1"}{SCALAR}} :
  0 0          
  0 0          
  0 0          
  0            
486              
487             # nothing
488             undef;
489              
490 0 0         sprintf( $fmt, $val ) if defined $val;
491             /ex;
492              
493 0           $prefix . '/' . $self->{device};
494             }
495              
496             1;
497              
498             #
499             # This file is part of PGPLOT-Device
500             #
501             # This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
502             #
503             # This is free software, licensed under:
504             #
505             # The GNU General Public License, Version 3, June 2007
506             #
507              
508             =pod
509              
510             =head1 NAME
511              
512             PGPLOT::Device - autogenerate PGPLOT device names
513              
514             =head1 VERSION
515              
516             version 0.09
517              
518             =head1 SYNOPSIS
519              
520             use PGPLOT::Device;
521              
522             $device = PGPLOT::Device->new( $spec );
523             $device = PGPLOT::Device->new( \%specs );
524              
525             # straight PGPLOT
526             pgbegin( 0, $device, 1, 1);
527              
528             # PDL
529             $win = PDL::Graphics::PGPLOT::Window->new({ Device => $device} );
530              
531             =head1 DESCRIPTION
532              
533             It is sometimes surprisingly difficult to create an appropriate PGPLOT
534             device. Coding for both interactive and hardcopy devices can lead to
535             code which repeatedly has to check the device type to generate the
536             correct device name. If an application outputs multiple plots, it
537             needs to meld unique names (usually based upon the output format) to
538             the user's choice of output device. The user should be given some
539             flexibility in specifying a device or hardcopy filename output
540             specification without making life difficult for the developer.
541              
542             This module tries to help reduce the agony. It does this by creating
543             an object which will resolve to a legal PGPLOT device specification.
544             The object can handle auto-incrementing of interactive window ids,
545             interpolation of variables into file names, automatic generation of
546             output suffices for hardcopy devices, etc.
547              
548             Here's the general scheme:
549              
550             =over
551              
552             =item *
553              
554             The application creates the object, using the user's PGPLOT device
555             specification to initialize it.
556              
557             =item *
558              
559             Before creating a new plot, the application specifies the output
560             filename it would like to have. The filename may use interpolated
561             variables. This is ignored if the device is interactive, as it is
562             meaningless in that context
563              
564             =item *
565              
566             Each time that the object value is retrieved using the C
567             method, the internal window id is incremented, any variables in the
568             filename are interpolated, and the result is returned.
569              
570             =back
571              
572             =head2 Interactive devices
573              
574             Currently, the C and C devices are recognized as being
575             interactive. PGPLOT allows more than one such window to be displayed;
576             this is accomplished by preceding the device name with an integer id,
577             e.g. C<2/xs>. If a program generates several independent plots, it can
578             either prompt between overwriting plots in a single window, or it may
579             choose to use multiple plotting windows. This module assists in the
580             latter case by implementing auto-increment of the window id. The
581             device specification syntax is extended to C<+N/xs> where C is an
582             integer indicating the initial window id.
583              
584             =head2 Hardcopy devices
585              
586             Hardcopy device specifications (i.e. not C or C) are
587             specified as C. The filename is optional, and will
588             automatically be given the extension appropriate to the output file
589             format. If a filename is specified in the specification passed to the
590             B method, it cannot be overridden. This allows the user to
591             specify a single output file for all hardcopy plots. This works well
592             for PostScript, which can handle multiple pages per file, but for the
593             PNG device, this results in multiple output files with numbered
594             suffices. It's not pretty! This module needs to be extended so it
595             knows if a single output file can handle more than one page.
596              
597             Variables may be interpolated into the filenames using the
598             C<${variable}> syntax (curly brackets are required). Note that only
599             simple scalars may be interpolated (not hash or array elements). The
600             values may be formatted using B by appending the format, i.e.
601             C<${variable:format}>. Variables which are available to be
602             interpolated are either those declared using B, or those passed
603             into the class constructor.
604              
605             The internal counter which tracks the number of times the device object has
606             been used is available as C<${devn}>.
607              
608             =head1 METHODS
609              
610             =head2 new
611              
612             $dev = PGPLOT::Device->new( $spec, \%opts );
613              
614             This constructs a new object. B<$spec> is the PGPLOT device
615             specification, with the following allowed representations:
616              
617             =over
618              
619             =item I
620              
621             This results in the default PGPLOT behavior for the device.
622              
623             =item I
624              
625             N is an integer. This resolves to a constant output device. Usually
626             I is C or C.
627              
628             =item I<+N/device>
629              
630             N is an integer. This will create a device which
631             autoincrements. Usually I is C or C.
632              
633             =item I
634              
635             I is an output file name. Its format is as described in
636             L. An extension will be automatically added, if
637             required.
638              
639             =back
640              
641             The C<%opts> hash is available to pass other options to the
642             constructor. These are:
643              
644             =over
645              
646             =item vars
647              
648             This is a hashref containing values to be interpolated into filenames.
649             B dereferences the hashref at interpolation time, so
650             will track any changes made by the application. For example:
651              
652             my %vars;
653             $dev = PGPLOT::Device->new( "foo${a}${b}/ps",
654             { vars => \%vars } );
655              
656             $vars{a} = 3;
657             $vars{b} = 4;
658              
659             print $dev->next, "\n";
660              
661             will result in C. Additionally, if the values are scalar
662             references, they will be dereferenced. This way the application is
663             not forced to use a hash for its internal use:
664              
665             my ( $a, $b );
666             my %vars = ( a => \$a, b => \$b )
667              
668             $dev = PGPLOT::Device->new( "foo${a}${b}/ps",
669             { vars => \%vars } );
670              
671             $a = 3;
672             $b = 4;
673             print $dev->next, "\n";
674              
675             will also result in C.
676              
677             =back
678              
679             =head2 override
680              
681             $dev->override( $filename, \%opts );
682              
683             This method is used to override the initial values of C<$filename>
684             passed to the B method for non-interactive devices. This
685             allows the user control over the interactive device, but gives
686             the application more control over hardcopy destinations.
687              
688             Note that B<$filename> may include a PGPLOT device specification,
689             which will override any specified earlier, but this is frowned upon.
690              
691             It takes the same options as does the B method.
692              
693             =head2 devn
694              
695             $devn = $dev->devn;
696             $dev->devn( $new_value);
697              
698             This is an accessor which retrieves and/or sets the device number for
699             interactive devices.
700              
701             =head2 ask
702              
703             if ( $device->ask ) { .. }
704              
705             This is true if the device is interactive and constant, so that
706             new plots erase old plots. This can be used with the B
707             PGPLOT subroutine to ensure that the user will see all of the plots.
708             See L.
709              
710             =head2 next
711              
712             $dev_str = $dev->next;
713              
714             This method is the basis for the automatic updating of the device
715             specification when the object is used as a string. If desired it may
716             be used directly. It will return the next device specification. It
717             increments the device number.
718              
719             =head2 current
720              
721             $dev_str = $dev->current;
722              
723             This returns the device string which would be generated in the current
724             environment. It does not alter the environment.
725              
726             =head2 last
727              
728             $dev_str = $dev->current;
729              
730             This returns the last generated device string. It does not alter the
731             environment.
732              
733             =head2 is_const
734              
735             if ( $dev->is_const ) { ... }
736              
737             This method returns true if the device specification does not
738             interpolate any variables or device numbers.
739              
740             =head2 would_change
741              
742             if ( $dev->would_change ) { ... }
743              
744             This method returns true if the last generated device specification
745             would differ from one generated with the current environment. It
746             returns true if no device specification has yet been generated.
747              
748             It does not change the current environment.
749              
750             =head2 is_interactive
751              
752             if ( $dev->is_interactive ) { ... }
753              
754             This method returns true if the device is an interactive device.
755              
756             =head2 is_ephemeral
757              
758             if ( $dev->is_ephemeral ) { ... }
759              
760             This method returns true if the plot display will disappear if the
761             device is closed (e.g., the C device ).
762              
763             =head1 EXAMPLES
764              
765             =over
766              
767             =item *
768              
769             Here's the prototypical example. The application outputs multiple
770             plots and the user is allowed to specify an output device. The device
771             is initialized directly from the user's input:
772              
773             $device = PGPLOT::Device->new( $user_device_spec );
774              
775             Before each call to C or Cnew>, indicate
776             via the B method the new hardcopy filename, without any
777             suffix. The filename will be ignored if the user has specified an
778             interactive device:
779              
780             $device->override( 'out_${theta:%05.2f}' );
781              
782             Use B to retrieve the value:
783              
784             pgbegin( 0, $device->next, 1, );
785             $win = PDL::Graphics::PGPLOT::Window->new({ Device => $device->next} );
786              
787             =item *
788              
789             The application outputs multiple plots, and the user should be able to
790             decide whether a single interactive device window should be used, or
791             whether multiple ones should be used. In the first instance, the user
792             specifies the device as C, in the second C<+/xs> or C<+1/xs>:
793              
794             $device = PGPLOT::Device->new( $user_device_spec );
795              
796             $device->override( 'hardcopy-${vara}-${varb}' );
797              
798             $win = PDL::Graphics::PGPLOT::Window->new({ Device => $device->next} );
799              
800             [... generate plot 1 ... ]
801              
802             # do this after generating the plot, because Window
803             # be constant, and that'll confuse is_const()
804             pgask( $device->ask );
805              
806             # next plot.
807              
808             if ( $device->would_change )
809             {
810             $win->close;
811             $win = PDL::Graphics::PGPLOT::Window->new({ Device => $device->next} );
812             }
813              
814             # etc.
815              
816             # make sure that the user is prompted before the device is closed
817             # if the device will disappear.
818             pgask( 1 ) if $device->ephemeral;
819             $win->close;
820              
821             Note that B will return true if no specification has
822             yet been generated. This allows one to simplify coding if plots
823             are generated within loops:
824              
825             my $win;
826              
827             my %vars;
828             my $device = PGPLOT::Device->new( $user_device_spec );
829             $device->override( 'file-${a}-${b}', { vars => \%vars } );
830             my $not_first = 0;
831             for my $plot ( @plots )
832             {
833             $vars{a} = $plot->{a};
834             $vars{b} = $plot->{b};
835              
836             # prompt user before displaying second and subsequent plots if
837             # a new plot will erase the previous one
838             pgask( $param{device}->ask ) if $not_first++;
839              
840             if ( $device->would_change )
841             {
842             $win->close if defined $win;
843             $win = PDL::Graphics::PGPLOT::Window->new({ Device => $device->next} );
844             }
845              
846             [... plot stuff ...]
847             }
848              
849             if ( defined $win )
850             {
851             # make sure that the plot stays up until the user is done with it
852             pgask(1) if $device->ephemeral;
853             $win->close;
854             }
855              
856             =back
857              
858             =head1 BUGS
859              
860             Please report any bugs or feature requests on the bugtracker website
861             L or by
862             email to
863             L.
864              
865             When submitting a bug or request, please include a test-file or a
866             patch to an existing test-file that illustrates the bug or desired
867             feature.
868              
869             =head1 SOURCE
870              
871             The development version is on github at L
872             and may be cloned from L
873              
874             =head1 SEE ALSO
875              
876             Please see those modules/websites for more information related to this module.
877              
878             =over 4
879              
880             =item *
881              
882             L
883              
884             =item *
885              
886             L
887              
888             =item *
889              
890             L
891              
892             =back
893              
894             =head1 AUTHOR
895              
896             Diab Jerius
897              
898             =head1 COPYRIGHT AND LICENSE
899              
900             This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
901              
902             This is free software, licensed under:
903              
904             The GNU General Public License, Version 3, June 2007
905              
906             =cut
907              
908             __END__