Example #1
0
	def identify_locations(self):
		"""Identify locations with user-provided home, work, school locations if 
			possible."""
		# TODO this function was written in a hurry and should be made more robust
		if self.home:
			for location in self.locations:
				if distance( location, self.home ) <= 150: # meters 
					location.identify('home')
		if self.work:
			for location in self.locations:
				if distance( location, self.work ) <= 150: # meters 
					location.identify('work')
		if self.school:
			for location in self.locations:
				if distance( location, self.school ) <= 150: # meters 
					location.identify('school')
Example #2
0
	def observe_neighbors(self,indices=[]):
		"""Get angle and distance measurements to and from adjacent points.
			Store in the point object. Operates on points, the inices of which 
			are given in a list referring to the current point list."""
		# for each point, except those first and last
		for i in indices:
			# skip first and last points
			if i <= 0 or i >= len(self.points)-1: 
				continue
			point = self.points[i]
			# Find the nearest DIFFERENT geometries
			# first walk backwards to the next different point
			i_ante = i-1
			while point.geom == self.points[i_ante].geom:
				if i_ante <= 0: break
				i_ante -= 1
			# then forward to the next different point
			i_post = i+1
			while point.geom == self.points[i_post].geom:
				if i_post >= len(self.points)-1: break
				i_post += 1
			# distance to previous point
			point.d_ante = distance(point,self.points[i_ante])
			# distance to next point
			point.d_post = distance(point,self.points[i_post])
			# if either distance is zero, this is an end point and has no angle
			if point.d_ante * point.d_post == 0:
				point.angle = 180 
			else:
				# calculate the inner angle
				point.angle = inner_angle_sphere( self.points[i_ante], point, self.points[i_post] )
			# is point is identical with both neighbors?
			if (
				point.geom == self.points[i-1].geom and 
				point.geom == self.points[i+1].geom 
			): 
				point.inter = True
Example #3
0
	def pair_interpolation(self, other_point):
		"""Given this and one other Point object, attempts to supply a list of 
			interpolated points between the two such that gaps between the points 
			are never greater than config.interpolation_distance."""
		new_points = [self.copy()] # Why is this copied?
		dist = distance(self, other_point)
		if dist > config.interpolation_distance:
			time_dif = (other_point.time - self.time).seconds
			n_segs = ceil( dist / config.interpolation_distance )
			seg_len = dist // n_segs
			x1, y1 = project(self.longitude, self.latitude)
			x2, y2 = project(other_point.longitude, other_point.latitude)
			dx, dy = (x2 - x1)/n_segs, (y2 - y1)/n_segs
			dt = time_dif / n_segs
			for np in range(1, n_segs):
				x0, y0 = x1 + np*dx, y1 + np*dy
				lng, lat = unproject(x0, y0)
				tstamp = self.time + timedelta(seconds=dt*np)
				ts = ts_str(tstamp, self.ts[-5:])
				new_points.append(Point(ts, lng, lat, self.accuracy))
		return new_points
Example #4
0
	def make_known_subsets(self):
		"""Partition the trace points into sets for which we're confident 
			we don't have substantial missing data. That is, exclude segments 
			where it seems like we have no data, but substantial movement; for 
			which trip and activity reconstruction would be impossible.
			TODO: Eventually we will need some much stricter checking here 
			and eventually an explicit check foro subway trips."""
		known_segments = []
		segment = [ self.points[0] ]
		# iterate over all points (except the first). Test each point to see 
		# whether we add it to the current segment or the one after.
		for i in range(1,len(self.points)):
			if ( 
				# distance over 1 km?
				distance( self.points[i], self.points[i-1] ) > 1000 and
				# time gap > 2 hours?
				self.points[i].epoch - self.points[i-1].epoch > 1*3600
			):
				# append point to next segment
				known_segments.append( segment )
				segment = [ self.points[i] ]
			else:
				# add this point to the current segment
				segment.append( self.points[i] )
		if len(segment) > 1:
			known_segments.append( segment )
		# check these segments for plausibility and append to the global property
		for segment in known_segments:
			if (
				# at least one point
				len(segment) > 1 and
				# sufficient time between last and first points
				segment[-1].epoch - segment[0].epoch > 3600
			): # mininum time length of segment?
				self.known_subsets.append(segment)
		print( '\t',len(self.known_subsets)-1,'gap(s) found in data' )
Example #5
0
	def break_trips(self):
		"""Use a Hidden Markov Model to classify all points as deriving from 
			either time spent travelling or time spent at one of the potential 
			activity locations. Allocate time to these sequences of activities 
			accordingly."""
		for point in self.all_interpolated_points:
			# get first-pass emission probabilities from all locations 
			dists = [ distance(loc,point) for loc in self.locations ]
			dists = [ d - 100 for d in dists ]
			dists = [ 0 if d < 0 else d for d in dists ]
			point.emit_p = [ gaussian(d,100) for d in dists ]
			# standardize to one if necessary
			if sum(point.emit_p) > 1:
				point.emit_p = [ p / sum(point.emit_p) for p in point.emit_p ]
			# prepend travel probability as the difference from 1 if there is any
			point.emit_p = [1 - sum(point.emit_p)] + point.emit_p
		# make a list of starting probabilities (50/50 start travelling, start stationary)
		start_p = [0.5]+[(0.5/len(self.locations))]*len(self.locations)
		# get list of potential state indices
		# 0 is travel, others are then +1 from their list location
		states = range(0,len(self.locations)+1)
		# list of locations that actually get used
		used_locations = set()
		# simple transition probability matrix e.g.:
		#     0   1   2	
		# 0  .8  .1  .1
		# 1  .2  .8  .0
		# 2  .2  .0  .8
		trans_p = []
		for s0 in states:
			trans_p.append([])
			for s1 in states:
				if s0 + s1 == 0: # travel -> travel
					trans_p[s0].append( 0.8 )
				elif s0 == 0: # travel -> place
					trans_p[s0].append( 0.2 / len(self.locations) )
				elif s1 == 0: # place -> travel
					trans_p[s0].append( 0.2 )
				elif s0 == s1: # place -> same place
					trans_p[s0].append( 0.8 )
				else: # place -> place (no travel)
					trans_p[s0].append( 0.0 ) 
		# run the viterbi algorithm on each known subset 
		for points in self.known_subsets_interpolated:
			# VITERBI ALGORITHM
			V = [{}]
			path = {}
			for state in states:
				# Initialize base cases (t == 0)
				V[0][state] = start_p[state] * points[0].emit_p[state]
				path[state] = [state]
			for t in range(1,len(points)):	# Run Viterbi for t > 0
				V.append({})
				newpath = {}
				for s1 in states:
					(prob, state) = max(
						[ ( V[t-1][s0] * trans_p[s0][s1] * points[t].emit_p[s1], s0 ) for s0 in states ]
					)
					V[t][s1] = prob
					newpath[s1] = path[state] + [s1]
				path = newpath	# Don't need to remember the old paths
			(prob, final_state) = max( [ (V[len(points)-1][s], s) for s in states ] )
			# get the optimal sequence of states
			state_path = path[final_state]
			# note which locations have been used TODO move this elsewhere
			for visited_id in set([s-1 for s in state_path if s != 0]):
				self.locations[visited_id].visited = True
			# now record the first activity episode
			self.episodes.append( Episode( 
				points[0].time, # start_time
				# location, if any
				None if state_path[0] == 0 else self.locations[state_path[0]-1],
				False # unknown_time
			) )
			prev_state = state_path[0]
			start_time = points[0].epoch
			# for each point after the first
			for i in range(1,len(state_path)):
				# look for state changes
				if prev_state != state_path[i]:
					# assume the transition happens halfway between points
					transition_time = points[i-1].time + (points[i].time-points[i-1].time)/2
					# output start of this new state
					# now record the first activity episode
					self.episodes.append( Episode( 
						points[i].time, # start_time
						# location, if any
						None if state_path[i] == 0 else self.locations[state_path[i]-1],
						False # unknown_time
					) )
					prev_state = state_path[i]
			# now record the first activity episode
			self.episodes.append( Episode( 
				points[-1].time,	# start_time				
				None,	# no location,
				True	# unknown time ends every segment
			) )
		print( '\tFound',len(self.episodes),'activities/trips' )