def Laplace_Beltrami_Operator(file_name=default_VTK, which='norm1', kernel=cotangent_kernel, sigma=10, components=200, export=True, return_header=False):
	""" Laplace_Beltrami_Operator."""
	
	##############################################################
	##### Extract Nodes and Meshes from VTK file: 
	
	Data = pyvtk.VtkData(file_name)
	Nodes = np.asarray(Data.structure.points)
	Meshes = np.asarray(Data.structure.polygons)
	
	##############################################################
	##### Compute Weight Matrix:
	
	t0 = time()
	aff_mat = compute_weights(Nodes, Meshes, kernel=kernel, add_to_graph=False, sigma=sigma)
	print("done in %0.3fs" % (time() - t0))

	##############################################################
	##### Compute Graph Laplacian:

	t0 = time()
	Laplacian = graph_laplacian(aff_mat, which=which)
	print("done in %0.3fs" % (time() - t0))

	##############################################################
	##### Obtain Eigen Spectrum:
	
	print 'Finding the eigen spectrum...'
	t0 = time()
	Laplacian = Laplacian.tocsc()
	if components >= Nodes.shape[0]:
		components = Nodes.shape[0] - 1
	evals, evecs = eigsh(Laplacian, components, sigma=0)
	print("done in %0.3fs" % (time() - t0))
	
	if export:
		file_name2 = file_name[:-4] + '.npy'
		h = open(file_name2, 'w')
		pickle.dump(evals, h)
		h.close()

	################################################################
	##### Write New VTK File With Feidler Vector Overlayed On Brain:
	
	# f = vo.write_all(file_name[:-4]+'_eigen.vtk', Nodes, Meshes, evecs[:,1], label_type='Eigenvector')

	#################################################################
	##### Return Results:
	
	if return_header:
		return Nodes, Meshes, aff_mat, Laplacian, evals, evecs, Data.header
	else:
		return Nodes, Meshes, aff_mat, Laplacian, evals, evecs
def LabelPropagation(VTK = default_VTK, fundi_file = default_fundi_file, algorithm=default_algorithm, kernel=default_kernel, sigma=default_sigma, alpha=default_alpha, diagonal=0, 
					 repeat=default_repeat, max_iters=3000, tol=1e-3, eps=1e-7):
	"""
	Main Function: Propagates labels to unlabeled nodes in graph.
	
	Input: 	VTK file containing:
				n x 3 Matrix X of 3-dimensional nodes.
					n = l + u: l labeled nodes, u unlabeled nodes
				m x 3 Matrix M of triangular meshes.
				n x 1 Array of C unique labels.
					C = number of classes
					0 = no label
				
	Output:	Graph G with n labeled nodes along with probabilities.
 	
	Parameters
	----------
	kernel: function (x1, x2) --> float
		choice of similarity metric
	sigma: float
		parameter for gaussian (rbf) kernel
	
	alpha: float
		clamping factor
	
	diagonal: float
		choice of diagonal entries in weight matrix
	
	max_iters: float
		maximum number of iterations allowed
	tol: float
		threshold to consider the system at steady state
		
	eps: float
		epsilon value for numerical stability in some algorithms.
	"""
	
	Nodes = Meshes = Labels = A = 0
	
	# Step 0. Convert VTK file into numpy matrices
	Data = pyvtk.VtkData(VTK)
	Nodes = Data.structure.points
	Meshes = Data.structure.polygons
	
	data = convert_vtk_to_matrix(VTK, fundi_file)
	
	# Step 1. Transform input data into graph G_basic
	G_basic = build_graph(data['Nodes'])

	# Step 2. Compute edge weights using connectivity established in VTK file
	(G, aff_mat) = compute_weights(data['Nodes'], data['Meshes'], kernel, G=G_basic, sigma=sigma)
	aff_mat = aff_mat.tocsr()
	
	# Step 3. Transform column of labels into L x C Matrix, one column per class
	(Label_Matrix, label_mapping) = get_label_matrix(data['Fundi_Labels'])

	# Step 4. Propagate Labels! 
	if algorithm == "Weighted_Average":
		print 'Performing Weighted Average Algorithm! Parameters: max_iters={0}'.format(str(max_iters))
		(Graph, best_guess) = weighted_average(G, Label_Matrix, aff_mat, label_mapping, data['num_changed'],
								 repeat, diagonal, max_iters, tol)
	elif algorithm == "Label_Spreading":
		print 'Performing Label Spreading Algorithm! Parameters: alpha={0}, max_iters={1}'.format(str(alpha), str(max_iters))
		Graph = label_spreading(G, Label_Matrix, aff_mat, label_mapping, data['num_changed'],
							    repeat, alpha, max_iters, tol)
	elif algorithm == "Label_Propagation":
		Graph = label_propagation(G, Label_Matrix, aff_mat, label_mapping, data['num_changed'],
							 	  repeat, alpha, eps, max_iters, tol)
	elif algorithm == "Nearest_Neighbor":
		print 'Performing 1_nearest_neighbor algorithm!'
		Graph = nearest_neighbor(G, Label_Matrix, label_mapping)
	else:
		Graph = "That algorithm is not available."		

	# Step 5. Assess success of algorithm:
	results = assess(Graph, data['Manual_Labels'], data['num_changed'], data['preserved_labels'], best_guess, label_mapping)
	
	h = open('/home/eli/Desktop/NewLabels.vtk', 'w')
	line_num = 0
	total_lines_to_copy = 9 + data['Nodes'].shape[0] + data['Meshes'].shape[0] 
	for line in data['main_file']:
		if line_num < total_lines_to_copy:
			h.write(line)
			line_num += 1
	for i in xrange(len(Graph.nodes())):
		h.write('{0}\n'.format(str(results[i])))
	
	h.close()
		
	return Graph, results