/vector/gpxparser.py

https://bitbucket.org/njwilson23/geo_tools · Python · 120 lines · 83 code · 14 blank · 23 comment · 22 complexity · 444d232489ca2fe99e02bd857a9a7464 MD5 · raw file

  1. """
  2. GPX Parser
  3. Based on code by Rui Carmo, available at
  4. http://the.taoofmac.com/space/blog/2005/10/11/2359
  5. """
  6. import sys
  7. import numpy as np
  8. from xml.dom import minidom, Node
  9. try:
  10. from pyproj import Proj
  11. except ImportError:
  12. # No projection capabilities
  13. pass
  14. class GPXParser:
  15. """ Used for reading out track data from the GPX files that can be
  16. exported by many hand-held GPS units. """
  17. def __init__(self, filename):
  18. self.filename = filename
  19. self.tracks = {}
  20. self.has_projector = False
  21. try:
  22. doc = minidom.parse(filename)
  23. doc.normalize()
  24. except:
  25. sys.stderr.write('Error occurred parsing {0}\n'.format(filename))
  26. gpx = doc.documentElement
  27. for node in gpx.getElementsByTagName('trk'):
  28. self.parsetrack(node)
  29. def project(self, **kwargs):
  30. """ Wrapper for libproj.4 Proj class. """
  31. try:
  32. self.Projector = Proj(**kwargs)
  33. self.has_projector = True
  34. except NameError:
  35. raise ImportError("no pyproj found")
  36. return
  37. self.tracks_proj = {}
  38. for name in self.list():
  39. for t in self.tracks[name].keys():
  40. lon = self.track[name][t]['lon']
  41. lat = self.track[name][t]['lat']
  42. ele = self.track[name][t]['ele']
  43. x, y = self.Projector(lon, lat)
  44. self.tracks_proj[name][t] = {'x':x, 'y':y, 'ele':ele}
  45. def parsetrack(self, trk):
  46. name = trk.getElementsByTagName('name')[0].firstChild.data
  47. if not name in self.tracks:
  48. self.tracks[name] = {}
  49. for trkseg in trk.getElementsByTagName('trkseg'):
  50. for trkpt in trkseg.getElementsByTagName('trkpt'):
  51. lat = float(trkpt.getAttribute('lat'))
  52. lon = float(trkpt.getAttribute('lon'))
  53. ele = float(trkpt.getElementsByTagName('ele')[0].firstChild.data)
  54. time = trkpt.getElementsByTagName('time')[0].firstChild.data
  55. self.tracks[name][time]={'lat':lat,'lon':lon,'ele':ele}
  56. def getnames(self):
  57. """ List all track names within GPXParser. """
  58. return [str(i) for i in self.tracks.keys()]
  59. def gettrack(self, name):
  60. """ Return a list of triples containing track coordinates
  61. sorted by time for track with name. """
  62. times = self.tracks[name].keys()
  63. times.sort()
  64. points = [self.tracks[name][t] for t in times]
  65. return [(point['lon'],point['lat'],point['ele']) for point in points]
  66. def getxyz(self, name):
  67. """ Return a list of triples containing track projected
  68. coordinates, sorted by time, for track with name. """
  69. times = self.tracks_proj[name].keys()
  70. times.sort()
  71. points = [self.tracks_proj[name][t] for t in times]
  72. return [(point['lon'],point['lat'],point['ele']) for point in points]
  73. def gettimes(self, name):
  74. """ Return a list of times for the track with name. """
  75. times = self.tracks[name].keys()
  76. times.sort()
  77. return times
  78. def getpolyline(self):
  79. """ Return a guppy.Polyline containing all tracks. """
  80. pass
  81. def filter_by_displacement(self, name, threshold, proj_kwargs=None):
  82. """ Return a list of lists, where each sublist contains consecutive GPS
  83. points between which the displacement is less than threshold. """
  84. # Make sure coordinates are projected
  85. if not self.has_projector:
  86. if proj_kwargs is not None:
  87. self.project(**proj_kwargs)
  88. else:
  89. raise ProjectionError("Need to define proj_kwargs dictionary")
  90. return
  91. xyz = self.gettrack_proj(name)
  92. X = np.array([i[0] for i in xyz])
  93. Y = np.array([i[1] for i in xyz])
  94. Z = np.array([i[2] for i in xyz])
  95. DIST = np.sqrt((X[:-1]-X[1:])**2 + (Y[:-1]-Y[1:])**2)
  96. #[INCOMPLETE - NEED TO FILTER BASED ON DIST]
  97. def split_natural_breaks(self, name):
  98. """ Split a track into linear natural segments, with nodes where
  99. direction changes. """
  100. pass
  101. class ProjectionError(Exception):
  102. def __init__(self, value):
  103. self.value = value
  104. def __str__(self):
  105. return self.value