1

I need to generate a figure in PDF format for better quality (eps would still be good). In the figure, I need an oscillatory background, which is the actual signal, with a thin linewidth and a thicker (3 times) moving average filter line in the middle.

If I save the image in .png the desired linewidths are kept, the same does not apply for .pdf, .eps and .pgf, for which there seems to be a minimum linewidth, even though I didn't find anything in this sense on the docs. I'm running on Spyder with Python 3.7.3, updated matplotlib. I tried both to specify the linewidth into the ax.plot() call and also from rcParams but the behavior does not change: only .png keeps the correct format.

I attach the function which does the actual plot:

import matplotlib.pyplot as plt
import numpy as np

def data_plot(xaxis, sequences, xlabel, ylabel, legend, widths,
             alphas, colors, fil):

    n = len(sequences)    
    fig, ax = plt.subplots(figsize=(10,6))

    for i in range(n):
        ax.plot(xaxis, sequences[i], linewidth=widths[i], alpha=alphas[i], 
                color=colors[i])
        ax.plot(xaxis[int(fil/2)-1:len(xaxis)-int(fil/2)], 
                np.convolve(sequences[i],np.ones(fil)/fil,mode='valid'),
                linewidth=4*widths[i], alpha=2*alphas[i], color=colors[i], 
                label=legend[i])

    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.legend(loc='upper right', prop={'size': 12})

    plt.show()

seq = [np.random.uniform(12,14,500), np.random.uniform(11,12.5,500), 
np.random.uniform(12.7,15,500)]
x = np.linspace(1,100,500)
data_plot(x,seq,'x','y',['A','B','C'],
          [0.2,0.2,0.2],[0.5,0.4,0.3],['C0','C1','C2'],10)

plt.savefig('figure.png')
plt.savefig('figure.pdf')
giova
  • 19
  • 5
  • Please telll is what linewidth you tried. – Jody Klymak Aug 20 '19 at 13:13
  • 1
    That is, always use [mcve]s when asking about undesired behaviour of code. – ImportanceOfBeingErnest Aug 20 '19 at 13:21
  • Sorry, you are right. I called the method with this widths parameter: [0.4,0.3,0.2], but I tried to change it. If I call it with [0.1,0.1,0.1] the behavior is also more evident. This is why I would say that there exists a minimum supported. – giova Aug 20 '19 at 13:27
  • I provided a minimal working example. The code saves the figure in .png and .pdf and to me they are different. I would like the .pdf to look like the .png image as for what described above. – giova Aug 20 '19 at 16:06
  • Did you end up finding a solution? I've got a similar problem. – M. Boyet Aug 19 '20 at 19:44
  • No, no solution to this problem. I ended up saving the figure in PNG format with higher DPI and then converting it to PDF. Very poor solution. – giova Aug 20 '20 at 20:08

1 Answers1

1

In case others land here, I had the same issue and it turned out it was due to the PDF viewer. Specifically, with Foxit Reader Version 11.0.0.49893; see here. After uninstalling and downgrading to 10.1.3 linewidths display properly. So please check with another viewer.

However, this is not the problem with OP's script. Running it saves blank images. This is because of the plt.show called before plt.savefig; see here for explanation. You could, for example, move the savefig inside the function, or return the fig. The linewidths will then show correctly on the saved PDF/PNG files: saved plot

Pasting code below. *Increased linewidth from '4' to '20' for emphasis.

import matplotlib.pyplot as plt
import numpy as np

def data_plot(xaxis, sequences, xlabel, ylabel, legend, widths,
             alphas, colors, fil):

    n = len(sequences)    
    fig, ax = plt.subplots(figsize=(10,6))

    for i in range(n):
        ax.plot(xaxis, sequences[i], linewidth=widths[i], alpha=alphas[i], 
                color=colors[i])
        ax.plot(xaxis[int(fil/2)-1:len(xaxis)-int(fil/2)], 
                np.convolve(sequences[i],np.ones(fil)/fil,mode='valid'),
                linewidth=20*widths[i], alpha=2*alphas[i], color=colors[i], 
                label=legend[i])
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.legend(loc='upper right', prop={'size': 12})

    plt.show()
    return fig


seq = [np.random.uniform(12,14,500), np.random.uniform(11,12.5,500), 
np.random.uniform(12.7,15,500)]
x = np.linspace(1,100,500)
fig = data_plot(x,seq,'x','y',['A','B','C'],
          [0.2,0.2,0.2],[0.5,0.4,0.3],['C0','C1','C2'],10)

fig.savefig('figure.png')
fig.savefig('figure.pdf')
Odysseus
  • 81
  • 2
  • This does not solve the issue: the problem is due to the thinner background noise, which is thicker in .pdf format. – giova Jun 17 '21 at 12:08