def mixer_carrier_cancellation(SH, source, MC,
                               chI_par, chQ_par,
                               frequency: float=None,
                               SH_ref_level: float=-40,
                               init_stepsize: float=0.1,
                               x0=(0.0, 0.0),
                               label: str='Offset_calibration',
                               ftarget=-110, maxiter=300):
    """
    Varies the mixer offsets to minimize leakage at the carrier frequency.
    this is a generic version.

    Args:
        SH           (instr) : Signal hound used to measure power
        source       (instr) : mw_source that provides the leakage tone
        MC           (instr) :
        chI_par       (par)  :
        chQ_par       (par)  :
        frequency    (float) : the frequency in Hz at which to minimize leakage
        SH_ref_level (float) : Signal hound reference level
        init_stepsize (float): initial stepsize for Nelder mead algorithm
        x0           (tuple) : starting point for optimization
        ftarget      (float) : termination value
    """

    source.on()
    if frequency is None:
        frequency = source.frequency()
    else:
        source.frequency(frequency)

    '''
    Make coarse sweeps to approximate the minimum
    '''
    SH.ref_lvl(SH_ref_level)
    detector = det.Signal_Hound_fixed_frequency(
        SH, frequency=(source.frequency()),
        Navg=5, delay=0.0, prepare_for_each_point=False)

    ad_func_pars = {'adaptive_function': cma.fmin,
                    'x0': x0,
                    'sigma0':1,
                    'options': {'maxiter': maxiter,    # maximum function cals
                                # Scaling for individual sigma's
                                'cma_stds': [init_stepsize]*2,
                                'ftarget': ftarget
                                },
                    'minimize': True}
    MC.set_sweep_functions([chI_par, chQ_par])
    MC.set_detector_function(detector)  # sets test_detector
    MC.set_adaptive_function_parameters(ad_func_pars)
    MC.run(name=label, mode='adaptive')
    a = ma.OptimizationAnalysis(label=label)
    # v2 creates a pretty picture of the optimizations
    ma.OptimizationAnalysis_v2(label=label)

    ch_1_min = a.optimization_result[0][0]
    ch_2_min = a.optimization_result[0][1]
    return ch_1_min, ch_2_min
def mixer_skewness_calibration_CBoxV3(SH, source, LutMan, MC, CBox,
                                      f_mod,
                                      name='mixer_skewness_calibration_CBox'):
    '''
    Inputs:
        SH              (instrument)     the signal hound
        source          (instrument)     MW-source used for driving
        LutMan          (instrument)     LutMan responsible for loading pulses
        CBox            (instrument)     responsible for loading qumis and
        f_mod           (float Hz)       Modulation frequency

    returns:
        alpha, phi     the coefficients that go in the predistortion matrix

    Loads a continuous wave in the lookuptable and changes the predistortion
    to minimize the power in the spurious sideband.

    For details, see Leo's notes on mixer skewness calibration in the docs
    '''

    # phi and alpha are the coefficients that go in the predistortion matrix

    # Load the pulses required for a conintuous tone
    LutMan.lut_mapping()[0] = 'ModBlock'
    Mod_Block_len = 500e-9
    LutMan.Q_modulation(f_mod)
    LutMan.Q_block_length(Mod_Block_len)
    LutMan.Q_ampCW(.5)  # not 1 as we want some margin for the alpha correction
    LutMan.load_pulses_onto_AWG_lookuptable()

    # load the QASM/QuMis sequence
    Mod_Block_len_clk = ins_lib.convert_to_clocks(Mod_Block_len) - 1
    # -1 is a hack to fix some problems with the CBox AWG output
    # 19-07-2017 XFU & MAR
    operation_dict = {}
    operation_dict['Pulse'] = {
        'duration': Mod_Block_len_clk,
        'instruction': ins_lib.cbox_awg_pulse(
            codeword=0, awg_channels=[LutMan.awg_nr()],
            duration=Mod_Block_len_clk)}

    # this generates a SSB coninuous wave sequence
    cw_tone_elt = sqqs.CW_tone()
    cw_tone_asm = qta.qasm_to_asm(cw_tone_elt.name, operation_dict)
    CBox.load_instructions(cw_tone_asm.name)
    CBox.start()

    frequency = source.frequency() - f_mod
    alpha_swf = cbs.Lutman_par_with_reload_single_pulse(
        LutMan=LutMan,
        parameter=LutMan.mixer_alpha,
        pulse_names=['ModBlock'])

    phi_swf = cbs.Lutman_par_with_reload_single_pulse(
        LutMan=LutMan,
        parameter=LutMan.mixer_phi,
        pulse_names=['ModBlock'])
    d = det.Signal_Hound_fixed_frequency(SH, frequency)

    ad_func_pars = {'adaptive_function': nelder_mead,
                    'x0': [1.0, 0.0],
                    'initial_step': [.4, 20],
                    'no_improv_break': 10,
                    'minimize': True,
                    'maxiter': 500}
    MC.set_sweep_functions([alpha_swf, phi_swf])
    MC.set_detector_function(d)
    MC.set_adaptive_function_parameters(ad_func_pars)
    MC.set_adaptive_function_parameters(ad_func_pars)
    MC.run(name=name, mode='adaptive')
    a = ma.OptimizationAnalysis(label=name)
    ma.OptimizationAnalysis_v2(label=name)

    alpha = a.optimization_result[0][0]
    phi = a.optimization_result[0][1]

    return phi, alpha