def testStopSectionTimeline(self): eaist.segment_current_trips(self.testUUID) eaiss.segment_current_sections(self.testUUID) tl = esdt.get_timeline(self.testUUID, self.day_start_ts, self.day_end_ts) for i, element in enumerate(tl): logging.debug("%s: %s" % (i, type(element))) curr_type = self.get_type(element) if curr_type == ecwt.Trip: curr_tl = esdtq.get_timeline_for_trip(self.testUUID, element.get_id()) logging.debug("Got timeline %s for trip %s" % (curr_tl, element.start_fmt_time)) prev_sub_type = None prev_element = None checked_count = 0 j = 0 for j, curr_element in enumerate(curr_tl): logging.debug("curr_element = %s" % curr_element) curr_sub_type = self.get_type(curr_element) if prev_sub_type is not None: checked_count = checked_count + 1 self.assertNotEqual(prev_sub_type, curr_sub_type) if prev_sub_type == ecws.Stop: self.assertEqual(prev_element.starting_section, curr_element.get_id()) else: self.assertEqual(prev_sub_type, ecwsc.Section) self.assertEqual(prev_element.end_stop, curr_element.get_id()) prev_sub_type = curr_sub_type prev_element = curr_element self.assertEqual(checked_count, j)
def testStopSectionTimeline(self): eaist.segment_current_trips(self.testUUID) eaiss.segment_current_sections(self.testUUID) tl = esdt.get_timeline(self.testUUID, self.day_start_ts, self.day_end_ts) for i, element in enumerate(tl): logging.debug("%s: %s" % (i, type(element))) curr_type = self.get_type(element) if curr_type == ecwt.Trip: curr_tl = esdtq.get_timeline_for_trip(self.testUUID, element.get_id()) logging.debug("Got timeline %s for trip %s" % (curr_tl, element.start_fmt_time)) prev_sub_type = None prev_element = None checked_count = 0 j = 0 for j, curr_element in enumerate(curr_tl): logging.debug("curr_element = %s" % curr_element) curr_sub_type = self.get_type(curr_element) if prev_sub_type is not None: checked_count = checked_count + 1 self.assertNotEqual(prev_sub_type, curr_sub_type) if prev_sub_type == ecws.Stop: self.assertEqual(prev_element.starting_section, curr_element.get_id()) else: self.assertEqual(prev_sub_type, ecwsc.Section) self.assertEqual(prev_element.end_stop, curr_element.get_id()) prev_sub_type = curr_sub_type prev_element = curr_element self.assertEqual(checked_count, j)
def get_maps_for_range_old(user_id, start_ts, end_ts): # First, get the timeline for that range. ts = esta.TimeSeries.get_time_series(user_id) trip_list = esdt.get_trips(user_id, enua.UserCache.TimeQuery("start_ts", start_ts, end_ts)) # TODO: Should the timeline support random access as well? # If it did, we wouldn't need this additional map # I think that it would be good to support a doubly linked list, i.e. prev and next in addition # to the iteration interface place_list = esdp.get_places(user_id, enua.UserCache.TimeQuery("exit_ts", start_ts, end_ts)) place_list = place_list + (esdp.get_places(user_id, enua.UserCache.TimeQuery("enter_ts", start_ts, end_ts))) place_map = dict([(p.get_id(), p) for p in place_list]) map_list = [] flipped_midpoint = lambda(p1, p2): [(p1.coordinates[1] + p2.coordinates[1])/2, (p1.coordinates[0] + p2.coordinates[0])/2] for i, trip in enumerate(trip_list): logging.debug("-" * 20 + trip.start_fmt_time + "=>" + trip.end_fmt_time + "(" + str(trip.end_ts - trip.start_ts) + ")") if (len(esdt.get_sections_for_trip(user_id, trip.get_id())) == 0 and len(esdt.get_stops_for_trip(user_id, trip.get_id())) == 0): logging.debug("Skipping trip because it has no stops and no sections") continue start_point = gj.GeoJSON.to_instance(trip.start_loc) end_point = gj.GeoJSON.to_instance(trip.end_loc) curr_map = folium.Map(flipped_midpoint((start_point, end_point))) map_list.append(curr_map) logging.debug("About to display places %s and %s" % (trip.start_place, trip.end_place)) update_place(curr_map, trip.start_place, place_map, marker_color='green') update_place(curr_map, trip.end_place, place_map, marker_color='red') # TODO: Should get_timeline_for_trip work on a trip_id or on a trip object # it seems stupid to convert trip object -> id -> trip object curr_trip_timeline = esdt.get_timeline_for_trip(user_id, trip.get_id()) for i, trip_element in enumerate(curr_trip_timeline): # logging.debug("Examining element %s of type %s" % (trip_element, type(trip_element))) if type(trip_element) == ecws.Stop: time_query = esds.get_time_query_for_stop(trip_element.get_id()) logging.debug("time_query for stop %s = %s" % (trip_element, time_query)) stop_points_df = ts.get_data_df("background/filtered_location", time_query) # logging.debug("stop_points_df.head() = %s" % stop_points_df.head()) if len(stop_points_df) > 0: update_line(curr_map, stop_points_df, line_color = sel_color_list[-1], popup="%s -> %s" % (trip_element.enter_fmt_time, trip_element.exit_fmt_time)) else: assert(type(trip_element) == ecwsc.Section) time_query = esdsc.get_time_query_for_section(trip_element.get_id()) logging.debug("time_query for section %s = %s" % (trip_element, "[%s,%s,%s]" % (time_query.timeType, time_query.startTs, time_query.endTs))) section_points_df = ts.get_data_df("background/filtered_location", time_query) logging.debug("section_points_df.tail() = %s" % section_points_df.tail()) if len(section_points_df) > 0: update_line(curr_map, section_points_df, line_color = sel_color_list[trip_element.sensed_mode.value], popup="%s (%s -> %s)" % (trip_element.sensed_mode, trip_element.start_fmt_time, trip_element.end_fmt_time)) else: logging.warn("found no points for section %s" % trip_element) return map_list
def trip_to_geojson(trip, tl): """ Trips are the main focus of our current visualization, so they are most complex. Each trip is represented as a feature collection with the following features: - two features for the start and end places - features for each stop in the trip - features for each section in the trip :param trip: the trip object to be converted :param tl: the timeline used to retrieve related objects :return: the geojson version of the trip """ feature_array = [] curr_start_place = tl.get_object(trip.start_place) curr_end_place = tl.get_object(trip.end_place) start_place_geojson = place_to_geojson(curr_start_place) start_place_geojson["properties"]["feature_type"] = "start_place" feature_array.append(start_place_geojson) end_place_geojson = place_to_geojson(curr_end_place) end_place_geojson["properties"]["feature_type"] = "end_place" feature_array.append(end_place_geojson) trip_tl = esdt.get_timeline_for_trip(trip.user_id, trip.get_id()) stops = trip_tl.places for stop in stops: feature_array.append(stop_to_geojson(stop)) trip_distance = 0 for i, section in enumerate(trip_tl.trips): # TODO: figure out whether we should do this at the model. # The first section starts with the start of the trip. But the trip itself starts at the first # point where we exit the geofence, not at the start place. That is because we don't really know when # we left the start place. We can fix this in the model through interpolation. For now, we assume that the # gap between the real departure time and the time that the trip starts is small, and just combine it here. section_gj = section_to_geojson(section, tl) feature_array.append(section_gj) # import bson.json_util as bju # for f in section_gj.features: # logging.debug("Section has feature %s" % bju.dumps(f)) # TODO: Fix me to use the wrapper section_distance = [ f["properties"]["distance"] for f in section_gj.features if f.type == "Feature" and f.geometry.type == "LineString" ] logging.debug("found distance %s for section %s" % (section_distance, section.get_id())) trip_distance = trip_distance + sum(section_distance) trip_geojson = gj.FeatureCollection(features=feature_array, properties=trip) trip_geojson.id = str(trip.get_id()) trip_geojson.properties["feature_type"] = "trip" trip_geojson.properties["distance"] = trip_distance return trip_geojson
def get_maps_for_range_old(user_id, start_ts, end_ts): # First, get the timeline for that range. ts = esta.TimeSeries.get_time_series(user_id) trip_list = esdt.get_trips(user_id, enua.UserCache.TimeQuery("start_ts", start_ts, end_ts)) # TODO: Should the timeline support random access as well? # If it did, we wouldn't need this additional map # I think that it would be good to support a doubly linked list, i.e. prev and next in addition # to the iteration interface place_list = esdp.get_places(user_id, enua.UserCache.TimeQuery("exit_ts", start_ts, end_ts)) place_list = place_list + (esdp.get_places(user_id, enua.UserCache.TimeQuery("enter_ts", start_ts, end_ts))) place_map = dict([(p.get_id(), p) for p in place_list]) map_list = [] flipped_midpoint = lambda(p1, p2): [(p1.coordinates[1] + p2.coordinates[1])/2, (p1.coordinates[0] + p2.coordinates[0])/2] for i, trip in enumerate(trip_list): logging.debug("-" * 20 + trip.start_fmt_time + "=>" + trip.end_fmt_time + "(" + str(trip.end_ts - trip.start_ts) + ")") if (len(esdt.get_sections_for_trip(user_id, trip.get_id())) == 0 and len(esdt.get_stops_for_trip(user_id, trip.get_id())) == 0): logging.debug("Skipping trip because it has no stops and no sections") continue start_point = gj.GeoJSON.to_instance(trip.start_loc) end_point = gj.GeoJSON.to_instance(trip.end_loc) curr_map = folium.Map(flipped_midpoint((start_point, end_point))) map_list.append(curr_map) logging.debug("About to display places %s and %s" % (trip.start_place, trip.end_place)) update_place(curr_map, trip.start_place, place_map, marker_color='green') update_place(curr_map, trip.end_place, place_map, marker_color='red') # TODO: Should get_timeline_for_trip work on a trip_id or on a trip object # it seems stupid to convert trip object -> id -> trip object curr_trip_timeline = esdt.get_timeline_for_trip(user_id, trip.get_id()) for i, trip_element in enumerate(curr_trip_timeline): # logging.debug("Examining element %s of type %s" % (trip_element, type(trip_element))) if type(trip_element) == ecws.Stop: time_query = esds.get_time_query_for_stop(trip_element.get_id()) logging.debug("time_query for stop %s = %s" % (trip_element, time_query)) stop_points_df = ts.get_data_df("background/filtered_location", time_query) # logging.debug("stop_points_df.head() = %s" % stop_points_df.head()) if len(stop_points_df) > 0: update_line(curr_map, stop_points_df, line_color = sel_color_list[-1], popup="%s -> %s" % (trip_element.enter_fmt_time, trip_element.exit_fmt_time)) else: assert(type(trip_element) == ecwsc.Section) time_query = esdsc.get_time_query_for_section(trip_element.get_id()) logging.debug("time_query for section %s = %s" % (trip_element, "[%s,%s,%s]" % (time_query.timeType, time_query.startTs, time_query.endTs))) section_points_df = ts.get_data_df("background/filtered_location", time_query) logging.debug("section_points_df.tail() = %s" % section_points_df.tail()) if len(section_points_df) > 0: update_line(curr_map, section_points_df, line_color = sel_color_list[trip_element.sensed_mode.value], popup="%s (%s -> %s)" % (trip_element.sensed_mode, trip_element.start_fmt_time, trip_element.end_fmt_time)) else: logging.warn("found no points for section %s" % trip_element) return map_list
def trip_to_geojson(trip, tl): """ Trips are the main focus of our current visualization, so they are most complex. Each trip is represented as a feature collection with the following features: - two features for the start and end places - features for each stop in the trip - features for each section in the trip :param trip: the trip object to be converted :param tl: the timeline used to retrieve related objects :return: the geojson version of the trip """ feature_array = [] curr_start_place = tl.get_object(trip.start_place) curr_end_place = tl.get_object(trip.end_place) start_place_geojson = place_to_geojson(curr_start_place) start_place_geojson["properties"]["feature_type"] = "start_place" feature_array.append(start_place_geojson) end_place_geojson = place_to_geojson(curr_end_place) end_place_geojson["properties"]["feature_type"] = "end_place" feature_array.append(end_place_geojson) trip_tl = esdt.get_timeline_for_trip(trip.user_id, trip.get_id()) stops = trip_tl.places for stop in stops: feature_array.append(stop_to_geojson(stop)) trip_distance = 0 for i, section in enumerate(trip_tl.trips): # TODO: figure out whether we should do this at the model. # The first section starts with the start of the trip. But the trip itself starts at the first # point where we exit the geofence, not at the start place. That is because we don't really know when # we left the start place. We can fix this in the model through interpolation. For now, we assume that the # gap between the real departure time and the time that the trip starts is small, and just combine it here. section_gj = section_to_geojson(section, tl) feature_array.append(section_gj) # import bson.json_util as bju # for f in section_gj.features: # logging.debug("Section has feature %s" % bju.dumps(f)) # TODO: Fix me to use the wrapper section_distance = [f["properties"]["distance"] for f in section_gj.features if f.type == "Feature" and f.geometry.type == "LineString"] logging.debug("found distance %s for section %s" % (section_distance, section.get_id())) trip_distance = trip_distance + sum(section_distance) trip_geojson = gj.FeatureCollection(features=feature_array, properties=trip) trip_geojson.id = str(trip.get_id()) trip_geojson.properties["feature_type"] = "trip" trip_geojson.properties["distance"] = trip_distance return trip_geojson