Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reprojecting polar to cartesian grid

Tags:

I have a polar (r,theta) grid (which means that each cell is an annulus section) containing values of some physical quantity (e.g. temperature), and I would like to re-grid (or re-project, or resample) these values onto a cartesian grid. Are there any Python packages that can do this?

I am not interested in converting the coordinates of the centers of the cells from polar to cartesian - this is very easy. Instead, I'm looking for a package that can actually re-grid the data properly.

Thanks for any suggestions!

like image 282
astrofrog Avatar asked Jan 29 '10 19:01

astrofrog


People also ask

How do you convert polar coordinate to Cartesian coordinate?

Summary: to convert from Polar Coordinates (r,θ) to Cartesian Coordinates (x,y) : x = r × cos( θ ) y = r × sin( θ )

How do you convert polar to Cartesian to cylindrical?

To convert a point from Cartesian coordinates to cylindrical coordinates, use equations r2=x2+y2,tanθ=yx, and z=z.


2 Answers

Thanks for your answers - after thinking a bit more about this I came up with the following code:

import numpy as np

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as mpl

from scipy.interpolate import interp1d
from scipy.ndimage import map_coordinates


def polar2cartesian(r, t, grid, x, y, order=3):

    X, Y = np.meshgrid(x, y)

    new_r = np.sqrt(X*X+Y*Y)
    new_t = np.arctan2(X, Y)

    ir = interp1d(r, np.arange(len(r)), bounds_error=False)
    it = interp1d(t, np.arange(len(t)))

    new_ir = ir(new_r.ravel())
    new_it = it(new_t.ravel())

    new_ir[new_r.ravel() > r.max()] = len(r)-1
    new_ir[new_r.ravel() < r.min()] = 0

    return map_coordinates(grid, np.array([new_ir, new_it]),
                            order=order).reshape(new_r.shape)

# Define original polar grid

nr = 10
nt = 10

r = np.linspace(1, 100, nr)
t = np.linspace(0., np.pi, nt)
z = np.random.random((nr, nt))

# Define new cartesian grid

nx = 100
ny = 200

x = np.linspace(0., 100., nx)
y = np.linspace(-100., 100., ny)

# Interpolate polar grid to cartesian grid (nearest neighbor)

fig = mpl.figure()
ax = fig.add_subplot(111)
ax.imshow(polar2cartesian(r, t, z, x, y, order=0), interpolation='nearest')
fig.savefig('test1.png')

# Interpolate polar grid to cartesian grid (cubic spline)

fig = mpl.figure()
ax = fig.add_subplot(111)
ax.imshow(polar2cartesian(r, t, z, x, y, order=3), interpolation='nearest')
fig.savefig('test2.png')

Which is not strictly re-gridding, but works fine for what I need. Just posting the code in case it is useful to anyone else. Feel free to suggest improvements!

like image 140
astrofrog Avatar answered Oct 14 '22 12:10

astrofrog


I came to this post some time ago when trying to do something similar, this is, reprojecting polar data into a cartesian grid and vice-versa. The solution proposed here works fine. However, it takes some time to perform the coordinate transform. I just wanted to share another approach which can reduce the processing time up to 50 times or more.

The algorithm uses the scipy.ndimage.interpolation.map_coordinates function.

Let's see a little example:

import numpy as np

# Auxiliary function to map polar data to a cartesian plane
def polar_to_cart(polar_data, theta_step, range_step, x, y, order=3):

    from scipy.ndimage.interpolation import map_coordinates as mp

    # "x" and "y" are numpy arrays with the desired cartesian coordinates
    # we make a meshgrid with them
    X, Y = np.meshgrid(x, y)

    # Now that we have the X and Y coordinates of each point in the output plane
    # we can calculate their corresponding theta and range
    Tc = np.degrees(np.arctan2(Y, X)).ravel()
    Rc = (np.sqrt(X**2 + Y**2)).ravel()

    # Negative angles are corrected
    Tc[Tc < 0] = 360 + Tc[Tc < 0]

    # Using the known theta and range steps, the coordinates are mapped to
    # those of the data grid
    Tc = Tc / theta_step
    Rc = Rc / range_step

    # An array of polar coordinates is created stacking the previous arrays
    coords = np.vstack((Ac, Sc))

    # To avoid holes in the 360º - 0º boundary, the last column of the data
    # copied in the begining
    polar_data = np.vstack((polar_data, polar_data[-1,:]))

    # The data is mapped to the new coordinates
    # Values outside range are substituted with nans
    cart_data = mp(polar_data, coords, order=order, mode='constant', cval=np.nan)

    # The data is reshaped and returned
    return(cart_data.reshape(len(y), len(x)).T)

polar_data = ... # Here a 2D array of data is assumed, with shape thetas x ranges

# We create the x and y axes of the output cartesian data
x = y = np.arange(-100000, 100000, 1000)

# We call the mapping function assuming 1 degree of theta step and 500 meters of
# range step. The default order of 3 is used.
cart_data = polar_to_cart(polar_data, 1, 500, x, y)

I hope this helps someone in the same situation as me.

like image 40
Iñigo Hernáez Corres Avatar answered Oct 14 '22 11:10

Iñigo Hernáez Corres