<commit_before>from xml.etree import ElementTree as ET
import datetime
import pyproj
from math import hypot
geod = pyproj.Geod(ellps='WGS84')

def proj_distance(lat1, lon1, lat2, lon2, elev1=None, elev2=None):
    try:
        hdelta = geod.inv(lon2, lat2, lon1, lat1)[2]
        if elev1 and elev2:
            distdelta = hypot(hdelta, elev1-elev2)
        else:
            distdelta = hdelta
        return distdelta
    except ValueError:
        return 0.0

class GPXEntry(object):

    def __init__(self, time, hr, speed, cadence, altitude, lon, lat):
        self.time = time
        self.hr = hr
        self.speed = speed
        self.cadence = cadence
        if not altitude:
            altitude = 0
        self.altitude = altitude
        self.lat = lat
        self.lon = lon

class GPXParser(object):

    garmin_ns = '{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}'
    start_lon = 0.0
    start_lat = 0.0

    end_lon = 0.0
    end_lat = 0.0

    entries = []
    distance = 0.0
    ascent = 0.0
    descent = 0.0
    max_speed = 0
    avg_speed = 0
    max_hr = 0
    avg_hr = 0
    avg_cadence = 0
    max_cadence = 0
    kcal_sum = 0
    # comment = '' Fixme


    def val_or_none(self, item, val, return_zero=False):
        ''' Return value if found or none if not. makes it easier to deal with 
        missing elements in xml'''
        try:
            e = item.find(self.ns + val)
            return float(e.text)
        except ValueError:
            if return_zero:
                return 0
            return None # missing element
        except AttributeError:
            if return_zero:
                return 0
            return None # missing element

    def __init__(self, filename=None):
        if filename:
            self.parse_uploaded_file(filename)

    def parse_uploaded_file(self, filename):
        if self.entries: # Do not parse again if sent filename in constructor
            return

        try:
            doc = ET.parse(filename)
        except:
            # mongofil
            return
        root = doc.getroot()
        ns = root.tag[:-3]
        self.ns = ns

        # http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
        vdop_cutoff = 30
        hdop_cutoff = 90

        for trk in root.findall(ns + 'trk'):
            trksegs = trk.findall(ns + 'trkseg')
            for trkseg in trksegs:
                trkpts = trkseg.findall(ns + 'trkpt')
                for trkpt in trkpts:
                    lat = float(trkpt.attrib['lat'])
                    lon = float(trkpt.attrib['lon'])
                    ele = self.val_or_none(trkpt, 'ele')
                    vdop = self.val_or_none(trkpt, 'vdop')
                    hdop = self.val_or_none(trkpt, 'hdop')
                    if vdop > vdop_cutoff:
                        # If accurarcy is low, use previous sample
                        if self.entries:
                            ele = self.entries[-1].altitude
                    if hdop > hdop_cutoff:
                        # If accurarcy is low, use previous sample
                        if self.entries:
                            lat = self.entries[-1].lat
                            lon = self.entries[-1].lon

                    speed = self.val_or_none(trkpt, 'speed', return_zero=True)
                    tstring = trkpt.find(ns + 'time').text
                    time = datetime.datetime(*map(int, map(float, tstring.replace("T","-").replace(":","-").strip("Z").split("-"))))

                    # extensions (hr)
                    hr = 0
                    try:
                        hr_ele = trkpt.find('.//' +self.garmin_ns + 'hr')
                        hr = int(hr_ele.text)
                        self.avg_hr += hr
                        self.max_hr = max(hr, self.max_hr)
                    except AttributeError:
                        pass # no hr in file
                    # extensions (cadence)
                    cad = 0
                    try:
                        cad_ele = trkpt.find('.//' +self.garmin_ns + 'cad')
                        cad = int(cad_ele.text)
                        self.avg_cadence += cad
                        self.max_cadence = max(cad, self.max_cadence)
                    except AttributeError:
                        pass # no hr in file

                    if self.entries:
                        this_distance = proj_distance(self.entries[-1].lat,
                                self.entries[-1].lon,
                                lat,
                                lon,
                                self.entries[-1].altitude,<commit_msg>less error prone gpxparser<commit_after>from xml.etree import ElementTree as ET
import datetime
import pyproj
from math import hypot
geod = pyproj.Geod(ellps='WGS84')

def proj_distance(lat1, lon1, lat2, lon2, elev1=None, elev2=None):
    try:
        hdelta = geod.inv(lon2, lat2, lon1, lat1)[2]
        if elev1 and elev2:
            distdelta = hypot(hdelta, elev1-elev2)
        else:
            distdelta = hdelta
        return distdelta
    except ValueError:
        return 0.0

class GPXEntry(object):

    def __init__(self, time, hr, speed, cadence, altitude, lon, lat):
        self.time = time
        self.hr = hr
        self.speed = speed
        self.cadence = cadence
        if not altitude:
            altitude = 0
        self.altitude = altitude
        self.lat = lat
        self.lon = lon

class GPXParser(object):

    garmin_ns = '{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}'
    start_lon = 0.0
    start_lat = 0.0

    end_lon = 0.0
    end_lat = 0.0

    entries = []
    distance = 0.0
    ascent = 0.0
    descent = 0.0
    max_speed = 0
    avg_speed = 0
    max_hr = 0
    avg_hr = 0
    avg_cadence = 0
    max_cadence = 0
    kcal_sum = 0
    # comment = '' Fixme


    def val_or_none(self, item, val, return_zero=False):
        ''' Return value if found or none if not. makes it easier to deal with 
        missing elements in xml'''
        try:
            e = item.find(self.ns + val)
            return float(e.text)
        except ValueError:
            if return_zero:
                return 0
            return None # missing element
        except AttributeError:
            if return_zero:
                return 0
            return None # missing element

    def __init__(self, filename=None):
        if filename:
            self.parse_uploaded_file(filename)

    def parse_uploaded_file(self, filename):
        if self.entries: # Do not parse again if sent filename in constructor
            return

        try:
            doc = ET.parse(filename)
        except:
            # mongofil
            return
        root = doc.getroot()
        ns = root.tag[:-3]
        self.ns = ns

        # http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
        vdop_cutoff = 30
        hdop_cutoff = 90

        for trk in root.findall(ns + 'trk'):
            trksegs = trk.findall(ns + 'trkseg')
            for trkseg in trksegs:
                trkpts = trkseg.findall(ns + 'trkpt')
                for trkpt in trkpts:
                    lat = float(trkpt.attrib['lat'])
                    lon = float(trkpt.attrib['lon'])
                    ele = self.val_or_none(trkpt, 'ele')
                    vdop = self.val_or_none(trkpt, 'vdop')
                    hdop = self.val_or_none(trkpt, 'hdop')
                    if vdop > vdop_cutoff:
                        # If accurarcy is low, use previous sample
                        if self.entries:
                            ele = self.entries[-1].altitude
                    if hdop > hdop_cutoff:
                        # If accurarcy is low, use previous sample
                        if self.entries:
                            lat = self.entries[-1].lat
                            lon = self.entries[-1].lon

                    speed = self.val_or_none(trkpt, 'speed', return_zero=True)
                    try:
                        tstring = trkpt.find(ns + 'time').text
                    except AttributeError:
                        # maybe stupid garmin format with multiple trkseg, one without time. skip skip
                        continue
                    time = datetime.datetime(*map(int, map(float, tstring.replace("T","-").replace(":","-").strip("Z").split("-"))))

                    # extensions (hr)
                    hr = 0
                    try:
                        hr_ele = trkpt.find('.//' +self.garmin_ns + 'hr')
                        hr = int(hr_ele.text)
                        self.avg_hr += hr
                        self.max_hr = max(hr, self.max_hr)
                    except AttributeError:
                        pass # no hr in file
                    # extensions (cadence)
                    cad = 0
                    try:
                        cad_ele = trkpt.find('.//' +self.garmin_ns + 'cad')
                        cad = int(cad_ele.text)
                        self.avg_cadence += cad
                        self.max_cadence = max(cad, self.max_cadence)
                    except AttributeError:
                        pass # no hr in file

                    if self.entries:
                        this_distance = proj_distance(self.entries[-1].lat,
                                self.entries[-1].lon,
                                lat,
                                lon,
                                self.entries[-1].altitude,
{'fraction_non_alphanumeric': 0.09125355225765709, 'fraction_numerical': 0.011998736975055258, 'mean_word_length': 1.2463356973995272, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '81117', 'n_tokens_mistral': 2862, 'n_tokens_neox': 2648, 'n_words': 666}