How to plot a timeline

I want to ask how I can plot a timeline like this one in Julia

1 Like

Except for the curly braces, It can be done with GMT. But with some work. See inspiring examples here plus the custom axes here

Thanks for the reply. I am looking at the PGFPlots package, but haven’t figured out how to do it.

I find PGFPlotsX.jl very useful for these situations where there exists a solution which you can copy and modify for use in Julia. The solution for this plot can be found on stackexchange.

The following example shows how PGFPlotsX can be used for copying an existing solution, this is by no means best practices and is essentially just copying of text. Note that there exists several options in the documentation of the package to facilitate the transfer of data from Julia to fit you needs when creating the plot.

using PGFPlotsX

#Add necessary preamble information once
if !in(raw"\usetikzlibrary{decorations.pathreplacing}",PGFPlotsX.CUSTOM_PREAMBLE)
    push!(PGFPlotsX.CUSTOM_PREAMBLE,
    raw"\usetikzlibrary{decorations.pathreplacing}
        \definecolor{myLightGray}{RGB}{191,191,191}
        \definecolor{myGray}{RGB}{160,160,160}
        \definecolor{myDarkGray}{RGB}{144,144,144}
        \definecolor{myDarkRed}{RGB}{167,114,115}
        \definecolor{myRed}{RGB}{255,58,70}
        \definecolor{myGreen}{RGB}{0,255,71}")
end

function plot_tline()
       
    tp = @pgf TikzPicture(
    {
        "every node/.style"={
        font=raw"\scriptsize",
        text_height="1ex",
        text_depth=".25ex",
        },
    },)

    push!(tp,
        raw"% draw horizontal line   
        \draw[->] (0,0) -- (8.5,0);
        
        % draw vertical lines
        \foreach \x in {0,1,...,8}{
            \draw (\x cm,3pt) -- (\x cm,0pt);
        }
        
        % place axis labels
        \node[anchor=north] at (3,0) {$t-2$};
        \node[anchor=north] at (4,0) {$t-1$};
        \node[anchor=north] at (5,0) {$t$};
        \node[anchor=north] at (6,0) {$t+1$};
        \node[anchor=north] at (8.5,0) {years};
        
        % draw scale above
        \fill[myLightGray] (1,0.25) rectangle (2,0.4);
        \fill[myDarkGray] (2,0.25) rectangle (3,0.4);
        \fill[myDarkRed] (3,0.25) rectangle (4,0.4);
        \fill[myRed] (4,0.25) rectangle (5,0.4);
        \draw[myRed,dashed,thick,-latex] (5.05,0.325) -- (6.05,0.325);
        
        % draw scale below
        \fill[myLightGray] (3,-0.4) rectangle (4,-0.55);
        \fill[myGray] (4,-0.4) rectangle (5,-0.55);
        \fill[myGreen] (5,-0.4) rectangle (6,-0.55);
        \draw[myGreen,dashed,thick,-latex] (6.05,-0.475) -- (7.05,-0.475);
        
        % draw curly braces and add their labels
        \draw[decorate,decoration={brace,amplitude=5pt}] (3,0.45) -- (5,0.45)
            node[anchor=south,midway,above=4pt] {Training period};
        \draw[decorate,decoration={brace,amplitude=5pt}] (6,-0.6) -- (5,-0.6)
            node[anchor=north,midway,below=4pt] {Testing period};"
    )
    return tp
end

tp=plot_tline()
display(tp)
#pgfsave("tline.tikz", tp)
1 Like

Thanks for the reply. I am aware of this solution, is there a Julian way of doing this? I prefer Julia syntax to LaTex syntax.

If you are interested in having this a tikzed picture, as the example you showed, I’m not sure that there are many options using only Julia code to generate what you need. I would suggest reading through the documentation of PGFPlotsX, using as much of the functionality within there as you like and then writing you own functions to convert the data you need displayed to the correct tikz syntax and pushing that to the plot.

1 Like

Ok, here is the GMT solution (had to play a little with the vertical offsets). And since we have no curly braces (would have to construct a custom symbol), I used a double arrow.

using GMT

basemap(region=(0,10,0,1), frame=(axes=:S, ticks=1), figsize=15, par=(MAP_FRAME_TYPE=:inside, MAP_TICK_LENGTH=0.5), y_off=5)
basemap!(frame=(axes=:S,), xaxis=(custom=(pos=[3; 4; 5; 6], type=["a t-2", "a t-1", "a t", "a t+1"]),), par=(MAP_FRAME_TYPE=:graph, MAP_VECTOR_SHAPE=1, MAP_TICK_LENGTH=0))
text!(text_record([10.5 0], "years"), font=12, justify=:CB, noclip=true, y_off=-0.5)
lines!([3 0; 4 0], pen=(16,200), y_off=-0.6)
lines!([4 0; 5 0], pen=(16,150))
lines!([5 0; 6 0], pen=(16,:green))
arrows!([6 0 0 1.5], arrow=(length="10p", stop=true), fill=:green, pen=(1,:green, :dashed), noclip=true, y_off=0.15)
arrows!([5 0 0 1.5], arrow=(length="4p", start=true, stop=true), lw=0.5, noclip=true, fill=:black, y_off=-0.4)
text!(text_record([5.5 0], "Testing period"), font=12, justify=:CB, noclip=true, y_off=-0.6)
# Now the upper side
lines!([1 0; 2 0], pen=(16,200), y_off=2.6)
lines!([2 0; 3 0], pen=(16,150))
lines!([3 0; 4 0], pen=(16,[150 100 100]))
lines!([4 0; 5 0], pen=(16,:red))
arrows!([5 0 0 1.5], arrow=(length="10p", stop=true), fill=:red, pen=(1,:red, :dashed), noclip=true, y_off=0.15)
arrows!([3 0 0 3.0], arrow=(length="4p", start=true, stop=true), lw=0.5, noclip=true, fill=:black, y_off=0.4)
text!(text_record([4.0 0], "Training period"), font=12, justify=:CB, noclip=true, y_off=0.3, fmt=:png, savefig="timeline", show=true)

6 Likes

What is the difference between PGFPlots and PGFPlotsX?

from

It is similar in spirit to the package PGFPlots.jl but it tries to have a very close mapping to the PGFPlots API as well as minimize the number of dependencies. The fact that the syntax is similar to the TeX version means that examples from Stack Overflow and the PGFPlots manual can easily be incorporated in the Julia code.

Thanks for the clarification. Do you mind sharing me how to draw the timeline with PGFPlotsX?

@MrUrq already gave you a solution,

1 Like

I am learning the GMT package now. When I run your code, I got the error message:

ERROR: error compiling finish_PS_module: error compiling gmt: could not load library “libgmt”
libgmt.so: cannot open shared object file: No such file or directory

In addition, how do I save the figure as a png file. Thanks.

You are in Linux, I presume. When you do using GMT it will warn you if GMT (not GMT.jl) is installed (internally it does the equivalent of run(`gmt --version`)). Didn’t you get any warning? What GMT version have you installed?

To choose the image format use fmt:png or :PNG, :jpg, :pdf. The upper case PNG is used for images with transparency. To give a file name do safefig="filename", otherwise the file is saved in tmp directory with a generic name.

Yes, I am running Julia 1.1.0 on Fedora 30. I have already installed GMT.jl, and using GMT gives no warning message. GMT.jl is version 0.10.0.

When I run the code:

basemap(region=(0,10,0,1), frame=(axes=:S, ticks=1), figsize=15, par=(MAP_FRAME_TYPE=:inside, MAP_TICK_LENGTH=0.5), y_off=5)

The error message showed up:

ERROR: error compiling finish_PS_module: error compiling gmt: could not load library "libgmt"
libgmt.so: cannot open shared object file: No such file or directory

I have installed GMT 5.4.5 on my laptop.

I tried this code on windows 10, but still failed.

That error message makes think on a shared lib trouble (if I remember well there were some caused by an update of the netCDF lib). I know it works well in Linux because the Travis tests run in a Linux VM (see the .travis.yml to how it builds the GMT package (the C lib)).

Regarding the Windows version, you should have followed the advice in the GMT.jl readme page that points users to the GMT6 dev version. GMT5 works too but there many things that have slight different syntax and it’s hard for me to make it work in all cases.

Later today we’ll make public the GMT 6.0 RC1 version (source code already here)

I followed the instructions for my fedora machine on this link:
https://gmt.soest.hawaii.edu/projects/gmt/wiki/BuildingGMT
but still got the error.

What error? Just tried in my machine with GMT5.4.5 and it worked too.

Regarding the Linux build, you proceeded well but as I said the error message makes think on a dependency problem on the Linux libs.

On the linux shell, does this create a plot with a black circle in the middle? (I mean a ps file with that figure)

echo 0 0 | psxy -R-1/1/-1/1 -Ba1 -JX12c -Sc0.5 -G0 -P > test.ps

Yes, I got the figure. In fedora I need to do this:

echo 0 0 | gmt psxy -R-1/1/-1/1 -Ba1 -JX12c -Sc0.5 -G0 -P > test.ps

which adds the gmt before psxy

So is it Julia that can’t find libgmt.so? Can you add its location to LD_LIBARYPATH?
As I said, for running the test I don’t need to do it but I never understood why in *nix sometimes one has to do it and others not.

How can I add its location to LD_LIBARYPATH?