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.

Другие вопросы по тегам