예제 #1
0
def compute_corr_3d(src=[], target=[], x=0, xshift=0, xsize=0, y=0, yshift=0, ysize=0, z=0, zshift=0, zsize=0, xtarget=0, ytarget=0, ztarget=0, zrange=[], verbose=1, save_suffix='', gaussian_weighting=True, path_output='../'):
    """
    Find z that maximizes correlation between src and target 3d data.
    :param src: 3d source data
    :param target: 3d target data
    :param x:
    :param xshift:
    :param xsize:
    :param y:
    :param yshift:
    :param ysize:
    :param z:
    :param zshift:
    :param zsize:
    :param xtarget:
    :param ytarget:
    :param ztarget:
    :param zrange:
    :param verbose:
    :param save_suffix:
    :return:
    """
    # parameters
    thr_corr = 0.2  # disc correlation threshold. Below this value, use template distance.
    # get dimensions from src
    nx, ny, nz = src.shape
    # Get pattern from template
    pattern = target[
              xtarget - xsize: xtarget + xsize + 1,
              ytarget + yshift - ysize: ytarget + yshift + ysize + 1,
              ztarget + zshift - zsize: ztarget + zshift + zsize + 1]
    pattern1d = pattern.ravel()
    # initializations
    I_corr = np.zeros(len(zrange))
    allzeros = 0
    # current_z = 0
    ind_I = 0
    # loop across range of z defined by src
    for iz in zrange:
        # if pattern extends towards the top part of the image, then crop and pad with zeros
        if z + iz + zsize + 1 > nz:
            # print 'iz='+str(iz)+': padding on top'
            padding_size = z + iz + zsize + 1 - nz
            data_chunk3d = src[
                           x - xsize: x + xsize + 1,
                           y + yshift - ysize: y + yshift + ysize + 1,
                           z + iz - zsize: z + iz + zsize + 1 - padding_size]
            data_chunk3d = np.pad(data_chunk3d, ((0, 0), (0, 0), (0, padding_size)), 'constant',
                                  constant_values=0)
        # if pattern extends towards bottom part of the image, then crop and pad with zeros
        elif z + iz - zsize < 0:
            # print 'iz='+str(iz)+': padding at bottom'
            padding_size = abs(iz - zsize)
            data_chunk3d = src[
                           x - xsize: x + xsize + 1,
                           y + yshift - ysize: y + yshift + ysize + 1,
                           z + iz - zsize + padding_size: z + iz + zsize + 1]
            data_chunk3d = np.pad(data_chunk3d, ((0, 0), (0, 0), (padding_size, 0)), 'constant',
                                  constant_values=0)
        else:
            # print 'iz='+str(iz)+': no padding'
            data_chunk3d = src[
                           x - xsize: x + xsize + 1,
                           y + yshift - ysize: y + yshift + ysize + 1,
                           z + iz - zsize: z+ iz + zsize + 1]
        # if verbose == 2 and iz in range(0, nz, 10):
        #     # display template and subject patterns
        #     plt.figure(11)
        #     plt.subplot(131)
        #     plt.imshow(np.flipud(np.mean(pattern[:, :, :], axis=0).transpose()), origin='upper',
        #                cmap=plt.cm.gray,
        #                interpolation='none')
        #     plt.title('Template pattern')
        #     plt.subplot(132)
        #     plt.imshow(np.flipud(np.mean(data_chunk3d[:, :, :], axis=0).transpose()), origin='upper',
        #                cmap=plt.cm.gray,
        #                interpolation='none')
        #     plt.title('Subject pattern at iz=0')
        #     # save figure
        #     plt.figure(11), plt.savefig('../fig_pattern'+save_suffix+'_z'+str(iz)+'.png'), plt.close()
        # convert subject pattern to 1d
        data_chunk1d = data_chunk3d.ravel()
        # check if data_chunk1d contains at least one non-zero value
        # if np.any(data_chunk1d): --> old code which created issue #794 (jcohenadad 2016-04-05)
        if (data_chunk1d.size == pattern1d.size) and np.any(data_chunk1d):
            #I_corr[ind_I] = np.corrcoef(data_chunk1d, pattern1d)[0, 1]
            # data_chunk2d = np.mean(data_chunk3d, 1)
            # pattern2d = np.mean(pattern, 1)
            I_corr[ind_I] = mutual_information(data_chunk1d, pattern1d, nbins=16)
        else:
            allzeros = 1
            # printv('.. WARNING: iz='+str(iz)+': Data only contains zero. Set correlation to 0.', verbose)
        ind_I = ind_I + 1
    # ind_y = ind_y + 1
    if allzeros:
        printv('.. WARNING: Data contained zero. We probably hit the edge of the image.', verbose)

    # adjust correlation with Gaussian function centered at the right edge of the curve (most rostral point of FOV)
    if gaussian_weighting:
        gaussian_std_factor = 0.5
        from scipy.signal import gaussian
        gaussian_window = gaussian(len(I_corr) * 2, std=len(I_corr) * gaussian_std_factor)
        I_corr = np.multiply(I_corr, gaussian_window[0:len(I_corr)])

    # Find global maximum
    # ind_peak = ind_peak[np.argmax(I_corr[ind_peak])]
    if np.any(I_corr):
        # if I_corr contains at least a non-zero value
        ind_peak = [i for i in range(len(I_corr)) if I_corr[i] == max(I_corr)][0]  # index of max along z
        # ind_peak[1] = np.where(I_corr == I_corr.max())[1]  # index of max along y
        printv('.. Peak found: z=' + str(zrange[ind_peak]) + ' (correlation = ' + str(I_corr[ind_peak]) + ')', verbose)
        # check if correlation is high enough
        if I_corr[ind_peak] < thr_corr:
            printv('.. WARNING: Correlation is too low. Using adjusted template distance.', verbose)
            ind_peak = zrange.index(0)  # approx_distance_to_next_disc
            # ind_peak[1] = int(round(len(length_y_corr)/2))
    else:
        # if I_corr contains only zeros
        printv('.. WARNING: Correlation vector only contains zeros. Using adjusted template distance.', verbose)
        ind_peak = zrange.index(0)  # approx_distance_to_next_disc

    # display patterns and correlation
    if verbose == 2:
        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt
        # display template pattern
        plt.figure(11, figsize=(15, 7))
        plt.subplot(131)
        plt.imshow(np.flipud(np.mean(pattern[:, :, :], axis=0).transpose()), origin='upper', cmap=plt.cm.gray, interpolation='none')
        plt.title('Template pattern')
        # display subject pattern at best z
        plt.subplot(132)
        iz = zrange[ind_peak]
        data_chunk3d = src[
                       x - xsize: x + xsize + 1,
                       y + yshift - ysize: y + yshift + ysize + 1,
                       z + iz - zsize: z + iz + zsize + 1]
        plt.imshow(np.flipud(np.mean(data_chunk3d[:, :, :], axis=0).transpose()), origin='upper', cmap=plt.cm.gray, clim=[0, 800], interpolation='none')
        plt.title('Subject at iz=' + str(iz))
        # display correlation curve
        plt.subplot(133)
        plt.plot(zrange, I_corr)
        plt.title('corr(subject, template)')
        plt.plot(zrange[ind_peak], I_corr[ind_peak], 'ro'), plt.draw()
        plt.axvline(x=zrange.index(0), linewidth=1, color='black', linestyle='dashed')
        plt.axhline(y=thr_corr, linewidth=1, color='r', linestyle='dashed')
        plt.grid()
        # save figure
        plt.figure(11), plt.savefig(path_output + 'fig_pattern'+save_suffix+'.png'), plt.close()

    # return z-origin (z) + z-displacement minus zshift (to account for non-centered disc)
    return z + zrange[ind_peak] - zshift
예제 #2
0
def compute_corr_3d(src, target, x, xshift, xsize, y, yshift, ysize, z, zshift,
                    zsize, xtarget, ytarget, ztarget, zrange, verbose,
                    save_suffix, gaussian_std, path_output):
    """
    Find z that maximizes correlation between src and target 3d data.
    :param src: 3d source data
    :param target: 3d target data
    :param x:
    :param xshift:
    :param xsize:
    :param y:
    :param yshift:
    :param ysize:
    :param z:
    :param zshift:
    :param zsize:
    :param xtarget:
    :param ytarget:
    :param ztarget:
    :param zrange:
    :param verbose:
    :param save_suffix:
    :param gaussian_std:
    :return:
    """
    # parameters
    thr_corr = 0.2  # disc correlation threshold. Below this value, use template distance.
    # get dimensions from src
    nx, ny, nz = src.shape
    # Get pattern from template
    pattern = target[xtarget - xsize:xtarget + xsize + 1,
                     ytarget + yshift - ysize:ytarget + yshift + ysize + 1,
                     ztarget + zshift - zsize:ztarget + zshift + zsize + 1]
    pattern1d = pattern.ravel()
    # initializations
    I_corr = np.zeros(len(zrange))
    allzeros = 0
    # current_z = 0
    ind_I = 0
    # loop across range of z defined by src
    for iz in zrange:
        # if pattern extends towards the top part of the image, then crop and pad with zeros
        if z + iz + zsize + 1 > nz:
            # sct.printv('iz='+str(iz)+': padding on top')
            padding_size = z + iz + zsize + 1 - nz
            data_chunk3d = src[x - xsize:x + xsize + 1,
                               y + yshift - ysize:y + yshift + ysize + 1, z +
                               iz - zsize:z + iz + zsize + 1 - padding_size]
            data_chunk3d = np.pad(data_chunk3d,
                                  ((0, 0), (0, 0), (0, padding_size)),
                                  'constant',
                                  constant_values=0)
        # if pattern extends towards bottom part of the image, then crop and pad with zeros
        elif z + iz - zsize < 0:
            # sct.printv('iz='+str(iz)+': padding at bottom')
            padding_size = abs(iz - zsize)
            data_chunk3d = src[x - xsize:x + xsize + 1,
                               y + yshift - ysize:y + yshift + ysize + 1, z +
                               iz - zsize + padding_size:z + iz + zsize + 1]
            data_chunk3d = np.pad(data_chunk3d,
                                  ((0, 0), (0, 0), (padding_size, 0)),
                                  'constant',
                                  constant_values=0)
        else:
            data_chunk3d = src[x - xsize:x + xsize + 1,
                               y + yshift - ysize:y + yshift + ysize + 1,
                               z + iz - zsize:z + iz + zsize + 1]

        # convert subject pattern to 1d
        data_chunk1d = data_chunk3d.ravel()
        # check if data_chunk1d contains at least one non-zero value
        if (data_chunk1d.size == pattern1d.size) and np.any(data_chunk1d):
            I_corr[ind_I] = mutual_information(data_chunk1d,
                                               pattern1d,
                                               nbins=16,
                                               normalized=False)
        else:
            allzeros = 1
        ind_I = ind_I + 1
    # ind_y = ind_y + 1
    if allzeros:
        sct.printv(
            '.. WARNING: Data contained zero. We probably hit the edge of the image.',
            verbose)

    # adjust correlation with Gaussian function centered at the right edge of the curve (most rostral point of FOV)
    from scipy.signal import gaussian
    gaussian_window = gaussian(len(I_corr) * 2, std=len(I_corr) * gaussian_std)
    I_corr_gauss = np.multiply(I_corr, gaussian_window[0:len(I_corr)])

    # Find global maximum
    if np.any(I_corr_gauss):
        # if I_corr contains at least a non-zero value
        ind_peak = [
            i for i in range(len(I_corr_gauss))
            if I_corr_gauss[i] == max(I_corr_gauss)
        ][0]  # index of max along z
        sct.printv(
            '.. Peak found: z=' + str(zrange[ind_peak]) + ' (correlation = ' +
            str(I_corr_gauss[ind_peak]) + ')', verbose)
        # check if correlation is high enough
        if I_corr_gauss[ind_peak] < thr_corr:
            sct.printv(
                '.. WARNING: Correlation is too low. Using adjusted template distance.',
                verbose)
            ind_peak = zrange.index(0)  # approx_distance_to_next_disc
    else:
        # if I_corr contains only zeros
        sct.printv(
            '.. WARNING: Correlation vector only contains zeros. Using adjusted template distance.',
            verbose)
        ind_peak = zrange.index(0)  # approx_distance_to_next_disc

    # display patterns and correlation
    if verbose == 2:
        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt
        # display template pattern
        plt.figure(11, figsize=(15, 7))
        plt.subplot(131)
        plt.imshow(np.flipud(np.mean(pattern[:, :, :], axis=0).transpose()),
                   origin='upper',
                   cmap=plt.cm.gray,
                   interpolation='none')
        plt.title('Template pattern')
        # display subject pattern at best z
        plt.subplot(132)
        iz = zrange[ind_peak]
        data_chunk3d = src[x - xsize:x + xsize + 1,
                           y + yshift - ysize:y + yshift + ysize + 1,
                           z + iz - zsize:z + iz + zsize + 1]
        plt.imshow(np.flipud(
            np.mean(data_chunk3d[:, :, :], axis=0).transpose()),
                   origin='upper',
                   cmap=plt.cm.gray,
                   clim=[0, 800],
                   interpolation='none')
        plt.title('Subject at iz=' + str(iz))
        # display correlation curve
        plt.subplot(133)
        plt.plot(zrange, I_corr)
        plt.plot(zrange, I_corr_gauss, 'black', linestyle='dashed')
        plt.legend(['I_corr', 'I_corr_gauss'])
        plt.title('Mutual Info, gaussian_std=' + str(gaussian_std))
        plt.plot(zrange[ind_peak], I_corr_gauss[ind_peak], 'ro'), plt.draw()
        plt.axvline(x=zrange.index(0),
                    linewidth=1,
                    color='black',
                    linestyle='dashed')
        plt.axhline(y=thr_corr, linewidth=1, color='r', linestyle='dashed')
        plt.grid()
        # save figure
        plt.figure(11), plt.savefig(
            os.path.join(path_output,
                         "fig_pattern" + save_suffix + '.png')), plt.close()

    # return z-origin (z) + z-displacement minus zshift (to account for non-centered disc)
    return z + zrange[ind_peak] - zshift