File Coverage

blib/lib/PDL/Graphics/Simple/Prima.pm
Criterion Covered Total %
statement 32 329 9.7
branch 3 122 2.4
condition 1 33 3.0
subroutine 8 24 33.3
pod 0 3 0.0
total 44 511 8.6


line stmt bran cond sub pod time code
1             ######################################################################
2             ######################################################################
3             ######################################################################
4             ###
5             ###
6             ### Prima backend for PDL::Graphics:Simple
7             ###
8             ### See the PDL::Graphics::Simple docs for details
9             ###
10             ### Prima setup is borrowed from D. Mertens' PDL::Graphics::Prima::Simple
11             ###
12             ##
13             #
14              
15             package PDL::Graphics::Simple::Prima;
16              
17 1     1   8 use strict;
  1         2  
  1         50  
18 1     1   7 use warnings;
  1         2  
  1         73  
19 1     1   8 use PDL;
  1         2  
  1         6  
20 1     1   4539 use PDL::ImageND; # for polylines
  1         2  
  1         10  
21 1     1   189 use PDL::Options q/iparse/;
  1         3  
  1         94  
22 1     1   8 use File::Temp qw/tempfile/;
  1         3  
  1         6888  
23              
24             our $mod = {
25             shortname => 'prima',
26             module => 'PDL::Graphics::Simple::Prima',
27             engine => 'PDL::Graphics::Prima',
28             synopsis => 'Prima (interactive, fast, PDL-specific)',
29             pgs_api_version=> '1.012',
30             };
31             PDL::Graphics::Simple::register( $mod );
32              
33             our (@colors, @patterns, $types);
34              
35             ##########
36             # PDL::Graphics::Simple::Prima::check
37             # Checker
38             sub check {
39 1     1 0 4 my $force = shift;
40 1 50       21 $force = 0 unless(defined($force));
41              
42 1 50 33     9 return $mod->{ok} unless( $force or !defined($mod->{ok}));
43 1         4 $mod->{ok} = 0; # makes default case simpler
44              
45             # Check Prima availability
46 1         3 my $min_version = 0.18;
47 1         3 eval { require PDL::Graphics::Prima; };
  1         190  
48 1 50       6 if($@) {
49 1         4 $mod->{msg} = "Couldn't load PDL::Graphics::Prima: ".$@;
50 1         2 undef $@;
51 1         6 return 0;
52             }
53 0 0         if ($PDL::Graphics::Prima::VERSION < $min_version) {
54 0           $mod->{msg} = "Prima version $PDL::Graphics::Prima::VERSION is too low ($min_version required)";
55 0           return 0;
56             }
57              
58 0           eval { require PDL::Graphics::Prima::Simple; };
  0            
59 0 0         if($@) {
60 0           $mod->{msg} = "Couldn't load PDL::Graphics::Prima::Simple: ".$@;
61 0           undef $@;
62 0           return 0;
63             }
64              
65 0           eval {
66 0           require Prima::Application;
67 0           Prima::Application->import();
68             };
69 0 0         if($@) {
70 0           $mod->{msg} = "Couldn't load Prima application: ".$@;
71 0           undef $@;
72 0           return 0;
73             }
74              
75             # Don't know if all these are actually needed; I'm stealing from the demo.
76             # --CED
77 0           eval {
78 0           require Prima::Label;
79 0           require Prima::PodView;
80 0           require Prima::Buttons;
81 0           require Prima::Utils;
82 0           require Prima::Edit;
83 0           require Prima::Const;
84             };
85 0 0         if($@){
86 0           $mod->{msg} = "Couldn't load auxiliary Prima modules: ".$@;
87 0           undef $@;
88 0           return 0;
89             }
90             @colors = (
91 0           cl::Black(), cl::Red(), cl::Green(), cl::Blue(), cl::Cyan(),
92             cl::Magenta(), cl::Yellow(), cl::Brown(),
93             cl::LightRed(), cl::LightGreen(), cl::LightBlue(), cl::Gray(),
94             );
95 0           @patterns = (
96             lp::Solid(), lp::Dash(), lp::LongDash(), lp::ShortDash(), lp::DotDot(),
97             lp::DashDot(), lp::DashDotDot(),
98             );
99 0           _load_types();
100 0           $mod->{prima_version} = $Prima::VERSION;
101 0           $mod->{ok} =1;
102 0           return 1;
103             }
104              
105              
106             ##############################
107             # New - constructor
108             our $new_defaults = {
109             size => [6,4.5,'in'],
110             type=>'i',
111             output=>'',
112             multi=>undef
113             };
114              
115             ## Much of this boilerplate is stolen from PDL::Graphics::Prima::Simple...
116             our $N_windows = 0;
117              
118             sub new {
119 0     0 0   my $class = shift;
120 0           my $opt_in = shift;
121 0 0         $opt_in = {} unless(defined($opt_in));
122 0           my $opt = { iparse($new_defaults, $opt_in) };
123 0 0         unless( check() ) {
124 0 0         die "$mod->{shortname} appears nonfunctional: $mod->{msg}\n" unless(check(1));
125             }
126              
127 0           my $size = PDL::Graphics::Simple::_regularize_size($opt->{size},'px');
128              
129             my $pw = Prima::Window->create( text => $opt->{output} || "PDL/Prima Plot",
130             size => [$size->[0], $size->[1]],
131 0     0     onCreate => sub { $PDL::Graphics::Prima::Simple::N_windows++; },
132 0     0     onDestroy => sub { $PDL::Graphics::Prima::Simple::N_windows--;
133 0 0         PDL::Graphics::Prima::Simple::twiddling(0) if($PDL::Graphics::Prima::Simple::N_windows==0);
134             }
135 0   0       );
136 0 0         die "Couldn't create a Prima window!" unless(defined($pw));
137              
138 0 0         if($opt_in->{type} =~ m/^f/i) {
139 0           $pw->hide;
140             }
141             my $me = { obj => $pw,
142             widgets => [],
143             next_plotno=>0,
144             multi=>$opt_in->{multi},
145             type=>$opt->{type},
146             output=>$opt->{output}
147 0           };
148 0           return bless($me, "PDL::Graphics::Simple::Prima");
149             }
150              
151             sub DESTROY {
152 0     0     my $me = shift;
153 0 0         if($me->{type} =~ m/f/i) {
154             ##############################
155             # File-saving code...
156 0 0         unless( $me->{multi} ) {
157              
158             ##############################
159             # Save plot to file
160              
161 0 0         if($me->{widgets}->[0]) {
162 0           eval {$me->{widgets}->[0]->save_to_file($me->{output})};
  0            
163 0 0         if($@) {
164 0           print $@;
165 0           undef $@;
166             }
167             } else {
168 0           print STDERR "No plot was sent to $me->{output}\n";
169             }
170             } else {
171              
172             ##############################
173             # Multiplot - save the plots individually, then splice them together.
174             # Lame, lame - I think this can be done in memory with Prima.
175             # But it gets us to a place where we are supporting stuff.
176              
177 0 0         if(@{$me->{widgets}} < 1) {
  0            
178 0           print STDERR "No plot was sent to $me->{output}\n";
179             } else {
180 0           print STDERR "WARNING - multiplot support is experimental for the Prima engine\n";
181              
182 0           my ($h,$tmpfile) = tempfile('PDL-Graphics-Simple-XXXX');
183 0           close $h;
184 0           unlink($tmpfile);
185              
186 0           my $suffix;
187 0 0         if($me->{output}=~ s/(\.\w{2,4})$//) {
188 0           $suffix = $1;
189             } else {
190 0           $suffix = ".png";
191             }
192 0           $tmpfile .= $suffix;
193              
194 0           my $widget_dex = 0;
195 0           my $im = undef;
196 0           my $ztile = undef;
197 0           ROW:for my $row(0..$me->{multi}->[1]-1) {
198 0           my $imrow = undef;
199 0           for my $col(0..$me->{multi}->[0]-1) {
200              
201 0           my $tile;
202              
203 0 0         if($widget_dex < @{$me->{widgets}}) {
  0            
204 0           eval { $me->{widgets}->[$widget_dex++]->save_to_file($tmpfile) };
  0            
205 0 0         last ROW if($@);
206 0           $tile = rim($tmpfile);
207 0           $ztile = zeroes($tile)+255;
208 0           unlink($tmpfile);
209             } else {
210             # ztile is always initialized by first run through...
211 0           $tile = $ztile;
212             }
213              
214 0 0         if(!defined($imrow)) {
215 0           $imrow = $tile;
216             } else {
217 0           $imrow = $imrow->glue(0,$tile);
218             }
219             } # end of row loop
220              
221 0 0         if(!defined($im)) {
222 0           $im = $imrow;
223             } else {
224 0           $im = $imrow->glue(1,$im);
225             }
226             }
227 0 0         unless($@) {
228 0           wim($im, $me->{output}.$suffix);
229             } else {
230 0           print STDERR $@;
231 0           undef $@;
232             }
233             }
234             }
235             }
236              
237 0           eval { # in case of global destruction
238 0           $me->{obj}->hide;
239 0           $me->{obj}->destroy;
240             };
241             }
242              
243             ##############################
244             # apply method makes sepiatone values for input data,
245             # to match the style of PDL::Graphics::Prima::Palette,
246             # in order to make the Matrix plot type happy (for 'with=>image').
247             @PDL::Graphics::Simple::Prima::Sepia_Palette::ISA = 'PDL::Graphics::Prima::Palette';
248             sub PDL::Graphics::Simple::Prima::Sepia_Palette::apply {
249 0     0     my $h = shift;
250 0           my $data = shift;
251 0           my ($min, $max) = @$h{qw(min max)};
252 0 0         my $g = ($min==$max)? $data->zeroes : (($data->double - $min)/($max-$min))->clip(0,1);
253 0           my $r = $g->sqrt;
254 0           my $b = $g*$g;
255 0           return (pdl($r,$g,$b)*255.999)->floor->mv(-1,0)->rgb_to_color;
256             }
257              
258              
259             ##############################
260             # Plot types
261             #
262             # This probably needs a little more smarts.
263             # Currently each entry is either a ppair:: return or a sub that implements
264             # the plot type in terms of others.
265             sub _load_types {
266             $types = {
267             lines => 'Lines',
268              
269             points => [ map ppair->can($_)->(), qw/Blobs Triangles Squares Crosses Xs Asterisks/ ],
270              
271             bins => sub {
272 0     0     my ($me, $plot, $block, $cprops) = @_;
273 0           my ($x, $y) = @$block;
274 0           my $x1 = $x->range( [[0],[-1]], [$x->dim(0)], 'e' )->average;
275 0           my $x2 = $x->range( [[1],[0]], [$x->dim(0)], 'e' )->average;
276 0           my $newx = pdl($x1, $x2)->mv(-1,0)->clump(2)->sever;
277 0           my $newy = $y->dummy(0,2)->clump(2)->sever;
278 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } =
  0            
279             ds::Pair($newx,$newy,plotType=>ppair::Lines(), @$cprops);
280             },
281              
282             # as of 1.012, known to not draw all its lines(!) overplotting an image
283             # draws them all without an image in same plot() call, or separate plot()
284             contours => sub {
285 0     0     my ($me, $plot, $block, $cprops) = @_;
286 0           my ($vals, $cvals) = @$block;
287 0           for my $thresh ($cvals->list) {
288 0           my ($pi, $p) = contour_polylines($thresh, $vals, $vals->ndcoords);
289 0 0         next if $pi->at(0) < 0;
290 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } =
291             ds::Pair($_->dog, plotType=>ppair::Lines(), @$cprops)
292 0           for path_segs($pi, $p->mv(0,-1));
293             }
294             },
295              
296             polylines => sub {
297 0     0     my ($me, $plot, $block, $cprops) = @_;
298 0           my ($xy, $pen) = @$block;
299 0           my $pi = $pen->eq(0)->which;
300 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } =
301             ds::Pair($_->dog, plotType=>ppair::Lines(), @$cprops)
302 0           for path_segs($pi, $xy->mv(0,-1));
303             },
304              
305             image => sub {
306 0     0     my ($me, $plot, $data, $cprops, $co, $ipo) = @_;
307 0           my ($xmin, $xmax) = $data->[0]->minmax;
308 0 0         my $dx = 0.5 * ($xmax-$xmin) / ($data->[0]->dim(0) - (($data->[0]->dim(0)==1) ? 0 : 1));
309 0           $xmin -= $dx;
310 0           $xmax += $dx;
311 0           my ($ymin, $ymax) = $data->[1]->minmax;
312 0 0         my $dy = 0.5 * ($ymax-$ymin) / ($data->[0]->dim(1) - (($data->[1]->dim(1)==1) ? 0 : 1));
313 0           $ymin -= $dy;
314 0           $ymax += $dy;
315 0           my $dataset;
316 0           my $imdata = $data->[2];
317 0           my @bounds = (x_bounds=>[ $xmin, $xmax ], y_bounds=>[ $ymin, $ymax ]);
318 0 0         if ($imdata->ndims > 2) {
319 0 0         $imdata = $imdata->mv(-1,0) if $imdata->dim(0) != 3;
320 0           $dataset = ds::Image($imdata, @bounds);
321             } else {
322 0           my $crange = $me->{ipo}{crange};
323 0 0         my ($cmin, $cmax) = defined($crange) ? @$crange : ();
324 0   0       $cmin //= $imdata->min;
325 0   0       $cmax //= $imdata->max;
326 0           my $palette = PDL::Graphics::Simple::Prima::Sepia_Palette->new(
327             min => $cmin, max => $cmax, data => $imdata,
328             );
329             $dataset = ds::Grid($imdata,
330             @bounds,
331 0 0         plotType=>pgrid::Matrix($ipo->{wedge} ? () : (palette => $palette)),
332             );
333 0 0         $plot->color_map($palette) if $ipo->{wedge};
334             }
335 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } = $dataset;
  0            
336             },
337              
338             circles => sub {
339 0     0     my ($me, $plot, $data, $cprops) = @_;
340 0           our $cstash;
341 0 0         unless(defined($cstash)) {
342 0           my $ang = PDL->xvals(362)*3.14159/180;
343 0           $cstash = {c => $ang->cos, s => $ang->sin};
344 0           $cstash->{s}->slice("361") .= $cstash->{c}->slice("361") .= PDL->pdl(1.1)->acos; # NaN
345             }
346 0           my $dr = $data->[2]->flat;
347 0           my $dx = ($data->[0]->flat->dummy(0,1) + $dr->dummy(0,1)*$cstash->{c})->flat;
348 0           my $dy = ($data->[1]->flat->dummy(0,1) + $dr->dummy(0,1)*$cstash->{s})->flat;
349 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } =
  0            
350             ds::Pair( $dx, $dy, plotType=>ppair::Lines(), @$cprops);
351             },
352              
353             labels => sub {
354 0     0     my ($me,$plot,$block,$cprops,$co,$ipo) = @_;
355 0           my ($x, $y) = map $_->flat->copy, @$block[0,1]; # copy as mutate below
356 0           my @labels = @{$block->[2]};
  0            
357 0           my @lrc = ();
358 0           for my $i(0..$x->dim(0)-1) {
359 0           my $j =0;
360 0 0         if($labels[$i] =~ s/^([\<\|\> ])//) {
361 0           my $ch = $1;
362 0 0         if($ch =~ m/[\|\>]/) {
363 0           my $tw = $plot->get_text_width($labels[$i]);
364 0 0         $tw /= 2 if($ch eq '|');
365 0           $x->slice("($i)") .=
366             $plot->x->pixels_to_reals(
367             $plot->x->reals_to_pixels( $x->slice("($i)") ) - $tw
368             );
369             }
370             }
371             }
372 0           $plot->dataSets()->{1+keys(%{$plot->dataSets()})} =
  0            
373             ds::Note(
374             map pnote::Text($labels[$_],x=>$x->slice("($_)"),y=>$y->slice("($_)")), 0..$#labels
375             );
376             },
377              
378             limitbars => sub {
379             # Strategy: make T-errorbars out of the x/y/height data and generate a Line
380             # plot. The T-errorbar width is 4x the LineWidth (+/- 2x).
381 0     0     my ($me, $plot, $block, $cprops, $co, $ipo) = @_;
382 0           my $x = $block->[0]->flat;
383 0           my $y = $block->[1]->flat;
384 0           my $ylo = $block->[2]->flat;
385 0           my $yhi = $block->[3]->flat;
386             # Calculate T bar X ranges
387 0   0       my $of = ($co->{width}||1) * 2;
388 0           my $xp = $plot->x->reals_to_pixels($x);
389 0           my $xlo = $plot->x->pixels_to_reals( $xp - $of );
390 0           my $xhi = $plot->x->pixels_to_reals( $xp + $of );
391 0           my $nan = PDL->new_from_specification($x->dim(0)); $nan .= asin(pdl(1.1));
  0            
392 0           my $xdraw = pdl($xlo,$xhi,$x, $x, $xlo,$xhi,$nan)->mv(1,0)->flat;
393 0           my $ydraw = pdl($ylo,$ylo,$ylo,$yhi,$yhi,$yhi,$nan)->mv(1,0)->flat;
394 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } =
  0            
395             ds::Pair($xdraw,$ydraw,plotType=>ppair::Lines(), @$cprops);
396 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } =
397 0           ds::Pair($x,$y,plotType=>$types->{points}->[ ($me->{curvestyle}-1) %(0+@{$types->{points}}) ], @$cprops);
  0            
398             },
399              
400             errorbars => sub {
401             # Strategy: make T-errorbars out of the x/y/height data and generate a Line
402             # plot. The T-errorbar width is 4x the LineWidth (+/- 2x).
403 0     0     my ($me, $plot, $block, $cprops, $co, $ipo) = @_;
404 0           my $halfwidth = $block->[2]->flat;
405 0           $block->[2] = $block->[1] - $halfwidth;
406 0           $block->[3] = $block->[1] + $halfwidth;
407 0           $types->{limitbars}->($me, $plot, $block, $cprops, $co, $ipo);
408             },
409 0     0     };
410             }
411              
412             ##############################
413             # Plot subroutine
414             #
415             #
416             sub plot {
417 0     0 0   my $me = shift;
418 0           my $ipo = shift;
419              
420 0           $me->{ipo} = $ipo;
421              
422 0 0         if(defined($ipo->{legend})) {
423 0           printf(STDERR "WARNING: Ignoring 'legend' option (Legends not yet supported by PDL::Graphics::Simple::Prima v%s)",$PDL::Graphics::Simple::VERSION);
424             }
425              
426 0           my $plot;
427              
428 0 0 0       if ($ipo->{oplot} and defined($me->{last_plot})) {
429 0           $plot = $me->{last_plot};
430             } else {
431 0           $me->{curvestyle} = 0;
432              
433 0 0         if ($me->{multi}) {
434             # Multiplot - handle logic and plot placement
435              
436             # Advance to the next plot position. Erase the window if necessary.
437 0 0 0       if ($me->{next_plotno} and $me->{next_plotno} >= $me->{multi}->[0] * $me->{multi}->[1]) {
438 0           map {$_->destroy} @{$me->{widgets}};
  0            
  0            
439 0           $me->{widgets} = [];
440 0           $me->{next_plotno} = 0;
441             }
442              
443 0           my $pno = $me->{next_plotno};
444             $plot = $me->{obj}->insert('Plot',
445             place => {
446             relx => ($pno % $me->{multi}->[0])/$me->{multi}->[0],
447             relwidth => 1.0/$me->{multi}->[0],
448             rely => 1.0 - (1 + int($pno / $me->{multi}->[0]))/$me->{multi}->[1],
449 0           relheight => 1.0/$me->{multi}->[1],
450             anchor => 'sw'});
451 0           $plot->titleFont(size => 12);
452              
453 0           $me->{next_plotno}++;
454             } else {
455             # No multiplot - just instantiate a plot (and destroy any widgets from earlier)
456 0           $_->destroy for @{$me->{widgets}};
  0            
457 0           $me->{widgets} = [];
458 0           $plot = $me->{obj}->insert('Plot',
459             pack=>{fill=>'both',expand=>1}
460             );
461 0           $plot->titleFont(size => 14);
462             }
463             }
464              
465 0           push(@{$me->{widgets}}, $plot);
  0            
466 0           $me->{last_plot} = $plot;
467              
468 0           for my $block (@_) {
469 0           my $co = $block->[0];
470 0 0         if ($co->{with} eq 'fits') {
471 0           ($co->{with}, my $new_opts, my $new_img, my @coords) = PDL::Graphics::Simple::_fits_convert($block->[1], $ipo);
472 0           $block = [ $co, @coords, $new_img ];
473 0           @$ipo{keys %$new_opts} = values %$new_opts;
474             }
475             }
476              
477 0 0         if (!$ipo->{oplot}) {
478             ## Set global plot options: titles, axis labels, and ranges.
479 0           $plot->hide;
480 0           $plot->lock;
481 0 0         $plot->title( $ipo->{title} ) if(defined($ipo->{title}));
482 0 0         $plot->x->label( $ipo->{xlabel} ) if(defined($ipo->{xlabel}));
483 0 0         $plot->y->label( $ipo->{ylabel} ) if(defined($ipo->{ylabel}));
484              
485 0 0         $plot->x->scaling(sc::Log()) if($ipo->{logaxis}=~ m/x/i);
486 0 0         $plot->y->scaling(sc::Log()) if($ipo->{logaxis}=~ m/y/i);
487              
488 0 0 0       $plot->x->min($ipo->{xrange}[0]) if(defined($ipo->{xrange}) and defined($ipo->{xrange}[0]));
489 0 0 0       $plot->x->max($ipo->{xrange}[1]) if(defined($ipo->{xrange}) and defined($ipo->{xrange}[1]));
490 0 0 0       $plot->y->min($ipo->{yrange}[0]) if(defined($ipo->{yrange}) and defined($ipo->{yrange}[0]));
491 0 0 0       $plot->y->max($ipo->{yrange}[1]) if(defined($ipo->{yrange}) and defined($ipo->{yrange}[1]));
492              
493             ##############################
494             # I couldn't find a way to scale the plot to make the plot area justified, so
495             # we cheat and adjust the axis values instead.
496             # This is a total hack, but at least it produces justified plots.
497 0 0         if ($ipo->{justify}) {
498 0           my ($dmin,$pmin,$dmax,$pmax,$xscale,$yscale);
499              
500 0           ($dmin,$dmax) = $plot->x->minmax;
501 0           $pmin = $plot->x->reals_to_pixels($dmin);
502 0           $pmax = $plot->x->reals_to_pixels($dmax);
503 0           $xscale = ($pmax-$pmin)/($dmax-$dmin);
504              
505 0           ($dmin,$dmax) = $plot->y->minmax;
506 0           $pmin = $plot->y->reals_to_pixels($dmin);
507 0           $pmax = $plot->y->reals_to_pixels($dmax);
508 0           $yscale = ($pmax-$pmin)/($dmax-$dmin);
509              
510 0           my $ratio = $yscale / $xscale;
511 0 0         if($ratio > 1) {
    0          
512             # More Y pixels per datavalue than X pixels. Hence we expand the Y range.
513 0           my $ycen = ($dmax+$dmin)/2;
514 0           my $yof = ($dmax-$dmin)/2;
515 0           my $new_yof = $yof * $yscale/$xscale;
516 0           $plot->y->min($ycen-$new_yof);
517 0           $plot->y->max($ycen+$new_yof);
518             } elsif($ratio < 1) {
519             # More X pixels per datavalue than Y pixels. Hence we expand the X range.
520 0           ($dmin,$dmax) = $plot->x->minmax;
521 0           my $xcen = ($dmax+$dmin)/2;
522 0           my $xof = ($dmax-$dmin)/2;
523 0           my $new_xof = $xof * $xscale/$yscale;
524 0           $plot->x->min($xcen-$new_xof);
525 0           $plot->x->max($xcen+$new_xof);
526             }
527             }
528             }
529              
530             ##############################
531             # Rubber meets the road -- loop over data blocks and
532             # ship out each curve to the appropriate dispatcher in the $types table
533 0           for my $block (@_) {
534 0           my ($co, @rest) = @$block;
535              
536             # Parse out curve style (for points type selection)
537 0 0         if (defined $co->{style}) {
538 0           $me->{curvestyle} = $co->{style};
539             } else {
540 0           $me->{curvestyle}++;
541             }
542              
543             my $cprops = [
544             color => $colors[ ($me->{curvestyle}-1) % @colors ],
545             linePattern => $patterns[ ($me->{curvestyle}-1) % @patterns ],
546 0   0       lineWidth => $co->{width} || 1
547             ];
548              
549 0           my $with = $co->{with};
550 0           my $type = $types->{$with};
551 0 0         die "$with is not yet implemented in PDL::Graphics::Simple for Prima.\n"
552             if !defined $type;
553 0 0         if ( ref($type) eq 'CODE' ) {
554 0           $type->($me, $plot, \@rest, $cprops, $co, $ipo);
555             } else {
556 0 0         my $pt = ref($type) eq 'ARRAY' ? $type->[ ($me->{curvestyle}-1) % (0+@{$type}) ] : ppair->can($type)->();
  0            
557 0           $plot->dataSets()->{ 1+keys(%{$plot->dataSets()}) } = ds::Pair(@rest, plotType => $pt, @$cprops);
  0            
558             }
559             }
560              
561 0 0         if ($me->{type} !~ m/f/i) {
562 0           $plot->show;
563 0           $plot->unlock;
564             } else {
565             # Belt-and-suspenders to stay hidden
566 0           $plot->hide;
567 0           $me->{obj}->hide;
568             }
569              
570             ##############################
571             # Another lame kludge. Run the event loop for 50 milliseconds, to enable a redraw,
572             # then exit it.
573             Prima::Timer->create(
574 0     0     onTick=>sub{$_[0]->stop; die "done with event loop\n"},
  0            
575 0           timeout=>50
576             )->start;
577 1     1   13 eval { no warnings 'once'; $::application->go };
  1         3  
  1         427  
  0            
  0            
578 0 0         die unless $@ =~ /^done with event loop/;
579 0           undef $@;
580             }
581              
582             1;