File Coverage

plplot.pd
Criterion Covered Total %
statement 380 444 85.5
branch 103 154 66.8
condition 26 37 70.2
subroutine 21 24 87.5
pod 11 16 68.7
total 541 675 80.1


line stmt bran cond sub pod time code
1             # User can set this global variable to 1 if he wants
2             # to use the normal plplot order of arguments, not the PP-required
3             # order for functions with OtherPars.
4             $PDL::Graphics::PLplot::standard_order = 0;
5              
6             pp_addpm({At => Top}, <<'EOD');
7 32     32   274  
  32         82  
  32         2764  
8             use Carp qw(confess);
9              
10             our $VERSION;
11 32     32   301906 BEGIN {
12             $VERSION = '0.84';
13             };
14              
15             =head1 NAME
16              
17             PDL::Graphics::PLplot - Object-oriented interface from perl/PDL to the PLPLOT plotting library
18              
19             =head1 SYNOPSIS
20              
21             use PDL;
22             use PDL::Graphics::PLplot;
23              
24             my $pl = PDL::Graphics::PLplot->new (DEV => "png", FILE => "test.png");
25             my $x = sequence(10);
26             my $y = $x**2;
27             $pl->xyplot($x, $y);
28             $pl->close;
29              
30             Only version 5.15.0+ of PLplot is fully supported, due to a C-level API change
31             that is invisible at PDL-level. However, the library does support installation
32             with PLplot 5.13.0+.
33              
34             For more information on PLplot, see
35              
36             http://www.plplot.org/
37              
38             Also see the test file, F in this distribution for some working examples.
39              
40             =head1 LONG NAMES
41              
42             If you are annoyed by the long constructor call, consider installing the
43             L CPAN package. Using C, the above example
44             becomes
45              
46             use PDL;
47             use aliased 'PDL::Graphics::PLplot';
48              
49             my $pl = PLplot->new (DEV => "png", FILE => "test.png");
50             my $x = sequence(10);
51             # etc, as above
52              
53             =head1 DESCRIPTION
54              
55             This is the PDL interface to the PLplot graphics library. It provides
56             a familiar 'perlish' Object Oriented interface as well as access to
57             the low-level PLplot commands from the C-API.
58              
59             =head1 OPTIONS
60              
61             The following options are supported. Most options can be used
62             with any function. A few are only supported on the call to 'new'.
63              
64             =head2 Options used upon creation of a PLplot object (with 'new'):
65              
66             =head3 BACKGROUND
67              
68             Set the color for index 0, the plot background
69              
70             =head3 DEV
71              
72             Set the output device type. To see a list of allowed types, try:
73              
74             PDL::Graphics::PLplot->new();
75              
76             =for example
77              
78             PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png');
79              
80             =head3 FILE
81              
82             Set the output file or display. For file output devices, sets
83             the output file name. For graphical displays (like C<'xwin'>) sets
84             the name of the display, eg (C<'hostname.foobar.com:0'>)
85              
86             =for example
87              
88             PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png');
89             PDL::Graphics::PLplot->new(DEV => 'xwin', FILE => ':0');
90              
91             =head3 OPTS
92              
93             Set plotting options. See the PLplot documentation for the complete
94             listing of available options. The value of C<'OPTS'> must be a hash
95             reference, whose keys are the names of the options. For instance, to obtain
96             PostScript fonts with the ps output device, use:
97              
98             =for example
99              
100             PDL::Graphics::PLplot->new(DEV => 'ps', OPTS => {drvopt => 'text=1'});
101              
102             =head3 MEM
103              
104             This option is used in conjunction with C<< DEV => 'mem' >>. This option
105             takes as input a PDL image and allows one to 'decorate' it using PLplot.
106             The 'decorated' PDL image can then be written to an image file using,
107             for example, L. This option may not be available if
108             plplot does not include the 'mem' driver.
109              
110             =for example
111              
112             # read in Earth image and draw an equator.
113             my $pl = PDL::Graphics::PLplot->new (MEM => $earth, DEV => 'mem');
114             my $x = pdl(-180, 180);
115             my $y = zeroes(2);
116             $pl->xyplot($x, $y,
117             BOX => [-180,180,-90,90],
118             VIEWPORT => [0.0, 1.0, 0.0, 1.0],
119             XBOX => '', YBOX => '',
120             PLOTTYPE => 'LINE');
121             $pl->close;
122              
123             =head3 FRAMECOLOR
124              
125             Set color index 1, the frame color
126              
127             =head3 JUST
128              
129             A flag used to specify equal scale on the axes. If this is
130             not specified, the default is to scale the axes to fit best on
131             the page.
132              
133             =for example
134              
135             PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png', JUST => 1);
136              
137             =head3 ORIENTATION
138              
139             The orientation of the plot:
140              
141             0 -- 0 degrees (landscape mode)
142             1 -- 90 degrees (portrait mode)
143             2 -- 180 degrees (seascape mode)
144             3 -- 270 degrees (upside-down mode)
145              
146             Intermediate values (0.2) are acceptable if you are feeling daring.
147              
148             =for example
149              
150             # portrait orientation
151             PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png', ORIENTATION => 1);
152              
153             =head3 PAGESIZE
154              
155             Set the size in pixels of the output page.
156              
157             =for example
158              
159             # PNG 500 by 600 pixels
160             PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png', PAGESIZE => [500,600]);
161              
162             =head3 SUBPAGES
163              
164             Set the number of sub pages in the plot, [$nx, $ny]
165              
166             =for example
167              
168             # PNG 300 by 600 pixels
169             # Two subpages stacked on top of one another.
170             PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png', PAGESIZE => [300,600],
171             SUBPAGES => [1,2]);
172              
173             =head2 Options used after initialization (after 'new')
174              
175             =head3 BOX
176              
177             Set the plotting box in world coordinates. Used to explicitly
178             set the size of the plotting area.
179              
180             =for example
181              
182             my $pl = PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png');
183             $pl->xyplot ($x, $y, BOX => [0,100,0,200]);
184              
185             =head3 CHARSIZE
186              
187             Set the size of text in multiples of the default size.
188             C<< CHARSIZE => 1.5 >> gives characters 1.5 times the normal size.
189              
190             =head3 COLOR
191              
192             Set the current color for plotting and character drawing.
193             Colors are specified not as color indices but as RGB triples.
194             Some pre-defined triples are included:
195              
196             BLACK GREEN WHEAT BLUE
197             RED AQUAMARINE GREY BLUEVIOLET
198             YELLOW PINK BROWN CYAN
199             TURQUOISE MAGENTA SALMON WHITE
200             ROYALBLUE DEEPSKYBLUE VIOLET STEELBLUE1
201             DEEPPINK MAGENTA DARKORCHID1 PALEVIOLETRED2
202             TURQUOISE1 LIGHTSEAGREEN SKYBLUE FORESTGREEN
203             CHARTREUSE3 GOLD2 SIENNA1 CORAL
204             HOTPINK LIGHTCORAL LIGHTPINK1 LIGHTGOLDENROD
205              
206             =for example
207              
208             # These two are equivalent:
209             $pl->xyplot ($x, $y, COLOR => 'YELLOW');
210             $pl->xyplot ($x, $y, COLOR => [0,255,0]);
211              
212             =head3 CONTOURLABELS
213              
214             Control of labels for contour plots.
215              
216             Must either be 0 (turn off contour labels), 1 (turn on default contour labels)
217             or a five element array:
218              
219             offset: Offset of label from contour line (if set to 0.0, labels are printed on the lines). Default value is 0.006.
220             size: Font height for contour labels (normalized). Default value is 0.3.
221             spacing: Spacing parameter for contour labels. Default value is 0.1.
222             lexp: If the contour numerical label is greater than 10^(lexp) or less than 10^(-lexp),
223             then the exponential format is used. Default value of lexp is 4.
224             sigdig: Number of significant digits. Default value is 2";
225              
226             =for example
227              
228             $pl->shadeplot ($z, $nsteps, BOX => [-1, 1, -1, 1], PLOTTYPE => 'CONTOUR', CONTOURLABELS => [0.004, 0.2, 0.2, 4, 2]);
229             $pl->shadeplot ($z, $nsteps, BOX => [-1, 1, -1, 1], PLOTTYPE => 'CONTOUR', CONTOURLABELS => 0); # turn off labels
230             $pl->shadeplot ($z, $nsteps, BOX => [-1, 1, -1, 1], PLOTTYPE => 'CONTOUR', CONTOURLABELS => 1); # use default labels
231              
232             =head3 GRIDMAP
233              
234             Set a user-defined grid map. This is an X and Y vector that
235             tells what are the world coordinates for each pixel in $z
236             It is used in 'shadeplot' for non-standard mappings between the
237             input 2D surface to plot and the world coordinates. For example
238             if your surface does not completely fill up the plotting window.
239              
240             =for example
241              
242             my $z = $surface; # 2D PDL to plot (generated elsewhere)
243             my $nlevels = 20;
244             my ($nx, $ny) = $z->dims;
245             my @zbounds = ($minx, $maxx, $miny, $maxy);
246              
247             # Map X coords linearly to X range, Y coords linearly to Y range
248             my $xmap = ((sequence($nx)*(($zbounds[1] - $zbounds[0])/($nx - 1))) + $zbounds[0]);
249             my $ymap = ((sequence($ny)*(($zbounds[3] - $zbounds[2])/($ny - 1))) + $zbounds[2]);
250             $pl->shadeplot ($z, $nlevels, PALETTE => 'GREENRED', GRIDMAP => [$xmap, $ymap]);
251              
252             =head3 GRIDMAP2
253              
254             Set a user-defined two dimensional grid map. These are 2D X and Y matrices that
255             tell what are the world coordinates for each pixel in $z
256             It is used in 'shadeplot' for non-standard mappings between the
257             input 2D surface to plot and the world coordinates, for example
258             irregular grids like polar projections.
259              
260             =for example
261              
262             my $r_pts = 40;
263             my $theta_pts = 40;
264             my $pi = 4*atan2(1,1);
265             my $nlevels = 20;
266              
267             my $r = ((sequence ($r_pts)) / ($r_pts - 1))->dummy (1, $theta_pts);
268             my $z = $r; # or any other 2D surface to plot...
269             my $theta = ((2 * $pi / ($theta_pts - 2)) * sequence ($theta_pts))->dummy (0, $r_pts);
270             my $xmap = $r * cos ($theta);
271             my $ymap = $r * sin ($theta);
272              
273             $pl->shadeplot ($z, $nlevels, PLOTTYPE => 'CONTOUR',
274             JUST => 1,
275             BOX => [-1,1,-1,1],
276             PALETTE => 'GREENRED',
277             GRIDMAP2 => [$xmap, $ymap]);
278              
279             =head3 LINEWIDTH
280              
281             Set the line width for plotting. Values range from 1 to a device dependent maximum.
282              
283             =head3 LINESTYLE
284              
285             Set the line style for plotting. Pre-defined line styles use values 1 to 8, one being
286             a solid line, 2-8 being various dashed patterns.
287              
288             =head3 MAJTICKSIZE
289              
290             Set the length of major ticks as a fraction of the default setting.
291             One (default) means leave these ticks the normal size.
292              
293             =head3 MINTICKSIZE
294              
295             Set the length of minor ticks (and error bar terminals) as a fraction of the default setting.
296             One (default) means leave these ticks the normal size.
297              
298             =head3 NXSUB
299              
300             The number of minor tick marks between each major tick mark on the X axis.
301             Specify zero (default) to let PLplot compute this automatically.
302              
303             =head3 NYSUB
304              
305             The number of minor tick marks between each major tick mark on the Y axis.
306             Specify zero (default) to let PLplot compute this automatically.
307              
308             =head3 PALETTE
309              
310             Load pre-defined color map 1 color ranges. Currently, values include:
311              
312             RAINBOW -- from Red to Violet through the spectrum
313             REVERSERAINBOW -- Violet through Red
314             GREYSCALE -- from black to white via grey.
315             REVERSEGREYSCALE -- from white to black via grey.
316             GREENRED -- from green to red
317             REDGREEN -- from red to green
318              
319             =for example
320              
321             # Plot x/y points with the z axis in color
322             $pl->xyplot ($x, $y, PALETTE => 'RAINBOW', PLOTTYPE => 'POINTS', COLORMAP => $z);
323              
324             =head3 PLOTTYPE
325              
326             Specify which type of XY or shade plot is desired:
327              
328             LINE -- A line
329             POINTS -- A bunch of symbols
330             LINEPOINTS -- both
331              
332             or, for 'shadeplot':
333             CONTOUR -- A contour plot of 2D data
334             SHADE -- A shade plot of 2D data
335              
336             =head3 STACKED_BAR_COLORS
337              
338             For 'bargraph', request a stacked bar chart.
339             Must contain a reference to a perl list of color names or RGB triples.
340              
341             =for example
342              
343             # $labels is a reference to a perl array with N x-axis labels
344             # $values is an NxM PDL where M is the number of stacked bars (in this case 2,
345             # since STACKED_BAR_COLORS contains two colors).
346             $pl->bargraph($labels, $values, STACKED_BAR_COLORS => ['GREEN', [128,0,55]);
347              
348             =head3 SUBPAGE
349              
350             Set which subpage to plot on. Subpages are numbered 1 to N.
351             A zero can be specified meaning 'advance to the next subpage' (just a call to
352             L).
353              
354             =for example
355              
356             my $pl = PDL::Graphics::PLplot->new(DEV => 'png',
357             FILE => 'test.png',
358             SUBPAGES => [1,2]);
359             $pl->xyplot ($x, $y, SUBPAGE => 1);
360             $pl->xyplot ($a, $b, SUBPAGE => 2);
361              
362              
363             =head3 SYMBOL
364              
365             Specify which symbol to use when plotting C<< PLOTTYPE => 'POINTS' >>.
366             A large variety of symbols are available, see:
367             http://plplot.sourceforge.net/examples-data/demo07/x07.*.png, where * is 01 - 17.
368             You are most likely to find good plotting symbols in the 800s:
369             http://plplot.sourceforge.net/examples-data/demo07/x07.06.png
370              
371             =head3 SYMBOLSIZE
372              
373             Specify the size of symbols plotted in multiples of the default size (1).
374             Value are real numbers from 0 to large.
375              
376             =head3 TEXTPOSITION
377              
378             Specify the placement of text. Either relative to border, specified as:
379              
380             [$side, $disp, $pos, $just]
381              
382             Where
383              
384             side = 't', 'b', 'l', or 'r' for top, bottom, left and right
385             disp is the number of character heights out from the edge
386             pos is the position along the edge of the viewport, from 0 to 1.
387             just tells where the reference point of the string is: 0 = left, 1 = right, 0.5 = center.
388              
389             or inside the plot window, specified as:
390              
391             [$x, $y, $dx, $dy, $just]
392              
393             Where
394              
395             x = x coordinate of reference point of string.
396             y = y coordinate of reference point of string.
397             dx Together with dy, this specifies the inclination of the string.
398             The baseline of the string is parallel to a line joining (x, y) to (x+dx, y+dy).
399             dy Together with dx, this specifies the inclination of the string.
400             just Specifies the position of the string relative to its reference point.
401             If just=0, the reference point is at the left and if just=1,
402             it is at the right of the string. Other values of just give
403             intermediate justifications.
404              
405             =for example
406              
407             # Plot text on top of plot
408             $pl->text ("Top label", TEXTPOSITION => ['t', 4.0, 0.5, 0.5]);
409              
410             # Plot text in plotting area
411             $pl->text ("Line label", TEXTPOSITION => [50, 60, 5, 5, 0.5]);
412              
413             =head3 TITLE
414              
415             Add a title on top of a plot.
416              
417             =for example
418              
419             # Plot text on top of plot
420             $pl->xyplot ($x, $y, TITLE => 'X vs. Y');
421              
422             =head3 UNFILLED_BARS
423              
424             For 'bargraph', if set to true then plot the bars as outlines
425             in the current color and not as filled boxes
426              
427             =for example
428              
429             # Plot text on top of plot
430             $pl->bargraph($labels, $values, UNFILLED_BARS => 1);
431              
432             =head3 VIEWPORT
433              
434             Set the location of the plotting window on the page.
435             Takes a four element array ref specifying:
436              
437             xmin -- The coordinate of the left-hand edge of the viewport. (0 to 1)
438             xmax -- The coordinate of the right-hand edge of the viewport. (0 to 1)
439             ymin -- The coordinate of the bottom edge of the viewport. (0 to 1)
440             ymax -- The coordinate of the top edge of the viewport. (0 to 1)
441              
442             You will need to use this to make color keys or insets.
443              
444             =for example
445              
446             # Make a small plotting window in the lower left of the page
447             $pl->xyplot ($x, $y, VIEWPORT => [0.1, 0.5, 0.1, 0.5]);
448              
449             # Also useful in creating color keys:
450             $pl->xyplot ($x, $y, PALETTE => 'RAINBOW', PLOTTYPE => 'POINTS', COLORMAP => $z);
451             $pl->colorkey ($z, 'v', VIEWPORT => [0.93, 0.96, 0.15, 0.85]);
452              
453             # Plot an inset; first the primary data and then the inset. In this
454             # case, the inset contains a selection of the orignal data
455             $pl->xyplot ($x, $y);
456             $pl->xyplot (where($x, $y, $x < 1.2), VIEWPORT => [0.7, 0.9, 0.6, 0.8]);
457              
458             =head3 XBOX
459              
460             Specify how to label the X axis of the plot as a string of option letters:
461              
462             a: Draws axis, X-axis is horizontal line (y=0), and Y-axis is vertical line (x=0).
463             b: Draws bottom (X) or left (Y) edge of frame.
464             c: Draws top (X) or right (Y) edge of frame.
465             d: Plot labels as date / time. Values are assumed to be seconds since the epoch (as used by gmtime).
466             f: Always use fixed point numeric labels.
467             g: Draws a grid at the major tick interval.
468             h: Draws a grid at the minor tick interval.
469             i: Inverts tick marks, so they are drawn outwards, rather than inwards.
470             l: Labels axis logarithmically. This only affects the labels, not the data,
471             and so it is necessary to compute the logarithms of data points before
472             passing them to any of the drawing routines.
473             m: Writes numeric labels at major tick intervals in the
474             unconventional location (above box for X, right of box for Y).
475             n: Writes numeric labels at major tick intervals in the conventional location
476             (below box for X, left of box for Y).
477             s: Enables subticks between major ticks, only valid if t is also specified.
478             t: Draws major ticks.
479              
480             The default is C<'BCNST'> which draws lines around the plot, draws major and minor
481             ticks and labels major ticks.
482              
483             =for example
484              
485             # plot two lines in a box with independent X axes labeled
486             # differently on top and bottom
487             $pl->xyplot($x1, $y, XBOX => 'bnst', # bottom line, bottom numbers, ticks, subticks
488             YBOX => 'bnst'); # left line, left numbers, ticks, subticks
489             $pl->xyplot($x2, $y, XBOX => 'cmst', # top line, top numbers, ticks, subticks
490             YBOX => 'cst', # right line, ticks, subticks
491             BOX => [$x2->minmax, $y->minmax]);
492              
493             =head3 XERRORBAR
494              
495             Used only with L. Draws horizontal error bars at all points (C<$x>, C<$y>) in the plot.
496             Specify a PDL containing the same number of points as C<$x> and C<$y>
497             which specifies the width of the error bar, which will be centered at (C<$x>, C<$y>).
498              
499             =head3 XLAB
500              
501             Specify a label for the X axis.
502              
503             =head3 XTICK
504              
505             Interval (in graph units/world coordinates) between major x axis tick marks.
506             Specify zero (default) to allow PLplot to compute this automatically.
507              
508             =head3 YBOX
509              
510             Specify how to label the Y axis of the plot as a string of option letters.
511             See L.
512              
513             =head3 YERRORBAR
514              
515             Used only for xyplot. Draws vertical error bars at all points (C<$x>, C<$y>) in the plot.
516             Specify a PDL containing the same number of points as C<$x> and C<$y>
517             which specifies the width of the error bar, which will be centered at (C<$x>, C<$y>).
518              
519             =head3 YLAB
520              
521             Specify a label for the Y axis.
522              
523             =head3 YTICK
524              
525             Interval (in graph units/world coordinates) between major y axis tick marks.
526             Specify zero (default) to allow PLplot to compute this automatically.
527              
528             =head3 ZRANGE
529              
530             For L (when C is specified), for
531             L and for L.
532             Normally, the range of the Z variable (color) is taken as
533             C<< $z->minmax >>. If a different range is desired,
534             specify it in C, like so:
535              
536             $pl->shadeplot ($z, $nlevels, PALETTE => 'GREENRED', ZRANGE => [0,100]);
537              
538             or
539              
540             $pl->xyplot ($x, $y, PALETTE => 'RAINBOW', PLOTTYPE => 'POINTS',
541             COLORMAP => $z, ZRANGE => [-90,-20]);
542             $pl->colorkey ($z, 'v', VIEWPORT => [0.93, 0.96, 0.13, 0.85],
543             ZRANGE => [-90,-20]);
544              
545             =head1 METHODS
546              
547             These are the high-level, object oriented methods for PLplot.
548              
549             =head2 new
550              
551             =for ref
552              
553             Create an object representing a plot.
554              
555             =for usage
556              
557             Arguments:
558             none.
559              
560             Supported options:
561             BACKGROUND
562             DEV
563             FILE
564             FRAMECOLOR
565             JUST
566             PAGESIZE
567             SUBPAGES
568              
569             =for example
570              
571             my $pl = PDL::Graphics::PLplot->new(DEV => 'png', FILE => 'test.png');
572              
573              
574             =head2 setparm
575              
576             =for ref
577              
578             Set options for a plot object.
579              
580             =for usage
581              
582             Arguments:
583             none.
584              
585             Supported options:
586             All options except:
587              
588             BACKGROUND
589             DEV
590             FILE
591             FRAMECOLOR
592             JUST
593             PAGESIZE
594             SUBPAGES
595              
596             (These must be set in call to 'new'.)
597              
598             =for example
599              
600             $pl->setparm (TEXTSIZE => 2);
601              
602             =head2 xyplot
603              
604             =for ref
605              
606             Plot XY lines and/or points. Also supports color scales for points.
607             This function works with bad values. If a bad value is specified for
608             a points plot, it is omitted. If a bad value is specified for a line
609             plot, the bad value makes a gap in the line. This is useful for
610             drawing maps; for example C<$x> and C<$y> can be the continent boundary
611             latitude and longitude.
612              
613             =for usage
614              
615             Arguments:
616             $x, $y
617              
618             Supported options:
619             All options except:
620              
621             BACKGROUND
622             DEV
623             FILE
624             FRAMECOLOR
625             JUST
626             PAGESIZE
627             SUBPAGES
628              
629             (These must be set in call to 'new'.)
630              
631             =for example
632              
633             $pl->xyplot($x, $y, PLOTTYPE => 'POINTS', COLOR => 'BLUEVIOLET', SYMBOL => 1, SYMBOLSIZE => 4);
634             $pl->xyplot($x, $y, PLOTTYPE => 'LINEPOINTS', COLOR => [50,230,30]);
635             $pl->xyplot($x, $y, PALETTE => 'RAINBOW', PLOTTYPE => 'POINTS', COLORMAP => $z);
636              
637             =head2 stripplots
638              
639             =for ref
640              
641             Plot a set of strip plots with a common X axis, but with different Y axes.
642             Looks like a stack of long, thin XY plots, all line up on the same X axis.
643              
644             =for usage
645              
646             Arguments:
647             $xs -- 1D PDL with common X axis values, length = N
648             $ys -- reference to a list of 1D PDLs with Y-axis values, length = N
649             or 2D PDL with N x M elements
650             -- OR --
651             $xs -- reference to a list of 1D PDLs with X-axis values
652             $ys -- reference to a list of 1D PDLs with Y-axis values
653             %opts -- Options hash
654              
655             Supported options:
656             All options except:
657              
658             BACKGROUND
659             DEV
660             FILE
661             FRAMECOLOR
662             JUST
663             PAGESIZE
664             SUBPAGES
665              
666             (These must be set in call to 'new'.)
667              
668             =for example
669              
670             my $x = sequence(20);
671             my $y1 = $x**2;
672             my $y2 = sqrt($x);
673             my $y3 = $x**3;
674             my $y4 = sin(($x/20) * 2 * $pi);
675             $ys = cat($y1, $y2, $y3, $y4);
676             $pl->stripplots($x, $ys, PLOTTYPE => 'LINE', TITLE => 'functions',
677             YLAB => ['x**2', 'sqrt(x)', 'x**3', 'sin(x/20*2pi)'],
678             COLOR => ['GREEN', 'DEEPSKYBLUE', 'DARKORCHID1', 'DEEPPINK'], XLAB => 'X label');
679             # Equivalent to above:
680             $pl->stripplots($x, [$y1, $y2, $y3, $y4],
681             PLOTTYPE => 'LINE', TITLE => 'functions',
682             YLAB => ['x**2', 'sqrt(x)', 'x**3', 'sin(x/20*2pi)'],
683             COLOR => ['GREEN', 'DEEPSKYBLUE', 'DARKORCHID1', 'DEEPPINK'], XLAB => 'X label');
684              
685             # Here's something a bit different. Notice that different xs have
686             # different lengths.
687             $x1 = sequence(20);
688             $y1 = $x1**2;
689              
690             $x2 = sequence(18);
691             $y2 = sqrt($x2);
692              
693             $x3 = sequence(24);
694             $y3 = $x3**3;
695              
696             my $x4 = sequence(27);
697             $a = ($x4/20) * 2 * $pi;
698             my $y4 = sin($a);
699              
700             $xs = [$x1, $x2, $x3, $x4];
701             $ys = [$y1, $y2, $y3, $y4];
702             $pl->stripplots($xs, $ys, PLOTTYPE => 'LINE', TITLE => 'functions',
703             YLAB => ['x**2', 'sqrt(x)', 'x**3', 'sin(x/20*2pi)'],
704             COLOR => ['GREEN', 'DEEPSKYBLUE', 'DARKORCHID1', 'DEEPPINK'], XLAB => 'X label');
705              
706             In addition, COLOR may be specified as a reference to a list of colors. If
707             this is done, the colors are applied separately to each plot.
708              
709             Also, the options Y_BASE and Y_GUTTER can be specified. Y_BASE gives the Y offset
710             of the bottom of the lowest plot (0-1, specified like a VIEWPORT, defaults to 0.1) and Y_GUTTER
711             gives the gap between the graphs (0-1, default = 0.02).
712              
713             =head2 colorkey
714              
715             =for ref
716              
717             Plot a color key showing which color represents which value
718              
719             =for usage
720              
721             Arguments:
722             $range : A PDL which tells the range of the color values
723             $orientation : 'v' for vertical color key, 'h' for horizontal
724              
725             Supported options:
726             All options except:
727              
728             BACKGROUND
729             DEV
730             FILE
731             FRAMECOLOR
732             JUST
733             PAGESIZE
734             SUBPAGES
735              
736             (These must be set in call to 'new'.)
737              
738             =for example
739              
740             # Plot X vs. Y with Z shown by the color. Then plot
741             # vertical key to the right of the original plot.
742             $pl->xyplot ($x, $y, PALETTE => 'RAINBOW', PLOTTYPE => 'POINTS', COLORMAP => $z);
743             $pl->colorkey ($z, 'v', VIEWPORT => [0.93, 0.96, 0.15, 0.85]);
744              
745              
746             =head2 shadeplot
747              
748             =for ref
749              
750             Create a shaded contour plot of 2D PDL 'z' with 'nsteps' contour levels.
751             Linear scaling is used to map the coordinates of Z(X, Y) to world coordinates
752             via the L option.
753              
754             =for usage
755              
756             Arguments:
757             $z : A 2D PDL which contains surface values at each XY coordinate.
758             $nsteps : The number of contour levels requested for the plot.
759              
760             Supported options:
761             All options except:
762              
763             BACKGROUND
764             DEV
765             FILE
766             FRAMECOLOR
767             JUST
768             PAGESIZE
769             SUBPAGES
770              
771             (These must be set in call to 'new'.)
772              
773             =for example
774              
775             # vertical key to the right of the original plot.
776             # The BOX must be specified to give real coordinate values to the $z array.
777             $pl->shadeplot ($z, $nsteps, BOX => [-1, 1, -1, 1], PALETTE => 'RAINBOW', ZRANGE => [0,100]);
778             $pl->colorkey ($z, 'v', VIEWPORT => [0.93, 0.96, 0.15, 0.85], ZRANGE => [0,100]);
779              
780             =head2 histogram
781              
782             =for ref
783              
784             Create a histogram of a 1-D variable.
785              
786             =for usage
787              
788             Arguments:
789             $x : A 1D PDL
790             $nbins : The number of bins to use in the histogram.
791              
792             Supported options:
793             All options except:
794              
795             BACKGROUND
796             DEV
797             FILE
798             FRAMECOLOR
799             JUST
800             PAGESIZE
801             SUBPAGES
802              
803             (These must be set in call to 'new'.)
804              
805             =for example
806              
807             $pl->histogram ($x, $nbins, BOX => [$min, $max, 0, 100]);
808              
809             =head2 histogram1
810              
811             =for ref
812              
813             Create a histogram of a 1-D variable. This alternative to 'histogram'
814             creates filled boxes and also handles Y-axis scaling better.
815              
816             =for usage
817              
818             Arguments:
819             $x : A 1D PDL
820             $nbins : The number of bins to use in the histogram.
821              
822             Supported options:
823             All options except:
824              
825             BACKGROUND
826             DEV
827             FILE
828             FRAMECOLOR
829             JUST
830             PAGESIZE
831             SUBPAGES
832              
833             (These must be set in call to 'new'.)
834              
835             =for example
836              
837             $pl->histogram1 ($x, $nbins, COLOR => 'GREEN');
838              
839             =head2 bargraph
840              
841             =for ref
842              
843             Simple utility to plot a bar chart with labels on the X axis.
844             The usual options can be specified, plus one other: MAXBARLABELS
845             specifies the maximum number of labels to allow on the X axis.
846             The default is 20. If this value is exceeded, then every other
847             label is plotted. If twice MAXBARLABELS is exceeded, then only
848             every third label is printed, and so on.
849              
850             if UNFILLED_BARS is set to true, then plot the bars as outlines
851             and not as filled rectangles.
852              
853             A stacked bar graph can be created if the STACKED_BAR_COLORS
854             option is set. The option takes a reference to a perl list of
855             color names or RGB triplets. If this option is set, then $x should
856             not be a 1-D PDL of N bar heights, but a 2D PDL of NxM where N is the
857             number of bars and M is the number of colors in STACKED_BAR_COLORS.
858              
859             =for usage
860              
861             Arguments:
862             $labels -- A reference to a perl list of strings.
863             $values -- A PDL of values to be plotted.
864              
865             Supported options:
866             All options except:
867              
868             BACKGROUND
869             DEV
870             FILE
871             FRAMECOLOR
872             JUST
873             PAGESIZE
874             SUBPAGES
875              
876             (These must be set in call to 'new'.)
877              
878             =for example
879              
880             $labels = ['one', 'two', 'three'];
881             $values = pdl(1, 2, 3);
882              
883             # Note if TEXTPOSITION is specified, it must be in 4 argument mode (border mode):
884             # [$side, $disp, $pos, $just]
885             #
886             # Where side = 't', 'b', 'l', or 'r' for top, bottom, left and right
887             # 'tv', 'bv', 'lv' or 'rv' for top, bottom, left or right perpendicular to the axis.
888             #
889             # disp is the number of character heights out from the edge
890             # pos is the position along the edge of the viewport, from 0 to 1.
891             # just tells where the reference point of the string is: 0 = left, 1 = right, 0.5 = center.
892             #
893             # The '$pos' entry will be ignored (computed by the bargraph routine)
894             $pl->bargraph($labels, $values, MAXBARLABELS => 30, TEXTPOSITION => ['bv', 0.5, 1.0, 1.0]);
895              
896             # A stacked bar chart:
897             $labels = ['label1', 'label2', 'label3'];
898             $values = pdl([[50,40,60], # green bars
899             [20,10,30]]); # purple ([128, 0, 56]) bars
900             $pl->bargraph ($labels, $values, STACKED_BAR_COLORS => ['GREEN', [128, 0, 56]])
901              
902             =head2 text
903              
904             =for ref
905              
906             Write text on a plot. Text can either be written
907             with respect to the borders or at an arbitrary location and angle
908             (see the L entry).
909              
910             =for usage
911              
912             Arguments:
913             $t : The text.
914              
915             Supported options:
916             All options except:
917              
918             BACKGROUND
919             DEV
920             FILE
921             FRAMECOLOR
922             JUST
923             PAGESIZE
924             SUBPAGES
925              
926             (These must be set in call to 'new'.)
927              
928             =for example
929              
930             $pl->text("Count", COLOR => 'PINK',
931             TEXTPOSITION => ['t', 3, 0.5, 0.5]); # top, 3 units out, string ref. pt in
932             # center of string, middle of axis
933              
934             =head2 close
935              
936             =for ref
937              
938             Close a PLplot object, writing out the file and cleaning up.
939              
940             =for usage
941              
942             Arguments:
943             None
944              
945             Returns:
946             Nothing
947              
948             This closing of the PLplot object can be done explicitly though the
949             'close' method. Alternatively, a DESTROY block does an automatic
950             close whenever the PLplot object passes out of scope.
951              
952             =for example
953              
954             $pl->close;
955              
956 640     640 0 1394 =cut
  1920         4515  
957              
958             # Colors (from rgb.txt) are stored as RGB triples
959             # with each value from 0-255
960             sub cc2t { [map {hex} split ' ', shift] }
961             our %_constants = (
962             BLACK => [ 0, 0, 0],
963             RED => [240, 50, 50],
964             YELLOW => [255,255, 0],
965             GREEN => [ 0,255, 0],
966             AQUAMARINE => [127,255,212],
967             PINK => [255,192,203],
968             WHEAT => [245,222,179],
969             GREY => [190,190,190],
970             BROWN => [165, 42, 42],
971             BLUE => [ 0, 0,255],
972             BLUEVIOLET => [138, 43,226],
973             CYAN => [ 0,255,255],
974             TURQUOISE => [ 64,224,208],
975             MAGENTA => [255, 0,255],
976             SALMON => [250,128,114],
977             WHITE => [255,255,255],
978             ROYALBLUE => cc2t('2B 60 DE'),
979             DEEPSKYBLUE => cc2t('3B B9 FF'),
980             VIOLET => cc2t('8D 38 C9'),
981             STEELBLUE1 => cc2t('5C B3 FF'),
982             DEEPPINK => cc2t('F5 28 87'),
983             MAGENTA => cc2t('FF 00 FF'),
984             DARKORCHID1 => cc2t('B0 41 FF'),
985             PALEVIOLETRED2 => cc2t('E5 6E 94'),
986             TURQUOISE1 => cc2t('52 F3 FF'),
987             LIGHTSEAGREEN => cc2t('3E A9 9F'),
988             SKYBLUE => cc2t('66 98 FF'),
989             FORESTGREEN => cc2t('4E 92 58'),
990             CHARTREUSE3 => cc2t('6C C4 17'),
991             GOLD2 => cc2t('EA C1 17'),
992             SIENNA1 => cc2t('F8 74 31'),
993             CORAL => cc2t('F7 65 41'),
994             HOTPINK => cc2t('F6 60 AB'),
995             LIGHTCORAL => cc2t('E7 74 71'),
996             LIGHTPINK1 => cc2t('F9 A7 B0'),
997             LIGHTGOLDENROD => cc2t('EC D8 72'),
998             );
999              
1000             # a hash of subroutines to invoke when certain keywords are specified
1001             # These are called with arg(0) = $self (the plot object)
1002             # and arg(1) = value specified for keyword
1003             our %_actions =
1004             (
1005              
1006              
1007             # Set color for index 0, the plot background
1008             BACKGROUND => sub {
1009             my $self = shift;
1010             my $color = _color(shift);
1011             $self->{COLORS}[0] = $color;
1012             plscolbg (@$color);
1013             },
1014              
1015             # set plotting box in world coordinates
1016             BOX => sub {
1017             my $self = shift;
1018             my $box = shift;
1019             die "Box must be a ref to a four element array" unless (ref($box) =~ /ARRAY/ and @$box == 4);
1020             $self->{BOX} = $box;
1021             },
1022              
1023             CHARSIZE => sub { my $self = shift;
1024             $self->{CHARSIZE} = $_[0];
1025             plschr (0, $self->{CHARSIZE}) unless ($self->{ISNEW}); # do not call plsch from the 'new' routine.
1026             },
1027              
1028             # maintain color map, set to specified rgb triple
1029             COLOR => sub {
1030             my $self = shift;
1031             my $color = _color(shift);
1032              
1033             # init.
1034             $self->{COLORS} = [] unless exists($self->{COLORS});
1035              
1036             my @idx = @{$self->{COLORS}}; # map of color index (0-15) to RGB triples
1037             my $found = 0;
1038             for (my $i=2;$i<@idx;$i++) { # map entries 0 and 1 are reserved for BACKGROUND and FRAMECOLOR
1039             if (_coloreq ($color, $idx[$i])) {
1040             $self->{CURRENT_COLOR_IDX} = $i;
1041             $found = 1;
1042             plscol0 ($self->{CURRENT_COLOR_IDX}, @$color);
1043             }
1044             }
1045             return if ($found);
1046              
1047             die "Too many colors used! (max 15)" if (@{$self->{COLORS}} > 14);
1048              
1049             # add this color as index 2 or greater (entries 0 and 1 reserved)
1050             my $idx = (@{$self->{COLORS}} > 1) ? @{$self->{COLORS}} : 2;
1051             $self->{COLORS}[$idx] = $color;
1052             $self->{CURRENT_COLOR_IDX} = $idx;
1053             plscol0 ($self->{CURRENT_COLOR_IDX}, @$color);
1054             },
1055              
1056             # Contour plot label parameters (see setcontlabelparam and setcontlabelformat)
1057             CONTOURLABELS => sub { my $self = shift;
1058             my $parms = shift; # [offset, size, spacing, lexp, sigdig], or 0 (deactivate) or 1 (activate)
1059             my $defaults = [0.006, 0.3, 0.1, 4, 2];
1060             if ( (ref($parms) =~ /ARRAY/) && (@$parms == 5) ) {
1061             $self->{CONTOURLABELS} = $parms;
1062             } elsif ($parms == 0) {
1063             $self->{CONTOURLABELS} = 0;
1064             } elsif ($parms == 1) {
1065             $self->{CONTOURLABELS} = $defaults;
1066             } else {
1067             die
1068             "Illegal contour label parameters: Must either be 0 (turn off contour labels), 1 (turn on default contour labels)
1069             or a five element array:
1070             offset: Offset of label from contour line (if set to 0.0, labels are printed on the lines). Default value is 0.006.
1071             size: Font height for contour labels (normalized). Default value is 0.3.
1072             spacing: Spacing parameter for contour labels. Default value is 0.1.
1073             lexp: If the contour numerical label is greater than 10^(lexp) or less than 10^(-lexp),
1074             then the exponential format is used. Default value of lexp is 4.
1075             sigdig: Number of significant digits. Default value is 2";
1076             }
1077             },
1078              
1079             # set output device type
1080             DEV => sub { my $self = shift;
1081             my $dev = shift;
1082             $self->{DEV} = $dev;
1083             plsdev ($dev)
1084             }, # this must be specified with call to new!
1085              
1086             # set PDL to plot into (alternative to specifying DEV)
1087             MEM => sub { my $self = shift;
1088             my $pdl = shift;
1089             my $x = $pdl->getdim(1);
1090             my $y = $pdl->getdim(2);
1091             plsmem ($x, $y, $pdl);
1092             },
1093              
1094             # set output file
1095             FILE => sub { plsfnam ($_[1]) }, # this must be specified with call to new!
1096              
1097             # set color for index 1, the plot frame and text
1098             # set color index 1, the frame color
1099             FRAMECOLOR => sub {
1100             my $self = shift;
1101             my $color = _color(shift);
1102             $self->{COLORS}[1] = $color;
1103             plscol0 (1, @$color);
1104             },
1105              
1106             GRIDMAP => sub {
1107             # Use a user-defined grid map if requested. This is an X and Y vector that
1108             # tells what are the world coordinates for each pixel in $z
1109             # It is used in 'shadeplot'.
1110             my $self = shift;
1111             my $map = shift;
1112             die "GRIDMAP must be an array reference" if (ref($map) !~ /ARRAY/);
1113             die "GRIDMAP must be a two element array reference" if (@$map != 2);
1114             die "GRIDMAP must contain two PDLs" if ( (ref($$map[0]) !~ /PDL/) || (ref($$map[1]) !~ /PDL/) );
1115             die "GRIDMAP must contain two 1D PDLs" if ( ($$map[0]->dims != 1) || ($$map[1]->dims != 1) );
1116             $self->{GRIDMAP} = $map;
1117             },
1118              
1119             GRIDMAP2 => sub {
1120             # Use a user-defined grid map if requested. These are an X and Y matrices that
1121             # tells what are the world coordinates for each pixel in $z
1122             # They are used in 'shadeplot'.
1123             my $self = shift;
1124             my $map = shift;
1125             die "GRIDMAP2 must be an array reference" if (ref($map) !~ /ARRAY/);
1126             die "GRIDMAP2 must be a two element array reference" if (@$map != 2);
1127             die "GRIDMAP2 must contain two PDLs" if ( (ref($$map[0]) !~ /PDL/) || (ref($$map[1]) !~ /PDL/) );
1128             die "GRIDMAP2 must contain two 2D PDLs" if ( ($$map[0]->dims != 2) || ($$map[1]->dims != 2) );
1129             $self->{GRIDMAP2} = $map;
1130             },
1131              
1132             # Set flag for equal scale axes
1133             JUST => sub {
1134             my $self = shift;
1135             my $just = shift;
1136             die "JUST must be 0 or 1 (defaults to 0)" unless ($just == 0 or $just == 1);
1137             $self->{JUST} = $just;
1138             },
1139              
1140             LINEWIDTH => sub {
1141             my $self = shift;
1142             my $wid = shift;
1143             die "LINEWIDTH must range from 0 to LARGE8" unless ($wid >= 0);
1144             $self->{LINEWIDTH} = $wid;
1145             },
1146              
1147             LINESTYLE => sub {
1148             my $self = shift;
1149             my $sty = shift;
1150             die "LINESTYLE must range from 1 to 8" unless ($sty >= 1 and $sty <= 8);
1151             $self->{LINESTYLE} = $sty;
1152             },
1153              
1154             MAJTICKSIZE => sub {
1155             my $self = shift;
1156             my $val = shift;
1157             die "MAJTICKSIZE must be greater than or equal to zero"
1158             unless ($val >= 0);
1159             plsmaj (0, $val);
1160             },
1161              
1162             MINTICKSIZE => sub {
1163             my $self = shift;
1164             my $val = shift;
1165             die "MINTICKSIZE must be greater than or equal to zero"
1166             unless ($val >= 0);
1167             plsmin (0, $val);
1168             },
1169              
1170             NXSUB => sub {
1171             my $self = shift;
1172             my $val = shift;
1173             die "NXSUB must be an integer greater than or equal to zero"
1174             unless ($val >= 0 and int($val) == $val);
1175             $self->{NXSUB} = $val;
1176             },
1177              
1178             NYSUB => sub {
1179             my $self = shift;
1180             my $val = shift;
1181             die "NYSUB must be an integer greater than or equal to zero"
1182             unless ($val >= 0 and int($val) == $val);
1183             $self->{NYSUB} = $val;
1184             },
1185              
1186             # set driver options, example for ps driver, {text => 1} is accepted
1187             OPTS => sub {
1188             my $self = shift;
1189             my $opts = shift;
1190              
1191             foreach my $opt (keys %$opts) {
1192             plsetopt ($opt, $$opts{$opt});
1193             }
1194             },
1195              
1196             # set driver options, example for ps driver, {text => 1} is accepted
1197             ORIENTATION => sub {
1198             my $self = shift;
1199             my $orient = shift;
1200              
1201             die "Orientation must be between 0 and 4" unless ($orient >= 0 and $orient <= 4);
1202             $self->{ORIENTATION} = $orient;
1203             },
1204              
1205             PAGESIZE =>
1206             # set plot size in mm. Only useful in call to 'new'
1207             sub {
1208             my $self = shift;
1209             my $dims = shift;
1210              
1211             die "plot size must be a 2 element array ref: X size in pixels, Y size in pixels"
1212             if ((ref($dims) !~ /ARRAY/) || @$dims != 2);
1213             $self->{PAGESIZE} = $dims;
1214             },
1215              
1216             # load some pre-done color map 1 setups
1217             PALETTE => sub {
1218             my $self = shift;
1219             my $pal = shift;
1220              
1221             my %legal = (REVERSERAINBOW => 1, REVERSEGREYSCALE => 1, REDGREEN => 1, RAINBOW => 1, GREYSCALE => 1, GREENRED => 1);
1222             if ($legal{$pal}) {
1223             $self->{PALETTE} = $pal;
1224             if ($pal eq 'RAINBOW') {
1225             plscmap1l (0, PDL->new(0,1), PDL->new(0,300), PDL->new(0.5, 0.5), PDL->new(1,1), PDL->new(0,0));
1226             } elsif ($pal eq 'REVERSERAINBOW') {
1227             plscmap1l (0, PDL->new(0,1), PDL->new(270,-30), PDL->new(0.5, 0.5), PDL->new(1,1), PDL->new(0,0));
1228             } elsif ($pal eq 'GREYSCALE') {
1229             plscmap1l (0, PDL->new(0,1), PDL->new(0,0), PDL->new(0,1), PDL->new(0,0), PDL->new(0,0));
1230             } elsif ($pal eq 'REVERSEGREYSCALE') {
1231             plscmap1l (0, PDL->new(0,1), PDL->new(0,0), PDL->new(1,0), PDL->new(0,0), PDL->new(0,0));
1232             } elsif ($pal eq 'GREENRED') {
1233             plscmap1l (0, PDL->new(0,1), PDL->new(120,0), PDL->new(0.5, 0.5), PDL->new(1,1), PDL->new(1,1));
1234             } elsif ($pal eq 'REDGREEN') {
1235             plscmap1l (0, PDL->new(0,1), PDL->new(0,120), PDL->new(0.5, 0.5), PDL->new(1,1), PDL->new(1,1));
1236             }
1237             } else {
1238             die "Illegal palette name. Legal names are: " . join (" ", keys %legal);
1239             }
1240             },
1241              
1242             # specify plot type (LINE, POINTS, LINEPOINTS, CONTOUR, SHADE)
1243             PLOTTYPE => sub {
1244             my $self = shift;
1245             my $val = shift;
1246              
1247             my %legal = (LINE => 1, POINTS => 1, LINEPOINTS => 1, CONTOUR => 1, SHADE => 1);
1248             if ($legal{$val}) {
1249             $self->{PLOTTYPE} = $val;
1250             } else {
1251             die "Illegal plot type. Legal options are: " . join (" ", keys %legal);
1252             }
1253             },
1254              
1255             # Specify outline bars for bargraph
1256             STACKED_BAR_COLORS => sub {
1257             my $self = shift;
1258             my $val = shift;
1259             my $err = "STACKED_BAR_COLORS must be a reference to a perl list of color names or RGB triples";
1260             die $err if (ref($val) !~ /ARRAY/);
1261             delete $self->{STACKED_BAR_COLORS};
1262             foreach my $e (@$val) {
1263             push @{$self->{STACKED_BAR_COLORS}}, _color($e); # Will throw an exception if this is not a legal color
1264             }
1265             },
1266              
1267             # specify which subpage to plot on 1-N or 0 (meaning 'next')
1268             SUBPAGE => sub {
1269             my $self = shift;
1270             my $val = shift;
1271             my $err = "SUBPAGE = \$npage where \$npage = 1-N or 0 (for 'next subpage')";
1272             if ($val >= 0) {
1273             $self->{SUBPAGE} = $val;
1274             } else {
1275             die $err;
1276             }
1277             },
1278              
1279             # specify number of sub pages [nx, ny]
1280             SUBPAGES => sub {
1281             my $self = shift;
1282             my $val = shift;
1283             my $err = "SUBPAGES = [\$nx, \$ny] where \$nx and \$ny are between 1 and 127";
1284             if (ref($val) =~ /ARRAY/ and @$val == 2) {
1285             my ($nx, $ny) = @$val;
1286             if ($nx > 0 and $nx < 128 and $ny > 0 and $ny < 128) {
1287             $self->{SUBPAGES} = [$nx, $ny];
1288             } else {
1289             die $err;
1290             }
1291             } else {
1292             die $err;
1293             }
1294             },
1295              
1296             # specify type of symbol to plot
1297             SYMBOL => sub {
1298             my $self = shift;
1299             my $val = shift;
1300              
1301             if ($val >= 0 && $val < 3000) {
1302             $self->{SYMBOL} = $val;
1303             } else {
1304             die "Illegal symbol number. Legal symbols are between 0 and 3000";
1305             }
1306             },
1307              
1308             SYMBOLSIZE => sub {
1309             my ($self, $size) = @_;
1310             die "symbol size must be a real number from 0 to (large)" unless ($size >= 0);
1311             $self->{SYMBOLSIZE} = $size;
1312             },
1313              
1314             # specify placement of text. Either relative to border, specified as:
1315             # [$side, $disp, $pos, $just]
1316             # or
1317             # inside plot window, specified as:
1318             # [$x, $y, $dx, $dy, $just] (see POD doc for details)
1319             TEXTPOSITION => sub {
1320             my $self = shift;
1321             my $val = shift;
1322             die "TEXTPOSITION value must be an array ref with either:
1323             [$side, $disp, $pos, $just] or [$x, $y, $dx, $dy, $just]"
1324             unless ((ref($val) =~ /ARRAY/) and ((@$val == 4) || (@$val == 5)));
1325             if (@$val == 4) {
1326             $self->{TEXTMODE} = 'border';
1327             } else {
1328             $self->{TEXTMODE} = 'plot';
1329             }
1330             $self->{TEXTPOSITION} = $val;
1331             },
1332              
1333             # draw a title for the graph
1334             TITLE => sub {
1335             my $self = shift;
1336             my $text = shift;
1337             $self->{TITLE} = $text;
1338             },
1339              
1340             # Specify outline bars for bargraph
1341             UNFILLED_BARS => sub {
1342             my $self = shift;
1343             my $val = shift;
1344             $self->{UNFILLED_BARS} = $val;
1345             },
1346              
1347             # set the location of the plotting window on the page
1348             VIEWPORT => sub {
1349             my $self = shift;
1350             my $vp = shift;
1351             die "Viewport must be a ref to a four element array"
1352             unless (ref($vp) =~ /ARRAY/ and @$vp == 4);
1353             $self->{VIEWPORT} = $vp;
1354             },
1355              
1356             # set X axis label options. See pod for definitions.
1357             XBOX => sub {
1358             my $self = shift;
1359             my $opts = lc shift;
1360             my @opts = split '', $opts;
1361             map { 'abcdfghilmnst' =~ /$_/i || die "Illegal option $_. Only abcdfghilmnst permitted" } @opts;
1362             $self->{XBOX} = $opts;
1363             },
1364              
1365             # draw an X axis label for the graph
1366             XLAB => sub {
1367             my $self = shift;
1368             my $text = shift;
1369             $self->{XLAB} = $text;
1370             },
1371              
1372             XTICK => sub {
1373             my $self = shift;
1374             my $val = shift;
1375             die "XTICK must be greater than or equal to zero"
1376             unless ($val >= 0);
1377             $self->{XTICK} = $val;
1378             },
1379              
1380             # set Y axis label options. See pod for definitions.
1381             YBOX => sub {
1382             my $self = shift;
1383             my $opts = shift;
1384             my @opts = split '', $opts;
1385             map { 'abcfghilmnstv' =~ /$_/i || die "Illegal option $_. Only abcfghilmnstv permitted" } @opts;
1386             $self->{YBOX} = $opts;
1387             },
1388              
1389             # draw an Y axis label for the graph
1390             YLAB => sub {
1391             my $self = shift;
1392             my $text = shift;
1393             $self->{YLAB} = $text;
1394             },
1395              
1396             YTICK => sub {
1397             my $self = shift;
1398             my $val = shift;
1399             die "YTICK must be greater than or equal to zero"
1400             unless ($val >= 0);
1401             $self->{YTICK} = $val;
1402             },
1403              
1404             ZRANGE => sub {
1405             my $self = shift;
1406             my $val = shift;
1407             die "ZRANGE must be a perl array ref with min and max Z values"
1408             unless (ref($val) =~ /ARRAY/ && @$val == 2);
1409             $self->{ZRANGE} = $val;
1410             },
1411              
1412             );
1413              
1414              
1415             #
1416             ## Internal utility routines
1417 489     489   645 #
1418 489 100       1536  
    50          
1419 6         13 # handle color as string in _constants hash or [r,g,b] triple
1420             # Input: either color name or [r,g,b] array ref
1421 483         818 # Output: [r,g,b] array ref or exception
1422             sub _color {
1423 0         0 my $c = shift;
1424             if (ref($c) =~ /ARRAY/) {
1425             return $c;
1426             } elsif ($c = $_constants{$c}) {
1427             return $c;
1428             } else {
1429 83     83   115 die "Color $c not defined";
1430 83 100       135 }
  142         355  
1431 15         31 }
1432              
1433             # return 1 if input [r,g,b] triples are equal.
1434             sub _coloreq {
1435             my ($a, $b) = @_;
1436             for (my $i=0;$i<3;$i++) { return 0 if ($$a[$i] != $$b[$i]); }
1437             return 1;
1438 726     726   917 }
1439              
1440             # Initialize plotting window given the world coordinate box and
1441 726 100       2850 # a 'justify' flag (for equal axis scales).
1442 726         1173 sub _setwindow {
1443              
1444             my $self = shift;
1445 726   100     1685  
1446             # choose correct subwindow
1447 6 50   6 0 11 pladv ($self->{SUBPAGE}) if (exists ($self->{SUBPAGE}));
1448             delete ($self->{SUBPAGE}); # get rid of SUBPAGE so future plots will stay on same
1449             # page unless user asks for specific page
1450 726         2188  
1451 726         77765 my $box = $self->{BOX} || [0,1,0,1]; # default window
1452 726         2321  
1453 726         8966 sub MAX { ($_[0] > $_[1]) ? $_[0] : $_[1]; }
1454 726         5274  
1455 726         4908 # get subpage offsets from page left/bottom of image
1456 726         4674 my ($spxmin, $spxmax, $spymin, $spymax) = (PDL->new(0),PDL->new(0),PDL->new(0),PDL->new(0));
1457 726         1021 plgspa($spxmin, $spxmax, $spymin, $spymax);
1458             $spxmin = $spxmin->at(0);
1459 726         813 $spxmax = $spxmax->at(0);
  726         1881  
1460             $spymin = $spymin->at(0);
1461             $spymax = $spymax->at(0);
1462 726 100       1541 my $xsize = $spxmax - $spxmin;
1463 724         18647 my $ysize = $spymax - $spymin;
1464              
1465             my @vp = @{$self->{VIEWPORT}}; # view port xmin, xmax, ymin, ymax in fraction of image size
1466              
1467 2         4 # if JUSTify is zero, set to the user specified (or default) VIEWPORT
1468 2         56 if ($self->{JUST} == 0) {
1469 2         45 plvpor(@vp);
1470 2         3  
1471 2         13 # compute viewport to allow the same scales for both axes
1472 2         2 } else {
1473 2         2 my $p_def = PDL->new(0);
1474 2         3 my $p_ht = PDL->new(0);
1475 2         4 plgchr ($p_def, $p_ht);
1476 2         2 $p_def = $p_def->at(0);
1477 2         4 my $lb = 8.0 * $p_def;
1478 2         3 my $rb = 5.0 * $p_def;
1479 2         5 my $tb = 5.0 * $p_def;
1480 2         4 my $bb = 5.0 * $p_def;
1481 2         2 my $dx = $$box[1] - $$box[0];
1482 2         4 my $dy = $$box[3] - $$box[2];
1483 2         2 my $xscale = $dx / ($xsize - $lb - $rb);
1484 2         65 my $yscale = $dy / ($ysize - $tb - $bb);
1485 2         13 my $scale = MAX($xscale, $yscale);
1486             my $vpxmin = MAX($lb, 0.5 * ($xsize - $dx / $scale));
1487             my $vpxmax = $vpxmin + ($dx / $scale);
1488             my $vpymin = MAX($bb, 0.5 * ($ysize - $dy / $scale));
1489 726         14432 my $vpymax = $vpymin + ($dy / $scale);
1490             plsvpa($vpxmin, $vpxmax, $vpymin, $vpymax);
1491             $self->{VIEWPORT} = [$vpxmin/$xsize, $vpxmax/$xsize, $vpymin/$ysize, $vpymax/$ysize];
1492             }
1493              
1494             # set up world coords in window
1495             plwind (@$box);
1496 565     565   658  
1497             }
1498 565         6839  
1499 565 100       1509 # Add title and axis labels.
1500 565 100       1057 sub _drawlabels {
1501 565 100       1092  
1502 565         4281 my $self = shift;
1503              
1504             plcol0 (1); # set to frame color
1505             plmtex (2.5, 0.5, 0.5, 't', $self->{TITLE}) if ($self->{TITLE});
1506             plmtex (3.0, 0.5, 0.5, 'b', $self->{XLAB}) if ($self->{XLAB});
1507             plmtex (3.5, 0.5, 0.5, 'l', $self->{YLAB}) if ($self->{YLAB});
1508             plcol0 ($self->{CURRENT_COLOR_IDX}); # set back
1509              
1510             }
1511              
1512              
1513             #
1514             ## user-visible routines
1515             #
1516              
1517             # Pool of PLplot stream numbers. One of these stream numbers is taken when 'new' is called
1518             # and when the corresponding 'close' is called, it is returned to the pool. The pool is
1519 148     148 1 470698 # just a queue: 'new' shifts stream numbers from the top of the queue, 'close' pushes them
1520 148         241 # back on the bottom of the queue.
1521             my @plplot_stream_pool = (0..99);
1522              
1523 148         555 # This routine starts out a plot. Generally one specifies
1524             # DEV and FILE (device and output file name) as options.
1525 148         261 sub new {
1526             my $type = shift;
1527 148         293 my $self = {};
1528              
1529             # set up object
1530 148         350 $self->{PLOTTYPE} = 'LINE';
1531 148 50       403 # $self->{CURRENT_COLOR_IDX} = 1;
1532 148         3220 $self->{COLORS} = [];
1533              
1534             bless $self, $type;
1535 148         420  
1536             # set stream number first
1537             $self->{STREAMNUMBER} = shift @plplot_stream_pool;
1538             die "No more PLplot streams left, too many open PLplot objects!" if (!defined($self->{STREAMNUMBER}));
1539 148         1649 plsstrm($self->{STREAMNUMBER});
1540              
1541             # set background and frame color first
1542             $self->setparm(BACKGROUND => 'WHITE',
1543             FRAMECOLOR => 'BLACK');
1544              
1545             # set defaults, allow input options to override
1546             my %opts = (
1547             COLOR => 'BLACK',
1548             XBOX => 'BCNST',
1549             YBOX => 'BCNST',
1550             JUST => 0,
1551             SUBPAGES => [1,1],
1552             VIEWPORT => [0.1, 0.87, 0.13, 0.82],
1553             SUBPAGE => 0,
1554             PAGESIZE => [600, 500],
1555             LINESTYLE => 1,
1556             LINEWIDTH => 0,
1557             SYMBOL => 751, # a small square
1558             NXSUB => 0,
1559             NYSUB => 0,
1560 148         381 ORIENTATION=> 0,
1561 148         682 XTICK => 0,
1562 148         479 YTICK => 0,
1563             CHARSIZE => 1,
1564             @_);
1565 148 50       290  
  148         3751  
1566 148         234  
  148         1551  
1567 148         1923 # apply options
1568 148         1266 $self->{ISNEW} = 1;
1569 148         1033 $self->setparm(%opts);
1570 148         4400 $self->{ISNEW} = 0;
1571 148         42632  
1572             # Do initial setup
1573             plspage (0, 0, @{$self->{PAGESIZE}}, 0, 0) if (defined($self->{PAGESIZE}));
1574 148         3784 plssub (@{$self->{SUBPAGES}});
1575             plsfam (0, -1, -1); # fix for plplot 5.11.0
1576             plfontld (1); # extented symbol pages
1577 148         1253 plscmap0n (16); # set up color map 0 to 16 colors. Is this needed?
1578             plscmap1n (128); # set map 1 to 128 colors (should work for devices with 256 colors)
1579             plinit ();
1580 148         511  
1581             # Now (as of plplot5.11) this must be done after plinit();
1582 148         1153 plschr (0, $self->{CHARSIZE});
1583              
1584             # set page orientation
1585             plsdiori ($self->{ORIENTATION});
1586              
1587 880     880 1 1110 # set up plotting box
1588             $self->_setwindow;
1589 880         2466  
1590             return $self;
1591             }
1592 880         7173  
1593             # set parameters. Called from user directly or from other routines.
1594             sub setparm {
1595             my $self = shift;
1596 880         2774  
1597 4110 50       8493 my %opts = @_;
1598 0         0  
1599 0         0 # Set PLplot to right output stream
1600             plsstrm($self->{STREAMNUMBER});
1601 4110         4763  
  4110         6631  
1602             # apply all options
1603             OPTION:
1604             foreach my $o (keys %opts) {
1605             unless (exists($_actions{$o})) {
1606             warn "Illegal option $o, ignoring";
1607 549     549 1 47276 next OPTION;
1608 549         667 }
1609 549         644 &{$_actions{$o}}($self, $opts{$o});
1610             }
1611 549         1790 }
1612              
1613             # handle 2D plots
1614 549         7508 sub xyplot {
1615             my $self = shift;
1616             my $x = shift;
1617 549         1064 my $y = shift;
1618 549         695  
1619             my %opts = @_;
1620              
1621 549         983 # Set PLplot to right output stream
1622 549         633 plsstrm($self->{STREAMNUMBER});
1623 549         621  
1624 549         732 # only process COLORMAP entries once
1625             my $z = $opts{COLORMAP};
1626             delete ($opts{COLORMAP});
1627 549         1874  
1628             # handle ERRORBAR options
1629 549 100       1329 my $xeb = $opts{XERRORBAR};
1630 131         386 my $yeb = $opts{YERRORBAR};
1631             delete ($opts{XERRORBAR});
1632             delete ($opts{YERRORBAR});
1633              
1634 549         7178 # apply options
1635             $self->setparm(%opts);
1636              
1637 549         1648 unless (exists($self->{BOX})) {
1638             $self->{BOX} = [$x->minmax, $y->minmax];
1639             }
1640 549         3810  
1641             # set up viewport, subpage, world coordinates
1642 549         2219 $self->_setwindow;
1643              
1644             # draw labels
1645             $self->_drawlabels;
1646              
1647 549         13568 # plot box
1648             plcol0 (1); # set to frame color
1649             plbox ($self->{XTICK}, $self->{NXSUB}, $self->{YTICK}, $self->{NYSUB},
1650 549         5283 $self->{XBOX}, $self->{YBOX}); # !!! note out of order call
1651              
1652             # set the color according to the color specified in the object
1653 549         4889 # (we don't do this as an option, because then the frame might
1654             # get the color requested for the line/points
1655             plcol0 ($self->{CURRENT_COLOR_IDX});
1656 549 100       2366  
1657 146         1584 # set line style for plot only (not box)
1658             pllsty ($self->{LINESTYLE});
1659              
1660             # set line width for plot only (not box)
1661 549         3650 plwidth ($self->{LINEWIDTH});
1662              
1663             # Plot lines if requested
1664 549 100       1848 if ($self->{PLOTTYPE} =~ /LINE/) {
1665 405         803 plline ($x, $y);
1666 405 50       990 }
1667              
1668             # set line width back
1669             plwidth (0);
1670 0         0  
1671 0 0       0 # plot points if requested
1672             if ($self->{PLOTTYPE} =~ /POINTS/) {
1673 405 100       1080 my $c = $self->{SYMBOL};
1674             unless (defined($c)) {
1675 405 100       793  
1676 2 50       12 # the default for $c is a PDL of ones with shape
  0         0  
1677 2         828 # equal to $x with the first dimension removed
1678             my $z = PDL->zeroes($x->nelem);
1679 403         6643 $c = PDL->ones($z->zcover) unless defined($c);
1680             }
1681             plssym (0, $self->{SYMBOLSIZE}) if (defined($self->{SYMBOLSIZE}));
1682              
1683             if (defined($z)) { # if a color range plot requested
1684 549 100       1136 my ($min, $max) = exists ($self->{ZRANGE}) ? @{$self->{ZRANGE}} : $z->minmax;
1685             plcolorpoints ($x, $y, $z, $c, $min, $max);
1686 1         7 } else {
1687             plsym ($x, $y, $c);
1688             }
1689 549 100       972 }
1690              
1691 1         5 # Plot error bars, if requested
1692             if (defined($xeb)) {
1693             # horizontal (X) error bars
1694             plerrx ($x->nelem, $x - $xeb/2, $x + $xeb/2, $y);
1695 549         21502 }
1696              
1697             if (defined($yeb)) {
1698             # vertical (Y) error bars
1699             plerry ($y->nelem, $x, $y - $yeb/2, $y + $yeb/2);
1700 2     2 1 571 }
1701 2         3  
1702 2         4 # Flush the PLplot stream.
1703             plflush();
1704 2         9 }
1705              
1706             sub stripplots {
1707 2   50     13  
1708 2         3 my $self = shift;
1709             my $xs = shift;
1710             my $yargs = shift;
1711 2         4  
1712 2         3 my %opts = @_;
1713              
1714             # NYTICK => number of y axis ticks
1715 2   50     5 my $nytick = $opts{NYTICK} || 2;
1716 2   100     7 delete ($opts{NYTICK});
1717 2 50 33     14  
  2         5  
1718 2         8 # only process COLORMAP entries once
1719             my $zs = $opts{COLORMAP};
1720             delete ($opts{COLORMAP});
1721 2         3  
1722 2 50       9 # handle XLAB, YLAB and TITLE options
    0          
1723 2         2 my $title = $opts{TITLE} || '';
1724             my $xlab = $opts{XLAB} || '';
1725             my @ylabs = defined($opts{YLAB}) && (ref($opts{YLAB}) =~ /ARRAY/) ? @{$opts{YLAB}} : ();
1726 0         0 delete @opts{qw(TITLE XLAB YLAB)};
1727              
1728             # Ensure we're dealing with an array reference
1729 0         0 my $ys;
1730             if (ref ($yargs) eq 'ARRAY') {
1731             $ys = $yargs;
1732             }
1733             elsif (ref ($yargs) =~ /PDL/) {
1734             $ys = [dog $yargs];
1735             }
1736             else {
1737             barf("stripplots requires that its second argument be either a 2D ndarray or\na reference to a list of 1D ndarrays, but you provided neither.");
1738             }
1739              
1740             # This doesn't work because $xs can be an anonymous array, too
1741 2         4 # # Let's be sure the user sent us what we expected:
1742             # foreach (@$ys) {
1743             # barf ("stripplots needs to have ndarrays for its y arguments!")
1744 1         3 # unless (ref =~ /PDL/);
1745 2 50 66     14 # barf("stripplots requires that the x and y dimensions agree!")
    100          
1746             # unless ($_->nelem == $xs->nelem);
1747 2         5 # }
1748              
1749 2 50       4 my $nplots = @$ys;
1750 2 50       4  
1751 2         3 # Use list of colors, or single color. If COLOR not specified, default to BLACK for each graph
1752             my @colors = (defined ($opts{COLOR}) && ref($opts{COLOR}) =~ /ARRAY/) ? @{$opts{COLOR}}
1753             : defined ($opts{COLOR}) ? ($opts{COLOR}) x $nplots
1754 2         6 : ('BLACK') x $nplots;
1755             delete @opts{qw(COLOR)};
1756 2         4  
1757 2 50       6 my $y_base = defined($opts{Y_BASE}) ? $opts{Y_BASE} : 0.1; # Y offset to start bottom plot
1758 0         0 my $y_gutter = defined($opts{Y_GUTTER}) ? $opts{Y_GUTTER} : 0.02; # Y gap between plots
1759             delete @opts{qw(Y_BASE Y_GUTTER)};
1760              
1761 2         4 # apply options
  7         139  
1762 2         338 $self->setparm(%opts);
  7         53  
1763              
1764             my ($xmin, $xmax);
1765             if (ref ($xs) =~ /PDL/) {
1766 2         344 ($xmin, $xmax) = $xs->minmax;
1767             }
1768 7         12 else {
1769 7 50       23 $xmin = pdl(map { $_->min } @$xs)->min;
1770 7         143 $xmax = pdl(map { $_->max } @$xs)->max;
1771 7         28 }
1772 7         913  
1773 7 50       570 SUBPAGE:
1774 7 50       13 for (my $subpage=0;$subpage<$nplots;$subpage++) {
1775 7         11  
1776             my $y = $ys->[$subpage];
1777 7         11 my $x = ref ($xs) =~ /PDL/ ? $xs : $xs->[$subpage];
1778 7         12 my $mask = $y->isgood;
1779             $y = $y->where($mask);
1780 7         9 $x = $x->where($mask);
1781 7 100       13 my $z = $zs->slice(":,($subpage)")->where($mask) if (defined($zs));
1782             my $yeb = $yebs->slice(":,($subpage)")->where($mask) if (defined($yebs));
1783 7         43 my $ylab = $ylabs[$subpage];
1784 7 50       18  
1785 7 50       327 my $bottomplot = ($subpage == 0);
1786 7         439 my $topplot = ($subpage == $nplots-1);
1787 7         289  
1788 7 50       109 my $xbox = 'bc';
1789 7 50       51 $xbox = 'cstnb' if ($bottomplot);
1790              
1791             my $box = $opts{BOX};
1792             my $yrange = defined($box) ? $$box[3] - $$box[2] : $y->max - $y->min;
1793             my $del = $yrange ? $yrange * 0.05 : 1;
1794             my @ybounds = ($y->min - $del, $y->max + $del);
1795             my $ytick = ($yrange/$nytick);
1796             my @COLORMAP = (COLORMAP => $z) if defined($z);
1797             $self->xyplot($x, $y,
1798             COLOR => $colors[$subpage],
1799             BOX => defined($box) ? $box : [$xmin, $xmax, @ybounds],
1800             XBOX => $xbox,
1801             YBOX => 'BCNT',
1802             YTICK => $ytick,
1803             MAJTICKSIZE => 0.6,
1804             CHARSIZE => 0.4,
1805             @COLORMAP,
1806 7 50       45 VIEWPORT => [
1807 7 100 100     37 0.15,
1808 7 100 66     85 0.9,
1809             $y_base + ($subpage * (0.8/$nplots)),
1810             $y_base - $y_gutter + (($subpage+1) * (0.8/$nplots)),
1811             ],
1812             );
1813              
1814             $self->text($ylab, TEXTPOSITION => ['L', 4, 0.5, 0.5], COLOR => 'BLACK', CHARSIZE => 0.6) if (defined($ylab));
1815             $self->text($xlab, TEXTPOSITION => ['B', 3, 0.5, 0.5], COLOR => 'BLACK', CHARSIZE => 0.6) if ($xlab && $bottomplot);
1816 5     5 1 50 $self->text($title, TEXTPOSITION => ['T', 2, 0.5, 0.5], COLOR => 'BLACK', CHARSIZE => 1.3) if ($title && $topplot);
1817 5         8  
1818 5         10 }
1819              
1820 5         19 }
1821              
1822              
1823 5         101 # Draw a color key or wedge showing the scale of map1 colors
1824             sub colorkey {
1825             my $self = shift;
1826 5         25 my $var = shift;
1827             my $orientation = shift; # 'v' (for vertical) or 'h' (for horizontal)
1828              
1829 5         17 my %opts = @_;
1830              
1831             # Set PLplot to right output stream
1832 5         21 plsstrm($self->{STREAMNUMBER});
1833              
1834             # apply options
1835 5 50       19 $self->setparm(%opts);
1836 5 50       13  
1837             # set up viewport, subpage, world coordinates
1838 5         6 $self->_setwindow;
1839              
1840 5         38 # draw labels
1841             $self->_drawlabels;
1842 5 50       32  
  0         0  
1843             # Allow user to set X, Y box type for color key scale. D. Hunt 1/7/2009
1844             my $xbox = exists($self->{XBOX}) ? $self->{XBOX} : 'TM';
1845 5 100       206 my $ybox = exists($self->{YBOX}) ? $self->{YBOX} : 'TM';
    50          
1846              
1847 3         8 my @box;
1848 3         61  
1849 3         13 plcol0 (1); # set to frame color
1850              
1851 2         7 my ($min, $max) = exists ($self->{ZRANGE}) ? @{$self->{ZRANGE}} : $var->minmax;
1852 2         44  
1853 2         12 # plot box
1854             if ($orientation eq 'v') {
1855 0         0 # set world coordinates based on input variable
1856             @box = (0, 1, $min, $max);
1857             plwind (@box);
1858             plbox (0, 0, 0, 0, '', $ybox); # !!! note out of order call
1859 5         99 } elsif ($orientation eq 'h') {
1860             @box = ($min, $max, 0, 1);
1861             plwind (@box);
1862             plbox (0, 0, 0, 0, $xbox, ''); # !!! note out of order call
1863             } else {
1864 5 50       23 die "Illegal orientation value: $orientation. Should be 'v' (vertical) or 'h' (horizontal)";
1865             }
1866 5 100       16  
1867 3         9 # restore color setting
1868 3         6 plcol0 ($self->{CURRENT_COLOR_IDX});
1869 3         11  
1870 384         24795 # This is the number of colors shown in the color wedge. Make
1871 384         411 # this smaller for gif images as these are limited to 256 colors total.
1872 384         5518 # D. Hunt 8/9/2006
1873             my $ncols = ($self->{DEV} =~ /gif/) ? 32 : 128;
1874              
1875             if ($orientation eq 'v') {
1876 384         778 my $yinc = ($box[3] - $box[2])/$ncols;
1877 3840         226689 my $y0 = $box[2];
1878 3840         4400 for (my $i=0;$i<$ncols;$i++) {
1879 3840         6502 $y0 = $box[2] + ($i * $yinc);
1880             my $y1 = $y0 + $yinc;
1881             PDL::Graphics::PLplot::plcol1($i/$ncols);
1882              
1883             # Instead of using plfill (which is not supported on some devices)
1884 2         7 # use multiple calls to plline to color in the space. D. Hunt 8/9/2006
1885 2         4 foreach my $inc (0..9) {
1886 2         9 my $frac = $inc * 0.1;
1887 256         16936 my $y = $y0 + (($y1 - $y0) * $frac);
1888 256         296 PDL::Graphics::PLplot::plline (PDL->new(0,1), PDL->new($y,$y));
1889 256         3792 }
1890              
1891             }
1892             } else {
1893 256         501 my $xinc = ($box[1] - $box[0])/$ncols;
1894 2560         153549 my $x0 = $box[0];
1895 2560         3148 for (my $i=0;$i<$ncols;$i++) {
1896 2560         4640 $x0 = $box[0] + ($i * $xinc);
1897             my $x1 = $x0 + $xinc;
1898             PDL::Graphics::PLplot::plcol1($i/$ncols);
1899              
1900             # Instead of using plfill (which is not supported on some devices)
1901             # use multiple calls to plline to color in the space. D. Hunt 8/9/2006
1902             foreach my $inc (0..9) {
1903 5         690 my $frac = $inc * 0.1;
1904             my $x = $x0 + (($x1 - $x0) * $frac);
1905             PDL::Graphics::PLplot::plline (PDL->new($x,$x), PDL->new(0,1));
1906             }
1907 2     2 1 499  
1908 2         4 }
1909 2         3 }
1910              
1911 2         9 # Flush the PLplot stream.
1912             plflush();
1913             }
1914 2         19  
1915             sub shadeplot {
1916             my $self = shift;
1917 2         7 my $z = shift;
1918             my $nsteps = shift;
1919 2         374  
1920             my %opts = @_;
1921 2 50       12  
1922 0         0 # Set PLplot to right output stream
1923             plsstrm($self->{STREAMNUMBER});
1924              
1925             # apply options
1926 2         8 $self->setparm(%opts);
1927              
1928             my ($nx, $ny) = $z->dims;
1929 2         8  
1930             unless (exists($self->{BOX})) {
1931             $self->{BOX} = [0, $nx, 0, $ny];
1932 2         12 }
1933              
1934 2         11 # set up plotting box
1935             $self->_setwindow;
1936 2 50       18  
  0         0  
1937 2         160 # draw labels
1938             $self->_drawlabels;
1939              
1940 2         204 # plot box
1941 2         2 plcol0 (1); # set to frame color
1942 2         3 plbox ($self->{XTICK}, $self->{NXSUB}, $self->{YTICK}, $self->{NYSUB},
1943             $self->{XBOX}, $self->{YBOX}); # !!! note out of order call
1944 2         2  
1945             my ($min, $max) = exists ($self->{ZRANGE}) ? @{$self->{ZRANGE}} : $z->minmax;
1946             my $clevel = ((PDL->sequence($nsteps)*(($max - $min)/($nsteps-1))) + $min);
1947              
1948             # may add as options later. Now use constants
1949             my $fill_width = 2;
1950 2         4 my $cont_color = 0;
1951 2 50       7 my $cont_width = 0;
    100          
1952 0         0  
  0         0  
1953 0         0 my $rectangular = 1; # only false for non-linear coord mapping (not done yet in perl)
1954 0         0  
1955             # Use a user-defined grid map if requested. This is an X and Y vector that
1956 1         1 # tells what are the world coordinates for each pixel in $z
  1         3  
1957 1         33 # It is also possible to specify a 2D mapping for non-linear transforms. This is specified
1958 1         3 # in GRIDMAP2.
1959             my ($xmap, $ymap, $grid, $mapping_function);
1960             if (exists($self->{GRIDMAP})) {
1961 1         3 ($xmap, $ymap) = @{$self->{GRIDMAP}};
1962 1         61 $grid = plAllocGrid ($xmap, $ymap);
1963 1         58 $mapping_function = \&pltr1;
1964 1         2 } elsif (exists($self->{GRIDMAP2})) {
1965             ($xmap, $ymap) = @{$self->{GRIDMAP2}};
1966             $grid = plAlloc2dGrid ($xmap, $ymap);
1967             $mapping_function = \&pltr2;
1968 2 100 66     10 } else {
1969             # map X coords linearly to X range, Y coords linearly to Y range
1970 1 50 33     4 $xmap = ((PDL->sequence($nx)*(($self->{BOX}[1] - $self->{BOX}[0])/($nx - 1))) + $self->{BOX}[0]);
1971 0         0 $ymap = ((PDL->sequence($ny)*(($self->{BOX}[3] - $self->{BOX}[2])/($ny - 1))) + $self->{BOX}[2]);
  0         0  
1972 0         0 $grid = plAllocGrid ($xmap, $ymap);
1973 0         0 $mapping_function = \&pltr1;
1974             }
1975 1         24  
1976             # Choose shade plot or contour plot
1977             if (defined($self->{PLOTTYPE}) && ($self->{PLOTTYPE} eq 'CONTOUR') ) {
1978 1         8175  
1979             if (defined($self->{CONTOURLABELS}) && $self->{CONTOURLABELS}) {
1980             my ($offset, $size, $spacing, $lexp, $sigdig) = @{$self->{CONTOURLABELS}};
1981             pl_setcontlabelparam ($offset, $size, $spacing, 1); # 1 = activate
1982 1         2 pl_setcontlabelformat ($lexp, $sigdig);
  1         5  
1983             } else { # == 0, set labels off
1984             pl_setcontlabelparam (0.006, 0.3, 0.1, 0); # 0 = deactivate
1985             }
1986              
1987             plcont ($z, 1, $nx-1, 1, $ny-1, $clevel, $mapping_function, $grid);
1988 2 100       16  
1989 1         13 } else {
1990              
1991 1         11 plshades($z, @{$self->{BOX}}, $clevel, $fill_width,
1992             $cont_color, $cont_width, $rectangular,
1993             0, $mapping_function, $grid);
1994              
1995 2         101 }
1996              
1997             if (exists($self->{GRIDMAP2})) {
1998             plFree2dGrid ($grid);
1999 0     0 1 0 } else {
2000 0         0 plFreeGrid ($grid);
2001 0         0 }
2002              
2003 0         0 # Flush the PLplot stream.
2004             plflush();
2005 0         0 }
2006 0 0       0  
2007 0         0 sub histogram1 {
  0         0  
2008             my $self = shift;
2009 0         0 my $x = shift;
2010             my $nbins = shift;
2011              
2012 0         0 my $n = $x->nelem;
2013 0         0  
2014             my ($min, $max);
2015 0 0       0 if (exists($self->{BOX})) {
2016             ($min, $max) = @{$self->{BOX}}[0,1];
2017             } else {
2018 0         0 ($min, $max) = $x->minmax;
2019 0         0 }
2020              
2021             my $step = ($max - $min)/$nbins;
2022 0         0 my ($xvals, $yvals) = PDL::hist($x,$min,$max,$step);
2023              
2024             $self->{BOX} = [$min, $max, 0, $yvals->max] unless (exists($self->{BOX}));
2025 0         0  
2026             # apply options
2027             my %opts = @_;
2028 0         0 $self->setparm(%opts);
2029 0         0  
2030             # set up plotting box
2031             $self->_setwindow;
2032 0         0  
2033 0         0 # draw labels
2034 0         0 $self->_drawlabels;
2035 0 0       0  
2036             # plot box
2037 0         0 plcol0 (1); # set to frame color
2038             plbox ('', '', '', '', 'BNTI', 'BNTI'); # !!! note out of order call
2039 0         0  
2040 0         0 # draw colored histogram boxes
2041 0         0 plcol0 ($self->{CURRENT_COLOR_IDX});
2042             for (my $i=0;$i<$yvals->nelem;$i++) {
2043             my $y = $yvals->at($i);
2044             next if ($y == 0); # don't bother plotting
2045 0         0  
2046             my $x = $xvals->at($i);
2047              
2048 0         0 my $x0 = $x - ($step/2);
2049             my $x1 = $x + ($step/2);
2050             plfill (PDL->new($x0, $x1, $x1, $x0), PDL->new(0, 0, $y, $y));
2051             }
2052              
2053 3     3 1 19 # set color to frame color
2054 3         4 plcol0 (1);
2055 3         4  
2056             # draw outline for histogram blocks
2057 3         7 plbin ($xvals->nelem, $xvals, $yvals, 1); # '1' is oldbins parm: dont call plenv!
2058              
2059             }
2060 3         25  
2061             sub histogram {
2062             my $self = shift;
2063 3         8 my $x = shift;
2064             my $nbins = shift;
2065 3         3  
2066 3 50       5 my %opts = @_;
2067 3         3  
  3         7  
2068             # Set PLplot to right output stream
2069 0         0 plsstrm($self->{STREAMNUMBER});
2070 0         0  
2071             # apply options
2072             $self->setparm(%opts);
2073              
2074 3         6 my ($min, $max);
2075             if (exists($self->{BOX})) {
2076             ($min, $max) = @{$self->{BOX}}[0,1];
2077 3         8 } else {
2078             ($min, $max) = $x->minmax;
2079             $self->{BOX} = [$min, $max, 0, $x->nelem]; # box probably too tall!
2080 3         13 }
2081              
2082 3         10 # set up plotting box
2083             $self->_setwindow;
2084              
2085 3         41 # draw labels
2086             $self->_drawlabels;
2087              
2088 3         19 # plot box
2089             plcol0 (1); # set to frame color
2090             plbox ($self->{XTICK}, $self->{NXSUB}, $self->{YTICK}, $self->{NYSUB},
2091 3         27 $self->{XBOX}, $self->{YBOX}); # !!! note out of order call
2092              
2093 3         95 # set line style for plot only (not box)
2094             pllsty ($self->{LINESTYLE});
2095              
2096 3         15 # set line width for plot only (not box)
2097             plwidth ($self->{LINEWIDTH});
2098              
2099 3         65 # set color for histograms
2100             plcol0 ($self->{CURRENT_COLOR_IDX});
2101              
2102             plhist ($x, $min, $max, $nbins, 1); # '1' is oldbins parm: dont call plenv!
2103 6     6 1 1400  
2104 6         7 # set line width back
2105 6         4 plwidth (0);
2106              
2107 6         19 # Flush the PLplot stream.
2108             plflush();
2109             }
2110 6 100       13  
2111 6         6 sub bargraph {
2112             my $self = shift;
2113             my $labels = shift; # ref to perl list of labels for bars
2114 6         48 my $values = shift; # pdl of values for bars
2115 6         8  
2116             my %opts = @_;
2117              
2118 6         38 # max number of readable labels on x axis
2119             my $maxlab = defined($opts{MAXBARLABELS}) ? $opts{MAXBARLABELS} : 20;
2120 6   100     27 delete ($opts{MAXBARLABELS});
2121              
2122             # Set PLplot to right output stream
2123 6         8 plsstrm($self->{STREAMNUMBER});
2124 6 100       8 my $xmax = scalar(@$labels);
2125 1         1  
2126 1         23 # apply options
2127             $self->setparm(%opts);
2128 5         20  
2129             my $color_stack = $self->{STACKED_BAR_COLORS} // 0; # A list of colors for a stacked bar chart
2130              
2131 6 50       197 # ymax is either the largest value in bars, or the largest total of all stacked bars
2132 6         14 my ($ymin, $ymax);
2133             if ($color_stack) {
2134             $ymin = 0;
2135             $ymax = $values->xchg(0,1)->sumover->max;
2136 6         12 } else {
2137             ($ymin, $ymax) = $values->minmax;
2138             }
2139 6         13  
2140             unless (exists($self->{BOX})) {
2141             $self->{BOX} = [0, $xmax, $ymin, $ymax]; # box probably too tall!
2142 6         25 }
2143              
2144 6         20 # set up plotting box
2145             $self->_setwindow;
2146              
2147             # draw labels
2148 6         13 $self->_drawlabels;
2149 6 100 66     23  
2150 3         2 # plot box
  3         6  
2151             plcol0 (1); # set to frame color
2152             plbox ($self->{XTICK}, $self->{NXSUB}, $self->{YTICK}, $self->{NYSUB},
2153             'bc', $self->{YBOX}); # !!! note out of order call
2154 6         80  
2155 6         8 # Now respect TEXTPOSITION setting if TEXTMODE eq 'border'
2156 6         13 # This allows the user to tweak the label placement. D. Hunt 9/4/2007
2157 6         12 my ($side, $disp, $foo, $just) = ('BV', 0.2, 0, 1.0);
2158 107         142 if (defined($self->{TEXTMODE}) && $self->{TEXTMODE} eq 'border') {
2159 107         128 ($side, $disp, $foo, $just) = @{$self->{TEXTPOSITION}};
2160 107         126 }
2161              
2162             # plot labels
2163 6         69 plschr (0, $self->{CHARSIZE} * 0.7); # use smaller characters
2164             my $pos = 0;
2165             my $skip = int($xmax/$maxlab) + 1;
2166 6         67 for (my $i=0;$i<$xmax;$i+=$skip) {
2167             $pos = ((0.5+$i)/$xmax);
2168             my $lab = $$labels[$i];
2169 6         39 plmtex ($disp, $pos, $just, $side, $lab); # !!! out of order parms
2170             }
2171              
2172             plcol0 ($self->{CURRENT_COLOR_IDX}); # set back to line color
2173              
2174             # set line style for plot only (not box)
2175             pllsty ($self->{LINESTYLE});
2176 6 100       10  
2177             # set line width for plot only (not box)
2178 1         2 plwidth ($self->{LINEWIDTH});
2179 1         3  
2180 1         13 #
2181 1         37 ## draw bars
2182 3         8 #
2183 3         34  
2184 3         11 # Stacked bar chart
2185 3         183 if ($color_stack) {
2186 3 50       55  
2187 0         0 my $idx = 0;
2188             my $bh = zeroes($xmax); # base height
2189 3         114 my $w = ones($xmax); # bar width
2190             foreach my $color (@$color_stack) {
2191 3         8 $self->setparm(COLOR => $color);
2192 3         44 plcol0 ($self->{CURRENT_COLOR_IDX}); # set to current box color
2193             my $x = PDL->sequence($xmax)+0.5;
2194             my $y = $values->slice(":,($idx)");
2195 1         10 if ($self->{UNFILLED_BARS}) {
2196             plunfbox1 ($x, $y, $bh, $w);
2197             } else {
2198             plfbox1 ($x, $y, $bh, $w);
2199 5 100       8 }
2200 1         4 $bh += $y; # Increment the base height by the height of the last set of bars
2201             $idx++;
2202 4         17 }
2203              
2204             plcol0 ($self->{CURRENT_COLOR_IDX}); # set back to line color
2205              
2206             } else { # Normal bar chart
2207              
2208 6         2645 if ($self->{UNFILLED_BARS}) {
2209             plunfbox (PDL->sequence($xmax)+0.5, $values);
2210             } else {
2211 6         64 plfbox (PDL->sequence($xmax)+0.5, $values);
2212             }
2213              
2214 6         154 }
2215              
2216             # set line width back
2217             plwidth (0);
2218 13     13 1 37  
2219 13         17 # set char size back
2220             plschr (0, $self->{CHARSIZE});
2221              
2222 13         160 # Flush the PLplot stream.
2223             plflush();
2224             }
2225 13         36  
2226             sub text {
2227             my $self = shift;
2228 13         37 my $text = shift;
2229              
2230             # Set PLplot to right output stream
2231 13         219 plsstrm($self->{STREAMNUMBER});
2232              
2233             # apply options
2234 13 100       33 $self->setparm(@_);
    50          
2235 12         14  
  12         32  
2236 12         33 # set up viewport, subpage, world coordinates
2237             $self->_setwindow;
2238 1         2  
  1         3  
2239 1         137 # set the color according to the color specified in the object
2240             plcol0 ($self->{CURRENT_COLOR_IDX});
2241              
2242             # plot either relative to border, or inside view port
2243 13         370 if ($self->{TEXTMODE} eq 'border') {
2244             my ($side, $disp, $pos, $just) = @{$self->{TEXTPOSITION}};
2245             plmtex ($disp, $pos, $just, $side, $text); # !!! out of order parms
2246             } elsif ($self->{TEXTMODE} eq 'plot') {
2247             my ($x, $y, $dx, $dy, $just) = @{$self->{TEXTPOSITION}};
2248 0     0 0 0 plptex ($x, $y, $dx, $dy, $just, $text);
2249             }
2250              
2251 0         0 # Flush the PLplot stream.
2252             plflush();
2253 0         0 }
2254 0         0  
2255             # Clear the current page. This should only be used with interactive devices!
2256             sub clear {
2257             my $self = shift;
2258              
2259 0     0 0 0 # Set PLplot to right output stream
2260             plsstrm($self->{STREAMNUMBER});
2261              
2262 0         0 plclear();
2263             return;
2264             }
2265 0         0  
2266             # Get mouse click coordinates (OO version). This should only be used with interactive devices!
2267             sub cursor {
2268 0         0 my $self = shift;
2269              
2270             # Set PLplot to right output stream
2271 0         0 plsstrm($self->{STREAMNUMBER});
2272              
2273             # Flush the stream, to make sure the plot is visible & current
2274             plflush();
2275              
2276 148     148 1 1322 # Get the cursor position
2277             my %gin = plGetCursor();
2278              
2279 148         1708 # Return an array with the coordinates of the mouse click
2280             return ($gin{"wX"}, $gin{"wY"}, $gin{"pX"}, $gin{"pY"}, $gin{"dX"}, $gin{"dY"});
2281 148         6117 }
2282              
2283             # Explicitly close a plot and free the object
2284 148         505 sub close {
2285 148         273 my $self = shift;
2286              
2287 148         292 # Set PLplot to right output stream
2288             plsstrm($self->{STREAMNUMBER});
2289              
2290             plend1 ();
2291              
2292             # Return this stream number to the pool.
2293             push (@plplot_stream_pool, $self->{STREAMNUMBER});
2294             delete $self->{STREAMNUMBER};
2295              
2296             return;
2297             }
2298             EOD
2299              
2300             # Used throughout when generating documentation.
2301             my $doc;
2302              
2303             # Necessary includes for .xs file
2304             pp_addhdr(<<'EOH');
2305             #include
2306             #include
2307             #include
2308             #include
2309              
2310             #ifndef PDL /* this is needed for PDL pre-2.058 */
2311             #define PDL PDL_Graphics_PLplot
2312             Core* PDL = NULL; PDL_COMMENT("Structure hold core C functions")
2313             #endif
2314              
2315             #define PLPTR_DEFINE(t) typedef t *t ## Ptr; typedef t *t ## Ptr__OUT;
2316             PLPTR_DEFINE(PLcGrid)
2317             PLPTR_DEFINE(PLcGrid2)
2318             #define PLPTR_RECEIVE_IN(t, v, v_in) t *v = (t *)v_in;
2319             #define PLPTR_RECEIVE_SV(v) ((PLPointer) (SvROK(v) ? SvIV((SV*)SvRV(v)) : (IV)NULL))
2320             EOH
2321              
2322             # The create_low_level_constants function is used to make the #define'd
2323             # constants in plplot.h available in Perl in the form of functions. It
2324             # should be then possible to write code like this:
2325             #
2326             # plParseOpts (\@ARGV, PL_PARSE_SKIP | PL_PARSE_NOPROGRAM);
2327              
2328             sub create_low_level_constants {
2329             my $defn = shift;
2330             my @lines = split (/\n/, $defn);
2331              
2332             foreach my $line (@lines) {
2333             next if (($line =~ /^\#/) or ($line =~ /^\s*$/));
2334             foreach my $const ($line =~ /([^\s]+)/g) {
2335             my $func = <<"EOC";
2336             int
2337             $const()
2338             PROTOTYPE:
2339             CODE:
2340             RETVAL = $const;
2341             OUTPUT:
2342             RETVAL
2343             EOC
2344             pp_addxs ($func);
2345             pp_add_exported ($const);
2346             }
2347             }
2348             }
2349              
2350             create_low_level_constants (<<'EODEF');
2351              
2352             # Definitions used in plParseOpts
2353              
2354             PL_PARSE_PARTIAL
2355             PL_PARSE_FULL
2356             PL_PARSE_QUIET
2357             PL_PARSE_NODELETE
2358             PL_PARSE_SHOWALL
2359             PL_PARSE_OVERRIDE
2360             PL_PARSE_NOPROGRAM
2361             PL_PARSE_NODASH
2362             PL_PARSE_SKIP
2363              
2364             # Macro used (in some cases) to ignore value of argument
2365              
2366             PL_NOTSET
2367              
2368             # Definitions for plmesh and plsurf3d
2369              
2370             DRAW_LINEX
2371             DRAW_LINEY
2372             DRAW_LINEXY
2373             MAG_COLOR
2374             BASE_CONT
2375             TOP_CONT
2376             SURF_CONT
2377             DRAW_SIDES
2378             FACETED
2379             MESH
2380              
2381             # fonts
2382              
2383             PL_FCI_SANS
2384             PL_FCI_MONO
2385              
2386             # Input event (especially keyboard) definitions for use from plplot
2387             # event handlers.
2388              
2389             PLK_BackSpace PLK_Tab PLK_Linefeed PLK_Return PLK_Escape PLK_Delete
2390             PLK_Clear PLK_Pause PLK_Scroll_Lock PLK_Home PLK_Left PLK_Up PLK_Right
2391             PLK_Down PLK_Prior PLK_Next PLK_End PLK_Begin PLK_Select PLK_Print
2392             PLK_Execute PLK_Insert PLK_Undo PLK_Redo PLK_Menu PLK_Find PLK_Cancel
2393             PLK_Help PLK_Break PLK_Mode_switch PLK_script_switch PLK_Num_Lock
2394             PLK_KP_Space PLK_KP_Tab PLK_KP_Enter PLK_KP_F1 PLK_KP_F2 PLK_KP_F3
2395             PLK_KP_F4 PLK_KP_Equal PLK_KP_Multiply PLK_KP_Add PLK_KP_Separator
2396             PLK_KP_Subtract PLK_KP_Decimal PLK_KP_Divide PLK_KP_0 PLK_KP_1
2397             PLK_KP_2 PLK_KP_3 PLK_KP_4 PLK_KP_5 PLK_KP_6 PLK_KP_7 PLK_KP_8
2398             PLK_KP_9 PLK_F1 PLK_F2 PLK_F3 PLK_F4 PLK_F5 PLK_F6 PLK_F7 PLK_F8
2399             PLK_F9 PLK_F10 PLK_F11 PLK_L1 PLK_F12 PLK_L2 PLK_F13 PLK_L3 PLK_F14
2400             PLK_L4 PLK_F15 PLK_L5 PLK_F16 PLK_L6 PLK_F17 PLK_L7 PLK_F18 PLK_L8
2401             PLK_F19 PLK_L9 PLK_F20 PLK_L10 PLK_F21 PLK_R1 PLK_F22 PLK_R2 PLK_F23
2402             PLK_R3 PLK_F24 PLK_R4 PLK_F25 PLK_R5 PLK_F26 PLK_R6 PLK_F27 PLK_R7
2403             PLK_F28 PLK_R8 PLK_F29 PLK_R9 PLK_F30 PLK_R10 PLK_F31 PLK_R11 PLK_F32
2404             PLK_R12 PLK_R13 PLK_F33 PLK_F34 PLK_R14 PLK_F35 PLK_R15 PLK_Shift_L
2405             PLK_Shift_R PLK_Control_L PLK_Control_R PLK_Caps_Lock PLK_Shift_Lock
2406             PLK_Meta_L PLK_Meta_R PLK_Alt_L PLK_Alt_R PLK_Super_L PLK_Super_R
2407             PLK_Hyper_L PLK_Hyper_R
2408              
2409             # Type of gridding algorithm for plgriddata ()
2410              
2411             GRID_CSA
2412             GRID_DTLI
2413             GRID_NNI
2414             GRID_NNIDW
2415             GRID_NNLI
2416             GRID_NNAIDW
2417              
2418             EODEF
2419              
2420             create_low_level_constants (<<'EODEF');
2421              
2422             # Definitions for plslabelfunc
2423              
2424             PL_X_AXIS
2425             PL_Y_AXIS
2426             PL_Z_AXIS
2427              
2428             # Definitions for colorbar
2429              
2430             PL_COLORBAR_SHADE
2431             PL_COLORBAR_SHADE_LABEL
2432             PL_COLORBAR_IMAGE
2433             PL_COLORBAR_GRADIENT
2434             PL_COLORBAR_CAP_NONE
2435             PL_COLORBAR_CAP_LOW
2436             PL_COLORBAR_CAP_HIGH
2437             PL_COLORBAR_LABEL_LEFT
2438             PL_COLORBAR_LABEL_RIGHT
2439             PL_COLORBAR_LABEL_TOP
2440             PL_COLORBAR_LABEL_BOTTOM
2441              
2442             # Definitions for pllegend
2443              
2444             PL_LEGEND_BACKGROUND
2445             PL_LEGEND_BOUNDING_BOX
2446             PL_LEGEND_COLOR_BOX
2447             PL_LEGEND_LINE
2448             PL_LEGEND_NONE
2449             PL_LEGEND_ROW_MAJOR
2450             PL_LEGEND_SYMBOL
2451             PL_LEGEND_TEXT_LEFT
2452             PL_POSITION_BOTTOM
2453             PL_POSITION_INSIDE
2454             PL_POSITION_LEFT
2455             PL_POSITION_OUTSIDE
2456             PL_POSITION_RIGHT
2457             PL_POSITION_SUBPAGE
2458             PL_POSITION_TOP
2459             PL_POSITION_VIEWPORT
2460              
2461             EODEF
2462              
2463             # This code is used to reorder PP_DEF arguments into the
2464             # standard plplot order. This is necessary for some plplot functions
2465             # with a mixture of PDL and non-PDL arguments, since pp_def requires
2466             # all non-PDL (OtherPars) arguments to go at the end of the argument list
2467             sub _make_reorder {
2468             my $name = shift;
2469             <
2470             sub PDL::$name { _reorder('$name', 'PDL::_${name}_int', \$standard_order, \@_) }
2471             EOF
2472             }
2473             pp_addpm (<<'EOPM');
2474             my %REORDER = (
2475             plaxes => [0,1,6,2,3,7,4,5],
2476             plbox => [4,0,1,5,2,3], # 4th arg -> 0th arg, 0th arg -> 1st arg, etc
2477             plbox3 => [6,7,0,1,8,9,2,3,10,11,4,5],
2478             plmtex => [3,0,1,2,4],
2479             plmtex3 => [3,0,1,2,4],
2480             plstart => [2,0,1],
2481             plstripc => [\13,14,15,0..12,16..19],
2482             plmap => [4,5,0..3],
2483             plmeridians => [6,0..5], # 6th PDL arg gets sent as 0th C arg
2484             plshades => [0,10,1..9,11,12],
2485             plshade1 => [0,15,1..14,16,17],
2486             );
2487             sub _reorder {
2488 1897     1897   6061 my ($name, $int_name, $need_reorder) = splice @_, 0, 3;
2489 1897         4175 my $ordering = $REORDER{$name};
2490 1897 50       4829 die "Cannot find argument reordering for $name" if !defined $ordering;
2491 1897         3537 my $missing = @_ != @$ordering;
2492 32     32   388 no strict 'refs';
  32         54  
  32         100856  
2493 1897 100 100     573998 return $int_name->(@_) if !$missing and !$need_reorder;
2494             # either need to insert output ndarray, or reorder, or both
2495 2 100       14 my ($outarg_index) = map ref($_)?$$_:(), @$ordering;
2496 2 50 66     10 confess "$name: wrong number of args but no output arg\n"
2497             if $missing and !defined $outarg_index;
2498 2         8 my @pdl_args = @_;
2499 2 100       4 if (!$need_reorder) {
2500             # args in PDL order; by definition need insert output
2501 1         6 splice @pdl_args, $outarg_index, 0, my $out_ndarray = PDL->null;
2502 1         1009 $int_name->(@pdl_args);
2503 1         8 return $out_ndarray;
2504             }
2505             # need to reorder, might need to insert output
2506 1         2 my $out_ndarray;
2507 1 50       2 if ($missing) {
2508 0         0 $out_ndarray = PDL->null;
2509 0         0 my $i = 0;
2510 0 0       0 @pdl_args = map ref($_) ? $out_ndarray : $pdl_args[$i++], @$ordering;
2511             }
2512 1 50       5 my @pdl_indices = map ref($_)?$$_:$_, @$ordering;
2513 1         17 my @input_indices = 0..$#$ordering;
2514 1         4 @pdl_args[@pdl_indices] = @pdl_args[@input_indices];
2515 1         299 $int_name->(@pdl_args);
2516 1 50       8 $missing ? $out_ndarray : ();
2517             }
2518              
2519             # Routine for users to set normal plplot argument order
2520             sub plplot_use_standard_argument_order {
2521 2     2 0 940 $PDL::Graphics::PLplot::standard_order = shift;
2522             }
2523             EOPM
2524             pp_add_exported('plplot_use_standard_argument_order');
2525              
2526             =head1 LOW-LEVEL INTERFACE
2527             =cut
2528              
2529             pp_addpm (<<'EOPM');
2530              
2531             =pod
2532              
2533             The PDL low-level interface to the PLplot library closely mimics the C API.
2534             Users are referred to the PLplot User's Manual, distributed with the source
2535             PLplot tarball. This manual is also available on-line at the PLplot web
2536             site (L).
2537              
2538             There are three differences in the way the functions are called. The first
2539             one is due to a limitation in the pp_def wrapper of PDL, which forces all
2540             the non-ndarray arguments to be at the end of the arguments list. It is
2541             the case of strings (C) arguments in the C API. This affects the
2542             following functions:
2543              
2544             plaxes
2545             plbox
2546             plbox3
2547             plmtex
2548             plmtex3
2549             plstart
2550             plstripc
2551             plmap
2552             plmeridians
2553             plshades
2554             plshade1
2555              
2556             This difference can be got around by a call to
2557              
2558             plplot_use_standard_argument_order(1);
2559              
2560             This re-arranges the string arguments to their proper/intuitive position
2561             compared with the C plplot interface. This can be restored to its default
2562             by calling:
2563              
2564             plplot_use_standard_argument_order(0);
2565              
2566             The second notable different between the C and the PDL APIs is that many of
2567             the PDL calls do not need arguments to specify the size of the the vectors
2568             and/or matrices being passed. These size parameters are deduced from the
2569             size of the ndarrays, when possible and are just omitted from the C call
2570             when translating it to perl.
2571              
2572             The third difference has to do with output parameters. In C these are
2573             passed in with the input parameters. In the perl interface, they are omitted.
2574             For example:
2575              
2576             C:
2577              
2578             pllegend(&p_legend_width, &p_legend_height,
2579             opt, position, x, y, plot_width, bg_color, bb_color, bb_style, nrow, ncolumn, nlegend,
2580             opt_array,
2581             text_offset, text_scale, text_spacing, text_justification,
2582             text_colors, (const char **)text, box_colors, box_patterns, box_scales, box_line_widths,
2583             line_colors, line_styles, line_widths, symbol_colors, symbol_scales, symbol_numbers, (const char **)symbols);
2584              
2585             perl:
2586              
2587             my ($legend_width, $legend_height) =
2588             pllegend ($position, $opt, $x, $y, $plot_width, $bg_color, $nlegend,
2589             \@opt_array,
2590             $text_offset, $text_scale, $text_spacing, $test_justification,
2591             \@text_colors, \@text, \@box_colors, \@box_patterns, \@box_scales, \@line_colors,
2592             \@line_styles, \@line_widths, \@symbol_colors, \@symbol_scales, \@symbol_numbers, \@symbols);
2593              
2594             Some of the API functions implemented in PDL have other specificities in
2595             comparison with the C API and will be discussed below.
2596              
2597             =cut
2598              
2599             EOPM
2600              
2601             pp_def ('pladv',
2602             NoPthread => 1,
2603             GenericTypes => [D],
2604             Pars => 'int page()',
2605             OtherPars => '',
2606             Code => 'c_pladv($page());'
2607             );
2608              
2609             pp_def ('plaxes',
2610             NoPthread => 1,
2611             GenericTypes => [D],
2612             Pars => 'double xzero();double yzero();double xtick();int nxsub();double ytick();int nysub()',
2613             OtherPars => 'char *xopt;char *yopt',
2614             PMCode => _make_reorder('plaxes'),
2615             Code => 'c_plaxes($xzero(),$yzero(),$COMP(xopt),$xtick(),$nxsub(),$COMP(yopt),$ytick(),$nysub());'
2616             );
2617              
2618             pp_def ('plbin',
2619             NoPthread => 1,
2620             GenericTypes => [D],
2621             Pars => 'int nbin();double x(dima);double y(dima);int center()',
2622             OtherPars => '',
2623             Code => 'c_plbin($nbin(),$P(x),$P(y),$center());'
2624             );
2625              
2626             pp_addxs (<<"EOC");
2627             void
2628             plbop()
2629             CODE:
2630             c_plbop();
2631              
2632             EOC
2633             pp_add_exported('plbop');
2634              
2635             pp_def ('plbox',
2636             NoPthread => 1,
2637             GenericTypes => [D],
2638             Pars => 'double xtick();int nxsub();double ytick();int nysub()',
2639             OtherPars => 'char *xopt;char *yopt',
2640             PMCode => _make_reorder('plbox'),
2641             Code => 'c_plbox($COMP(xopt),$xtick(),$nxsub(),$COMP(yopt),$ytick(),$nysub());'
2642             );
2643              
2644             pp_def ('plbox3',
2645             NoPthread => 1,
2646             GenericTypes => [D],
2647             Pars => 'double xtick();int nsubx();double ytick();int nsuby();double ztick();int nsubz()',
2648             OtherPars => 'char *xopt;char *xlabel;char *yopt;char *ylabel;char *zopt;char *zlabel',
2649             PMCode => _make_reorder('plbox3'),
2650             Code => 'c_plbox3($COMP(xopt),$COMP(xlabel),$xtick(),$nsubx(),$COMP(yopt),$COMP(ylabel),$ytick(),$nsuby(),$COMP(zopt),$COMP(zlabel),$ztick(),$nsubz());'
2651             );
2652              
2653             pp_addxs (<<"EOC");
2654             void
2655             plclear()
2656             CODE:
2657             c_plclear();
2658              
2659             EOC
2660             pp_add_exported('plclear');
2661              
2662             pp_def ('plcol0',
2663             NoPthread => 1,
2664             GenericTypes => [D],
2665             Pars => 'int icolzero()',
2666             OtherPars => '',
2667             Code => 'c_plcol0($icolzero());'
2668             );
2669              
2670             pp_def ('plcol1',
2671             NoPthread => 1,
2672             GenericTypes => [D],
2673             Pars => 'double colone()',
2674             OtherPars => '',
2675             Code => 'c_plcol1($colone());'
2676             );
2677              
2678             pp_def ('plcpstrm',
2679             NoPthread => 1,
2680             GenericTypes => [D],
2681             Pars => 'int iplsr();int flags()',
2682             OtherPars => '',
2683             Code => 'c_plcpstrm($iplsr(),$flags());'
2684             );
2685              
2686             pp_def ('pldid2pc',
2687             NoPthread => 1,
2688             GenericTypes => [D],
2689             Pars => 'double xmin(dima);double ymin(dima);double xmax(dima);double ymax(dima)',
2690             OtherPars => '',
2691             Code => 'pldid2pc($P(xmin),$P(ymin),$P(xmax),$P(ymax));'
2692             );
2693              
2694             pp_def ('pldip2dc',
2695             NoPthread => 1,
2696             GenericTypes => [D],
2697             Pars => 'double xmin(dima);double ymin(dima);double xmax(dima);double ymax(dima)',
2698             OtherPars => '',
2699             Code => 'pldip2dc($P(xmin),$P(ymin),$P(xmax),$P(ymax));'
2700             );
2701              
2702             pp_addxs (<<"EOC");
2703             void
2704             plend()
2705             CODE:
2706             c_plend();
2707              
2708             EOC
2709             pp_add_exported('plend');
2710              
2711             pp_addxs (<<"EOC");
2712             void
2713             plend1()
2714             CODE:
2715             c_plend1();
2716              
2717             EOC
2718             pp_add_exported('plend1');
2719              
2720             pp_def ('plenv',
2721             NoPthread => 1,
2722             GenericTypes => [D],
2723             Pars => 'double xmin();double xmax();double ymin();double ymax();int just();int axis()',
2724             OtherPars => '',
2725             Code => 'c_plenv($xmin(),$xmax(),$ymin(),$ymax(),$just(),$axis());'
2726             );
2727              
2728             pp_def ('plenv0',
2729             NoPthread => 1,
2730             GenericTypes => [D],
2731             Pars => 'double xmin();double xmax();double ymin();double ymax();int just();int axis()',
2732             OtherPars => '',
2733             Code => 'c_plenv0($xmin(),$xmax(),$ymin(),$ymax(),$just(),$axis());'
2734             );
2735              
2736             pp_addxs (<<"EOC");
2737             void
2738             pleop()
2739             CODE:
2740             c_pleop();
2741              
2742             EOC
2743             pp_add_exported('pleop');
2744              
2745             pp_def ('plerrx',
2746             NoPthread => 1,
2747             GenericTypes => [D],
2748             Pars => 'int n();double xmin(dima);double xmax(dima);double y(dima)',
2749             OtherPars => '',
2750             Code => 'c_plerrx($n(),$P(xmin),$P(xmax),$P(y));'
2751             );
2752              
2753             pp_def ('plerry',
2754             NoPthread => 1,
2755             GenericTypes => [D],
2756             Pars => 'int n();double x(dima);double ymin(dima);double ymax(dima)',
2757             OtherPars => '',
2758             Code => 'c_plerry($n(),$P(x),$P(ymin),$P(ymax));'
2759             );
2760              
2761             pp_addxs (<<"EOC");
2762             void
2763             plfamadv()
2764             CODE:
2765             c_plfamadv();
2766              
2767             EOC
2768             pp_add_exported('plfamadv');
2769              
2770             pp_def ('plfill3',
2771             NoPthread => 1,
2772             GenericTypes => [D],
2773             Pars => 'int n();double x(dima);double y(dima);double z(dima)',
2774             OtherPars => '',
2775             Code => 'c_plfill3($n(),$P(x),$P(y),$P(z));'
2776             );
2777              
2778             pp_addxs (<<"EOC");
2779             void
2780             plflush()
2781             CODE:
2782             c_plflush();
2783              
2784             EOC
2785             pp_add_exported('plflush');
2786              
2787             pp_def ('plfont',
2788             NoPthread => 1,
2789             GenericTypes => [D],
2790             Pars => 'int ifont()',
2791             OtherPars => '',
2792             Code => 'c_plfont($ifont());'
2793             );
2794              
2795             pp_def ('plfontld',
2796             NoPthread => 1,
2797             GenericTypes => [D],
2798             Pars => 'int fnt()',
2799             OtherPars => '',
2800             Code => 'c_plfontld($fnt());'
2801             );
2802              
2803             pp_def ('plgchr',
2804             NoPthread => 1,
2805             GenericTypes => [D],
2806             Pars => 'double [o]p_def();double [o]p_ht()',
2807             OtherPars => '',
2808             Code => 'c_plgchr($P(p_def),$P(p_ht));'
2809             );
2810              
2811             pp_def ('plgcompression',
2812             NoPthread => 1,
2813             GenericTypes => [D],
2814             Pars => 'int [o]compression()',
2815             OtherPars => '',
2816             Code => 'c_plgcompression($P(compression));'
2817             );
2818              
2819             pp_def ('plgdidev',
2820             NoPthread => 1,
2821             GenericTypes => [D],
2822             Pars => 'double [o]p_mar();double [o]p_aspect();double [o]p_jx();double [o]p_jy()',
2823             OtherPars => '',
2824             Code => 'c_plgdidev($P(p_mar),$P(p_aspect),$P(p_jx),$P(p_jy));'
2825             );
2826              
2827             pp_def ('plgdiori',
2828             NoPthread => 1,
2829             GenericTypes => [D],
2830             Pars => 'double [o]p_rot()',
2831             OtherPars => '',
2832             Code => 'c_plgdiori($P(p_rot));'
2833             );
2834              
2835             pp_def ('plgdiplt',
2836             NoPthread => 1,
2837             GenericTypes => [D],
2838             Pars => 'double [o]p_xmin();double [o]p_ymin();double [o]p_xmax();double [o]p_ymax()',
2839             OtherPars => '',
2840             Code => 'c_plgdiplt($P(p_xmin),$P(p_ymin),$P(p_xmax),$P(p_ymax));'
2841             );
2842              
2843             pp_def ('plgfam',
2844             NoPthread => 1,
2845             GenericTypes => [D],
2846             Pars => 'int [o]p_fam();int [o]p_num();int [o]p_bmax()',
2847             OtherPars => '',
2848             Code => 'c_plgfam($P(p_fam),$P(p_num),$P(p_bmax));'
2849             );
2850              
2851             pp_def ('plglevel',
2852             NoPthread => 1,
2853             GenericTypes => [D],
2854             Pars => 'int [o]p_level()',
2855             OtherPars => '',
2856             Code => 'c_plglevel($P(p_level));'
2857             );
2858              
2859             pp_def ('plgpage',
2860             NoPthread => 1,
2861             GenericTypes => [D],
2862             Pars => 'double [o]p_xp();double [o]p_yp();int [o]p_xleng();int [o]p_yleng();int [o]p_xoff();int [o]p_yoff()',
2863             OtherPars => '',
2864             Code => 'c_plgpage($P(p_xp),$P(p_yp),$P(p_xleng),$P(p_yleng),$P(p_xoff),$P(p_yoff));'
2865             );
2866              
2867             pp_addxs (<<"EOC");
2868             void
2869             plgra()
2870             CODE:
2871             c_plgra();
2872              
2873             EOC
2874             pp_add_exported('plgra');
2875              
2876             pp_def ('plgspa',
2877             NoPthread => 1,
2878             GenericTypes => [D],
2879             Pars => 'double [o]xmin();double [o]xmax();double [o]ymin();double [o]ymax()',
2880             OtherPars => '',
2881             Code => 'c_plgspa($P(xmin),$P(xmax),$P(ymin),$P(ymax));'
2882             );
2883              
2884             pp_def ('plgvpd',
2885             NoPthread => 1,
2886             GenericTypes => [D],
2887             Pars => 'double [o]p_xmin();double [o]p_xmax();double [o]p_ymin();double [o]p_ymax()',
2888             OtherPars => '',
2889             Code => 'c_plgvpd($P(p_xmin),$P(p_xmax),$P(p_ymin),$P(p_ymax));'
2890             );
2891              
2892             pp_def ('plgvpw',
2893             NoPthread => 1,
2894             GenericTypes => [D],
2895             Pars => 'double [o]p_xmin();double [o]p_xmax();double [o]p_ymin();double [o]p_ymax()',
2896             OtherPars => '',
2897             Code => 'c_plgvpw($P(p_xmin),$P(p_xmax),$P(p_ymin),$P(p_ymax));'
2898             );
2899              
2900             pp_def ('plgxax',
2901             NoPthread => 1,
2902             GenericTypes => [D],
2903             Pars => 'int [o]p_digmax();int [o]p_digits()',
2904             OtherPars => '',
2905             Code => 'c_plgxax($P(p_digmax),$P(p_digits));'
2906             );
2907              
2908             pp_def ('plgyax',
2909             NoPthread => 1,
2910             GenericTypes => [D],
2911             Pars => 'int [o]p_digmax();int [o]p_digits()',
2912             OtherPars => '',
2913             Code => 'c_plgyax($P(p_digmax),$P(p_digits));'
2914             );
2915              
2916             pp_def ('plgzax',
2917             NoPthread => 1,
2918             GenericTypes => [D],
2919             Pars => 'int [o]p_digmax();int [o]p_digits()',
2920             OtherPars => '',
2921             Code => 'c_plgzax($P(p_digmax),$P(p_digits));'
2922             );
2923              
2924             pp_addxs (<<"EOC");
2925             void
2926             plinit()
2927             CODE:
2928             c_plinit();
2929              
2930             EOC
2931             pp_add_exported('plinit');
2932              
2933             pp_def ('pljoin',
2934             NoPthread => 1,
2935             GenericTypes => [D],
2936             Pars => 'double xone();double yone();double xtwo();double ytwo()',
2937             OtherPars => '',
2938             Code => 'c_pljoin($xone(),$yone(),$xtwo(),$ytwo());'
2939             );
2940              
2941             pp_addxs (<<"EOC");
2942             void
2943             pllab(xlabel,ylabel,tlabel)
2944             char * xlabel
2945             char * ylabel
2946             char * tlabel
2947             CODE:
2948             c_pllab(xlabel,ylabel,tlabel);
2949              
2950             EOC
2951             pp_add_exported('pllab');
2952              
2953             pp_def ('pllightsource',
2954             NoPthread => 1,
2955             GenericTypes => [D],
2956             Pars => 'double x();double y();double z()',
2957             OtherPars => '',
2958             Code => 'c_pllightsource($x(),$y(),$z());'
2959             );
2960              
2961             pp_def ('pllsty',
2962             NoPthread => 1,
2963             GenericTypes => [D],
2964             Pars => 'int lin()',
2965             OtherPars => '',
2966             Code => 'c_pllsty($lin());'
2967             );
2968              
2969             pp_def ('plmtex',
2970             NoPthread => 1,
2971             GenericTypes => [D],
2972             Pars => 'double disp();double pos();double just()',
2973             OtherPars => 'char *side;char *text',
2974             PMCode => _make_reorder('plmtex'),
2975             Code => 'c_plmtex($COMP(side),$disp(),$pos(),$just(),$COMP(text));'
2976             );
2977              
2978             pp_def ('plmtex3',
2979             NoPthread => 1,
2980             GenericTypes => [D],
2981             Pars => 'double disp();double pos();double just()',
2982             OtherPars => 'char *side;char *text',
2983             PMCode => _make_reorder('plmtex3'),
2984             Code => 'c_plmtex3($COMP(side),$disp(),$pos(),$just(),$COMP(text));'
2985             );
2986              
2987             pp_def ('plpat',
2988             NoPthread => 1,
2989             GenericTypes => [D],
2990             Pars => 'int nlin();int inc(dima);int del(dima)',
2991             OtherPars => '',
2992             Code => 'c_plpat($nlin(),$P(inc),$P(del));'
2993             );
2994              
2995             pp_def ('plprec',
2996             NoPthread => 1,
2997             GenericTypes => [D],
2998             Pars => 'int setp();int prec()',
2999             OtherPars => '',
3000             Code => 'c_plprec($setp(),$prec());'
3001             );
3002              
3003             pp_def ('plpsty',
3004             NoPthread => 1,
3005             GenericTypes => [D],
3006             Pars => 'int patt()',
3007             OtherPars => '',
3008             Code => 'c_plpsty($patt());'
3009             );
3010              
3011             pp_def ('plptex',
3012             NoPthread => 1,
3013             GenericTypes => [D],
3014             Pars => 'double x();double y();double dx();double dy();double just()',
3015             OtherPars => 'char *text',
3016             Code => 'c_plptex($x(),$y(),$dx(),$dy(),$just(),$COMP(text));'
3017             );
3018              
3019             pp_def ('plptex3',
3020             NoPthread => 1,
3021             GenericTypes => [D],
3022             Pars => 'double x();double y();double z();double dx();double dy();double dz();double sx();double sy();double sz();double just()',
3023             OtherPars => 'char *text',
3024             Code => 'c_plptex3($x(),$y(),$z(),$dx(),$dy(),$dz(),$sx(),$sy(),$sz(),$just(),$COMP(text));'
3025             );
3026              
3027             pp_addxs (<<"EOC");
3028             void
3029             plreplot()
3030             CODE:
3031             c_plreplot();
3032              
3033             EOC
3034             pp_add_exported('plreplot');
3035              
3036             pp_def ('plschr',
3037             NoPthread => 1,
3038             GenericTypes => [D],
3039             Pars => 'double def();double scale()',
3040             OtherPars => '',
3041             Code => 'c_plschr($def(),$scale());'
3042             );
3043              
3044             pp_def ('plscmap0n',
3045             NoPthread => 1,
3046             GenericTypes => [D],
3047             Pars => 'int ncolzero()',
3048             OtherPars => '',
3049             Code => 'c_plscmap0n($ncolzero());'
3050             );
3051              
3052             pp_def ('plscmap1n',
3053             NoPthread => 1,
3054             GenericTypes => [D],
3055             Pars => 'int ncolone()',
3056             OtherPars => '',
3057             Code => 'c_plscmap1n($ncolone());'
3058             );
3059              
3060             pp_def ('plscol0',
3061             NoPthread => 1,
3062             GenericTypes => [D],
3063             Pars => 'int icolzero();int r();int g();int b()',
3064             OtherPars => '',
3065             Code => 'c_plscol0($icolzero(),$r(),$g(),$b());'
3066             );
3067              
3068             pp_def ('plscolbg',
3069             NoPthread => 1,
3070             GenericTypes => [D],
3071             Pars => 'int r();int g();int b()',
3072             OtherPars => '',
3073             Code => 'c_plscolbg($r(),$g(),$b());'
3074             );
3075              
3076             pp_def ('plscolor',
3077             NoPthread => 1,
3078             GenericTypes => [D],
3079             Pars => 'int color()',
3080             OtherPars => '',
3081             Code => 'c_plscolor($color());'
3082             );
3083              
3084             pp_def ('plscompression',
3085             NoPthread => 1,
3086             GenericTypes => [D],
3087             Pars => 'int compression()',
3088             OtherPars => '',
3089             Code => 'c_plscompression($compression());'
3090             );
3091              
3092             pp_addxs (<<"EOC");
3093             void
3094             plsdev(devname)
3095             char * devname
3096             CODE:
3097             c_plsdev(devname);
3098              
3099             EOC
3100             pp_add_exported('plsdev');
3101              
3102             # key: function name
3103             # value: description of group of devices returned
3104             my %plgDevsFuncs = (
3105             plgFileDevs => 'file-oriented',
3106             plgDevs => 'all',
3107             );
3108             for my $func (sort keys %plgDevsFuncs) {
3109             pp_addpm (<
3110             =head2 $func
3111              
3112             =for sig
3113              
3114             \$devices = $func ()
3115              
3116             =for ref
3117              
3118             Returns a HashRef of $plgDevsFuncs{$func} device names (key)
3119             and their menu strings (value).
3120              
3121             =cut
3122             EOPM
3123              
3124             pp_addxs (<<"EOC");
3125             SV*
3126             $func ()
3127             INIT:
3128             const int ndev_alloc = 100; /* per docs, "20 or so is plenty" */
3129             const char **menustr = (const char**) malloc(ndev_alloc * sizeof(char*));
3130             const char **devname = (const char**) malloc(ndev_alloc * sizeof(char*));
3131             int ndev = ndev_alloc;
3132             CODE:
3133             $func (&menustr, &devname, &ndev);
3134             HV* hv = newHV();
3135             int i;
3136             for( i = 0; i < ndev; i++ ) {
3137             SV* menustr_sv = newSVpvn(menustr[i], strlen(menustr[i]));
3138             if( NULL == hv_store(hv, devname[i], strlen(devname[i]), menustr_sv, 0) ) {
3139             sv_free(menustr_sv);
3140             croak("Could not return devices");
3141             }
3142             }
3143             RETVAL = newRV_noinc((SV*) hv);
3144             OUTPUT:
3145             RETVAL
3146             CLEANUP:
3147             free(menustr);
3148             free(devname);
3149             EOC
3150             pp_add_exported($func);
3151             }
3152              
3153             pp_def ('plsdidev',
3154             NoPthread => 1,
3155             GenericTypes => [D],
3156             Pars => 'double mar();double aspect();double jx();double jy()',
3157             OtherPars => '',
3158             Code => 'c_plsdidev($mar(),$aspect(),$jx(),$jy());'
3159             );
3160              
3161             pp_def ('plsdimap',
3162             NoPthread => 1,
3163             GenericTypes => [D],
3164             Pars => 'int dimxmin();int dimxmax();int dimymin();int dimymax();double dimxpmm();double dimypmm()',
3165             OtherPars => '',
3166             Code => 'c_plsdimap($dimxmin(),$dimxmax(),$dimymin(),$dimymax(),$dimxpmm(),$dimypmm());'
3167             );
3168              
3169             pp_def ('plsdiori',
3170             NoPthread => 1,
3171             GenericTypes => [D],
3172             Pars => 'double rot()',
3173             OtherPars => '',
3174             Code => 'c_plsdiori($rot());'
3175             );
3176              
3177             pp_def ('plsdiplt',
3178             NoPthread => 1,
3179             GenericTypes => [D],
3180             Pars => 'double xmin();double ymin();double xmax();double ymax()',
3181             OtherPars => '',
3182             Code => 'c_plsdiplt($xmin(),$ymin(),$xmax(),$ymax());'
3183             );
3184              
3185             pp_def ('plsdiplz',
3186             NoPthread => 1,
3187             GenericTypes => [D],
3188             Pars => 'double xmin();double ymin();double xmax();double ymax()',
3189             OtherPars => '',
3190             Code => 'c_plsdiplz($xmin(),$ymin(),$xmax(),$ymax());'
3191             );
3192              
3193             pp_def ('pl_setcontlabelparam',
3194             NoPthread => 1,
3195             GenericTypes => [D],
3196             Pars => 'double offset();double size();double spacing();int active()',
3197             OtherPars => '',
3198             Code => 'c_pl_setcontlabelparam($offset(),$size(),$spacing(),$active());'
3199             );
3200              
3201             pp_def ('pl_setcontlabelformat',
3202             NoPthread => 1,
3203             GenericTypes => [D],
3204             Pars => 'int lexp();int sigdig()',
3205             OtherPars => '',
3206             Code => 'c_pl_setcontlabelformat($lexp(),$sigdig());'
3207             );
3208              
3209             pp_def ('plsfam',
3210             NoPthread => 1,
3211             GenericTypes => [D],
3212             Pars => 'int fam();int num();int bmax()',
3213             OtherPars => '',
3214             Code => 'c_plsfam($fam(),$num(),$bmax());'
3215             );
3216              
3217             pp_addxs (<<"EOC");
3218             void
3219             plsfnam(fnam)
3220             char * fnam
3221             CODE:
3222             c_plsfnam(fnam);
3223              
3224             EOC
3225             pp_add_exported('plsfnam');
3226              
3227             pp_def ('plsmaj',
3228             NoPthread => 1,
3229             GenericTypes => [D],
3230             Pars => 'double def();double scale()',
3231             OtherPars => '',
3232             Code => 'c_plsmaj($def(),$scale());'
3233             );
3234              
3235             pp_def ('plsmin',
3236             NoPthread => 1,
3237             GenericTypes => [D],
3238             Pars => 'double def();double scale()',
3239             OtherPars => '',
3240             Code => 'c_plsmin($def(),$scale());'
3241             );
3242              
3243             pp_def ('plsori',
3244             NoPthread => 1,
3245             GenericTypes => [D],
3246             Pars => 'int ori()',
3247             OtherPars => '',
3248             Code => 'c_plsori($ori());'
3249             );
3250              
3251             pp_def ('plspage',
3252             NoPthread => 1,
3253             GenericTypes => [D],
3254             Pars => 'double xp();double yp();int xleng();int yleng();int xoff();int yoff()',
3255             OtherPars => '',
3256             Code => 'c_plspage($xp(),$yp(),$xleng(),$yleng(),$xoff(),$yoff());'
3257             );
3258              
3259             pp_def ('plspause',
3260             NoPthread => 1,
3261             GenericTypes => [D],
3262             Pars => 'int pause()',
3263             OtherPars => '',
3264             Code => 'c_plspause($pause());'
3265             );
3266              
3267             pp_def ('plsstrm',
3268             NoPthread => 1,
3269             GenericTypes => [D],
3270             Pars => 'int strm()',
3271             OtherPars => '',
3272             Code => 'c_plsstrm($strm());'
3273             );
3274              
3275             pp_def ('plssub',
3276             NoPthread => 1,
3277             GenericTypes => [D],
3278             Pars => 'int nx();int ny()',
3279             OtherPars => '',
3280             Code => 'c_plssub($nx(),$ny());'
3281             );
3282              
3283             pp_def ('plssym',
3284             NoPthread => 1,
3285             GenericTypes => [D],
3286             Pars => 'double def();double scale()',
3287             OtherPars => '',
3288             Code => 'c_plssym($def(),$scale());'
3289             );
3290              
3291             pp_def ('plstar',
3292             NoPthread => 1,
3293             GenericTypes => [D],
3294             Pars => 'int nx();int ny()',
3295             OtherPars => '',
3296             Code => 'c_plstar($nx(),$ny());'
3297             );
3298              
3299             pp_def ('plstart',
3300             NoPthread => 1,
3301             GenericTypes => [D],
3302             Pars => 'int nx();int ny()',
3303             OtherPars => 'char *devname',
3304             PMCode => _make_reorder('plstart'),
3305             Code => 'c_plstart($COMP(devname),$nx(),$ny());'
3306             );
3307              
3308             pp_def ('plstripa',
3309             NoPthread => 1,
3310             GenericTypes => [D],
3311             Pars => 'int id();int pen();double x();double y()',
3312             OtherPars => '',
3313             Code => 'c_plstripa($id(),$pen(),$x(),$y());'
3314             );
3315              
3316             pp_def ('plstripd',
3317             NoPthread => 1,
3318             GenericTypes => [D],
3319             Pars => 'int id()',
3320             OtherPars => '',
3321             Code => 'c_plstripd($id());'
3322             );
3323              
3324             pp_def ('plsvpa',
3325             NoPthread => 1,
3326             GenericTypes => [D],
3327             Pars => 'double xmin();double xmax();double ymin();double ymax()',
3328             OtherPars => '',
3329             Code => 'c_plsvpa($xmin(),$xmax(),$ymin(),$ymax());'
3330             );
3331              
3332             pp_def ('plsxax',
3333             NoPthread => 1,
3334             GenericTypes => [D],
3335             Pars => 'int digmax();int digits()',
3336             OtherPars => '',
3337             Code => 'c_plsxax($digmax(),$digits());'
3338             );
3339              
3340             pp_def ('plsxwin',
3341             NoPthread => 1,
3342             GenericTypes => [D],
3343             Pars => 'int window_id()',
3344             OtherPars => '',
3345             Code => 'plsxwin($window_id());'
3346             );
3347              
3348             pp_def ('plsyax',
3349             NoPthread => 1,
3350             GenericTypes => [D],
3351             Pars => 'int digmax();int digits()',
3352             OtherPars => '',
3353             Code => 'c_plsyax($digmax(),$digits());'
3354             );
3355              
3356             pp_def ('plszax',
3357             NoPthread => 1,
3358             GenericTypes => [D],
3359             Pars => 'int digmax();int digits()',
3360             OtherPars => '',
3361             Code => 'c_plszax($digmax(),$digits());'
3362             );
3363              
3364             pp_addxs (<<"EOC");
3365             void
3366             pltext()
3367             CODE:
3368             c_pltext();
3369              
3370             EOC
3371             pp_add_exported('pltext');
3372              
3373             pp_def ('plvasp',
3374             NoPthread => 1,
3375             GenericTypes => [D],
3376             Pars => 'double aspect()',
3377             OtherPars => '',
3378             Code => 'c_plvasp($aspect());'
3379             );
3380              
3381             pp_def ('plvpas',
3382             NoPthread => 1,
3383             GenericTypes => [D],
3384             Pars => 'double xmin();double xmax();double ymin();double ymax();double aspect()',
3385             OtherPars => '',
3386             Code => 'c_plvpas($xmin(),$xmax(),$ymin(),$ymax(),$aspect());'
3387             );
3388              
3389             pp_def ('plvpor',
3390             NoPthread => 1,
3391             GenericTypes => [D],
3392             Pars => 'double xmin();double xmax();double ymin();double ymax()',
3393             OtherPars => '',
3394             Code => 'c_plvpor($xmin(),$xmax(),$ymin(),$ymax());'
3395             );
3396              
3397             pp_addxs (<<"EOC");
3398             void
3399             plvsta()
3400             CODE:
3401             c_plvsta();
3402             EOC
3403              
3404             pp_add_exported('plvsta');
3405              
3406             pp_def ('plw3d',
3407             NoPthread => 1,
3408             GenericTypes => [D],
3409             Pars => 'double basex();double basey();double height();double xminzero();double xmaxzero();double yminzero();double ymaxzero();double zminzero();double zmaxzero();double alt();double az()',
3410             OtherPars => '',
3411             Code => 'c_plw3d($basex(),$basey(),$height(),$xminzero(),$xmaxzero(),$yminzero(),$ymaxzero(),$zminzero(),$zmaxzero(),$alt(),$az());'
3412             );
3413              
3414             pp_def ('plwidth',
3415             NoPthread => 1,
3416             GenericTypes => [D],
3417             Pars => 'int width()',
3418             OtherPars => '',
3419             Code => 'plwidth($width());'
3420             );
3421              
3422             pp_def ('plwind',
3423             NoPthread => 1,
3424             GenericTypes => [D],
3425             Pars => 'double xmin();double xmax();double ymin();double ymax()',
3426             OtherPars => '',
3427             Code => 'c_plwind($xmin(),$xmax(),$ymin(),$ymax());'
3428             );
3429              
3430             pp_addxs (<<"EOC");
3431             void
3432             plsetopt(opt,optarg)
3433             char * opt
3434             char * optarg
3435             CODE:
3436             c_plsetopt(opt,optarg);
3437              
3438             EOC
3439             pp_add_exported('plsetopt');
3440              
3441             pp_def ('plP_gpixmm',
3442             NoPthread => 1,
3443             GenericTypes => [D],
3444             Pars => 'double p_x(dima);double p_y(dima)',
3445             OtherPars => '',
3446             Code => 'plP_gpixmm($P(p_x),$P(p_y));'
3447             );
3448              
3449             pp_def ('plscolbga',
3450             NoPthread => 1,
3451             GenericTypes => [D],
3452             Pars => 'int r();int g();int b();double a()',
3453             OtherPars => '',
3454             Code => 'c_plscolbga($r(),$g(),$b(),$a());'
3455             );
3456              
3457             pp_def ('plscol0a',
3458             NoPthread => 1,
3459             GenericTypes => [D],
3460             Pars => 'int icolzero();int r();int g();int b();double a()',
3461             OtherPars => '',
3462             Code => 'c_plscol0a($icolzero(),$r(),$g(),$b(),$a());'
3463             );
3464              
3465             # C routine to draw lines with gaps. This is useful for map continents and other things.
3466             =head2 plline
3467             =cut
3468              
3469             $doc = <<'EOD';
3470             =for ref
3471              
3472             Draws line segments along (x1,y1)->(x2,y2)->(x3,y3)->...
3473              
3474             =for bad
3475              
3476             If the nth value of either x or y are bad, then it will be skipped, breaking
3477             the line. In this way, you can specify multiple line segments with a single
3478             pair of x and y ndarrays.
3479              
3480             The usage is straight-forward:
3481              
3482             =for usage
3483              
3484             plline($x, $y);
3485              
3486             For example:
3487              
3488             =for example
3489              
3490             # Draw a sine wave
3491             $x = sequence(100)/10;
3492             $y = sin($x);
3493              
3494             # Draws the sine wave:
3495             plline($x, $y);
3496              
3497             # Set values above 3/4 to 'bad', effectively drawing a bunch of detached,
3498             # capped waves
3499             $y->setbadif($y > 3/4);
3500             plline($x, $y);
3501              
3502             =cut
3503             EOD
3504              
3505             pp_def ('plline',
3506             NoPthread => 1,
3507             Pars => 'x(n); y(n)',
3508             GenericTypes => [D],
3509             HandleBad => 1,
3510             NoBadifNaN => 1,
3511             Code => 'c_plline($SIZE(n),$P(x),$P(y));',
3512             BadCode => 'int i;
3513             int j;
3514             for (i=1;i<$SIZE(n);i++) {
3515             j = i-1; /* PP does not like using i-1 in a PDL ref. Use j instead. */
3516             if ($ISGOOD(x(n=>i)) && $ISGOOD(x(n=>j)) && $ISGOOD(y(n=>i)) && $ISGOOD(y(n=>j))) {
3517             c_pljoin ($x(n=>j), $y(n=>j), $x(n=>i), $y(n=>i));
3518             }
3519             }',
3520             Doc => $doc,
3521             );
3522              
3523             pp_def ('plpath',
3524             NoPthread => 1,
3525             Pars => 'int n(); x1(); x2(); y1(); y2()',
3526             GenericTypes => [D],
3527             HandleBad => 0,
3528             NoBadifNaN => 1,
3529             Code => 'c_plpath($n(), $x1(), $x2(), $y1(), $y2());',
3530             );
3531              
3532             =head2 plcolorpoints
3533             =cut
3534              
3535             $doc = <<'EOD';
3536             =for ref
3537              
3538             PDL-specific: Implements what amounts to a threaded version of plsym.
3539              
3540             =for bad
3541              
3542             Bad values for z are simply skipped; all other bad values are not processed.
3543              
3544             In the following usage, all of the ndarrays must have the same dimensions:
3545              
3546             =for usage
3547              
3548             plcolorpoints($x, $y, $z, $symbol_index, $minz, $maxz)
3549              
3550             For example:
3551              
3552             =for example
3553              
3554             # Generate a parabola some points
3555             my $x = sequence(30) / 3; # Regular sampling
3556             my $y = $x**2; # Parabolic y
3557             my $z = 30 - $x**3; # Cubic coloration
3558             my $symbols = floor($x); # Use different symbols for each 1/3 of the plot
3559             # These should be integers.
3560              
3561             plcolorpoints($x, $y, $z, $symbols, -5, 20); # Thread over everything
3562             plcolorpoints($x, $y, 1, 1, -1, 2); # same color and symbol for all
3563              
3564             =cut
3565             EOD
3566              
3567             # C routine to draw points with a color scale
3568             pp_def ('plcolorpoints',
3569             NoPthread => 1,
3570             Pars => 'x(n); y(n); z(n); int sym(); minz(); maxz()',
3571             GenericTypes => [D],
3572             HandleBad => 1,
3573             Code => 'int i;
3574             int j;
3575             int ns = $SIZE(n);
3576             PLFLT zrange, ci;
3577              
3578             zrange = $maxz() - $minz();
3579              
3580             for (i=0;i
3581             ci = (zrange == 0.0) ? 0.5 : ($z(n=>i) - $minz()) / zrange; /* get color idx in 0-1 range */
3582             if (ci < 0) ci = 0; /* enforce bounds */
3583             if (ci > 1) ci = 1;
3584             c_plcol1 (ci); /* set current color */
3585             c_plsym (1, &$x(n=>i), &$y(n=>i), $sym()); /* plot it */
3586             }',
3587             BadCode =>
3588             'int i;
3589             int j;
3590             int ns = $SIZE(n);
3591             PLFLT zrange, ci;
3592              
3593             zrange = $maxz() - $minz();
3594              
3595             for (i=0;i
3596             if ($ISBAD(z(n=>i))) continue;
3597             ci = (zrange == 0.0) ? 0.5 : ($z(n=>i) - $minz()) / zrange; /* get color idx in 0-1 range */
3598             if (ci < 0) ci = 0; /* enforce bounds */
3599             if (ci > 1) ci = 1;
3600             c_plcol1 (ci); /* set current color */
3601             c_plsym (1, &$x(n=>i), &$y(n=>i), $sym()); /* plot it */
3602              
3603             }',
3604             Doc => $doc,
3605             );
3606              
3607             pp_def ('plsmem',
3608             NoPthread => 1,
3609             GenericTypes => [B],
3610             Pars => 'int maxx();int maxy();image(3,x,y)',
3611             Code => 'c_plsmem($maxx(),$maxy(),$P(image));'
3612             );
3613              
3614             pp_def ('plfbox',
3615             NoPthread => 1,
3616             Pars => 'xo(); yo()',
3617             GenericTypes => [D],
3618             Doc => 'Box drawing primitive, taken from PLPLOT bar graph example',
3619             Code => 'PLFLT x[4], y[4];
3620             x[0] = $xo() - 0.5;
3621             y[0] = 0.;
3622             x[1] = $xo() - 0.5;
3623             y[1] = $yo();
3624             x[2] = $xo() + 0.5;
3625             y[2] = $yo();
3626             x[3] = $xo() + 0.5;
3627             y[3] = 0.;
3628             plfill(4, x, y);',
3629             );
3630              
3631             pp_def ('plfbox1',
3632             NoPthread => 1,
3633             Pars => 'xo(); yo(); bh(); w()',
3634             GenericTypes => [D],
3635             Doc => 'Box drawing primitive that allows specifying base height and width in addition to offset and height',
3636             Code => 'PLFLT x[4], y[4];
3637             x[0] = $xo() - ( 0.5 * $w() );
3638             y[0] = $bh();
3639             x[1] = $xo() - ( 0.5 * $w() );
3640             y[1] = $bh() + $yo();
3641             x[2] = $xo() + ( 0.5 * $w() );
3642             y[2] = $bh() + $yo();
3643             x[3] = $xo() + ( 0.5 * $w() );
3644             y[3] = $bh();
3645             plfill(4, x, y);',
3646             );
3647              
3648             pp_def ('plunfbox',
3649             NoPthread => 1,
3650             Pars => 'xo(); yo()',
3651             GenericTypes => [D],
3652             Doc => 'Similar box drawing primitive, but without fill (just draw outline of box)',
3653             Code => 'PLFLT x[4], y[4];
3654             x[0] = $xo() - 0.5;
3655             y[0] = 0.;
3656             x[1] = $xo() - 0.5;
3657             y[1] = $yo();
3658             x[2] = $xo() + 0.5;
3659             y[2] = $yo();
3660             x[3] = $xo() + 0.5;
3661             y[3] = 0.;
3662             plline(4, x, y);',
3663             );
3664              
3665             pp_def ('plunfbox1',
3666             NoPthread => 1,
3667             Pars => 'xo(); yo(); bh(); w()',
3668             GenericTypes => [D],
3669             Doc => 'Box drawing primitive that allows specifying base height and width in addition to offset and height',
3670             Code => 'PLFLT x[4], y[4];
3671             x[0] = $xo() - ( 0.5 * $w() );
3672             y[0] = $bh();
3673             x[1] = $xo() - ( 0.5 * $w() );
3674             y[1] = $bh() + $yo();
3675             x[2] = $xo() + ( 0.5 * $w() );
3676             y[2] = $bh() + $yo();
3677             x[3] = $xo() + ( 0.5 * $w() );
3678             y[3] = $bh();
3679             plline(4, x, y);',
3680             );
3681              
3682             pp_def ('plParseOpts',
3683             NoPthread => 1,
3684             GenericTypes => [D],
3685             Pars => 'int [o] retval()',
3686             OtherPars => 'SV* argv; int mode',
3687             Doc => 'Parse PLplot options given in @ARGV-like arrays',
3688             Code => '
3689             SV* sv = $COMP (argv);
3690             SV* dummy;
3691             AV* arr;
3692             int argc, newargc, i, retval;
3693             char** args;
3694              
3695             if ( !(SvROK (sv) && SvTYPE (SvRV (sv)) == SVt_PVAV)) {
3696             barf("plParseOpts requires an array ref");
3697             }
3698              
3699             arr = (AV*) SvRV (sv);
3700             newargc = argc = av_len (arr) + 1;
3701             if (argc > 0) {
3702             Newx(args, argc, char *);
3703             if(args == NULL) $CROAK("Failed to allocate memory in plParseOpts");
3704              
3705             for (i = 0; i < argc; i++) {
3706             STRLEN len;
3707             args[i] = SvPV (* av_fetch (arr, i, 0), len);
3708             }
3709              
3710             $retval() = c_plparseopts (&newargc, (PLCHAR_NC_MATRIX)args, $COMP (mode));
3711              
3712             for (i = 0; i < newargc; i++)
3713             av_push (arr, newSVpv (args[i], 0));
3714              
3715             for (i = 0; i < argc; i++)
3716             dummy = av_shift (arr); /* assign to dummy to suppress compile warning */
3717              
3718             Safefree (args);
3719             }
3720             ',
3721             );
3722              
3723             pp_def ('plpoin',
3724             NoPthread => 1,
3725             Pars => 'x(n); y(n); int code()',
3726             GenericTypes => [D],
3727             Doc => 'Plots a character at the specified points',
3728             Code => 'c_plpoin($SIZE(n),$P(x),$P(y),$code());'
3729             );
3730              
3731             pp_def ('plpoin3',
3732             NoPthread => 1,
3733             Pars => 'x(n); y(n); z(n); int code()',
3734             GenericTypes => [D],
3735             Doc => 'Plots a character at the specified points in 3 space',
3736             Code => 'c_plpoin3($SIZE(n),$P(x),$P(y),$P(z),$code());'
3737             );
3738              
3739             pp_def ('plline3',
3740             NoPthread => 1,
3741             Pars => 'x(n); y(n); z(n)',
3742             GenericTypes => [D],
3743             Doc => 'Draw a line in 3 space',
3744             Code => 'c_plline3($SIZE(n),$P(x),$P(y),$P(z));'
3745             );
3746              
3747             pp_def ('plpoly3',
3748             NoPthread => 1,
3749             Pars => 'x(n); y(n); z(n); int draw(m); int ifcc()',
3750             GenericTypes => [D],
3751             Doc => 'Draws a polygon in 3 space',
3752             Code => 'c_plpoly3($SIZE(n),$P(x),$P(y),$P(z),$P(draw),$ifcc());'
3753             );
3754              
3755             pp_def ('plhist',
3756             NoPthread => 1,
3757             Pars => 'data(n); datmin(); datmax(); int nbin(); int oldwin()',
3758             GenericTypes => [D],
3759             Doc => 'Plot a histogram from unbinned data',
3760             Code => 'c_plhist($SIZE(n),$P(data),$datmin(),$datmax(),$nbin(),$oldwin());'
3761             );
3762              
3763             pp_def ('plfill',
3764             NoPthread => 1,
3765             Pars => 'x(n); y(n)',
3766             GenericTypes => [D],
3767             Doc => 'Area fill',
3768             Code => 'c_plfill($SIZE(n),$P(x),$P(y));'
3769             );
3770              
3771             pp_def ('plgradient',
3772             NoPthread => 1,
3773             Pars => 'x(n); y(n); angle();',
3774             GenericTypes => [D],
3775             Doc => 'Area fill with color gradient',
3776             Code => 'c_plgradient($SIZE(n),$P(x),$P(y),$angle());'
3777             );
3778              
3779             pp_def ('plsym',
3780             NoPthread => 1,
3781             Pars => 'x(n); y(n); int code()',
3782             GenericTypes => [D],
3783             Doc => 'Plots a symbol at the specified points',
3784             Code => 'c_plsym($SIZE(n),$P(x),$P(y),$code());'
3785             );
3786              
3787             pp_def ('plsurf3d',
3788             NoPthread => 1,
3789             Pars => 'x(nx); y(ny); z(nx,ny); int opt(); clevel(nlevel);',
3790             GenericTypes => [D],
3791             Doc => 'Plot shaded 3-d surface plot',
3792             Code => '
3793             int i, j, size_x, size_y;
3794             PLFLT** zz;
3795              
3796             size_x = $SIZE(nx);
3797             size_y = $SIZE(ny);
3798             plAlloc2dGrid (&zz, size_x, size_y);
3799             for (i = 0; i < size_x; i++)
3800             for (j = 0; j < size_y; j++)
3801             zz[i][j] = $z(nx => i, ny => j);
3802             c_plsurf3d ($P(x), $P(y), (const PLFLT **)zz, size_x, size_y, $opt(),
3803             $P(clevel), $SIZE(nlevel));
3804             plFree2dGrid (zz, size_x, size_y);'
3805             );
3806              
3807             pp_def('plsurf3dl',
3808             NoPthread => 1,
3809             Pars => 'x(nx); y(ny); z(nx,ny); int opt(); clevel(nlevel); int indexxmin(); int indexxmax(); int indexymin(nx); int indexymax(nx);',
3810             GenericTypes => [D],
3811             Doc => 'Plot shaded 3-d surface plot with limits',
3812             Code => '
3813             int i, j, size_x, size_y;
3814             PLFLT** zz;
3815             size_x = $SIZE(nx);
3816             size_y = $SIZE(ny);
3817             plAlloc2dGrid (&zz, size_x, size_y);
3818             for (i = 0; i < size_x; i++)
3819             for (j = 0; j < size_y; j++)
3820             zz[i][j] = $z(nx => i, ny => j);
3821             c_plsurf3dl(
3822             $P(x), $P(y), (const PLFLT **) zz, size_x, size_y, $opt(),
3823             $P(clevel), $SIZE(nlevel),
3824             $indexxmin(), $indexxmax(), $P(indexymin), $P(indexymax)
3825             );
3826             plFree2dGrid (zz, size_x, size_y);'
3827             );
3828              
3829             pp_def ('plstyl',
3830             NoPthread => 1,
3831             Pars => 'int mark(nms); int space(nms)',
3832             GenericTypes => [D],
3833             Doc => 'Set line style',
3834             Code => 'c_plstyl ($SIZE(nms), $P(mark), $P(space));'
3835             );
3836              
3837             # PLplot standard random number generation. Using this
3838             # helps to keep the demo plots identical.
3839              
3840             pp_def ('plseed',
3841             NoPthread => 1,
3842             Pars => 'int seed()',
3843             Code => 'unsigned int useed = (unsigned int)$seed(); c_plseed(useed);'
3844             );
3845              
3846             pp_def ('plrandd',
3847             NoPthread => 1,
3848             Pars => 'double [o]rand()',
3849             Code => '$rand() = c_plrandd();'
3850             );
3851              
3852             # pltr0: Identity transformation
3853             # pltr1: Linear interpolation from singly dimensioned coord arrays
3854             # Linear interpolation from doubly dimensioned coord arrays
3855              
3856             for my $t ([qw(pltr0 SV*)], [qw(pltr1 PLcGridPtr)], [qw(pltr2 PLcGrid2Ptr)]) {
3857             my ($func, $type) = @$t;
3858             pp_addxs (<<"EOC");
3859             void
3860             $func(x, y, grid)
3861             double x
3862             double y
3863             $type grid
3864             PPCODE:
3865             PLFLT tx, ty;
3866             $func(x, y, &tx, &ty, (PLPointer) grid);
3867             EXTEND (SP, 2);
3868             PUSHs(sv_2mortal(newSVnv((double) tx)));
3869             PUSHs(sv_2mortal(newSVnv((double) ty)));
3870             EOC
3871             pp_add_exported($func);
3872             }
3873              
3874             pp_def ('plAllocGrid',
3875             NoPthread => 1,
3876             Pars => 'double xg(nx); double yg(ny)',
3877             OtherPars => '[o] PLcGridPtr__OUT grid',
3878             GenericTypes => [D],
3879             Doc => 'Allocates a PLcGrid object for use in pltr1',
3880             Code => '
3881             PLcGrid *grid;
3882             int i, nx = $SIZE(nx), ny = $SIZE(ny);
3883             Newx(grid, 1, PLcGrid);
3884             if(grid == NULL) $CROAK("Failed to allocate memory for grid");
3885             Newxz(grid->xg, nx, PLFLT);
3886             if(grid->xg == NULL) $CROAK("Failed to allocate memory for grid->xg");
3887             Newxz(grid->yg, ny, PLFLT);
3888             if(grid->yg == NULL) $CROAK("Failed to allocate memory for grid->yg");
3889             grid->nx = nx;
3890             grid->ny = ny;
3891             for (i = 0; i < nx; i++)
3892             grid->xg[i] = $xg(nx => i);
3893             for (i = 0; i < ny; i++)
3894             grid->yg[i] = $yg(ny => i);
3895             $COMP(grid) = (PLcGridPtr__OUT)grid;'
3896             );
3897              
3898              
3899             # Free a PLcGrid object
3900              
3901             pp_addxs (<<"EOC");
3902             void
3903             plFreeGrid (pg)
3904             PLcGridPtr pg
3905             PPCODE:
3906             PLPTR_RECEIVE_IN(PLcGrid, grid, pg)
3907             Safefree(grid->xg);
3908             Safefree(grid->yg);
3909             Safefree(grid);
3910             EOC
3911              
3912             pp_add_exported (plFreeGrid);
3913              
3914             pp_def ('plAlloc2dGrid',
3915             NoPthread => 1,
3916             Pars => 'double xg(nx,ny); double yg(nx,ny)',
3917             OtherPars => '[o] PLcGrid2Ptr__OUT grid',
3918             GenericTypes => [D],
3919             Doc => 'Allocates a PLcGrid2 object for use in pltr2',
3920             Code => '
3921             int i, j, nx = $SIZE(nx), ny = $SIZE(ny);
3922             PLcGrid2 *grid = (PLcGrid2*) malloc(sizeof(PLcGrid2));
3923             if (!grid) $CROAK("Failed to allocate memory for grid");
3924             plAlloc2dGrid(&(grid->xg), nx, ny);
3925             plAlloc2dGrid(&(grid->yg), nx, ny);
3926             for (i = 0; i < nx; i++)
3927             for (j = 0; j < ny; j++) {
3928             grid->xg[i][j] = $xg(nx => i, ny => j);
3929             grid->yg[i][j] = $yg(nx => i, ny => j);
3930             }
3931             grid->nx = nx;
3932             grid->ny = ny;
3933             $COMP(grid) = grid;'
3934             );
3935              
3936              
3937             # Free a PLcGrid2 object
3938              
3939             pp_addxs (<<"EOC");
3940             void
3941             plFree2dGrid(pg)
3942             PLcGrid2Ptr pg
3943             PPCODE:
3944             PLPTR_RECEIVE_IN(PLcGrid2, grid, pg)
3945             plFree2dGrid(grid->xg, grid->nx, grid->ny);
3946             plFree2dGrid(grid->yg, grid->nx, grid->ny);
3947             free(grid);
3948             EOC
3949              
3950             pp_add_exported (plFree2dGrid);
3951              
3952             pp_addhdr (<<'EOH');
3953              
3954             void pltr_iv_set(IV iv0, IV iv1, IV iv2);
3955             void pltr_callback_set(SV *sv, char *msg);
3956             void pltr_callback(PLFLT x, PLFLT y, PLFLT* tx, PLFLT* ty, PLPointer pltr_data);
3957             void* get_standard_pltrcb(SV* cb);
3958             void defined_callback_set(SV *sv, char *msg);
3959             PLINT defined_callback(PLFLT x, PLFLT y);
3960             void default_magic(pdl *p, size_t pa);
3961             void mapform_callback_set(SV *sv, char *msg);
3962             void mapform_callback(PLINT n, PLFLT* x, PLFLT* y);
3963             void xform_callback_set(SV *sv, char *msg);
3964             void xform_callback(PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data);
3965             void labelfunc_callback_set(SV *sv, char *msg);
3966             void labelfunc_callback(PLINT axis, PLFLT value, char *label_text, PLINT length, void *data);
3967             EOH
3968              
3969             pp_def ('init_pltr',
3970             NoPthread => 1,
3971             GenericTypes => [D],
3972             Pars => '',
3973             OtherPars => 'SV* p0; SV* p1; SV* p2;',
3974             Doc => <<'EOF',
3975             Used internally to set the variables C to the "pointers"
3976             of the Perl subroutines C. These variables are later used by
3977             C to provide the pointers to the C function C.
3978             This accelerates functions like plcont and plshades when those standard
3979             transformation functions are used.
3980             EOF
3981             Code => '
3982             pltr_iv_set(
3983             (IV) SvRV ($COMP(p0)),
3984             (IV) SvRV ($COMP(p1)),
3985             (IV) SvRV ($COMP(p2)));');
3986              
3987             pp_addpm (<<'EOPM');
3988             init_pltr (\&pltr0, \&pltr1, \&pltr2);
3989             EOPM
3990              
3991             pp_def ('plmap',
3992             NoPthread => 1,
3993             Pars => 'minlong(); maxlong(); minlat(); maxlat();', # 0-3
3994             OtherPars => 'SV* mapform; char* type;', # 4,5
3995             PMCode => _make_reorder('plmap'),
3996             Doc => 'plot continental outline in world coordinates',
3997             GenericTypes => [D],
3998             Code => '
3999             int use_xform;
4000             mapform_callback_set($COMP(mapform),
4001             "plmap: mapform must be either 0 or a subroutine pointer");
4002              
4003             use_xform = SvTRUE ($COMP(mapform));
4004             plmap (use_xform ? mapform_callback : NULL,
4005             $COMP(type), $minlong(), $maxlong(), $minlat(), $maxlat());',
4006             );
4007              
4008             pp_def ('plstring',
4009             NoPthread => 1,
4010             Pars => 'x(na); y(na);',
4011             OtherPars => 'char* string;',
4012             GenericTypes => [D],
4013             Doc => 'plot a string along a line',
4014             Code => 'c_plstring($SIZE(na), $P(x), $P(y), $COMP(string));',
4015             );
4016              
4017             pp_def ('plstring3',
4018             NoPthread => 1,
4019             Pars => 'x(na); y(na); z(na)',
4020             OtherPars => 'char* string;',
4021             GenericTypes => [D],
4022             Doc => 'plot a string along a 3D line',
4023             Code => 'c_plstring3($SIZE(na), $P(x), $P(y), $P(z), $COMP(string));',
4024             );
4025              
4026             pp_def ('plmeridians',
4027             NoPthread => 1,
4028             Pars => 'dlong(); dlat(); minlong(); maxlong(); minlat(); maxlat();', # 0-5
4029             OtherPars => 'SV* mapform;', # 6
4030             PMCode => _make_reorder('plmeridians'),
4031             GenericTypes => [D],
4032             Doc => 'Plot the latitudes and longitudes on the background',
4033             Code => '
4034             mapform_callback_set($COMP(mapform),
4035             "plmeridians: mapform must be either 0 or a subroutine pointer");
4036             plmeridians (SvTRUE ($COMP(mapform)) ? mapform_callback : NULL,
4037             $dlong(), $dlat(), $minlong(), $maxlong(), $minlat(), $maxlat());'
4038             );
4039              
4040             pp_def ('plshades',
4041             NoPthread => 1,
4042             Pars => 'z(x,y); xmin(); xmax(); ymin(); ymax();
4043             clevel(l); int fill_width(); int cont_color();
4044             int cont_width(); int rectangular()', # 0-9
4045             OtherPars => 'SV* defined; SV* pltr; SV* pltr_data;', # 10-12
4046             PMCode => _make_reorder('plshades'),
4047             GenericTypes => [D],
4048             Doc => 'Shade regions on the basis of value',
4049             Code => '
4050             int nx = $SIZE(x);
4051             int ny = $SIZE(y);
4052             int nlvl = $SIZE(l);
4053             int i, j;
4054             PLFLT **z;
4055             void (*pltrcb) ();
4056             PLPointer pltrdt;
4057              
4058             plAlloc2dGrid (&z, nx, ny);
4059              
4060             for (i = 0; i < nx; i++)
4061             for (j = 0; j < ny; j++)
4062             z[i][j] = (PLFLT) $z(x => i, y => j);
4063              
4064             defined_callback_set($COMP(defined),
4065             "plshades: defined must be either 0 or a subroutine pointer");
4066              
4067             pltr_callback_set($COMP(pltr),
4068             "plshades: pltr must be either 0 or a subroutine pointer");
4069              
4070             pltrcb = get_standard_pltrcb ($COMP(pltr));
4071             if (pltrcb != pltr_callback)
4072             pltrdt = PLPTR_RECEIVE_SV($COMP(pltr_data));
4073             else
4074             pltrdt = $COMP(pltr_data);
4075              
4076             c_plshades ((const PLFLT **)z, nx, ny,
4077             SvTRUE ($COMP(defined)) ? defined_callback : NULL,
4078             $xmin(), $xmax(), $ymin(), $ymax(),
4079             $P(clevel), nlvl, $fill_width(), $cont_color(), $cont_width(),
4080             plfill, $rectangular(), pltrcb, pltrdt);
4081              
4082             plFree2dGrid(z, nx, ny);',
4083             );
4084              
4085             pp_def ('plcont',
4086             NoPthread => 1,
4087             GenericTypes => [D],
4088             Pars => 'f(nx,ny); int kx(); int lx(); int ky(); int ly(); '
4089             . 'clevel(nlevel)', # 0-5
4090             OtherPars => 'SV* pltr; SV* pltr_data;', # 6,7
4091             Doc => 'Plot contours',
4092             Code => '
4093             int i, j, size_x, size_y;
4094             PLFLT** ff;
4095             void (*pltrcb) ();
4096             PLPointer pltrdt;
4097              
4098             size_x = $SIZE(nx);
4099             size_y = $SIZE(ny);
4100              
4101             plAlloc2dGrid (&ff, size_x, size_y);
4102              
4103             for (i = 0; i < size_x; i++)
4104             for (j = 0; j < size_y; j++)
4105             ff[i][j] = $f(nx => i, ny => j);
4106              
4107             pltr_callback_set($COMP(pltr),
4108             "plcont: pltr must be either 0 or a subroutine pointer");
4109              
4110             pltrcb = get_standard_pltrcb ($COMP(pltr));
4111             if (pltrcb != pltr_callback)
4112             pltrdt = PLPTR_RECEIVE_SV($COMP(pltr_data));
4113             else
4114             pltrdt = $COMP(pltr_data);
4115              
4116             c_plcont ((const PLFLT **)ff, size_x, size_y, $kx(), $lx(), $ky(), $ly(),
4117             $P(clevel), $SIZE(nlevel),
4118             pltrcb, pltrdt);
4119              
4120             plFree2dGrid (ff, size_x, size_y);'
4121             );
4122              
4123             pp_def ('plmesh',
4124             NoPthread => 1,
4125             Pars => 'x(nx); y(ny); z(nx,ny); int opt()',
4126             GenericTypes => [D],
4127             Doc => 'Surface mesh',
4128             Code => '
4129             int i, j, size_x, size_y;
4130             PLFLT** zz;
4131              
4132             size_x = $SIZE(nx);
4133             size_y = $SIZE(ny);
4134              
4135             plAlloc2dGrid (&zz, size_x, size_y);
4136              
4137             for (i = 0; i < size_x; i++)
4138             for (j = 0; j < size_y; j++)
4139             zz[i][j] = $z(nx => i, ny => j);
4140              
4141             c_plmesh ($P(x), $P(y), (const PLFLT **)zz, size_x, size_y, $opt());
4142              
4143             plFree2dGrid (zz, size_x, size_y);'
4144             );
4145              
4146             pp_def ('plmeshc',
4147             NoPthread => 1,
4148             Pars => 'x(nx); y(ny); z(nx,ny); int opt(); clevel(nlevel)',
4149             GenericTypes => [D],
4150             Doc => 'Magnitude colored plot surface mesh with contour',
4151             Code => '
4152             int i, j, size_x, size_y;
4153             PLFLT** zz;
4154              
4155             size_x = $SIZE(nx);
4156             size_y = $SIZE(ny);
4157              
4158             plAlloc2dGrid (&zz, size_x, size_y);
4159              
4160             for (i = 0; i < size_x; i++)
4161             for (j = 0; j < size_y; j++)
4162             zz[i][j] = $z(nx => i, ny => j);
4163              
4164             c_plmeshc ($P(x), $P(y), (const PLFLT **)zz, size_x, size_y, $opt(),
4165             $P(clevel), $SIZE(nlevel));
4166              
4167             plFree2dGrid (zz, size_x, size_y);'
4168             );
4169              
4170             pp_def ('plot3d',
4171             NoPthread => 1,
4172             Pars => 'x(nx); y(ny); z(nx,ny); int opt(); int side()',
4173             GenericTypes => [D],
4174             Doc => '3-d surface plot',
4175             Code => '
4176             int i, j, size_x, size_y;
4177             PLFLT** zz;
4178              
4179             size_x = $SIZE(nx);
4180             size_y = $SIZE(ny);
4181              
4182             plAlloc2dGrid (&zz, size_x, size_y);
4183              
4184             for (i = 0; i < size_x; i++)
4185             for (j = 0; j < size_y; j++)
4186             zz[i][j] = $z(nx => i, ny => j);
4187              
4188             c_plot3d ($P(x), $P(y), (const PLFLT **)zz, size_x, size_y, $opt(), $side());
4189              
4190             plFree2dGrid (zz, size_x, size_y);'
4191             );
4192              
4193             pp_def ('plot3dc',
4194             NoPthread => 1,
4195             Pars => 'x(nx); y(ny); z(nx,ny); int opt(); clevel(nlevel)',
4196             GenericTypes => [D],
4197             Doc => 'Plots a 3-d representation of the function z[x][y] with contour',
4198             Code => '
4199             int i, j, size_x, size_y;
4200             PLFLT** zz;
4201              
4202             size_x = $SIZE(nx);
4203             size_y = $SIZE(ny);
4204              
4205             plAlloc2dGrid (&zz, size_x, size_y);
4206              
4207             for (i = 0; i < size_x; i++)
4208             for (j = 0; j < size_y; j++)
4209             zz[i][j] = $z(nx => i, ny => j);
4210              
4211             c_plot3dc ($P(x), $P(y), (const PLFLT **)zz, size_x, size_y, $opt(),
4212             $P(clevel), $SIZE(nlevel));
4213              
4214             plFree2dGrid (zz, size_x, size_y);'
4215             );
4216              
4217             pp_def ('plscmap1l',
4218             NoPthread => 1,
4219             Pars => 'int itype(); isty(n); coord1(n); coord2(n); coord3(n);'
4220             . ' int rev(nrev)',
4221             GenericTypes => [D],
4222             Doc => 'Set color map1 colors using a piece-wise linear relationship',
4223             Code => '
4224             PLINT* rev;
4225              
4226             if ($SIZE(nrev) == 0)
4227             rev = NULL;
4228             else if ($SIZE(nrev) == $SIZE(n))
4229             rev = $P(rev);
4230             else
4231             $CROAK("plscmap1l: rev must have either length == 0 or have the same length of the other input arguments");
4232              
4233             c_plscmap1l ($itype(), $SIZE(n), $P(isty), $P(coord1),
4234             $P(coord2), $P(coord3), rev);'
4235             );
4236              
4237             pp_def ('plshade1',
4238             NoPthread => 1,
4239             GenericTypes => [D],
4240             Pars => 'a(nx,ny); left(); right(); bottom(); top(); shade_min();'
4241             . 'shade_max(); sh_cmap(); sh_color(); sh_width();'
4242             . 'min_color(); min_width(); max_color(); max_width();'
4243             . 'rectangular()', # 0-14
4244             OtherPars => 'SV* defined; SV* pltr; SV* pltr_data;',# 15-17
4245             PMCode => _make_reorder('plshade1'),
4246             Doc => 'Shade individual region on the basis of value',
4247             Code => '
4248             int i, j, size_x, size_y;
4249             PLFLT **a;
4250             void (*pltrcb) ();
4251             PLPointer pltrdt;
4252              
4253             size_x = $SIZE(nx);
4254             size_y = $SIZE(ny);
4255              
4256             plAlloc2dGrid (&a, size_x, size_y);
4257             if(a == NULL) $CROAK("Failed to allocate memory in plshade1_pp");
4258              
4259             for (i = 0; i < size_x; i++)
4260             for (j = 0; j < size_y; j++)
4261             a[i][j] = $a(nx => i, ny => j);
4262              
4263             defined_callback_set($COMP(defined),
4264             "plshade1: defined must be either 0 or a subroutine pointer");
4265              
4266             pltr_callback_set($COMP(pltr),
4267             "plshade1: pltr must be either 0 or a subroutine pointer");
4268              
4269             pltrcb = get_standard_pltrcb ($COMP(pltr));
4270             if (pltrcb != pltr_callback)
4271             pltrdt = PLPTR_RECEIVE_SV($COMP(pltr_data));
4272             else
4273             pltrdt = $COMP(pltr_data);
4274              
4275             c_plshade ((PLFLT_MATRIX) a, size_x, size_y,
4276             SvTRUE ($COMP(defined)) ? defined_callback : NULL,
4277             $left(), $right(), $bottom(), $top(),
4278             $shade_min(), $shade_max(), $sh_cmap(), $sh_color(), $sh_width(),
4279             $min_color(), $min_width(), $max_color(), $max_width(),
4280             plfill, $rectangular(), pltrcb, pltrdt);
4281              
4282             plFree2dGrid(a, size_x, size_y);'
4283             );
4284              
4285             pp_def ('plimage',
4286             NoPthread => 1,
4287             GenericTypes => [D],
4288             Doc => 'Plot gray-level image',
4289             Pars => 'idata(nx,ny); xmin(); xmax(); ymin(); ymax();'
4290             . 'zmin(); zmax(); Dxmin(); Dxmax(); Dymin(); Dymax();',
4291             Code => '
4292             int i, j, size_x, size_y;
4293             PLFLT** idata;
4294              
4295             size_x = $SIZE(nx);
4296             size_y = $SIZE(ny);
4297              
4298             plAlloc2dGrid (&idata, size_x, size_y);
4299              
4300             for (i = 0; i < size_x; i++)
4301             for (j = 0; j < size_y; j++)
4302             idata[i][j] = $idata(nx => i, ny => j);
4303              
4304             plimage ((const PLFLT **)idata, size_x, size_y,
4305             $xmin(), $xmax(), $ymin(), $ymax(), $zmin(), $zmax(),
4306             $Dxmin(), $Dxmax(), $Dymin(), $Dymax());
4307              
4308             plFree2dGrid (idata, size_x, size_y);'
4309             );
4310              
4311              
4312             pp_def ('plimagefr',
4313             NoPthread => 1,
4314             GenericTypes => [D],
4315             # plimagefr (idata, nx, ny, xmin, xmax, ymin, ymax, zmin, zmax, valuemin, valuemax, pltr, pltr_data);
4316             # plimagefr ($img, 0, $width, 0, $height, 0, 0, $img_min, $img_max, \&pltr2, $grid);
4317             Pars => 'idata(nx,ny); xmin(); xmax(); ymin(); ymax();'
4318             . 'zmin(); zmax(); valuemin(); valuemax();', # 0-8
4319             OtherPars => 'SV* pltr; SV* pltr_data;', # 9,10
4320             Doc => 'Plot image with transformation',
4321             Code => '
4322             int i, j, size_x, size_y;
4323             PLFLT** idata;
4324             void (*pltrcb) ();
4325             PLPointer pltrdt;
4326              
4327             size_x = $SIZE(nx);
4328             size_y = $SIZE(ny);
4329              
4330             pltr_callback_set($COMP(pltr),
4331             "plimagefr: pltr must be either 0 or a subroutine pointer");
4332              
4333             pltrcb = get_standard_pltrcb ($COMP(pltr));
4334             if (pltrcb != pltr_callback)
4335             pltrdt = PLPTR_RECEIVE_SV($COMP(pltr_data));
4336             else
4337             pltrdt = $COMP(pltr_data);
4338              
4339             plAlloc2dGrid (&idata, size_x, size_y);
4340              
4341             for (i = 0; i < size_x; i++)
4342             for (j = 0; j < size_y; j++)
4343             idata[i][j] = $idata(nx => i, ny => j);
4344              
4345             c_plimagefr ((const PLFLT **)idata, size_x, size_y,
4346             $xmin(), $xmax(), $ymin(), $ymax(), $zmin(), $zmax(),
4347             $valuemin(), $valuemax(),
4348             (SvTRUE ($COMP(pltr)) ? pltrcb : NULL),
4349             (SvTRUE ($COMP(pltr)) ? pltrdt : NULL));
4350              
4351             plFree2dGrid (idata, size_x, size_y);'
4352             );
4353              
4354             pp_addpm (<<'EOPM');
4355             =head2 plxormod
4356              
4357             =for sig
4358              
4359             $status = plxormod ($mode)
4360              
4361             =for ref
4362              
4363             Set xor mode:
4364             mode = 1-enter, 0-leave, status = 0 if not interactive device
4365              
4366             See the PLplot manual for reference.
4367              
4368             =cut
4369             EOPM
4370              
4371             pp_addxs (<<"EOC");
4372             int
4373             plxormod (mode)
4374             int mode
4375             CODE:
4376             PLINT status;
4377             c_plxormod (mode, &status);
4378             RETVAL = status;
4379             OUTPUT:
4380             RETVAL
4381             EOC
4382              
4383             pp_add_exported ('plxormod');
4384              
4385             pp_addpm (<<'EOPM');
4386             =head2 plGetCursor
4387              
4388             =for sig
4389              
4390             %gin = plGetCursor ()
4391              
4392             =for ref
4393              
4394             plGetCursor waits for graphics input event and translate to world
4395             coordinates and returns a hash with the following keys:
4396              
4397             type: of event (CURRENTLY UNUSED)
4398             state: key or button mask
4399             keysym: key selected
4400             button: mouse button selected
4401             subwindow: subwindow (alias subpage, alias subplot) number
4402             string: translated string
4403             pX, pY: absolute device coordinates of pointer
4404             dX, dY: relative device coordinates of pointer
4405             wX, wY: world coordinates of pointer
4406              
4407             Returns an empty hash if no translation to world coordinates is possible.
4408              
4409             =cut
4410             EOPM
4411              
4412             pp_addxs (<<"EOC");
4413             void
4414             plGetCursor ()
4415             PPCODE:
4416             PLGraphicsIn gin;
4417             if (plGetCursor (&gin)) {
4418             EXTEND (SP, 24);
4419             PUSHs (sv_2mortal (newSVpv ("type", 0)));
4420             PUSHs (sv_2mortal (newSViv ((IV) gin.type)));
4421             PUSHs (sv_2mortal (newSVpv ("state", 0)));
4422             PUSHs (sv_2mortal (newSVuv ((UV) gin.state)));
4423             PUSHs (sv_2mortal (newSVpv ("keysym", 0)));
4424             PUSHs (sv_2mortal (newSVuv ((UV) gin.keysym)));
4425             PUSHs (sv_2mortal (newSVpv ("button", 0)));
4426             PUSHs (sv_2mortal (newSVuv ((UV) gin.button)));
4427             PUSHs (sv_2mortal (newSVpv ("subwindow", 0)));
4428             PUSHs (sv_2mortal (newSViv ((IV) gin.subwindow)));
4429             PUSHs (sv_2mortal (newSVpv ("string", 0)));
4430             PUSHs (sv_2mortal (newSVpv (gin.string, 0)));
4431             PUSHs (sv_2mortal (newSVpv ("pX", 0)));
4432             PUSHs (sv_2mortal (newSViv ((IV) gin.pX)));
4433             PUSHs (sv_2mortal (newSVpv ("pY", 0)));
4434             PUSHs (sv_2mortal (newSViv ((IV) gin.pY)));
4435             PUSHs (sv_2mortal (newSVpv ("dX", 0)));
4436             PUSHs (sv_2mortal (newSVnv ((double) gin.dX)));
4437             PUSHs (sv_2mortal (newSVpv ("dY", 0)));
4438             PUSHs (sv_2mortal (newSVnv ((double) gin.dY)));
4439             PUSHs (sv_2mortal (newSVpv ("wX", 0)));
4440             PUSHs (sv_2mortal (newSVnv ((double) gin.wX)));
4441             PUSHs (sv_2mortal (newSVpv ("wY", 0)));
4442             PUSHs (sv_2mortal (newSVnv ((double) gin.wY)));
4443             }
4444             EOC
4445              
4446             pp_add_exported ('plGetCursor');
4447              
4448             pp_addpm (<<'EOPM');
4449             =head2 plgstrm
4450              
4451             =for sig
4452              
4453             $strm = plgstrm ()
4454              
4455             =for ref
4456              
4457             Returns the number of the current output stream.
4458              
4459             =cut
4460             EOPM
4461              
4462             pp_addxs (<<"EOC");
4463             int
4464             plgstrm ()
4465             CODE:
4466             PLINT strm;
4467             c_plgstrm (&strm);
4468             RETVAL = strm;
4469             OUTPUT:
4470             RETVAL
4471             EOC
4472              
4473             pp_add_exported ('plgstrm');
4474              
4475             pp_addpm (<<'EOPM');
4476             =head2 plgsdev
4477              
4478             =for sig
4479              
4480             $driver = plgdev ()
4481              
4482             =for ref
4483              
4484             Returns the current driver name.
4485              
4486             =cut
4487             EOPM
4488              
4489             pp_addxs (<<"EOC");
4490             char*
4491             plgdev ()
4492             CODE:
4493             char driver[80];
4494             c_plgdev (driver);
4495             RETVAL = driver;
4496             OUTPUT:
4497             RETVAL
4498             EOC
4499              
4500             pp_add_exported ('plgdev');
4501              
4502             pp_addxs (<<"EOC");
4503             char*
4504             plgfnam ()
4505             CODE:
4506             char driver[80];
4507             c_plgfnam (driver);
4508             RETVAL = driver;
4509             OUTPUT:
4510             RETVAL
4511             EOC
4512              
4513             pp_add_exported ('plgfnam');
4514              
4515             pp_addpm (<<'EOPM');
4516             =head2 plmkstrm
4517              
4518             =for sig
4519              
4520             $strm = plmkstrm ()
4521              
4522             =for ref
4523              
4524             Creates a new stream and makes it the default. Returns the number of
4525             the created stream.
4526              
4527             =cut
4528             EOPM
4529              
4530             pp_addxs (<<"EOC");
4531             int
4532             plmkstrm ()
4533             CODE:
4534             PLINT strm;
4535             c_plmkstrm (&strm);
4536             RETVAL = strm;
4537             OUTPUT:
4538             RETVAL
4539             EOC
4540              
4541             pp_add_exported ('plmkstrm');
4542              
4543             pp_addpm (<<'EOPM');
4544             =head2 plgver
4545              
4546             =for sig
4547              
4548             $version = plgver ()
4549              
4550             =for ref
4551              
4552             Get the current library version number
4553              
4554             See the PLplot manual for reference.
4555              
4556             =cut
4557             EOPM
4558              
4559             pp_addxs (<<"EOC");
4560             char*
4561             plgver ()
4562             CODE:
4563             char ver[80];
4564             c_plgver (ver);
4565             RETVAL = ver;
4566             OUTPUT:
4567             RETVAL
4568             EOC
4569              
4570             pp_add_exported ('plgver');
4571              
4572             #----------------------------------------------------------------------------
4573              
4574             pp_def ('plstripc',
4575             NoPthread => 1,
4576             GenericTypes => [D],
4577             Pars => 'xmin(); xmax(); xjump(); ymin(); ymax();' # 0-4
4578             . 'xlpos(); ylpos(); int y_ascl(); int acc();' # 5-8
4579             . 'int colbox(); int collab();' # 9-10
4580             . 'int colline(n); int styline(n);' # 11-12
4581             . 'int [o] id()', # 13 if given - else decr the rest
4582             OtherPars => 'char* xspec; char* yspec; SV* legline;' # 14-16
4583             . 'char* labx; char* laby; char* labtop', # 17-19
4584             PMCode => _make_reorder('plstripc'),
4585             Doc => 'FIXME: documentation here!',
4586             Code => '
4587             I32 i;
4588             PLINT id;
4589             char* legline[4];
4590             SV* sv_legline = $COMP(legline);
4591             AV* av_legline;
4592              
4593             if (! SvROK (sv_legline)
4594             || SvTYPE (SvRV (sv_legline)) != SVt_PVAV)
4595             $CROAK("plstripc: legline must be a reference to an array");
4596              
4597             av_legline = (AV*) SvRV (sv_legline);
4598              
4599             if (av_len (av_legline) != 3)
4600             $CROAK("plstripc: legline must have four elements");
4601              
4602             if ($SIZE(n) != 4)
4603             $CROAK("plstripc: colline and styline must have four elements");
4604              
4605             for (i = 0; i < 4; i++) {
4606             SV** elem = av_fetch (av_legline, i, 0);
4607             legline[i] = (char *) SvPV_nolen (*elem);
4608             }
4609              
4610             c_plstripc (&id, $COMP(xspec), $COMP(yspec),
4611             $xmin(), $xmax(), $xjump(), $ymin(), $ymax(),
4612             $xlpos(), $ylpos(),$y_ascl(), $acc(), $colbox(), $collab(),
4613             $P(colline), $P(styline), (const char **)legline,
4614             $COMP(labx), $COMP(laby), $COMP(labtop));
4615              
4616             $id() = (int) id;'
4617             );
4618              
4619             #----------------------------------------------------------------------------
4620              
4621             pp_def ('plgriddata',
4622             NoPthread => 1,
4623             GenericTypes => [D],
4624             Pars => 'x(npts); y(npts); z(npts); xg(nptsx); yg(nptsy);'
4625             . 'int type(); data(); [o] zg(nptsx,nptsy)',
4626             Doc => 'FIXME: documentation here!',
4627             Code => '
4628             int i, j, size_x, size_y;
4629             PLFLT** zg;
4630              
4631             size_x = $SIZE(nptsx);
4632             size_y = $SIZE(nptsy);
4633              
4634             plAlloc2dGrid (&zg, size_x, size_y);
4635              
4636             c_plgriddata ($P(x), $P(y), $P(z), $SIZE(npts),
4637             $P(xg), size_x, $P(yg), size_y,
4638             zg, $type(), $data());
4639              
4640             for (i = 0; i < size_x; i++)
4641             for (j = 0; j < size_y; j++)
4642             $zg(nptsx => i, nptsy => j) = zg[i][j];
4643              
4644             plFree2dGrid (zg, size_x, size_y);
4645             '
4646             );
4647              
4648             #-----------------------------------------------------------------------------
4649              
4650             pp_addpm (<<'EOPM');
4651             =head2 plarc
4652              
4653             =for sig
4654              
4655             plarc ($x, $y, $a, $b, $angle1, $angle2, $rotate, $fill);
4656              
4657             =for ref
4658              
4659             Draw a (possibly) filled arc centered at x, y with semimajor axis a and semiminor axis b, starting at angle1 and ending at angle2.
4660             See the PLplot manual for reference.
4661              
4662             =cut
4663             EOPM
4664             pp_addxs (<<"EOC");
4665             int
4666             plarc (x, y, a, b, angle1, angle2, rotate, fill)
4667             double x
4668             double y
4669             double a
4670             double b
4671             double angle1
4672             double angle2
4673             double rotate
4674             int fill
4675             CODE:
4676             plarc (x, y, a, b, angle1, angle2, rotate, fill);
4677             EOC
4678             pp_add_exported ('plarc');
4679              
4680             #----------------------------------------------------------------------------
4681              
4682             pp_addpm (<<'EOPM');
4683             =head2 plstransform
4684              
4685             =for sig
4686              
4687             plstransform ($subroutine_reference, $data);
4688              
4689             =for ref
4690              
4691             Sets the default transformation routine for plotting.
4692              
4693             sub mapform {
4694             my ($x, $y, $data) = @_;
4695              
4696             my $radius = 90.0 - $y;
4697             my $xp = $radius * cos ($x * pi / 180);
4698             my $yp = $radius * sin ($x * pi / 180);
4699              
4700             return ($xp, $yp);
4701             }
4702             plstransform (\&mapform, undef);
4703              
4704             See the PLplot manual for more details.
4705              
4706             =cut
4707             EOPM
4708              
4709             pp_addxs (<<"EOC");
4710             int
4711             plstransform (xform, data)
4712             SV* xform
4713             SV* data
4714             CODE:
4715             if (SvTRUE(xform)) xform_callback_set(SvRV(xform),
4716             "plstransform: xform must be either 0 or a subroutine pointer");
4717             plstransform (SvTRUE(xform) ? xform_callback : NULL, data);
4718             EOC
4719             pp_add_exported ('plstransform');
4720              
4721             #----------------------------------------------------------------------------
4722              
4723             pp_addpm (<<'EOPM');
4724             =head2 plslabelfunc
4725              
4726             =for sig
4727              
4728             plslabelfunc ($subroutine_reference);
4729              
4730             =for ref
4731              
4732             # A custom axis labeling function for longitudes and latitudes.
4733             sub geolocation_labeler {
4734             my ($axis, $value, $length) = @_;
4735             my ($direction_label, $label_val);
4736             if (($axis == PL_Y_AXIS) && $value == 0) {
4737             return "Eq";
4738             } elsif ($axis == PL_Y_AXIS) {
4739             $label_val = $value;
4740             $direction_label = ($label_val > 0) ? " N" : " S";
4741             } elsif ($axis == PL_X_AXIS) {
4742             my $times = floor((abs($value) + 180.0 ) / 360.0);
4743             $label_val = ($value < 0) ? $value + 360.0 * $times : $value - 360.0 * $times;
4744             $direction_label = ($label_val > 0) ? " E"
4745             : ($label_val < 0) ? " W"
4746             : "";
4747             }
4748             return substr (sprintf ("%.0f%s", abs($label_val), $direction_label), 0, $length);
4749             }
4750             plslabelfunc(\&geolocation_labeler);
4751              
4752             The PDL version of plslabelfunc only has one argument--the perl subroutine
4753             to do the label translation:
4754              
4755             my $labeltext = perl_labelfunc($axis, $value, $length);
4756              
4757             No 'data' argument is used, it is assumed that global data or a closure containing
4758             necessary data can be used in 'perl_labelfunc'.
4759              
4760             See the PLplot manual for more details.
4761              
4762             =cut
4763             EOPM
4764              
4765             pp_addxs (<<"EOC");
4766             int
4767             plslabelfunc (labelfunc)
4768             SV* labelfunc
4769             CODE:
4770             if (SvTRUE(labelfunc)) labelfunc_callback_set(SvRV(labelfunc),
4771             "plslabelfunc: labelfunc must be either 0 or a subroutine pointer");
4772             plslabelfunc (SvTRUE(labelfunc) ? labelfunc_callback : NULL, NULL);
4773             EOC
4774             pp_add_exported ('plslabelfunc');
4775              
4776             #----------------------------------------------------------------------------
4777              
4778             pp_addpm (<<'EOPM');
4779             =head2 pllegend
4780              
4781             =for sig
4782              
4783             my ($legend_width, $legend_height) =
4784             pllegend ($position, $opt, $x, $y, $plot_width, $bg_color, $nlegend,
4785             \@opt_array,
4786             $text_offset, $text_scale, $text_spacing, $test_justification,
4787             \@text_colors, \@text, \@box_colors, \@box_patterns, \@box_scales, \@line_colors,
4788             \@line_styles, \@line_widths, \@symbol_colors, \@symbol_scales, \@symbol_numbers, \@symbols);
4789              
4790             =for ref
4791              
4792             See the PLplot manual for more details.
4793              
4794             =cut
4795             EOPM
4796              
4797             my $width_type = 'double';
4798              
4799             pp_addxs (<<"EOC");
4800             void
4801             pllegend(opt, position, x, y, plot_width, bg_color, bb_color, bb_style, nrow, ncolumn, nlegend, opt_array_rv, text_offset, text_scale, text_spacing, text_justification, text_colors_rv, text_rv, box_colors_rv, box_patterns_rv, box_scales_rv, box_line_widths_rv, line_colors_rv, line_styles_rv, line_widths_rv, symbol_colors_rv, symbol_scales_rv, symbol_numbers_rv, symbols_rv)
4802             int opt
4803             int position
4804             double x
4805             double y
4806             double plot_width
4807             int bg_color
4808             int bb_color
4809             int bb_style
4810             int nrow
4811             int ncolumn
4812             int nlegend
4813             SV* opt_array_rv
4814             double text_offset
4815             double text_scale
4816             double text_spacing
4817             double text_justification
4818             SV* text_colors_rv
4819             SV* text_rv
4820             SV* box_colors_rv
4821             SV* box_patterns_rv
4822             SV* box_scales_rv
4823             SV* box_line_widths_rv
4824             SV* line_colors_rv
4825             SV* line_styles_rv
4826             SV* line_widths_rv
4827             SV* symbol_colors_rv
4828             SV* symbol_scales_rv
4829             SV* symbol_numbers_rv
4830             SV* symbols_rv
4831             PPCODE:
4832             int i;
4833             double p_legend_width;
4834             double p_legend_height;
4835             int opt_array[nlegend];
4836             int text_colors[nlegend];
4837             char *text[nlegend];
4838             int box_colors[nlegend];
4839             int box_patterns[nlegend];
4840             double box_scales[nlegend];
4841             $width_type box_line_widths[nlegend];
4842             int line_colors[nlegend];
4843             int line_styles[nlegend];
4844             $width_type line_widths[nlegend];
4845             int symbol_colors[nlegend];
4846             double symbol_scales[nlegend];
4847             int symbol_numbers[nlegend];
4848             char *symbols[nlegend];
4849             SV **elem;
4850              
4851             for (i = 0; i < nlegend; i++) {
4852              
4853             elem = av_fetch((AV *)SvRV(opt_array_rv), i, 0); opt_array[i] = (int)SvIV(*elem);
4854             elem = av_fetch((AV *)SvRV(text_colors_rv), i, 0); text_colors[i] = (int)SvIV(*elem);
4855             elem = av_fetch((AV *)SvRV(text_rv), i, 0); text[i] = (char *)SvPV_nolen(*elem);
4856             box_colors[i] = 0;
4857             if (SvROK(box_colors_rv)) {
4858             elem = av_fetch((AV *)SvRV(box_colors_rv), i, 0);
4859             if (elem && SvOK(*elem)) {
4860             box_colors[i] = (int)SvIV(*elem);
4861             }
4862             }
4863             box_patterns[i] = 0;
4864             if (SvROK(box_patterns_rv)) {
4865             elem = av_fetch((AV *)SvRV(box_patterns_rv), i, 0);
4866             if (elem && SvOK(*elem)) {
4867             box_patterns[i] = (int)SvIV(*elem);
4868             }
4869             }
4870             box_scales[i] = 0.0;
4871             if (SvROK(box_scales_rv)) {
4872             elem = av_fetch((AV *)SvRV(box_scales_rv), i, 0);
4873             if (elem && SvOK(*elem)) {
4874             box_scales[i] = (double)SvNV(*elem);
4875             }
4876             }
4877             box_line_widths[i] = 0.0;
4878             if (SvROK(box_line_widths_rv)) {
4879             elem = av_fetch((AV *)SvRV(box_line_widths_rv), i, 0);
4880             if (elem && SvOK(*elem)) {
4881             box_line_widths[i] = (double)SvIV(*elem);
4882             }
4883             }
4884             line_colors[i] = 0;
4885             if (SvROK(line_colors_rv)) {
4886             elem = av_fetch((AV *)SvRV(line_colors_rv), i, 0);
4887             if (elem && SvOK(*elem)) {
4888             line_colors[i] = (int)SvIV(*elem);
4889             }
4890             }
4891              
4892             line_styles[i] = 0;
4893             if (SvROK(line_styles_rv)) {
4894             elem = av_fetch((AV *)SvRV(line_styles_rv), i, 0);
4895             if (elem && SvOK(*elem)) {
4896             line_styles[i] = (int)SvIV(*elem);
4897             }
4898             }
4899              
4900             line_widths[i] = 0.0;
4901             if (SvROK(line_widths_rv)) {
4902             elem = av_fetch((AV *)SvRV(line_widths_rv), i, 0);
4903             if (elem && SvOK(*elem)) {
4904             line_widths[i] = (double)SvIV(*elem);
4905             }
4906             }
4907              
4908             symbol_colors[i] = 0;
4909             if (SvROK(symbol_colors_rv)) {
4910             elem = av_fetch((AV *)SvRV(symbol_colors_rv), i, 0);
4911             if (elem && SvOK(*elem)) {
4912             symbol_colors[i] = (int)SvIV(*elem);
4913             }
4914             }
4915              
4916             symbol_scales[i] = 0.0;
4917             if (SvROK(symbol_scales_rv)) {
4918             elem = av_fetch((AV *)SvRV(symbol_scales_rv), i, 0);
4919             if (elem && SvOK(*elem)) {
4920             symbol_scales[i] = (double)SvNV(*elem);
4921             }
4922             }
4923              
4924             symbol_numbers[i] = 0;
4925             if (SvROK(symbol_numbers_rv)) {
4926             elem = av_fetch((AV *)SvRV(symbol_numbers_rv), i, 0);
4927             if (elem && SvOK(*elem)) {
4928             symbol_numbers[i] = (int)SvIV(*elem);
4929             }
4930             }
4931              
4932             symbols[i] = "0";
4933             if (SvROK(symbols_rv)) {
4934             elem = av_fetch((AV *)SvRV(symbols_rv), i, 0);
4935             if (elem && SvOK(*elem)) {
4936             symbols[i] = (char *)SvPV_nolen(*elem);
4937             }
4938             }
4939             }
4940              
4941             pllegend(&p_legend_width, &p_legend_height,
4942             opt, position, x, y, plot_width, bg_color, bb_color, bb_style, nrow, ncolumn, nlegend,
4943             opt_array,
4944             text_offset, text_scale, text_spacing, text_justification,
4945             text_colors, (const char **)text, box_colors, box_patterns, box_scales, box_line_widths,
4946             line_colors, line_styles, line_widths, symbol_colors, symbol_scales, symbol_numbers, (const char **)symbols);
4947              
4948             EXTEND (SP, 2);
4949             PUSHs (sv_2mortal (newSVnv (p_legend_width)));
4950             PUSHs (sv_2mortal (newSVnv (p_legend_height)));
4951             EOC
4952             pp_add_exported ('pllegend');
4953              
4954             #----------------------------------------------------------------------------
4955              
4956             pp_addpm (<<'EOPM');
4957             =head2 plspal0
4958              
4959             =for sig
4960              
4961             plspal0($filename);
4962              
4963             =for ref
4964              
4965             Set color palette 0 from the input .pal file. See the PLplot manual for more details.
4966              
4967             =cut
4968             EOPM
4969              
4970             pp_addxs (<<"EOC");
4971             int
4972             plspal0 (filename)
4973             char* filename
4974             PPCODE:
4975             plspal0((const char *)filename);
4976             EOC
4977             pp_add_exported ('plspal0');
4978              
4979             #----------------------------------------------------------------------------
4980              
4981             pp_addpm (<<'EOPM');
4982             =head2 plspal1
4983              
4984             =for sig
4985              
4986             plspal1($filename);
4987              
4988             =for ref
4989              
4990             Set color palette 1 from the input .pal file. See the PLplot manual for more details.
4991              
4992             =cut
4993             EOPM
4994              
4995             pp_addxs (<<"EOC");
4996             int
4997             plspal1 (filename, interpolate)
4998             char* filename
4999             int interpolate
5000             PPCODE:
5001             plspal1((const char *)filename, (PLBOOL)interpolate);
5002             EOC
5003             pp_add_exported ('plspal1');
5004              
5005             pp_addpm (<<'EOPM');
5006             =head2 plbtime
5007              
5008             =for sig
5009              
5010             my ($year, $month, $day, $hour, $min, $sec) = plbtime($ctime);
5011              
5012             =for ref
5013              
5014             Calculate broken-down time from continuous time for current stream.
5015              
5016             =cut
5017             EOPM
5018              
5019             pp_addxs (<<"EOC");
5020             void
5021             plbtime (ctime)
5022             double ctime
5023             PPCODE:
5024             PLINT year;
5025             PLINT month;
5026             PLINT day;
5027             PLINT hour;
5028             PLINT min;
5029             PLFLT sec;
5030             c_plbtime(&year, &month, &day, &hour, &min, &sec, ctime);
5031             EXTEND (SP, 6);
5032             PUSHs (sv_2mortal (newSViv (year)));
5033             PUSHs (sv_2mortal (newSViv (month)));
5034             PUSHs (sv_2mortal (newSViv (day)));
5035             PUSHs (sv_2mortal (newSViv (hour)));
5036             PUSHs (sv_2mortal (newSViv (min)));
5037             PUSHs (sv_2mortal (newSVnv (sec)));
5038             EOC
5039             pp_add_exported ('plbtime');
5040              
5041             pp_addpm (<<'EOPM');
5042             =head2 plconfigtime
5043              
5044             =for sig
5045              
5046             plconfigtime($scale, $offset1, $offset2, $ccontrol, $ifbtime_offset, $year, $month, $day, $hour, $min, $sec);
5047              
5048             =for ref
5049              
5050             Configure transformation between continuous and broken-down time (and
5051             vice versa) for current stream.
5052              
5053             =cut
5054             EOPM
5055              
5056             pp_addxs (<<"EOC");
5057             void
5058             plconfigtime(scale, offset1, offset2, ccontrol, ifbtime_offset, year, month, day, hour, min, sec)
5059             double scale
5060             double offset1
5061             double offset2
5062             int ccontrol
5063             int ifbtime_offset
5064             int year
5065             int month
5066             int day
5067             int hour
5068             int min
5069             double sec
5070             PPCODE:
5071             c_plconfigtime((PLFLT) scale, (PLFLT) offset1, (PLFLT) offset2,
5072             (PLINT) ccontrol, (PLBOOL) ifbtime_offset, (PLINT) year,
5073             (PLINT) month, (PLINT) day, (PLINT) hour, (PLINT) min, (PLFLT) sec);
5074             EOC
5075             pp_add_exported ('plconfigtime');
5076              
5077             pp_addpm (<<'EOPM');
5078             =head2 plctime
5079              
5080             =for sig
5081              
5082             my $ctime = plctime($year, $month, $day, $hour, $min, $sec);
5083              
5084             =for ref
5085              
5086             Calculate continuous time from broken-down time for current stream.
5087              
5088             =cut
5089             EOPM
5090              
5091             pp_addxs (<<"EOC");
5092             void
5093             plctime(year, month, day, hour, min, sec)
5094             int year
5095             int month
5096             int day
5097             int hour
5098             int min
5099             double sec
5100             PPCODE:
5101             PLFLT ctime;
5102             c_plctime(year, month, day, hour, min, sec, &ctime);
5103             EXTEND (SP, 1);
5104             PUSHs (sv_2mortal (newSVnv (ctime)));
5105             EOC
5106             pp_add_exported ('plctime');
5107              
5108             pp_addpm (<<'EOPM');
5109             =head2 pltimefmt
5110              
5111             =for sig
5112              
5113             pltimefmt($fmt);
5114              
5115             =for ref
5116              
5117             Set format for date / time labels. Labels must be configured to treat values as
5118             seconds since the epoch via the XBOX/YBOX flags. C<$fmt> is generally
5119             consistent with the POSIX strpformat/strftime flags, but see the PLplot manual
5120             for details.
5121              
5122             =cut
5123             EOPM
5124              
5125             pp_addxs (<<"EOC");
5126             void
5127             pltimefmt(fmt)
5128             char *fmt
5129             PPCODE:
5130             c_pltimefmt((const char *)fmt);
5131             EOC
5132             pp_add_exported ('pltimefmt');
5133              
5134             pp_addpm (<<'EOPM');
5135             =head2 plsesc
5136              
5137             =for sig
5138              
5139             plsesc($esc);
5140              
5141             =for ref
5142              
5143              
5144             Set the escape character for text strings. See the PLplot manual for more details.
5145              
5146             =cut
5147             EOPM
5148              
5149             pp_addxs (<<"EOC");
5150             void
5151             plsesc (esc)
5152             SV* esc
5153             PPCODE:
5154             char *esc_c;
5155             esc_c = (char *)SvPV_nolen(esc);
5156             c_plsesc((char)*esc_c);
5157              
5158             EOC
5159             pp_add_exported ('plsesc');
5160              
5161             pp_def ('plvect',
5162             NoPthread => 1,
5163             GenericTypes => [D],
5164             Pars => 'u(nx,ny); v(nx,ny); scale();',
5165             OtherPars => 'SV* pltr; SV* pltr_data;',
5166             Doc => 'Vector field plots',
5167             Code => '
5168             int i, j, size_x, size_y;
5169             PLFLT** u;
5170             PLFLT** v;
5171             void (*pltrcb) ();
5172             PLPointer pltrdt;
5173              
5174             size_x = $SIZE(nx);
5175             size_y = $SIZE(ny);
5176              
5177             plAlloc2dGrid (&u, size_x, size_y);
5178             plAlloc2dGrid (&v, size_x, size_y);
5179              
5180             for (i = 0; i < size_x; i++)
5181             for (j = 0; j < size_y; j++) {
5182             u[i][j] = $u(nx => i, ny => j);
5183             v[i][j] = $v(nx => i, ny => j);
5184             }
5185              
5186             pltr_callback_set($COMP(pltr),
5187             "plvect: pltr must be either 0 or a subroutine pointer");
5188              
5189             pltrcb = get_standard_pltrcb ($COMP(pltr));
5190             if (pltrcb != pltr_callback)
5191             pltrdt = PLPTR_RECEIVE_SV($COMP(pltr_data));
5192             else
5193             pltrdt = $COMP(pltr_data);
5194              
5195             plvect ((const PLFLT **)u, (const PLFLT **)v, size_x, size_y, $scale(), pltrcb, pltrdt);
5196              
5197             plFree2dGrid (u, size_x, size_y);
5198             plFree2dGrid (v, size_x, size_y);'
5199             );
5200              
5201             pp_def ('plsvect',
5202             NoPthread => 1,
5203             Pars => 'arrowx(npts); arrowy(npts); int fill()',
5204             GenericTypes => [D],
5205             Doc => 'Give zero-length PDLs for arrowx and arrowy to pass NULL to PLplot func.',
5206             Code => '
5207             c_plsvect (
5208             ($SIZE(npts) != 0) ? $P(arrowx) : NULL,
5209             ($SIZE(npts) != 0) ? $P(arrowy) : NULL,
5210             $SIZE(npts), $fill()
5211             );
5212             '
5213             );
5214              
5215             pp_def ('plhlsrgb',
5216             NoPthread => 1,
5217             GenericTypes => [D],
5218             Pars => 'double h();double l();double s();double [o]p_r();double [o]p_g();double [o]p_b()',
5219             Code => 'c_plhlsrgb($h(),$l(),$s(),$P(p_r),$P(p_g),$P(p_b));'
5220             );
5221              
5222             # void c_plgcol0(PLINT icol0, PLINT *r, PLINT *g, PLINT *b);
5223             pp_def ('plgcol0',
5224             NoPthread => 1,
5225             Pars => 'int icolzero(); int [o]r(); int [o]g(); int [o]b()',
5226             Code => 'c_plgcol0($icolzero(),$P(r),$P(g),$P(b));'
5227             );
5228              
5229             # void c_plgcolbg(PLINT *r, PLINT *g, PLINT *b);
5230             pp_def ('plgcolbg',
5231             NoPthread => 1,
5232             Pars => 'int [o]r(); int [o]g(); int [o]b()',
5233             Code => 'c_plgcolbg($P(r),$P(g),$P(b));'
5234             );
5235              
5236             # void c_plscmap0(PLINT *r, PLINT *g, PLINT *b, PLINT ncol0);
5237             pp_def ('plscmap0',
5238             NoPthread => 1,
5239             Pars => 'int r(n); int g(n); int b(n)',
5240             Code => 'c_plscmap0($P(r),$P(g),$P(b), $SIZE(n));'
5241             );
5242              
5243             # void c_plscmap1(PLINT *r, PLINT *g, PLINT *b, PLINT ncol1);
5244             pp_def ('plscmap1',
5245             NoPthread => 1,
5246             Pars => 'int r(n); int g(n); int b(n)',
5247             Code => 'c_plscmap1($P(r),$P(g),$P(b), $SIZE(n));'
5248             );
5249              
5250             if (!$noalpha) {
5251              
5252             # void c_plgcol0a(PLINT icol0, PLINT *r, PLINT *g, PLINT *b, PLFLT *a);
5253             pp_def ('plgcol0a',
5254             NoPthread => 1,
5255             Pars => 'int icolzero(); int [o]r(); int [o]g(); int [o]b(); double [o]a()',
5256             Code => 'c_plgcol0a($icolzero(),$P(r),$P(g),$P(b),$P(a));'
5257             );
5258              
5259             # void c_plgcolbga(PLINT *r, PLINT *g, PLINT *b, PLFLT *a);
5260             pp_def ('plgcolbga',
5261             NoPthread => 1,
5262             Pars => 'int [o]r(); int [o]g(); int [o]b(); double [o]a()',
5263             Code => 'c_plgcolbga($P(r),$P(g),$P(b),$P(a));'
5264             );
5265              
5266             # void c_plscmap0a(PLINT *r, PLINT *g, PLINT *b, PLFLT *a, PLINT ncol0);
5267             pp_def ('plscmap0a',
5268             NoPthread => 1,
5269             Pars => 'int r(n); int g(n); int b(n); double a(n)',
5270             Code => 'c_plscmap0a($P(r),$P(g),$P(b),$P(a),$SIZE(n));'
5271             );
5272              
5273             # void c_plscmap1a(PLINT *r, PLINT *g, PLINT *b, PLFLT *a, PLINT ncol1);
5274             pp_def ('plscmap1a',
5275             NoPthread => 1,
5276             Pars => 'int r(n); int g(n); int b(n); double a(n)',
5277             Code => 'c_plscmap1a($P(r),$P(g),$P(b),$P(a),$SIZE(n));'
5278             );
5279              
5280             pp_def ('plscmap1la',
5281             NoPthread => 1,
5282             Pars => 'int itype(); isty(n); coord1(n); coord2(n); coord3(n); coord4(n);'
5283             . ' int rev(nrev)',
5284             GenericTypes => [D],
5285             Doc => 'Set color map1 colors using a piece-wise linear relationship, include alpha channel',
5286             Code => '
5287             PLINT* rev;
5288              
5289             if ($SIZE(nrev) == 0)
5290             rev = NULL;
5291             else if ($SIZE(nrev) == $SIZE(n))
5292             rev = $P(rev);
5293             else
5294             $CROAK("plscmap1la: rev must have either length == 0 or have the same length of the other input arguments");
5295              
5296             c_plscmap1la ($itype(), $SIZE(n), $P(isty), $P(coord1),
5297             $P(coord2), $P(coord3), $P(coord4), rev);'
5298             );
5299             }
5300              
5301              
5302             #
5303             ## UNICODE font manipulation
5304             #
5305              
5306             # plgfont(PLINT *p_family, PLINT *p_style, PLINT *p_weight);
5307             pp_def ('plgfont',
5308             NoPthread => 1,
5309             Pars => 'int [o]p_family(); int [o]p_style(); int [o]p_weight();',
5310             Code => 'c_plgfont($P(p_family),$P(p_style),$P(p_weight));'
5311             );
5312              
5313             # plsfont (PLINT family, PLINT style, PLINT weight);
5314             pp_def ('plsfont',
5315             NoPthread => 1,
5316             Pars => 'int family(); int style(); int weight();',
5317             Code => 'c_plsfont($family(),$style(),$weight());'
5318             );
5319              
5320             # plcalc_world (PLFLT rx, PLFLT ry, PLFLT *wx, PLFLT *wy, PLINT *window);
5321             pp_def ('plcalc_world',
5322             NoPthread => 1,
5323             Pars => 'double rx(); double ry(); double [o]wx(); double [o]wy(); int [o]window()',
5324             Code => 'c_plcalc_world($rx(), $ry(), $P(wx), $P(wy), $P(window));'
5325             );
5326              
5327             pp_addxs (<<"EOC");
5328             unsigned int
5329             plgfci ()
5330             CODE:
5331             c_plgfci(&RETVAL);
5332             OUTPUT:
5333             RETVAL
5334             EOC
5335             pp_add_exported('', 'plgfci');
5336              
5337             pp_addxs (<<'EOC');
5338             void
5339             plsfci(fci)
5340             unsigned int fci
5341             CODE:
5342             c_plsfci(fci);
5343             EOC
5344             pp_add_exported('', 'plsfci');
5345              
5346             pp_addpm (<<'EOPM');
5347             =head2 pl_cmd
5348              
5349             =for sig
5350              
5351             pl_cmd($CMD, $data);
5352              
5353             =for ref
5354              
5355             See the PLplot manual for reference.
5356             Gives access to low level driver. $CMD is an integer. $data opaque data.
5357              
5358             =cut
5359             EOPM
5360              
5361             pp_addxs (<<"EOC");
5362             void
5363             pl_cmd (cmd, data)
5364             int cmd
5365             void *data
5366             CODE:
5367             pl_cmd(cmd, data);
5368             EOC
5369             pp_add_exported('pl_cmd');
5370              
5371             pp_addpm (<<'EOPM');
5372             =head2 pl_setCairoCtx
5373              
5374             =for sig
5375              
5376             pl_setCairoCtx($cairo_context);
5377              
5378             =for ref
5379              
5380             Used with cairo external drivers to set the cairo context.
5381             $cairo_context should be a Cairo::Context object.
5382             Uses pl_cmd underneath, but extracts the real C struct pointer from the Cairo::Context.
5383              
5384             =cut
5385             EOPM
5386              
5387             pp_addxs (<<"EOC");
5388             void
5389             pl_setCairoCtx(SV *sv)
5390             CODE:
5391             pl_cmd(PLESC_DEVINIT, (void *)(SvIV ((SV *) SvRV (sv))));
5392             EOC
5393             pp_add_exported('pl_setCairoCtx');
5394              
5395              
5396              
5397             pp_addpm (<<'EOPM');
5398              
5399             =pod
5400              
5401             =head1 WARNINGS AND ERRORS
5402              
5403             PLplot gives many errors and warnings. Some of these are given by the
5404             PDL interface while others are internal PLplot messages. Below are
5405             some of these messages, and what you need to do to address them:
5406              
5407             =over
5408              
5409             =item *
5410             Box must be a ref to a four element array
5411              
5412             When specifying a box, you must pass a reference to a
5413             four-element array, or use an anonymous four-element array.
5414              
5415             # Gives trouble:
5416             $pl->xyplot($x, $y, BOX => (0, 0, 100, 200) );
5417             # What you meant to say was:
5418             $pl->xyplot($x, $y, BOX => [0, 0, 100, 200] );
5419              
5420             =item *
5421             Too many colors used! (max 15)
5422              
5423              
5424             =back
5425              
5426             =head1 AUTHORS
5427              
5428             Doug Hunt
5429             Rafael Laboissiere
5430             David Mertens
5431              
5432             =head1 SEE ALSO
5433              
5434             perl(1), PDL(1), L
5435              
5436             The other common graphics packages include L
5437             and L.
5438              
5439             =cut
5440              
5441             EOPM
5442              
5443             pp_done();
5444              
5445             # Local Variables:
5446             # mode: cperl
5447             # End: