I have found that I can not get axes autoscale to work on the 1st axes after creating a second axes using twinx. Is this expected?
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 10, 0.1)
y1 = 0.05 * x**2
y2 = -1 *y1
fig, axL = plt.subplots() # Make Left Axes
axR = axL.twinx() # Make Left Axes
axL.plot(x, y1, 'g-') # Plot on Left
axL.grid()
axL.autoscale(enable=True, axis=u'both', tight=False)
plt.show()
# Do some stuff then later plot on axR
When I run the above code it autoscales in the y-direction correctly on the left axes (0 to 5) but changes the X-Axis scale to +/- 0.06 instead of the correct 0 to 10. However, once axR is no longer blank and something is plotted on axR it behaves as I would expect.
This is only an example as I first came across this issue in more complicated PyQT4 GUI that allows the user to create multiple subplots & left/right combinations. Since the user is the one manually controlling the plot creation order it is possible for the above situation to present itself.
Is there a way for autoscale to work with a blank twinx right axes. Or is the Xlimit just going to have to be manually set?
FYI, I am using Python 3.4 as part of Anaconda v2.0.1 with Matplotlib v1.3.1
Thanks.
This is merely a workaround than a proper solution or explanation.
Simply add an invisible point in the right axes so it is not completely empty:
axR.plot(0, 0, visible=False)
You have to make sure though, that the invisible point lies within the ranges of the data that you plot in axL. E.g.:
axR.plot(np.mean(x),np.mean(y1),visible=False)
As for an explanation (I'm guessing):
axR.dataLim is [-np.inf, np.inf] initially. The union of axR.dataLim and axL.dataLim still gives [-np.inf, np.inf] which is then collapsed to [0,0].
EDIT: This was fixed recently (here). Upgrading to matplotlib v1.4.* should solve the problem.
Related
For my thesis I use the mplstereonet package to plot stereographic projections of points and planes obtained by using the ObsPy package. For my application I want to use azimuth labels that plot at a given angle outside of the circle. I am not using axis labels since they may overlap with possible data points in the centre of the circle.
The arguments of the set_azimuth_ticks function are:
positions of ticks around the circle in degrees
labels of ticks
distance of ticks from the circle. 1 is on, 0.9 is inside and 1.1 is outside the circle.
This is the code I use alongside my result:
I obtain this result:
enter image description here
As you can see the labels are way too far from the circle.
import mplstereonet
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='stereonet')
ax.grid()
ax.set_azimuth_ticks([0],['N'], frac = 0.9)
I'm noticing a difference in behaviour between a python3.7 environment (which places the labels where I expect them) and a python 3.9 environment where they are too far out as the original poster observed. As a workaround, I am using this:
import mplstereonet as mpls
fig, ax = mpls.subplots(figsize=[5, 5])
ax.set_azimuth_ticks([])
just to remove the unsightly, bizarrely far away labels.
I was experiencing same issue as OP even in python3.7. My workaround, if labels are desired, uses ax.text with ax.transAxes transformation to position labels wrt plot axes. Remove bad labels as previous answer and add the following:
...
label = np.arange(0,360,45)
labx= 0.5-0.55*np.cos(np.radians(label+90))
laby= 0.5+0.55*np.sin(np.radians(label+90))
for i in range(len(label)):
ax.text(labx[i],laby[i],str(int(label[i]))+'\N{DEGREE SIGN}', \
transform=ax.transAxes, ha='center', va='center')
Create a function with the code above if additional flexibility is needed. If you're plotting color bar or plot title you'll need to pad elements appropriately.
I am running python 3.9 and have the same issue with the ticks plotting way too far away from the axis. I found this workaround on the github site for this issue:
Add the line "ax._polar.set_position(ax.get_position())" before calling plt.show().
This resolved the issue. Hopefully they fix the code soon in mpl though
I am trying to customize the xticks and yticks for my scatterplot with the simple code below:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
y_ticks = np.arange(10, 41, 10)
x_ticks = np.arange(1000, 5001, 1000)
ax.set_yticks(y_ticks)
ax.set_xticks(x_ticks)
ax.scatter(some_x, some_y)
plt.show()
If we comment out the line: ax.scatter(x, y), we get an empty plot with the correct result:
However if the code is run exactly as shown, we get this:
Finally, if we run the code with ax.set_yticks(yticks) and ax.set_xticks(xticks) commented out, we also get the correct result (just with the axes not in the ranges I desire them to be):
Note that I am using Python version 2.7. Additionally, some_x and some_y are omitted.
Any input on why the axes are changing in such an odd manner only after I try plotting a scatterplot would be appreciated.
EDIT:
If I run ax.scatter(x, y) before xticks and yticks are set, I get odd results that are slightly different than before:
Matplotlib axes will always adjust themselves to the content. This is a desirable feature, because it allows to always see the plotted data, no matter if it ranges from -10 to -9 or from 1000 to 10000.
Setting the xticks will only change the tick locations. So if you set the ticks to locations between -10 and -9, but then plot data from 1000 to 10000, you would simply not see any ticks, because they do not lie in the shown range.
If the automatically chosen limits are not what you are looking for, you need to set them manually, using ax.set_xlim() and ax.set_ylim().
Finally it should be clear that in order to have correct numbers appear on the axes, you need to actually use numbers. If some_x and some_y in ax.scatter(some_x, some_y) are strings, they will not obey to any reasonable limits, but simply be plotted one after the other.
Ok, this is my first time asking a question on here, so please be patient with me ;-)
I'm trying to create a series of subplots (with two y-axes each) in a figure using matplotlib and then saving that figure. I'm using GridSpec to create a grid for the subplots and realised that they're overlapping a little, which I don't want. So I'm trying to use tight_layout() to sort this out, which according to the matplotlib documentation should work just fine. Simplifying things a bit, my code looks something like this:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure(num=None, facecolor='w', edgecolor='k')
grid = gridspec.GridSpec(2, numRows)
# numRows comes from the number of subplots required
# then I loop over all the data files I'm importing and create a subplot with two y-axes each time
ax1 = fig.add_subplot(grid[column, row])
# now I do all sorts of stuff with ax1...
ax2 = ax1.twinx()
# again doing some stuff here
After the loop for data processing is done and I have created all the subplots, I eventually end with
fig.tight_layout()
fig.savefig(str(location))
As far as I can work out, this should work, however when calling tight_layout(), I get a ValueError from the function self.subplotpars: left cannot be >= right. My question is: How do I figure out what's causing this error and how do I fix it?
I've had this error before, and I have a solution that worked for me. I'm not sure if it will work for you though. In matplotlib, the command
plt.fig.subplots_adjust()
can be used to sort of stretch the plot. The left and bottom stretch more the smaller the number gets, while the top and right stretch more the greater the number is. So if left is greater than or equal to the right, or bottom is greater than or equal to the top, than the graph would kind of flip over. I adjusted my command to look like this:
fig = plt.figure()
fig.subplots_adjust(bottom = 0)
fig.subplots_adjust(top = 1)
fig.subplots_adjust(right = 1)
fig.subplots_adjust(left = 0)
Then you can fill in your own numbers to adjust this, as long as you keep the left and bottom smaller. I hope this fixes your problem.
I want a simple x,y plot created with matplotlib stretched physically in x-direction.
The intention is to get a result were it is easier for me to detect features in the signal.
So I don't want to change any scales or values or limits. Just change the distance between two gridpoint in my output file...
I want to do that on four subplots which should have the same size afterwards.
Thanks in advance... I tried for hours now and I think one of you could probably help me...
David Zwicker already solved my problem in this special case, thanks a lot for that, but in general... If I plot 2 subplots like in this code:
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
plot(u_av,z)
ax2 = fig.add_subplot(1,2,2)
plot(pgrd_av,z)
clf()
and want to stretch only one of them. What can I do?
You can change the figure size by using plt.figure(figsize=(20,5)). See the documentation of the figure command.
I know, this is a bit out of the context. But if someone is looking for a solution while using pandas plot which internally uses matplotlib. Here is the solution.
df.plot('col_x', 'col_y', title='stretched_plot', figsize=(20, 1))
You can directly add axes to the canvas at an arbitrary position with plt.axes(). For instance:
ax1 = plt.axes([0, 0, 3, 0.5])
ax2 = plt.axes([0, 0.6, 1, 1])
You can do this:
x = 1.5 # or your needed amount
plt.plot(x_array * x, y_array)
Your line or graph will move to the right depending on your x value
I have multiple lines to be drawn on the same axes, and each of them are dynamically updated (I use set_data), The issue being that i am not aware of the x and y limits of each of the lines. And axes.autoscale_view(True,True,True) / axes.set_autoscale_on(True) are not doing what they are supposed to. How do i auto scale my axes?
import matplotlib.pyplot as plt
fig = plt.figure()
axes = fig.add_subplot(111)
axes.set_autoscale_on(True)
axes.autoscale_view(True,True,True)
l1, = axes.plot([0,0.1,0.2],[1,1.1,1.2])
l2, = axes.plot([0,0.1,0.2],[-0.1,0,0.1])
#plt.show() #shows the auto scaled.
l2.set_data([0,0.1,0.2],[-1,-0.9,-0.8])
#axes.set_ylim([-2,2]) #this works, but i cannot afford to do this.
plt.draw()
plt.show() #does not show auto scaled
I have referred to these already, this , this.
In all cases I have come across, the x,y limits are known. I have multiple lines on the axes and their ranges change, keeping track of the ymax for the entire data is not practical
A little bit of exploring got me to this,
xmin,xmax,ymin,ymax = matplotlib.figure.FigureImage.get_extent(FigureImage)
But here again, i do not know how to access FigureImage from the Figure instance.
Using matplotlib 0.99.3
From the matplotlib docs for autoscale_view:
The data limits are not updated automatically when artist data are changed after the artist has been added to an Axes instance. In that case, use matplotlib.axes.Axes.relim() prior to calling autoscale_view.
So, you'll need to add two lines before your plt.draw() call after the set_data call:
axes.relim()
axes.autoscale_view(True,True,True)