Matplotlib | Change the orientation to portrait - python

I have this scrip to plot 7 series in the same page. I would like to set the page orientation to Portrait. As you can see bellow, I have tried:
f.savefig(sta+'.pdf', orientation='portrait', format='pdf')
But nothing happens!
Do you have any suggestion?
f, (ax1, ax2, ax3, ax4, ax5, ax6, ax7) = plt.subplots(7, sharex=True, sharey=False)
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.5)
ax1.plot(xtr[:num.size(xt),i], color='black')
ax2.plot(ytr[:num.size(yt),i], color='black')
ax3.plot(ztr[:num.size(zt),i], color='black')
ax4.plot(obs_dataV[:,i], color='g')
ax5.plot(obs_dataH[:,i], color='r')
ax6.plot(obs_dataP, color='g')
ax7.plot(obs_dataS, color='r')
ax1.set_title( sta+' Raw data', loc='left', fontsize='10')
ax4.set_title('Vertical and Horizontal traces', loc='left', fontsize='10')
ax6.set_title('Characteristic functions', loc='left', fontsize='10')
ax1.legend('X',loc='center right', fontsize='12')
ax2.legend('Y',loc='upper right', fontsize='12')
ax3.legend('Z',loc='upper right', fontsize='12')
ax4.legend('P',loc='upper right', fontsize='12')
ax5.legend('S',loc='upper right', fontsize='12')
ax6.legend('P',loc='upper right', fontsize='12')
ax7.legend('S',loc='upper right', fontsize='12')
f.savefig(sta+'.pdf', orientation='portrait', format='pdf')
plt.show()
Thanks in advance :-)

I think you're wanting to change the figure size, rather than anything having to do with page layout. The orientation kwarg to savefig really only applies to the PS and EPS backends. For a PDF, the page size is defined as equal to the figure size, so it has no effect.
As a quick example of what your current results might look like:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(nrows=7, sharex=True, sharey=False)
fig.subplots_adjust(hspace=0.5)
plt.show()
To change the size of the figure, use the figsize kwarg:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(nrows=7, figsize=(8, 11), sharex=True, sharey=False)
fig.subplots_adjust(hspace=0.5)
plt.show()

Related

Is there a way to plot two cartopy maps as subplots in the same figure?

I have attempted to achieve this following the code provided at the end of this page.
What I have tried is the following:
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(24, 10))
fig.suptitle('Comparison of 1970-2000 and 2070-2100 Soil Moisture Content')
ax1 = plt.axes(projection=ccrs.PlateCarree())
ax1.set_title('Under SSP245 Scenario')
cf1 = ax1.contourf(lon_hist, lat_hist, mrsos_change45, transform=ccrs.PlateCarree(), cmap='BrBG')
fig.colorbar(cf1, ax=ax1)
ax1.set_aspect('equal', adjustable=None)
ax1.add_feature(ctp.feature.BORDERS, linestyle='-', alpha=1)
ax1.coastlines(resolution='10m')
ax1.add_feature(ctp.feature.OCEAN, zorder=100, edgecolor='k')
ax1.coastlines()
ax1.gridlines(draw_labels=True)
ax2 = plt.axes(projection=ccrs.PlateCarree())
ax2.set_title('Under SSP585 Scenario')
cf2 = ax2.contourf(lon_hist, lat_hist, mrsos_change85, cf1.levels, transform=ccrs.PlateCarree(), cmap='BrBG')
fig.colorbar(cf2, ax=ax2)
ax2.set_aspect('equal')
ax2.add_feature(ctp.feature.BORDERS, linestyle='-', alpha=1)
ax2.coastlines(resolution='10m')
ax2.add_feature(ctp.feature.OCEAN, zorder=100, edgecolor='k')
ax2.coastlines()
ax2.gridlines(draw_labels=True)
plt.show()
But this only produces one the second of the two cartopy maps that I am trying to produce.
Unfortunately, I am unable to provide the data I am using as it is very large data files. But can anyone see mistakes in the code that stops it from producing the first one?
You create ax1 and ax2 then destroy/redefine both ax1 and ax2 in your code. The solution is creating them correctly in the first place, and do not redefine them.
# modified code (relevant parts only)
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy
# Use subplot_kw to declare the projection
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(24, 7), subplot_kw={"projection": ccrs.PlateCarree()})
fig.suptitle('Comparison of 1970-2000 and 2070-2100 Soil Moisture Content')
#ax1 = plt.axes(projection=ccrs.PlateCarree()) #this destroys/redefines ax1
ax1.set_title('Under SSP245 Scenario')
#cf1 = ax1.contourf(lon_hist, lat_hist, mrsos_change45, transform=ccrs.PlateCarree(), cmap='BrBG')
#fig.colorbar(cf1, ax=ax1)
ax1.set_aspect('equal', adjustable=None)
ax1.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
#ax1.coastlines(resolution='10m')
ax1.add_feature(cartopy.feature.OCEAN, zorder=100, edgecolor='k')
ax1.coastlines()
ax1.gridlines(draw_labels=True)
#ax2 = plt.axes(projection=ccrs.PlateCarree()) #this destroys/redefines ax2
ax2.set_title('Under SSP585 Scenario', fontsize=14, va='bottom', backgroundcolor="white")
#cf2 = ax2.contourf(lon_hist, lat_hist, mrsos_change85, cf1.levels, transform=ccrs.PlateCarree(), cmap='BrBG')
#fig.colorbar(cf2, ax=ax2)
#ax2.set_aspect('equal')
ax2.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
#ax2.coastlines(resolution='10m')
ax2.add_feature(cartopy.feature.OCEAN, zorder=100, edgecolor='k')
ax2.coastlines()
ax2.gridlines(draw_labels=True)
plt.show()

The following is my matplotlib but i think there's something wrong in it

fig=plt.figure()
ax1=fig.add_axes([0,0,1,1])
ax2=fig.add_axes([0.2,0.5,0.4,0.4])
ax1.set_xlim([0,100])
ax1.set_ylim([0,10000])
ax2.set_xlim([20,22])
ax2.set_ylim([30,50])
ax1.set_ylabel('Z')
ax1.set_xlabel('X')
ax1.xaxis.set_major_locator(ticker.MultipleLocator(2000))
ax1.yaxis.set_major_locator(ticker.MultipleLocator(20))
ax2.set_ylabel('Y')
ax2.set_xlabel('X')
ax2.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax2.yaxis.set_major_locator(ticker.MultipleLocator(0.5))
This is printing out the following plot.
Fixed tick locators, adjusted subplot positioning, organized code a bit, hid spines, added dashed y grid, increased tick label font sizes.
fig, ax1 = plt.subplots(figsize=(12,8))
ax2 = fig.add_axes([0.575,0.55,0.3,0.3])
ax1.set_xlim([0,100])
ax1.set_ylim([0,10000])
ax1.set_xlabel('X', fontweight='bold')
ax1.set_ylabel('Z', rotation=0, fontweight='bold')
ax1.xaxis.set_major_locator(ticker.MultipleLocator(20))
ax1.yaxis.set_major_locator(ticker.MultipleLocator(1000))
ax1.grid(axis='y', dashes=(8,3), color='gray', alpha=0.3)
ax2.set_xlim([20,22])
ax2.set_ylim([30,50])
ax2.set_xlabel('X', fontweight='bold')
ax2.set_ylabel('Y', rotation=0, fontweight='bold')
ax2.xaxis.set_major_locator(ticker.MultipleLocator(0.5))
ax2.yaxis.set_major_locator(ticker.MultipleLocator(5))
for ax in [ax1, ax2]:
[ax.spines[s].set_visible(False) for s in ['top','right']]
ax.tick_params(axis='both', labelsize=12, left=False, bottom=False)

Matplotlib: Minor ticks not showing

for some reason my minor ticks in my plot are not showing anymore. Yesterday, I still had them in and I just don't know what I changed such that they disappeared...
Here is my code:
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
fig, axs = plt.subplots(nrows=1, ncols=1, sharex=True, sharey=True)
font = font_manager.FontProperties(family='sans-serif', style='normal', size=16)
for (i, alpha) in enumerate(alpha_values_small):
filt = data[
(data["Topology"] == "UNIFORM") &
(data["HashingPowerDistribution"] == "UNIFORM") &
(data["CentralityMeasure"] == "RANDOM") &
(data["Alpha"] == alpha)]
axs.plot(
1/filt["Gamma"],
filt["OrphanBlockRate"],
label=r"$\alpha = {}$".format(np.round(alpha, 2)),
color=color_list[i],
marker=marker_list[i],
linestyle="",
markersize=12,
linewidth=1.5,
markeredgewidth=2,
)
axs.set_xscale("log")
axs.set_xlabel(r"$\lambda_{nd}$", fontfamily='sans-serif', fontsize=22)
axs.set_ylabel("Orphan block rate", fontfamily='sans-serif', fontsize=22)
axs.tick_params(which='major', direction="in", top=True, left=True, right=True, width=1.5, size=6, labelsize=16)
axs.tick_params(which='minor', direction="in", top=True, left=True, right=True, width=1, size=4, labelsize=16)
axs.legend(prop=font, frameon=False)
plt.show()
This produces the following output:
Does anyone know why it's not showing my minor ticks?
Thank you so much in advance!!
I believe minor ticks are visible only if there is enough space.
You may try to increase the figure size
fig, axs = plt.subplots(..., figsize=(10,10))
or decrease the font size.

How to Return a MatPlotLib Figure with its corresponding Legend

I'm trying to define a function which returns a pre-styled figure with certain grid, style, width and other properties. However, when I return the fig and its axes, the legend is missing. Here's a simplified example:
def getfig():
plt.style.use('default')
fig, axs = plt.subplots(1, 1, figsize=(1,1), sharey=False)
if issubclass(type(axs),mpl.axes.SubplotBase):
axs=[axs]
for ax in axs:
ax.grid(color='grey', axis='both', linestyle='-.', linewidth=0.4)
ax.legend(loc=9, bbox_to_anchor=(0.5, -0.3), ncol=2)
return fig,axs
fig,axs=getfig()
axs[0].plot(range(10), label="label")
What am I missing?
Thanks!
UPDATE:
This is what I'm using so far but I think there really should be a way to force all future legends associated to a figure to have a certain style.
def fig_new(rows=1,columns=1,figsize=(1,1)):
plt.style.use('default')
fig, axs = plt.subplots(rows,columns, figsize=figsize, sharey=False)
if issubclass(type(axs),mpl.axes.SubplotBase):
axs=[axs]
for ax in axs:
ax.grid(color='grey', axis='both', linestyle='-.', linewidth=0.4)
return fig,axs
def fig_leg(fig):
for ax in fig.get_axes():
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.3), ncol=5)
fig,axs=fig_new()
axs[0].plot(range(10), label="label")
fig_leg(fig)
You need to call the legend after an artist with a label is plotted to the axes.
An option is to let the function return the arguments to use for the legend afterwards.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
def getfig():
plt.style.use('default')
fig, axs = plt.subplots(1, 1, figsize=(1,1), sharey=False)
if issubclass(type(axs),mpl.axes.SubplotBase):
axs=np.array([axs])
legendkw = []
for ax in axs:
ax.grid(color='grey', axis='both', linestyle='-.', linewidth=0.4)
legendkw.append(dict(loc=9, bbox_to_anchor=(0.5, -0.3), ncol=2))
return fig,axs,legendkw
fig,axs,kw=getfig()
axs[0].plot(range(10), label="label")
for i,ax in enumerate(axs.flat):
ax.legend(**kw[i])
plt.show()

Python: Suplots with secondary-axis

I wrote the following code below to do the following graph:
fig, ax = plt.subplots(figsize=(8, 6))
ax.patch.set_facecolor('white')
ax.plot(df.index, df.X1.values, 'b',
label='NMA', linewidth=1.5)
ax.set_ylabel('Index')
ax2 = ax.twinx()
ax2.plot(df.index, df.Y.values, 'r--',
label='Rate', linewidth=1.5)
ax2.set_ylabel('Rate')
lines = ax.get_lines() + ax2.get_lines()
lgd = ax.legend(lines, [line.get_label() for line in lines],
loc='lower center', ncol=2, bbox_to_anchor=(0.5, -0.15),
frameon=False)
ax.set_title('Economic Rate and Index',
weight='bold')
for i in range(5):
plt.axvspan(Dates['Peak'][i], Dates['Trough'][i],
facecolor='grey', alpha=0.5)
plt.grid(False)
plt.savefig('C:\\test.pdf',
bbox_extra_artists=(lgd,), bbox_inches='tight')
I am having a hard time to reproduce this figure in a subplot (2X2). The only thing I would change in each of the subplots is the blue line (X1 in df... for X2, X3...). How can I have a 2X2 subplot of the above graph? Of Course I would only keep one legend at the bottom of the subplots. Thanks for the help.
The data is here and the "Dates" to reproduce the gray bars here.
This is how you could create a 2x2 raster with twinx each:
import matplotlib.pyplot as plt
fig, ((ax1a, ax2a), (ax3a, ax4a)) = plt.subplots(2, 2)
ax1b = ax1a.twinx()
ax2b = ax2a.twinx()
ax3b = ax3a.twinx()
ax4b = ax4a.twinx()
ax1a.set_ylabel('ax1a')
ax2a.set_ylabel('ax2a')
ax3a.set_ylabel('ax3a')
ax4a.set_ylabel('ax4a')
ax1b.set_ylabel('ax1b')
ax2b.set_ylabel('ax2b')
ax3b.set_ylabel('ax3b')
ax4b.set_ylabel('ax4b')
plt.tight_layout()
plt.show()
Result:

Categories