def getting_amplitude_and_dt(ax: plt.Axes, x: np.ndarray, cold: np.ndarray, hot: np.ndarray) -> plt.Axes: """Adds hot and cold trace to axes with a straight line before and after transition to emphasise amplitude etc""" ax.set_title("Hot and cold part of transition") ax.set_xlabel('Sweep Gate (mV)') ax.set_ylabel('I (nA)') ax.plot(x, cold, color='blue', label='Cold', linewidth=1) ax.plot(x, hot, color='red', label='Hot', linewidth=1) # Add straight lines before and after transition to emphasise amplitude transition_width = 0.30 before_transition_id = U.get_data_index(x, np.mean(x) - transition_width, is_sorted=True) after_transition_id = U.get_data_index(x, np.mean(x) + transition_width, is_sorted=True) line = lm.models.LinearModel() top_line = line.fit(cold[:before_transition_id], x=x[:before_transition_id], nan_policy='omit') bottom_line = line.fit(cold[after_transition_id:], x=x[after_transition_id:], nan_policy='omit') ax.plot(x, top_line.eval(x=x), linestyle=':', color='black') ax.plot(x, bottom_line.eval(x=x), linestyle=':', color='black') # Add vertical arrow between dashed lines # x_val = (np.mean(x) + x[-1]) / 2 # 3/4 along x_val = 0.20 y_bot = bottom_line.eval(x=x_val) y_top = top_line.eval(x=x_val) arrow = ax.annotate(text='', xy=(x_val, y_bot), xytext=(x_val, y_top), arrowprops=dict(arrowstyle='<|-|>', lw=1)) text = ax.text(x=x_val + 0.02, y=(y_top + y_bot) / 2, s='dI/dN') ax.set_xlim(-0.5, 0.5) ax.legend(loc='center left') # Add horizontal lines to show thetas # TODO: should decide if I want to do this from fit results, or if it is just to give an idea theta.. return ax
def one_d_data_vs_n(self): if self.datnum: self.which = ['i_sense_cold', 'dndt', 'occupation'] try: x, data_dndt = _get_x_and_data(self.datnum, self.experiment_name, 'dndt') except NotFoundInHdfError: logger.warning(f'Dat{self.datnum}: dndt data not found, probably a transition only dat') return go.Figure() nrg_func = NRG_func_generator(which='dndt') nrg_dndt = nrg_func(x, self.mid, self.g, self.theta, self.amp, self.lin, self.const, self.occ_lin) nrg_func = NRG_func_generator(which='occupation') occupation = nrg_func(x, self.mid, self.g, self.theta, self.amp, self.lin, self.const, self.occ_lin) # Rescale dN/dTs to have a peak at 1 nrg_dndt = nrg_dndt * (1 / np.nanmax(nrg_dndt)) x_max = x[get_data_index(data_dndt, np.nanmax(data_dndt))] x_range = abs(x[-1] - x[0]) indexs = get_data_index(x, [x_max - x_range / 50, x_max + x_range / 50]) avg_peak = np.nanmean(data_dndt[indexs[0]:indexs[1]]) # avg_peak = np.nanmean(data_dndt[np.nanargmax(data_dndt) - round(x.shape[0] / 50): # np.nanargmax(data_dndt) + round(x.shape[0] / 50)]) data_dndt = data_dndt * (1 / avg_peak) if (new_max := np.nanmax(np.abs([np.nanmax(data_dndt), np.nanmin(data_dndt)]))) > 5: # If very noisy data_dndt = data_dndt / (new_max / 5) # Reduce to +-5ish interp_range = np.where(np.logical_and(occupation < 0.99, occupation > 0.01)) if len(interp_range[0]) > 5: # If enough data to actually plot something interp_data = occupation[interp_range] interp_x = x[interp_range] interper = interp1d(x=interp_x, y=interp_data, assume_sorted=True, bounds_error=False) occ_x = interper(x) plotter = OneD(dat=None) fig = plotter.figure(xlabel='Occupation', ylabel='Arbitrary', title=f'dN/dT vs N: G={self.g:.2f}mV, ' f'{THETA}={self.theta:.2f}mV, ' f'{THETA}/G={self.theta / self.g:.2f}' f' -- Dat{self.datnum}') fig.add_trace(plotter.trace(x=occ_x, data=data_dndt, name='Data dN/dT', mode='lines+markers')) fig.add_trace(plotter.trace(x=occ_x, data=nrg_dndt, name='NRG dN/dT', mode='lines')) return fig
def get_dats_closest_to_temp(self, temp: float) -> SingleTraceData: """Return the dats at the closest temperature to requested. If it is more than 10% off then warn user""" v = list(self.temp_dat_dict.keys())[U.get_data_index( list(self.temp_dat_dict.keys()), temp)] if v not in self._single_trace_datas.keys(): if (diff := abs(temp - v)) > temp / 10: logging.warning( f'Closest temperature to requested is {v:.2f} which is {diff:.2f} from requested {temp:.2f}' ) dats = self.temp_dat_dict[v] self._single_trace_datas[v] = SingleTraceData(dats, temperature=v)
def plot_csq_trace(dat: DatHDF, cutoff: Optional[float] = None) -> Data1D: plotter = OneD(dat=dat) plotter.TEMPLATE = 'simple_white' fig = plotter.figure(xlabel='CSQ Gate (mV)', ylabel='Current (nA)', title='CS current vs CSQ gate') x = dat.Data.x data = dat.Data.i_sense if cutoff: upper_lim = U.get_data_index(x, cutoff) x, data = x[:upper_lim], data[:upper_lim] fig.add_trace(plotter.trace(data=data, x=x)) fig.show() return Data1D(x=x, data=data)
def do_calc(datnum): dat = get_dat(datnum) fit = dat.Transition.avg_fit mid = fit.best_values.mid width = fit.best_values.theta * 15 x1, x2 = U.get_data_index(dat.Transition.avg_x, [mid - width, mid + width], is_sorted=True) x = dat.Transition.avg_x[x1:x2] data = dat.Transition.avg_data[x1:x2] new_fit = dat.Transition.get_fit(which='avg', name='narrow_centered', overwrite=True, x=x, data=data) print(f'Fitting Dat{dat.datnum} from {x[0]:.2f} -> {x[-1]:.2f}mV') return new_fit
def vp_transition_fit(self) -> DataInfo: dat = self.vp_dat self.vp_info = self.DataInfo(dat, xlabel='V_P (mV)') vp = self.vp_info vp.full_data = dat.Data.i_sense vp.full_x = dat.Data.x vp.smoothed_data, vp.smoothed_x = U.resample_data(vp.full_data, vp.full_x, max_num_pnts=100, resample_method='bin') vp.rough_center = vp.smoothed_x[np.nanargmin(np.diff(vp.smoothed_data))] ids = U.get_data_index(vp.full_x, [vp.rough_center - 4, vp.rough_center + 4]) vp.fit_data = vp.full_data[ids[0]:ids[1]] vp.fit_x = vp.full_x[ids[0]:ids[1]] vp.fit = self._fit(vp.fit_data, vp.fit_x) return self.vp_info
def plot_slice(datnum, data_name, slice_val) -> go.Figure: if datnum: dat = get_dat(datnum) data = dat.Data.get_data(data_name) if data.ndim > 1: x = dat.Data.get_data('x') y = dat.Data.get_data('y') if slice_val is None: slice_val = y[0] slice_val = U.get_data_index(y, slice_val) z = dat.Data.get_data('i_sense')[slice_val] x, z = [U.bin_data_new(arr, int(round(z.shape[-1] / 500))) for arr in (x, z)] plotter = DashOneD(dat=dat) fig = plotter.plot(data=z, x=x, mode='lines', title=f'Dat{datnum}: Slice at y = {y[slice_val]:.1f}') return fig return go.Figure()
def _center_2d_data(x, data2d, occupation2d) -> Data2D: assert all(a.ndim == 2 for a in [data2d, occupation2d]) new_data = [] for data, occupation in zip(data2d, occupation2d): idx = U.get_data_index(occupation, 0.5) # Get values near to occ = 0.5 interper = interp1d(occupation[idx - 1:idx + 2], x[idx - 1:idx + 2], bounds_error=False, fill_value=(0, 1)) # will include occ = 0.5 half_x = interper(0.5) new_x = x - half_x data_interper = interp1d(new_x, data, bounds_error=False, fill_value=(data[0], data[-1])) new_data.append(data_interper(x)) return Data2D(x=x, y=np.arange(len(new_data)), data=np.array(new_data))
def plot_slice(fig, slice_val, slice_tog): if slice_tog == [True]: if not slice_val: slice_val = 0 d = fig.get('data', None) if d: d = d[0] x = d.get('x', None) y = d.get('y', None) z = d.get('z', None) if all([a is not None for a in [x, y, z]]): # x, z = [U.bin_data_new(arr, int(round(z.shape[-1] / 500))) for arr in (x, z)] slice_index = U.get_data_index(y, slice_val) data = z[slice_index] fig = go.Figure() fig.add_trace(go.Scatter(mode='lines', x=x, y=data)) fig.update_layout(title=f'Slice at y = {y[slice_index]:.1f}') return fig return go.Figure()
def plotting_center_shift(): nrg_func = NRG_func_generator('occupation') params = lm.Parameters() params.add_many( ('mid', 0, True, -200, 200, None, 0.001), ('theta', 3.9, False, 1, 500, None, 0.001), ('amp', 1, True, 0, 3, None, 0.001), ('lin', 0, True, 0, 0.005, None, 0.00001), ('occ_lin', 0, True, -0.0003, 0.0003, None, 0.000001), ('const', 0, True, -2, 10, None, 0.001), ('g', 1, True, 0.2, 2000, None, 0.01), ) model = lm.Model(nrg_func) x = np.linspace(-10, 5000, 10000) gs = np.linspace(0, 200, 201) thetas = np.logspace(0.1, 2, 20) # thetas = np.linspace(1, 500, 10) # thetas = [1, 2, 5, 10, 20] all_mids = [] for theta in thetas: params['theta'].value = theta mids = [] for g in gs: params['g'].value = g occs = model.eval(x=x, params=params) mids.append(x[U.get_data_index(occs, 0.5, is_sorted=True)]) all_mids.append(mids) plotter = OneD(dat=None) fig = plotter.figure(xlabel='Gamma /mV', ylabel='Shift of 0.5 OCC', title='Shift of 0.5 Occupation vs Theta and G') fig.update_layout(legend=dict(title='Theta /mV')) for mids, theta in zip(all_mids, thetas): fig.add_trace( plotter.trace(data=mids, x=gs, name=f'{theta:.1f}', mode='lines')) fig.show() return fig
def do_calc(datnum): """Just a function which can be passed to a process pool for faster calculation""" save_name = 'SPS.0045' dat = get_dat(datnum) setpoints = [0.0045, None] # Get other inputs setpoint_times = square_wave_time_array(dat.SquareEntropy.square_awg) sp_start, sp_fin = [U.get_data_index(setpoint_times, sp) for sp in setpoints] logger.debug(f'Setpoint times: {setpoints}, Setpoint indexs: {sp_start, sp_fin}') # Run Fits pp = dat.SquareEntropy.get_ProcessParams(name=None, # Start from default and modify from there setpoint_start=sp_start, setpoint_fin=sp_fin, transition_fit_func=i_sense, save_name=save_name) out = dat.SquareEntropy.get_Outputs(name=save_name, inputs=None, process_params=pp, overwrite=False) dat.Entropy.get_fit(which='avg', name=save_name, data=out.average_entropy_signal, x=out.x, check_exists=False) [dat.Entropy.get_fit(which='row', row=i, name=save_name, data=row, x=out.x, check_exists=False) for i, row in enumerate(out.entropy_signal)]
for dat in all_dats: w_val = 100 strong_fit = dat.NrgOcc.get_fit(name=strong_fit_name) if strong_fit.best_values.g > strong_gamma_cutoff: fit_name = strong_fit_name else: fit_name = weak_fit_name int_data = get_integrated_data( dat, fit_name=fit_name, zero_point=-w_val, csq_datnum=csq_datnum, which_linear_theta_fit=which_linear_theta_fit) idx = U.get_data_index(int_data.x, w_val) # Measure entropy at x = xxx if idx >= int_data.x.shape[ -1] - 1: # or the end if it doesn't reach xxx idx -= 10 int_entropy = np.nanmean(int_data.data[idx - 10:idx + 10]) avg_dndt = get_avg_entropy_data(dat, center_func=_center_func, csq_datnum=csq_datnum) fit = dat.Entropy.get_fit(calculate_only=True, data=avg_dndt.data, x=avg_dndt.x) cg_vals.append(dat.Logs.dacs['ESC']) int_entropies.append(int_entropy) fit_entropies.append(fit.best_values.dS)