Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: Change PlateCarree vector handling #1920

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions lib/cartopy/crs.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,23 @@ def transform_vectors(self, src_proj, x, y, u, v):
# Rotate the input vectors to the projection.
#
# 1: Find the magnitude and direction of the input vectors.
vector_magnitudes = (u**2 + v**2)**0.5
vector_magnitudes = np.sqrt(u**2 + v**2)
if isinstance(src_proj, PlateCarree):
# This means we were given lon/lat coordinates and
# east/north vector components
# When projecting the components, we need to account for the
# fact that we are using PlateCarree to represent our vectors
# and scale the u component for the transformation to maintain
# the proper angles
scale_factor = np.cos(y / 180 * np.pi)
# Force these values due to floating point precision near
# the poles with cos()
pole_points = np.isclose(np.abs(y), 90)
if np.any(pole_points):
warnings.warn('Vector transforms near the pole '
'may not have been transformed correctly')
scale_factor[pole_points] = np.inf
u = u / scale_factor
vector_angles = np.arctan2(v, u)
# 2: Find a point in the direction of the original vector that is
# a small distance away from the base point of the vector (near
Expand Down Expand Up @@ -530,8 +546,25 @@ def transform_vectors(self, src_proj, x, y, u, v):
source_y + y_perturbations)
target_x_perturbed = proj_xyz[..., 0]
target_y_perturbed = proj_xyz[..., 1]

x_delta = target_x_perturbed - target_x
if isinstance(self, PlateCarree):
# Account for scaling to the North/South components in the
# opposite manner as the source handling
# (i.e. inverse scale factor), with target_y being
# the latitudes we are going to
scale_factor = np.cos(target_y / 180 * np.pi)
# Force these values due to floating point precision near
# the poles with cos()
pole_points = np.isclose(np.abs(target_y), 90)
if np.any(pole_points):
warnings.warn('Vector transforms near the pole '
'may not have been transformed correctly')
scale_factor[pole_points] = np.inf
scale_factor[pole_points] = np.inf
x_delta = x_delta * scale_factor
projected_angles = np.arctan2(target_y_perturbed - target_y,
target_x_perturbed - target_x)
x_delta)
if reversed_vectors.any():
projected_angles[reversed_vectors] += np.pi
# 5: Form the projected vector components, preserving the magnitude
Expand Down
8 changes: 4 additions & 4 deletions lib/cartopy/tests/test_vector_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ def test_with_transform(self):
[7.5, 7.5, 7.5, 7.5, 7.5],
[10., 10., 10., 10., 10]])
expected_u_grid = np.array([[np.nan, np.nan, np.nan, np.nan, np.nan],
[np.nan, 2.3838, 3.5025, 2.6152, np.nan],
[2, 3.0043, 4, 2.9022, 2]])
[np.nan, 2.3893, 3.5097, 2.6194, np.nan],
[2, 3.0005, 4, 2.8977, 2]])
expected_v_grid = np.array([[np.nan, np.nan, np.nan, np.nan, np.nan],
[np.nan, 2.6527, 2.1904, 2.4192, np.nan],
[5.5, 4.6483, 4, 4.47, 5.5]])
[np.nan, 2.6486, 2.1878, 2.4138, np.nan],
[5.5, 4.6497, 4, 4.4702, 5.5]])

x_grid, y_grid, u_grid, v_grid = vec_trans.vector_scalar_to_grid(
src_crs, target_crs, (5, 3), x_nps, y_nps, u_nps, v_nps)
Expand Down