Esempio n. 1
0
def test_bundles_distances_mdf():
    xyz1A = np.array([[0,0,0],[1,0,0],[2,0,0]],dtype='float32')
    xyz2A = np.array([[0,1,1],[1,0,1],[2,3,-2]],dtype='float32')
    xyz1B = np.array([[-1,0,0],[2,0,0],[2,3,0]],dtype='float32')
    tracksA = [xyz1A,xyz2A]
    tracksB = [xyz1B, xyz1A, xyz2A]           
    DM2 = pf.bundles_distances_mdf(tracksA, tracksB)
Esempio n. 2
0
def count_close_tracks(sla, slb, dist_thr=20):
    cnt_a_close = np.zeros(len(slb))
    for ta in sla:
        dta = bundles_distances_mdf([ta], slb)[0]
        # dta = bundles_distances_mam([ta],slb)[0]
        cnt_a_close += binarise(dta, dist_thr)
    return cnt_a_close
Esempio n. 3
0
def show_coverage(C1,C2):
    vs1,ls1,tot1=bring_virtuals(C1)
    vs2,ls2,tot2=bring_virtuals(C2)
    d12=bundles_distances_mdf(vs1,vs2)
    nfa,nfb = nearest_fraction(d12,4.)
    cfa,cfb = cover_fraction(d12,ls1,ls2,4.,1,1)
    print "nf %6.1f %6.1f cf %6.1f %6.1f" % (100*nfa,100*nfb,100*cfa,100*cfb)    
    return d12
Esempio n. 4
0
    def _reduce_search_space(self, model_centroids,
                             reduction_thr=20, reduction_distance='mdf'):
        if self.verbose:
            t = time()
            print('# Reduce search space')
            print(' Reduction threshold %0.3f' % (reduction_thr,))
            print(' Reduction distance {}'.format(reduction_distance))

        if reduction_distance.lower() == 'mdf':
            if self.verbose:
                print(' Using MDF')
            centroid_matrix = bundles_distances_mdf(model_centroids,
                                                    self.centroids)
        elif reduction_distance.lower() == 'mam':
            if self.verbose:
                print(' Using MAM')
            centroid_matrix = bundles_distances_mdf(model_centroids,
                                                    self.centroids)
        else:
            raise ValueError('Given reduction distance not known')

        centroid_matrix[centroid_matrix > reduction_thr] = np.inf

        mins = np.min(centroid_matrix, axis=0)
        close_clusters_indices = list(np.where(mins != np.inf)[0])

        close_clusters = self.cluster_map[close_clusters_indices]

        neighb_indices = [cluster.indices for cluster in close_clusters]

        neighb_streamlines = Streamlines(chain(*close_clusters))

        nb_neighb_streamlines = len(neighb_streamlines)

        if nb_neighb_streamlines == 0:
            print(' You have no neighbor streamlines... No bundle recognition')
            return Streamlines([]), []

        if self.verbose:
            print(' Number of neighbor streamlines %d' %
                  (nb_neighb_streamlines,))
            print(' Duration %0.3f sec. \n' % (time() - t,))

        return neighb_streamlines, neighb_indices
def auto_extract(model_cluster_map, submission_cluster_map,
                 number_pts_per_str=NB_POINTS_RESAMPLE,
                 close_centroids_thr=20,
                 clean_thr=7.):

    model_centroids = model_cluster_map.centroids

    centroid_matrix = bundles_distances_mdf(model_centroids,
                                            submission_cluster_map.centroids)

    centroid_matrix[centroid_matrix > close_centroids_thr] = np.inf
    mins = np.min(centroid_matrix, axis=0)
    close_clusters = [submission_cluster_map[i]
                      for i in np.where(mins != np.inf)[0]]
    close_indices_inter = [submission_cluster_map[i].indices
                           for i in np.where(mins != np.inf)[0]]
    close_indices = list(chain.from_iterable(close_indices_inter))

    close_streamlines = list(chain(*close_clusters))
    closer_streamlines = close_streamlines

    rcloser_streamlines = set_number_of_points(closer_streamlines,
                                               number_pts_per_str)

    clean_matrix = bundles_distances_mdf(model_cluster_map.refdata,
                                         rcloser_streamlines)

    clean_matrix[clean_matrix > clean_thr] = np.inf

    mins = np.min(clean_matrix, axis=0)

    clean_indices = [i for i in np.where(mins != np.inf)[0]]

    # Clean indices refer to the streamlines in closer_streamlines,
    # which are the same as the close_streamlines. Each close_streamline
    # has a related element in close_indices, for which the value
    # is the index of the original streamline in the moved_streamlines.
    final_selected_indices = [close_indices[idx] for idx in clean_indices]

    return final_selected_indices
Esempio n. 6
0
def test_bundles_distances_mdf():
    xyz1A = np.array([[0,0,0],[1,0,0],[2,0,0]],dtype='float32')    
    xyz2A = np.array([[0,1,1],[1,0,1],[2,3,-2]],dtype='float32')
    xyz3A = np.array([[0,0,0],[1,0,0],[3,0,0]],dtype='float32')    
    xyz1B = np.array([[-1,0,0],[2,0,0],[2,3,0]],dtype='float32')
       
    tracksA = [xyz1A,xyz2A]
    tracksB = [xyz1B, xyz1A, xyz2A]           
    DM2 = pf.bundles_distances_mdf(tracksA, tracksB)
    
    tracksA = [xyz1A,xyz1A]
    tracksB = [xyz1A,xyz1A]
    
    DM2 = pf.bundles_distances_mdf(tracksA, tracksB)
    assert_array_almost_equal(DM2,np.zeros((2,2)))
    
    tracksA = [xyz1A,xyz3A]
    tracksB = [xyz2A]
    
    DM2 = pf.bundles_distances_mdf(tracksA, tracksB)
    print(DM2)
        
    #assert_array_almost_equal(DM2,np.zeros((2,2)))    
    DM=np.zeros(DM2.shape)
    for (a,ta) in enumerate(tracksA):
        for (b,tb) in enumerate(tracksB):
            md=np.sum(np.sqrt(np.sum((ta-tb)**2,axis=1)))/3.
            md2=np.sum(np.sqrt(np.sum((ta-tb[::-1])**2,axis=1)))/3.
            DM[a,b]=np.min((md,md2))
    print(DM)
    
    print('--------------')
    for t in tracksA:
        print(t)
    print('--------------')
    for t in tracksB:
        print(t)
        
    assert_array_almost_equal(DM,DM2,4)
Esempio n. 7
0
 def exemplars(self,tracks=None):
     if self.exemps==None:            
         self.exemps=[]
         self.exempsi=[]
         C=self.clustering
         if tracks==None:
             tracks=self.tracksd            
         for c in C:
             cluster=[tracks[i] for i in C[c]['indices']]                
             D=bundles_distances_mdf([C[c]['hidden']/float(C[c]['N'])],cluster)
             D=D.ravel()
             si=np.argmin(D)
             self.exempsi.append(si)
             self.exemps.append(cluster[si])                               
     return self.exemps, self.exempsi
Esempio n. 8
0
def find_matches():
    
    fsolid='/home/ian/Data/LSC_stability/solid_1M.npy'
    T=np.load(fsolid)

    samplesize = 10**3
    lscdist = 4.
    labels1 = np.arange(0*samplesize,1*samplesize)
    T1=T[labels1]
    C1=local_skeleton_clustering(T1,lscdist)

    labels2 = np.arange(1*samplesize,2*samplesize)
    T2=T[labels2]
    C2=local_skeleton_clustering(T2,lscdist)

    v1,l1,tot1 = bring_virtuals(C1)
    v2,l2,tot2 = bring_virtuals(C2)

    d12 = bundles_distances_mdf(v1,v2)        

    mv21 = np.argmin(d12,axis=0)
    
    print mv21[0], C2[0]['indices'], C1[mv21[0]]['indices']
Esempio n. 9
0
def bundle_adjacency(dtracks0, dtracks1, threshold):
    """ Find bundle adjacency between two given tracks/bundles

    Parameters
        ----------
        dtracks0 : Streamlines
        dtracks1 : Streamlines
        threshold: float
    References
    ----------
    .. [Garyfallidis12] Garyfallidis E. et al., QuickBundles a method for
                        tractography simplification, Frontiers in Neuroscience,
                        vol 6, no 175, 2012.
    """
    d01 = bundles_distances_mdf(dtracks0, dtracks1)

    pair12 = []

    for i in range(len(dtracks0)):
        if np.min(d01[i, :]) < threshold:
            j = np.argmin(d01[i, :])
            pair12.append((i, j))

    pair12 = np.array(pair12)
    pair21 = []

    # solo2 = []
    for i in range(len(dtracks1)):
        if np.min(d01[:, i]) < threshold:
            j = np.argmin(d01[:, i])
            pair21.append((i, j))

    pair21 = np.array(pair21)
    A = len(pair12) / np.float(len(dtracks0))
    B = len(pair21) / np.float(len(dtracks1))
    res = 0.5 * (A + B)
    return res
Esempio n. 10
0
    def _prune_what_not_in_model(self, model_centroids,
                                 transf_streamlines,
                                 neighb_indices,
                                 mdf_thr=5,
                                 pruning_thr=10,
                                 pruning_distance='mdf'):

        if pruning_thr < 0:
            print('Pruning_thr has to be greater or equal to 0')

        if self.verbose:
            print('# Prune streamlines using the MDF distance')
            print(' Pruning threshold %0.3f' % (pruning_thr,))
            print(' Pruning distance {}'.format(pruning_distance))
            t = time()

        thresholds = [40, 30, 20, 10, mdf_thr]
        rtransf_cluster_map = qbx_and_merge(transf_streamlines,
                                            thresholds, nb_pts=20,
                                            select_randomly=500000,
                                            rng=self.rng,
                                            verbose=self.verbose)

        if self.verbose:
            print(' QB Duration %0.3f sec. \n' % (time() - t, ))

        rtransf_centroids = rtransf_cluster_map.centroids

        if pruning_distance.lower() == 'mdf':
            if self.verbose:
                print(' Using MDF')
            dist_matrix = bundles_distances_mdf(model_centroids,
                                                rtransf_centroids)
        elif pruning_distance.lower() == 'mam':
            if self.verbose:
                print(' Using MAM')
            dist_matrix = bundles_distances_mam(model_centroids,
                                                rtransf_centroids)
        else:
            raise ValueError('Given pruning distance is not available')
        dist_matrix[np.isnan(dist_matrix)] = np.inf
        dist_matrix[dist_matrix > pruning_thr] = np.inf

        pruning_matrix = dist_matrix.copy()

        if self.verbose:
            print(' Pruning matrix size is (%d, %d)'
                  % pruning_matrix.shape)

        mins = np.min(pruning_matrix, axis=0)
        pruned_indices = [rtransf_cluster_map[i].indices
                          for i in np.where(mins != np.inf)[0]]
        pruned_indices = list(chain(*pruned_indices))
        pruned_streamlines = transf_streamlines[np.array(pruned_indices)]

        initial_indices = list(chain(*neighb_indices))
        final_indices = [initial_indices[i] for i in pruned_indices]
        labels = final_indices

        if self.verbose:
            msg = ' Number of centroids: %d'
            print(msg % (len(rtransf_centroids),))
            msg = ' Number of streamlines after pruning: %d'
            print(msg % (len(pruned_streamlines),))

        if len(pruned_streamlines) == 0:
            print(' You have removed all streamlines')
            return Streamlines([]), []

        if self.verbose:
            print(' Duration %0.3f sec. \n' % (time() - t, ))

        return pruned_streamlines, labels
Esempio n. 11
0
    def _prune_what_not_in_model(self,
                                 model_centroids,
                                 transf_streamlines,
                                 neighb_indices,
                                 mdf_thr=5,
                                 pruning_thr=10,
                                 pruning_distance='mdf'):
        if self.verbose:
            if pruning_thr < 0:
                logger.info('Pruning_thr has to be greater or equal to 0')

            logger.info('# Prune streamlines using the MDF distance')
            logger.info(' Pruning threshold %0.3f' % (pruning_thr, ))
            logger.info(' Pruning distance {}'.format(pruning_distance))
            t = time()

        thresholds = [40, 30, 20, 10, mdf_thr]
        rtransf_cluster_map = qbx_and_merge(transf_streamlines,
                                            thresholds,
                                            nb_pts=20,
                                            select_randomly=500000,
                                            rng=self.rng)
        if self.verbose:
            logger.info(' QB Duration %0.3f sec. \n' % (time() - t, ))

        rtransf_centroids = rtransf_cluster_map.centroids

        if pruning_distance.lower() == 'mdf':
            if self.verbose:
                logger.info(' Using MDF')
            dist_matrix = bundles_distances_mdf(model_centroids,
                                                rtransf_centroids)
        elif pruning_distance.lower() == 'mam':
            if self.verbose:
                logger.info(' Using MAM')
            dist_matrix = bundles_distances_mam(model_centroids,
                                                rtransf_centroids)
        else:
            raise ValueError('Given pruning distance is not available')
        dist_matrix[np.isnan(dist_matrix)] = np.inf
        dist_matrix[dist_matrix > pruning_thr] = np.inf

        pruning_matrix = dist_matrix.copy()
        if self.verbose:
            logger.info(' Pruning matrix size is (%d, %d)' %
                        pruning_matrix.shape)

        mins = np.min(pruning_matrix, axis=0)
        pruned_indices = [
            rtransf_cluster_map[i].indices for i in np.where(mins != np.inf)[0]
        ]
        pruned_indices = list(chain(*pruned_indices))
        idx = np.array(pruned_indices)
        if len(idx) == 0:
            if self.verbose:
                logger.info(' You have removed all streamlines')
            return Streamlines([]), []

        pruned_streamlines = transf_streamlines[idx]

        initial_indices = list(chain(*neighb_indices))
        final_indices = [initial_indices[i] for i in pruned_indices]
        labels = final_indices
        if self.verbose:
            msg = ' Number of centroids: %d'
            logger.info(msg % (len(rtransf_centroids), ))
            msg = ' Number of streamlines after pruning: %d'
            logger.info(msg % (len(pruned_streamlines), ))
            logger.info(' Duration %0.3f sec. \n' % (time() - t, ))

        return pruned_streamlines, labels
Esempio n. 12
0
def cluster_confidence(streamlines,
                       max_mdf=5,
                       subsample=12,
                       power=1,
                       override=False):
    """ Computes the cluster confidence index (cci), which is an
    estimation of the support a set of streamlines gives to
    a particular pathway.

    Ex: A single streamline with no others in the dataset
    following a similar pathway has a low cci. A streamline
    in a bundle of 100 streamlines that follow similar
    pathways has a high cci.

    See: Jordan et al. 2017
    (Based on streamline MDF distance from Garyfallidis et al. 2012)

    Parameters
    ----------
    streamlines : list of 2D (N, 3) arrays
        A sequence of streamlines of length N (# streamlines)
    max_mdf : int
        The maximum MDF distance (mm) that will be considered a
        "supporting" streamline and included in cci calculation
    subsample: int
        The number of points that are considered for each streamline
        in the calculation. To save on calculation time, each
        streamline is subsampled to subsampleN points.
    power: int
        The power to which the MDF distance for each streamline
        will be raised to determine how much it contributes to
        the cci. High values of power make the contribution value
        degrade much faster. E.g., a streamline with 5mm MDF
        similarity contributes 1/5 to the cci if power is 1, but
        only contributes 1/5^2 = 1/25 if power is 2.
    override: bool, False by default
        override means that the cci calculation will still occur even
        though there are short streamlines in the dataset that may alter
        expected behaviour.

    Returns
    -------
    Returns an array of CCI scores

    References
    ----------
    [Jordan17] Jordan K. Et al., Cluster Confidence Index: A Streamline-Wise
    Pathway Reproducibility Metric for Diffusion-Weighted MRI Tractography,
    Journal of Neuroimaging, vol 28, no 1, 2017.

    [Garyfallidis12] Garyfallidis E. et al., QuickBundles a method for
    tractography simplification, Frontiers in Neuroscience,
    vol 6, no 175, 2012.

    """

    # error if any streamlines are shorter than 20mm
    lengths = list(length(streamlines))
    if min(lengths) < 20 and not override:
        raise ValueError('Short streamlines found. We recommend removing them.'
                         ' To continue without removing short streamlines set'
                         ' override=True')

    # calculate the pairwise MDF distance between all streamlines in dataset
    subsamp_sls = set_number_of_points(streamlines, subsample)

    cci_score_mtrx = np.zeros([len(subsamp_sls)])

    for i, sl in enumerate(subsamp_sls):
        mdf_mx = bundles_distances_mdf([subsamp_sls[i]], subsamp_sls)
        if (mdf_mx == 0).sum() > 1:
            raise ValueError('Identical streamlines. CCI calculation invalid')
        mdf_mx_oi = (mdf_mx > 0) & (mdf_mx < max_mdf) & ~np.isnan(mdf_mx)
        mdf_mx_oi_only = mdf_mx[mdf_mx_oi]
        cci_score = np.sum(np.divide(1, np.power(mdf_mx_oi_only, power)))
        cci_score_mtrx[i] = cci_score

    return cci_score_mtrx
def compute_terminal_points_matrix(S_A, S_B):
    from dipy.tracking.streamline import set_number_of_points
    S_A_res = np.array([set_number_of_points(s, nb_points=2) for s in S_A])
    S_B_res = np.array([set_number_of_points(s, nb_points=2) for s in S_B])
    return 2.0 * bundles_distances_mdf(S_A_res, S_B_res)
Esempio n. 14
0
def cluster_confidence(streamlines, max_mdf=5, subsample=12, power=1,
                       override=False):
    """ Computes the cluster confidence index (cci), which is an
    estimation of the support a set of streamlines gives to
    a particular pathway.

    Ex: A single streamline with no others in the dataset
    following a similar pathway has a low cci. A streamline
    in a bundle of 100 streamlines that follow similar
    pathways has a high cci.

    See: Jordan et al. 2017
    (Based on streamline MDF distance from Garyfallidis et al. 2012)

    Parameters
    ----------
    streamlines : list of 2D (N, 3) arrays
        A sequence of streamlines of length N (# streamlines)
    max_mdf : int
        The maximum MDF distance (mm) that will be considered a
        "supporting" streamline and included in cci calculation
    subsample: int
        The number of points that are considered for each streamline
        in the calculation. To save on calculation time, each
        streamline is subsampled to subsampleN points.
    power: int
        The power to which the MDF distance for each streamline
        will be raised to determine how much it contributes to
        the cci. High values of power make the contribution value
        degrade much faster. Example: a streamline with 5mm MDF
        similarity contributes 1/5 to the cci if power is 1, but
        only contributes 1/5^2 = 1/25 if power is 2.
    override: bool, False by default
        override means that the cci calculation will still occur even
        though there are short streamlines in the dataset that may alter
        expected behaviour.

    Returns
    -------
    Returns an array of CCI scores

    References
    ----------
    [Jordan17] Jordan K. Et al., Cluster Confidence Index: A Streamline-Wise
    Pathway Reproducibility Metric for Diffusion-Weighted MRI Tractography,
    Journal of Neuroimaging, vol 28, no 1, 2017.

    [Garyfallidis12] Garyfallidis E. et al., QuickBundles a method for
    tractography simplification, Frontiers in Neuroscience,
    vol 6, no 175, 2012.

    """

    # error if any streamlines are shorter than 20mm
    lengths = list(length(streamlines))
    if min(lengths) < 20 and not override:
        raise ValueError('Short streamlines found. We recommend removing them.'
                         ' To continue without removing short streamlines set'
                         ' override=True')

    # calculate the pairwise MDF distance between all streamlines in dataset
    subsamp_sls = set_number_of_points(streamlines, subsample)

    cci_score_mtrx = np.zeros([len(subsamp_sls)])

    for i, sl in enumerate(subsamp_sls):
        mdf_mx = bundles_distances_mdf([subsamp_sls[i]], subsamp_sls)
        if (mdf_mx == 0).sum() > 1:
            raise ValueError('Identical streamlines. CCI calculation invalid')
        mdf_mx_oi = (mdf_mx > 0) & (mdf_mx < max_mdf) & ~ np.isnan(mdf_mx)
        mdf_mx_oi_only = mdf_mx[mdf_mx_oi]
        cci_score = np.sum(np.divide(1, np.power(mdf_mx_oi_only, power)))
        cci_score_mtrx[i] = cci_score

    return cci_score_mtrx
Esempio n. 15
0
def compute_bundle_adjacency_streamlines(bundle_1,
                                         bundle_2,
                                         non_overlap=False,
                                         centroids_1=None,
                                         centroids_2=None):
    """
    Compute the distance in millimeters between two bundles. Uses centroids
    to limit computation time. Each centroid of the first bundle is matched
    to the nearest centroid of the second bundle and vice-versa.
    Distance between matched paired is averaged for the final results.
    References
    ----------
    .. [Garyfallidis15] Garyfallidis et al. Robust and efficient linear
        registration of white-matter fascicles in the space of streamlines,
        Neuroimage, 2015.
    Parameters
    ----------
    bundle_1: list of ndarray
        First set of streamlines.
    bundle_2: list of ndarray
        Second set of streamlines.
    non_overlap: bool
        Exclude overlapping streamlines from the computation.
    centroids_1: list of ndarray
        Pre-computed centroids for the first bundle.
    centroids_2: list of ndarray
        Pre-computed centroids for the second bundle.
    Returns
    -------
    float: Distance in millimeters between both bundles.
    """
    if not bundle_1 or not bundle_2:
        return -1
    thresholds = [32, 24, 12, 6]
    # Intialize the clusters
    if centroids_1 is None:
        centroids_1 = qbx_and_merge(bundle_1,
                                    thresholds,
                                    rng=RandomState(0),
                                    verbose=False).centroids
    if centroids_2 is None:
        centroids_2 = qbx_and_merge(bundle_2,
                                    thresholds,
                                    rng=RandomState(0),
                                    verbose=False).centroids
    if non_overlap:
        non_overlap_1, _ = perform_streamlines_operation(difference,
                                                         [bundle_1, bundle_2],
                                                         precision=0)
        non_overlap_2, _ = perform_streamlines_operation(difference,
                                                         [bundle_2, bundle_1],
                                                         precision=0)
        if non_overlap_1:
            non_overlap_centroids_1 = qbx_and_merge(non_overlap_1,
                                                    thresholds,
                                                    rng=RandomState(0),
                                                    verbose=False).centroids
            distance_matrix_1 = bundles_distances_mdf(non_overlap_centroids_1,
                                                      centroids_2)

            min_b1 = np.min(distance_matrix_1, axis=0)
            distance_b1 = np.average(min_b1)
        else:
            distance_b1 = 0

        if non_overlap_2:
            non_overlap_centroids_2 = qbx_and_merge(non_overlap_2,
                                                    thresholds,
                                                    rng=RandomState(0),
                                                    verbose=False).centroids
            distance_matrix_2 = bundles_distances_mdf(centroids_1,
                                                      non_overlap_centroids_2)
            min_b2 = np.min(distance_matrix_2, axis=1)
            distance_b2 = np.average(min_b2)
        else:
            distance_b2 = 0

    else:
        distance_matrix = bundles_distances_mdf(centroids_1, centroids_2)
        min_b1 = np.min(distance_matrix, axis=0)
        min_b2 = np.min(distance_matrix, axis=1)
        distance_b1 = np.average(min_b1)
        distance_b2 = np.average(min_b2)

    return (distance_b1 + distance_b2) / 2.0
Esempio n. 16
-1
def save_distances(vs1,vs2,filename='d12.npy'):
    print 'making distances ...'
    d12 = bundles_distances_mdf(vs1,vs2)
    #save_pickle('d12.skl',d12)
    np.save(filename,d12)
    print 'distances pickled ...'
    return d12