# Manually transforming rotated lat/lon to regular lat/lon?

First I should clarify I don't have previous experience with the field, so I don't know the technical terminology. My question is as follows:

I have two weather datasets:

• The first one has the regular coordinate system (I don't know if it has an specific name), ranging from -90 to 90 and -180 to 180, and the poles are at latitudes -90 and 90.

• In the second one, although it should correspond to the same region, I noticed something different: latitude and longitude were not the same, as they have another reference point (in the description is called a rotated grid). Together with the lat/lon pairs, comes the following information: southern pole lat: -35.00, southern pole lon: -15.00, angle: 0.0.

I need to transform the second pair of lon/lat to the first one. It could be as simple as add 35 to the latitudes and 15 to the longitudes, since the angle is 0 and it seems a simple shifting, but I'm not sure.

Edit: The information I have about the coordinates is the following

http://rda.ucar.edu/docs/formats/grib/gribdoc/llgrid.html

Apparently, the second coordinate system is defined by a general rotation of the sphere

"One choice for these parameters is:

• The geographic latitude in degrees of the southern pole of the coordinate system, thetap for example;

• The geographic longitude in degrees of the southern pole of the coordinate system, lambdap for example;

• The angle of rotation in degrees about the new polar axis (measured clockwise when looking from the southern to the northern pole) of the coordinate system, assuming the new axis to have been obtained by first rotating the sphere through lambdap degrees about the geographic polar axis, and then rotating through (90 + thetap) degrees so that the southern pole moved along the (previously rotated) Greenwich meridian."

but still I don't know how to convert this to the first one.

• So is this GRIB data? If so, maybe we need a grib tag. – Kirk Kuykendall Jun 9 '11 at 15:59
• @skd the ECMWF links do not seem to be valid. Can you edit ? – gansub Dec 13 '15 at 7:05
• @gansub I've edited the links. I don't know if the information is exactly the same since it has been a long time, but I believe the new link can provide some context for future reference. – skd Dec 21 '15 at 17:32
• @skd when you say `angle=0.0`, do you mean the bearing? I have a netcdf file with the rotated pole coordinates, but there's no mention of any angle. – FaCoffee Dec 15 '16 at 14:34
• @CF84 I'm actually not sure. I guess if there is no mention of the angle then it is the same as angle = 0 – skd Dec 16 '16 at 14:34

Manually reversing the rotation should do the trick; there should be a formula for rotating spherical coordinate systems somewhere, but since I can't find it, here's the derivation ( ' marks the rotated coordinate system; normal geographic coordinates use plain symbols):

First convert the data in the second dataset from spherical (lon', lat') to (x',y',z') using:

``````x' = cos(lon')*cos(lat')
y' = sin(lon')*cos(lat')
z' = sin(lat')
``````

Then use two rotation matrices to rotate the second coordinate system so that it coincides with the first 'normal' one. We'll be rotating the coordinate axes, so we can use the axis rotation matrices. We need to reverse the sign in the ϑ matrix to match the rotation sense used in the ECMWF definition, which seems to be different from the standard positive direction.

Since we're undoing the rotation described in the definition of the coordinate system, we first rotate by ϑ = -(90 + lat0) = -55 degrees around the y' axis (along the rotated Greenwich meridian) and then by φ = -lon0 = +15 degrees around the z axis):

``````x   ( cos(φ), sin(φ), 0) (  cos(ϑ), 0, sin(ϑ)) (x')
y = (-sin(φ), cos(φ), 0).(  0     , 1, 0     ).(y')
z   ( 0     , 0     , 1) ( -sin(ϑ), 0, cos(ϑ)) (z')
``````

Expanded, this becomes:

``````x = cos(ϑ) cos(φ) x' + sin(φ) y' + sin(ϑ) cos(φ) z'
y = -cos(ϑ) sin(φ) x' + cos(φ) y' - sin(ϑ) sin(φ) z'
z = -sin(ϑ) x' + cos(ϑ) z'
``````

Then convert back to 'normal' (lat,lon) using

``````lat = arcsin(z)
lon = atan2(y, x)
``````

If you don't have atan2, you can implement it yourself by using atan(y/x) and examining the signs of x and y

Make sure that you convert all angles to radians before using the trigonometric functions, or you'll get weird results; convert back to degrees in the end if that's what you prefer...

Example (rotated sphere coordinates ==> standard geographic coordinates):

• southern pole of the rotated CS is (lat0, lon0)

(-90°, *) ==> (-35°, -15°)

• prime meridian of the rotated CS is the -15° meridian in geographic (rotated 55° towards north)

(0°, 0°) ==> (55°, -15°)

• symmetry requires that both equators intersect at 90°/-90° in the new CS, or 75°/-105° in geographic coordinates

(0°, 90°) ==> (0°, 75°)
(0°, -90°) ==> (0°,-105°)

EDIT: Rewritten the answer thanks to very constructive comment by whuber: the matrices and the expansion are now in sync, using proper signs for the rotation parameters; added reference to the definition of the matrices; removed atan(y/x) from the answer; added examples of conversion.

EDIT 2: It is possible to derive expressions for the same result without explicit tranformation into cartesian space. The `x`, `y`, `z` in the result can be substituted with their corresponding expressions, and the same can be repeated for `x'`, `y'` and `z'`. After applying some trigonometric identities, the following single-step expressions emerge:

``````lat = arcsin(cos(ϑ) sin(lat') - cos(lon') sin(ϑ) cos(lat'))
lon = atan2(sin(lon'), tan(lat') sin(ϑ) + cos(lon') cos(ϑ)) - φ
``````
• The idea's good, but some of the details need fixing. lon0 = -15, not +15. All three lines in the expansion of the matrix product are incorrect. ATan2 (or its equivalent) must be used, modified to return any reasonable longitude when x=y=0. Note that because x^2+y^2+z^2 = 1, at the end you get simply lat = Arcsin(z). – whuber Sep 19 '11 at 19:59
• Thanks. I fixed the answer to at least make the math correct. The rotations should now match the description in the CS definition, but it's hard to be certain about their sign without an example (other than the position of the south pole). – mkadunc Sep 20 '11 at 12:36
• Well done! I'm surprised this reply isn't getting more votes, because it provides useful and hard-to-find material. – whuber Sep 20 '11 at 15:07
• This is indeed very hard to find material, thank you very much for the answer. I ended up using this software code.zmaw.de/projects/cdo to convert from a rotated grid to a regular grid. My guess is that it first transforms the coordinates as in this answer and then interpolates them in order to give the results at the points of a rectangular grid. Although a little late, I leave this her for future reference. – skd Mar 19 '13 at 15:00
• @alfe I am not an expert on Bloch spheres, but the principle looks very similar to what I've done, but instead of converting to cartesian space with 3 real coordinates, the hint suggests converting to a space with 2 imaginary coordinates (which means 4 real components) and executing the rotation there. Triggered by your comment, I put all the expressions together and added a result in which the intermediate cartesian step is not apparent any more. – mkadunc Dec 15 '17 at 14:52

In case anyone is interested I've shared a MATLAB script on the file exchange transforming regular lat/lon to rotated lat/lon and vice versa: Rotated grid transform

``````function [grid_out] = rotated_grid_transform(grid_in, option, SP_coor)

lon = grid_in(:,1);
lat = grid_in(:,2);

lon = (lon*pi)/180; % Convert degrees to radians
lat = (lat*pi)/180;

SP_lon = SP_coor(1);
SP_lat = SP_coor(2);

theta = 90+SP_lat; % Rotation around y-axis
phi = SP_lon; % Rotation around z-axis

phi = (phi*pi)/180; % Convert degrees to radians
theta = (theta*pi)/180;

x = cos(lon).*cos(lat); % Convert from spherical to cartesian coordinates
y = sin(lon).*cos(lat);
z = sin(lat);

if option == 1 % Regular -> Rotated

x_new = cos(theta).*cos(phi).*x + cos(theta).*sin(phi).*y + sin(theta).*z;
y_new = -sin(phi).*x + cos(phi).*y;
z_new = -sin(theta).*cos(phi).*x - sin(theta).*sin(phi).*y + cos(theta).*z;

elseif option == 2 % Rotated -> Regular

phi = -phi;
theta = -theta;

x_new = cos(theta).*cos(phi).*x + sin(phi).*y + sin(theta).*cos(phi).*z;
y_new = -cos(theta).*sin(phi).*x + cos(phi).*y - sin(theta).*sin(phi).*z;
z_new = -sin(theta).*x + cos(theta).*z;

end

lon_new = atan2(y_new,x_new); % Convert cartesian back to spherical coordinates
lat_new = asin(z_new);

lon_new = (lon_new*180)/pi; % Convert radians back to degrees
lat_new = (lat_new*180)/pi;

grid_out = [lon_new lat_new];
``````
• Just in case the link goes dead can you please insert the code for future readers. Thanks. – Michael Stimson Oct 1 '15 at 0:19
• Sure - code inserted. – simondk Oct 6 '15 at 8:35

This transformation can also be computed with proj software (either using command-line or programmatically) by employing what proj calls an oblique translation (`ob_tran`) applied to a latlon transformation. The projection parameters to be set are:

• `o_lat_p` = north pole latitude => 35° in the example
• `lon_0` = south pole longitude => -15° in the example
• `o_lon_p` = 0

additionally, `-m 57.2957795130823` (180/pi) is required in order to consider projected values in degrees.

Replicating the examples proposed by mkadunc gives the same result (notice that here order is `lon lat` not `(lat,lon)`, coodinates are typed in standard input, output is marked by `=>`):

``````invproj -f "=> %.6f" -m 57.2957795130823 +proj=ob_tran +o_proj=latlon +o_lon_p=0 +o_lat_p=35 +lon_0=-15
0 -90
=> -15.000000   => -35.000000
40 -90
=> -15.000000   => -35.000000
0 0
=> -15.000000   => 55.000000
90 0
=> 75.000000    => -0.000000
-90 0
=> -105.000000  => -0.000000
``````

`invproj` command is used for converting from "projected" (i.e. rotated) coordinates to geographic, while `proj` for doing the opposite.

I have developed an asp.net page for converting coordinate from rotated to non-rotated based on CORDEX domains.

It based on above methods. You can use it freely in this link:

Manually transforming rotated lat/lon to regular lat/lon

https://www.mathworks.com/matlabcentral/fileexchange/43435-rotated-grid-transform

PYTHON:

``````from math import *

def rotated_grid_transform(grid_in, option, SP_coor):
lon = grid_in
lat = grid_in;

lon = (lon*pi)/180; # Convert degrees to radians
lat = (lat*pi)/180;

SP_lon = SP_coor;
SP_lat = SP_coor;

theta = 90+SP_lat; # Rotation around y-axis
phi = SP_lon; # Rotation around z-axis

theta = (theta*pi)/180;
phi = (phi*pi)/180; # Convert degrees to radians

x = cos(lon)*cos(lat); # Convert from spherical to cartesian coordinates
y = sin(lon)*cos(lat);
z = sin(lat);

if option == 1: # Regular -> Rotated

x_new = cos(theta)*cos(phi)*x + cos(theta)*sin(phi)*y + sin(theta)*z;
y_new = -sin(phi)*x + cos(phi)*y;
z_new = -sin(theta)*cos(phi)*x - sin(theta)*sin(phi)*y + cos(theta)*z;

else:  # Rotated -> Regular

phi = -phi;
theta = -theta;

x_new = cos(theta)*cos(phi)*x + sin(phi)*y + sin(theta)*cos(phi)*z;
y_new = -cos(theta)*sin(phi)*x + cos(phi)*y - sin(theta)*sin(phi)*z;
z_new = -sin(theta)*x + cos(theta)*z;

lon_new = atan2(y_new,x_new); # Convert cartesian back to spherical coordinates
lat_new = asin(z_new);

lon_new = (lon_new*180)/pi; # Convert radians back to degrees
lat_new = (lat_new*180)/pi;

print lon_new,lat_new;

rotated_grid_transform((0,0), 1, (0,30))
``````

The cartopy module for python has a rotated pole facility. It understands the transformations it seems.

https://scitools.org.uk/cartopy/docs/latest/gallery/rotated_pole.html#sphx-glr-gallery-rotated-pole-py