Skip to content
86 changes: 80 additions & 6 deletions pydarn/plotting/maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# vector
# 2022-08-15: CJM - Removed plot_FOV call for default uses
# 2022-12-13: CJM - Limited reference vectors to only velocity use
# 2023-03-14: CJM - Added true vector option
# 2023-06-28: CJM - Refactored return values
# 2024-07-11: CJM - Added potential time series plot
#
Expand Down Expand Up @@ -114,20 +115,23 @@ def plot_mapdata(cls, dmap_data: List[dict], ax=None,
MapParams.FITTED_VELOCITY: 'plasma',
MapParams.MODEL_VELOCITY: 'plasma',
MapParams.RAW_VELOCITY: 'plasma',
MapParams.TRUE_VELOCITY: 'plasma',
MapParams.POWER: 'plasma_r',
MapParams.SPECTRAL_WIDTH: PyDARNColormaps.PYDARN_VIRIDIS
zmin: int
The minimum parameter value for coloring
Default: MapParams.FITTED_VELOCITY: [0],
MapParams.MODEL_VELOCITY: [0],
MapParams.RAW_VELOCITY: [0],
MapParams.TRUE_VELOCITY: [0],
MapParams.POWER: [0],
MapParams.SPECTRAL_WIDTH: [0]
zmax: int
The maximum parameter value for coloring
Default: MapParams.FITTED_VELOCITY: [1000],
MapParams.MODEL_VELOCITY: [1000],
MapParams.RAW_VELOCITY: [1000],
MapParams.TRUE_VELOCITY: [1000],
MapParams.POWER: [250],
MapParams.SPECTRAL_WIDTH: [250]
colorbar: bool
Expand Down Expand Up @@ -176,13 +180,15 @@ def plot_mapdata(cls, dmap_data: List[dict], ax=None,
cmap = {MapParams.FITTED_VELOCITY: PyDARNColormaps.PYDARN_PLASMA_R,
MapParams.MODEL_VELOCITY: PyDARNColormaps.PYDARN_PLASMA_R,
MapParams.RAW_VELOCITY: PyDARNColormaps.PYDARN_PLASMA_R,
MapParams.TRUE_VELOCITY: PyDARNColormaps.PYDARN_PLASMA_R,
MapParams.POWER: PyDARNColormaps.PYDARN_PLASMA,
MapParams.SPECTRAL_WIDTH: PyDARNColormaps.PYDARN_VIRIDIS}
cmap = cmap[parameter]
# Setting zmin and zmax
defaultzminmax = {MapParams.FITTED_VELOCITY: [0, 1000],
MapParams.MODEL_VELOCITY: [0, 1000],
MapParams.RAW_VELOCITY: [0, 1000],
MapParams.TRUE_VELOCITY: [0, 1000],
MapParams.POWER: [0, 250],
MapParams.SPECTRAL_WIDTH: [0, 250]}
if zmin is None:
Expand Down Expand Up @@ -259,23 +265,39 @@ def plot_mapdata(cls, dmap_data: List[dict], ax=None,
record]['fit.order'],
lat_min=dmap_data[
record]['latmin'])

elif parameter == MapParams.MODEL_VELOCITY:
v_mag = dmap_data[record]['model.vel.median']
azm_v = np.radians(dmap_data[record]['model.kvect'])
elif parameter == MapParams.RAW_VELOCITY:
v_mag = dmap_data[record]['vector.vel.median']
azm_v = np.radians(dmap_data[record]['vector.kvect'])
elif parameter == MapParams.TRUE_VELOCITY:
# Get LOS velocities
v_los = dmap_data[record]['vector.vel.median']
a_los = np.radians(dmap_data[record]['vector.kvect'])
# Get fitted velocities
v_fit, a_fit = \
cls.calculated_fitted_velocities(mlats=mlats,
mlons=np.radians(
data_lons),
hemisphere=hemisphere,
fit_coefficient=dmap_data[
record]['N+2'],
fit_order=dmap_data[
record]['fit.order'],
lat_min=dmap_data[
record]['latmin'])
v_mag, azm_v = cls.calculated_true_velocities(v_los, a_los,
v_fit, a_fit)
elif parameter == MapParams.POWER:
v_mag = dmap_data[record]['vector.pwr.median']
azm_v = np.radians(dmap_data[record]['vector.kvect'])

elif parameter == MapParams.SPECTRAL_WIDTH:
v_mag = dmap_data[record]['vector.wdt.median']
azm_v = np.radians(dmap_data[record]['vector.kvect'])

if parameter in [MapParams.FITTED_VELOCITY, MapParams.MODEL_VELOCITY,
MapParams.RAW_VELOCITY]:
MapParams.RAW_VELOCITY, MapParams.TRUE_VELOCITY]:
# Make reference vector and add it to the array to
# be calculated too
reflat = (np.abs(plt.gca().get_ylim()[1]) - 5) * hemisphere.value
Expand Down Expand Up @@ -374,7 +396,8 @@ def plot_mapdata(cls, dmap_data: List[dict], ax=None,
# Plot the sock start dots and reference vector if known
if color_vectors is True:
if parameter in [MapParams.MODEL_VELOCITY,
MapParams.RAW_VELOCITY]:
MapParams.RAW_VELOCITY,
MapParams.TRUE_VELOCITY]:
if reference_vector > 0:
ax.scatter(mlons[:-1], mlats[:-1], c=v_mag[:-1], s=2.0,
vmin=zmin, vmax=zmax, cmap=cmap, zorder=5.0,
Expand Down Expand Up @@ -429,7 +452,8 @@ def plot_mapdata(cls, dmap_data: List[dict], ax=None,
# no color so make sure colorbar is turned off
colorbar = False
if parameter in [MapParams.MODEL_VELOCITY,
MapParams.RAW_VELOCITY]:
MapParams.RAW_VELOCITY,
MapParams.TRUE_VELOCITY]:
if reference_vector > 0:
ax.scatter(mlons[:-1], mlats[:-1], c='#292929', s=2.0,
zorder=5.0, clip_on=True)
Expand Down Expand Up @@ -493,7 +517,8 @@ def plot_mapdata(cls, dmap_data: List[dict], ax=None,
else:
if parameter in [MapParams.FITTED_VELOCITY,
MapParams.MODEL_VELOCITY,
MapParams.RAW_VELOCITY]:
MapParams.RAW_VELOCITY,
MapParams.TRUE_VELOCITY]:
cb.set_label('Velocity (m s$^{-1}$)')
elif parameter is MapParams.SPECTRAL_WIDTH:
cb.set_label('Spectral Width (m s$^{-1}$)')
Expand Down Expand Up @@ -597,6 +622,55 @@ def index_legendre(cls, el: int, m: int):
return (m == 0 and el**2) or ((el != 0)
and (m != 0) and el**2 + 2 * m - 1) or 0

@classmethod
def calculated_true_velocities(cls, v_los: list, a_los: list,
v_fit: list, a_fit: list):
"""
Calculates the true velocities (Lasse Clausen/Ade Grocott Version)
The True velocity is calculated as the combined LOS vector and the
perpendicular-to-LOS component of the fitted velocity
Be aware many of the vectors in this function are in multi-dimensional
arrays

Parameters
----------
v_los: array
magnitude of LOS velocity vector
a_los: array
angle of LOS velocity vector from north
v_fit: array
magnitude of fitted velocity vector
a_fit: array
angle of fitted velocity vector from magnetic north
"""
# Reduce LOS vector to components
tkvect = np.empty([2, len(a_los)])
tkvect[0,:] = - v_los * np.cos(a_los)
tkvect[1,:] = v_los * np.sin(a_los)

# Get fitted vector components
rvect = np.empty([2, len(a_fit)])
rvect[0,:] = - v_fit * np.cos(a_fit)
rvect[1,:] = v_fit * np.sin(a_fit)

# Get fitted component along the los direction
# (a.b / b.b) * b
vn = (np.sum(rvect * tkvect, axis=0) / np.sum(tkvect * tkvect, axis=0)) * tkvect

# Perp is original vect - parallel
tvect = rvect - vn

# Combine vectors
for k in range(0,len(v_los)):
tvect[:,k] = tvect[:,k] + tkvect[:,k]

# Calculate the magnitude and azimuth
v_true = np.sqrt(tvect[0,:]**2 + tvect[1,:]**2)
a_true = np.arctan2(tvect[1,:], -tvect[0,:])

return v_true, a_true


@classmethod
def calculated_fitted_velocities(cls, mlats: np.array, mlons: np.array,
fit_coefficient: np.array,
Expand Down
1 change: 1 addition & 0 deletions pydarn/utils/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class MapParams(enum.Enum):
FITTED_VELOCITY = "fitted"
MODEL_VELOCITY = "model.vel.median"
RAW_VELOCITY = "vector.vel.median"
TRUE_VELOCITY = "true"
POWER = "vector.pwr.median"
SPECTRAL_WIDTH = "vector.wdt.median"

Expand Down