def test_ccovf_fft_vs_convolution(demean, adjusted, reset_randomstate): x = np.random.normal(size=128) y = np.random.normal(size=128) F1 = ccovf(x, y, demean=demean, adjusted=adjusted, fft=False) F2 = ccovf(x, y, demean=demean, adjusted=adjusted, fft=True) assert_almost_equal(F1, F2, decimal=7)
def phase_align(reference, target, roi, res=100): ''' Cross-correlate data within region of interest at a precision of 1./res if data is cross-correlated at native resolution (i.e. res=1) this function can only achieve integer precision Args: reference (1d array/list): signal that won't be shifted target (1d array/list): signal to be shifted to reference roi (tuple): region of interest to compute chi-squared res (int): factor to increase resolution of data via linear interpolation Returns: shift (float): offset between target and reference signal ''' # convert to int to avoid indexing issues ROI = slice(int(roi[0]), int(roi[1]), 1) # interpolate data onto a higher resolution grid x, r1 = highres(reference[ROI], kind='linear', res=res) x, r2 = highres(target[ROI], kind='linear', res=res) # subtract mean r1 -= r1.mean() r2 -= r2.mean() # compute cross covariance cc = ccovf(r1, r2, demean=False, unbiased=False) # determine if shift if positive/negative if np.argmax(cc) == 0: cc = ccovf(r2, r1, demean=False, unbiased=False) mod = -1 else: mod = 1 # often found this method to be more accurate then the way below return np.argmax(cc) * mod * (1. / res) # interpolate data onto a higher resolution grid x, r1 = highres(reference[ROI], kind='linear', res=res) x, r2 = highres(target[ROI], kind='linear', res=res) # subtract off mean r1 -= r1.mean() r1 -= r2.mean() # compute the phase-only correlation function product = np.fft.fft(r1) * np.fft.fft(r2).conj() cc = np.fft.fftshift(np.fft.ifft(product)) # manipulate the output from np.fft l = reference[ROI].shape[0] shifts = np.linspace(-0.5 * l, 0.5 * l, l * res) # plt.plot(shifts,cc,'k-'); plt.show() return shifts[np.argmax(cc.real)]
matplotlib.rcParams.update({'font.size': 16}) ##################################################################################### # 1D CCF ##################################################################################### # Load calibrated data print("Loading data: {0}-imageplane-dynspectrum-calibrated.stokesI.txt".format(src)) dynspec_I = np.loadtxt("{0}-imageplane-dynspectrum-calibrated.stokesI.txt".format(src)) # TODO: Weight the time average by fscrunch, rather than doing a simple mean pulse1spectra = np.mean(dynspec_I[ccfstart1:ccfstop1+1], 0) pulse2spectra = np.mean(dynspec_I[ccfstart2:ccfstop2+1], 0) # CCF calculation for individual bins print("Computing CCF between user-selected pulse1 and pulse2") # Calculate the 1D CCF across frequency between the two user-selected time ranges using statsmodels.tsa.stattools.ccovf ccf = st.ccovf(pulse1spectra, pulse2spectra) # Set up figure and axes ccf_fig, ccf_ax = plt.subplots(figsize=(7,7)) # Plot the CCF ccf_ax.plot(ccf, label='CCF (bins {0}-{1} x {2}-{3})'.format(ccfstart1,ccfstop1,ccfstart2,ccfstop2)) plt.legend() ccf_fig.savefig("{0}-CCF_bin{1}-{2}x{3}-{4}.png".format(src,ccfstart1,ccfstop1,ccfstart2,ccfstop2), bbox_inches='tight')
def test_compare_acovf_vs_ccovf(demean, adjusted, fft, reset_randomstate): x = np.random.normal(size=128) F1 = acovf(x, demean=demean, adjusted=adjusted, fft=fft) F2 = ccovf(x, x, demean=demean, adjusted=adjusted, fft=fft) assert_almost_equal(F1, F2, decimal=7)