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
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
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
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.
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
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)
68 Notes
69 -----
70 Copyright 2017 Thomas Guymer [1]_
72 References
73 ----------
74 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
75 """
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
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
89 # **************************************************************************
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
99 # **************************************************************************
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