Quickly Plotting Polar Radar Data using Python?

倖福魔咒の 提交于 2021-02-10 19:57:28

问题


I've got an interesting application that requires transforming 3D polar data (angle, distance, and value at that point) into images representing the data. It's NOAA NEXRAD radar data that I'm using in a custom application.

The data is stored in 3 arrays, range_data (the distance from the radar in meters, 1800 points), azimuth_data (the angle in 0.5 degree steps, 720 points), and radar_data (a 720x1800 array containing a data value for each combination of range and azimuth). This is the format I get the data in from NOAA so there's not much I can do to change things on that front.

Right now, I'm plotting it using a matplotlib pcolormesh in the following way (basically this example from the library I'm using):

x = range_data * np.sin(np.deg2rad(azimuth_data))[:,None]
y = range_data * np.cos(np.deg2rad(azimuth_data))[:,None]

fig, ax = plt.subplots(1,1,figsize=(4,4))
ax.pcolormesh(x,y,radar_data,cmap=ref_cmap,norm=ref_norm)
ax.set_aspect('equal','datalim')
ax.set_xlim(-460, 460)
ax.set_ylim(-460, 460)
ax.set_axis_off()
plt.axis('off')

plt.savefig(imgpath, bbox_inches='tight', transparent=True, dpi=dpiCalc)

The major hangup right now is in the actual rendering and saving of the plot using the savefig() command. It takes around 7 seconds per image and with 20 or so sets of data to process it takes far too long for the application I have in mind.

Since I just need the colormapped data as an image, I don't really need the majority of matplotlib's tools and features. I'm thinking there must be a quicker way to generate this image from my raw data.

I tried stepping through the data and populating an x-y array piece-by-piece, then saving the array with PIL, but iterating through the data manually took way longer than even matplotlib. Doing array operations with numpy would be way faster but I can't really think of any operations to convert the data between coordinate systems.

To breakdown the question even simpler, I've got polar data stored in a 720x1800 radar_data array in the format value[angle,distance], and I want to generate a colormapped radar image like this one (without the axes or frame) in the quickest way possible. Since I'm not a programmer nor a mathematician by trade, there might be something simple I'm overlooking.

Any and all recommendations are appreciated!


回答1:


I think you essentially want to do a polar distortion, converting this:

into this:

I did that using ImageMagick in the Terminal as it is easy and quick and installed on most Linux distros and is available for macOS and Windows. The command I used is:

magick image.png -virtual-pixel Black -distort Polar 0 result.png

Note: If you are using ImageMagick v6, replace magick with convert in the preceding command.

Note: In case you want to experiment, I made the initial image like this:

magick -size 1800x720  gradient:red-blue image.png 

If that is what you want, you can do it in Python using any one of a number of tools:

  • skimage - warp_polar()
  • OpenCV - warpPolar()
  • wand - distort()

Or you could just "shell out" to the ImageMagick command I used above.

Keywords: Python, image processing, polar, depolar, cartesian, transform, radar, plot




回答2:


Matplotlib is not a good solution for that.

  • Vispy

    OpenGL-supported plotting. Interface is not that polished, but a lot of functions are already available. Just click through the examples and try to find the functions where you don't have to write GLSL (the ones not in folder "gloo" but in "plot" or "scene").

  • PyQtGraph

    Works fine for realtime plotting, but is currently unmaintained. Qt4 only.

  • PyQwt

    Also unmaintained. Qt4 only.

You can also put together a custom GUI without that much work, there are many examples around. e.g. here. Just look for "real time plotting Qt".




回答3:


Worth noting that the following code takes 1 second for me:

import numpy as np
import matplotlib.pyplot as plt
import time

t = time.time()
range_data = np.arange(1800)
azimuth_data = np.linspace(0, 359.5, 720)
radar_data = np.dot(np.atleast_2d(azimuth_data).T , np.atleast_2d(range_data))

x = range_data * np.sin(np.deg2rad(azimuth_data))[:,None]
y = range_data * np.cos(np.deg2rad(azimuth_data))[:,None]

fig, ax = plt.subplots(1,1,figsize=(4,4))
ax.pcolormesh(x,y,radar_data)
ax.set_aspect('equal','datalim')

ax.set_axis_off()

plt.savefig("radar.png", transparent=True, dpi=100)
print(time.time()-t)

If you half the resolution, i.e. 900 x 360 points instead of 1800 x 720, it would only take 0.3 seconds. So it's also mainly a question of how large of an image you want to get.




回答4:


I assume you are already doing this, just to be sure: If your azimuth_data is not a numpy array, you could lose performance.



来源:https://stackoverflow.com/questions/59206372/quickly-plotting-polar-radar-data-using-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!