As a demonstration, I'm plotting x^0 through x^9 with x values in range from 10 to 20.
Then I'm slicing those images so that I have 9 slices:
x = (10 to 11), (11 to 12) etc. to (18 to 19)
I want my images cropped so that y values are always spread from top to bottom in each slice, but what I'm getting is autoscale always scales to the full dataset rather than the current slice.
import matplotlib.pyplot as plt
import numpy as np
# create some test data
for i in range(10):
x = np.arange(10,20)
y = x**i
plt.plot(x,y,c='red',marker='.',ms=2)
# get all x values in chart and reduce to a sorted list set
xd = []
for n in range(len(plt.gca().get_lines())):
line = plt.gca().get_lines()[n]
xd.append((line.get_xdata()).tolist())
xd = [item for sublist in xd for item in sublist]
xd = sorted(list(set(xd)))
# attempt to plot slices of x with autoscaled y
ax = plt.gca()
for i in range(len(xd)-1):
ax.set_xlim([xd[i],xd[i+1]])
ax.axes.autoscale(enable=True,axis='y', tight=True)
plt.pause(1) #timing
#uncommenting the next line will create nine tiny (6kb) image files
#plt.savefig(('image_%s.png' % i), bbox_inches=0, dpi=48)
In my actual application, I'm attempting to generate 100k tiny images in this manner as a database from stochastic data. For every x there are between 2 and 200 y values. Then I'm using OpenCV to image match new images to the best fit amongst the historical database.
Its critical that the y values are stretched from top to bottom in each image for OpenCV to find a good match.
if it helps my x values will always be int() type and equally spaced
ETA: I've attempted to implement some of the solutions here but have made no progress:
Matplotlib - fixing x axis scale and autoscale y axis
Matplotlib scale y axis based on manually zoomed x axis
but at least I've learned:
Autoscaling always uses the full range of the data, so the y-axis is scaled by full extent of the y-data, not just what's within the x-limits.
still no solution that works here though
def autoscale_y()
presented by @DanHickstein
gives me:
h = np.max(y_displayed) - np.min(y_displayed)
ValueError: zero-size array to reduction operation maximum which has no identity
From those links, I'm unsure where to implement @Joe Kington's mask solution in my for loops.
I'm now working with @bernie solution proposed here to get Y values given X:
How to extract points from a graph?
maybe then I can set_ylim() given the min and max Y values at that X manually?
This would be so much easier if there was a way to autoscale within the defined xlim as a standard matplotlib method