Skip to content

Commit 6f56b97

Browse files
authored
Merge pull request #929 from dopplershift/fix_issues_339_455
Fix stereographic scaling issues
2 parents 3ca1301 + da433a5 commit 6f56b97

2 files changed

Lines changed: 62 additions & 13 deletions

File tree

lib/cartopy/crs.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,12 +1310,27 @@ def y_limits(self):
13101310
class Stereographic(Projection):
13111311
def __init__(self, central_latitude=0.0, central_longitude=0.0,
13121312
false_easting=0.0, false_northing=0.0,
1313-
true_scale_latitude=None, globe=None):
1313+
true_scale_latitude=None,
1314+
scale_factor=None, globe=None):
13141315
proj4_params = [('proj', 'stere'), ('lat_0', central_latitude),
13151316
('lon_0', central_longitude),
13161317
('x_0', false_easting), ('y_0', false_northing)]
1317-
if true_scale_latitude:
1318+
1319+
if true_scale_latitude is not None:
1320+
if central_latitude not in (-90., 90.):
1321+
warnings.warn('"true_scale_latitude" parameter is only used '
1322+
'for polar stereographic projections. Consider '
1323+
'the use of "scale_factor" instead.')
13181324
proj4_params.append(('lat_ts', true_scale_latitude))
1325+
1326+
if scale_factor is not None:
1327+
if true_scale_latitude is not None:
1328+
raise ValueError('It does not make sense to provide both '
1329+
'"scale_factor" and "true_scale_latitude". '
1330+
'Ignoring "scale_factor".')
1331+
else:
1332+
proj4_params.append(('k_0', scale_factor))
1333+
13191334
super(Stereographic, self).__init__(proj4_params, globe=globe)
13201335

13211336
# TODO: Let the globe return the semimajor axis always.
@@ -1358,17 +1373,23 @@ def y_limits(self):
13581373

13591374

13601375
class NorthPolarStereo(Stereographic):
1361-
def __init__(self, central_longitude=0.0, globe=None):
1376+
def __init__(self, central_longitude=0.0, true_scale_latitude=None,
1377+
globe=None):
13621378
super(NorthPolarStereo, self).__init__(
13631379
central_latitude=90,
1364-
central_longitude=central_longitude, globe=globe)
1380+
central_longitude=central_longitude,
1381+
true_scale_latitude=true_scale_latitude, # None is +90
1382+
globe=globe)
13651383

13661384

13671385
class SouthPolarStereo(Stereographic):
1368-
def __init__(self, central_longitude=0.0, globe=None):
1386+
def __init__(self, central_longitude=0.0, true_scale_latitude=None,
1387+
globe=None):
13691388
super(SouthPolarStereo, self).__init__(
13701389
central_latitude=-90,
1371-
central_longitude=central_longitude, globe=globe)
1390+
central_longitude=central_longitude,
1391+
true_scale_latitude=true_scale_latitude, # None is -90
1392+
globe=globe)
13721393

13731394

13741395
class Orthographic(Projection):

lib/cartopy/tests/crs/test_stereographic.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# (C) British Crown Copyright 2013 - 2017, Met Office
1+
# (C) British Crown Copyright 2013 - 2018, Met Office
22
#
33
# This file is part of cartopy.
44
#
@@ -52,14 +52,42 @@ def test_eccentric_globe(self):
5252
[-3932.82587779, 3932.82587779], decimal=4)
5353

5454
def test_true_scale(self):
55-
# The "true_scale_latitude" parameter to Stereographic appears
56-
# meaningless. This test just ensures that the correct proj4
57-
# string is being created. (#339)
58-
stereo = ccrs.Stereographic(true_scale_latitude=10)
59-
expected = ('+ellps=WGS84 +proj=stere +lat_0=0.0 +lon_0=0.0 '
60-
'+x_0=0.0 +y_0=0.0 +lat_ts=10 +no_defs')
55+
# The "true_scale_latitude" parameter only makes sense for
56+
# polar stereographic projections (#339 and #455).
57+
# For now only the proj4 string creation is tested
58+
# See test_scale_factor for test on projection.
59+
globe = ccrs.Globe(ellipse='sphere')
60+
stereo = ccrs.NorthPolarStereo(true_scale_latitude=30, globe=globe)
61+
expected = ('+ellps=sphere +proj=stere +lat_0=90 +lon_0=0.0 '
62+
'+x_0=0.0 +y_0=0.0 +lat_ts=30 +no_defs')
63+
assert stereo.proj4_init == expected
64+
65+
def test_scale_factor(self):
66+
# See #455
67+
# Use spherical Earth in North Polar Stereographic to check
68+
# equivalence between true_scale and scale_factor.
69+
# In these conditions a scale factor of 0.75 corresponds exactly to
70+
# a standard parallel of 30N.
71+
globe = ccrs.Globe(ellipse='sphere')
72+
stereo = ccrs.Stereographic(central_latitude=90., scale_factor=0.75,
73+
globe=globe)
74+
expected = ('+ellps=sphere +proj=stere +lat_0=90.0 +lon_0=0.0 '
75+
'+x_0=0.0 +y_0=0.0 +k_0=0.75 +no_defs')
6176
assert stereo.proj4_init == expected
6277

78+
# Now test projections
79+
lon, lat = 10, 10
80+
projected_scale_factor = stereo.transform_point(lon, lat,
81+
ccrs.Geodetic())
82+
83+
# should be equivalent to North Polar Stereo with
84+
# true_scale_latitude = 30
85+
nstereo = ccrs.NorthPolarStereo(globe=globe, true_scale_latitude=30)
86+
projected_true_scale = nstereo.transform_point(lon, lat,
87+
ccrs.Geodetic())
88+
89+
assert projected_true_scale == projected_scale_factor
90+
6391
def test_eastings(self):
6492
stereo = ccrs.Stereographic()
6593
stereo_offset = ccrs.Stereographic(false_easting=1234,

0 commit comments

Comments
 (0)