geofast 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geofast-0.2.0/LICENSE +21 -0
- geofast-0.2.0/PKG-INFO +324 -0
- geofast-0.2.0/README.md +276 -0
- geofast-0.2.0/geofast/__init__.py +145 -0
- geofast-0.2.0/geofast/cache.py +651 -0
- geofast-0.2.0/geofast/cli.py +153 -0
- geofast-0.2.0/geofast/core.py +167 -0
- geofast-0.2.0/geofast/cuda_kernels.py +422 -0
- geofast-0.2.0/geofast/executor.py +326 -0
- geofast-0.2.0/geofast/formats.py +958 -0
- geofast-0.2.0/geofast/geo_ops.py +703 -0
- geofast-0.2.0/geofast/parallel.py +391 -0
- geofast-0.2.0/geofast/primitives.py +471 -0
- geofast-0.2.0/geofast/spatial_index.py +416 -0
- geofast-0.2.0/geofast/utils.py +229 -0
- geofast-0.2.0/geofast.egg-info/PKG-INFO +324 -0
- geofast-0.2.0/geofast.egg-info/SOURCES.txt +21 -0
- geofast-0.2.0/geofast.egg-info/dependency_links.txt +1 -0
- geofast-0.2.0/geofast.egg-info/entry_points.txt +2 -0
- geofast-0.2.0/geofast.egg-info/requires.txt +26 -0
- geofast-0.2.0/geofast.egg-info/top_level.txt +1 -0
- geofast-0.2.0/pyproject.toml +103 -0
- geofast-0.2.0/setup.cfg +4 -0
geofast-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Headings Helicopters
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
geofast-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: geofast
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: High-performance geospatial processing with GPU acceleration, Numba JIT, and format conversion
|
|
5
|
+
Author-email: Norm <norm@headingshelicopters.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/headingshelicopters/geofast
|
|
8
|
+
Project-URL: Documentation, https://github.com/headingshelicopters/geofast#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/headingshelicopters/geofast
|
|
10
|
+
Project-URL: Issues, https://github.com/headingshelicopters/geofast/issues
|
|
11
|
+
Keywords: geospatial,gis,gpu,cuda,numba,parallel,shapely,geopandas,kml,geojson,gpx,mpz,format-conversion
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: numpy>=1.21
|
|
28
|
+
Provides-Extra: geo
|
|
29
|
+
Requires-Dist: geopandas>=0.12; extra == "geo"
|
|
30
|
+
Requires-Dist: shapely>=2.0; extra == "geo"
|
|
31
|
+
Requires-Dist: fiona>=1.8; extra == "geo"
|
|
32
|
+
Requires-Dist: pyproj>=3.0; extra == "geo"
|
|
33
|
+
Provides-Extra: gpu
|
|
34
|
+
Requires-Dist: cupy-cuda12x; extra == "gpu"
|
|
35
|
+
Provides-Extra: numba
|
|
36
|
+
Requires-Dist: numba>=0.56; extra == "numba"
|
|
37
|
+
Provides-Extra: full
|
|
38
|
+
Requires-Dist: numba>=0.56; extra == "full"
|
|
39
|
+
Requires-Dist: shapely>=2.0; extra == "full"
|
|
40
|
+
Provides-Extra: all
|
|
41
|
+
Requires-Dist: geofast[geo,numba]; extra == "all"
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
45
|
+
Requires-Dist: black; extra == "dev"
|
|
46
|
+
Requires-Dist: ruff; extra == "dev"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# GeoFast
|
|
50
|
+
|
|
51
|
+
High-performance geospatial processing framework with GPU acceleration, Numba JIT compilation, file format conversion, and intelligent caching.
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **Multi-backend execution**: CPU, CPU Parallel, GPU (CUDA), Numba JIT, Hybrid
|
|
56
|
+
- **Automatic backend selection**: Based on data size and available hardware
|
|
57
|
+
- **File format conversion**: GeoJSON, KML, GPX, CSV, MPZ/MapPlus
|
|
58
|
+
- **Numba JIT primitives**: Point-in-polygon, haversine, Douglas-Peucker, hex grids
|
|
59
|
+
- **Spatial indexing**: R-tree, hex grid index, point index
|
|
60
|
+
- **GPU kernels**: CUDA acceleration via Numba CUDA and CuPy
|
|
61
|
+
- **Intelligent caching**: Memory and disk caching for expensive computations
|
|
62
|
+
- **Command-line interface**: Convert files, view system info, manage cache
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Basic installation (CPU only)
|
|
68
|
+
pip install geofast
|
|
69
|
+
|
|
70
|
+
# With Numba JIT support (recommended)
|
|
71
|
+
pip install geofast[full]
|
|
72
|
+
|
|
73
|
+
# With GPU support (requires NVIDIA GPU + CUDA)
|
|
74
|
+
pip install geofast[gpu]
|
|
75
|
+
|
|
76
|
+
# Everything
|
|
77
|
+
pip install geofast[all]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### From source
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/headingshelicopters/geofast.git
|
|
84
|
+
cd geofast
|
|
85
|
+
pip install -e ".[full]"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Quick Start
|
|
89
|
+
|
|
90
|
+
### File Format Conversion
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from geofast import convert, read_kml, MPZReader
|
|
94
|
+
|
|
95
|
+
# Convert between formats (auto-detects from extension)
|
|
96
|
+
convert('tracks.kml', 'tracks.geojson')
|
|
97
|
+
convert('field.geojson', 'field.kml')
|
|
98
|
+
convert('points.csv', 'points.gpx')
|
|
99
|
+
|
|
100
|
+
# Read KML directly
|
|
101
|
+
data = read_kml('file.kml') # Returns GeoJSON-like dict
|
|
102
|
+
|
|
103
|
+
# Read MapPlus/MPZ files
|
|
104
|
+
with MPZReader('data.mpz') as reader:
|
|
105
|
+
tracks = reader.get_tracks()
|
|
106
|
+
polygons = reader.get_polygons()
|
|
107
|
+
geojson = reader.to_geojson()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### High-Performance Primitives
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from geofast import (
|
|
114
|
+
haversine_scalar, haversine_batch,
|
|
115
|
+
point_in_polygon, points_in_polygon_batch,
|
|
116
|
+
douglas_peucker,
|
|
117
|
+
lat_lon_to_hex, polygon_to_hex_cells,
|
|
118
|
+
)
|
|
119
|
+
import numpy as np
|
|
120
|
+
|
|
121
|
+
# Fast haversine distance (Numba JIT)
|
|
122
|
+
dist = haversine_scalar(lat1, lon1, lat2, lon2, radius=3959) # miles
|
|
123
|
+
|
|
124
|
+
# Batch operations (parallel)
|
|
125
|
+
lats1 = np.array([40.0, 41.0, 42.0])
|
|
126
|
+
lons1 = np.array([-74.0, -73.0, -72.0])
|
|
127
|
+
distances = haversine_batch(lats1, lons1, lats2, lons2)
|
|
128
|
+
|
|
129
|
+
# Point-in-polygon (Numba JIT)
|
|
130
|
+
poly_x = np.array([0, 1, 1, 0, 0], dtype=np.float64)
|
|
131
|
+
poly_y = np.array([0, 0, 1, 1, 0], dtype=np.float64)
|
|
132
|
+
inside = point_in_polygon(0.5, 0.5, poly_x, poly_y) # True
|
|
133
|
+
|
|
134
|
+
# Line simplification
|
|
135
|
+
coords = np.array([[0, 0], [1, 0.1], [2, 0], [3, 0.1], [4, 0]])
|
|
136
|
+
simplified = douglas_peucker(coords, epsilon=0.2)
|
|
137
|
+
|
|
138
|
+
# Hex grid operations
|
|
139
|
+
q, r = lat_lon_to_hex(40.7128, -74.0060, hex_size_lat=0.001, hex_size_lon=0.001)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Spatial Indexing
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from geofast import SpatialIndex, HexGridIndex
|
|
146
|
+
|
|
147
|
+
# R-tree index for fast polygon queries
|
|
148
|
+
index = SpatialIndex()
|
|
149
|
+
index.add_polygon('field1', polygon_coords)
|
|
150
|
+
index.add_polygon('field2', polygon_coords)
|
|
151
|
+
index.build()
|
|
152
|
+
|
|
153
|
+
# O(log n) point query
|
|
154
|
+
hits = index.query_point(lon, lat)
|
|
155
|
+
|
|
156
|
+
# Hex grid index for O(1) lookups
|
|
157
|
+
hex_index = HexGridIndex(hex_size_lat=0.001, hex_size_lon=0.001)
|
|
158
|
+
hex_index.add_polygons(polygons_dict)
|
|
159
|
+
hex_index.build()
|
|
160
|
+
field_ids = hex_index.query_point(lat, lon)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### GPU Acceleration
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from geofast import haversine_auto, hex_keys_auto, gpu_available
|
|
167
|
+
|
|
168
|
+
# Automatically uses GPU for large arrays, CPU for small
|
|
169
|
+
distances = haversine_auto(lats1, lons1, lats2, lons2)
|
|
170
|
+
q_arr, r_arr = hex_keys_auto(lats, lons, hex_size_lat, hex_size_lon)
|
|
171
|
+
|
|
172
|
+
# Check GPU availability
|
|
173
|
+
if gpu_available():
|
|
174
|
+
print("GPU acceleration available!")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Caching
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from geofast import (
|
|
181
|
+
get_polygon_cell_cache,
|
|
182
|
+
cached,
|
|
183
|
+
set_cache_config,
|
|
184
|
+
print_cache_stats,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Enable/configure caching
|
|
188
|
+
set_cache_config(enabled=True, cache_dir='~/.geofast/cache')
|
|
189
|
+
|
|
190
|
+
# Cache expensive computations
|
|
191
|
+
cache = get_polygon_cell_cache()
|
|
192
|
+
cells = cache.get_or_compute(polygon, hex_lat, hex_lon, compute_func)
|
|
193
|
+
|
|
194
|
+
# Decorator for automatic caching
|
|
195
|
+
@cached(cache_type='disk', ttl=3600)
|
|
196
|
+
def expensive_computation(data):
|
|
197
|
+
...
|
|
198
|
+
|
|
199
|
+
# View cache statistics
|
|
200
|
+
print_cache_stats()
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Decorator-based Backend Selection
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from geofast import process, Backend
|
|
207
|
+
|
|
208
|
+
# Auto-select best backend based on data size
|
|
209
|
+
@process(backend=Backend.AUTO, item_count_arg="geometries")
|
|
210
|
+
def simplify_fields(geometries, tolerance=0.001):
|
|
211
|
+
from shapely import simplify
|
|
212
|
+
return list(simplify(geometries, tolerance))
|
|
213
|
+
|
|
214
|
+
# Force GPU with CPU fallback
|
|
215
|
+
@process(backend=Backend.GPU, fallback=Backend.CPU)
|
|
216
|
+
def compute_distances(lats1, lons1, lats2, lons2):
|
|
217
|
+
...
|
|
218
|
+
|
|
219
|
+
# Parallel file processing
|
|
220
|
+
@process(backend=Backend.CPU_PARALLEL, batch=True)
|
|
221
|
+
def convert_files(filepaths):
|
|
222
|
+
...
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Command Line Interface
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# Convert files
|
|
229
|
+
geofast convert input.kml output.geojson
|
|
230
|
+
geofast convert tracks.mpz tracks.geojson
|
|
231
|
+
|
|
232
|
+
# Show system info
|
|
233
|
+
geofast info
|
|
234
|
+
geofast info --cache
|
|
235
|
+
|
|
236
|
+
# Manage cache
|
|
237
|
+
geofast cache --stats
|
|
238
|
+
geofast cache --clear
|
|
239
|
+
|
|
240
|
+
# List supported formats
|
|
241
|
+
geofast formats
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Supported File Formats
|
|
245
|
+
|
|
246
|
+
| Format | Read | Write | Notes |
|
|
247
|
+
|--------|------|-------|-------|
|
|
248
|
+
| GeoJSON | ✅ | ✅ | `.geojson`, `.json` |
|
|
249
|
+
| KML | ✅ | ✅ | `.kml` |
|
|
250
|
+
| GPX | ✅ | ✅ | `.gpx` (tracks, waypoints, routes) |
|
|
251
|
+
| CSV | ✅ | ✅ | Requires lat/lon columns |
|
|
252
|
+
| MPZ/MapPlus | ✅ | ❌ | `.mpz`, `.sdb` (SQLite-based) |
|
|
253
|
+
| Shapefile | ✅ | ✅ | Requires `fiona` |
|
|
254
|
+
|
|
255
|
+
## Backends
|
|
256
|
+
|
|
257
|
+
| Backend | Best For | Requirements |
|
|
258
|
+
|---------|----------|--------------|
|
|
259
|
+
| `CPU` | Small datasets, simple operations | numpy |
|
|
260
|
+
| `CPU_PARALLEL` | File I/O, embarrassingly parallel tasks | numpy |
|
|
261
|
+
| `GPU` | Large arrays (10k+), matrix operations | cupy |
|
|
262
|
+
| `NUMBA` | Tight loops, custom algorithms | numba |
|
|
263
|
+
| `NUMBA_CUDA` | Custom GPU kernels | numba + CUDA |
|
|
264
|
+
| `HYBRID` | Very large datasets, max throughput | all |
|
|
265
|
+
| `AUTO` | Let GeoFast decide | any |
|
|
266
|
+
|
|
267
|
+
## Configuration
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
from geofast import set_config
|
|
271
|
+
|
|
272
|
+
set_config(
|
|
273
|
+
max_workers=8, # CPU cores to use
|
|
274
|
+
chunk_size=1000, # Items per parallel chunk
|
|
275
|
+
gpu_batch_size=10000, # Items per GPU batch
|
|
276
|
+
auto_gpu_min_items=1000, # Threshold for AUTO->GPU
|
|
277
|
+
verbose=True # Log backend selection
|
|
278
|
+
)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Performance
|
|
282
|
+
|
|
283
|
+
Benchmarks on a system with 16 CPU cores and NVIDIA RTX 4050:
|
|
284
|
+
|
|
285
|
+
| Operation | Original | With GeoFast | Speedup |
|
|
286
|
+
|-----------|----------|--------------|---------|
|
|
287
|
+
| Polygon cell computation (7352 polygons) | ~20s | 1.3s (cached) | **15x** |
|
|
288
|
+
| Track processing (262 tracks) | ~60s | 10.7s | **5.6x** |
|
|
289
|
+
| Point-in-polygon (batch) | ~30s | 4.7s | **6.4x** |
|
|
290
|
+
| Full analysis pipeline | ~300s | 41s | **7.3x** |
|
|
291
|
+
|
|
292
|
+
## Project Structure
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
geofast/
|
|
296
|
+
├── __init__.py # Package exports
|
|
297
|
+
├── core.py # Backend enum, @process decorator
|
|
298
|
+
├── executor.py # Backend dispatch logic
|
|
299
|
+
├── primitives.py # Numba JIT functions
|
|
300
|
+
├── spatial_index.py # R-tree, hex grid indexing
|
|
301
|
+
├── cuda_kernels.py # GPU kernels (CUDA/CuPy)
|
|
302
|
+
├── parallel.py # Shared memory, parallel utilities
|
|
303
|
+
├── geo_ops.py # High-level geo operations
|
|
304
|
+
├── formats.py # File format converters
|
|
305
|
+
├── cache.py # Caching layer
|
|
306
|
+
├── cli.py # Command-line interface
|
|
307
|
+
└── utils.py # Detection, helpers
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Requirements
|
|
311
|
+
|
|
312
|
+
- Python 3.9+
|
|
313
|
+
- numpy
|
|
314
|
+
|
|
315
|
+
### Optional
|
|
316
|
+
|
|
317
|
+
- numba (for JIT compilation)
|
|
318
|
+
- shapely 2.0+ (for spatial operations)
|
|
319
|
+
- cupy (for GPU acceleration)
|
|
320
|
+
- geopandas, fiona (for shapefile support)
|
|
321
|
+
|
|
322
|
+
## License
|
|
323
|
+
|
|
324
|
+
MIT License - see LICENSE file for details.
|
geofast-0.2.0/README.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# GeoFast
|
|
2
|
+
|
|
3
|
+
High-performance geospatial processing framework with GPU acceleration, Numba JIT compilation, file format conversion, and intelligent caching.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-backend execution**: CPU, CPU Parallel, GPU (CUDA), Numba JIT, Hybrid
|
|
8
|
+
- **Automatic backend selection**: Based on data size and available hardware
|
|
9
|
+
- **File format conversion**: GeoJSON, KML, GPX, CSV, MPZ/MapPlus
|
|
10
|
+
- **Numba JIT primitives**: Point-in-polygon, haversine, Douglas-Peucker, hex grids
|
|
11
|
+
- **Spatial indexing**: R-tree, hex grid index, point index
|
|
12
|
+
- **GPU kernels**: CUDA acceleration via Numba CUDA and CuPy
|
|
13
|
+
- **Intelligent caching**: Memory and disk caching for expensive computations
|
|
14
|
+
- **Command-line interface**: Convert files, view system info, manage cache
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Basic installation (CPU only)
|
|
20
|
+
pip install geofast
|
|
21
|
+
|
|
22
|
+
# With Numba JIT support (recommended)
|
|
23
|
+
pip install geofast[full]
|
|
24
|
+
|
|
25
|
+
# With GPU support (requires NVIDIA GPU + CUDA)
|
|
26
|
+
pip install geofast[gpu]
|
|
27
|
+
|
|
28
|
+
# Everything
|
|
29
|
+
pip install geofast[all]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### From source
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/headingshelicopters/geofast.git
|
|
36
|
+
cd geofast
|
|
37
|
+
pip install -e ".[full]"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### File Format Conversion
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from geofast import convert, read_kml, MPZReader
|
|
46
|
+
|
|
47
|
+
# Convert between formats (auto-detects from extension)
|
|
48
|
+
convert('tracks.kml', 'tracks.geojson')
|
|
49
|
+
convert('field.geojson', 'field.kml')
|
|
50
|
+
convert('points.csv', 'points.gpx')
|
|
51
|
+
|
|
52
|
+
# Read KML directly
|
|
53
|
+
data = read_kml('file.kml') # Returns GeoJSON-like dict
|
|
54
|
+
|
|
55
|
+
# Read MapPlus/MPZ files
|
|
56
|
+
with MPZReader('data.mpz') as reader:
|
|
57
|
+
tracks = reader.get_tracks()
|
|
58
|
+
polygons = reader.get_polygons()
|
|
59
|
+
geojson = reader.to_geojson()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### High-Performance Primitives
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from geofast import (
|
|
66
|
+
haversine_scalar, haversine_batch,
|
|
67
|
+
point_in_polygon, points_in_polygon_batch,
|
|
68
|
+
douglas_peucker,
|
|
69
|
+
lat_lon_to_hex, polygon_to_hex_cells,
|
|
70
|
+
)
|
|
71
|
+
import numpy as np
|
|
72
|
+
|
|
73
|
+
# Fast haversine distance (Numba JIT)
|
|
74
|
+
dist = haversine_scalar(lat1, lon1, lat2, lon2, radius=3959) # miles
|
|
75
|
+
|
|
76
|
+
# Batch operations (parallel)
|
|
77
|
+
lats1 = np.array([40.0, 41.0, 42.0])
|
|
78
|
+
lons1 = np.array([-74.0, -73.0, -72.0])
|
|
79
|
+
distances = haversine_batch(lats1, lons1, lats2, lons2)
|
|
80
|
+
|
|
81
|
+
# Point-in-polygon (Numba JIT)
|
|
82
|
+
poly_x = np.array([0, 1, 1, 0, 0], dtype=np.float64)
|
|
83
|
+
poly_y = np.array([0, 0, 1, 1, 0], dtype=np.float64)
|
|
84
|
+
inside = point_in_polygon(0.5, 0.5, poly_x, poly_y) # True
|
|
85
|
+
|
|
86
|
+
# Line simplification
|
|
87
|
+
coords = np.array([[0, 0], [1, 0.1], [2, 0], [3, 0.1], [4, 0]])
|
|
88
|
+
simplified = douglas_peucker(coords, epsilon=0.2)
|
|
89
|
+
|
|
90
|
+
# Hex grid operations
|
|
91
|
+
q, r = lat_lon_to_hex(40.7128, -74.0060, hex_size_lat=0.001, hex_size_lon=0.001)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Spatial Indexing
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from geofast import SpatialIndex, HexGridIndex
|
|
98
|
+
|
|
99
|
+
# R-tree index for fast polygon queries
|
|
100
|
+
index = SpatialIndex()
|
|
101
|
+
index.add_polygon('field1', polygon_coords)
|
|
102
|
+
index.add_polygon('field2', polygon_coords)
|
|
103
|
+
index.build()
|
|
104
|
+
|
|
105
|
+
# O(log n) point query
|
|
106
|
+
hits = index.query_point(lon, lat)
|
|
107
|
+
|
|
108
|
+
# Hex grid index for O(1) lookups
|
|
109
|
+
hex_index = HexGridIndex(hex_size_lat=0.001, hex_size_lon=0.001)
|
|
110
|
+
hex_index.add_polygons(polygons_dict)
|
|
111
|
+
hex_index.build()
|
|
112
|
+
field_ids = hex_index.query_point(lat, lon)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### GPU Acceleration
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from geofast import haversine_auto, hex_keys_auto, gpu_available
|
|
119
|
+
|
|
120
|
+
# Automatically uses GPU for large arrays, CPU for small
|
|
121
|
+
distances = haversine_auto(lats1, lons1, lats2, lons2)
|
|
122
|
+
q_arr, r_arr = hex_keys_auto(lats, lons, hex_size_lat, hex_size_lon)
|
|
123
|
+
|
|
124
|
+
# Check GPU availability
|
|
125
|
+
if gpu_available():
|
|
126
|
+
print("GPU acceleration available!")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Caching
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from geofast import (
|
|
133
|
+
get_polygon_cell_cache,
|
|
134
|
+
cached,
|
|
135
|
+
set_cache_config,
|
|
136
|
+
print_cache_stats,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Enable/configure caching
|
|
140
|
+
set_cache_config(enabled=True, cache_dir='~/.geofast/cache')
|
|
141
|
+
|
|
142
|
+
# Cache expensive computations
|
|
143
|
+
cache = get_polygon_cell_cache()
|
|
144
|
+
cells = cache.get_or_compute(polygon, hex_lat, hex_lon, compute_func)
|
|
145
|
+
|
|
146
|
+
# Decorator for automatic caching
|
|
147
|
+
@cached(cache_type='disk', ttl=3600)
|
|
148
|
+
def expensive_computation(data):
|
|
149
|
+
...
|
|
150
|
+
|
|
151
|
+
# View cache statistics
|
|
152
|
+
print_cache_stats()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Decorator-based Backend Selection
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from geofast import process, Backend
|
|
159
|
+
|
|
160
|
+
# Auto-select best backend based on data size
|
|
161
|
+
@process(backend=Backend.AUTO, item_count_arg="geometries")
|
|
162
|
+
def simplify_fields(geometries, tolerance=0.001):
|
|
163
|
+
from shapely import simplify
|
|
164
|
+
return list(simplify(geometries, tolerance))
|
|
165
|
+
|
|
166
|
+
# Force GPU with CPU fallback
|
|
167
|
+
@process(backend=Backend.GPU, fallback=Backend.CPU)
|
|
168
|
+
def compute_distances(lats1, lons1, lats2, lons2):
|
|
169
|
+
...
|
|
170
|
+
|
|
171
|
+
# Parallel file processing
|
|
172
|
+
@process(backend=Backend.CPU_PARALLEL, batch=True)
|
|
173
|
+
def convert_files(filepaths):
|
|
174
|
+
...
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Command Line Interface
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Convert files
|
|
181
|
+
geofast convert input.kml output.geojson
|
|
182
|
+
geofast convert tracks.mpz tracks.geojson
|
|
183
|
+
|
|
184
|
+
# Show system info
|
|
185
|
+
geofast info
|
|
186
|
+
geofast info --cache
|
|
187
|
+
|
|
188
|
+
# Manage cache
|
|
189
|
+
geofast cache --stats
|
|
190
|
+
geofast cache --clear
|
|
191
|
+
|
|
192
|
+
# List supported formats
|
|
193
|
+
geofast formats
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Supported File Formats
|
|
197
|
+
|
|
198
|
+
| Format | Read | Write | Notes |
|
|
199
|
+
|--------|------|-------|-------|
|
|
200
|
+
| GeoJSON | ✅ | ✅ | `.geojson`, `.json` |
|
|
201
|
+
| KML | ✅ | ✅ | `.kml` |
|
|
202
|
+
| GPX | ✅ | ✅ | `.gpx` (tracks, waypoints, routes) |
|
|
203
|
+
| CSV | ✅ | ✅ | Requires lat/lon columns |
|
|
204
|
+
| MPZ/MapPlus | ✅ | ❌ | `.mpz`, `.sdb` (SQLite-based) |
|
|
205
|
+
| Shapefile | ✅ | ✅ | Requires `fiona` |
|
|
206
|
+
|
|
207
|
+
## Backends
|
|
208
|
+
|
|
209
|
+
| Backend | Best For | Requirements |
|
|
210
|
+
|---------|----------|--------------|
|
|
211
|
+
| `CPU` | Small datasets, simple operations | numpy |
|
|
212
|
+
| `CPU_PARALLEL` | File I/O, embarrassingly parallel tasks | numpy |
|
|
213
|
+
| `GPU` | Large arrays (10k+), matrix operations | cupy |
|
|
214
|
+
| `NUMBA` | Tight loops, custom algorithms | numba |
|
|
215
|
+
| `NUMBA_CUDA` | Custom GPU kernels | numba + CUDA |
|
|
216
|
+
| `HYBRID` | Very large datasets, max throughput | all |
|
|
217
|
+
| `AUTO` | Let GeoFast decide | any |
|
|
218
|
+
|
|
219
|
+
## Configuration
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from geofast import set_config
|
|
223
|
+
|
|
224
|
+
set_config(
|
|
225
|
+
max_workers=8, # CPU cores to use
|
|
226
|
+
chunk_size=1000, # Items per parallel chunk
|
|
227
|
+
gpu_batch_size=10000, # Items per GPU batch
|
|
228
|
+
auto_gpu_min_items=1000, # Threshold for AUTO->GPU
|
|
229
|
+
verbose=True # Log backend selection
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Performance
|
|
234
|
+
|
|
235
|
+
Benchmarks on a system with 16 CPU cores and NVIDIA RTX 4050:
|
|
236
|
+
|
|
237
|
+
| Operation | Original | With GeoFast | Speedup |
|
|
238
|
+
|-----------|----------|--------------|---------|
|
|
239
|
+
| Polygon cell computation (7352 polygons) | ~20s | 1.3s (cached) | **15x** |
|
|
240
|
+
| Track processing (262 tracks) | ~60s | 10.7s | **5.6x** |
|
|
241
|
+
| Point-in-polygon (batch) | ~30s | 4.7s | **6.4x** |
|
|
242
|
+
| Full analysis pipeline | ~300s | 41s | **7.3x** |
|
|
243
|
+
|
|
244
|
+
## Project Structure
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
geofast/
|
|
248
|
+
├── __init__.py # Package exports
|
|
249
|
+
├── core.py # Backend enum, @process decorator
|
|
250
|
+
├── executor.py # Backend dispatch logic
|
|
251
|
+
├── primitives.py # Numba JIT functions
|
|
252
|
+
├── spatial_index.py # R-tree, hex grid indexing
|
|
253
|
+
├── cuda_kernels.py # GPU kernels (CUDA/CuPy)
|
|
254
|
+
├── parallel.py # Shared memory, parallel utilities
|
|
255
|
+
├── geo_ops.py # High-level geo operations
|
|
256
|
+
├── formats.py # File format converters
|
|
257
|
+
├── cache.py # Caching layer
|
|
258
|
+
├── cli.py # Command-line interface
|
|
259
|
+
└── utils.py # Detection, helpers
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Requirements
|
|
263
|
+
|
|
264
|
+
- Python 3.9+
|
|
265
|
+
- numpy
|
|
266
|
+
|
|
267
|
+
### Optional
|
|
268
|
+
|
|
269
|
+
- numba (for JIT compilation)
|
|
270
|
+
- shapely 2.0+ (for spatial operations)
|
|
271
|
+
- cupy (for GPU acceleration)
|
|
272
|
+
- geopandas, fiona (for shapefile support)
|
|
273
|
+
|
|
274
|
+
## License
|
|
275
|
+
|
|
276
|
+
MIT License - see LICENSE file for details.
|