Wrapper function to perform neighborhood variance based feature selection, will throw error if input is not ndarray
    :param embedding: ndarray representing gene expression, consists of cells as rows and genes as columns
    :return genes_mat: ndarray of selected genes

def select_genes(embedding):
    '''
    Wrapper function to perform neighborhood variance based feature selection, will throw error if input is not ndarray
    :param embedding: ndarray representing gene expression, consists of cells as rows and genes as columns
    :return genes_mat: ndarray of selected genes
    '''
    if not ( isinstance( embedding, np.ndarray)):
        raise TypeError( 'data variable must be numpy ndarray')
    print ("Start min_conn_k")
    start=time.time() #just start a timer to see how long this whole thing takes in seconds
    k = min_conn_k(embedding) #run the min_conn_k to find k
    print (k, "connections needed") #prints the k for reference
    print ("Finished min_conn_k ")
    r = embedding.shape[0]
    c = embedding.shape[1]
    print ("Start traj_dist")
    traj_dist = sps.distance.squareform(sps.distance.pdist(embedding)) #distance calculation to use in making the adjacency matrix
    print ("Finished traj_dist")
    print ("Start adaptive_knn_graph")
    adj_mat = adaptive_knn_graph(traj_dist,k) #use traj_dist to make adjacency matrix
    print ("Finished adaptive_knn_graph")
    sel_vals = selection_val(embedding,adj_mat) #calculate selection values, or the ratios of global variance to neighborhood variance
    print ("Finished selection_val") 
    genes = np.where(sel_vals > 1) #decision made here, if neighborhood variance is lower than global, select that gene
    print ("Finished gene selection in",time.time()-start, "seconds") 
    #genes_mat = np.asmatrix(genes) #output of genes as a matrix
    print ("done")
    return np.squeeze( genes)