Twinx with dates affects xaxis intervals for future plots

827 views Asked by At

I am creating a GUI application with a MatplotlibWidget. Based on the user's selection in the MatplotlibWidget the graph can be:

A. a function y1(t), where y1 is float and t is datetime,

B. a function y1(t), y2(t) where y2 to be a float and with y2 to be ploted at the twinx axis, or

C. a function y1(y2) (y1, y2 floats, not datetime)

Every time the user changes the selection the axes are cleared and the new plot is showing in the MatplotlibWidget.

The problem is than when plotting the B selection and then the C, the xaxis preserves the interval from the dates and adds the new y2 interval. This results to huge xaxis interval far away from the interval of y2. This also happens when I try to plot only the twinx y2(t) without the y1(t) in the main axis.

I've also tried to plot an empty dataset in twinx for the C selection with xdata the same as the original xaxis and it works for the simple code presented here but it does not work in my original code..

One idea would be to delete/remove twinx axis. I've tried delaxes but still it does not change something.

Is there any ideas why this happens and how could I solve this problem?

Thanks!

Here is a more simplified version of the code:

from datetime import datetime
import matplotlib.pyplot as plt

y1 = range(0, 10)
y2 =  range(-10, -20, -1)
t = [datetime(2015, 10, i) for i in range(1, 11)]

# Create the plot
plt.figure()
ax1 = plt.subplot(111)

# A. Plot y1(t)
ax1.plot(t, y1, 'b')
plt.xlabel('t')
plt.ylabel('y1')
plt.draw()
print 'Xaxis interval y1(t) ax1: ', ax1.get_xlim()
# plt.show()

# C. Plot y1(y2)
ax1.clear()
ax1.plot(y2, y1, 'r')
plt.gcf().autofmt_xdate()
plt.xlabel('y2')
plt.ylabel('y1')
plt.draw()
print 'Xaxis interval y1(y2) ax1:', ax1.get_xlim(), '(correct)'
# plt.show()

# B. Plot y1(t) and y2(t)
ax1.clear()
ax2 = ax1.twinx()
ax2.plot(t, y2, 'g')
ax1.plot(t, y1, 'b')
plt.xlabel('t')
plt.ylabel('y1')
ax2.set_label('y2')
plt.draw()
print 'Xaxis interval y2(t) ax1:', ax1.get_xlim()
print 'Xaxis interval y2(t) ax2: ', ax2.get_xlim()
# plt.show()


# # Plot only y2(t) in twinx
# ax1.clear()
# ax2 = ax1.twinx()
# ax2.plot(t, y2, 'g')
# plt.xlabel('t')
# ax2.set_label('y2')
# plt.draw()
# print 'Xaxis interval y2(t): ax1',ax1.get_xlim()
# print 'Xaxis interval y2(t): ax2',ax2.get_xlim()
# # plt.show()

# C. Plot y1(y2)
ax1.clear()
ax2.clear()
ax1.plot(y2, y1, 'r')
plt.xlabel('y2')
plt.ylabel('y1')
plt.draw()
print 'Xaxis interval y1(y2), ax1: ',ax1.get_xlim(), '(wrong)'
print 'Xaxis interval y1(y2) ax2: ',ax2.get_xlim(), '(wrong)'
plt.show()

With results:

Xaxis interval y1(t) ax1: (735872.0, 735881.0)

Xaxis interval y1(y2) ax1: (-19.0, -10.0) (correct)

Xaxis interval y2(t) ax1: (735872.0, 735881.0)

Xaxis interval y2(t) ax2: (735872.0, 735881.0)

Xaxis interval y1(y2), ax1: (-100000.0, 800000.0) (wrong)

Xaxis interval y1(y2) ax2: (-100000.0, 800000.0) (wrong)

2

There are 2 answers

3
user1941126 On

how about ax1.autoscale() and ax2.autoscale() before drawing?

Keep in mind that this sets the "autoscale" property for the axes, so if you don't destroy them when refreshing the data it should work fine.

also you can do:

plt.cla() #clears axis
ax1.plot(y2,y1,'r')
ax2.plot(y2,y1,'b')
plt.axes([min(y2),max(y2), min(y1), max(y1)])

(this works as what I assume you wanted in t he beginning)

I don't know what happens with multiple axes objects though...

I'm not really familiar with matplotlib but there must be a much better way to update your charts.

Hope that helps!

0
elina On

One solution that I found and works for me is to delete both ax1 and ax2 and create a new subplot (new ax1) when I want to plot y1(y2) after having creating ax2 and ploting datetime on it.

from datetime import datetime
import matplotlib.pyplot as plt

y1 = range(0, 10)
y2 =  range(-10, -20, -1)
t = [datetime(2015, 10, i) for i in range(1, 11)]

# Create the plot
plt.figure()
ax1 = plt.subplot(111)

# B. Plot y1(t) and y2(t)
ax1.clear()
ax2 = ax1.twinx()
ax2.plot(t, y2, 'g')
ax1.plot(t, y1, 'b')
plt.xlabel('t')
plt.ylabel('y1')
ax2.set_label('y2')
plt.draw()
print 'Xaxis interval y2(t) ax1:', ax1.get_xlim()
print 'Xaxis interval y2(t) ax2: ', ax2.get_xlim()
# plt.show()

# C. Plot y1(y2)
plt.delaxes(ax1)
plt.delaxes(ax2)
ax1 = plt.subplot(111)
ax1.plot(y2, y1, 'r')
# ax2.plot(y2, [None for i in range(len(y2))])
plt.xlabel('y2')
plt.ylabel('y1')
plt.draw()
print 'Xaxis interval y1(y2), ax1: ',ax1.get_xlim()
plt.show()

Xaxis interval y2(t) ax1: (735872.0, 735881.0)

Xaxis interval y2(t) ax2: (735872.0, 735881.0)

Xaxis interval y1(y2), ax1: (-19.0, -10.0)