Coverage for pyguymer3/geo/find_middle_of_locs.py: 73%

26 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-08 18:47 +0000

1#!/usr/bin/env python3 

2 

3# Define function ... 

4def find_middle_of_locs( 

5 lons, 

6 lats, 

7 /, 

8 *, 

9 angConv = 0.1, 

10 conv = 1.0e3, 

11 debug = __debug__, 

12 eps = 1.0e-12, 

13 method = "GeodesicBox", 

14 midLat = None, 

15 midLon = None, 

16 nAng = 9, 

17 nIter = 100, 

18 nRefine = 1, 

19 pad = 10.0e3, 

20 useSciPy = False, 

21): 

22 """Find the middle of some locations 

23 

24 This function finds the middle of some locations such that the Geodesic 

25 distances to the West/East extremities are equalised and the Geodesic 

26 distances to the South/North extremities are equalised. 

27 

28 Parameters 

29 ---------- 

30 lons : numpy.ndarray 

31 the longitudes (in degrees) 

32 lats : numpy.ndarray 

33 the latitudes (in degrees) 

34 angConv : float, optional 

35 the angle change which classifies as converged (in degrees) 

36 conv : float, optional 

37 the distance that defines the middle as being converged (in degrees or 

38 metres) 

39 debug : bool, optional 

40 print debug messages 

41 eps : float, optional 

42 the tolerance of the Vincenty formula iterations 

43 method : str, optional 

44 the method for finding the middle of the locations 

45 nAng : int, optional 

46 the number of angles around the middle location to search over 

47 nIter : int, optional 

48 the maximum number of iterations (particularly the Vincenty formula) 

49 nRefine : int, optional 

50 the number of refinements to make (each refinement halves the "conv" 

51 distance) 

52 pad : float, optional 

53 the padding to add to the maximum distance from the middle to the most 

54 extreme location (in degrees or metres) 

55 useSciPy : bool, optional 

56 use "scipy.optimize.minimize" or my own minimizer 

57 

58 Returns 

59 ------- 

60 midLon : float 

61 the middle longitude (in degrees) 

62 midLat : float 

63 the middle latitude (in degrees) 

64 maxDist : float 

65 the maximum Geodesic distance from the middle to the most extreme 

66 location (in metres) 

67 

68 Notes 

69 ----- 

70 Copyright 2017 Thomas Guymer [1]_ 

71 

72 References 

73 ---------- 

74 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3 

75 """ 

76 

77 # Import special modules ... 

78 try: 

79 import numpy 

80 except: 

81 raise Exception("\"numpy\" is not installed; run \"pip install --user numpy\"") from None 

82 

83 # Import sub-functions ... 

84 from .find_middle_of_locsSrc import find_middle_of_locs_euclideanBox 

85 from .find_middle_of_locsSrc import find_middle_of_locs_euclideanCircle 

86 from .find_middle_of_locsSrc import find_middle_of_locs_geodesicBox 

87 from .find_middle_of_locsSrc import find_middle_of_locs_geodesicCircle 

88 

89 # ************************************************************************** 

90 

91 # Check arguments ... 

92 assert isinstance(lons, numpy.ndarray), "\"lons\" is not a NumPy array" 

93 assert isinstance(lats, numpy.ndarray), "\"lats\" is not a NumPy array" 

94 if lons.size == 1: 

95 if pad > 0.0: 

96 return lons[0], lats[0], pad 

97 return lons[0], lats[0], 0.0 

98 

99 # ************************************************************************** 

100 

101 # Check what method the user wants ... 

102 match method: 

103 case "EuclideanBox": 

104 # Return answer ... 

105 return find_middle_of_locs_euclideanBox( 

106 lons, 

107 lats, 

108 debug = debug, 

109 pad = pad, 

110 ) 

111 case "EuclideanCircle": 

112 # Return answer ... 

113 return find_middle_of_locs_euclideanCircle( 

114 lons, 

115 lats, 

116 angConv = angConv, 

117 conv = conv, 

118 debug = debug, 

119 iRefine = 0, 

120 midLat = midLat, 

121 midLon = midLon, 

122 nAng = nAng, 

123 nIter = nIter, 

124 nRefine = nRefine, 

125 pad = pad, 

126 useSciPy = useSciPy, 

127 ) 

128 case "GeodesicBox": 

129 # Return answer ... 

130 return find_middle_of_locs_geodesicBox( 

131 lons, 

132 lats, 

133 conv = conv, 

134 debug = debug, 

135 eps = eps, 

136 iRefine = 0, 

137 midLat = midLat, 

138 midLon = midLon, 

139 nIter = nIter, 

140 nRefine = nRefine, 

141 pad = pad, 

142 ) 

143 case "GeodesicCircle": 

144 # Return answer ... 

145 return find_middle_of_locs_geodesicCircle( 

146 lons, 

147 lats, 

148 angConv = angConv, 

149 conv = conv, 

150 debug = debug, 

151 eps = eps, 

152 iRefine = 0, 

153 midLat = midLat, 

154 midLon = midLon, 

155 nAng = nAng, 

156 nIter = nIter, 

157 nRefine = nRefine, 

158 pad = pad, 

159 useSciPy = useSciPy, 

160 ) 

161 case _: 

162 # Crash ... 

163 raise ValueError(f"\"method\" is an unexpected value ({repr(method)})") from None