def _optim_hparcel(feature, domain, graphs, nb_parcel, lamb=1., dmax=10.,
                   niter=5, initial_mask=None, chunksize=1.e5, verbose=0):
    """ Core function of the heirrachical parcellation procedure.

    Parameters
    ----------
    feature: list of subject-related feature arrays
    Pa : parcellation instance that is updated
    graphs: graph that represents the topology of the parcellation
    anat_coord: array of shape (nvox,3) space defining set of coordinates
    nb_parcel: int
               the number of desrired parcels
    lamb=1.0: parameter to weight position
              and feature impact on the algorithm
    dmax = 10: locality parameter (in the space of anat_coord)
              to limit surch volume (CPU save)
    chunksize = int, optional
    niter = 5: number of iterations in the algorithm
    verbose=0: verbosity level

    Returns
    -------
    U: list of arrays of length nsubj
       subject-dependent parcellations
    Proto_anat: array of shape (nvox) labelling of the common space
                (template parcellation)
    """
    nb_subj = len(feature)

    # a1. perform a rough clustering of the data to make prototype
    indiv_coord = np.array([domain.coord[initial_mask[:, s] > - 1]
                             for s in range(nb_subj)])
    reduced_anat, reduced_feature = _reduce_and_concatenate(
        indiv_coord, feature, chunksize)

    _, labs, _ = kmeans(reduced_feature, nb_parcel, Labels=None, maxiter=10)
    proto_anat = [np.mean(reduced_anat[labs == k], 0)
                  for k in range(nb_parcel)]
    proto_anat = np.array(proto_anat)
    proto = [np.mean(reduced_feature[labs == k], 0) for k in range(nb_parcel)]
    proto = np.array(proto)

    # a2. topological model of the parcellation
    # group-level part
    spatial_proto = Field(nb_parcel)
    spatial_proto.set_field(proto_anat)
    spatial_proto.voronoi_diagram(proto_anat, domain.coord)
    spatial_proto.set_gaussian(proto_anat)
    spatial_proto.normalize()

    for git in range(niter):
        LP = []
        LPA = []
        U = []
        Energy = 0
        for s in range(nb_subj):
            # b.subject-specific instances of the model
            # b.0 subject-specific information
            Fs = feature[s]
            lac = indiv_coord[s]
            target = proto_anat.copy()
            lseeds = np.zeros(nb_parcel, np.int)
            aux = np.argsort(rand(nb_parcel))
            toto = np.zeros(lac.shape[0])
            for j in range(nb_parcel):
                # b.1 speed-up :only take a small ball
                i = aux[j]
                dx = lac - target[i]
                iz = np.nonzero(np.sum(dx ** 2, 1) < dmax ** 2)
                iz = np.reshape(iz, np.size(iz))
                if np.size(iz) == 0:
                    iz = np.array([np.argmin(np.sum(dx ** 2, 1))])

                # b.2: anatomical constraints
                lanat = np.reshape(lac[iz], (np.size(iz),
                                             domain.coord.shape[1]))
                pot = np.zeros(np.size(iz))
                JM, rmin = _exclusion_map(i, spatial_proto, target, lanat)
                pot[JM < 0] = np.inf
                pot[JM >= 0] = - JM[JM >= 0]

                # b.3: add feature discrepancy
                df = Fs[iz] - proto[i]
                df = np.reshape(df, (np.size(iz), proto.shape[1]))
                pot += lamb * np.sum(df ** 2, 1)

                # b.4: solution
                if np.sum(np.isinf(pot)) == np.size(pot):
                    pot = np.sum(dx[iz] ** 2, 1)

                sol = iz[np.argmin(pot)]
                target[i] = lac[sol]
                lseeds[i] = sol
                toto[sol] = 1

            if verbose > 1:
                jm = _field_gradient_jac(spatial_proto, target)
                print jm.min(), jm.max(), np.sum(toto > 0)

            # c.subject-specific parcellation
            g = graphs[s]
            f = Field(g.V, g.edges, g.weights, Fs)
            U.append(f.constrained_voronoi(lseeds))

            Energy += np.sum((Fs - proto[U[-1]]) ** 2) / \
                np.sum(initial_mask[:, s] > - 1)
            # recompute the prototypes
            # (average in subject s)
            lproto = [np.mean(Fs[U[-1] == k], 0) for k in range(nb_parcel)]
            lproto = np.array(lproto)
            lproto_anat = np.array([np.mean(lac[U[-1] == k], 0)
                                    for k in range(nb_parcel)])

            LP.append(lproto)
            LPA.append(lproto_anat)

        # recompute the prototypes across subjects
        proto_mem = proto.copy()
        proto = np.mean(np.array(LP), 0)
        proto_anat = np.mean(np.array(LPA), 0)
        displ = np.sqrt(np.sum((proto_mem - proto) ** 2, 1).max())
        if verbose:
            print 'energy', Energy, 'displacement', displ

        # recompute the topological model
        spatial_proto.set_field(proto_anat)
        spatial_proto.voronoi_diagram(proto_anat, domain.coord)
        spatial_proto.set_gaussian(proto_anat)
        spatial_proto.normalize()

        if displ < 1.e-4 * dmax:
            break
    return U, proto_anat
Example #2
0
# Local import
from get_data_light import DATA_DIR, get_second_level_dataset

# paths
input_image = path.join(DATA_DIR, 'spmT_0029.nii.gz')
mask_image = path.join(DATA_DIR, 'mask.nii.gz')
if (not path.exists(mask_image)) or (not path.exists(input_image)):
    get_second_level_dataset()

# write directory
write_dir = path.join(getcwd(), 'results')
if not path.exists(write_dir):
    mkdir(write_dir)

# read the data
mask = load(mask_image).get_data() > 0
ijk = np.array(np.where(mask)).T
nvox = ijk.shape[0]
data = load(input_image).get_data()[mask]
image_field = Field(nvox)
image_field.from_3d_grid(ijk, k=6)
image_field.set_field(data)
u, _ = image_field.ward(100)

# write the results
label_image = path.join(write_dir, 'label.nii')
wdata = mask - 1
wdata[mask] = u
save(Nifti1Image(wdata, load(mask_image).get_affine()), label_image)
print("Label image written in %s" % label_image)
Example #3
0
from scipy.ndimage import gaussian_filter

try:
    import matplotlib.pyplot as plt
except ImportError:
    raise RuntimeError("This script needs the matplotlib library")

from nipy.algorithms.graph.field import Field

dx = 50
dy = 50
dz = 1
nbseeds = 10
data = gaussian_filter(np.random.randn(dx, dy), 2)
F = Field(dx * dy * dz)
xyz = np.reshape(np.indices((dx, dy, dz)), (3, dx * dy * dz)).T.astype(np.int)
F.from_3d_grid(xyz, 6)
F.set_field(data)

seeds = np.argsort(nr.rand(F.V))[:nbseeds]
seeds, label, J0 = F.geodesic_kmeans(seeds)
wlabel, J1 = F.ward(nbseeds)
seeds, label, J2 = F.geodesic_kmeans(seeds, label=wlabel.copy(), eps=1.e-7)

print('Inertia values for the 3 algorithms: ')
print('Geodesic k-means: ', J0, 'Wards: ', J1, 'Wards + gkm: ', J2)

plt.figure(figsize=(8, 4))
plt.subplot(1, 3, 1)
plt.imshow(np.reshape(data, (dx, dy)), interpolation='nearest')
Example #4
0
def _optim_hparcel(feature,
                   domain,
                   graphs,
                   nb_parcel,
                   lamb=1.,
                   dmax=10.,
                   niter=5,
                   initial_mask=None,
                   chunksize=1.e5,
                   verbose=0):
    """ Core function of the heirrachical parcellation procedure.

    Parameters
    ----------
    feature: list of subject-related feature arrays
    Pa : parcellation instance that is updated
    graphs: graph that represents the topology of the parcellation
    anat_coord: array of shape (nvox,3) space defining set of coordinates
    nb_parcel: int
               the number of desrired parcels
    lamb=1.0: parameter to weight position
              and feature impact on the algorithm
    dmax = 10: locality parameter (in the space of anat_coord)
              to limit surch volume (CPU save)
    chunksize = int, optional
    niter = 5: number of iterations in the algorithm
    verbose=0: verbosity level

    Returns
    -------
    U: list of arrays of length nsubj
       subject-dependent parcellations
    Proto_anat: array of shape (nvox) labelling of the common space
                (template parcellation)
    """
    nb_subj = len(feature)

    # a1. perform a rough clustering of the data to make prototype
    indiv_coord = np.array(
        [domain.coord[initial_mask[:, s] > -1] for s in range(nb_subj)])
    reduced_anat, reduced_feature = _reduce_and_concatenate(
        indiv_coord, feature, chunksize)

    _, labs, _ = kmeans(reduced_feature, nb_parcel, Labels=None, maxiter=10)
    proto_anat = [
        np.mean(reduced_anat[labs == k], 0) for k in range(nb_parcel)
    ]
    proto_anat = np.array(proto_anat)
    proto = [np.mean(reduced_feature[labs == k], 0) for k in range(nb_parcel)]
    proto = np.array(proto)

    # a2. topological model of the parcellation
    # group-level part
    spatial_proto = Field(nb_parcel)
    spatial_proto.set_field(proto_anat)
    spatial_proto.voronoi_diagram(proto_anat, domain.coord)
    spatial_proto.set_gaussian(proto_anat)
    spatial_proto.normalize()

    for git in range(niter):
        LP = []
        LPA = []
        U = []
        Energy = 0
        for s in range(nb_subj):
            # b.subject-specific instances of the model
            # b.0 subject-specific information
            Fs = feature[s]
            lac = indiv_coord[s]
            target = proto_anat.copy()
            lseeds = np.zeros(nb_parcel, np.int)
            aux = np.argsort(rand(nb_parcel))
            toto = np.zeros(lac.shape[0])
            for j in range(nb_parcel):
                # b.1 speed-up :only take a small ball
                i = aux[j]
                dx = lac - target[i]
                iz = np.nonzero(np.sum(dx**2, 1) < dmax**2)
                iz = np.reshape(iz, np.size(iz))
                if np.size(iz) == 0:
                    iz = np.array([np.argmin(np.sum(dx**2, 1))])

                # b.2: anatomical constraints
                lanat = np.reshape(lac[iz],
                                   (np.size(iz), domain.coord.shape[1]))
                pot = np.zeros(np.size(iz))
                JM, rmin = _exclusion_map(i, spatial_proto, target, lanat)
                pot[JM < 0] = np.inf
                pot[JM >= 0] = -JM[JM >= 0]

                # b.3: add feature discrepancy
                df = Fs[iz] - proto[i]
                df = np.reshape(df, (np.size(iz), proto.shape[1]))
                pot += lamb * np.sum(df**2, 1)

                # b.4: solution
                if np.sum(np.isinf(pot)) == np.size(pot):
                    pot = np.sum(dx[iz]**2, 1)

                sol = iz[np.argmin(pot)]
                target[i] = lac[sol]
                lseeds[i] = sol
                toto[sol] = 1

            if verbose > 1:
                jm = _field_gradient_jac(spatial_proto, target)
                print jm.min(), jm.max(), np.sum(toto > 0)

            # c.subject-specific parcellation
            g = graphs[s]
            f = Field(g.V, g.edges, g.weights, Fs)
            U.append(f.constrained_voronoi(lseeds))

            Energy += np.sum((Fs - proto[U[-1]]) ** 2) / \
                np.sum(initial_mask[:, s] > - 1)
            # recompute the prototypes
            # (average in subject s)
            lproto = [np.mean(Fs[U[-1] == k], 0) for k in range(nb_parcel)]
            lproto = np.array(lproto)
            lproto_anat = np.array(
                [np.mean(lac[U[-1] == k], 0) for k in range(nb_parcel)])

            LP.append(lproto)
            LPA.append(lproto_anat)

        # recompute the prototypes across subjects
        proto_mem = proto.copy()
        proto = np.mean(np.array(LP), 0)
        proto_anat = np.mean(np.array(LPA), 0)
        displ = np.sqrt(np.sum((proto_mem - proto)**2, 1).max())
        if verbose:
            print 'energy', Energy, 'displacement', displ

        # recompute the topological model
        spatial_proto.set_field(proto_anat)
        spatial_proto.voronoi_diagram(proto_anat, domain.coord)
        spatial_proto.set_gaussian(proto_anat)
        spatial_proto.normalize()

        if displ < 1.e-4 * dmax:
            break
    return U, proto_anat
Example #5
0
                [20, 20],
                [30, 20]])
ampli = np.array([3, 4, 4])

nbvox = dimx * dimy
x = simul.surrogate_2d_dataset(nbsubj=1, dimx=dimx, dimy=dimy,
                               pos=pos, ampli=ampli, width=10.0)

x = np.reshape(x, (dimx, dimy, 1))
beta = np.reshape(x, (nbvox, 1))
xyz = np.array(np.where(x))
nbvox = np.size(xyz, 1)
th = 2.36

# compute the field structure and perform the watershed
Fbeta = Field(nbvox)
Fbeta.from_3d_grid(xyz.T.astype(np.int), 18)
Fbeta.set_field(beta)
idx, label = Fbeta.custom_watershed(0, th)

#compute the region-based signal average
bfm = np.array([np.mean(beta[label == k]) for k in range(label.max() + 1)])
bmap = np.zeros(nbvox)
if label.max() > - 1:
    bmap[label > - 1] = bfm[label[label > - 1]]

label = np.reshape(label, (dimx, dimy))
bmap = np.reshape(bmap, (dimx, dimy))

###############################################################################
# plot the input image
Example #6
0
from scipy.ndimage import gaussian_filter

try:
    import matplotlib.pyplot as plt
except ImportError:
    raise RuntimeError("This script needs the matplotlib library")

from nipy.algorithms.graph.field import Field

dx = 50
dy = 50
dz = 1
nbseeds = 10
data = gaussian_filter(np.random.randn(dx, dy), 2)
F = Field(dx * dy * dz)
xyz = np.reshape(np.indices((dx, dy, dz)), (3, dx * dy * dz)).T.astype(np.int)
F.from_3d_grid(xyz, 6)
F.set_field(data)

seeds = np.argsort(nr.rand(F.V))[:nbseeds]
seeds, label, J0 = F.geodesic_kmeans(seeds)
wlabel, J1 = F.ward(nbseeds)
seeds, label, J2 = F.geodesic_kmeans(seeds, label=wlabel.copy(), eps=1.0e-7)

print "Inertia values for the 3 algorithms: "
print "Geodesic k-means: ", J0, "Wards: ", J1, "Wards + gkm: ", J2

plt.figure(figsize=(8, 4))
plt.subplot(1, 3, 1)
plt.imshow(np.reshape(data, (dx, dy)), interpolation="nearest")
Example #7
0
from nipy.algorithms.graph.field import Field

# Local import
from get_data_light import DATA_DIR, get_second_level_dataset

# paths
swd = os.getcwd()
input_image = os.path.join(DATA_DIR, 'spmT_0029.nii.gz')
mask_image = os.path.join(DATA_DIR, 'mask.nii.gz')

if (not os.path.exists(mask_image)) or (not os.path.exists(input_image)):
    get_second_level_dataset()

# read the data
mask = load(mask_image).get_data() > 0
ijk = np.array(np.where(mask)).T
nvox = ijk.shape[0]
data = load(input_image).get_data()[mask]
image_field = Field(nvox)
image_field.from_3d_grid(ijk, k=6)
image_field.set_field(data)
u, _ = image_field.ward(100)

# write the results
label_image = os.path.join(swd, 'label.nii')
wdata = mask - 1
wdata[mask] = u
save(Nifti1Image(wdata, load(mask_image).get_affine()), label_image)
print "Label image written in %s" % label_image