Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

#! /usr/bin/env python 

# -*- coding: utf-8 -*- 

 

import os 

 

 

class FlinnEngdahl(object): 

    """ 

    Load data from asc files and allow to resolve coordinates 

    to Flinn Engdahl region names. 

    """ 

 

    data_directory = os.path.join(os.path.dirname(__file__), 'data') 

 

    names_file = os.path.join(data_directory, 'names.asc') 

    quadsindex_file = os.path.join(data_directory, 'quadsidx.asc') 

    sect_files = ( 

        os.path.join(data_directory, 'nesect.asc'), 

        os.path.join(data_directory, 'nwsect.asc'), 

        os.path.join(data_directory, 'sesect.asc'), 

        os.path.join(data_directory, 'swsect.asc') 

    ) 

    quads_order = ('ne', 'nw', 'se', 'sw') 

 

    def __init__(self): 

        self.quads_index = [] 

 

        with open(self.names_file, 'r') as fh: 

            self.names = [name.strip() for name in fh] 

 

        with open(self.quadsindex_file, 'r') as fh: 

            indexes = [] 

            for index in fh: 

                indexes += [n.strip() for n in index.split(' ') if n != ''] 

 

        self.lons_per_lat = dict(zip( 

            self.quads_order, 

            [indexes[x:x + 91] for x in xrange(0, len(indexes), 91)] 

        )) 

 

        self.lat_begins = {} 

 

        for quad, index in self.lons_per_lat.items(): 

            begin = 0 

            end = -1 

            begins = [] 

            n = 0 

 

            for item in index: 

                n += 1 

                begin = end + 1 

                begins.append(begin) 

                end += int(item) 

 

            self.lat_begins[quad] = begins 

 

        self.lons = {} 

        self.fenums = {} 

        for quad, sect_file in zip(self.quads_order, self.sect_files): 

            sect = [] 

            with open(sect_file, 'r') as fh: 

                for line in fh: 

                    sect += [int(v) for v in line.strip().split(' ') 

                             if v != ''] 

 

            lons = [] 

            fenums = [] 

            n = 0 

            for item in sect: 

                n += 1 

                if n % 2: 

                    lons.append(item) 

                else: 

                    fenums.append(item) 

 

            self.lons[quad] = lons 

            self.fenums[quad] = fenums 

 

    def get_quadrant(self, longitude, latitude): 

        """ 

        Return quadrat from given coordinate 

 

        :param longitude: WGS84 longitude 

        :type longitude: int or float 

        :param latitude: WGS84 latitude 

        :type latitude: int or float 

        :rtype: string 

        :return: Quadrant name (ne, nw, se and sw) 

        """ 

        if longitude >= 0 and latitude >= 0: 

            return 'ne' 

        if longitude < 0 and latitude >= 0: 

            return 'nw' 

        if longitude >= 0 and latitude < 0: 

            return 'se' 

        if longitude < 0 and latitude < 0: 

            return 'sw' 

 

    def get_region(self, longitude, latitude): 

        """ 

        Return region from given coordinate 

 

        :param longitude: WGS84 longitude 

        :type longitude: int or float 

        :param latitude: WGS84 latitude 

        :type latitude: int or float 

        :rtype: string 

        :return: Flinn Engdahl region name 

        """ 

 

        if longitude < -180 or longitude > 180: 

            raise ValueError 

        if latitude < -90 or latitude > 90: 

            raise ValueError 

 

        if longitude == -180: 

            longitude = 180 

 

        quad = self.get_quadrant(longitude, latitude) 

 

        abs_longitude = int(abs(longitude)) 

        abs_latitude = int(abs(latitude)) 

 

        begin = self.lat_begins[quad][abs_latitude] 

        num = int(self.lons_per_lat[quad][abs_latitude]) 

 

        my_lons = self.lons[quad][begin:begin + num] 

        my_fenums = self.fenums[quad][begin:begin + num] 

 

        n = 0 

        for longitude in my_lons: 

            if longitude > abs_longitude: 

                break 

            n += 1 

 

        fe_index = n - 1 

        fe_num = my_fenums[fe_index] 

        fe_name = self.names[fe_num - 1] 

 

        return fe_name 

 

 

if __name__ == '__main__': 

    import doctest 

    doctest.testmod(exclude_empty=True)