/
utils.py
107 lines (76 loc) · 3.25 KB
/
utils.py
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
import os
import re
from bisect import bisect_left
from datetime import datetime, timedelta
from functools import wraps
import osgeo
import pyproj
from django.utils.timezone import utc
from pyproj import Transformer
from shapely.ops import transform
EPSG_RE = re.compile(r'\+init=epsg:([0-9]+)')
PYPROJ_EPSG_FILE_RE = re.compile(r'<([0-9]+)([^<]+)<')
def auto_memoize(func):
"""
Based on django.util.functional.memoize. Automatically memoizes instance methods for the lifespan of an object.
Only works with methods taking non-keword arguments. Note that the args to the function must be usable as
dictionary keys. Also, the first argument MUST be self. This decorator will not work for functions or class
methods, only object methods.
"""
@wraps(func)
def wrapper(*args):
inst = args[0]
inst._memoized_values = getattr(inst, '_memoized_values', {})
key = (func, args[1:])
if key not in inst._memoized_values:
inst._memoized_values[key] = func(*args)
return inst._memoized_values[key]
return wrapper
def best_fit(li, value):
"""For a sorted list li, returns the closest item to value"""
index = min(bisect_left(li, value), len(li) - 1)
if index in (0, len(li)):
return index
if li[index] - value < value - li[index-1]:
return index
else:
return index-1
def proj4_to_epsg(projection):
"""Attempts to convert a PROJ4 projection object to an EPSG code and returns None if conversion fails"""
def make_definition(value):
return {x.strip().lower() for x in value.split('+') if x}
# Use the EPSG in the definition if available
match = EPSG_RE.search(projection.srs)
if match:
return int(match.group(1))
# Otherwise, try to look up the EPSG from the pyproj data file
pyproj_data_dir = os.path.join(os.path.dirname(pyproj.__file__), 'data')
pyproj_epsg_file = os.path.join(pyproj_data_dir, 'epsg')
if os.path.exists(pyproj_epsg_file):
definition = make_definition(projection.srs)
f = open(pyproj_epsg_file, 'r')
for line in f.readlines():
match = PYPROJ_EPSG_FILE_RE.search(line)
if match:
file_definition = make_definition(match.group(2))
if definition == file_definition:
return int(match.group(1))
return None
def wkt_to_proj4(wkt):
"""Converts a well-known text string to a pyproj.Proj object"""
srs = osgeo.osr.SpatialReference()
srs.ImportFromWkt(wkt)
return pyproj.Proj(str(srs.ExportToProj4()))
def proj4_to_wkt(projection):
"""Converts a pyproj.Proj object to a well-known text string"""
srs = osgeo.osr.SpatialReference()
srs.ImportFromProj4(projection.srs)
return srs.ExportToWkt()
def project_geometry(geometry, source, target):
"""Projects a shapely geometry object from the source to the target projection."""
transformer = Transformer.from_proj(source, target)
return transform(transformer.transform, geometry)
def timestamp_to_date(timestamp):
return datetime.utcfromtimestamp(0).replace(tzinfo=utc) + timedelta(seconds=timestamp)
def date_to_timestamp(date_obj):
return int((date_obj - datetime.utcfromtimestamp(0).replace(tzinfo=utc)).total_seconds())