def insert_pause(samples, insert_pause_idx, move, pause_type): if (insert_pause_idx <= 0): return stop_sample = samples[insert_pause_idx - 1] start_sample = samples[insert_pause_idx] pause_duration = start_sample.time - stop_sample.time pause_distance = distance( (radian_to_degree( stop_sample.latitude), radian_to_degree(stop_sample.longitude)), (radian_to_degree(start_sample.latitude), radian_to_degree(start_sample.longitude))).meters # Introduce start of pause sample pause_sample = Sample() pause_sample.move = move pause_sample.utc = stop_sample.utc pause_sample.time = stop_sample.time stop_sample.utc -= timedelta( microseconds=1 ) # Cut off 1ms from last recorded sample in order to introduce the new pause sample and keep time order stop_sample.time -= timedelta(microseconds=1) pause_sample.events = { "pause": { "state": "True", "type": str(pause_type), "duration": str(pause_duration), "distance": str(pause_distance), } } samples.insert(insert_pause_idx, pause_sample) # Duplicate last element # Introduce end of pause sample pause_sample = Sample() pause_sample.move = move pause_sample.utc = start_sample.utc pause_sample.time = start_sample.time start_sample.utc += timedelta( microseconds=1 ) # Add 1ms to the first recorded sample in order to introduce the new pause sample and keep time order start_sample.time += timedelta(microseconds=1) pause_sample.events = { "pause": { "state": "False", "duration": "0", "distance": "0", "type": str(pause_type) } } samples.insert(insert_pause_idx + 1, pause_sample)
def insert_pause(samples, insert_pause_idx, move, pause_type): if (insert_pause_idx <= 0): return stop_sample = samples[insert_pause_idx - 1] start_sample = samples[insert_pause_idx] pause_duration = start_sample.time - stop_sample.time pause_distance = distance((radian_to_degree(stop_sample.latitude), radian_to_degree(stop_sample.longitude)), (radian_to_degree(start_sample.latitude), radian_to_degree(start_sample.longitude))).meters # Introduce start of pause sample pause_sample = Sample() pause_sample.move = move pause_sample.utc = stop_sample.utc pause_sample.time = stop_sample.time stop_sample.utc -= timedelta(microseconds=1) # Cut off 1ms from last recorded sample in order to introduce the new pause sample and keep time order stop_sample.time -= timedelta(microseconds=1) pause_sample.events = {"pause": {"state": "True", "type": str(pause_type), "duration": str(pause_duration), "distance": str(pause_distance), }} samples.insert(insert_pause_idx, pause_sample) # Duplicate last element # Introduce end of pause sample pause_sample = Sample() pause_sample.move = move pause_sample.utc = start_sample.utc pause_sample.time = start_sample.time start_sample.utc += timedelta(microseconds=1) # Add 1ms to the first recorded sample in order to introduce the new pause sample and keep time order start_sample.time += timedelta(microseconds=1) pause_sample.events = {"pause": {"state": "False", "duration": "0", "distance": "0", "type": str(pause_type) }} samples.insert(insert_pause_idx + 1, pause_sample)
def parse_samples(tree, move, gpx_namespace): all_samples = [] tracks = tree.iterchildren(tag=gpx_namespace + GPX_TRK) for track in tracks: track_samples = [] track_segments = track.iterchildren(tag=gpx_namespace + GPX_TRKSEG) for track_segment in track_segments: segment_samples = [] track_points = track_segment.iterchildren(tag=gpx_namespace + GPX_TRKPT) for track_point in track_points: sample = Sample() sample.move = move # GPS position / altitude sample.latitude = degree_to_radian(float(track_point.attrib[GPX_TRKPT_ATTRIB_LATITUDE])) sample.longitude = degree_to_radian(float(track_point.attrib[GPX_TRKPT_ATTRIB_LONGITUDE])) sample.sample_type = "gps-base" if hasattr(track_point, GPX_TRKPT_ATTRIB_ELEVATION): sample.gps_altitude = float(track_point.ele) sample.altitude = int(round(sample.gps_altitude)) # Time / UTC sample.utc = dateutil.parser.parse(str(track_point.time)) if len(segment_samples) > 0: # Accumulate time delta to previous sample to get the total duration time_delta = sample.utc - segment_samples[-1].utc sample.time = segment_samples[-1].time + time_delta # Accumulate distance to previous sample distance_delta = vincenty( (radian_to_degree(sample.latitude), radian_to_degree(sample.longitude)), ( radian_to_degree(segment_samples[-1].latitude), radian_to_degree(segment_samples[-1].longitude), ), ).meters sample.distance = segment_samples[-1].distance + distance_delta if time_delta > timedelta(0): sample.speed = distance_delta / time_delta.total_seconds() else: sample.speed = 0 elif len(track_samples) > 0: sample.time = track_samples[-1].time sample.distance = track_samples[-1].distance sample.speed = track_samples[-1].speed elif len(all_samples) > 0: sample.time = all_samples[-1].time sample.distance = all_samples[-1].distance sample.speed = all_samples[-1].speed else: sample.time = timedelta(0) sample.distance = 0 sample.speed = 0 parse_sample_extensions(sample, track_point) segment_samples.append(sample) # Insert an pause event between every tracksegment insert_pause(track_samples, segment_samples) track_samples.extend(segment_samples) # Insert an pause event between every track insert_pause(all_samples, track_samples) all_samples.extend(track_samples) return all_samples
def parse_samples(tree, move, gpx_namespace, import_options): all_samples = [] tracks = tree.iterchildren(tag=gpx_namespace + GPX_TRK) for track in tracks: track_samples = [] track_segments = track.iterchildren(tag=gpx_namespace + GPX_TRKSEG) for track_segment in track_segments: segment_samples = [] track_points = track_segment.iterchildren(tag=gpx_namespace + GPX_TRKPT) for track_point in track_points: sample = Sample() sample.move = move # GPS position / altitude sample.latitude = degree_to_radian(float(track_point.attrib[GPX_TRKPT_ATTRIB_LATITUDE])) sample.longitude = degree_to_radian(float(track_point.attrib[GPX_TRKPT_ATTRIB_LONGITUDE])) sample.sample_type = GPX_SAMPLE_TYPE if hasattr(track_point, GPX_TRKPT_ATTRIB_ELEVATION): sample.gps_altitude = float(track_point.ele) sample.altitude = int(round(sample.gps_altitude)) # Time / UTC sample.utc = dateutil.parser.parse(str(track_point.time)) # Option flags pause_detected = False # Track segment samples if len(segment_samples) > 0: # Accumulate time delta to previous sample to get the total duration time_delta = sample.utc - segment_samples[-1].utc sample.time = segment_samples[-1].time + time_delta # Accumulate distance to previous sample distance_delta = distance((radian_to_degree(sample.latitude), radian_to_degree(sample.longitude)), (radian_to_degree(segment_samples[-1].latitude), radian_to_degree(segment_samples[-1].longitude))).meters sample.distance = segment_samples[-1].distance + distance_delta if time_delta > timedelta(0): sample.speed = distance_delta / time_delta.total_seconds() else: sample.speed = 0 # Option: Pause detection based on time delta threshold if GPX_IMPORT_OPTION_PAUSE_DETECTION in import_options and time_delta > import_options[GPX_IMPORT_OPTION_PAUSE_DETECTION]: pause_detected = True sample.distance = segment_samples[-1].distance sample.speed = 0 # Track segment -> Track (multiple track segments contained) elif len(track_samples) > 0: sample.time = track_samples[-1].time + (sample.utc - track_samples[-1].utc) # Time diff to last sample of the previous track segment sample.distance = track_samples[-1].distance sample.speed = 0 # Track -> Full GPX (multiple tracks contained) elif len(all_samples) > 0: sample.time = all_samples[-1].time + (sample.utc - all_samples[-1].utc) # Time diff to last sample of the previous track sample.distance = all_samples[-1].distance sample.speed = 0 # First sample else: sample.time = timedelta(0) sample.distance = 0 sample.speed = 0 parse_sample_extensions(sample, track_point) segment_samples.append(sample) # Finally insert a found pause based on time delta threshold if pause_detected: insert_pause(segment_samples, len(segment_samples) - 1, move, pause_type=GPX_IMPORT_PAUSE_TYPE_PAUSE_DETECTION) # end for track_points # Insert an pause event between every track segment insert_pause_idx = len(track_samples) track_samples.extend(segment_samples) insert_pause(track_samples, insert_pause_idx, move, pause_type=GPX_TRKSEG) # end for track_segments # Insert an pause event between every track insert_pause_idx = len(all_samples) all_samples.extend(track_samples) insert_pause(all_samples, insert_pause_idx, move, pause_type=GPX_TRK) # end for tracks return all_samples
def parse_samples(tree, move, gpx_namespace, import_options): all_samples = [] tracks = tree.iterchildren(tag=gpx_namespace + GPX_TRK) for track in tracks: track_samples = [] track_segments = track.iterchildren(tag=gpx_namespace + GPX_TRKSEG) for track_segment in track_segments: segment_samples = [] track_points = track_segment.iterchildren(tag=gpx_namespace + GPX_TRKPT) for track_point in track_points: sample = Sample() sample.move = move # GPS position / altitude sample.latitude = degree_to_radian(float(track_point.attrib[GPX_TRKPT_ATTRIB_LATITUDE])) sample.longitude = degree_to_radian(float(track_point.attrib[GPX_TRKPT_ATTRIB_LONGITUDE])) sample.sample_type = GPX_SAMPLE_TYPE if hasattr(track_point, GPX_TRKPT_ATTRIB_ELEVATION): sample.gps_altitude = float(track_point.ele) sample.altitude = int(round(sample.gps_altitude)) # Time / UTC sample.utc = dateutil.parser.parse(str(track_point.time)) # Option flags pause_detected = False # Track segment samples if len(segment_samples) > 0: # Accumulate time delta to previous sample to get the total duration time_delta = sample.utc - segment_samples[-1].utc sample.time = segment_samples[-1].time + time_delta # Accumulate distance to previous sample distance_delta = vincenty((radian_to_degree(sample.latitude), radian_to_degree(sample.longitude)), (radian_to_degree(segment_samples[-1].latitude), radian_to_degree(segment_samples[-1].longitude))).meters sample.distance = segment_samples[-1].distance + distance_delta if time_delta > timedelta(0): sample.speed = distance_delta / time_delta.total_seconds() else: sample.speed = 0 # Option: Pause detection based on time delta threshold if GPX_IMPORT_OPTION_PAUSE_DETECTION in import_options and time_delta > import_options[GPX_IMPORT_OPTION_PAUSE_DETECTION]: pause_detected = True sample.distance = segment_samples[-1].distance sample.speed = 0 # Track segment -> Track (multiple track segments contained) elif len(track_samples) > 0: sample.time = track_samples[-1].time + (sample.utc - track_samples[-1].utc) # Time diff to last sample of the previous track segment sample.distance = track_samples[-1].distance sample.speed = 0 # Track -> Full GPX (multiple tracks contained) elif len(all_samples) > 0: sample.time = all_samples[-1].time + (sample.utc - all_samples[-1].utc) # Time diff to last sample of the previous track sample.distance = all_samples[-1].distance sample.speed = 0 # First sample else: sample.time = timedelta(0) sample.distance = 0 sample.speed = 0 parse_sample_extensions(sample, track_point) segment_samples.append(sample) # Finally insert a found pause based on time delta threshold if pause_detected: insert_pause(segment_samples, len(segment_samples) - 1, move, pause_type=GPX_IMPORT_PAUSE_TYPE_PAUSE_DETECTION) # end for track_points # Insert an pause event between every track segment insert_pause_idx = len(track_samples) track_samples.extend(segment_samples) insert_pause(track_samples, insert_pause_idx, move, pause_type=GPX_TRKSEG) # end for track_segments # Insert an pause event between every track insert_pause_idx = len(all_samples) all_samples.extend(track_samples) insert_pause(all_samples, insert_pause_idx, move, pause_type=GPX_TRK) # end for tracks return all_samples
def strava_import(current_user, activity_id): client = get_strava_client(current_user) activity = client.get_activity(activity_id=activity_id) stream_types = [ 'time', 'distance', 'latlng', 'temp', 'heartrate', 'velocity_smooth', 'altitude' ] streams = client.get_activity_streams(activity_id, types=stream_types) activity_string = map_type(activity.type) result = db.session.query( Move.activity_type).filter(Move.activity == activity_string).first() if result: activity_type, = result else: activity_type = None device = find_device(current_user) move = Move() move.user = current_user move.duration = activity.elapsed_time move.ascent = float(activity.total_elevation_gain) move.speed_avg = float(activity.average_speed) move.hr_avg = heart_rate(activity.average_heartrate) move.temperature_avg = celcius_to_kelvin(activity.average_temp) move.device = device move.date_time = activity.start_date_local move.activity = activity_string move.activity_type = activity_type move.distance = float(activity.distance) move.import_date_time = datetime.now() move.import_module = __name__ move.strava_activity_id = activity_id move.public = False move.source = "Strava activity id=%d; external_id='%s'" % ( activity_id, activity.external_id) if streams: lengths = set([len(streams[stream].data) for stream in streams]) assert len(lengths) == 1 length, = lengths else: length = 0 move.speed_max = move.speed_avg all_samples = [] for i in range(0, length): time = timedelta(seconds=streams['time'].data[i]) distance = float(streams['distance'].data[i]) if 'heartrate' in streams: hr = float(streams['heartrate'].data[i]) else: hr = None if 'latlng' in streams: lat, lng = streams['latlng'].data[i] else: lat = None lng = None if 'altitude' in streams: altitude = float(streams['altitude'].data[i]) else: altitude = None if 'velocity_smooth' in streams: speed = float(streams['velocity_smooth'].data[i]) else: speed = None if 'temp' in streams: temperature = celcius_to_kelvin(streams['temp'].data[i]) else: temperature = None sample = Sample() sample.sample_type = SAMPLE_TYPE sample.move = move sample.time = time sample.utc = (activity.start_date + time).replace(tzinfo=None) sample.distance = distance sample.latitude = degree_to_radian(lat) sample.longitude = degree_to_radian(lng) sample.hr = heart_rate(hr) sample.temperature = temperature sample.speed = speed sample.altitude = altitude move.speed_max = max(move.speed_max, speed) all_samples.append(sample) derive_move_infos_from_samples(move, all_samples) db.session.add(move) db.session.flush() postprocess_move(move) db.session.commit() return move
def strava_import(current_user, activity_id): client = get_strava_client(current_user) activity = client.get_activity(activity_id=activity_id) stream_types = ['time', 'distance', 'latlng', 'temp', 'heartrate', 'velocity_smooth', 'altitude'] streams = client.get_activity_streams(activity_id, types=stream_types) device_ids = [device_id for device_id, in db.session.query(func.distinct(Move.device_id)) .join(User) .join(Device) .filter(Device.name != gpx_import.GPX_DEVICE_NAME) .filter(Move.user == current_user).all()] assert len(device_ids) == 1 device_id = device_ids[0] device = db.session.query(Device).filter_by(id = device_id).one(); activity_string = map_type(activity.type) result = db.session.query(Move.activity_type).filter(Move.activity == activity_string).first() if result: activity_type, = result else: activity_type = None move = Move() move.user = current_user move.duration = activity.elapsed_time move.ascent = float(activity.total_elevation_gain) move.speed_avg = float(activity.average_speed) move.hr_avg = heart_rate(activity.average_heartrate) move.temperature_avg = celcius_to_kelvin(activity.average_temp) move.device = device move.date_time = activity.start_date_local move.activity = activity_string move.activity_type = activity_type move.distance = float(activity.distance) move.import_date_time = datetime.now() move.import_module = __name__ move.strava_activity_id = activity_id move.public = False move.source = "Strava activity id=%d; external_id='%s'" % (activity_id, activity.external_id) lengths = set([len(streams[stream].data) for stream in streams]) assert len(lengths) == 1 length, = lengths move.speed_max = move.speed_avg all_samples = [] for i in range(0, length): time = timedelta(seconds=streams['time'].data[i]) distance = float(streams['distance'].data[i]) if 'heartrate' in streams: hr = float(streams['heartrate'].data[i]) else: hr = None if 'latlng' in streams: lat, lng = streams['latlng'].data[i] else: lat = None lng = None if 'altitude' in streams: altitude = float(streams['altitude'].data[i]) else: altitude = None if 'velocity_smooth' in streams: speed = float(streams['velocity_smooth'].data[i]) else: speed = None if 'temp' in streams: temperature = celcius_to_kelvin(streams['temp'].data[i]) else: temperature = None sample = Sample() sample.sample_type = SAMPLE_TYPE sample.move = move sample.time = time sample.utc = (activity.start_date + time).replace(tzinfo=None) sample.distance = distance sample.latitude = degree_to_radian(lat) sample.longitude = degree_to_radian(lng) sample.hr = heart_rate(hr) sample.temperature = temperature sample.speed = speed sample.altitude = altitude move.speed_max = max(move.speed_max, speed) all_samples.append(sample) derive_move_infos_from_samples(move, all_samples) db.session.add(move) db.session.commit() return move