I have a dataframe that has coordinates of an antenna and the angle at which the antenna directs beam. There are 2 antenna with same coordinates but different angles. So I want to represent these in triangles and the head of the arrow indicates the angle.
df =
Antenna Latitude Longitude Angle
0 A 19.25 7.21 170
1 B 19.25 7.21 350
2 C 19.29 7.29 240
3 D 19.29 7.29 300
I tried the following:
fig, ax1 = plt.subplots()
ax1.set_xlabel('LAT')
ax1.set_ylabel('LON')
ax1.scatter(19.25, 7.21,label = 'A and B',markers='^',200 )
ax1.scatter(19.29, 7.29,label = 'C and D',marker='^'s=200 )
plt.legend()
which gives me the following image
Now I want to represent each antenna with a different triangleand head of the traingle should point towards the angle. Is there a way to do this?
CodePudding user response:
I don't think a triangle is a good direction indicator because there are three angles. So here I use a arrow (quiver) to indicate the direction.
import pandas as pd
from io import StringIO
import numpy as np
import matplotlib.pyplot as plt
inf='''
Antenna Latitude Longitude Angle
A 19.25 7.21 170
B 19.25 7.21 350
C 19.29 7.29 240
D 19.29 7.29 300
'''
df = pd.read_csv(StringIO(inf),sep="\s ")
# u = ws * cos(θ)
# v = ws * sin(θ)
# http://colaweb.gmu.edu/dev/clim301/lectures/wind/wind-uv
df['u'] = np.cos(np.deg2rad(df['Angle']))
df['v'] = np.sin(np.deg2rad(df['Angle']))
fig, ax1 = plt.subplots()
ax1.set_xlabel('LAT')
ax1.set_ylabel('LON')
colors = ['red','blue']
for ii,item in enumerate(df.groupby(['Latitude','Longitude'])):
ll, df1 = item
ax1.quiver(df1.Longitude, df1.Latitude,df1.u,df1.v ,color = colors[ii])
CodePudding user response:
import numpy as np
import matplotlib.pyplot as plt
# Here your data, in a different data structure
data = {(7.21,19.25):dict(A=170,B=350),
(7.29,19.29):dict(C=240,D=300)}
# Let's plot a point for each location, zorder is larger because
# we want the point to appear over the arrows
for loc in data:
plt.scatter(*loc, zorder=3, label="dummy string")
# place the legend in the axes, get an handle to it
legend = plt.legend()
# then, using the handle, change the labels
for loc, text in zip(data, legend.get_texts()):
label = ', '.join(antenna for antenna in data[loc])
text.set_text(label)
# eventually, for each antenna, draw an arrow directed like the angle
# maybe 200 pixels is too much?
for loc, antennas in data.items():
for antenna, angle in antennas.items():
angle_r = np.radians(angle)
s, c = np.sin(angle_r), np.cos(angle_r)
xt, yt = 200*c, 200*s # in pixels
plt.annotate(antenna, xy=loc, xytext=(xt, yt),
textcoords='offset pixels',
arrowprops=dict(arrowstyle='<-'))
# something is possibly outside of the figure...
plt.tight_layout()
plt.show()
PS there is a small misalignment, between the 170⁰ and the 350⁰ beams, probably due to a rounding problem - I am thinking about it but I have not found a solution yet.