def random_point(self, lam_min=None, lam_max=None, phi_min=None, phi_max=None): r""" Return a point (given in geodetic coordinates) sampled uniformly at random from the section of this ellipsoid with longitude in the range `lam_min <= lam < lam_max` and latitude in the range `phi_min <= phi < phi_max`. But avoid the poles. EXAMPLES:: >>> E = UNIT_SPHERE >>> print(E.random_point()) # doctest: +SKIP (-1.0999574573422948, 0.21029104897701129) """ PI = self.pi() if lam_min is None: lam_min = -PI if lam_max is None: lam_max = PI if phi_min is None: phi_min = -PI/2 if phi_max is None: phi_max = PI/2 if not self.radians: # Convert to radians. lam_min, lam_max, phi_min, phi_max = deg2rad( [lam_min, lam_max, phi_min, phi_max]) # Pick a longitude. while True: u = uniform(0, 1) lam = (lam_max - lam_min)*u + lam_min # Don't include lam_max. if lam < lam_max: # Success. break # Pick a latitude. delta = pi/360 while True: v = uniform(0, 1) if self.sphere: phi = arcsin( (sin(phi_max) - sin(phi_min))*v + sin(phi_min) ) else: # Sample from the authalic sphere. # The map from the ellipsoid to the authalic sphere is # an equiareal diffeomorphism. # So a uniform distribution on the authalic sphere gives # rise to a uniform distribution on the ellipsoid. beta0 = auth_lat(phi_min, e=self.e, radians=True) beta1 = auth_lat(phi_max, e=self.e, radians=True) beta = arcsin( (sin(beta1) - sin(beta0))*v + sin(beta0) ) phi = auth_lat(beta, e=self.e, radians=True, inverse=True) # Avoid the poles. if abs(phi) <= pi/2 - delta: # Success. break if not self.radians: # Convert back to degrees. lam, phi = rad2deg([lam, phi]) return lam, phi
def test_healpix_ellipsoid(self): # Expected output of healpix_ellipsoid() applied to inputs. e = 0.8 healpix_ellipsoid_outputs = [] for p in inputs: lam, phi = p beta = auth_lat(phi, e=e, radians=True) q = pjh.healpix_sphere(lam, beta) healpix_ellipsoid_outputs.append(q) # Forward projection should be correct on test points. given = inputs get = [pjh.healpix_ellipsoid(*p, e=e) for p in given] expect = healpix_ellipsoid_outputs # Fuzz to allow for rounding errors: error = 1e-12 for i in range(len(get)): self.assertTrue(rel_err(get[i], expect[i]) < error) # Inverse of projection of a point p should yield p. given = get get = [pjh.healpix_ellipsoid_inverse(*q, e=e) for q in given] expect = inputs # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = pi/4 alpha_ = auth_lat(auth_lat(alpha, e, radians=True), e, radians=True, inverse=True) error = 10*rel_err(alpha_, alpha) for i in range(len(get)): self.assertTrue(rel_err(get[i], expect[i]) < error)
def test_rhealpix_ellipsoid(self): # Test map projection. # Should return the same output as healpix_ellipsoid(), followed # by a scaling down, followed by combine_triangles(), # followed by a scaling up. e = 0.8 for (ns, ss) in product(list(range(4)), repeat=2): for p in inputs: q = pjr.rhealpix_ellipsoid(*p, north_square=ns, south_square=ss, e=e) qq = pjh.healpix_ellipsoid(*p, e=e) qq = pjr.combine_triangles(*qq, north_square=ns, south_square=ss) self.assertEqual(q, qq) # Test inverse projection. # The inverse of the projection of a point p should yield p. # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = pi/4 alpha_ = auth_lat(auth_lat(alpha, e), e, inverse=True) error = 10*rel_err(alpha_, alpha) for (ns, ss) in product(list(range(4)), repeat=2): for p in inputs: q = pjr.rhealpix_ellipsoid(*p, north_square=ns, south_square=ss, e=e) pp = pjr.rhealpix_ellipsoid_inverse(*q, north_square=ns, south_square=ss, e=e) self.assertTrue(rel_err(p, pp) < error)
def test_healpix_ellipsoid(self): # Expected output of healpix_ellipsoid() applied to inputs. e = 0.8 healpix_ellipsoid_outputs = [] for p in inputs: lam, phi = p beta = auth_lat(phi, e=e, radians=True) q = pjh.healpix_sphere(lam, beta) healpix_ellipsoid_outputs.append(q) # Forward projection should be correct on test points. given = inputs get = [pjh.healpix_ellipsoid(*p, e=e) for p in given] expect = healpix_ellipsoid_outputs # Fuzz to allow for rounding errors: error = 1e-12 for i in range(len(get)): self.assertTrue(rel_err(get[i], expect[i]) < error) # Inverse of projection of a point p should yield p. given = get get = [pjh.healpix_ellipsoid_inverse(*q, e=e) for q in given] expect = inputs # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = pi / 4 alpha_ = auth_lat(auth_lat(alpha, e, radians=True), e, radians=True, inverse=True) error = 10 * rel_err(alpha_, alpha) for i in range(len(get)): self.assertTrue(rel_err(get[i], expect[i]) < error)
def test_healpix_ellipsoid(self): # Ellipsoid parameters. a = 5 e = 0.8 R_A = auth_rad(a, e=e) # Expected output of healpix_ellipsoid() applied to inputs. healpix_ellipsoid_outputs = [] g = Proj(proj='healpix', R=R_A) for p in inputs: lam, phi = p beta = auth_lat(phi, e=e, radians=RADIANS) q = g(lam, beta, radians=RADIANS) healpix_ellipsoid_outputs.append(q) # Forward projection should be correct on test points. f = Proj(proj='healpix', a=a, e=e) given = inputs get = [f(*p, radians=RADIANS) for p in given] expect = healpix_ellipsoid_outputs # Fuzz to allow for rounding errors: error = 1e-12 print('=' * 80) print( 'HEALPix forward projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (radians) / expected output (meters) / received output') print('=' * 80) for i in range(len(get)): print(given[i], expect[i], get[i]) self.assertTrue(rel_err(get[i], expect[i]) < error) # Inverse of projection of a point p should yield p. given = get get = [f(*q, radians=RADIANS, inverse=True) for q in given] expect = inputs # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = PI / 4 alpha_ = auth_lat(auth_lat(alpha, e, radians=RADIANS), e, radians=RADIANS, inverse=True) error = 10 * rel_err(alpha_, alpha) print('=' * 80) print( 'HEALPix inverse projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (meters) / expected output (radians) / received output') print('=' * 80) for i in range(len(get)): print(given[i], expect[i], get[i]) self.assertTrue(rel_err(get[i], expect[i]) < error)
def test_rhealpix_ellipsoid(self): # Ellipsoid parameters. a = 5 e = 0.8 R_A = auth_rad(a, e=e) # Forward projection should be correct on test points. print('='*80) print('rHEALPix forward projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (radians) / expected output (meters) / received output') print('='*80) given = inputs # Fuzz to allow for rounding errors: error = 1e-12 for (ns, ss) in product(list(range(4)), repeat=2): print('_____ north_square = %s, south_square = %s' % (ns, ss)) expect = [] g = Proj(proj='rhealpix', R=R_A, north_square=ns, south_square=ss) for p in given: lam, phi = p beta = auth_lat(phi, e=e, radians=RADIANS) q = g(lam, beta, radians=RADIANS) expect.append(tuple(q)) f = Proj(proj='rhealpix', a=a, e=e, north_square=ns, south_square=ss) get = [f(*p, radians=RADIANS) for p in given] for i in range(len(given)): print(given[i], expect[i], get[i]) self.assertTrue(rel_err(get[i], expect[i]) < error) # Inverse of projection of point a p should yield p. # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = PI/4 alpha_ = auth_lat(auth_lat(alpha, e, radians=RADIANS), e, radians=RADIANS, inverse=True) error = 10*rel_err(alpha_, alpha) print('='*80) print('HEALPix inverse projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (meters) / expected output (radians) / received output') print('='*80) # The inverse of the projection of a point p should yield p. for (ns, ss) in product(list(range(4)), repeat=2): print('_____ north_square = %s, south_square = %s' % (ns, ss)) f = Proj(proj='rhealpix', a=a, e=e, north_square=ns, south_square=ss) for p in inputs: expect = p q = f(*p, radians=RADIANS) get = f(*q, radians=RADIANS, inverse=True) print(q, expect, get) self.assertTrue(rel_err(get, expect) < error)
def test_healpix_ellipsoid(self): # Ellipsoid parameters. a = 5 e = 0.8 R_A = auth_rad(a, e=e) # Expected output of healpix_ellipsoid() applied to inputs. healpix_ellipsoid_outputs = [] g = Proj(proj='healpix', R=R_A) for p in inputs: lam, phi = p beta = auth_lat(phi, e=e, radians=RADIANS) q = g(lam, beta, radians=RADIANS) healpix_ellipsoid_outputs.append(q) # Forward projection should be correct on test points. f = Proj(proj='healpix', a=a, e=e) given = inputs get = [f(*p, radians=RADIANS) for p in given] expect = healpix_ellipsoid_outputs # Fuzz to allow for rounding errors: error = 1e-12 print('='*80) print('HEALPix forward projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (radians) / expected output (meters) / received output') print('='*80) for i in range(len(get)): print(given[i], expect[i], get[i]) self.assertTrue(rel_err(get[i], expect[i]) < error) # Inverse of projection of a point p should yield p. given = get get = [f(*q, radians=RADIANS, inverse=True) for q in given] expect = inputs # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = PI/4 alpha_ = auth_lat(auth_lat(alpha, e, radians=RADIANS), e, radians=RADIANS, inverse=True) error = 10*rel_err(alpha_, alpha) print('='*80) print('HEALPix inverse projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (meters) / expected output (radians) / received output') print('='*80) for i in range(len(get)): print(given[i], expect[i], get[i]) self.assertTrue(rel_err(get[i], expect[i]) < error)
def csea_ellipsoid(lam, phi, e=0): r""" Compute the signature functions of the ISEA may projection of an oblate ellipsoid with eccentricity `e` whose authalic sphere is the unit sphere. INPUT: - `lam, phi` - Geodetic longitude-latitude coordinates in radians. Assume -pi <= `lam` < pi and -pi/2 <= `phi` <= pi/2. - `e` - Eccentricity of the oblate ellipsoid. """ beta = auth_lat(phi, e, radians=True) return csea_sphere(lam, beta)
def isea_ellipsoid(lam, phi, e=0): r""" Compute the signature functions of the ISEA may projection of an oblate ellipsoid with eccentricity `e` whose authalic sphere is the unit sphere. INPUT: - `lam, phi` - Geodetic longitude-latitude coordinates in radians. Assume -pi <= `lam` < pi and -pi/2 <= `phi` <= pi/2. - `e` - Eccentricity of the oblate ellipsoid. """ beta = auth_lat(phi, e, radians=True) return isea_sphere(lam, beta)
def __init__(self, R=None, a=WGS84_A, b=None, e=None, f=WGS84_F, lon_0=0, lat_0=0, radians=False): self.lon_0 = lon_0 self.lat_0 = lat_0 self.radians = radians if R is not None: # The ellipsoid is a sphere. # Override the other geometric parameters. self.sphere = True self.R = R self.a = R self.b = R self.e = 0 self.f = 0 self.R_A = R else: self.sphere = False self.a = a if b is not None: # Derive the other geometric parameters from a and b. self.b = b self.e = sqrt(1 - (b / a)**2) self.f = (a - b) / a elif e is not None: # Derive the other geometric parameters from a and e. self.e = e self.b = a * sqrt(1 - e**2) self.f = 1 - sqrt(1 - e**2) else: self.f = f self.b = self.a * (1 - f) self.e = sqrt(f * (1 - f)) self.R_A = auth_rad(self.a, self.e) self.phi_0 = auth_lat(arcsin(2.0 / 3), e=self.e, radians=True, inverse=True) if not self.radians: # Convert to degrees. self.phi_0 = rad2deg(self.phi_0)
def healpix_ellipsoid(lam, phi, e=0): r""" Compute the signature functions of the HEALPix projection of an oblate ellipsoid with eccentricity `e` whose authalic sphere is the unit sphere. Works when `e` = 0 (spherical case) too. INPUT: - `lam, phi` - Geodetic longitude-latitude coordinates in radians. Assume -pi <= `lam` < pi and -pi/2 <= `phi` <= pi/2. - `e` - Eccentricity of the oblate ellipsoid. EXAMPLES:: >>> print(my_round(healpix_ellipsoid(0, pi/7), 15)) (0, 0.51115723774642197) >>> print(my_round(healpix_ellipsoid(0, pi/7, e=0.8), 15)) (0, 0.26848445085783701) """ beta = auth_lat(phi, e, radians=True) return healpix_sphere(lam, beta)
def healpix_ellipsoid_inverse(x, y, e=0): r""" Compute the inverse of healpix_ellipsoid(). EXAMPLES:: >>> p = (0, pi/7) >>> q = healpix_ellipsoid(*p) >>> print(my_round(healpix_ellipsoid_inverse(*q), 15)) (0, 0.44879895051282798) >>> print(my_round(p, 15)) (0, 0.448798950512828) """ # Throw error if input coordinates are out of bounds. if not in_healpix_image(x, y): print("Error: input coordinates (%f, %f) are out of bounds" % \ (x, y)) return lam, beta = healpix_sphere_inverse(x, y) phi = auth_lat(beta, e, radians=True, inverse=True) return lam, phi
def __init__(self, R=None, a=WGS84_A, b=None, e=None, f=WGS84_F, lon_0=0, lat_0=0, radians=False): self.lon_0 = lon_0 self.lat_0 = lat_0 self.radians = radians if R is not None: # The ellipsoid is a sphere. # Override the other geometric parameters. self.sphere = True self.R = R self.a = R self.b = R self.e = 0 self.f = 0 self.R_A = R else: self.sphere = False self.a = a if b is not None: # Derive the other geometric parameters from a and b. self.b = b self.e = sqrt(1 - (b/a)**2) self.f = (a - b)/a elif e is not None: # Derive the other geometric parameters from a and e. self.e = e self.b = a*sqrt(1 - e**2) self.f = 1 - sqrt(1 - e**2) else: self.f = f self.b = self.a*(1 - f) self.e = sqrt(f*(1 - f)) self.R_A = auth_rad(self.a, self.e) self.phi_0 = auth_lat(arcsin(2.0/3), e=self.e, radians=True, inverse=True) if not self.radians: # Convert to degrees. self.phi_0 = rad2deg(self.phi_0)
def test_rhealpix_ellipsoid(self): # Ellipsoid parameters. a = 5 e = 0.8 R_A = auth_rad(a, e=e) # Forward projection should be correct on test points. print('=' * 80) print( 'rHEALPix forward projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (radians) / expected output (meters) / received output') print('=' * 80) given = inputs # Fuzz to allow for rounding errors: error = 1e-12 for (ns, ss) in product(list(range(4)), repeat=2): print('_____ north_square = %s, south_square = %s' % (ns, ss)) expect = [] g = Proj(proj='rhealpix', R=R_A, north_square=ns, south_square=ss) for p in given: lam, phi = p beta = auth_lat(phi, e=e, radians=RADIANS) q = g(lam, beta, radians=RADIANS) expect.append(tuple(q)) f = Proj(proj='rhealpix', a=a, e=e, north_square=ns, south_square=ss) get = [f(*p, radians=RADIANS) for p in given] for i in range(len(given)): print(given[i], expect[i], get[i]) self.assertTrue(rel_err(get[i], expect[i]) < error) # Inverse of projection of point a p should yield p. # Fuzz for rounding errors based on the error of the approximation to # the inverse authalic latitude function: alpha = PI / 4 alpha_ = auth_lat(auth_lat(alpha, e, radians=RADIANS), e, radians=RADIANS, inverse=True) error = 10 * rel_err(alpha_, alpha) print('=' * 80) print( 'HEALPix inverse projection, ellipsoid with major radius a = %s and eccentricity e = %s' % (a, e)) print('input (meters) / expected output (radians) / received output') print('=' * 80) # The inverse of the projection of a point p should yield p. for (ns, ss) in product(list(range(4)), repeat=2): print('_____ north_square = %s, south_square = %s' % (ns, ss)) f = Proj(proj='rhealpix', a=a, e=e, north_square=ns, south_square=ss) for p in inputs: expect = p q = f(*p, radians=RADIANS) get = f(*q, radians=RADIANS, inverse=True) print(q, expect, get) self.assertTrue(rel_err(get, expect) < error)