Пример #1
0
 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
Пример #2
0
    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)
Пример #3
0
 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)
Пример #4
0
    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)
Пример #5
0
    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)
Пример #8
0
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)  
Пример #9
0
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)  
Пример #10
0
 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)
Пример #11
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)  
Пример #12
0
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
Пример #13
0
 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)
Пример #14
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)
Пример #15
0
    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