Qplplot
q bindings of plplot -- 100M data points histogrammed in 500ms.
Install / Use
/learn @jaeheum/QplplotREADME
Qplplot
Q bindings of PLplot graphical data plotting library.
PLplot provides C API to plot data. Qplplot is q bindings of PLplot for plotting
data both in interactive mode inside kdb+ sessions and in batch mode from *.q
scripts.
A notable feature of PLplot is its speed. For example, plhist() computes
distribution or frequency of a data array of 100 million elements and makes a
histogram plot in a window in subsecond on a modern laptop.
(Sandy Bridge i7 from 2012 takes about 600ms).
There is no copying or transfering data from q to PLplot as
qplplot passes a pointer so that plotting is done with
in-place data managed by kdb+. Compare running example scripts x05.q and x05w100M.q.
version
As of today (2015.02.16), qplplot supports most of PLplot 5.10, the latest public release.
Qplplot Documentation
PLplot documentation
qplplot synopsis
Qplplot (in qplplot.q) uses pl as its namespace prefix.
\l qplplot.q / loads qplplot API as a dictionary named pl.
pl.functionname[] / matches plfunctionname() (functionname is a placeholder name)
pl`OPTION / matches OPTION C symbol exported by plplot.h
PLplot vs qplplot
Qplplot API mirrors that of PLplot so that users can refer to PLplot API reference.
pl.functionname[] corresponds to plfunctionanme() in PLplot. For example,
PLplot in C qplplot
-----------------------------------------------
plinit() pl.init[]
plline(n, x, y) pl.line[n; x; y]
Translating API of PLplot to q or qplplot is easy once types are understood:
PLplot types q types
-----------------------------------------------
(PLINT, input) `int atom or type -6h
(PLFLT, input) `float atom or type -9h
(PLBOOL, input) `int atom or type -9h, (NOT `boolean or -1h)
(const PLFLT *, input) `float vector or 9h
(char *, input) `sym or -11h
(char *, output) `sym or -11h, N.B. output parameter
Therefore plline(PLINT n, const PLFLT* x, const PLFLT* y)
would be translated into q as
pl.line[n; x; y] where n:count x; x and y, vectors of float (of equal counts).
Here is a short example that draws a random walk across 1000 points:
\l qplplot.q
pl.init[] / plinit();
pl.env[0f;1f;0f;1f;0;0] / plenv(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLINT just, PLINT axis).
pl.col0 9 / plcol0(PLINT icol0); // same as pl.col0 pl`blue;
K:1000
x:K?1f
y:K?1f
pl.line[K;x;y] / plline(PLINT n, const PLFLT*, const PLFLT* y); // draw lines of random walk across 1000 points.
pl.lab[`x; `y; `$"random walk across 1000 points"]
/ pllab(const char* xlabel, const char* ylabel, const char* tlabel);
pl.end[] / plend();
\\
Many PLplot APIs use PLplot's exported C symbols or constants. For example,
plmesh()
expects a PLINT opt argument that can be either DRAW_LINEX, DRAW_LINEY, or DRAW_LINEXY.
In qplplot's pl.mesh[], these opt values are q symbol keys to pl:
pl`DRAW_LINEX, pl`DRAW_LINEY or pl`DRAW_LINEXY.
plcol0()
expects an integer argument representing a color.
Qplplot lets users to use color names listed in the plcol0 reference,
e.g. pl.col0[0] works as well as pl.col0[pl`black].
Most PLplot APIs return void but some return an output parameter (marked output type). For example,
plgver()
plgver(char* p_ver);
p_ver (char *, output)
Pointer to the current library version number.
Qplplot's counterpart returns output parameter p_ver as a symbol:
q)pl.gver[]
`5.10.0
Some other APIs return multiple output parameters and qplplot wraps them in a dictionary. For example,
plgchr()
q)pl.gchr[] / plgchr(&p_def, &p_ht); in C
p_def| 7.5
p_ht | 7.5
Notice that symbol keys of the output dictionary match the names of output parameters in PLplot's API reference.
further hints for translation
- A qplplot function name is same as PLplot's original name except for a
.betweenpland the rest of the name. - Most PLplot API names are abbreviations:
plg*()APIs are usually getter functions, e.g.plgver()orpl.gver[]above.pls*()APIs are usually setter functions, e.g.plsdev(const char* devname)orpl.sdev[`devname].
- Examples resemble PLplot's original examples closely. See Examples section below.
types or `int vs `long
PLINTatom can be passed as`longor-7has long as its value fits`int. This leniency lets users skip addingi-suffix behind every integer that is`longby default in Kdb+ 3.0 or later.- However, if a list that expects a
PLINT(orPLBOOL), make sure to use`intin q. - Getters (
plg*()orpl.g*[]) returningPLINTreturns`int(seex31.q).
special cases
Because a q function allows maximum of 8 arguments
(define a function with more than 8 arguments and q returns 'params exception),
some PLplot APIs with more than 8 arguments deserve special attention.
For most PLplot APIs, qplplot preserves order, count and types of arguments of the original PLplot APIs so that PLplot's API documentation can cover qplplot's. However, PLplot APIs with more than 8 arguments are expressed differently in qplplot:
-
Arguments are grouped logically into lists. See the
pl.*functions below and cross-check with PLplot's reference. -
Often, argument for count and other bookkeeping arguments are elided.
-
plcont()uses a callback function: a user-defined one as well as built-inpltr0,pltr1or,pltr2. Qplplot'spl.cont*come with four flavors:pl.cont[],pl.cont0[],pl.cont1[]andpl.cont2[]. See examples for usage (see Examples section below). -
Likewise for
plimagefr(),plshade(),plshades(),plvect(). -
See also Bugs section below.
pl.box3[(`xopt;`lsxlabel;xtick;nxsub); (`yopt;`lsylabel;ytick;nysub); (`zopt;`lszlabel;ztick;nzsub)] pl.colorbar[dict] / dict is made of all input args as keys and values. / Returns a dict with keys p_colorbar_width and p_colorbar_height. pl.cont[z; (kx;lx); (ky;ly); clevel; pltr; pltr_data]; / nlevel=count clevel pl.cont0[f; (kx;ly); (ky;ly); clevel]; / nlevel=count clevel; pltr0 called by qplplot. pl.cont1[z; (kx;ly); (ky;ly); clevel; xg1; yg1]; / nlevel=count clevel; pltr1 called by qplplot. pl.cont2[f; (kx;ly); (ky;ly); clevel; xg2; yg2]; / nlevel=count clevel; pltr2 called by qplplot. pl.imagefr[x; (xmin;xmax;ymin;ymax);(zmin;zmax);(valuemin;valuemax); pltr; pltr_data] pl.imagefr0[x; (xmin;xmax;ymin;ymax);(zmin;zmax);(valuemin;valuemax)] pl.imagefr1[x; (xmin;xmax;ymin;ymax);(zmin;zmax);(valuemin;valuemax); xg1; yg1] pl.imagefr2[x; (xmin;xmax;ymin;ymax);(zmin;zmax);(valuemin;valuemax); xg2; yg2] pl.image[x; (xmin;xmax; ymin;ymax);(zmin;zmax);(dxmin;dxmax;dymin;dymax)] pl.legend[(opt; position; x; y; plot_width); (bg_color; bb_color; bb_style); (nrow,ncolumn,nlegend); opt_array; (text_offset; text_scale; text_spacing; test_justification; text_colors; text); (box_colors; box_patterns; box_scales; box_line_widths); (line_colors; line_styles; line_widths); (symbol_colors; symbol_scales; symbol_numbers; symbols)] pl.ptex3[(x;y;z);(dx;dy;dz);(sx;sy;sz);just;text] pl.shade[a; defined; (xmin;xmax;ymin;ymax;shade_min;shade_max); (sh_cmap;sh_color;sh_width;min_color;min_width;min_color;max_color;max_width); fill; rectangular; pltr; pltr_data] / fill is ignored but left for future compatibility pl.shade1[a; defined; (xmin;xmax;ymin;ymax;shade_min;shade_max); (sh_cmap;sh_color;sh_width;min_color;min_width;min_color;max_color;max_width); fill; rectangular; pltr; pltr_data] / fill is ignored but left for future compatibility pl.shades[a; defined; (xmin; xmax; ymin; ymax; clevel); (fill_width; cont_color; cont_width); fill; rectangular; pltr] / fill is ignored but left for future compatibility pl.shades0[a; defined; (xmin; xmax; ymin; ymax; clevel); (fill_width; cont_color; cont_width); fill; rectangular] / pltr0 setby pl.shades0[] pl.shades2[a; defined; (xmin; xmax; ymin; ymax; clevel); (fill_width; cont_color; cont_width); fill; rectangular; xg2; yg2] / pltr2 setby pl.shades2[] pl.stripc[(xspec;yspec); (xmin;xmax;xjump; ymin;ymax); (xlpos;ylpos); (y_ascl;acc); (colbox;collab); (colline;styline;legline); (labx;laby;labtop)] pl.surf3d[x; y; z; opt; clevel] pl.surf3dl[x; y; z; opt; clevel; (xmin;xmax); ymin;ymax)] pl.fsurf3d[x; y; z; opt; clevel] pl.vect[u; v; scale; pltr]; / nx=count u; ny=count v; pl.vect0[u; v; scale]; / nx=count u; ny=count v; pltr0 set by plvect. pl.vect1[u; v; scale; xg1; yg1]; / nx=count u; ny=count v
