gpxpy:如何从 gpx 文件中提取心率数据
gpxpy: How to extract heart rate data from gpx file
This commit to gpxpy library 包括对 Garmin 1.1 扩展的额外解析。然而,自此提交以来,代码似乎发生了很大变化,并且现在似乎可以自动解析扩展。
但是我一直无法弄清楚如何使用 gpxpy 从 gpx 文件中提取心率数据或其他扩展数据。有没有人用 gpxpy 做过这个?它是怎么做到的?
编辑以避免关闭此问题:
如果您查看我上面链接的提交中的代码添加,它会修改 TrackPoint class 以添加 "atemp" 和 "hr"
class GPXTrackPoint(mod_geo.Location):
def __init__(self, latitude, longitude, elevation=None, time=None, symbol=None, comment=None,
horizontal_dilution=None, vertical_dilution=None, position_dilution=None, speed=None,
name=None, atemp = None, hr = None):
然后稍后在 parser.py 你会看到添加了这个例程
def __parse_track_point_extension(self, node):
+ atemp_node = self.xml_parser.get_first_child(node, 'atemp')
+ atemp = mod_utils.to_number(self.xml_parser.get_node_data(atemp_node))
+
+ hr_node = self.xml_parser.get_first_child(node, 'hr')
+ hr = mod_utils.to_number(self.xml_parser.get_node_data(hr_node))
+ extensions = {"atemp":atemp, "hr":hr}
+ return extensions
然而,在当前代码中,结构看起来与最初提交时非常不同,但它似乎允许以更通用的方式解析扩展。但是我对 python 还不够熟练,无法理解如何让它解析这些标签。我的问题是试图了解我在新代码的工作方式中遗漏了什么。我的直觉是在第 74 行附近的 the gpx.py code 中添加这样一行。
mod_gpxfield.GPXField('heart_rate', 'hr', type=mod_gpxfield.FLOAT_TYPE),
不过,我希望有经验的人可以查看代码,看看是否有我遗漏的东西,比如指定列表 extensions=[hr, atemp] 并在读取数据时对它们进行一般解析。奇怪的是这个提交是在过去进行的,但现在这个功能已经丢失了,所以我想我遗漏了什么。
心率部分 xml 在 trkpt 中看起来像这样 compared to their test schema
<trkpt lat="1.6685718186199665069580078125" lon="-101.03414486162364482879638671875">
<time>2018-02-10T19:24:06.000Z</time>
<extensions>
<ns3:TrackPointExtension>
<ns3:hr>106</ns3:hr>
</ns3:TrackPointExtension>
</extensions>
</trkpt>
在他们的 test.py 中,您可以看到他们在他们的 gpx 测试文件中测试他们的测试扩展:
<trkpt lat="10.1" lon="-20.2">
<ele>11.1</ele>
<time>2013-01-01T12:00:04</time>
<extensions>
<last>true</last>
</extensions>
哪个正在测试标签:
self.assertEquals('true',gpx.tracks[0].segments[0].points[0].extensions['last'])
虽然我不明白它是如何被解析的,但这是否意味着做这样的事情:
hr=gpx.tracks[0].segments[0].points[0].extensions['hr']
请问return的数据?使用 python 调试器,我看不到这些加载到 gpx.tracks 数据结构中。
看来,如果 DOM 中的任何扩展扩展很复杂,则子节点不会被解析。
这显然是代码的一个长期存在的问题:
https://github.com/tkrajina/gpxpy/issues/73
编辑:
这是一个实际的例子,但这有点取决于你的结构。
heart_rate = gpx.tracks[0].segments[0].points[0].extensions[0]['hr']
表达式 .extensions[0]['hr']
似乎不适用于使用当前版本 gpxpy
的最新 Garmin GPX 文件:.extensions[0]
无法使用标签作为键进行查询 --它呈现一个子列表,您可以使用 .find()
.
对其进行迭代或查询
例如 hr
的标签名称很糟糕:
{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr
但您可以使用子字符串查询进行迭代并获取所需的 hr
元素,而不管扩展标签的顺序如何,如下所示:
In [10]: [el.text for el in gpx.tracks[0].segments[0].points[2].extensions[0] if 'hr' in el.tag][0]
Out[10]: ['122']
如果跟踪点中缺少 hr 数据,您将得到一个空列表,因此请对其进行完整性检查并提取数字。另一种方法是执行 Element.find()
:
In [11]: gpx.tracks[0].segments[0].points[2].extensions[0].find('{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr')
Out[11]: <Element '{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr' at 0x11b0424a0>
In [12]: _11.text
Out[12]: '122'
使用这种技术,完整性检查将发生在第 11 行和第 12 行之间,确保 _11 不是 None.
This commit to gpxpy library 包括对 Garmin 1.1 扩展的额外解析。然而,自此提交以来,代码似乎发生了很大变化,并且现在似乎可以自动解析扩展。
但是我一直无法弄清楚如何使用 gpxpy 从 gpx 文件中提取心率数据或其他扩展数据。有没有人用 gpxpy 做过这个?它是怎么做到的?
编辑以避免关闭此问题:
如果您查看我上面链接的提交中的代码添加,它会修改 TrackPoint class 以添加 "atemp" 和 "hr"
class GPXTrackPoint(mod_geo.Location):
def __init__(self, latitude, longitude, elevation=None, time=None, symbol=None, comment=None,
horizontal_dilution=None, vertical_dilution=None, position_dilution=None, speed=None,
name=None, atemp = None, hr = None):
然后稍后在 parser.py 你会看到添加了这个例程
def __parse_track_point_extension(self, node):
+ atemp_node = self.xml_parser.get_first_child(node, 'atemp')
+ atemp = mod_utils.to_number(self.xml_parser.get_node_data(atemp_node))
+
+ hr_node = self.xml_parser.get_first_child(node, 'hr')
+ hr = mod_utils.to_number(self.xml_parser.get_node_data(hr_node))
+ extensions = {"atemp":atemp, "hr":hr}
+ return extensions
然而,在当前代码中,结构看起来与最初提交时非常不同,但它似乎允许以更通用的方式解析扩展。但是我对 python 还不够熟练,无法理解如何让它解析这些标签。我的问题是试图了解我在新代码的工作方式中遗漏了什么。我的直觉是在第 74 行附近的 the gpx.py code 中添加这样一行。
mod_gpxfield.GPXField('heart_rate', 'hr', type=mod_gpxfield.FLOAT_TYPE),
不过,我希望有经验的人可以查看代码,看看是否有我遗漏的东西,比如指定列表 extensions=[hr, atemp] 并在读取数据时对它们进行一般解析。奇怪的是这个提交是在过去进行的,但现在这个功能已经丢失了,所以我想我遗漏了什么。
心率部分 xml 在 trkpt 中看起来像这样 compared to their test schema
<trkpt lat="1.6685718186199665069580078125" lon="-101.03414486162364482879638671875">
<time>2018-02-10T19:24:06.000Z</time>
<extensions>
<ns3:TrackPointExtension>
<ns3:hr>106</ns3:hr>
</ns3:TrackPointExtension>
</extensions>
</trkpt>
在他们的 test.py 中,您可以看到他们在他们的 gpx 测试文件中测试他们的测试扩展:
<trkpt lat="10.1" lon="-20.2">
<ele>11.1</ele>
<time>2013-01-01T12:00:04</time>
<extensions>
<last>true</last>
</extensions>
哪个正在测试标签:
self.assertEquals('true',gpx.tracks[0].segments[0].points[0].extensions['last'])
虽然我不明白它是如何被解析的,但这是否意味着做这样的事情:
hr=gpx.tracks[0].segments[0].points[0].extensions['hr']
请问return的数据?使用 python 调试器,我看不到这些加载到 gpx.tracks 数据结构中。
看来,如果 DOM 中的任何扩展扩展很复杂,则子节点不会被解析。
这显然是代码的一个长期存在的问题: https://github.com/tkrajina/gpxpy/issues/73
编辑: 这是一个实际的例子,但这有点取决于你的结构。
heart_rate = gpx.tracks[0].segments[0].points[0].extensions[0]['hr']
表达式 .extensions[0]['hr']
似乎不适用于使用当前版本 gpxpy
的最新 Garmin GPX 文件:.extensions[0]
无法使用标签作为键进行查询 --它呈现一个子列表,您可以使用 .find()
.
例如 hr
的标签名称很糟糕:
{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr
但您可以使用子字符串查询进行迭代并获取所需的 hr
元素,而不管扩展标签的顺序如何,如下所示:
In [10]: [el.text for el in gpx.tracks[0].segments[0].points[2].extensions[0] if 'hr' in el.tag][0]
Out[10]: ['122']
如果跟踪点中缺少 hr 数据,您将得到一个空列表,因此请对其进行完整性检查并提取数字。另一种方法是执行 Element.find()
:
In [11]: gpx.tracks[0].segments[0].points[2].extensions[0].find('{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr')
Out[11]: <Element '{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr' at 0x11b0424a0>
In [12]: _11.text
Out[12]: '122'
使用这种技术,完整性检查将发生在第 11 行和第 12 行之间,确保 _11 不是 None.