Esempio n. 1
0
def rectificate_trajectories_network(trajs, eff_target,	G, remove_nodes=False, resample_trajectories=True, **kwargs_rectificate):
	"""
	Wrapper of rectificate_trajectories to use efficiently with a networkx object. 
	Provide default functions to add nodes to network. Resample also the trajectories in the case
	where the 'remove_nodes' mode is chosen. Propagates the kwargs for the rectification.
	Signature of each trajectory : (n).

	Parameters
	----------
	trajs : list 
		of trajectories with signatures (n).
	eff_target : float
		target efficiency.
	G : hybrid network
		The label of the navpoints must be integers.
	remove_nodes : boolean, optional
		if True, remove the chosen nodes from the trajectories. Otherwise, duplicate and move the existing point.
	resample_trajectories : boolean, optional
		If True and remove_nodes is True, the function will recreate navpoint on the trajectories after the 
		rectification procedure so as to have the same number of navpoints than in the original trajectory. 
		The napvoints are equally spaced along the trajectory.
	kwargs_rectificate : additional parameters passed to rectificate_trajectories.
	
	Returns
	--------
	trajs : list 
		of modified trajectories.
	eff : float
		corresponding efficiency.
	G : networkx graph
		with added or removed nodes.
	groups : dictionnary
		the final groups.
	
	Notes
	-----
	TODO: test for DiGraph.
	Remark: The nodes are never removed from the network, only from the trajectories.
	Changed in 1.4: fixed sector allocations of new nodes. Using an hybrid netwrok instead of a navpoint network.
	Changed in 1.4.1: new nodes have sector -1 if they don't fall into any sector (it can happen if the sectors
	are not convex).

	"""

	assert not -10000 in [G.G_nav.node[n]['sec'] for n in G.G_nav.nodes()]

	# Function to get the coordinates of the nodes on the network.
	def get_coords(nvp):
		try:
			pouet = G.G_nav.node[nvp]['coord']
		except:
			print
			print nvp
			print G.G_nav.node[nvp]
			raise
		return G.G_nav.node[nvp]['coord']
		
	def d((n1, n2)):
		p1 = get_coords(n1)
		p2 = get_coords(n2)
		return np.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)

	# Function to get add a node to the network.
	def add_node(trajs, G, coords, f, p):
		# G here is the navpoint network.
		new_node = max(G.nodes())+1
		#G.add_node(new_node, coord=coords, sec=G.node[trajs[f][p-1]]['sec'])
		G.add_node(new_node, coord=coords, sec=-10000)

		weight = G[trajs[f][p-1]][trajs[f][p]]['weight'] * d((trajs[f][p-1], new_node))/d((trajs[f][p-1], trajs[f][p]))
		G.add_edge(trajs[f][p-1], new_node, weight=weight)
		weight = G[trajs[f][p]][trajs[f][p+1]]['weight'] * d((trajs[f][p+1], new_node))/d((trajs[f][p], trajs[f][p+1]))
		G.add_edge(new_node, trajs[f][p+1], weight=weight)
		trajs[f][p] = new_node

		return new_node, trajs, G

	old_max_label = max(G.G_nav.nodes())
	trajs_old = deepcopy(trajs)
	trajs_rec, eff, G.G_nav, groups_rec = rectificate_trajectories(trajs, eff_target, 
																add_node_func=add_node, 
																dist_func=d, 
																coords_func=get_coords,
																G=G.G_nav, 
																#inplace=True,
																remove_nodes=remove_nodes, 
																**kwargs_rectificate)

	if remove_nodes and resample_trajectories: # Resample trajectories.
		for i, traj in enumerate(trajs_rec):
			n_old = len(trajs_old[i])
			n_new = len(traj)
			n_gen = n_old - n_new

			# Compute linear distance after each point.
			long_dis, long_dis_cul = build_long_2d([G.G_nav.node[n]['coord'] for n in traj]) 
			long_dis, long_dis_cul = np.array(long_dis), np.array(long_dis_cul)

			# Equally spaced points along the trajectory.
			long_dis_new_points = [(j+1.)*(long_dis_cul[-1]-long_dis_cul[0])/float(n_gen+1.) for j in range(n_gen)] 
			
			new_point_coords = []
			new_point_indices = []
			for dd in long_dis_new_points:
				point_before = len(long_dis_cul[dd>long_dis_cul])-1#.index(True) # Index of point before future point

				dn = np.array(get_coords(traj[point_before+1])) - np.array(get_coords(traj[point_before])) # direction vector
				dn = dn/np.sqrt(sum(dn**2))#np.norm(dn)
				new_point_coords.append(list(np.array(get_coords(traj[point_before])) + (dd-long_dis_cul[point_before])*dn))
				new_point_indices.append(point_before)

			# Names (indices) of new navpoint in the network
			names = [max(G.G_nav.nodes()) + 1 + j for j in range(len(new_point_indices))]

			traj_rec_without_new_points = deepcopy(trajs_rec[i])
			trajs_rec[i] = insert_list_in_list(trajs_rec[i], names, new_point_indices)

			# First add all new nodes to network
			for j, name in enumerate(names):
				# TODO: do this more carefully.
				# if 'sec' in G.G_nav.node[traj_rec_without_new_points[new_point_indices[j]]].keys():
				#	sec = G.G_nav.node[traj_rec_without_new_points[new_point_indices[j]]]['sec']
				#else:
				#	sec = 0	
				G.G_nav.add_node(name, coord=new_point_coords[j], sec=-10000)

			# Then add all edges
			for j in range(len(trajs_rec[i])-1):
				if not trajs_rec[i][j+1] in G.G_nav.neighbors(trajs_rec[i][j]):
					# TODO: improve this?
					ref_point_bef = trajs_old[i][0]
					ref_point_aft = trajs_old[i][1]
					scale_weight = G.G_nav[ref_point_bef][ref_point_aft]['weight']/d((ref_point_bef, ref_point_aft))

					name_pt_bef = trajs_rec[i][j]


					weight = scale_weight * d((trajs_rec[i][j], trajs_rec[i][j+1]))
					G.G_nav.add_edge(trajs_rec[i][j], trajs_rec[i][j+1], weight=weight)

			# Check that all consecutive points of the trajectory are neighbors in the network
			for j in range(len(trajs_rec[i])-1):
				try:
					assert trajs_rec[i][j+1] in G.G_nav.neighbors(trajs_rec[i][j])
				except AssertionError:
					print trajs_rec[i][j], trajs_rec[i][j+1]
					raise

	# Find the sector containing the new nodes
	for n in G.G_nav.nodes():
		if n>old_max_label:
			sec = find_sector(n, G)

			if sec==None:
				G.G_nav.node[n]['sec'] = -1
				#print n, G.G_nav.node[n]
				#raise Exception()
			else:
				G.G_nav.node[n]['sec'] = sec
				G.node[sec]['navs'].append(n)

	return trajs_rec, eff, G, groups_rec
Esempio n. 2
0
def rectificate_trajectories_network_with_time_and_alt(trajs_w_t, eff_target, G, remove_nodes=False, 
	resample_trajectories=True, **kwargs_rectificate):
	"""
	Same than rectificate_trajectories_network_with_time, but recomputes altitudes with linear interpolation.

	Parameters
	----------
	trajs_w_t : list 
		of trajectories with signatures (n, z), t
	eff_target : float
		target efficiency.
	G : hybrid network
	remove_nodes : boolean, optional
		if True, remove the chosen nodes from the trajectories. Otherwise, duplicate and move the existing point.
	resample_trajectories : boolean, optional
		If True and remove_nodes is True, the function will recreate navpoint on the trajectories after the 
		rectification procedure so as to have the same number of navpoints than in the original trajectory. 
		The napvoints are equally spaced along the trajectory.
	kwargs_rectificate : additional parameters passed to rectificate_trajectories.

	Returns
	--------
	trajs : list 
		of modified trajectories with signature (n, z), t
	eff : float
		corresponding efficiency.
	G : networkx graph
		with added or removed nodes.
	groups : dictionnary
		the final groups.

	"""

	# Compute geometrical trajectories (with altitudes)
	geom_trajs_alt, start_dates = zip(*trajs_w_t)
	#geom_trajs_alt = list(geom_trajs)
	geom_trajs, alts = [], []
	for traj in geom_trajs_alt:
		g_t, alt = zip(*traj)
		geom_trajs.append(list(g_t))
		alts.append(list(alt))

	# Rectificate geometrical trajectories
	G_old = deepcopy(G)
	trajs_rec, eff, G, groups_rec = rectificate_trajectories_network(geom_trajs, eff_target, G, remove_nodes=remove_nodes, resample_trajectories=resample_trajectories, **kwargs_rectificate)

	# Recompute altitudes
	for i, traj_new in enumerate(trajs_rec):
		traj_old = geom_trajs[i]
		long_dis, long_dis_cul_old = build_long_2d([G_old.G_nav.node[n]['coord'] for n in traj_old]) 
		long_dis_cul_old = np.array(long_dis_cul_old)
		alt = alts[i]

		long_dis, long_dis_cul = build_long_2d([G.G_nav.node[n]['coord'] for n in traj_new]) 
		long_dis_cul = np.array(long_dis_cul)
		
		f_inter = return_linear_interpolation_altitude_func(long_dis_cul_old, alt)

		new_alt = [f_inter(d*long_dis_cul_old[-1]/long_dis_cul[-1]) for d in long_dis_cul]

		trajs_rec[i] = list(zip(traj_new, new_alt))

	# Put back the starting date.
	trajs_rec_w_t = list(zip(trajs_rec, start_dates))

	return trajs_rec_w_t, eff, G, groups_rec