Exemplo n.º 1
0
def remove_loops_and_sharp_turns(streamlines,
                                 max_angle,
                                 use_qb=False,
                                 qb_threshold=15.,
                                 qb_seed=0):
    """
    Remove loops and sharp turns from a list of streamlines.
    Parameters
    ----------
    streamlines: list of ndarray
        The list of streamlines from which to remove loops and sharp turns.
    max_angle: float
        Maximal winding angle a streamline can have before
        being classified as a loop.
    use_qb: bool
        Set to True if the additional QuickBundles pass is done.
        This will help remove sharp turns. Should only be used on
        bundled streamlines, not on whole-brain tractograms.
    qb_threshold: float
        Quickbundles distance threshold, only used if use_qb is True.
    qb_seed: int
        Seed to initialize randomness in QuickBundles

    Returns
    -------
    list: the ids of clean streamlines
        Only the ids are returned so proper filtering can be done afterwards
    """

    streamlines_clean = []
    ids = []
    for i, s in enumerate(streamlines):
        if tm.winding(s) < max_angle:
            ids.append(i)
            streamlines_clean.append(s)

    if use_qb:
        ids = []
        if len(streamlines_clean) > 1:
            curvature = []

            rng = np.random.RandomState(qb_seed)
            clusters = qbx_and_merge(streamlines_clean,
                                     [40, 30, 20, qb_threshold],
                                     rng=rng,
                                     verbose=False)

            for cc in clusters.centroids:
                curvature.append(tm.mean_curvature(cc))
            mean_curvature = sum(curvature) / len(curvature)

            for i in range(len(clusters.centroids)):
                if tm.mean_curvature(clusters.centroids[i]) <= mean_curvature:
                    ids.extend(clusters[i].indices)
        else:
            logging.debug("Impossible to use the use_qb option because " +
                          "not more than one streamline left from the\n" +
                          "input file.")
    return ids
Exemplo n.º 2
0
def compute_mean_bundle_curvature(bundle, nb_points=200):
    """Compute the mean scalar curvature of a bundle using tm.mean(curvature).
	"""
    bundle_res = np.array(
        [set_number_of_points(st, nb_points=nb_points) for st in bundle])
    mean_st_curvature = np.zeros(len(bundle_res))
    for i, sa in enumerate(bundle_res):
        m = tm.mean_curvature(sa)
        mean_st_curvature[i] = m
    mean_bundle_curvature = np.mean(mean_st_curvature)

    return mean_bundle_curvature
def computeStats(subjectID,reference,streamlines,classification,outdir):

	avg_length = []
	avg_curv = []
	stream_count = []
	mean_x = []
	mean_y = []
	mean_z = []
	num_vox = []

	tract_index_labels = np.trim_zeros(np.unique(classification['index'].tolist()))

	qb = QuickBundles(np.inf)

	for i in tract_index_labels:
		indices = [ t for t in range(len(classification['index'].tolist())) if classification['index'].tolist()[int(t)] == i ]
		avg_length.append(np.mean(length(streamlines[indices])))
		
		clusters = qb.cluster(streamlines[indices])
		avg_curv.append(mean_curvature(clusters.centroids[0]))
		orientation = mean_orientation(clusters.centroids[0])
		mean_x.append(orientation[0])
		mean_y.append(orientation[1])
		mean_z.append(orientation[2])
		stream_count.append(len(indices))
		denmap = density_map(streamlines[indices],reference.affine,reference.shape)
		num_vox.append(len(denmap[denmap>0]))

	df = pd.DataFrame([],dtype=object)
	df['subjectID'] = [ subjectID for f in range(len(classification['names'].tolist())) ]
	df['structureID'] = [ f for f in classification['names'].tolist() ]
	df['nodeID'] = [ 1 for f in range(len(df['structureID'])) ]
	df['streamline_count'] = stream_count
	df['average_length'] = avg_length
	df['average_curvature'] = avg_curv
	df['voxel_count'] = num_vox
	df['centroid_x'] = mean_x
	df['centroid_y'] = mean_y
	df['centroid_z'] = mean_z

	df.to_csv('%s/output_FiberStats.csv' %outdir,index=False)
def compute_measures(filename_tuple):
    sft = load_tractogram(filename_tuple[0], filename_tuple[1])
    _, dimensions, voxel_size, _ = sft.space_attributes

    nbr_streamlines = len(sft)
    if not nbr_streamlines:
        logging.warning('{} is empty'.format(filename_tuple[0]))
        return dict(
            zip([
                'volume', 'volume_endpoints', 'streamlines_count',
                'avg_length', 'std_length', 'min_length', 'max_length',
                'mean_curvature'
            ], [0, 0, 0, 0, 0, 0, 0, 0]))

    length_list = list(length(list(sft.streamlines)))
    length_avg = float(np.average(length_list))
    length_std = float(np.std(length_list))
    length_min = float(np.min(length_list))
    length_max = float(np.max(length_list))

    sft.to_vox()
    sft.to_corner()
    streamlines = sft.streamlines
    density = compute_tract_counts_map(streamlines, dimensions)
    endpoints_density = get_endpoints_density_map(streamlines, dimensions)

    curvature_list = np.zeros((nbr_streamlines, ))
    for i in range(nbr_streamlines):
        curvature_list[i] = mean_curvature(sft.streamlines[i])

    return dict(
        zip([
            'volume', 'volume_endpoints', 'streamlines_count', 'avg_length',
            'std_length', 'min_length', 'max_length', 'mean_curvature'
        ], [
            np.count_nonzero(density) * np.product(voxel_size),
            np.count_nonzero(endpoints_density) * np.product(voxel_size),
            nbr_streamlines, length_avg, length_std, length_min, length_max,
            float(np.mean(curvature_list))
        ]))
Exemplo n.º 5
0
def remove_loops_and_sharp_turns(streamlines,
                                 max_angle,
                                 use_qb=False,
                                 qb_threshold=15.,
                                 qb_seed=0):
    """
    Remove loops and sharp turns from a list of streamlines.
    Parameters
    ----------
    streamlines: list of ndarray
        The list of streamlines from which to remove loops and sharp turns.
    use_qb: bool
        Set to True if the additional QuickBundles pass is done.
        This will help remove sharp turns. Should only be used on
        bundled streamlines, not on whole-brain tractograms.
    max_angle: float
        Maximal winding angle a streamline can have before
        being classified as a loop.
    qb_threshold: float
        Quickbundles distance threshold, only used if use_qb is True.
    Returns
    -------
    A tuple containing
        list of ndarray: the clean streamlines
        list of ndarray: the list of removed streamlines, if any
    """

    loops = []
    streamlines_clean = []
    for s in streamlines:
        if tm.winding(s) >= max_angle:
            loops.append(s)
        else:
            streamlines_clean.append(s)

    if use_qb:
        if len(streamlines_clean) > 1:
            streamlines = streamlines_clean
            curvature = []
            streamlines_clean = []

            rng = np.random.RandomState(qb_seed)
            clusters = qbx_and_merge(streamlines, [40, 30, 20, qb_threshold],
                                     rng=rng, verbose=False)

            for cc in clusters.centroids:
                curvature.append(tm.mean_curvature(cc))
            mean_curvature = sum(curvature)/len(curvature)

            for i in range(len(clusters.centroids)):
                if tm.mean_curvature(clusters.centroids[i]) > mean_curvature:
                    for indice in clusters[i].indices:
                        loops.append(streamlines[indice])
                else:
                    for indice in clusters[i].indices:
                        streamlines_clean.append(streamlines[indice])
        else:
            logging.debug("Impossible to use the use_qb option because " +
                          "not more than one streamline left from the\n" +
                          "input file.")

    return streamlines_clean, loops
Exemplo n.º 6
0
def compute_measures(filename_tuple):
    sft = load_tractogram(filename_tuple[0], filename_tuple[1])
    _, dimensions, voxel_size, _ = sft.space_attributes
    uniformize_bundle_sft(sft)
    nbr_streamlines = len(sft)
    if not nbr_streamlines:
        logging.warning('{} is empty'.format(filename_tuple[0]))
        return dict(
            zip([
                'volume', 'volume_endpoints', 'streamlines_count',
                'avg_length', 'std_length', 'min_length', 'max_length', 'span',
                'curl', 'diameter', 'elongation', 'surface_area',
                'end_surface_area_head', 'end_surface_area_tail',
                'radius_head', 'radius_tail', 'irregularity',
                'irregularity_of_end_surface_head',
                'irregularity_of_end_surface_tail', 'mean_curvature',
                'fractal_dimension'
            ], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                ]))

    streamline_cords = list(sft.streamlines)
    length_list = list(length(streamline_cords))
    length_avg = float(np.average(length_list))
    length_std = float(np.std(length_list))
    length_min = float(np.min(length_list))
    length_max = float(np.max(length_list))

    sft.to_vox()
    sft.to_corner()
    streamlines = sft.streamlines
    density = compute_tract_counts_map(streamlines, dimensions)
    endpoints_density = get_endpoints_density_map(streamlines, dimensions)

    span_list = list(map(compute_span, streamline_cords))
    span = float(np.average(span_list))
    curl = length_avg / span
    volume = np.count_nonzero(density) * np.product(voxel_size)
    diameter = 2 * np.sqrt(volume / (np.pi * length_avg))
    elon = length_avg / diameter

    roi = np.where(density != 0, 1, density)
    surf_area = approximate_surface_node(roi) * (voxel_size[0]**2)
    irregularity = surf_area / (np.pi * diameter * length_avg)

    endpoints_map_head, endpoints_map_tail = \
        get_head_tail_density_maps(sft.streamlines, dimensions)
    endpoints_map_head_roi = \
        np.where(endpoints_map_head != 0, 1, endpoints_map_head)
    endpoints_map_tail_roi = \
        np.where(endpoints_map_tail != 0, 1, endpoints_map_tail)
    end_sur_area_head = \
        approximate_surface_node(endpoints_map_head_roi) * (voxel_size[0] ** 2)
    end_sur_area_tail = \
        approximate_surface_node(endpoints_map_tail_roi) * (voxel_size[0] ** 2)

    endpoints_coords_head = np.array(np.where(endpoints_map_head_roi)).T
    endpoints_coords_tail = np.array(np.where(endpoints_map_tail_roi)).T
    radius_head = 1.5 * np.average(
        np.sqrt(((endpoints_coords_head -
                  np.average(endpoints_coords_head, axis=0))**2).sum(axis=1)))
    radius_tail = 1.5 * np.average(
        np.sqrt(((endpoints_coords_tail -
                  np.average(endpoints_coords_tail, axis=0))**2).sum(axis=1)))
    end_irreg_head = (np.pi * radius_head**2) / end_sur_area_head
    end_irreg_tail = (np.pi * radius_tail**2) / end_sur_area_tail

    fractal_dimension = compute_fractal_dimension(density)

    curvature_list = np.zeros((nbr_streamlines, ))
    for i in range(nbr_streamlines):
        curvature_list[i] = mean_curvature(sft.streamlines[i])

    return dict(
        zip([
            'volume', 'volume_endpoints', 'streamlines_count', 'avg_length',
            'std_length', 'min_length', 'max_length', 'span', 'curl',
            'diameter', 'elongation', 'surface_area', 'end_surface_area_head',
            'end_surface_area_tail', 'radius_head', 'radius_tail',
            'irregularity', 'irregularity_of_end_surface_head',
            'irregularity_of_end_surface_tail', 'mean_curvature',
            'fractal_dimension'
        ], [
            volume,
            np.count_nonzero(endpoints_density) * np.product(voxel_size),
            nbr_streamlines, length_avg, length_std, length_min, length_max,
            span, curl, diameter, elon, surf_area, end_sur_area_head,
            end_sur_area_tail, radius_head, radius_tail, irregularity,
            end_irreg_head, end_irreg_tail,
            float(np.mean(curvature_list)), fractal_dimension
        ]))
Exemplo n.º 7
0
def remove_loops_and_sharp_turns(streamlines,
                                 use_qb,
                                 max_angle,
                                 qb_threshold,
                                 logger=None):
    """
    Remove loops and sharp turns from a list of streamlines.

    Parameters
    ----------
    streamlines: list of ndarray
        The list of streamlines from which to remove loops and sharp turns.
    use_qb: bool
        Set to True if the additional QuickBundles pass is done.
        This will help remove sharp turns. Should only be used on
        bundled streamlines, not on whole-brain tractograms.
    max_angle: float
        Maximal winding angle a streamline can have before
        being classified as a loop.
    qb_threshold: float
        Quickbundles distance threshold, only used if use_qb is True.
    logger: logging object, optional
        Logger to use.

    Returns
    -------
    A tuple containing
        list of ndarray: the clean streamlines
        list of ndarray: the list of removed streamlines, if any
    """
    if logger is None:
        logger = logging.getLogger()

    loops = []
    streamlines_clean = []
    for s in streamlines:
        if tm.winding(s) >= max_angle:
            loops.append(s)
        else:
            streamlines_clean.append(s)

    if use_qb:
        if len(streamlines_clean) > 1:
            streamlines = streamlines_clean
            curvature = []
            streamlines_clean = []

            qb = QuickBundles(threshold=qb_threshold)
            clusters = qb.cluster(streamlines)

            for cc in clusters.centroids:
                curvature.append(tm.mean_curvature(cc))
            mean_curvature = sum(curvature) / len(curvature)

            for i in xrange(len(clusters.centroids)):
                if tm.mean_curvature(clusters.centroids[i]) > mean_curvature:
                    for indice in clusters[i].indices:
                        loops.append(streamlines[indice])
                else:
                    for indice in clusters[i].indices:
                        streamlines_clean.append(streamlines[indice])
        else:
            logger.warning("Impossible to use the use_qb option because " +
                           "not more than one streamline left from the\n" +
                           "input file.")

    return streamlines_clean, loops
Exemplo n.º 8
0
 def get_mean_curvature(self):
     """Mean curvature of each streamline."""
     mean_curvature = [dtm.mean_curvature(stream) for stream in self._data]
     return mean_curvature