Draw a line on a figure with multiple axes - python

I have created a figure with multiple axes and added AnchoredText to some of these axes. This AnchoredText is like a label which connects the axis in which it resides to an outer axis, like this:
[Example image]
I have tried using AnnnotationBbox like this:
from matplotlib import pyplot as plt
from matplotlib.offsetbox import AnchoredText, AnnotationBbox, TextArea
fig_width = 16
fig_height = 9
fig = plt.figure(figsize=(fig_width, fig_height))
fig.add_axes(
(0, 0, 1, 1),
alpha=1,
xticks=[],
yticks=[],
)
fig.get_axes()[-1].set_xlim(0, fig_width)
fig.get_axes()[-1].set_ylim(0, fig_height)
fig.add_axes(
(0.66, 0.225, 0.075, 0.025),
label="L1",
alpha=1,
xticks=[],
yticks=[],
)
axis = fig.get_axes()[-1]
axis.set_xlim(
fig_width * 0.66, fig_width * (0.66 + .075)
)
axis.set_ylim(
fig_height * .225, fig_height * (.225 + .025)
)
circle = AnchoredText(
s="L1",
frameon=False,
loc="upper left",
prop=dict(bbox=dict(boxstyle="circle")),
)
axis.add_artist(circle)
fig.add_axes(
(0.62, 0.28, 0.03, 0.04),
label="L2",
alpha=1,
xticks=[],
yticks=[],
)
axis = fig.get_axes()[-1]
axis.set_xlim(
fig_width * 0.62, fig_width * (0.62 + .03)
)
axis.set_ylim(
fig_height * .28, fig_height * (.28 + .04)
)
def get_axes(fig, name):
for ax in fig.axes:
label = ax.get_label()
if label == name:
return ax
l1 = get_axes(fig, "L1") # Gets axis with given label
l2 = get_axes(fig, "L2")
offsetbox = TextArea("Test")
# Get the top outer limit of the l2 axis
xlim = (l2.get_xlim()[0] + l2.get_xlim()[1]) / 2
ylim = l2.get_ylim()[1]
xy = [xlim, ylim]
# Approximating the coordinates of AnchoredText
xlim2 = l1.get_xlim()[0] * 0.25
ylim2 = l1.get_ylim()[0] * 0.75
xy2 = [xlim2, ylim2]
ab = AnnotationBbox(
offsetbox,
xy2,
xybox=xy,
xycoords="data",
boxcoords=("axes fraction", "data"),
box_alignment=(0.0, 0.5),
arrowprops=dict(arrowstyle="-"),
)
l1.add_artist(ab)
plt.show()
Running the code above does not add the line in my figure and I'm not sure why. Is there a better way to approach this problem? How can I get the limit of the AnchoredText, if at all?

Here is stab at it. The trick is to plot the subplots in one general blank (and transparent) axes and then plot a line connecting the subplots.
from matplotlib import pyplot as plt
from matplotlib.offsetbox import AnchoredText
# Initialize figure
fig, ax_canvas = plt.subplots(figsize=(12, 6), constrained_layout=True)
# Set order of drawing, Ax canvas will be the last one so that the line connecting the other plots is on top
ax_canvas.set_zorder(10)
# Hide the main axis to set our blank canvas
ax_canvas.set_axis_off()
# Make background transparent so that it does not cover other plots when we draw the connecting line
ax_canvas.patch.set_facecolor('None')
ax_canvas.patch.set_visible(False)
# Set dimensions so it's easier to plot the line correctly
ax_canvas.set_xlim([0, 1])
ax_canvas.set_ylim([0, 1])
# First subplot axes in the canvas
left1, bottom1, width1, height1 = [0.1, 0.5, 0.5, 0.4]
ax1 = fig.add_axes([left1, bottom1, width1, height1])
ax1.set_zorder(0)
ax1.set_xlim([0, 1])
ax1.set_ylim([0, 1])
ax1.text(0.5, 0.5, 'Ax 1')
# Add the circle
circle = AnchoredText(
s="L1",
frameon=False,
loc="upper left",
prop=dict(bbox=dict(boxstyle="circle")),
)
ax1.add_artist(circle)
# Second axes in the canvas
left2, bottom2, width2, height2 = [0.45, 0.15, 0.3, 0.2]
ax2 = fig.add_axes([left2, bottom2, width2, height2])
ax1.set_zorder(0)
ax2.set_xlim([0, 1])
ax2.set_ylim([0, 1])
ax2.text(0.5, 0.5, 'Ax 2')
# Line connecting Ax1 and Ax2 in the Ax canvas
# The values below are eyeballed based on the ax_canvas having x and y limits 0 to 1
# Roughly where the circle is in Ax1, x middle of Ax2
x_line = [0.125, 0.6]
# Roughly where the circle is in Ax1, height of Ax2
y_line = [0.87, 0.35]
ax_canvas.plot(x_line, y_line, c='k', ls='--')
plt.show()

Related

Adding a stacked plot as a subplot in python

Please I need help with a plot. I am making a 3x3 dimension figure containing 7 subplots. I want two(2) of the subplots (ax6 and ax7) to be stacked plots. Does anyone have an idea how I can make this work? I used the code below to make the grid.
fig = plt.figure()
fig.set_figheight(8)
fig.set_figwidth(10)
gs = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[0, -2])
ax3 = plt.subplot(gs[0, -1])
ax4 = plt.subplot(gs[1, 0])
ax5 = plt.subplot(gs[-1, 0])
ax6 = plt.subplot(gs[1:, -2])
ax7 = plt.subplot(gs[1:, -1])
I tried making the stacked plot for ax6 using the code below
ax6[0].plot(s[['xa']], s[['ac1']], label = "Data")
ax6[0].plot(s[['xa']], s[['ac2']], label = "C-C")
ax6[0].plot(s[['xa']], s[['ac3']], label = "C-O")
ax6[0].plot(s[['xa']], s[['ac4']], label = "C=C")
ax6[0].plot(s[['xa']], s[['ea1']], label = "Envelope")
ax6[0].text(0.08, 0.70, 'C', ha='center', va='baseline', wrap=True, fontsize= 10, fontweight='bold', color='darkgreen', transform=ax6[0].transAxes)
ax6[1].plot(s[['xb']], s[['bc1']], label = "Data")
ax6[1].plot(s[['xb']], s[['bc2']], label = "C-C")
ax6[1].plot(s[['xb']], s[['bc3']], label = "C-O")
ax6[1].plot(s[['xb']], s[['bc4']], label = "C=C")
ax6[1].plot(s[['xb']], s[['be1']], label = "Envelope")
ax6[1].text(0.08, 0.70, 'm.C', ha='center', va='baseline', wrap=True, fontsize= 10, fontweight='bold', color='darkgreen', transform=ax6[1].transAxes)
Please look at the comments in the code:
import matplotlib.pyplot as plt
from matplotlib import gridspec
import numpy as np
fig = plt.figure(figsize=(10, 8))
g = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(g[0, 0])
ax2 = plt.subplot(g[0, 1])
ax3 = plt.subplot(g[0, 2])
ax4 = plt.subplot(g[1, 0])
ax5 = plt.subplot(g[2, 0])
# Create another grid
g2 = gridspec.GridSpec(3, 3)
g2.update(hspace=0.00)
# Generate data for three subplots in g2
x = np.linspace(0, 2 * np.pi, 400)
ya = np.sin(x)
yb = np.cos(x)
y7 = np.sin(x) ** 2
# Get three different Axes objects
ax6a = plt.subplot(g2[1, 1])
ax6b = plt.subplot(g2[2, 1], sharex=ax6a)
ax7 = plt.subplot(g2[1:, -1])
# Hide the xticklabels of top subplot in the shared plots
plt.setp(ax6a.get_xticklabels(), visible=False)
# Set xticks for lower subplots in the shared plots
ax6b.set_xticks(np.pi * np.array([0, 1/2, 1, 3/2, 2]))
# Try plotting
ax6a.plot(x, ya)
ax6b.plot(x, yb, 'g')
ax7.plot(x, y7, 'r')
plt.tight_layout()
plt.show()
This gives:
This answer was motivated by this answer and examples from older documentation of matplotlib.
If you want ax7 (red color subplot here) represented in to two separate subplots, either create a new Gridspec or use g depending on attributes you want to assign them e.g. in the code above:
# ax7 = plt.subplot(g2[1:, -1])
# ax7.plot(x, y7, 'r')
ax7a = plt.subplot(g[1, 2])
ax7b = plt.subplot(g[2, 2])
ax7a.plot(x, y7, 'r')
ax7b.plot(x, y7, 'r')
This gives:

How to insert a small square mark somewhere on a generated heatmap plot

I am creating a 2D matplotlib plot (i and j coordinates) which contains 10 subplots. Each subplot contains 150 by 150 grid cell data. How can I insert a small black-colored square mark (3 by 3 ) somewhere fixed (center at coordinates 62 and 62 ) on each generated heatmap sub-plot across those 10 sub-plots? The square mark would therefore contain 10 blocks from 60 to 64 in both x and y direction and contains a written text "Sale 1" centered at x 62 and y 62. My code below does not generate any patches. Any feedback is greatly appreciated.
from matplotlib.patches import Rectangle
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score, median_absolute_error
import os
import matplotlib.cm as cm
from mpl_toolkits import axes_grid1
import matplotlib.pyplot as plt
#import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.colors
import matplotlib.colors as colors
data = np.random.rand(10, 150, 150)
data = data.reshape(-1, 1)
property = "Sale"
pmin = data.min()
pmax = data.max()
v = np.linspace(round(pmin,3), round(pmax,3),15, endpoint=True)
v = [round(x,3) for x in v]
fig, ax = plt.subplots(2, 5, figsize=(160, 80))
row_count = 0
col_count = 0
for i in range(10):
sub_plot_data = data[(i)*(150*150):(i+1)*150*150]
x = 150
y = 150
#--------------------------- Define the map boundary ----------------------
xmin = 1258096.6
xmax = 1291155.0
ymin = 11251941.6
ymax = 11285000.0
pmin = min(sub_plot_data)
pmax = max(sub_plot_data)
# --------------------------- define color bar for Discrete color
bounds = np.linspace(-1, 1, 10)
Discrete_colors = plt.get_cmap('jet')(np.linspace(0,1,len(bounds)+1))
# create colormap without the outmost colors
cmap = mcolors.ListedColormap(Discrete_colors[1:-1]) #
actual_2d = np.reshape(sub_plot_data,(y,x))
im1 = ax[row_count, col_count].imshow(actual_2d, interpolation=None, cmap=cmap,
extent=(xmin, xmax, ymin, ymax), vmin=pmin, vmax=pmax)
plt.text(actual_2d[62, 62], actual_2d[62, 62], '%s' % 'Sale_1',
horizontalalignment='center', verticalalignment='center', color= 'black', fontsize= 90)
ax[row_count, col_count].set_title("Sale_Stores-%s - L: %s"%(i+1, layer),
fontsize=130, pad=44, x=0.5, y=0.999) # new
ax[row_count, col_count].set_aspect('auto')
ax[row_count, col_count].tick_params(left=False, labelleft=False, top=False,
labeltop=False, right=False, labelright=False, bottom=False, labelbottom=False) # new
#ax[row_count, col_count] = plt.gca()
plt.gca().add_patch(Rectangle((60, 60), 3, 3, edgecolor='black',
facecolor='black',fill=True,lw=2))
ax[row_count, col_count].add_patch(plt.text(62, 62, '%s' % 'Sale_1',
horizontalalignment='center', verticalalignment='center', color= 'black', fontsize= 90))
col_count +=1
if col_count == 5:
row_count +=1
col_count =0
fig.tight_layout(h_pad=10)
plt.subplots_adjust(left=0.02,
bottom=0.1,
right=0.91,
top=0.8,
wspace=0.1,
hspace=0.2)
cbaxes = fig.add_axes([0.94, 0.05, 0.02, 0.8])
cbar = fig.colorbar(im1, ax=ax.ravel().tolist(), ticks=v, extend='both', cax =cbaxes)
cbar.ax.tick_params(labelsize=70)
#cbar.set_ticks(v)
cbar.ax.set_yticklabels([i for i in v], fontsize=120)
output_dir = r"D/test"
plot_dir = os.path.join(output_dir, reservoir_property)
if not os.path.exists(plot_dir):
os.makedirs(plot_dir)
fig.savefig(r"%s/per_allmodel.png"%(plot_dir))
I tried your code and made a couple of modifications: first, the graph size was too huge and caused errors, so I made it smaller; second, I simplified the subplots: axes has a list of subplot objects, so I took them out with axes.flat; third The second is modifying the text as annotations. The graph size has been reduced and the font size and spacing have been adjusted, so please modify it yourself. Finally, tick_params is not set since the color bar ticks are disabled.
fig, axes = plt.subplots(2, 5, figsize=(16, 8))
row_count = 0
col_count = 0
for i,ax in enumerate(axes.flat):
sub_plot_data = data[(i)*(150*150):(i+1)*150*150]
x = 150
y = 150
#--------------------------- Define the map boundary ----------------------
xmin = 1258096.6
xmax = 1291155.0
ymin = 11251941.6
ymax = 11285000.0
pmin = min(sub_plot_data)
pmax = max(sub_plot_data)
# --------------------------- define color bar for Discrete color
bounds = np.linspace(-1, 1, 10)
Discrete_colors = plt.get_cmap('jet')(np.linspace(0,1,len(bounds)+1))
# create colormap without the outmost colors
cmap = mcolors.ListedColormap(Discrete_colors[1:-1]) #
actual_2d = np.reshape(sub_plot_data,(y,x))
#im = ax.imshow(actual_2d, interpolation=None, cmap=cmap, extent=(xmin, xmax, ymin, ymax), vmin=pmin, vmax=pmax)
im = ax.imshow(actual_2d, interpolation=None, cmap=cmap)
ax.text(actual_2d[62, 62], actual_2d[62, 62]-10, '%s' % 'Sale_1',
horizontalalignment='center', verticalalignment='center', color= 'black', fontsize=18)
ax.set_title("Sale_Stores-%s - L: %s"%(i+1, 1), fontsize=14, pad=30, x=0.5, y=0.999)
ax.set_aspect('auto')
ax.add_patch(Rectangle((60, 60), 6, 6, edgecolor='red', facecolor='red', fill=True, lw=2))
ax.text(62, 62, '%s' % 'Sale_1', ha='center', va='center', color='black', fontsize=14)
fig.tight_layout(h_pad=10)
plt.subplots_adjust(left=0.02,
bottom=0.1,
right=0.91,
top=0.8,
wspace=0.1,
hspace=0.5)
cbaxes = fig.add_axes([0.94, 0.05, 0.02, 0.8])
cbar = fig.colorbar(im, ax=axes.flat, ticks=v, extend='both', cax=cbaxes)
cbar.ax.tick_params(labelsize=10)
#cbar.set_ticks(v)
cbar.ax.set_yticklabels([str(i) for i in v], fontsize=12)
#plt.tick_params(left=False, labelleft=False, top=False, labeltop=False, right=False, labelright=False, bottom=False, labelbottom=False)
plt.show()

How to change background color of inset figure

I'm trying to create an inset figure that has a different projection from the parent. The only issue I have at this point is the inset figures's tick labels are not legible because they are black and blend in with the plot behind it. I could change the color of the ticks and labels to white, but that does not help when the data in ax0 yields lighter colors. Here is the MWE:
import calipsoFunctions as cf
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
import pylab as pl
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
from mpl_toolkits.axes_grid1.inset_locator import inset_axes, mark_inset, InsetPosition
x, y = np.arange(100), np.arange(200)
X, Y = np.meshgrid(x, y)
C = np.random.randint(0, 100, (200, 100))
fig = pl.figure(figsize=(6.5, 5.25))
gs0 = pl.GridSpec(3, 1)
gs0.update(left=0.08, right=0.925,
top=0.95, bottom=0.33,
hspace=0.10, wspace=0.0)
gs1 = pl.GridSpec(1, 2)
gs1.update(left=0.08, right=0.925,
top=0.225, bottom=0.05,
hspace=0.0, wspace=0.025)
# create primary axes
ax0 = pl.subplot(gs0[0])
ax1 = pl.subplot(gs0[1])
ax0.pcolormesh(X, Y, C, vmin=0, vmax=75)
ax1.pcolormesh(X, Y, C, vmin=0, vmax=75)
# add map plot (inset axis)
loc_box = [0.8, 0.55, 0.20, 0.45]
ax0_inset = fig.add_axes(loc_box,
projection=ccrs.PlateCarree(),
aspect="auto",
facecolor="w",
frameon=True)
lat_array = np.arange(-20, 20)
lon_array = np.arange(-10, 10, 0.5)
ax0_inset.plot(lat_array, lon_array, "k-", lw=1)
ip = InsetPosition(ax0, loc_box)
ax0_inset.set_axes_locator(ip)
ax0_inset.coastlines(resolution="10m", linewidth=0.25, color="k")
ax0_inset.add_feature(cfeature.LAND)
llat, ulat = lat_array.min(), lat_array.max()
llon, ulon = lon_array.min(), lon_array.max()
llat = np.round(llat / 10) * 10
ulat = np.round(ulat / 10) * 10
llon = np.round(llon / 5) * 5
ulon = np.round(ulon / 5) * 5
ax0_inset.set_yticks(np.arange(llat, ulat, 20), minor=False)
ax0_inset.set_yticks(np.arange(llat, ulat, 10), minor=True)
ax0_inset.set_yticklabels(np.arange(llat, ulat, 20),
fontsize=8)
ax0_inset.yaxis.set_major_formatter(LatitudeFormatter())
ax0_inset.set_xticks(np.arange(llon, ulon, 5), minor=False)
ax0_inset.set_xticks(np.arange(llon, ulon, 1), minor=True)
ax0_inset.set_xticklabels(np.arange(llon, ulon, 5),
fontsize=8,
rotation=45)
ax0_inset.xaxis.set_major_formatter(LongitudeFormatter())
ax0_inset.grid()
ax0_inset.tick_params(which="both",
axis="both",
direction="in",
labelsize=8)
fig.show()
Is there a way to change the background color of ax0_inset so that these tick labels are legible? I tried changing the face_color to "w", but that did not work. Ideally, I want the same behavior as ax0.figure.set_facecolor("w"), but for the ax0_inset axis. Is this doable?
Following #Mr. T's comment suggestion, a work-around solution could be:
# insert transparent (or opaque) rectangle around inset_axes plot
# to make axes labels more visible
# make buffer variable to control amount of buffer around inset_axes
buffer = 0.1 # fractional axes coordinates
# use ax inset tuple coords in loc_box to add rectangle patch
# [left, bottom, width, height] (fractional axes coordinates)
fig.add_patch(plt.Rectangle((
loc_box[0]-buffer, loc_box[1]-buffer),
loc_box[2]+buffer, loc_box[3]+buffer,
linestyle="-", edgecolor="k", facecolor="w",
linewidth=1, alpha=0.75, zorder=5,
transform=ax0.transAxes))

Changeing the labels distance from x and y ticks and choosing one color to the annotation in seaborn heat map

I am doing a correlation matrix using a seaborn heatmap, I need to :
Change the distance between the ticks and the labels of x and y.
Also, change the distance between the title and the heatmap.
Unifying the color of annotation to be either white or black.
I am using the following code:
from matplotlib import pyplot as plt
import matplotlib
import numpy as np
import seaborn as sns
#call data frame and apply correlation:
#data =
#df = pd.DataFrame(data, columns = features)
#df_small = df.iloc[:,:]#if only few parameters are needed
#correlation_mat = df_small.corr()
#Create color pallete:
def NonLinCdict(steps, hexcol_array):
cdict = {'red': (), 'green': (), 'blue': ()}
for s, hexcol in zip(steps, hexcol_array):
rgb =matplotlib.colors.hex2color(hexcol)
cdict['red'] = cdict['red'] + ((s, rgb[0], rgb[0]),)
cdict['green'] = cdict['green'] + ((s, rgb[1], rgb[1]),)
cdict['blue'] = cdict['blue'] + ((s, rgb[2], rgb[2]),)
return cdict
#https://www.december.com/html/spec/colorshades.html
hc = ['#e5e5ff', '#C7DDF2', '#8EBAE5', '#407FB7', '#00549F']#ffffff #e5e5ff
th = [0, 0.25, 0.5, 0.75, 1]
hc = hc[:0:-1] + hc # prepend a reversed copy, but without repeating the central value
cdict = NonLinCdict(np.linspace(0, 1, len(hc)), hc)
cm = matplotlib.colors.LinearSegmentedColormap('test', cdict)
corr=np.random.uniform(-1, 1, (6,6))
#plot correlation matrix:
plt.figure(figsize = (10,8))
ax=sns.heatmap(corr,center=0, linewidths=1, annot = True,cmap=cm ,square=True, vmin=-1, vmax=1,
robust=True, annot_kws={'size':16}, cbar=True,linecolor='#F6A800',xticklabels=True,
yticklabels=True)
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=10, axis='both', which='both', length=0)
cbar.set_ticks(np.linspace(-1, 1, 11))
plt.title("title", y=-1.5,fontsize = 18,)
plt.xlabel("X_parameters",fontsize = 18)
plt.ylabel("Y_paramaters",fontsize = 18)
ax.tick_params(axis='both', which='both', length=0)
ax.axhline(y=0, color='#F6A800',linewidth=4)
ax.axhline(y=corr.shape[1], color='#F6A800',linewidth=4)
ax.axvline(x=0, color='#F6A800',linewidth=4)
ax.axvline(x=corr.shape[0], color='#F6A800',linewidth=4)
#change position of lables and titles and assign colors.
plt.show()
My current output is:
Well, plt.title() has a parameter pad= to set the padding between the text of the title and the top spine of the plot (default is 6). plt.xlabel() and plt.ylabel() have a parameter labelpad= to set the distance between the axis label and the ticklabels.
sns.heatmap() has a parameter annot_kws which is a dictionary of parameters for the annotation texts. The color can be changed via sns.heatmap(..., annot_kws={'size': 16, 'color': 'black'}). Note that for readability, seaborn's default uses white for text on the dark-colored cells, and black for the light-colored cells.
from matplotlib import pyplot as plt
import matplotlib
import numpy as np
import seaborn as sns
def NonLinCdict(steps, hexcol_array):
cdict = {'red': (), 'green': (), 'blue': ()}
for s, hexcol in zip(steps, hexcol_array):
rgb = matplotlib.colors.hex2color(hexcol)
cdict['red'] = cdict['red'] + ((s, rgb[0], rgb[0]),)
cdict['green'] = cdict['green'] + ((s, rgb[1], rgb[1]),)
cdict['blue'] = cdict['blue'] + ((s, rgb[2], rgb[2]),)
return cdict
hc = ['#e5e5ff', '#C7DDF2', '#8EBAE5', '#407FB7', '#00549F'] # ffffff #e5e5ff
th = [0, 0.25, 0.5, 0.75, 1]
hc = hc[:0:-1] + hc # prepend a reversed copy, but without repeating the central value
cdict = NonLinCdict(np.linspace(0, 1, len(hc)), hc)
cm = matplotlib.colors.LinearSegmentedColormap('test', cdict)
corr = np.random.uniform(-1, 1, (6, 6))
# plot correlation matrix:
plt.figure(figsize=(10, 8))
ax = sns.heatmap(corr, center=0, linewidths=1, annot=True, cmap=cm, square=True, vmin=-1, vmax=1,
robust=True, annot_kws={'size': 16, 'color': 'black'}, cbar=True, linecolor='#F6A800',
xticklabels=True, yticklabels=True)
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=10, axis='both', which='both', length=0)
cbar.set_ticks(np.linspace(-1, 1, 11))
plt.title("title", y=-1.5, fontsize=18, pad=15)
plt.xlabel("X_parameters", fontsize=18, labelpad=15)
plt.ylabel("Y_paramaters", fontsize=18, labelpad=15)
ax.tick_params(axis='both', which='both', length=0)
ax.axhline(y=0, color='#F6A800', linewidth=4)
ax.axhline(y=corr.shape[1], color='#F6A800', linewidth=4)
ax.axvline(x=0, color='#F6A800', linewidth=4)
ax.axvline(x=corr.shape[0], color='#F6A800', linewidth=4)
plt.show()

How to show Cartesian system in polar plot in python?

Here I tried to add the polar plot on top of the Cartesian grid,but what I got instead was 2 separate figures(one polar another Cartesian),I want this polar figure to be embedded in the Cartesian plot. Also I have used some of the code previously available as I am new to matplotlib.
from pylab import *
import matplotlib.pyplot as plt
x = [0,10,-3,-10]
y = [0,10,1,-10]
color=['w','w','w','w']
fig = plt.figure()
ax1 = fig.add_subplot(111)
scatter(x,y, s=100 ,marker='.', c=color,edgecolor='w')
circle1=plt.Circle((0,0),5,color='r',fill=False)
circle_min=plt.Circle((0,0),4.5,color='g',fill=False)
circle_max=plt.Circle((0,0),5.445,color='b',fill=False)
fig = plt.gcf()
fig.gca().add_artist(circle1)
fig.gca().add_artist(circle_min)
fig.gca().add_artist(circle_max)
left,right = ax1.get_xlim()
low,high = ax1.get_ylim()
arrow( left, 0, right -left, 0, length_includes_head = True, head_width = 0.15 )
arrow( 0, low, 0, high-low, length_includes_head = True, head_width = 0.15 )
grid()
fig = plt.figure()
ax2 = fig.add_subplot(111)
scatter(x,y, s=100 ,marker='.', c=color,edgecolor='w')
circle2=plt.Circle((0,0),5,color='r',fill=False)
circle_min=plt.Circle((0,0),4.5,color='g',fill=False)
circle_max=plt.Circle((0,0),5.445,color='b',fill=False)
fig = plt.gcf()
fig.gca().add_artist(circle2)
fig.gca().add_artist(circle_min)
fig.gca().add_artist(circle_max)
left,right = ax2.get_xlim()
low,high = ax2.get_ylim()
arrow( left, 0, right -left, 0, length_includes_head = True, head_width = 0.15 )
arrow( 0, low, 0, high-low, length_includes_head = True, head_width = 0.15 )
import numpy as np
import matplotlib.pyplot as plt
theta = np.linspace(-np.pi, np.pi, 100)
r1 = 1 - np.sin(3*theta)
r2 = 1 + np.cos(theta)
ax = plt.subplot(111, polar=True, # add subplot in polar coordinates
axisbg='Azure') # background colour
ax.set_rmax(2.2) # r maximum value
ax.grid(True) # add the grid
ax.plot(theta, r1,
color='Tomato', # line colour
ls='--', # line style
lw=3, # line width
label='a 3-fold curve') # label
ax.plot(theta, r2,
color='purple',
linewidth=3,
ls = '-',
label = 'a cardioid')
ax.legend(loc="lower right") # legend location
titlefont = {
'family' : 'serif',
'color' : 'black',
'weight' : 'bold',
'size' : 16,
}
ax.set_title("A plot in polar coordinates", # title
va='bottom', # some space below the title
fontdict = titlefont # set the font properties
)
grid()
show()
#I am getting a separate Cartesian image + a polar image while what I need is both the things in a single image
import matplotlib.pyplot as plt
import numpy as np
#########################################
color=['w','w','w','w']
theta = np.linspace(-np.pi, np.pi, 100)
fig = plt.figure()# initializing the figure
rect = [0.1, 0.1, 0.8, 0.8]# setting the axis limits in [left, bottom, width, height]
ax_carthesian = fig.add_axes(rect)# the carthesian axis:
ax_polar = fig.add_axes(rect, polar=True, frameon=False)# the polar axis:
#########################################
ax_carthesian.add_artist(plt.Circle((0.5,0.5),5/15,color='r',fill=False))
ax_carthesian.add_artist(plt.Circle((0.5,0.5),4.5/15,color='g',fill=False))
ax_carthesian.add_artist(plt.Circle((0.5,0.5),5.445/15,color='b',fill=False))
ax_polar.plot(theta, 1 - np.sin(3*theta), color='Tomato',ls='--',lw=1, label='a 3-fold curve')
ax_polar.plot(theta, 1 + np.cos(theta), color='purple',linewidth=1,ls = '-',label = 'a cardioid')
plt.show()
I am not used to matplotlib but I reduced your code to his minimum to better understand it and make it look less redudant. look at what I get:
import pylab
import matplotlib.pyplot as plt
import numpy as np
#########################################
x = [0,10,-3,-10]
y = [0,10,1,-10]
color=['w','w','w','w']
theta = np.linspace(-np.pi, np.pi, 100)
#########################################
pylab.scatter(x,y, s=100 ,marker='.', c=color,edgecolor='w')
plt.gcf().gca().add_artist(plt.Circle((0,0),5,color='r',fill=False))
plt.gcf().gca().add_artist(plt.Circle((0,0),4.5,color='g',fill=False))
plt.gcf().gca().add_artist(plt.Circle((0,0),5.445,color='b',fill=False))
plt.figure().add_subplot(111)
ax = plt.subplot(111, polar=True,axisbg='Azure')
ax.plot(theta, 1 - np.sin(3*theta),color='Tomato',ls='--',lw=3,label='a 3-fold curve')
ax.plot(theta, 1 + np.cos(theta),color='purple',linewidth=3,ls = '-',label = 'a cardioid')
pylab.show()
it is nearly the same result...

Categories