gpxpy: как извлечь данные о частоте сердечных сокращений из файла gpx
Эта фиксация библиотеки gpxpy включает в себя дополнительный анализ расширений Garmin 1.1. Однако кажется, что код сильно изменился с момента этой фиксации, и теперь кажется, что расширения анализируются автоматически.
Однако я не смог понять, как извлечь данные о частоте сердечных сокращений или другие данные о расширении из файла gpx, используя gpxpy. Кто-нибудь делал это с помощью gpxpy? Как это сделать?
Изменить, чтобы не закрывать этот вопрос:
Если вы посмотрите на добавления кода в коммите, который я связал выше, он изменяет класс TrackPoint, добавляя "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, чтобы понять, как заставить его анализировать эти теги. Мой вопрос - попытка понять, что мне не хватает в том, как работает новый код. Мой инстинкт состоит в том, чтобы просто добавить такую строку в код gpx.py вокруг строки 74.
mod_gpxfield.GPXField('heart_rate', 'hr', type=mod_gpxfield.FLOAT_TYPE),
Однако я надеюсь, что кто-то опытный сможет просмотреть код и посмотреть, есть ли что-то, чего мне не хватает, например, указать список расширений =[hr, atemp] и проанализировать их при чтении данных. Кажется странным, что этот коммит был сделан в прошлом, но теперь эта функция была потеряна, поэтому я предполагаю, что что-то упустил.
Часть xml сердечного ритма выглядит так внутри trkpt по сравнению с их тестовой схемой
<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']
Вернет ли данные? Используя отладчик python, я не вижу их загруженными в структуру данных gpx.tracks.
2 ответа
Похоже, что если какие-либо из расширений в DOM являются сложными, дочерние узлы не анализируются.
Это давняя проблема, по-видимому, с кодом: https://github.com/tkrajina/gpxpy/issues/73
Выражение
.extensions[0]['hr']
не работает с последним файлом Garmin GPX, использующим текущую версию
gpxpy
:
.extensions[0]
нельзя запрашивать, используя теги в качестве ключей - он отображает дочерний список, который вы можете либо перебирать, либо запрашивать, используя
.find()
.
Например, имя тега для , ужасное:
{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']
Если данные о часах отсутствуют в трекпойнте, вы получите пустой список, поэтому проверьте его работоспособность и извлеките число. Другой способ сделать это - сделать
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.