def disc_shift(time_s, signal, height_th): """ use the set reset switch to locate the pulse edge and shift it to the center of the acquisition window. if all traces have the same acquisition window, they will be synchronised. """ center = int(len(time_s) / 2) [mask, clamp, edges, left_edges, right_edges] = pd.discriminator(time_s, signal, height_th=height_th, method=3) n_shift = left_edges[0] print n_shift return pa.shift(signal, -n_shift + center)
def fit_shift(time_s, signal, fit_model, height_th): """ fit the trace with a sample pulse and shift it to match the staritng time """ zero = int(len(time_s) / 4) * 0 dt = np.diff(time_s)[0] d_signal = savgol_filter(np.diff(signal), 301, 1) # ax = plt.gca() # ax2 = ax.twinx() # ax2.plot(np.array(time_v)[1:],d_signal*100) # use peaks only if they are legitimate edges identified by the set-reset switch [mask, clamp, edges, left_edges, right_edges] = pd.discriminator(time_s, signal, dt_left=100e-9, dt_right=0, height_th=height_th, method=2) # find peaks in the derivative to find the steepest point idx = left_edges[0] + peakutils.indexes(d_signal[(mask & clamp)[1:]], .5, 3000) # print time_v[left_edges], time_v[idx] if len(idx) == 0: return [np.nan for _ in time_v] # else: # idx=(mask&clamp)[idx]*idx idx_s = np.flipud(idx[d_signal[idx].argsort()]) p = Parameters() p.add('x_offset', time_s[np.argmax(signal)] - 4e-7 - zero * dt) if len(idx_s) > 0: p.add('x_offset', time_s[idx_s[0]] - zero * dt) p.add('amplitude', 1, vary=1) result = fit_model.fit(signal, x=time_s, params=p, weights=1 / 0.001) n_shift = int(result.best_values['x_offset'] / dt) # print n_shift*dt return pa.shift(signal, -n_shift)
def time_offset(time_v, trace, height_th): """ shift a trace so that the steepest point is at time 0 """ # start by finding the max of the derivative zero = int(len(time_v) / 4) * 0 signal = trace dt = np.diff(time_v)[0] # derivative of the signal, smoothed d_signal = savgol_filter(np.diff(signal), 301, 1) # ax = plt.gca() # ax2 = ax.twinx() # ax2.plot(np.array(time_v)[1:],d_signal*100) # use peaks only if they are legitimate edges identified by the set-reset switch [mask, clamp, edges, left_edges, right_edges] = pd.discriminator(time_v, signal, dt_left=100e-9, dt_right=0, height_th=height_th, method=2) # find peaks in the derivative to find the steepest point idx = left_edges[0] + peakutils.indexes(d_signal[(mask & clamp)[1:]], .5, 3000) # print time_v[left_edges], time_v[idx] if len(idx) == 0: return [np.nan for _ in time_v] # else: # idx=(mask&clamp)[idx]*idx idx_s = np.flipud(idx[d_signal[idx].argsort()])[0] try: time_p = peakutils.interpolate(time_v[:-1], d_signal, [idx_s])[0] except (RuntimeError, ValueError) as e: time_p = time_v[idx_s] n_shift = int(time_p / dt) return pa.shift(trace, -n_shift + zero)
def fit_two_cw(time, signal, two_pulse_fit, one_pulse, sigma0, # signal noise sum_mu, sum_tau, sum_a, sum_b, diff_tau, diff_a, diff_b, sampling, burn, thin, height_th, Plot=False, debug=False): # Identify Pulse Region, including more of the tail - use same params as area selection. [mask_area, clamp_area, edges_area, left_edges_area, right_edges_area] = pd.discriminator(time, signal, dt_left=300e-9, dt_right=1400e-9, height_th=height_th, Plot=False, method=2) # Identify Pulse Region Near edges [mask, clamp, edges, left_edges, right_edges] = pd.discriminator(time, signal, dt_left=0, dt_right=0, height_th=height_th, Plot=False, method=2) #select regions close to the front edge # Use method 2 sr latch reversed with extra time dt_right to manually adjust for additional pulse regions to be considered for the fit. # dt_right limit must be SMALLER than limit set for 2 photon selection # print [left_edges_area, right_edges_area] # print [left_edges, right_edges] reidentify_win = False if left_edges_area[0]>right_edges[0]: """ Slightly larger window used for area detection results in extra pulses detected along trace edges when a smaller window is used for fitting. If reducing the window size results in another pulse being picked up outside the larger window, then discard the pulse region. """ # Case 1: Extra pulse occurs to the left of 2 overlapping pulses time = time[right_edges[0]:] signal = signal[right_edges[0]:] reidentify_win = True if right_edges_area[-1]<left_edges[-1]: # Case 2: Extra pulse occurs to the right of 2 overlapping pulses time = time[:left_edges[-1]] signal = signal[:left_edges[-1]] reidentify_win = True if reidentify_win: # Rerun discriminator since indices might change after truncation [mask, clamp, edges, left_edges, right_edges] = pd.discriminator(time, signal, dt_left=0, dt_right=0, height_th=height_th, Plot=False, method=2) #select regions close to the front edge # Some flags for debugging later mcmc_flag = False unequal_edges = False # Raise flags based on number of edges if len(left_edges)==len(right_edges): """full pulses""" if len(left_edges)>=2: """2 or more edges""" mcmc_flag = False if len(left_edges)==1: """1 edge comprising of overlapping photons""" mcmc_flag = True else: mcmc_flag = True unequal_edges = True if mcmc_flag==True: # """ # >START MCMC # (comment out to use lmfit instead for overlapping pulses) # """ # result_mcmc = fit_two_mcmc(time[::1], signal[::1], height_th=height_th, # one_pulse=one_pulse, # sigma0=sigma0, # signal noise # sum_mu=sum_mu, # sum_tau=sum_tau, # sum_a=sum_a, # sum_b=sum_b, # diff_tau=diff_tau, # diff_a=diff_a, # diff_b=diff_b, # sampling=sampling, # burn=burn, # thin=thin, # Plot=Plot, # debug=debug) # """ # Use MCMC results to initialise lmfit: # (facilitates results extraction if all data is from the same lmfit object) # """ # one_x_offset_init = np.mean(result_mcmc.trace('one_x_offset')[-100:]) # two_x_offset_init = np.mean(result_mcmc.trace('two_x_offset')[-100:]) # one_x_offset_init_min = None; one_x_offset_init_max = None # two_x_offset_init_min = None; two_x_offset_init_max = None # sum_amps_init = np.mean(result_mcmc.trace('sum_amps')[-100:]) # diff_amps_init = np.mean(result_mcmc.trace('diff_amps')[-100:]) # one_amplitude_init = (sum_amps_init+diff_amps_init)/2 # two_amplitude_init = (sum_amps_init-diff_amps_init)/2 # """ # >END MCMC # """ """ >LMFIT: Initialise initial params only for overlapping pulses, compulsory LMFIT starts after mcmc_flag code block. (comment out to use mcmc instead for overlapping pulses) """ one_x_offset_init_min = time[left_edges[0]] one_x_offset_init_max = time[left_edges[0]+np.argmax(signal[left_edges[0]:right_edges[0]])] two_x_offset_init_max = time[right_edges[0]] two_x_offset_init_min = one_x_offset_init_min one_x_offset_init = one_x_offset_init_min two_x_offset_init = two_x_offset_init_max - 0.479999986425e-6 #0.58199998354e-6 one_amplitude_init = sum_mu/2 two_amplitude_init = sum_mu/2 if mcmc_flag==False: """ LMFIT: Initialise initial params only for non-overlapping pulses, compulsory LMFIT starts after mcmc_flag code block. """ one_x_offset_init_min = time[left_edges[0]] one_x_offset_init_max = time[left_edges[0]+np.argmax(signal[left_edges[0]:right_edges[0]])] two_x_offset_init_min = time[left_edges[1]] two_x_offset_init_max = time[left_edges[1]+np.argmax(signal[left_edges[1]:right_edges[1]])] one_x_offset_init = (one_x_offset_init_min+one_x_offset_init_max)/2 two_x_offset_init = (two_x_offset_init_min+two_x_offset_init_max)/2 one_amplitude_init = sum_mu/2 two_amplitude_init = sum_mu/2 """Compulsory LMFIT for both overlapping and non-overlapping cases""" p = Parameters() p.add('one_x_offset', one_x_offset_init, min=one_x_offset_init_min , max=one_x_offset_init_max, vary=True) p.add('two_x_offset', two_x_offset_init, min=two_x_offset_init_min , max=two_x_offset_init_max, vary=True) p.add('sum_amplitudes', (one_amplitude_init+two_amplitude_init)*1.01, #not sure why, but some assymetry is required... sum_mu can't be avg of sum_a and sum_b min=sum_a, max=sum_b, vary=True) p.add('diff_amplitudes', one_amplitude_init-two_amplitude_init, min=diff_a, max=diff_b, vary=True) p.add('one_amplitude', one_amplitude_init, expr= '(sum_amplitudes+diff_amplitudes)/2', vary=True) #warning: max >= 2 causes n=2 & noise to be fitted on a tau~0 2ph trace. p.add('two_amplitude', two_amplitude_init, expr= '(sum_amplitudes-diff_amplitudes)/2', vary=True) #warning: max >= 2 causes n=2 & noise to be fitted on a tau~0 2ph trace. result = two_pulse_fit.fit(np.array(signal), x=np.array(time), params=p, weights=1/sigma0, #10e100 method='powell' ) # print left_edges, right_edges return result, mcmc_flag, unequal_edges
Background Correction """ # bg = np.median(signal[signal<h_th]) bg = find_bg(signal) signal = signal - bg >>>>>>> 2a32507f24526850f2f413729b6adedbf5ac41fc """ Mask traces to reject noise Clamp traces to reject half pulses at edges """ <<<<<<< HEAD [mask, clamp, edges, left_edges, right_edges] = discriminator( time, signal, dt_left=200e-9, dt_right=700e-9, height_th=h_th, Plot=False, method=2) window = mask & clamp ======= [mask, clamp, edges, left_edges, right_edges] = discriminator(time, signal, dt_left=0*300e-9,dt_right=1300e-9, height_th=h_th, Plot=False, method=2) window = mask&clamp >>>>>>> 2a32507f24526850f2f413729b6adedbf5ac41fc """ Extract properties