Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib add a specific tick presenting axis max - multiple scales single observation

Trying to plot observations respectively to multiple scales per observation, I've managed to produce the following plot:

enter image description here

However I would like to add a tick presenting the y-max value in each scale, regardless of the gap between it and the previous tick. An example of a such plot is presented below . It is produced when the y-max is a multiple of the ticking interval.

enter image description here

Thanks, F.

Here is the code used to produce these example.

import numpy as np
import pylab as pl
import matplotlib as plt
import matplotlib.ticker as ticker
import matplotlib.transforms

def add_scales(fig, axes, scales, subplot_reduction_factor=0.1, margin_size=50):
    nb_scales = len(scales)
    b,l,w,h = zoom_ax.get_position().bounds

    _, ymax = axes.get_ylim()

    # Saves some space to the right so that we can add our scales
    fig.subplots_adjust(right=1-(subplot_reduction_factor)*nb_scales)

    for (n, (vmin, vmax, color, label, alignment)) in enumerate(scales):

        # Adjust wrt. the orignial figure's scale 
        nax = fig_zoom.add_axes((b,l,w,(h * alignment) / ymax))
        nax.spines['right'].set_position(('outward', -40+n*margin_size))
        nax.set_ylim((vmin,vmax))

        # Move ticks and label to the right
        nax.yaxis.set_label_position('right')
        nax.yaxis.set_ticks_position('right')

        # Hides everything except yaxis
        nax.patch.set_visible(False)
        nax.xaxis.set_visible(False)
        nax.yaxis.set_visible(True)
        nax.spines["top"].set_visible(False)
        nax.spines["bottom"].set_visible(False)

        # Color stuff
        nax.spines['right'].set_color(color)
        nax.tick_params(axis='y', colors=color)
        nax.yaxis.set_smart_bounds(False)
        #nax.yaxis.label.set_color(color)

        if label != None:
            nax.set_ylabel(None)

if __name__ == '__main__':

    a=(np.random.normal(10,5,100))

    a=np.linspace(0,100,100) 
    c=np.linspace(0,80, 100)
    d=np.linspace(0,40,100)


    fig_zoom = plt.pyplot.figure()
    zoom_ax = fig_zoom.add_subplot(1,1,1)


    zoom_ax.plot(a,c)
    zoom_ax.plot(a,d)
    zoom_ax.set_title('Zoom')
    zoom_ax.set_xlabel('A')
    zoom_ax.set_ylabel('B')
    zoom_ax.set_ylim((0,100))
    zoom_ax.grid()
    add_scales(fig_zoom, 
               zoom_ax, [(0,.55,'green',None,40),
                          (0,.85,'blue',None,80)])

    fig_zoom.savefig(open('./test.svg','w'),format='svg')
like image 373
François Kawala Avatar asked Oct 05 '22 18:10

François Kawala


1 Answers

You can set the highest ytick value to your maximum. If the second highest ytick value and your maximum are very close, the labels might clutter.

Try adding this to your loop:

tcks = nax.get_yticks()
tcks[-1] = vmax
nax.set_yticks(tcks)

enter image description here

like image 72
Rutger Kassies Avatar answered Oct 10 '22 17:10

Rutger Kassies