Mixer tunning code: Difference between revisions

From QT5201U wiki
Jump to navigation Jump to search
Yifan (talk | contribs)
No edit summary
Yifan (talk | contribs)
No edit summary
Line 1: Line 1:
{{code|
class MixerTuner(object):
class MixerTuner(object):
     def __init__(self, qm, sa, element, lo_freq, if_freq, ref_power):
     def __init__(self, qm, sa, element, lo_freq, if_freq, ref_power):
Line 99: Line 97:
         else:
         else:
             raise ValueError(result.message)
             raise ValueError(result.message)
}}

Revision as of 12:46, 27 April 2021

class MixerTuner(object):

   def __init__(self, qm, sa, element, lo_freq, if_freq, ref_power):
       self.qm = qm
       self.element = element
       self.sa = sa 
       self.lo_freq = lo_freq
       self.if_freq = if_freq
       self.ref_power = ref_power
       self.job = self.init_qm()  
   def init_qm(self):
       with program() as cw:
           with infinite_loop_():
               play("CW", element)
       self.job = self.qm.execute(cw)
       return self.job
   
   def close(self):
       self.job.halt()
   
   def no_dc_offset_correction(self):
       self.qm.set_output_dc_offset_by_element(self.element, "I", float(0)) 
       self.qm.set_output_dc_offset_by_element(self.element, "Q", float(0))
       self.qm.set_mixer_correction("mixer_qubit", qubit_IF, qubit_LO, IQ_imbalance(0, 0))
       freqs, amps = self.sa.sweep(center=self.lo_freq, span= 250e6, ref_power = self.ref_power)
       plt.figure()
       plt.plot(freqs, amps)
       
   def offset_lo_leakage(self, fatol=1):  
       # fatol = 1dB
       print('Offset Lo leakage')
       freq_i, amps_i = sa.sweep(center=self.lo_req, span= 250e6, ref_power = self.ref_power)
       plt.plot(freqs_i, amps_i)
       
       def objective_func(offset_I, offset_Q):
           self.qm.set_output_dc_offset_by_element(self.element, "I", float(offset_I)) 
           self.qm.set_output_dc_offset_by_element(self.element, "Q", float(offset_Q))
       
           freqs, amps = self.sa.sweep(center=self.lo_req, span= 250e6, ref_power = self.ref_power)
           
           # around postion of lo, required_sideband, removed_sideband
           # np.searchsorted(list, threshold, side='right') most fast way 
           # index_required_sideband = np.argmax(freq>= (self.lo_freq+self.if_freq))
           # index_removed_sideband = np.argmax(freq>= (self.lo_freq-self.if_freq))
           
           threshold = np.mean(amps)
           index_lo = np.argmax(freq>= self.lo_freq)
           lo_peak_amps = amps[index_lo]
           contrast = lo_peak_amps - threshold
           return np.abs(contrast) 
       
       result = sc.optimize.minimize(objective_func, [0, 0], method='Nelder-Mead', fatol= fatol)
       
       if result.success:
           fitted_params = result.x
           print("The I Q offsets are ",fitted_params)
           self.qm.set_output_dc_offset_by_element(self.element, "I", float(fitted_params[0])) 
           self.qm.set_output_dc_offset_by_element(self.element, "Q", float(fitted_params[1]))
           freqs_f, amps_f = self.sa.sweep(center=self.lo_req, span= 250e6, ref_power = self.ref_power)
           plt.plot(freqs_f, amps_f)
       else:
           raise ValueError(result.message)
       
   def offset_iq_imbalance(self, fatol=1):  
       # fatol = 1dB
       print('Offset IQ imbalance')
       freq_i, amps_i = sa.sweep(center=self.lo_req, span= 250e6, ref_power = self.ref_power)
       plt.plot(freqs_i, amps_i)
       
       
       def objective_func(gain, phase):
           self.qm.set_mixer_correction("mixer_"+element, int(self.if_freq), int(self.lo_freq), IQ_imbalance(gain, phase))
       
           freqs, amps = self.sa.sweep(center=self.lo_req, span= 250e6, ref_power = self.ref_power)
           
           # around postion of lo, required_sideband, removed_sideband
           # np.searchsorted(list, threshold, side='right') most fast way 
           # index_required_sideband = np.argmax(freq>= (self.lo_freq+self.if_freq))
           index_removed_sideband = np.argmax(freq>= (self.lo_freq-self.if_freq))
           
           threshold = np.mean(amps)
           removed_sideband_peak_amps = amps[index_removed_sideband]
           contrast = removed_sideband_peak_amps - threshold
           return np.abs(contrast) 
       
       result = sc.optimize.minimize(objective_func, [0, 0], method='Nelder-Mead', fatol= fatol)
       
       if result.success:
           fitted_params = result.x
           print("The mixer correction is ",fitted_params)
           fitted_params
           self.qm.set_mixer_correction("mixer_"+element, int(self.if_freq), int(self.lo_freq), IQ_imbalance(fitted_params[0], fitted_params[0]))
           
           freqs_f, amps_f = self.sa.sweep(center=self.lo_req, span= 200e6, ref_power = self.ref_power)
           plt.plot(freqs_f, amps_f)
       else:
           raise ValueError(result.message)