Set location of image in matplotlib - python

I have a list of three images' file names, I want to plot them using matplotlib, the attempt I made is below. I tried to plot them all but they are all plotted to the same location so the final image appears on top.
I want to plot the first at location coordinates (0,0), the second at (100,200) and the third at (200,200). I read the documentation on matplotlib.imshow but cannot find how to set the location of the image using the coordinates.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
imageList = ["foo.jpg", "bar.jpg", "foobar.jpg"]
coordinatesList = [[0,0],[100,200],[200,200]]
for i in range(3):
imageFile = imageList[i]
coordinate = coordinatesList[i]
img=mpimg.imread(imageFile)
imgplot = plt.imshow(img)

I see 2 ways to do this:
with matplotlib.transforms:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib as mpl
imageList = ["image.jpg", "image.jpg", "image.jpg"]
coordinatesList = [[0, 0], [100, 200], [200, 200]]
ax = plt.gca()
ax.set_xlim(0, 300)
ax.set_ylim(0, 300)
for i in range(3):
imageFile = imageList[i]
img=mpimg.imread(imageFile)
imgplot = ax.imshow(img)
tx, ty = coordinatesList[i]
transform = mpl.transforms.Affine2D().translate(tx, ty)
imgplot.set_transform(transform + ax.transData)
plt.show()
with extent option (but I know my image's dimensions):
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
imageList = ["image.jpg", "image.jpg", "image.jpg"]
coordinatesList = [[0, 0], [100, 200], [200, 200]]
ax = plt.gca()
ax.set_xlim(0, 300)
ax.set_ylim(0, 300)
imgplot = [None] * len(imageList)
for i in range(3):
imageFile = imageList[i]
img=mpimg.imread(imageFile)
tx, ty = coordinatesList[i]
ax.imshow(img, extent=(tx, tx + 50, ty, ty + 50))
plt.show()
Here's the result using a 50px square as a picture image.png:

Related

Color code of lines based on an array using Matplotlib

I am drawing multiple horizontal and vertical lines using ax.hlines() and ax.vlines() respectively. I want to assign values to these lines using the array P and the order of assignment is presented in the expected output.
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
fig,ax = plt.subplots(1)
n=3
for i in range(0,n):
for j in range(0,n):
rect = mpl.patches.Rectangle((200+200*i,200+200*j),10*n, 10*n, linewidth=1, edgecolor='black', facecolor='black')
ax.add_patch(rect)
ax.hlines(200+200*i+5*n, 200, 200*n, zorder=0)
ax.vlines(200+200*j+5*n, 200, 200*n, zorder=0)
ax.set_xlim(left = 0, right = 220*n)
ax.set_ylim(bottom = 0, top = 220*n)
plt.show()
#########################################
P=np.array([[1.9],
[4.9],
[6.1],
[8.2],
[1.8],
[5.8],
[9.7],
[7.3],
[8.9],
[2.5],
[9.9],
[0.7]])
#########################################
The current output is
The expected output is
Values bar is added following #Davide_sd.
I'm not sure if this sovles your problem.
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
from matplotlib.colors import Normalize
from matplotlib import cm
fig,ax = plt.subplots(1)
n=3
P=np.array([[1.9],
[4.9],
[6.1],
[8.2],
[1.8],
[5.8],
[9.7],
[7.3],
[8.9],
[2.5],
[9.9],
[0.7]])
color = cm.get_cmap('Blues')
norm = Normalize(vmin=0, vmax=10)
color_list = []
for i in range(len(P)):
color_list.append(color(P[i]/10))
print(color_list)
id = 0
for j in range(0, n):
for k in range(n-1):
ax.hlines(200+200*(n-j-1)+5*n, 200*(k+1)+5*n, 200*(k+2)+5*n, zorder=0, colors=color_list[id])
id += 1
for i in range(0, n):
rect = mpl.patches.Rectangle((200+200*i, 200+200*j), 10*n, 10*n, linewidth=1, edgecolor='black', facecolor='black')
ax.add_patch(rect)
if j < n-1:
ax.vlines(200+200*i+5*n, 200*(n-1-j)+5*n, 200*(n-j)+5*n, zorder=0, colors=color_list[id])
id += 1
cb = fig.colorbar(cm.ScalarMappable(cmap=color, norm=norm))
cb.set_label("Values")
ax.set_xlim(left = 0, right = 220*n)
ax.set_ylim(bottom = 0, top = 220*n)
plt.show()
And the ouput is like:
You need to use a colormap, Normalize and ScalarMappable in order to create a colorbar.
Here is the procedure:
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import matplotlib.cm as cm
from matplotlib.colors import Normalize
import numpy as np
#########################################
P=np.array([[1.9],
[4.9],
[6.1],
[8.2],
[1.8],
[5.8],
[9.7],
[7.3],
[8.9],
[2.5],
[9.9],
[0.7]])
#########################################
# normalize the values. Values between 0 and 10 will be
# normalized to values from 0 and 1.
norm = Normalize(vmin=0, vmax=10)
Pnorm = norm(P)
# choose an appropriate colormap
cmap = cm.Blues
fig,ax = plt.subplots(1)
n=3
k = 0
for i in range(0,n):
for j in range(0,n):
rect = mpl.patches.Rectangle((200+200*i,200+200*j),10*n, 10*n, linewidth=1, edgecolor='black', facecolor='black')
ax.add_patch(rect)
# extract the color from the colormap
ax.hlines(200+200*i+5*n, 200, 200*n, zorder=0, color=cmap(Pnorm[k]))
ax.vlines(200+200*j+5*n, 200, 200*n, zorder=0, color=cmap(Pnorm[k]))
k += 1
cb = fig.colorbar(ScalarMappable(cmap=cmap, norm=norm))
cb.set_label("Values")
ax.set_xlim(left = 0, right = 220*n)
ax.set_ylim(bottom = 0, top = 220*n)
plt.show()
There is a problem with the way you are currently plotting lines, as they are overlapping. You need to fix it!

How to filter data while drawing?

I have a dataframe which I drawed as you can see the figure and codes below;
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
df = pd.read_excel('nötronn.xlsx')
fig, ax = plt.subplots(figsize=(20,40))
ax1 = plt.subplot2grid((1,5), (0,0), rowspan=1, colspan = 1)
ax1.plot(df["N/F*10"], df['Depth'], color = "green", linewidth = 0.5)
ax1.set_xlabel("Porosity")
ax1.xaxis.label.set_color("green")
ax1.set_xlim(10, 50)
ax1.set_ylabel("Depth (m)")
ax1.tick_params(axis='x', colors="green")
ax1.spines["top"].set_edgecolor("green")
ax1.title.set_color('green')
ax1.set_xticks([10, 20, 30, 40, 50])
I want to filter data so that I can realize the differences better. I tried these:
z = np.polyfit(df["N/F*10"], df['Depth'], 2)
p = np.poly1d(z)
plt.plot(df["N/F*10"], p(df["N/F*10"]))
But it gives :LinAlgError: SVD did not converge in Linear Least Squares
How can I solve it? Thanks.
Output expectation:
This works!
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from statsmodels.nonparametric.smoothers_lowess import lowess
data = pd.read_excel('nötronn.xlsx')
sub_data = data[data['Depth'] > 21.5]
result = lowess(sub_data['Eksi'], sub_data['Depth'].values)
x_smooth = result[:,0]
y_smooth = result[:,1]
tot_result = lowess(data['Eksi'], data['Depth'].values, frac=0.01)
x_tot_smooth = tot_result[:,0]
y_tot_smooth = tot_result[:,1]
fig, ax = plt.subplots(figsize=(20, 8))
##ax.plot(data.depth.values, data['N/F*10'], label="raw")
ax.plot(x_tot_smooth, y_tot_smooth, label="lowess 1%", linewidth=3, color="g")
ax.plot(data['GR-V121B-ETi'])
ax.plot(data['Caliper'], linestyle = 'dashed')

Python Basemap Heatmap

I am trying to copy the method that was done on this page: https://makersportal.com/blog/2018/7/20/geographic-mapping-from-a-csv-file-using-python-and-basemap under "Mapping Interesting Data" to have a color bar associated with my data.
Right now I just get a plain map of South America, which is what I want as my background but there is no data included.
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
m = Basemap(projection='mill',
llcrnrlat = -30, #bottom
llcrnrlon = -120, #left
urcrnrlat = 20, #top
urcrnrlon = -50, #right
resolution='c')
m.drawcoastlines()
m.drawcountries()
# format colors for elevation range
SST_min = np.min(df5.DaasgardSST)
SST_max = np.max(df5.DaasgardSST)
cmap = plt.get_cmap('gist_earth')
normalize = matplotlib.colors.Normalize(vmin=SST_min, vmax=SST_max)
# plot SST with different colors
for i in range(0,len(df5.DaasgardSST)):
x,y = m(lon,lat)
color_interp = np.interp(df5,[SST_min,SST_max],[0,30])
plt.plot(x,y,marker='o',markersize=6,color=cmap(int(color_interp)))
# format the colorbar
cax, _ = matplotlib.colorbar.make_axes(ax)
cbar = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap,norm=normalize,label='Elevation')
plt.title('Title')
plt.show()

Background image in a python plot

I need to plot over an image. I use this code to display the image:
plt.figure()
mngr = plt.get_current_fig_manager()
fname = 'erausal-valence.jpg'
image = Image.open(fname).convert("L")
arr = np.asarray(image)
plt.imshow(arr)
Over on this image I need to plot an array build with components:
for i in range(0, len(BPM)):
for k in range(0, len(BPM)):
(X[k], Y[k]) = pol2cart(BPM[k], -SC[k]);
plt.plot(X[k], Y[k])
but plot shows the image and doesn't show the plot of the X and Y arrays.
What are the values of X and Y? I've used the code below and could plot a graph over an image.
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
imageFile = cbook.get_sample_data('ada.png')
image = plt.imread(imageFile)
plt.imshow(image)
coords = [0, 100, 200, 300, 400, 500, 600]
plt.plot(coords, coords, 'r--', linewidth=2)
plt.show()
To add the background image, you have to add this import :
from matplotlib import cbook
And now to fill it in the background you should add these lines before the show instruction:
imageFile = cbook.get_sample_data('<Path_to_your_image>')
image = plt.imread(imageFile)
plt.imshow(image)

How to format a polar contour plot in matplotlib

I have some sample code to make a polar contour plot:
import numpy as np
import matplotlib.pyplot as plt
azimuths = np.radians(np.linspace(0, 180, 90))
zeniths = np.arange(50, 5050, 50)
r, theta = np.meshgrid(zeniths, azimuths)
values = 90.0+5.0*np.random.random((len(azimuths), len(zeniths)))
fig, ax = plt.subplots(subplot_kw=dict(projection='polar'))
ax.set_theta_zero_location("W")
pp = plt.contourf(theta, r, values, label='tmp')
cbar = plt.colorbar(pp, orientation='vertical')
cbar.ax.set_ylabel('scale label')
plt.show()
which gives me something like:
...but I would like something more like this:
...with space in the middle, and only showing 0 to 180 degrees. Does anyone know of a convenient way to do this?
I'm not sure how convenient this is, but here's a hackable solution (taken from here):
import numpy as np
import mpl_toolkits.axisartist.floating_axes as floating_axes
from matplotlib.projections import PolarAxes
from mpl_toolkits.axisartist.grid_finder import FixedLocator, MaxNLocator, \
DictFormatter
import matplotlib.pyplot as plt
tr = PolarAxes.PolarTransform()
degree_ticks = lambda d: (d*np.pi/180, "%d$^\\circ$"%(360-d))
angle_ticks = map(degree_ticks, np.linspace(180, 360, 5))
grid_locator1 = FixedLocator([v for v, s in angle_ticks])
tick_formatter1 = DictFormatter(dict(angle_ticks))
tick_formatter2 = DictFormatter(dict(zip(np.linspace(1000, 6000, 6),
map(str, np.linspace(0, 5000, 6)))))
grid_locator2 = MaxNLocator(5)
gh = floating_axes.GridHelperCurveLinear(tr,
extremes=(2*np.pi, np.pi, 1000, 6000),
grid_locator1=grid_locator1,
grid_locator2=grid_locator2,
tick_formatter1=tick_formatter1,
tick_formatter2=tick_formatter2)
fig = plt.figure()
ax = floating_axes.FloatingSubplot(fig, 111, grid_helper=gh)
fig.add_subplot(ax)
azimuths = np.radians(np.linspace(180, 360, 90)) # added 180 degrees
zeniths = np.arange(1050, 6050, 50) # added 1000
r, theta = np.meshgrid(zeniths, azimuths)
values = 90.0+5.0*np.random.random((len(azimuths), len(zeniths)))
aux_ax = ax.get_aux_axes(tr)
aux_ax.patch = ax.patch
ax.patch.zorder = 0.9
aux_ax.contourf(theta, r, values) # use aux_ax instead of ax
plt.show()
Note that (in order to get the space near the origin), you'll need to shift all your data points by 1000 in the radius direction and by pi in the theta direction (to get the lower hemisphere).
This yields:

Categories

Resources