Search code examples
pythonmatplotliblinestyle

Matplotlib Line Overlap/Resolution


I'm making a plot in Matplotlib where it is imperative for different lines to not overlap when they have differing x-values. For some reason, when I draw lines, there is overlap if they are close enough together (but not overlapping). For example,

fig = plt.figure(num=None, facecolor='w', edgecolor='k')
ax = fig.add_subplot(2, 1, 1)
ax.plot((0, 10000000), (3, 3), linewidth = 2, markersize = 0, clip_on = True, aa = True)
ax.plot((10000001, 200000001), (3, 3), linewidth = 1, markersize = 0, clip_on = True, aa = True)

plt.savefig('test.png', format='png')

enter image description here I want the blue line and the green line to not overlap at all, since 10000000 < 10000001.

I made the blue line slightly thicker, so if you zoom in, you can see how the blue and green lines overlap. I made the dpi very high, so it isn't a resolution problem. I will have to be dealing with large numbers because I am working with genome data--are the large numbers an issue? When I plot with x-values of (0 to 10000) and (10001, 20000), the problem still exists.

Thanks so much for your help.


Solution

  • It has to do with the cap style of the Line2D object, the default style is 'projecting', which result in overlapping, see a zoom-in-ed PDF: enter image description here

    We want to change it to 'butt' style:

    L1=ax.plot((0, 10000000), (3, 3), linewidth = 2, markersize = 0, clip_on = True, aa = True)
    L2=ax.plot((10000001, 200000001), (3, 3), linewidth = 1, markersize = 0, clip_on = True, aa = True)
    for item in L1+L2:
        item.set_solid_capstyle('butt')
    

    enter image description here

    The gap is very small, sure, since it is 1/10000000.

    Or if you want, a quick dirty solution is just to draw a small white circle marker of size=1 at (10000000.5, 3).


    fig, ax = plt.subplots(1, 1, figsize=(8, 4))
    
    L1 = ax.plot((0, 1), (1, 1), linewidth=10, label='No capstyle')
    L2 = ax.plot((1, 2), (1, 1), linewidth=7, label='No capstyle')
    
    
    L3 = ax.plot((0, 1), (0.9, 0.9), linewidth=10, solid_capstyle='butt', label='With butt capstyle')
    L4 = ax.plot((1, 2), (0.9, 0.9), linewidth=7, solid_capstyle='butt', label='With butt capstyle')
    
    ax.set_ylim(0, 2)
    ax.grid()
    ax.legend()
    

    enter image description here