# Tips to create beautiful, publication-quality plots

**URL:** <https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384>\
**Category:** General Usage\
**Tags:** plotting, plots\
**Created:** [December 17, 2019, 1:53pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384 "2019-12-17T13:53:05Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 1:53pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/1 "2019-12-17T13:53:05Z")

</div>

Edit: an equivalent blog post is available here, as suggested by colleagues:

[https://nextjournal.com/leandromartinez98/tips-to-create-beautiful-publication-quality-plots-in-julia](https://nextjournal.com/leandromartinez98/tips-to-create-beautiful-publication-quality-plots-in-julia)

* * *

I was about to send an e-mail to my students with a series of tips to produce good looking plots with Julia, and decided to post the tips here instead. I hope this is useful for more people, and please let me know of any other tips, nice examples, and possible corrections.

To exemplify, I will describe how to produce this figure, which was published recently [[LINK]](https://doi.org/10.1002/prot.25843), and contains many details in its construction which are worth mentioning:

 ![all](https://global.discourse-cdn.com/julialang/original/3X/c/a/ca8d87c5bbd024dbe6d590a2efa1b1989aeac10c.png)

To start with, I am using `Plots` with `GR` (the default option), with

```julia
using Plots

```

I will also use the following packages:

```julia
using LaTeXStrings
using Statistics
using ColorSchemes

```

And I will use one function from a in-house package we have to build one density function from data (probably other options exist):

```julia
using M3GTools # from https://github.com/mcubeg/M3GTools

```

Initially, the layout of the plot is set using

```julia
plot(layout=(2,2))

```

meaning two rows and two columns. I start defining a variable, called `sp` (for `subplot`), which will define in which subplot the following commands will operate:

```julia
sp=1

```

Subplot 1 contains data for a series of labels (1G6X to 1BXO) which are colored sequentially. This was done as follows. The list of labels is defined with

```julia
names = ["1AMM", "1ARB", "1ATG", "1B0B", "1BXO", "1C52", "1C75", "1D06", "1D4T", "1EW4", "1FK5", "1G67", "1G6X", "1G8A", "1GCI"]  

```

To plot the data associated with each label with a different color, I used:

```julia
  for i in 1:length(names)
    c = get(ColorSchemes.rainbow,i./length(names))
    plot!(subplot=sp,x,y[i,:],linewidth=2,label=names[i],color=c)
  end 

```

(I am assuming that in `x` the data is the same for all plots, and is stored in vector `x[ndata]`, and the plotted data in `y` is in an array `y` of size `y[length(names),ndata]`.

One of the limitations of `GR` as plotting back-end is the managing of special characters. To define the labels of the axes, therefore, we use `LaTeXStrings` and, furthermore, we change the font of the text such that it is not that different from the standard font of the tick labels and legend:

```julia
plot!(xlabel=L"\textrm{\sffamily Contact Distance Threshold / \AA}",subplot=sp)
plot!(ylabel=L"\textrm{\sffamily Probability of~}n\leq n_{XL\cap DCA}",subplot=sp)   

```

The interesting features of the second plot are the overlapping bars, and the variable labels in the `x` axis and their angle.

The labels in the `x`-axis are defined in a vector (here, amino acid residue types):

```julia
restypes = ["ALA", "ARG", "ASN", "ASP", "CYS", "GLU", "GLN", "GLY", "HIS", "ILE", "LEU", "LYS", "MET", "PHE", "PRO", "SER", "THR", "TRP", "TYR", "VAL"] 

```

Start with

```julia
sp=2

```

to change where the next commands will operate.

The plot contains two sets of data (red and blue), which we plot using `bar!`. First the red data, labeled DCAs. We use `alpha=0.5` so that the red color becomes more soft:

```julia
bar!(dca_data,alpha=0.5,label="DCAs",color="red",subplot=sp)

```

The second set of data, “XLs”, will be blue and will overlap the red data. We also used this call to `bar!` to define the `xticks` with custom labels, and the rotation of the labels:

```julia
bar!(xl_data,alpha=0.5,xrotation=60,label="XLs",xticks=(1:1:20,restypes),color="blue",subplot=sp)

```

Finally, we set the labels of the axes, also using Latex and changing fonts:

```julia
bar!(xlabel=L"\textrm{\sffamily Residue Type}",ylabel=L"\textrm{\sffamily Count}",subplot=sp)  

```

The peculiarity of the third plot (`sp=3`) (bottom left) is that we have two data sets defined in different ranges, but we want to plot bars with the same width for both sets. This requires a “trick”.

Initially, we tested some different number of bins for one of the sets until we liked the result. We found that for the blue set 40 bins were nice:

```julia
histogram!(xl_data,bins=40,label="XLs",alpha=1.0,color="blue",subplot=sp)

```

Now we need to adjust the number of bins of the other set such that both have the same width. We find out the bin width by computing the range of the “XL” (blue) set above, and dividing it by 40:

```julia
xl_bin = ( maximum(xl_data) - minimum(xl_data) ) / 40   

```

The number of bins of the other (DCA - red) set, will be, therefore, computed from the maximum and minimum values of this set and the bin width:

```julia
ndcabins = round(Int64,( maximum(all_dca) - minimum(all_dca) ) / xl_bin)

```

And this number of bins is used to plot the bars of the red set:

```julia
histogram!(dca_data,bins=ndcabins,label="DCAs",alpha=0.5,color="red",subplot=sp)

```

In this plot we also plot some dots indicating the mean of each distribution, something that we did with:

```julia
m1 = mean(dca_data)
scatter!([m1,m1,m1,m1],[100,104,108,112],label="",color="red",linewidth=3,linestyle=:dot,subplot=sp,markersize=3) 

```

(the y-positions of the dots were set by hand). And, of course, we use Latex to set the axis labels again:

```julia
histogram!(xlabel=L"\textrm{\sffamily C}\alpha\textrm{\sffamily~Euclidean Distance} / \textrm{\sffamily~\AA}",subplot=sp)
histogram!(ylabel=L"\textrm{\sffamily Count}",subplot=sp)  

```

The fourth plot (`sp=4`, bottom right) is similar to the third, but it contains a density function (instead of the bars) for one of the data sets (“All contacts” - green). This density function was computed using our own function, using:

```julia
x, y = M3GTools.density(all_max_contact_surfdist,step=1.0,vmin=1.0)

```

and plotted with:

```julia
plot!(x,y,subplot=sp,label="All contacts",linewidth=2,color="green",alpha=0.8)

```

We also added the figure labels A, B, C, D. This was done with the `annotate` option. The trick here is to add these annotations to the last plot, such that they stay above every other plot element:

```julia
fontsize=48
annotate!( -1.8-16.5, 500, text("A", :left, fontsize), subplot=4)
annotate!( -1.8, 500, text("B", :left, fontsize), subplot=4)
annotate!( -1.8-16.5, 200, text("C", :left, fontsize), subplot=4)
annotate!( -1.8, 200, text("D", :left, fontsize), subplot=4)  

```

(the positions were set by hand, but they are quite easy to align because we need only two positions in `x` and two positions in `y`).

Last but not least, we save the figure in PDF format (saving it to PNG directly does not provide the same result, at least in my experience):

```julia
plot!(size=(750,750))
savefig("./all.pdf")  

```

PDF is a vector graphic format, so that the size does not define the resolution. The `size=(750,750)` is used to define the overall size of the plot in what concerns the relative font sizes. Thus, this size is adjusted until the font sizes are nice taking into account the final desired plot size in print.

If required (and I do that), I open this final plot in GIMP, converting it to a bitmap with 300dpi resolution, and save it to TIFF or PNG depending on what I want to do with the figure later.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [December 17, 2019, 2:17pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/2 "2019-12-17T14:17:14Z")

</div>

This is great work and will help lots of people creating nice plots.

One thing I have to complain is about colors. Plot A will be problematic for color blind (red-green) people. See e.g. [Picking a colour scale for scientific graphics | Better Figures](https://betterfigures.org/2015/06/23/picking-a-colour-scale-for-scientific-graphics/)

I think you already know about this and it is more about technical aspects on how to generate plots in general. But I thought I say it anyways for others who are not yet aware of this.

---

<div class="post-metadata">

**Author:** ![Olivier\_Merchiers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/olivier_merchiers/32/4073_2.png) [@Olivier\_Merchiers](https://discourse.julialang.org/u/Olivier_Merchiers)\
**Post date:** [December 17, 2019, 2:40pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/3 "2019-12-17T14:40:13Z")

</div>

Thanks for sharing.  
Looks very nice.  
Are the other figures (1 and 3) of the paper also generated with Julia?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 2:51pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/4 "2019-12-17T14:51:45Z")

</div>

A second example [[LINK]](https://pubs.rsc.org/en/content/articlelanding/2019/CP/C9CP05196A#!divAbstract). This example is interesting because we have added non-linear fits to scatter plots, and there are some tricks to get the same colors for specific sets of data in different plots and annotations.

The example figure is this one:

 ![hbonds6M](https://global.discourse-cdn.com/julialang/original/3X/5/a/5a40fe53d5a2eb10bc4228cedb5e467017746c09.png)

Here, we use the following packages:

```julia
using Plots
using DelimitedFiles
using LsqFit
using LaTeXStrings

```

We used the `DelimitedFiles` package to read the data, with

```julia
file = "./data/data.dat"
data = readdlm(file,comments=true,comment_char='#') 
time = data[:,1] # time in the first column
hbonds = data[:,3] # data in the third column

```

The layout is the same as that of the first example `plot(layout=(2,2))`, and I will focus in the new features used only. Subplots 1 and 2 (upper ones), are bar plots which contain error bars:

```julia
labels=["BCL as acceptor","BCL as donor"]
bar!(labels,y,label="",subplot=sp,color=[1,2],yerr=yerr,ylim=[0,ymax])
plot!(ylabel=L"\textrm{\sffamily Urea H-bonds}",subplot=sp)
plot!(title="Deprotonated",subplot=sp)

```

Note that “ymax” was adjusted, so that in this case it is the same in both plots, for comparison.  
The error bars are added with `yerr`, and the labels of the x-axis were defined with the `labels` vector, defined before the plot.

We will perform exponential fits to some of our data to produce the plots “C” and “D”. We define the model here (it will be used by the `LsqFit` package):

```julia
# Exponential fit model
@. model(x,p) = exp(-x/p[1])
p0 = [0.5] # initial guess

```

For each data set, the fit is performed with

We will perform exponential fits to some of our data to produce the plots “C” and “D”. We define the model here (it will be used by the `LsqFit` package):

```julia
fit = curve_fit(model,times,lifetime,p0)

```

(`times` and `lifetime` are the vector containing the actual `x` and `y` data).

And the final characteristic time is, in this case, the first element of the array that is retrieved by the `coef` function of `LsqFit`, given the `fit` result:

```julia
tau = coef(fit)[1]  

```

Using the parameter from the fit, we can generate data to plot a line corresponding to the model. The trick here is to the use the `collect` function to generate a `x` vector, and then the model already defined to obtain the `y` data given the parameters:

```julia
x = collect(0:0.01:10)
y = model(x,[tau])

```

The fit will be plotted as a line, accompanied by the scatter of the actual data:

```julia
idata=1
plot!(x,y,linewidth=2,subplot=sp,label="BCL as acceptor",color=idata)
scatter!(times,lifetime,label="",color=idata,subplot=sp)

```

Note the color definition `idata=1`. This will guarantee that the the two data sets are ploted with the same color. Now we want to write an annotation with that same color. This is tricky, and is done with:

```julia
color=get_color_palette(:auto, plot_color(:white), 5)[idata]

```

(I don’t even understand the details of this command, but it works). It will retrieve the color in the current colorscale associated with the index `idata`. With this it is possible to write annotations with the desired colors, but again some tricks are required. We need to parse the string using `raw` and `latextrings`, to use the `text` option of the `annotate` function and change the color of the text:

```julia
note=raw"\large\textrm{\sffamily "*"$tau_avg"*raw"} \pm \textrm{\sffamily "*"$tau_std"*raw"}"
annotate!( 0.0, 0.04, text(latexstring(note), :left, 7, color=color),subplot=sp) 

```

(the complication here with the `raw` function is only because we want to use the Latex fonts and the \pm symbol in those annotations).

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 2:52pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/5 "2019-12-17T14:52:09Z")

</div>

Very nice remark. I am not completely aware of that.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 3:00pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/6 "2019-12-17T15:00:34Z")

</div>

No, those figures were done by students and, if I am not mistaken, the first plot was done using `gnuplot` and the third in `R`.

Nevertheless, beautiful contact maps can be done with the `heatmap` function in Julia.

---

<div class="post-metadata">

**Author:** ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)\
**Post date:** [December 17, 2019, 3:26pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/7 "2019-12-17T15:26:19Z")

</div>

nice! this could have a lot of reach in the form of a Julia blog post 😄

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 4:12pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/8 "2019-12-17T16:12:52Z")

</div>

Is that a suggestion about which I can do anything?

---

<div class="post-metadata">

**Author:** ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)\
**Post date:** [December 17, 2019, 4:34pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/9 "2019-12-17T16:34:29Z")

</div>

For what i know, there always a need to blog posts about julia, as a form of outreach, Discurse has the disadvantage of having a hard discoverability, but a blog doesn’t have that inconvenient. Also, there is a page, [Julia Bloggers](https://www.juliabloggers.com/), that help reach a larger portion of people that doesn’t have necessarily an account on Discourse.  
For example, the rust community directy [calls for community blog posts](https://blog.rust-lang.org/2018/01/03/new-years-rust-a-call-for-community-blogposts.html), julia as a language can benefit a lot from the outreach generated from things like this 😃

---

<div class="post-metadata">

**Author:** ![bashonubuntu](https://avatars.discourse-cdn.com/v4/letter/b/f19dbf/32.png) [@bashonubuntu](https://discourse.julialang.org/u/bashonubuntu)\
**Post date:** [December 17, 2019, 4:50pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/10 "2019-12-17T16:50:47Z")

</div>

I second the suggestion to make this a blog. Discourse will likely have comments interspersed with your helpful plotting tips, so it may be best to make it a full blogpost elsewhere.

---

<div class="post-metadata">

**Author:** ![tshort](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tshort/32/43_2.png) [@tshort](https://discourse.julialang.org/u/tshort)\
**Post date:** [December 17, 2019, 5:10pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/11 "2019-12-17T17:10:36Z")

</div>

[Nextjournal](https://nextjournal.com/sdanisch) would be a good place for a blog like this. You could show examples.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 6:05pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/12 "2019-12-17T18:05:49Z")

</div>

Nice. I created an equivalent blog post here:

> **[Tips to create beautiful, publication-quality plots in Julia](https://nextjournal.com/leandromartinez98/tips-to-create-beautiful-publication-quality-plots-in-julia)**
>
> I was about to send an e-mail to my students with a series of tips to produce good looking plots with Julia, and decided to post the tips here instead. I hope this is useful for more people, and please let me know of any other tips, nice examples,...

Yet without actual running examples, but perhaps another day. I will sent it to Julia Bloggers.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [December 17, 2019, 7:09pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/13 "2019-12-17T19:09:23Z")

</div>

Nice examples!

Should `using Statstics` be `using Statistics`?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 17, 2019, 7:47pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/14 "2019-12-17T19:47:43Z")

</div>

fixed

---

<div class="post-metadata">

**Author:** ![isentropic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/isentropic/32/11894_2.png) [@isentropic](https://discourse.julialang.org/u/isentropic)\
**Post date:** [December 19, 2019, 6:01am UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/15 "2019-12-19T06:01:38Z")

</div>

Do you by chance know how to make serif axes ticks so that it displays correctly in scientific notation. This was my biggest problem with GR. And just changing fonts in general.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 19, 2019, 2:02pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/16 "2019-12-19T14:02:46Z")

</div>

You can use Latex for the ticks with, for example:

```julia
x=rand(10) ; y=rand(10)
plot(x,y)
xlabels=[L"10^{-3}",L"10^{-2}",L"10^{-1}"]
plot!(xticks=(0:0.5:1,xlabels))

```

You might change the font to serif using:

```julia
xlabels=[L"\textrm{\sffamily 10}^{\textrm{\sffamily -3}}",L"10^{-2}",L"10^{-1}"]

```

(here I changed the first one). Or, if you want the exponent to be smaller, using

```julia
 xlabels=[L"\textrm{\sffamily 10}^{\textrm{\sffamily\tiny -3}}",L"10^{-2}",L"10^{-1}"]

```

Of course this is quite unpractical and probably a function should be written for converting  
the tick labels into that format. The result is:

 ![plot](https://global.discourse-cdn.com/julialang/original/3X/4/e/4ef453b509ebbf727c51135f92d07790728222b0.png)

(again, I changed to serif only the first tick label).

(also, in my experience always save the figure to PDF an convert it other formats using GIMP or other software)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 20, 2019, 3:10pm UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/17 "2019-12-20T15:10:02Z")

</div>

Adding to the previous answer, I wrote the function (because I will use it myself, for sure). This is a working example:

```julia

using LaTeXStrings
using Formatting

# First parameter: number, second parameter: number of decimal places
# optional font parameter: if anything else than "sf", will be default latex font

function latex_sci_not( x , ndec; font="sf" )
  xchar = strip(Formatting.sprintf1("%17.$(ndec)e",x))
  data = split(xchar,"e")
  inonzero = findfirst( i -> i != '0', data[2][2:length(data[2])])
  if font == "sf"
    f = "\\textrm{\\sffamily "
    fe = "\\textrm{\\sffamily\\scriptsize "
  else
    f = "{"
    fe = "{"
  end
  if inonzero == nothing
    string = latexstring("$f$(data[1])}")
  else
    if data[2][1] == '-'
      string = latexstring("$f$(data[1])}\\times $f 10}^{$fe$(data[2][1])$(data[2][inonzero+1:length(data[2])])}}")
    else
      string = latexstring("$f$(data[1])}\\times $f 10}^{$fe$(data[2][inonzero+1:length(data[2])])}}")
    end
  end
  return string
end

x = rand(10) ; y = rand(10) ;

ticks = collect(0:0.2:1)
ticklabels = [latex_sci_not(x,2) for x in ticks]
plot(x,y,xticks=(ticks,ticklabels))
plot!(size=(300,300))
savefig("teste.pdf")

```

Which produces:

 ![teste](https://global.discourse-cdn.com/julialang/original/3X/6/0/60449613774c3ca0800a718fd1f7a11edbdd0f60.png)

---

<div class="post-metadata">

**Author:** ![isentropic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/isentropic/32/11894_2.png) [@isentropic](https://discourse.julialang.org/u/isentropic)\
**Post date:** [December 23, 2019, 6:36am UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/18 "2019-12-23T06:36:29Z")

</div>

Thank you for sharing this. I just wish there was a simpler way to achieve this. In my job, units usually require sci. notation, log scales pretty often. Here, for example, you have a problem with 0.0 on X axis. The spacing of “-” in the exponent of 10s weird. Typically, “x10^{-1}” is typed off the axes, to mean that everything on this axis is to be multiplied by “x10^{-1}”. I wish Plots.jl would support common scientific needs.

Right now, it feels like both Plots.jl and Makie.jl are made by developers just to showcase their products. I feel that common needs of a scientist is to have very fast yet beatiful plotting system with minimal config from users side. Things like like exponents off the axis (and axes offsets) should be naturally taken care of by the plotting environment.

Currently, PyPlot achieves offsetting exponents and serves well. It is, yet the best plotting system Julia has. GR is immature to plot consistently. Gnuplot suffers from offsets and exponents too. I just wish someone to meet these common needs. Here is what I mean in an example:

```julia
using PyPlot
using Plots
using Gaston
gr()
x = collect(@. (10^-5 * (1:10)) + 1)
y = collect(@. (10^-13 * (1:10)) + 10);
PyPlot.plot(x, y)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/c/f/cffd7df3f28aa5caa408e2024cc5960dc6f4cb0c.png)

```julia
Plots.plot(x,y)

```

Just exits with error

```julia
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
GKS: Rectangle definition is invalid in routine SET_WINDOW
GKS: Rectangle definition is invalid in routine SET_WINDOW
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
GKS: Rectangle definition is invalid in routine SET_WINDOW
GKS: Rectangle definition is invalid in routine SET_WINDOW

```

Gnuplot

```julia
Gaston.plot(x,y)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/e/6/e6856cdbfb97d1ce7ac9be03a6adcb9969fb34f9.png)

Plots pyplot:

```julia
pyplot()
Plots.plot(x, y)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/f/8/f8c8a8e99b4e0cf77b46af53488c044f5dd0bfca.png)

```julia
┌ Warning: No strict ticks found
└ @ PlotUtils /home/zhanibek/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168
┌ Warning: No strict ticks found
└ @ PlotUtils /home/zhanibek/.julia/packages/PlotUtils/EybJR/src/ticks.jl:168

```

Errors for some mysterious reasons.

Take this is with a grain of salt, but this is a typical scenario for a scientist, and s/he will be very frustrated to see that a common user case just straight up fails miserably. It could be my buggy system and installation, but it would happen to some people, and that is a great discouragement to use Julia on a constant basis. `Plots` is just immature. We need to focus on this alongside “time-to-first-plot”, it does not matter how fast julia gets booted if it fails to plot a simple line.

I love Julia for its speed and problems it solves, it really changed the way I do my work. But Julia has no:

- No mature (consistently working) plotting system. Plots tries to be jack of all, but just ends up being bad at some use case. `PyPlot` is the only thing what would work for the most general case
- Too many plotting unpolished plotting packages: `PGFPlotsX`, `Gaston`, `Makie`, `Gadfly`, `Winston` …

For me, the only way to plot in Julia has been `PyPlot` with `seaborn`, which produces fairly good-looking plots, without any hassle, with `pdf` output it serves as almost “Publication Quality”, fonts look consistent and equally spaced (although offsets are not latex formatted, but at least it has it)

![image](https://global.discourse-cdn.com/julialang/original/3X/0/c/0c036908422d0789ff6d2aa44466d3166f8a7b84.png)

I have been looking to get `Plots` to workout, but I always come to find some unexpected behaviours. Could someone point me toward a better solution for plotting? I really wish I am wrong about my opinion about `Plots`, please help me to just find a better solution.

My system:

```julia
              _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.0.5 (2019-09-09)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/  

    Status `~/.julia/environments/v1.0/Project.toml`
  [537997a7] AbstractPlotting v0.9.10
  [6e4b80f9] BenchmarkTools v0.4.3
  [336ed68f] CSV v0.5.16
  [717857b8] DSP v0.6.1
  [a93c6f00] DataFrames v0.19.4
  [0c46a032] DifferentialEquations v6.9.0
  [31c24e10] Distributions v0.21.7
  [7a1cc6ca] FFTW v1.1.0 #master (https://github.com/JuliaMath/FFTW.jl.git)
  [4af5e9cd] Findpeaks v0.0.0 #master (https://github.com/tungli/Findpeaks.jl)
  [59287772] Formatting v0.4.1
  [f7f18e0c] GLFW v3.1.0
  [4b11ee91] Gaston v0.10.0 #master (https://github.com/mbaz/Gaston.jl.git)
  [7073ff75] IJulia v1.20.2
  [a98d9a8b] Interpolations v0.12.5
  [2fda8390] LsqFit v0.8.1
  [47be7bcc] ORCA v0.3.0 #master (https://github.com/sglyon/ORCA.jl.git)
  [429524aa] Optim v0.19.4
  [d96e819e] Parameters v0.12.0
  [5ad8b20f] PhysicalConstants v0.2.0
  [995b91a9] PlotUtils v0.6.1
  [f0f68f2c] PlotlyJS v0.13.0 #master (https://github.com/sglyon/PlotlyJS.jl.git)
  [91a5bcdd] Plots v0.27.0 #master (https://github.com/JuliaPlots/Plots.jl.git)
  [438e738f] PyCall v1.91.2
  [d330b81b] PyPlot v2.8.2
  [295af30f] Revise v2.3.1
  [79098fc4] Rmath v0.6.0
  [6038ab10] Rotations v0.12.0 #master (https://github.com/FugroRoames/Rotations.jl)
  [90137ffa] StaticArrays v0.11.1
  [2913bbd2] StatsBase v0.32.0
  [f3b207a7] StatsPlots v0.12.0
  [a759f4b9] TimerOutputs v0.5.3
  [37b6cedf] Traceur v0.3.0
  [37e2e46d] LinearAlgebra 
  [10745b16] Statistics 

```

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [December 23, 2019, 8:48am UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/19 "2019-12-23T08:48:45Z")

</div>

FWIW I can reproduce this in Plots currently, however I’m not sure this kind of tone is very helpful in encouraging people who have put in quite a bit of effort to get `Plots` and other packages to the place they are now to invest more of their time in solving your problems.

It appears that PyPlot is doing something automagically here for certain values of x- and y-ticks, have you opened an issue on the Plots repo to see whether somethingn like this could be implemented?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 23, 2019, 9:21am UTC](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384/20 "2019-12-23T09:21:43Z")

</div>

> [@isentropic](#):
>
> both Plots.jl and Makie.jl are made by developers just to showcase their products

Please consider the possibility that you are extremely misinformed about this. I am not even sure what you consider the “products” here.

> [@isentropic](#):
>
> Too many plotting unpolished plotting packages: `PGFPlotsX`

PGFPlotsX is just a very thin layer on the LaTeX library pgfplots, which is very mature and polished.

[Next page](https://discourse.julialang.org/t/tips-to-create-beautiful-publication-quality-plots/32384.md?page=2)
