GithubHelp home page GithubHelp logo

tkrajina / gpxpy Goto Github PK

View Code? Open in Web Editor NEW
974.0 40.0 221.0 1.38 MB

gpx-py is a python GPX parser. GPX (GPS eXchange Format) is an XML based file format for GPS tracks.

License: Apache License 2.0

Python 99.68% Makefile 0.32%
gpx gpx-library python python3 gps

gpxpy's Introduction

Build Status Coverage Status

gpxpy -- GPX file parser

This is a simple Python library for parsing and manipulating GPX files. GPX is an XML based format for GPS tracks.

You can see it in action on my online GPS track editor and organizer.

There is also a Golang port of gpxpy: gpxgo.

See also srtm.py if your track lacks elevation data.

Usage

import gpxpy
import gpxpy.gpx

# Parsing an existing file:
# -------------------------

gpx_file = open('test_files/cerknicko-jezero.gpx', 'r')

gpx = gpxpy.parse(gpx_file)

for track in gpx.tracks:
    for segment in track.segments:
        for point in segment.points:
            print(f'Point at ({point.latitude},{point.longitude}) -> {point.elevation}')

for waypoint in gpx.waypoints:
    print(f'waypoint {waypoint.name} -> ({waypoint.latitude},{waypoint.longitude})')

for route in gpx.routes:
    print('Route:')
    for point in route.points:
        print(f'Point at ({point.latitude},{point.longitude}) -> {point.elevtion}')

# There are many more utility methods and functions:
# You can manipulate/add/remove tracks, segments, points, waypoints and routes and
# get the GPX XML file from the resulting object:

print('GPX:', gpx.to_xml())

# Creating a new file:
# --------------------

gpx = gpxpy.gpx.GPX()

# Create first track in our GPX:
gpx_track = gpxpy.gpx.GPXTrack()
gpx.tracks.append(gpx_track)

# Create first segment in our GPX track:
gpx_segment = gpxpy.gpx.GPXTrackSegment()
gpx_track.segments.append(gpx_segment)

# Create points:
gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(2.1234, 5.1234, elevation=1234))
gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(2.1235, 5.1235, elevation=1235))
gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(2.1236, 5.1236, elevation=1236))

# You can add routes and waypoints, too...

print('Created GPX:', gpx.to_xml())

GPX version

gpx.py can parse and generate GPX 1.0 and 1.1 files. The generated file will always be a valid XML document, but it may not be (strictly speaking) a valid GPX document. For example, if you set gpx.email to "my.email AT mail.com" the generated GPX tag won't confirm to the regex pattern. And the file won't be valid. Most applications will ignore such errors, but... Be aware of this!

Be aware that the gpxpy object model is not 100% equivalent with the underlying GPX XML file schema. That's because the library object model works with both GPX 1.0 and 1.1.

For example, GPX 1.0 specified a speed attribute for every track point, but that was removed in GPX 1.1. If you parse GPX 1.0 and serialize back with gpx.to_xml() everything will work fine. But if you have a GPX 1.1 object, changes in the speed attribute will be lost after gpx.to_xml(). If you want to force using 1.0, you can gpx.to_xml(version="1.0"). Another possibility is to use extensions to save the speed in GPX 1.1.

GPX extensions

gpx.py preserves GPX extensions. They are stored as ElementTree DOM objects. Extensions are part of GPX 1.1, and will be ignored when serializing a GPX object in a GPX 1.0 file.

XML parsing

If lxml is available, then it will be used for XML parsing, otherwise minidom is used. Lxml is 2-3 times faster so, if you can choose -- use it.

The GPX version is automatically determined when parsing by reading the version attribute in the gpx node. If this attribute is not present then the version is assumed to be 1.0. A specific version can be forced by setting the version parameter in the parse function. Possible values for the 'version' parameter are 1.0, 1.1 and None.

GPX max speed

Gpxpy is a GPX parser and by using it you have access to all the data from the original GPX file. The additional methods to calculate stats have some additional heuristics to remove common GPS errors. For example, to calculate max_speed it removes the top 5% of speeds and points with nonstandard distance (those are usually GPS errors).

"Raw" max speed can be calculated with:

moving_data = gpx.get_moving_data(raw=True)

Pull requests

Branches:

  • master contains the code of the latest release
  • dev branch is where code for the next release should go.

Send your pull request against dev, not master!

Before sending a pull request -- check that all tests are OK. Run all the static typing checks and unit tests with:

$ make mypy-and-tests

Run a single test with:

$ python3 -m unittest test.GPXTests.test_haversine_and_nonhaversine

Gpxpy runs only with python 3.6+. The code must have type hints and must pass all the mypy checks.

GPX tools

Additional command-line tools for GPX files can be downloaded here https://github.com/tkrajina/gpx-cmd-tools or installed with:

pip install gpx-cmd-tools

License

GPX.py is licensed under the Apache License, Version 2.0

gpxpy's People

Contributors

benedikto avatar brewingcode avatar chrisfauerbach avatar ekspla avatar eumiro avatar famanson avatar fbonzon avatar fgouget avatar hugovk avatar hyperknot avatar itoldya avatar jedie avatar luapi avatar marcelrv avatar minchinweb avatar nawagers avatar pajdk avatar pseyfert avatar qulogic avatar rikojacob avatar rob-smallshire avatar simon-d-b avatar sjol avatar sweravn avatar titsworth avatar tkrajina avatar ufranske avatar vmarceau avatar wrohdewald avatar zimeon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gpxpy's Issues

extensions with complex children are not parsed

For example, consider these extensions:

<extensions>
  <gpxtpx:TrackPointExtension>
    <gpxtpx:atemp>29</gpxtpx:atemp>
    <gpxtpx:hr>89</gpxtpx:hr>
    <gpxtpx:cad>83</gpxtpx:cad>
  </gpxtpx:TrackPointExtension>
</extensions>

The problem is that GPXExtensionField assumes that all extensions are simple values, and doesn't parse the children:

https://github.com/tkrajina/gpxpy/blob/master/gpxpy/gpxfield.py#L254

I think the fix is to make the extensions into objects, but this breaks API compatibility as some users are expecting that extensions['myextension'] returns a string value, not an object. One way to deal with this would be to have extensions have a new field called subExtensions that contains the children.

What do you think?

reduce_points compares distances incorrectly

I believe that the reduce_points algorithm incorrectly compares distances. The code you've written is the following:

reduced_points = []
for point in self.points:
    if reduced_points:
        distance = reduced_points[-1].distance_3d(point)
        if distance >= min_distance:
            reduced_points.append(point)
    else:
        # Leave first point:
        reduced_points.append(point)

self.points = reduced_points

The first point is always kept. The distance between the first point and second point is compared to the threshold. If it's over the threshold, the second point is added. If not, the first point is compared to the third point. This is where the mistake is.

Measuring the distance from the first point to the third point doesn't follow the path, unless all the points follow a straight line. The best case is that the distance is longer than the accumulated distance following the path, and in the worst case, it stays under the threshold because the real path loops back close to another section of the track.

I'm not sure if this is the cause of the strange results I'm seeing, but when I take the following track...

thun_1_raw

...and run reduce_points(10) on it, I get the following...

thun_1_raw

...which doesn't look correct. I'd love to know what your thoughts are on this.

You can find the GPX files in my repository here: https://github.com/jonblack/cmpgpx

Elevation calculation

I realized that the calculation of the elevation (uphill, downhill values) differs quite a lot from other tools. In my case I use the movescount.com webpage and GPSMaster and the values are significant higher than the gpxpy values.

The reason for this is that the elevations are smoothed in the calculations. When removing the smoothed part I get similar values as with the other tools. see svendroid@7af065b.

Why is the smoothing done? Is it more accurate than just adding the differences? Could you maybe give me a link to more information about this approach?

Thanks a lot for the nice lib,
Sven

Invalid XML in <trkpt>, empty <link >

Using the function .to_xml() generates XML with empty tags inside the elements (and possibly others). The gpx schema defines the link as XML LinkType, the definition requires the 'refs' attribute:

<xs:complexType mixed="true" name="LinkType">
<xs:complexContent>
<xs:extension base="baseElementType">
<xs:attribute name="refs" type="xs:IDREFS" use="required"/>
<xs:attribute name="role" type="xs:string"/>
<xs:attribute name="title" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>

The output trackpoints look like this:

<trkpt lat="41.3342050742358" lon="-72.67007832415402">
<ele>43.88</ele>
<time>2017-09-04T14:59:23Z</time>
<link ></link></trkpt>

The input trackpoints do not have any link tags from a valid GPX modified in Garmin Basecamp. The file does have extensions, but I don't think that matters, haven't investigated fully yet.

Python 3.6.0

GPX In and Out.zip

Version 1.1 and <link>

Download track from mapmytracks: comes in version 1.1 with no tags.

Because all trackpoints come on one single line, parse and to_xml() with gpxpy

now there are tags without values for every trackpoint and in other places.

Would it be possible to suppress them when they have no value?

output is not reproducible

Python3, gpxpy 1.1.1 (installed today with pip3)

the header xml fields have random order. It would be nice always having the same order:

  • md5sum would tell me that the content did not change
  • saving output in a git archive would not cause unwanted commits

@@ -1,5 +1,5 @@

-
+

Adding attributes

Hi everyone. I'm currently working on gpx files, in a running-app project.
I succeed to read my files, manipulate them as shown in tutorial. But I did not find the way to add attributes as heart pulses in my points. Is there any way to do this?

Thank you.

<ele> tag missing from GPX <trkpt> if elevation == 0

Using gpxpy 1.1.1, GPX 1.1, and python 3.4
I had some issues where tags were missing, turn out if gpx_point.elevation = 0 as floating point type then tag doesn't make it through.

A couple locations where elevation = 0 fails comparisons:
gpx.py line 1280 in def has_elevations(self):
if track_point.elevation:
found += 1

I changed this to:
if track_point.elevation is not None:
found += 1

This way the value of 0 is still allowed.
I also believe the following statement in gpxfield.py incorrectly removes a 0 tag:
def to_xml(self, value, version):
if not value:
return ''

and should be:
def to_xml(self, value, version):
if value is None:
return ''

There must be another location where elevation==0 gets filtered out. I made it this far then was in time crunch so did my own conversion of float to string when assigning elevation and it worked.

Broken file raises GPXException, XMLSyntaxError, TypeError

When I use the parser with a broken GPX file an exception is raised. Here is the code I use. My first assumption was to catch a GPXException.

368  file = open(filepath)
369  try:
370      gpx = gpxpy.parse(file)
371  except gpxpy.gpx.GPXException:
372      print "GPXException for %s." % filepath
373      return 1

However the main reason is somewhere else.

Parsing points in sometrack.gpx
ERROR:root:expected '>', line 3125, column 29
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gpxpy-0.8.7-py2.7.egg/gpxpy/parser.py", line 209, in parse
    self.xml_parser = LXMLParser(self.xml)
  File "/usr/local/lib/python2.7/dist-packages/gpxpy-0.8.7-py2.7.egg/gpxpy/parser.py", line 107, in __init__
    self.dom = mod_etree.XML(self.xml)
  File "lxml.etree.pyx", line 2734, in lxml.etree.XML (src/lxml/lxml.etree.c:54411)
  File "parser.pxi", line 1578, in lxml.etree._parseMemoryDocument (src/lxml/lxml.etree.c:82748)
  File "parser.pxi", line 1457, in lxml.etree._parseDoc (src/lxml/lxml.etree.c:81546)
  File "parser.pxi", line 965, in lxml.etree._BaseParser._parseDoc (src/lxml/lxml.etree.c:78216)
  File "parser.pxi", line 569, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:74472)
  File "parser.pxi", line 650, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:75363)
  File "parser.pxi", line 590, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:74696)
XMLSyntaxError: expected '>', line 3125, column 29

File "somescript.py", line 370, in extractpoints gpx = gpxpy.parse(file)
File "/usr/local/lib/python2.7/dist-packages/gpxpy-0.8.7-py2.7.egg/gpxpy/__init__.py",
     line 28, in parse raise mod_gpx.GPXException('Error parsing {0}: {1}'
                       .format(xml_or_file[0 : 100], parser.get_error()))
TypeError: 'file' object has no attribute '__getitem__'

Please refer to this Stackoverflow post which already suggests a solution to the problem.

Here is a sample file that produces the syntax error.

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<gpx version="1.1" creator="nl.sogeti.android.gpstracker" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/gpx/1/1/gpx.xsd" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gpx10="http://www.topografix.com/GPX/1/0" xmlns:ogt10="http://gpstracker.android.sogeti.nl/GPX/1/0">
<metadata>
<time>2013-03-29T13:52:22Z</time>
</metadata>
<trk>
<name>Track 2013-03-29 14:52</name>
<trkseg>
<trkpt lat="52.48128721585312" lon="13.452307177252663">
<ele>76.0</ele>
<time>2013-03-29T14:09:34Z</time>
<extensions>
<gpx10:speed>5.1076788902282715</gpx10:speed>
<ogt10:accuracy>10.0</ogt10:accuracy>
<gpx10:course>216.4146728515625</gpx10:course></extensions>
</trkpt>
<trkpt lat="52.48077771999975" lon="13.452037039115906">
<ele>78.0</ele>
<time>2013-03-29T14:09:47Z</time>
<extensions>
<gpx10:speed>4.982673168182373</gpx10:speed>
<ogt10:accuracy>10.0</ogt10:accuracy>
<gpx10:course>131.78286743164063</gpx10:course></extensions>
</trkpt>
<trkpt lat="52.480716389960826" lon="13.45214590285023">
<ele>78.0</ele>
<time>2013-03-29T14:09:49Z</time>
<extensions>
<gpx10:speed>4.982266426086426</gpx10:speed>
<ogt10:accuracy>10.0</ogt10:accuracy>
<gpx10:course>129.60655212402344</gpx10:course></extensions>
</trkpt>
<trkpt lat="52.48065528656295" lon="13.452274408986215">
<ele>78.0</ele>
<time>2013-03-29T14:09:51Z</time

.simplify() removes points >max_distance away

The simplify routine removes incorrect points due to 2 errors in the simplify_polyline function in geo.py.

The algorithm accepts a list of 'points' with points[0] and points[-1] being begin and end. The first task is to find the point furthest away from the line between 'begin' and 'end' so we should check all points between begin and end.

for point_no in range(len(points[1:-1])):
    point = points[point_no]

This starts at points[0] (begin) and ends at points[-3] skipping 'end' and one before 'end'. Instead, we should use:
for point_no in points[1:-1]:
or
for point_no in range(1,len(points)-1):

The second error is in the recursive call.
return (simplify_polyline(points[:tmp_max_distance_position + 2], max_distance) + simplify_polyline(points[tmp_max_distance_position + 1:], max_distance)[1:])

We want to call the function from (begin to anchor) and (anchor to end), removing one of the anchors during concatenation. The anchor point is tmp_max_distance_position and because of slicing we have to +1 (and +0), but in the code it was +2 (and +1), so not using the furthest point as an anchor, but whatever point came after that. What we want is:

return (simplify_polyline(points[:tmp_max_distance_position+1], max_distance) + simplify_polyline(points[tmp_max_distance_position:], max_distance)[1:])

Empty tags not cleaned.

After creating a basic file/track/segment/point, empty tags appear in the output. This only affects tags which contain other tags.
It seems to come from the fact that they are harcoded in gpx_1_1_fields. There seems to be a way to avoid it by letting the field contain its children (like the "extensions" field), but I wasn't able to quickly figure out how to make child tags available as attributes on the same object as parent.

Problem with time element formatting

When trying to make waypoints with time elements, things crash when making the xml.

The format I am using for the time element is YYYY-MM-DDTHH:MM:SSZ, but I'm not sure whether the format I am using is the problem, or whether it's a bug. See example code and traceback below:


import gpxpy
import gpxpy.gpx
wptName="aWayPoint"
wptLat=17.9875
wptLon=14.8564
wptEle=1700
wptTime="2011-05-09T10:00:01Z"
wptSym="pin"
wptDesc="This is an example waypoint"
wptCmt="Just a comment"
gpx=gpxpy.gpx.GPX()
gpx_waypoints=gpxpy.gpx.GPXWaypoint(latitude=wptLat, longitude=wptLon,
... name=wptName,elevation=wptEle, symbol=wptSym, time=wptTime,
... description=wptDesc, comment=wptCmt)
gpx.waypoints.append(gpx_waypoints)
print gpx.to_xml()
Traceback (most recent call last):
File "", line 1, in
File "/Users/seant/.virtualenvs/cleanasFUCK/lib/python2.7/site-packages/gpxpy/gpx.py", line 1522, in to_xml
content += waypoint.to_xml(version)
File "/Users/seant/.virtualenvs/cleanasFUCK/lib/python2.7/site-packages/gpxpy/gpx.py", line 108, in to_xml
content += mod_utils.to_xml('time', content=self.time.strftime(DATE_FORMAT))
AttributeError: 'str' object has no attribute 'strftime'

type built-in overridden [bug]

In some places of the code, the builtin function type is being assigned to (as in type=blah). This is not the expected behavior.

AttributeError: 'set' object has no attribute 'items' when using gpx.to_xml() with version 1.1

Following this stackoverflow question: http://stackoverflow.com/questions/39993739/gpxpy-not-outputting-extensions-in-to-xml/

When using gpx.to_xml(varsion="1.1") the following stack trace is received (no error with version 1.0):

Traceback (most recent call last):
File "C:/programing/GPXConverter/forstack.py", line 14, in
print(gpx.to_xml(version="1.1"))
File "C:\Users\aayaffe\AppData\Local\Programs\Python\Python35\lib\site-packages\gpxpy\gpx.py", line 2594, in to_xml
content = mod_gpxfield.gpx_fields_to_xml(self, 'gpx', version, custom_attributes=xml_attributes)
File "C:\Users\aayaffe\AppData\Local\Programs\Python\Python35\lib\site-packages\gpxpy\gpxfield.py", line 312, in gpx_fields_to_xml
xml_value = gpx_field.to_xml(value, version)
File "C:\Users\aayaffe\AppData\Local\Programs\Python\Python35\lib\site-packages\gpxpy\gpxfield.py", line 192, in to_xml
result += gpx_fields_to_xml(obj, self.tag, version)
File "C:\Users\aayaffe\AppData\Local\Programs\Python\Python35\lib\site-packages\gpxpy\gpxfield.py", line 312, in gpx_fields_to_xml
xml_value = gpx_field.to_xml(value, version)
File "C:\Users\aayaffe\AppData\Local\Programs\Python\Python35\lib\site-packages\gpxpy\gpxfield.py", line 269, in to_xml
for ext_key, ext_value in value.items():
AttributeError: 'set' object has no attribute 'items'

Code used:

import xml.etree.ElementTree import gpxpy.gpx f = xml.etree.ElementTree.parse('stack.gpx') gpx = gpxpy.gpx.GPX() gpx.creator = "a" odpoint = f.find("{http://www.opencpn.org}path").find("{http://www.opencpn.org}ODPoint") w1 = gpxpy.gpx.GPXWaypoint() w1.latitude = odpoint.attrib.get('lat') w1.longitude = odpoint.attrib.get('lon') w1.extensions = {odpoint.find('{http://www.opencpn.org}guid')} w1.type = 'WPT' gpx.waypoints.append(w1) print(gpx.to_xml(version="1.1"))

GPX file used:

<?xml version="1.0"?> <OCPNDraw version="0.1" creator="OpenCPN" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opencpn="http://www.opencpn.org"> <opencpn:path> <opencpn:type>Boundary</opencpn:type> <opencpn:ODPoint lat="47.0" lon="59.0"> <opencpn:type>Boundary Point</opencpn:type> <opencpn:guid>4fbfffff-806d-4317-b245-4e6e2d190000</opencpn:guid> </opencpn:ODPoint> </opencpn:path> </OCPNDraw>

Custom date formats

Thanks for the excellent library with such a clean API.

Now to the problem. My selection of .gpx files was generated by two N9 applications: SportsTracker and GPSLogMee. Both save the timestamps in formats that don't match gpxpy.gpx.DATE_FORMAT. SportsTracker seems to follow ISO 8601 (which is implied by GPX) while GPSLogMee sticks to RFC 822 for some reason. However ugly it is, monkey-patching the format string mostly helps... but SportsTracker sometimes omits microseconds (which defeats the possibility to correctly parse the whole file generated by ST). And, indeed, even ISO 8601 implies a certain degree of variability, not to mention the deviations from canonical GPX.

So, the date/time format depends on the data source and there can be more than one valid date/time format per data source.

Possible solutions:

  1. ease the pain of monkey-patching by converting gpxpy.gpx.DATE_FORMAT into a list of strings (and possibly populate it with multiple common formats);
  2. allow passing a list of possible date/time formats to the parser.

What do you think?

gpxpy writes logs in the root logger

Hello,

I spotted that throughout the library, the logs are written in the ROOT logger. This is not really convenient if an application using this library wants to redirect the logs to another file.

I would propose to define a default logger for the gpxpy library and prevent writing logs by default as explained here https://docs.python.org/3/howto/logging.html#library-config.

If you think it is worth taking some time to do it, just tell me and I will provide a PR.
Regards,
Stac

Add git tags for releases

Hi, could you also add git tags corresponding to your releases on PyPI. That would make things easier if I want to check out the sourcecode of a version I am using from PyPI. Thank you.

Python3 support

It would be great if this supported Python3. I did a bit of poking around, and it looks like the main complexity will be in bytes/str handling.

test cases don't handle loops

I hand crafted a gpx for testing and got some test errors from the simplify_polyline call. The track that I made was a loop and had the same exact start point and end point. I don't think it is against the spec to have such a track, and it is almost impossible to have such a track in real life, but I thought I'd bring it up anyway in case you wanted to fix that corner case.

variable formatting of output

I am no friend of all those GPX GUI utilities, I prefer directly editing the gpx. One of my needs is removing unwanted trackpoints (like when forgetting to stop recording before driving back home).

That is much easier if there is exactly one line per trackpoint.

My bad hack is to do

gpxpy.utils.to_xml = to_xml

where to_xml is my own implementation starting with
if tag in ('ele', 'time'):
result = '<%s' % tag
else:
result = '\n<%s' % tag

Of course this is bad -
it depends of implementation details
it should probably respect more tags but those are the two I am currently outputting

It would be nice if I could pass a list of tag names which gpxpy should not prepend with a LF.

Splits calculation

Is it possible to calculate kilometer(km) splits including data such as km, pace, (+-) elevation with this tool?

I also noticed that point.speed is None, but point.exentions['gpxdata:speed] is populated. What is the extensions attribute? I couldn't find any helpful resources online.

gpx.adjust_times does not adjust waypoints

Well - it does exactly what the docstring says - so it is actually correct.

But it makes the gpx file in its entirety inconsistent, users have to remember that they also need to adjust waypoints and maybe other places where there are times.

It is also inconsistent within the API: gpx.move will move tracks, routes, waypoints - so why shouldn't adjust_time also adjust all of them?

Changing that would be an incompatible change but I still think it would be a good idea.

Add speed to gpx if missing

First of all gpxpy is really great and I like that I can add the elevation so easily to a track with the help of srtm.py. I would be cool to have this feature also for the speed. There is get_moving_data that actually calculates what I want but does not return it. A function add_missing_speed would be nice that calculates and adds the smoothed speed to all the GPXTrackPoint points. A simple way of smoothing would be to assign the calculated speed from time and distance to the center of the line between to GPXTrackPoints. The speed at a GPXTrackPoint is now the weighted speed of the two adjoining lines. For the first and last GPXTrackPoint one would need to assume 0 or a cyclic boundary condition.

Gpxpy Error handling

is gpxpy provide an error handling when parsing the .gpx file? for example invalidate gpx or corrupted file

Support for GPX1.1

I read all GPX standard and i found the difference between version.
The first difference is the moving of metadata in a "metadata" child. The difference in the metadata child is:

  • the author/mail in the 1.0 become the author in 1.1 with personType
  • the mail is divided in id and domain attribute
  • the url/urlname in 1.0 become linktype in 1.1 and add the possibility to add more link
  • added the copyrigth
    In the other part of GPX standard the only difference is the url → link modify.
    I try to adjust the parsing code to add the possibility for parsing both version.
    For creation gpx code start at end of parsing code modification.

adjust_time: Metadata

Currently if I use the adjust_time method, only the times of the trackpoints are updated.
I think that also the time in the metadata should be adjusted,

GPXTrackPoint(latitude=0, longitude=0) serialize/deserialize raises exception

I was writing some test cases where a GPX file was written and then read from disk, so I presumed 0,0 would be a safe pair of coordinates to use, but it raised an exception:

root: ERROR: latitude is mandatory in None
Traceback (most recent call last):
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/parser.py", line 196, in parse
    self.__parse_dom()
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/parser.py", line 221, in __parse_dom
    mod_gpxfield.gpx_fields_from_xml(self.gpx, self.xml_parser, node, version)
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 348, in gpx_fields_from_xml
    value = gpx_field.from_xml(parser, current_node, version)
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 180, in from_xml
    result.append(gpx_fields_from_xml(self.classs, parser, child_node, version))
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 348, in gpx_fields_from_xml
    value = gpx_field.from_xml(parser, current_node, version)
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 180, in from_xml
    result.append(gpx_fields_from_xml(self.classs, parser, child_node, version))
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 348, in gpx_fields_from_xml
    value = gpx_field.from_xml(parser, current_node, version)
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 180, in from_xml
    result.append(gpx_fields_from_xml(self.classs, parser, child_node, version))
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 348, in gpx_fields_from_xml
    value = gpx_field.from_xml(parser, current_node, version)
  File "/home/august/autologic/api/env/lib/python3.5/site-packages/gpxpy/gpxfield.py", line 137, in from_xml
    raise mod_gpx.GPXException('%s is mandatory in %s' % (self.name, self.tag))
gpxpy.gpx.GPXException: latitude is mandatory in None

The latitude/longitudes were not written to the file if they were equal to 0. I'm going to guess that some bit of code in the serialization step is using if not latitude: when it should be if latitude is None:, or, perhaps more generally if attribute.value: write_attribute(attribute) instead of if attribute.value is not None: write_attribute(attribute)

Error in track segment elevation extremes calculation

When calculating the elevation extremes for a track segment, the min/max return values are reversed, resulting in a bad min/max at the segment level. (This is masked at the track level since the segment mins/maxes are thrown into a common list and min/max is recalculated)

slow

GPX parsing needs a lot of time for converting the time strings in the points to datetime.datetime (calling strptime).

If I disable this by doing

import gpxpy.gpxfield as mod_gpxfield
mod_gpxfield.TIME_TYPE=None

before I import from gpxpy what I need, my application is about 25% faster. That is too much for me to be ignored.

So what I would like to see is an official stable API which disables parsing for times in points. The application can do that if and when it needs datetimes. My application rarely does. Even comparing still works for the unparsed strings as long as they are formatted the same way (which they hopefully are within one file).

Or maybe gpxpy could transparently delay parsing until a datetime is really needed (a property, caching the calculation).

Write speed in to_xml()

When I read in a gpx file, add speeds for the first and last point of each segment, run add_missing_speeds() the speed for each point gets set. Now running to_xml() generates an XML file which lacks the speed information although speed is an optional field in the GPX format. Was this forgotten in the to_xml() function?

entry_points in setup.py is not supported without setuptools

Hi gpxpy team,

a warning will be thrown when installing the package with the setup.py in master branch:

UserWarning: Unknown distribution option: 'entry_points'

The gpxinfo executable script can not be generated or installed properly either.

After some searching work, I found that the installation process would be alright if I added the import of setuptools in setup.py:

from setuptools import setup

However, the generated gpxinfo still doesn't work. Its content is as follows.

#!/usr/local/opt/python/bin/python2.7
# EASY-INSTALL-ENTRY-SCRIPT: 'gpxpy==0.9.8','console_scripts','gpxinfo'
__requires__ = 'gpxpy==0.9.8'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.exit(
        load_entry_point('gpxpy==0.9.8', 'console_scripts', 'gpxinfo')()
    )

Error message is:

Traceback (most recent call last):
  File "/usr/local/bin/gpxinfo", line 9, in <module>
    load_entry_point('gpxpy==0.9.8', 'console_scripts', 'gpxinfo')()
  File "build/bdist.macosx-10.10-x86_64/egg/pkg_resources/__init__.py", line 519, in load_entry_point
  File "build/bdist.macosx-10.10-x86_64/egg/pkg_resources/__init__.py", line 2630, in load_entry_point
  File "build/bdist.macosx-10.10-x86_64/egg/pkg_resources/__init__.py", line 2310, in load
  File "build/bdist.macosx-10.10-x86_64/egg/pkg_resources/__init__.py", line 2316, in resolve
ImportError: No module named gpxinfo

My environment is OS X 10.10.3 with python 2.7.9 installed via homebrew.

Would you please give me some hints? Thanks.

Huge Option

Hi folks,

I get an exception:

Excessive depth in document: 256 use XML_PARSE_HUGE option, line 769, column 5 (, line 769)
At first I thought there was an issue with special chars in the file name, but even with clean file names some files raises that error.

Do you need anything else?

Cheers, Marcel

UnicodeWarning in recent release

Under Python 2.7, I'm getting the following warning in the recent release:

gpxpy/parser.py:168: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal

time parsing

Hey Tomo,

first of all: great work!

I think the time-parsing should be a little smarter. I'm getting "None" for every time that has no "Z"-suffix... Maybe it's even possible to get the timezone from the coordinates if none is provided by the timestamp.

I think the follwowing formats should be supported:

2007-04-05T14:30 (get timezone from coordinates, or just expect UTC)
2007-04-05T12:30-02:00
2007-04-05T14:30Z (the only format working for me)

Kind regards,

Kai

Unexpected Errors

I got some unexpected errors when I ran the sample code:

gpx = gpxpy.parse(gpx_file)
ERROR:root:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\gpxpy\parser.py", line 196, in parse
self.xml_parser = LXMLParser(self.xml)
File "C:\Python27\lib\site-packages\gpxpy\parser.py", line 94, in init
assert mod_etree
AssertionError
Traceback (most recent call last):
File "", line 1, in
File "C:\Python27\lib\site-packages\gpxpy__init__.py", line 28, in parse
return parser.parse()
File "C:\Python27\lib\site-packages\gpxpy\parser.py", line 217, in parse
raise mod_gpx.GPXXMLSyntaxException('Error parsing XML: %s' % str(e), e)
gpxpy.gpx.GPXXMLSyntaxException: Error parsing XML:

Am I doing something wrong?

Regards,

Alan

Missing CDATA while exporting gpx

Using gpx.to_xml() misses CDATA marks in tags, e.g:
original file: <name><![CDATA[Ślad zapisany przez OSMTracker - Android™]]></name>
after calling to_xml(): <name>Ślad zapisany przez OSMTracker - Android™</name>

This can cause real problems :)

Please sign source tarballs

Hi,

I am packaging gpxpy for Debian. It would be great if you could gpg-sign your tarballs uploaded to PyPI from the next release.

Cheers,
Nik

TypeError: argument of type 'builtin_function_or_method' is not iterable

could this be some missing library? (the file loads fine on the site you have hosted)

i will paste gpx file in comment.

File "/home/vagrant/.virtualenvs/trip2/lib/python3.4/site-packages/gpxpy/parser.py", line 423, in __parse_track_segment
if self.xml_parser.get_node_name(child_node) == 'trkpt':
File "/home/vagrant/.virtualenvs/trip2/lib/python3.4/site-packages/gpxpy/parser.py", line 130, in get_node_name
if '}' in node.tag:
TypeError: argument of type 'builtin_function_or_method' is not iterable

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "", line 1, in
File "/home/vagrant/.virtualenvs/trip2/lib/python3.4/site-packages/gpxpy/init.py", line 32, in parse
return parser.parse()
File "/home/vagrant/.virtualenvs/trip2/lib/python3.4/site-packages/gpxpy/parser.py", line 219, in parse
raise mod_gpx.GPXXMLSyntaxException('Error parsing XML: %s' % str(e), e)
gpxpy.gpx.GPXXMLSyntaxException: Error parsing XML: argument of type 'builtin_function_or_method' is not iterable

Weird behavior between Python 3 and Python 2.7 for timestamps

Hello,

When parsing a GPX where precision is on milliseconds, using Python 2 and gpxpy, no issue to get the correct timestamp value per point. But if I use Python, I end up with a 1s precision and then got duplicate timestamps when recording is less than every seconds and fail to calculate speed compared to previous point.

Are you aware of any issue with Python version and timestamp ?

Regards

In attachement the GPX I use to test.
Move_2017_02_07_12_21_36_Course.gpx.zip

Error on gpx 1.0 format parsing because of <course> float value

Hi,

Thanks a lot for gpxpy that i use a lot.

I noticed there was a possible mistake in the parsing about the value of "course" tags. The GPX 1.0 format (http://www.topografix.com/gpx_manual.asp) tells us its unit is degrees, so in other words, a float. But the gpxpy parser apparently tries to read it as an int.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/gpxpy/__init__.py", line 34, in parse
    return parser.parse()
  File "/usr/local/lib/python2.7/dist-packages/gpxpy/parser.py", line 211, in parse
    raise mod_gpx.GPXXMLSyntaxException('Error parsing XML: %s' % str(e), e)
gpxpy.gpx.GPXXMLSyntaxException: Error parsing XML: Invalid value for <course>... 67.72383 (invalid literal for int() with base 10: '67.72383')

Apparently the "course" tag is not included anymore in GPX 1.1 (last implementation) but there are still lots of programs producing GPX 1.0 files.

Do you agree with me that "course" values should be red as floats in gpxpy ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.