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
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