Function returns the minimum number of connections, k, that are required to form a fully connected graph based gene expression data
    :param traj_exp: ndarray representing gene expression
    :return k: int of the minimum number of connections needed for a minimally connected graph

def min_conn_k(traj_exp):
    '''
    Function returns the minimum number of connections, k, that are required to form a fully connected graph based gene expression data
    :param traj_exp: ndarray representing gene expression
    :return k: int of the minimum number of connections needed for a minimally connected graph
    '''
    traj_dist=sps.distance.squareform(sps.distance.pdist(traj_exp)) #this is the gene expression euclidean distance calculation
    conn_comp=2 #just a starting value for the number of connected components in the graph
    k=0 #just a starting value for the number of neighbors required in the graph
    while (conn_comp>1):
        k=k+1 #each time this loops, increase the number of neighbors by 1 until we get 1 graph component(indicating a fully connected graph)
        adj_mat=adaptive_knn_graph(traj_dist,k) #uses adaptive_knn_graph to generate an adjacency matrix
        traj_graph = nx.Graph(adj_mat) #uses that adjacency matrix to make a graph
        conn_comp = nx.number_connected_components(traj_graph) #count the number of connected components in that graph
    return k