def test_fit_double_gaussian(self): x_data = np.arange(-4, 4, .05) initial_parameters = [10, 20, 1, 1, -2, 2] y_data = double_gaussian(x_data, initial_parameters) fitted_parameters, _ = fit_double_gaussian(x_data, y_data) parameter_diff = np.abs(fitted_parameters - initial_parameters) self.assertTrue(np.all(parameter_diff < 1e-3))
def _plot_rts_histogram(data, num_bins, par_fit, split, figure_title): _, bins, _ = plt.hist(data, bins=num_bins) bincentres = np.array([(bins[i] + bins[i + 1]) / 2 for i in range(0, len(bins) - 1)]) plt.plot(bincentres, double_gaussian(bincentres, par_fit), 'r', label='Fitted double gaussian') plt.plot(split, double_gaussian(split, par_fit), 'ro', markersize=8, label='split: %.3f' % split) plt.xlabel('Measured value (a.u.)') plt.ylabel('Data points per bin') plt.legend() plt.title(figure_title)
def _plot_rts_histogram(data, num_bins, double_gaussian_fit, split, figure_title): _, bins, _ = plt.hist(data, bins=num_bins) bincentres = np.array([(bins[i] + bins[i + 1]) / 2 for i in range(0, len(bins) - 1)]) get_left_mean_std_amplitude = operator.itemgetter(4, 2, 0) get_right_mean_std_amplitude = operator.itemgetter(5, 3, 1) left_gaussian = list(get_left_mean_std_amplitude(double_gaussian_fit)) right_gaussian = list(get_right_mean_std_amplitude(double_gaussian_fit)) plt.plot(bincentres, double_gaussian(bincentres, double_gaussian_fit), '-m', label='Fitted double gaussian') plt.plot(bincentres, gaussian(bincentres, *left_gaussian), 'g', label='Left Gaussian', alpha=.85, linewidth=.75) plt.plot(bincentres, gaussian(bincentres, *right_gaussian), 'r', label='Right Gaussian', alpha=.85, linewidth=.75) plt.plot(split, double_gaussian(split, double_gaussian_fit), 'ro', markersize=8, label='split: %.3f' % split) plt.xlabel('Measured value (a.u.)') plt.ylabel('Data points per bin') plt.legend() plt.title(figure_title)
def tunnelrates_RTS(data, samplerate=None, min_sep=2.0, max_sep=7.0, min_duration=5, num_bins=None, plungers=[], fig=None, ppt=None, verbose=0): """ This function takes an RTS dataset, fits a double gaussian, finds the split between the two levels, determines the durations in these two levels, fits a decaying exponantial on two arrays of durations, which gives the tunneling frequency for both the levels. Args: data (array): qcodes DataSet (or 1d data array) with the RTS data plungers ([str, str]): array of the two plungers used to perform the RTS measurement samplerate (int or float): sampling rate of either the fpga or the digitizer, optional if given in the metadata of the measured data min_sep (float): if the separation found for the fit of the double gaussian is less then this value, the fit probably failed and a FittingException is raised max_sep (float): if the separation found for the fit of the double gaussian is more then this value, the fit probably failed and a FittingException is raised min_duration (int): minimal number of datapoints a duration should last to be taking into account for the analysis fig (None or int): shows figures and sends them to the ppt when is not None ppt (None or int): determines if the figures are send to a powerpoint presentation verbose (int): prints info to the console when > 0 Returns: tunnelrate_dn (numpy.float64): tunneling rate of the down level (kHz) tunnelrate_up (numpy.float64): tunneling rate of the up level (kHz) parameters (dict): dictionary with relevent (fit) parameters """ if type(data) == qcodes.data.data_set.DataSet: try: plungers = plungers metadata = data.metadata gates = metadata['allgatevalues'] plungervalue = gates[plungers[0]] except: plungervalue = [] if samplerate is None: metadata = data.metadata samplerate = metadata['samplerate'] data = np.array(data.measured) else: plungervalue = [] if samplerate is None: raise Exception('samplerate is None') # plotting a 2d histogram of the RTS if fig: xdata = np.array(range(0, len(data))) / samplerate * 1000 Z, xedges, yedges = np.histogram2d( xdata, data, bins=[int(np.sqrt(len(xdata))) / 2, int(np.sqrt(len(data))) / 2]) title = '2d histogram RTS' plt.figure(title) plt.clf() plt.pcolormesh(xedges, yedges, Z.T) cb = plt.colorbar() cb.set_label('Data points per bin') plt.xlabel('Time (ms)') plt.ylabel('Signal sensing dot (a.u.)') plt.title(title) if ppt: addPPTslide(title=title, fig=plt.figure(title)) # binning the data and determining the bincentres if num_bins is None: num_bins = int(np.sqrt(len(data))) counts, bins = np.histogram(data, bins=num_bins) bincentres = np.array([(bins[i] + bins[i + 1]) / 2 for i in range(0, len(bins) - 1)]) # fitting the double gaussian and finding the split between the up and the down state, separation between the max of the two gaussians measured in the sum of the std par_fit, result_dict = fit_double_gaussian(bincentres, counts) separation = result_dict['separation'] split = result_dict['split'] if verbose: print('Fit parameters double gaussian:\n mean down: %.3f counts' % par_fit[4] + ', mean up:%.3f counts' % par_fit[5] + ', std down: %.3f counts' % par_fit[2] + ', std up:%.3f counts' % par_fit[3]) print('Separation between peaks gaussians: %.3f std' % separation) print('Split between two levels: %.3f' % split) # plotting the data in a histogram, the fitted two gaussian model and the split if fig: title = 'Histogram of two levels RTS' plt.figure(title) plt.clf() counts, bins, _ = plt.hist(data, bins=num_bins) plt.plot(bincentres, double_gaussian(bincentres, par_fit), 'r', label='Fitted double gaussian') plt.plot(split, double_gaussian(split, par_fit), 'ro', markersize=8, label='split: %.3f' % split) plt.xlabel('Measured value (a.u.)') plt.ylabel('Data points per bin') plt.legend() plt.title(title) if ppt: addPPTslide( title=title, fig=plt.figure(title), notes='Fit paramaters double gaussian:\n mean down: %.3f counts' % par_fit[4] + ', mean up:%.3f counts' % par_fit[5] + ', std down: %.3f counts' % par_fit[2] + ', std up:%.3f counts' % par_fit[3] + '.Separation between peaks gaussians: %.3f std' % separation + '. Split between two levels: %.3f' % split) if separation < min_sep: raise FittingException( 'Separation between the peaks of the gaussian %.1f is less then %.1f std, indicating that the fit was not succesfull.' % (separation, min_sep)) if separation > max_sep: raise FittingException( 'Separation between the peaks of the gaussian %.1f is more then %.1f std, indicating that the fit was not succesfull.' % (separation, max_sep)) # count the number of transitions and their duration durations_dn_idx, durations_up_idx = transitions_durations(data, split) # throwing away the durations with less data points then min_duration durations_up_min_duration = durations_up_idx > min_duration durations_up = durations_up_idx[durations_up_min_duration] durations_dn_min_duration = durations_dn_idx > min_duration durations_dn = durations_dn_idx[durations_dn_min_duration] if len(durations_up) < 1: raise FittingException( 'All durations_up are shorter than the minimal duration.') if len(durations_dn) < 1: raise FittingException( 'All durations_dn are shorter than the minimal duration.') # calculating durations in seconds durations_dn = durations_dn / samplerate durations_up = durations_up / samplerate # sorting the durations durations_dn_srt = np.sort(durations_dn) durations_up_srt = np.sort(durations_up) # calculating the number of bins and counts for down level numbins_dn = int(np.sqrt(len(durations_dn_srt))) counts_dn, bins_dn = np.histogram(durations_dn_srt, bins=numbins_dn) if counts_dn[0] < 400: warnings.warn( 'Number of datapoints might not be enough to make an acurate fit of the exponantial decay for level down.' ) if counts_dn[0] < 50: raise FittingException( 'Number of datapoints is not be enough to make an acurate fit of the exponantial decay for level down.' ) bincentres_dn = np.array([(bins_dn[i] + bins_dn[i + 1]) / 2 for i in range(0, len(bins_dn) - 1)]) # fitting exponantial decay for down level A_dn_fit, B_dn_fit, gamma_dn_fit = fit_exp_decay(bincentres_dn, counts_dn) tunnelrate_dn = gamma_dn_fit / 1000 if verbose: print('Tunnel rate down: %.1f kHz' % tunnelrate_dn) if fig: title = 'Fitted exponantial decay, level down' plt.figure(title) plt.clf() plt.plot(bincentres_dn, counts_dn, 'o', label='Counts down') plt.plot(bincentres_dn, exp_function(bincentres_dn, A_dn_fit, B_dn_fit, gamma_dn_fit), 'r', label='Fitted exponantial decay \n $\Gamma_{dn}$: %.1f kHz' % tunnelrate_dn) plt.xlabel('Lifetime (s)') plt.ylabel('Counts per bin') plt.legend() plt.title(title) if ppt: addPPTslide(title=title, fig=plt.figure(title)) # calculating the number of bins and counts for up level numbins_up = int(np.sqrt(len(durations_up_srt))) counts_up, bins_up = np.histogram(durations_up_srt, bins=numbins_up) if counts_up[0] < 50: warnings.warn( 'Number of datapoints might not be enough to make an acurate fit of the exponantial decay for level up.' ) if counts_dn[0] < 50: raise FittingException( 'Number of datapoints is not be enough to make an acurate fit of the exponantial decay for level down.' ) bincentres_up = np.array([(bins_up[i] + bins_up[i + 1]) / 2 for i in range(0, len(bins_up) - 1)]) # fitting exponantial decay for up level A_up_fit, B_up_fit, gamma_up_fit = fit_exp_decay(bincentres_up, counts_up) tunnelrate_up = gamma_up_fit / 1000 if verbose: print('Tunnel rate up: %.1f kHz' % tunnelrate_up) if fig: title = 'Fitted exponantial decay, level up' plt.figure(title) plt.plot(bincentres_up, counts_up, 'o', label='Counts up') plt.plot(bincentres_up, exp_function(bincentres_up, A_up_fit, B_up_fit, gamma_up_fit), 'r', label='Fitted exponantial decay \n $\Gamma_{up}$: %.1f kHz' % tunnelrate_up) plt.xlabel('Lifetime (s)') plt.ylabel('Data points per bin') plt.legend() plt.title(title) if ppt: addPPTslide(title=title, fig=plt.figure(title)) parameters = { 'plunger value': plungervalue, 'sampling rate': samplerate, 'fit parameters double gaussian': par_fit, 'separations between peaks gaussians': separation, 'split between the two levels': split, 'fit parameters exp. decay down': [A_dn_fit, B_dn_fit, gamma_dn_fit], 'fit parameters exp. decay up': [A_up_fit, B_up_fit, gamma_up_fit] } return tunnelrate_dn, tunnelrate_up, parameters