Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 51473c2

Browse files
committed
Improve speed
1 parent a2ddfc0 commit 51473c2

File tree

1 file changed

+42
-33
lines changed
  • lib/matplotlib/projections

1 file changed

+42
-33
lines changed

lib/matplotlib/projections/geo.py

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import math
12
import numpy as np
23

34
from matplotlib import _api, rcParams
@@ -73,7 +74,7 @@ def _set_lim_and_transforms(self):
7374
# This is the transform for longitude ticks.
7475
self._xaxis_pretransform = \
7576
Affine2D() \
76-
.scale(1, self._longitude_cap * 2) \
77+
.scale(1, self._longitude_cap * 2.0) \
7778
.translate(0, -self._longitude_cap)
7879
self._xaxis_transform = \
7980
self._xaxis_pretransform + \
@@ -88,7 +89,7 @@ def _set_lim_and_transforms(self):
8889
Affine2D().translate(0, -4)
8990

9091
# This is the transform for latitude ticks.
91-
yaxis_stretch = Affine2D().scale(np.pi * 2, 1).translate(-np.pi, 0)
92+
yaxis_stretch = Affine2D().scale(np.pi * 2.0, 1).translate(-np.pi, 0)
9293
yaxis_space = Affine2D().scale(1, 1.1)
9394
self._yaxis_transform = \
9495
yaxis_stretch + \
@@ -109,7 +110,7 @@ def _set_lim_and_transforms(self):
109110
def _get_affine_transform(self):
110111
transform = self._get_core_transform(1)
111112
xscale, _ = transform.transform((np.pi, 0))
112-
_, yscale = transform.transform((0, np.pi/2))
113+
_, yscale = transform.transform((0, 0.5 * np.pi))
113114
return Affine2D() \
114115
.scale(0.5 / xscale, 0.5 / yscale) \
115116
.translate(0.5, 0.5)
@@ -261,14 +262,16 @@ def transform_non_affine(self, ll):
261262
longitude, latitude = ll.T
262263

263264
# Pre-compute some values
264-
half_long = longitude / 2.0
265-
cos_latitude = np.cos(latitude)
265+
half_long = 0.5 * longitude
266+
cos_half = np.cos(half_long)
267+
sin_half = np.cos(half_long)
268+
cos_latitude = cos_half*cos_half - sin_half*sin_half
266269

267-
alpha = np.arccos(cos_latitude * np.cos(half_long))
270+
alpha = np.arccos(cos_latitude * cos_half)
268271
sinc_alpha = np.sinc(alpha / np.pi) # np.sinc is sin(pi*x)/(pi*x).
269272

270-
x = (cos_latitude * np.sin(half_long)) / sinc_alpha
271-
y = np.sin(latitude) / sinc_alpha
273+
x = (cos_latitude * sin_half) / sinc_alpha
274+
y = 2.0 * sin_half * cos_half / sinc_alpha # sin(lat) / sinc_alpha
272275
return np.column_stack([x, y])
273276

274277
def inverted(self):
@@ -287,7 +290,7 @@ def inverted(self):
287290
return AitoffAxes.AitoffTransform(self._resolution)
288291

289292
def __init__(self, *args, **kwargs):
290-
self._longitude_cap = np.pi / 2.0
293+
self._longitude_cap = 0.5 * np.pi
291294
super().__init__(*args, **kwargs)
292295
self.set_aspect(0.5, adjustable='box', anchor='C')
293296
self.cla()
@@ -305,12 +308,14 @@ class HammerTransform(_GeoTransform):
305308
def transform_non_affine(self, ll):
306309
# docstring inherited
307310
longitude, latitude = ll.T
308-
half_long = longitude / 2.0
309-
cos_latitude = np.cos(latitude)
310-
sqrt2 = np.sqrt(2.0)
311-
alpha = np.sqrt(1.0 + cos_latitude * np.cos(half_long))
312-
x = (2.0 * sqrt2) * (cos_latitude * np.sin(half_long)) / alpha
313-
y = (sqrt2 * np.sin(latitude)) / alpha
311+
half_long = 0.5 * longitude
312+
cos_half = np.cos(half_long)
313+
sin_half = np.cos(half_long)
314+
cos_latitude = cos_half*cos_half - sin_half*sin_half
315+
sqrt2 = math.sqrt(2.0)
316+
alpha = np.sqrt(1.0 + cos_latitude * cos_half)
317+
x = (2.0 * sqrt2 * cos_latitude * sin_half) / alpha
318+
y = (2.0 * sqrt2 * cos_half * sin_half) / alpha # sin(lat)
314319
return np.column_stack([x, y])
315320

316321
def inverted(self):
@@ -323,16 +328,16 @@ def transform_non_affine(self, xy):
323328
# docstring inherited
324329
x, y = xy.T
325330
z = np.sqrt(1 - (x / 4) ** 2 - (y / 2) ** 2)
326-
longitude = 2 * np.arctan((z * x) / (2 * (2 * z ** 2 - 1)))
327-
latitude = np.arcsin(y*z)
331+
longitude = 2.0 * np.arctan((z * x) / (2 * (2 * z ** 2 - 1)))
332+
latitude = np.arcsin(y * z)
328333
return np.column_stack([longitude, latitude])
329334

330335
def inverted(self):
331336
# docstring inherited
332337
return HammerAxes.HammerTransform(self._resolution)
333338

334339
def __init__(self, *args, **kwargs):
335-
self._longitude_cap = np.pi / 2.0
340+
self._longitude_cap = 0.5 * np.pi
336341
super().__init__(*args, **kwargs)
337342
self.set_aspect(0.5, adjustable='box', anchor='C')
338343
self.cla()
@@ -351,12 +356,12 @@ def transform_non_affine(self, ll):
351356
# docstring inherited
352357
def d(theta):
353358
delta = (-(theta + np.sin(theta) - pi_sin_l)
354-
/ (1 + np.cos(theta)))
359+
/ (1.0 + np.cos(theta)))
355360
return delta, np.abs(delta) > 0.001
356361

357362
longitude, latitude = ll.T
358363

359-
clat = np.pi/2 - np.abs(latitude)
364+
clat = 0.5 * np.pi - np.abs(latitude)
360365
ihigh = clat < 0.087 # within 5 degrees of the poles
361366
ilow = ~ihigh
362367
aux = np.empty(latitude.shape, dtype=float)
@@ -368,16 +373,17 @@ def d(theta):
368373
while np.any(large_delta):
369374
theta[large_delta] += delta[large_delta]
370375
delta, large_delta = d(theta)
371-
aux[ilow] = theta / 2
376+
aux[ilow] = 0.5 * theta
372377

373378
if ihigh.any(): # Taylor series-based approx. solution
374379
e = clat[ihigh]
375-
d = 0.5 * (3 * np.pi * e**2) ** (1.0/3)
376-
aux[ihigh] = (np.pi/2 - d) * np.sign(latitude[ihigh])
380+
d = 0.5 * np.cbrt(3.0 * np.pi * e ** 2)
381+
aux[ihigh] = (0.5 * np.pi - d) * np.sign(latitude[ihigh])
377382

378383
xy = np.empty(ll.shape, dtype=float)
379-
xy[:, 0] = (2.0 * np.sqrt(2.0) / np.pi) * longitude * np.cos(aux)
380-
xy[:, 1] = np.sqrt(2.0) * np.sin(aux)
384+
sqrt2 = math.sqrt(2)
385+
xy[:, 0] = (2.0 * sqrt2 / np.pi) * longitude * np.cos(aux)
386+
xy[:, 1] = sqrt2 * np.sin(aux)
381387

382388
return xy
383389

@@ -392,9 +398,10 @@ def transform_non_affine(self, xy):
392398
x, y = xy.T
393399
# from Equations (7, 8) of
394400
# https://mathworld.wolfram.com/MollweideProjection.html
395-
theta = np.arcsin(y / np.sqrt(2))
396-
longitude = (np.pi / (2 * np.sqrt(2))) * x / np.cos(theta)
397-
latitude = np.arcsin((2 * theta + np.sin(2 * theta)) / np.pi)
401+
sqrt2 = math.sqrt(2.0)
402+
theta = np.arcsin(y / sqrt2)
403+
longitude = (np.pi / (2.0 * sqrt2)) * x / np.cos(theta)
404+
latitude = np.arcsin((2.0 * theta + np.sin(2.0 * theta)) / np.pi)
398405
return np.column_stack([longitude, latitude])
399406

400407
def inverted(self):
@@ -434,15 +441,17 @@ def transform_non_affine(self, ll):
434441
clat = self._center_latitude
435442
cos_lat = np.cos(latitude)
436443
sin_lat = np.sin(latitude)
444+
cos_clat = np.cos(clat)
445+
sin_clat = np.sin(clat)
437446
diff_long = longitude - clong
438447
cos_diff_long = np.cos(diff_long)
439448

440449
inner_k = np.maximum( # Prevent divide-by-zero problems
441-
1 + np.sin(clat)*sin_lat + np.cos(clat)*cos_lat*cos_diff_long,
450+
1.0 + sin_clat*sin_lat + cos_clat*cos_lat*cos_diff_long,
442451
1e-15)
443-
k = np.sqrt(2 / inner_k)
452+
k = np.sqrt(2.0 / inner_k)
444453
x = k * cos_lat*np.sin(diff_long)
445-
y = k * (np.cos(clat)*sin_lat - np.sin(clat)*cos_lat*cos_diff_long)
454+
y = k * (cos_clat*sin_lat - sin_clat*cos_lat*cos_diff_long)
446455

447456
return np.column_stack([x, y])
448457

@@ -466,7 +475,7 @@ def transform_non_affine(self, xy):
466475
clong = self._center_longitude
467476
clat = self._center_latitude
468477
p = np.maximum(np.hypot(x, y), 1e-9)
469-
c = 2 * np.arcsin(0.5 * p)
478+
c = 2.0 * np.arcsin(0.5 * p)
470479
sin_c = np.sin(c)
471480
cos_c = np.cos(c)
472481

@@ -485,7 +494,7 @@ def inverted(self):
485494
self._resolution)
486495

487496
def __init__(self, *args, center_longitude=0, center_latitude=0, **kwargs):
488-
self._longitude_cap = np.pi / 2
497+
self._longitude_cap = 0.5 * np.pi
489498
self._center_longitude = center_longitude
490499
self._center_latitude = center_latitude
491500
super().__init__(*args, **kwargs)

0 commit comments

Comments
 (0)