## JOG: Jhack's Own Graphics

A very slim and portable graphic software:

#### jogging is good for your figures!

## Features

This software was designed to produce scatter and triangular plots from plain ascii files using the postscript language. It is a small set of postscript functions and a C program to wrap the postscript code into either a printable A4 page document or a so called encapsulated postscript image suitable to include in office documents. This slim software is not designed to produce 3d plots or contour plots. So if you need this, check somewhere else: scilab may be a possibility.

- the source files ( *.jog) and graphics (*.ps or *.eps) are plain ascii files following the postscript syntax hence portable to most computing environments.
- the jog files are very compact yet clearly structured. The original data remain visible in both the source and graphic files: no information is lost in the graphics unlike many fat graphers. The source(s) file(s) are simply appended to a very compact postscript prologue and terminated by a short epilogue.
- complex graphics can be made automatically and efficiently for repetitive evaluation of some modelisation or calculations. Jog can use external shell commands to calculate data points or anything else...
- simple data transformations can be easily achieved using plain Postscript language, therefore original data can be kept untouched in the file and plotted modified for scaling, changing units etc... with simple postscript commands and, last but not least, commented as needed. The jogfile can be authoritative for the data avoiding the nightmare of version multiplications: moreover they can be handled gracefully in a versioning system such as CVS.
- for a simple graphic the amount of information to provide is very small, yet producing decent plots as illustrated in the next paragraphs.
- extensions and customising is unlimited... well only by the postscript interpreter used ( ghostscript is used by default ). The all thing fits in less than a thousand lines of postscript and less than 200 lines of very plain C. The project should be very easy to read to moderately computer litterate users and adapted as required.

## Jogging: first steps

The next few examples provides a quick survey and and a set of templates for the impatients. They are intended to help potential users to find out if this software is able to efficiently tackle their problem. A more formal description of the software is given elsewhere but this document should be enough for a quick evaluation of the features strengths and weaknesses versus that of other tools such as gnuplot, grace (Xmgr), spreadsheets...
A basic understanding of postscript syntaxe is needed to fully understand this document: see for instance <insert some url or link>

### Simple scatter plots

This exemple shows 3 instructions used to define a rectangular scatter plot. The argument of Axe2 command is a vector giving the low and high bounds of the X and Y axis, i.e. [ Xmin Xmax Ymin Ymax ]. The next two lines defines the graduations and labels of both axis. All other layout parameters are default values. This should be the most common way to start a graphic. Note that labels are given as a vector of strings of numerical values between (). This enables to choose precisely the format for the labels.

    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY

The previous figure is a bitmap image ( 0.png ) of the original encapsulated postscript imahe ( 0.eps ) obtained with the command ge 0 which uses the source jog file 0.jog ( on the right side of the figure ). However to get a hard copy on an A4 page the companion command g 0 will produce 0.ps which is shown below (using ghostview) and illustrates the standard layout of the plot on an A4 page. I choosed to leave blank space above the figure for tables of labels or other informations and on the left for binding. Note that the eps figure is cropped automatically with a small 10 points margin around the drawing, so its actual location and size are not critical. Also eps can be scaled as needed in the final document without loss of information.
The next example shows a plot of data points using the default plot mode ( black open circles ). The coordinates of each data point are given in a vector delimited by []. The actual layout of the code is unimportant (spaces, tabs and end of line are not distinguished in Postscript), however the presentation used shows Xi and Yi in two columns for clarity.

    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    [
     10 -0.3
     20 0.15
     30 0.25
     40 0.40
     60 0.65
     80 0.73
    ] Plot

Data points can be given in several other ways. The next example shows the same data points plotted as the previous example, then using two vectors [ xi ] then [ yi ] and plotted in red with lines and crosses. A small set of commands enable to modify the current plot mode, controlling the symbol used, color, filled or not, with or without lines/symbol.

    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    [
     10 -0.3
     20 0.15
     30 0.25
     40 0.40
     60 0.65
     80 0.73
    ] Plot

    [ 10 20 30 40 60 80 ]
    [ -0.3 0.15 0.25 0.40 0.65 0.73 ]
    WithLines Red Cross

Postscrip is a full fledge programing language. The following example shows how to use variables. Vector a and b are defined then used in two plot instructions.

    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    /a [ 10 20 30 40 60 80 ] def
    /b [ -0.3 0.15 0.25 0.40 0.65 0.73 ] def
    a b Black Circles
    a [ 1.2 0.95 0.6 0.3 -0.1 -0.3 ]
    WithLines Green Filled Diamonds

### Using tables of data: Cols and Col

Often the data are selected colums of a table (may be copied from a spreadsheet). The funtions Cols and Col shown in the next example help to handle this type of data. The Cols functions prototype is:

    amn n jx jy Cols -> xy

where amn is an array of m*n elements seen as an m rows by n column matrix; the number of column n must be given as 2d argument and consistent with the actual length of the array; then jx and jy are the indices of the columns used for X and Y values respectively. The second function Col extract a single column of a table. Its use is shown in the last paragraph of the code ploting the orange squares and dashed line, using the first column of t1 and the second of t2.
NOTE: t1 and t2 identifiers are actually substituted by an array and an integer; the integer is the number of columns of the m by n matrix mapped on the postscript array. Therefore the calls to Cols or Col are t1 jx jy Cols or t1 jx Col because the array and n are hidden in t1 or t2. Remember that postscript does not care for end of lines, so that the layout of t1 suggest that I consider an array of 20 elements as a matrix of 4 rows by 5 columns, but this must be asserted explicitly giving the number of columns and assuming a row major ordering (C style) for the array.

    % Using tables of data
    % note the number of col after the array.
    % t1 represents an array and an integer
    % needed in this order in the plot functions
    /t1 { [
        1   0  -1   2   1
        2   2   0   5   0
        3   4   2   3   1
        4   3   3   2   2
    ] 5 } def

    % same number of lines as t1
    % BTW NOTE 1/3 and 2/3 accurate values in col 3
    % coded 1 3 div ! YES it works !
    /t2 { [
     2   1 3 div
     5   2 3 div
     3   0.6
     2   2.4
    ] 2 } def

    [ -2 6 -2 6 ] Axe2
    [(0)(2)(4)(6)] GradX
    [(-2)(0)(2)(4)(6)] GradY

    Filled % symbols
    Blue
    t1 1 5 Cols Circles
    Violet
    t1 1 3 Cols WithLines Diamonds

    % plot x y vectors of the same size taken from different tables
    Orange 2 Dash
    t1 1 Col t2 2 Col Squares

## Labels and other tricks

Several other features are shown in the next figure:

- Place labels for different plot style starting at a given paper position.
- The size and position of the graphic in the page can be modified using a second argument to the Axe2 instruction. Here the plot will be in a square window of 500 points width, the bottom left corner at 70 70 ( points from the bottom left of the default A4 layout ). Many instructions are overloaded and can manage various argument list, such as Axe2, GradX, GradY, all plot instructions can handle various type of argument which are recognised by their type and number.
- Yet another way to give data points coordinates to plot commands to handle evenly spaced data along X axis. One can give the abscissa of the first point, then the step between each point and an array of ordinate values (see the Violet Filled Circles instruction in the example).
- Use other postscript character fonts and sizes.
- Adding titles to axes with GradX and GradY and a string argument.
- Finally a simple debuging instruction: a line starting by a question mark will be replaced in the final postscript file by a tracing instruction printing the current line number and the postscript stack at that point. This is usually enough to pin down errors.

    (Times-Roman) 15 Font
    [70 570 70 570][ 0 100 0 100 ] Axe2
    [(25)(50)(75)] GradX
    [(25)(50)(75)] GradY
    25 Font
    (Axe X) GradX
    (Axe Y) GradY
    ?
    0 10 [ 0 10 20 30 40 50 60 ] Violet Filled Circles
    ?
    [0 10 20 30 40 50 60]
    [60 50 40 30 20 10 0 ]
    Blue Cross
    ?
    [
    0 5 10 15 20 25 30 35
    40 45
    50 55
    60 65
    ] WithLines Red Filled Squares
    ?
    Black 15 Font
    10 90 s2o % paper location to start writing labels
    (NoLines Violet Filled Circles) ( What it is ) Label
    (WithLines Red Filled Squares) ( Another one ) Label
    (NoLines Blue Cross) (and the last one) Label
    ?

## Jogging with style

Using some simple postscript features to get a clearly structured file and first of all comments. Some other tricks are used: metric conversion of points with the mm command. Using some predefined dashed patterns and gsave grestore postscript instructions to save and restore the current graphic mode ( color, line thickness etc...). Another convenient instruction is used to convert from user coordinate to paper coordinate ( currently named s2o from french sujet -> objet ; I might change this to pp for paper or postscript points).

    (Times-Roman) 15 Font
    0.35 mm Pen % modify curent line width in mm
    [70 570 70 570] % [left right bottom top] in paper coordinates
    [ 0 100 0 100 ] % [Xmin Xmax Ymin Ymax ] in user coordinates
    Axe2

    [(25)(50)(75)] GradX % array of string means text and position
    [(25)(50)(75)] GradY % of labels for GradX and GradY
    25 Font % use larger font for titles
    (Axe X) GradX % a string argument is understood as the title
    (Axe Y) GradY
    % Here we define the data vectors to plot
    /X [ 5 15 30 45 50 70 80 ] def
    /Y1 [60 50 40 30 20 10 0 ] def
    /Y2 [ 30 35 40 43 25 22 12 ] def
    % we can do some simple calculation on data
    /Y3 [ Y2 { 1.2 mul } forall ] def
    /XY [ 30 35 60 65 80 85 ] def
    % then use them in plot function call
    0 10 Y1 NoLines Violet Filled Circles
    X Y1 NoLines Orange Filled Squares
    X Y2 NoLines Red Cross
    X Y3 WithLines Blue Empty Diamonds
    gsave XY Red 1 Dash Lines grestore % local dash
    % write some labels for the various plots
    Black 15 Font
    10 90 s2o % paper location to start writing labels
    % s2o convert from user coordinate to paper coordinats
    % these 2 numbers are used by the first Label call
    % subsequent calls just skip to the next line
    (NoLines Violet Filled Circles) ( 0 10 Y1 ) Label
    (NoLines Orange Filled Squares) ( X Y1 ) Label
    (NoLines Red Cross) ( X Y2 ) Label
    (WithLines Blue Empty Diamonds) ( X Y3 ) Label
    gsave
    (Red 1 Dash Lines) ( XY ) Label
    grestore
    % some more drawing on the graph in user coord
    0.1 mm Pen
    [ 0 20 100 20 ] Black Lines

## Colors and other decorations

Managing colors and simple calculations to layout a table of colored symbols and a few other things: plotting closed lines and surfaces, clipping.

    ?
    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    ?
    % axes titles can also be provided in GradX and GradY functions
    18 Font (Axe X) (Axe Y) Titles
    25 Font (Labels and colors) Titles
    18 Font Blue 2 Pen
    ?
    % Test for clipping within a given area default the plot window
    % this is not recommanded because export software may not handle clipping properly
    gsave
    ?
    Clip % by default Fobj Clip
    ?
    [ -20 0.9 40 0.2 120 -0.4 ] Lines
    grestore % returns to unclipped
    % clip is off after restore so circles are drawn across border line
    20 Size % change symbol size
    [0 0 50 0 100 0] Green Plot
    10 Size
    % Draw in reverse depth so background first...
    0.9 setgray
    [
     5 -0.15
     20 0.2
     35 0.45
     50 0.23
     60 -0.11
    ] Surface
    10 Size Red WithLines Diamonds
    ?
    [
     30 0.123
     50 0.456
     70 0.895
    ] Plot
    % the plot statement is the last one Order of other is unimportant
    % They can be placed even before the data vector
    [ 80 1.21 85 0.85 ] Violet 6 Size NoLines Filled Circles
    % or Lines : here same thing if called before symbol
    [ 85 1.0 95 0.90 ] Red WithLines Empty Squares
    ?
    15 Size NoLines Black % color for text of legends while symbols
    % will have their own color as given in first arg.
    /x 150 def /y 700 def % we need variables to
    % layout our table of symbols and labels
    ?
    x y
    ( 0 Color Filled Circles ) (Color 0) Label
    ( 1 Color Filled Circles ) (Color 1) Label
    ( 2 Color Filled Circles ) (Color 2) Label
    ( 3 Color Filled Circles ) (Color 3) Label
    ( 4 Color Filled Circles ) (Color 4) Label

    x 100 add y
    ( 5 Color Filled Circles ) (Color 5) Label
    ( 6 Color Filled Circles ) (Color 6) Label
    ( 7 Color Filled Circles ) (Color 7) Label
    ( 8 Color Filled Circles ) (Color 8) Label
    ( 9 Color Filled Circles ) (Color 9) Label

    x 200 add y
    ( 10 Color Filled Circles ) (Color 10) Label
    ( 11 Color Filled Circles ) (Color 11) Label
    ( 12 Color Filled Circles ) (Color 12) Label
    ( 13 Color Filled Circles ) (Color 13) Label
    ( 14 Color Filled Circles ) (Color 14) Label
    ?
    x 320 add y
    ( 15 Color Filled Circles ) ( Color 15 ) Label
    ( 16 Color Filled Circles ) ( Color 16 ) Label
    ( 17 Color Filled Circles ) ( Color 17 ) Label
    ( 18 Color Filled Circles ) ( Color 18 ) Label
    ( 19 Color Filled Circles ) ( Color 19 ) Label
    % example of strings with index/exponents and greek letters
    % Only one modifier for the next char ( NO greek index/exponent though ! )
    Black
    30 Font
    200 385 moveto (`m_1 `u_a `b `G) Show
    200 350 moveto (H_2O f_H_2 `DG_r) Show

## Jogging and running

One important feature is to be able to run external commands and include the output in the graphic. This is illustrated with 2 trivial shell script in the next example. Lines with a leading ! are replaced by the output of the following shell command. In the example we use two external awk scripts to generate the functions ploted.
Note: The F appended to the font name indicates a re-encoded font for the latin character set ( so that french accented characters are maped properly ). Both Times-RomanF and HelveticaF are available. Times-Roman and Helvetica are standard postscript fonts with posrscript encoding ( this is ok for plain ascii ).

    (Times-RomanF) 25 Font
    0.5 mm Pen
    [ 50 550 50 800][ 0 30 -0.5 1 ] Axe2
    [ (0) (10) (20) (30) ] GradX
    [ (-0.4) (-0.2) (0) (0.2) (0.4) (0.6) (0.8) (1.0) ] GradY

    gsave % save current color pen etc...
     0.15 mm Pen
     [ Xmin 0 Xmax 0 ] Black 1 Dash Lines
    grestore % restore color pen dash...
    ?
    gsave
    [
    % LC_NUMERIC=C to make sure that "." is the decimal separator
    ! LC_NUMERIC=C ./sinx.awk
    ] Blue Lines
    grestore
    ?
    gsave
    [
    ! LC_NUMERIC=C ./sinx2.awk
    ] 1 Dash Red Lines
    grestore
    300 720
    % beware to escape ( in a postscript string
    ( Blue ) ( sin\(x\)/x ) Label
    ( Red 1 Dash Lines ) ( sin\(x\)/sqrt\(x\) ) Label
    ?

The two simple awk script are shown below:

    sinx.awk
    sinx2.awk
    #! /bin/awk -f
    BEGIN {
    for ( x=0.02; x<30.0; x+=0.05 ) {
     printf("%10.3f %10.5f\n",x,sin(x)/x)
     }
    }
    #! /bin/awk -f
    BEGIN {
    for ( x=0.02; x<30; x+=0.05 ) {
     printf("%10.3f %10.5f\n",
     x,
     sin(x)/sqrt(x)+0.1)
     }
    }

## Multiple plots

This shows how to use several plot windows simultaneously in the same graphic; 4 plotting windows are defined and their properties saved in the variables W1, W2, W3 and W4 using the Win command with an identifier as argument e.g. /W1 Win. Then the second variant of the Win command with a value argument enables to chose the current plot windowe.g. W1 Win.
There is also a test of Clipping within the plot window. This is sometimes needed, but note that clipping will make your graphics less portable in the sense that translation to different vector languages ( xfig, open office draw, svg... ) will most probably not handle clipping properly.

    % kludge to move and scale the fig on the page without
    % modification to the code
    % 0.7 0.7 scale
    % 130 320 translate
    (Times-Roman) 12 Font
    /Data [ 15 10 20 20 50 50 75 25 12 18 ] def
    /Width 250 def
    /Height 250 def
    /Bottom 60 def
    /Left 50 def
    /Xshift { Width 10 add } def
    /Yshift { Height 10 add } def
    % same values for all windows
    [ 0 100 0 100 ] Axe2
    /gr [(20)(40)(60)(80)] def
    gr (Titre X_1) GradX
    gr (Y_1 axis title) GradY
    /W1 Win % save user window 1
    %
    /Left Left Xshift add def
    [ 0 100 0 100 ] Axe2
    (Titre X_2) gr GradX
    gr false GradY
    /W2 Win % save user window 2
    %
    /Left Left Xshift sub def % order
    /Bottom Bottom Yshift add def % is
    [ 0 100 0 100 ] Axe2
    gr false GradX
    (Y_3 axis title) gr GradY
    /W3 Win % save user window 3
    %
    /Left Left Xshift add def
    [ 0 100 0 100 ] Axe2
    gr false GradX
    gr false GradY
    /W4 Win % save user window 4
    %
    W1 Win %=== recall W1 user window
    Data Filled Red Circles
    %
    W2 Win % now in the 2d window and so on...
    Data Empty Blue Circles
    ?
    W3 Win
    Data Filled Green Circles
    ?
    W4 Win
    Data Filled Black Squares
    ?
    W1 Win
    [-5 -10 120 110 ] 1 Dash 0.5 setgray Lines
    gsave
    Fobj Clip % Clip plot in current window
    [-5 -10 120 110 ] Red Lines
    grestore % revert to unclipped plot mode

## Jogging along a triangle

The Axe3 module must be loaded as it is not included by default. Point coordinates are given as fractions of component 2 (SiO2) and 3 (K2O). A simple postscript code is used to adjust the data given in % to the default scale of the plot which is 0..1. This is just to point out again that postscript offers all standard control such as loops. There are variants of Axe3 function to avoid this kind of trick.

    #include Axe3
    (Na_2O) (SiO_2) (K_2O) Axe3
    /Tbl [
     20.0 25.0
     35.0 15.0
     50.0 16.5
     60.0 5.33
    ] def
    % here I scale to 0..1 instead of 0..100
    [ Tbl { 100 div } forall ] Plot

Multiple plots can also be used with triangular plots as illustrated below:

sub and superscripts in a string |
    #include Axe3
    % TODO ? change Xa Ya -> Gauche Bas or Left Bottom
    % and Cote should be Largeur / Width...

    /Cote 70 mm def
    8 Font
    0.5 Pen
    2 Size

    /Xa 30 def
    /Ya 30 def
    (Na_2O) (SiO_2) (K_2O) Axe3
    /T1 Win

    /Ya Yc 30 add def
    (K_2O) (SiO_2) (K_2O) Axe3
    /T2 Win

    /Ya Yc 30 add def
    (Al_2O_3) (SiO_2) (FeO) Axe3
    /T3 Win

    /Xa Xb 50 add def
    /Ya 30 def
    (Na_2O) (SiO_2) (K_2O) Axe3
    /T4 Win

    /Ya Yc 30 add def
    (K_2O) (SiO_2) (K_2O) Axe3
    /T5 Win

    /Ya Yc 30 add def
    (Al_2O_3) (SiO_2) (FeO) Axe3
    /T6 Win

    % the data table
    /Tbl [
     20.0 25.0
     35.0 15.0
     50.0 16.5
     60.0 5.33
    ] def

    Filled % all symbols filled

    T1 Win
    [ Tbl { 100 div } forall ] Blue Circles

    T5 Win
    [ Tbl { 100 div } forall ] Red Squares

    T2 Win
    4 Size
    [ 0.3 0.2 0.154 0.233 ] Olive WithLines Squares

## Careful or sloppy text

The function Wrt enables to write lines of text anywhere; the following example is also meant to be a quick reference on how to code all greek characters.
Default line spacing is used controlled by the current font size. Advance text processing IS NOT within the scope of a slim software, and kept deliberately very simple.
Note: in this example no plot window is defined. In this case the standard postscript coordinate system is used: isometric, length in points ( 1/72 inch ) origin at the botom left corner of the page.

    % Writing one line at 50,700
    50 700 (Table of) Wrt
    % without coord. writes on the next line(s)
    (matching) Wrt
    % append other lines to the current paragraph...
    (Roman) (and Greek) (characters) Wrt
    % This can also be achieved in a single Wrt with
    % a pair of coordinates and one or several strings
    200 700
    (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13)
    Wrt
    % now let's print a nice blue table of greek letters
    Blue
    /xo 270 def
    /yo 700 def
    xo yo
    (a `a) (b `b) (c `c) (d `d) (e `e) (f `f)
    (g `g) (h `h) (i `i) (j `j) (k `k) (l `l) (m `m) Wrt
    /xo xo 60 add def
    xo yo
    (n `n) (o `o) (p `p) (q `q) (r `r) (s `s)
    (t `t) (u `u) (v `v) (w `w) (x `x) (y `y) (z `z) Wrt
    /xo xo 60 add def
    xo yo
    (A `A) (B `B) (C `C) (D `D) (E `E) (F `F)
    (G `G) (H `H) (I `I) (J `J) (K `K) (L `L) (M `M) Wrt
    /xo xo 60 add def
    xo yo
    (N `N) (O `O) (P `P) (Q `Q) (R `R) (S `S)
    (T `T) (U `U) (V `V) (W `W) (X `X) (Y `Y) (Z `Z) Wrt
    %
    /p1 {68 126} def % defining coord. of a point p1
    /p2 {170 287} def % and p2
    /p3 {270 160} def % and yet a third point
    %
    [ p1 p2 p3 ] Green Polygone
    Violet
    % NOTE points p1 must be different from p2 otherwise slope is undefined
    [ p1 p2 ] ( <- p_1 p_2 -> ) Wrt
     p1 p3 ( <- p_1 p_3 -> ) Wrt % this variant is also accepted
    % yet I prefer [] () Wrt for consistency with Plot functions
    [ p2 p3 ] ( <- p_2 p_3 -> ) Wrt
    [ p3 p2 ] ( <- p_3 p_2 -> ) Wrt

A simplified version of the previous example is shown below, with the encapsulated postscript image as a screen copy of ghostview window. This shows how to use the Wrt function. First we select the current font at 30 points. Then locate the first string to print on the page and print the first column. Then we offset the x value to the right and prints the other 3 columns. Note: the ` modifier applies to the next character only.

    30 Font
    /xo 270 def
    /yo 700 def
    xo yo
    (a `a) (b `b) (c `c) (d `d) (e `e) (f `f)
    (g `g) (h `h) (i `i) (j `j) (k `k) (l `l) (m `m) Wrt
    /xo xo 80 add def
    xo yo
    (n `n) (o `o) (p `p) (q `q) (r `r) (s `s)
    (t `t) (u `u) (v `v) (w `w) (x `x) (y `y) (z `z) Wrt
    /xo xo 80 add def
    xo yo
    (A `A) (B `B) (C `C) (D `D) (E `E) (F `F)
    (G `G) (H `H) (I `I) (J `J) (K `K) (L `L) (M `M) Wrt
    /xo xo 80 add def
    xo yo
    (N `N) (O `O) (P `P) (Q `Q) (R `R) (S `S)
    (T `T) (U `U) (V `V) (W `W) (X `X) (Y `Y) (Z `Z) Wrt