assert np.all(ri.adc_valon.get_phase_locks()) tools.set_and_attempt_external_phase_lock(ri=ri, f_lo=1e-6 * f_lo, f_lo_spacing=1e-6 * df_lo) for attenuation_index, (attenuation, fft_gain) in enumerate(zip(attenuations, fft_gains)): ri.set_dac_attenuator(attenuation) ri.set_fft_gain(fft_gain) state = hw.state() state['lo_index'] = lo_index coarse_sweep = acquire.run_loaded_sweep(ri, length_seconds=sweep_length_seconds, tone_bank_indices=np.arange(0, num_sweep_tones, coarse_stride))[0] npd.write(coarse_sweep) coarse_f_r = coarse_sweep.resonator.f_0 coarse_Q = coarse_sweep.resonator.Q logger.info("Coarse sweep f_r = {:.3f} MHz +/- {:.0f} Hz".format(1e-6 * coarse_f_r, coarse_sweep.resonator.f_0_error)) logger.info("Coarse sweep Q = {:.0f} +/- {:.0f}".format(coarse_Q, coarse_sweep.resonator.Q_error)) df_filterbank = calculate.stream_sample_rate(ri_state) f_baseband_bin_center = df_filterbank * np.round(f_baseband.mean() / df_filterbank) f_lo_fine = df_lo * np.round((coarse_f_r - f_baseband_bin_center) / df_lo) ri.set_lo(lomhz=1e-6 * f_lo_fine, chan_spacing=1e-6 * df_lo) fine_indices = np.where(np.abs(f_lo_fine + f_baseband - coarse_f_r) <= (fine_sweep_num_linewidths / 2) * (coarse_f_r / coarse_Q))[0] fine_sweep_off = acquire.run_loaded_sweep(ri, length_seconds=sweep_length_seconds, tone_bank_indices=fine_indices)[0] ri.select_bank(np.argmin(np.abs(f_baseband_bin_center - f_baseband))) ri.select_fft_bins(np.array([0])) logger.info("Recording {:.1f} s stream".format(stream_length_seconds)) stream_off = ri.get_measurement(num_seconds=stream_length_seconds, demod=True)[0] npd.write(basic.SingleSweepStream(sweep=fine_sweep_off, stream=stream_off, state=state)) npd.write(ri.get_adc_measurement()) i_mA = float(raw_input("Enable the source output and enter the current in mA: ")) state['source']['current_mA'] = i_mA
coarse_sweep = acquire.run_sweep( ri=ri, tone_banks=1e-6 * (f_lo + f_baseband[::coarse_stride, np.newaxis]), num_tone_samples=2**tone_sample_exponent, length_seconds=stream_length_seconds, state=coarse_state, verbose=True)[0] npd.write(coarse_sweep) coarse_f_r = coarse_sweep.resonator.f_0 coarse_Q = coarse_sweep.resonator.Q logger.info("Coarse sweep f_r = {:.3f} MHz +/- {:.0f} Hz".format( 1e-6 * coarse_f_r, coarse_sweep.resonator.f_0_error)) logger.info("Coarse sweep Q = {:.0f} +/- {:.0f}".format( coarse_Q, coarse_sweep.resonator.Q_error)) df_filterbank = calculate.stream_sample_rate(ri_state) f_baseband_bin_center = df_filterbank * np.round( f_baseband.mean() / df_filterbank) f_lo_fine = f_lo_spacing * np.round( (coarse_f_r - f_baseband_bin_center) / f_lo_spacing) ri.set_lo(lomhz=1e-6 * f_lo_fine, chan_spacing=1e-6 * f_lo_spacing) fine_indices = np.where( np.abs(f_lo_fine + f_baseband - coarse_f_r) <= (fine_sweep_num_linewidths / 2) * (coarse_f_r / coarse_Q))[0] fine_sweep = acquire.run_sweep( ri=ri, tone_banks=1e-6 * (f_lo + f_baseband[fine_indices, np.newaxis]), num_tone_samples=2**tone_sample_exponent, length_seconds=stream_length_seconds,
stream_seconds = 0.01 f_lo_resolution = 10e3 # 5 kHz is the limit of the LO in divide-by-1 mode. num_tones_maximum = 2 ** 7 # This currently has to be a power of two. f_minimum = 5e6 # The minimum spacing from the LO frequency. f_maximum = 200e6 # The filter turns on not too far above this frequency. num_filterbanks_per_tone = 16 # The minimum spacing between filter banks read out simultaneously. # Hardware ri = hardware_tools.r2_with_mk2() ri.set_dac_atten(40) ri.set_fft_gain(4) ri.set_modulation_output('high') roach_state = ri.state # Cache this for speed; its values are in Hz. # Calculated parameters f_tone = num_filterbanks_per_tone * calculate.stream_sample_rate(roach_state) # The minimum spacing between tones print("Minimum tone spacing: {:.0f} kHz.".format(1e-3 * f_tone)) tone_sample_exponent = np.ceil(np.log2(roach_state.adc_sample_rate / f_lo_resolution)) num_tone_samples = 2 ** tone_sample_exponent f_roach_resolution = roach_state.adc_sample_rate / num_tone_samples print("LO resolution: {:.2f} kHz.".format(1e-3 * f_lo_resolution)) print("ROACH resolution: {:.2f} kHz.".format(1e-3 * f_roach_resolution)) num_tones = num_tones_maximum while num_tones * f_tone > f_maximum - f_minimum: num_tones /= 2 f_block = num_tones * f_tone # The spacing between blocks print("Using {} simultaneous tones spanning {:.1f} MHz.".format(num_tones, 1e-6 * f_block)) f_center_MHz = 1e-6 * np.arange(f_start, f_stop, f_block) print("Block center frequencies in MHz: {}".format(', '.join(['{:.1f}'.format(f) for f in f_center_MHz]))) f_lo_offset_MHz = 1e-6 * (np.arange(-f_tone / 2, f_tone / 2, f_lo_resolution) - f_minimum) # This order covers the entire band then comes back to fill in the gaps.