def nelder_mead(self,
                    no_improve_thr=10e-6,
                    no_improv_break=10,
                    max_iter=0,
                    alpha=1.,
                    gamma=2.,
                    rho=-0.5,
                    sigma=0.5,
                    time=0):
        '''
        Pure Python/Numpy implementation of the Nelder-Mead algorithm.
        Reference: https://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method
        '''
        '''
            @param f (function): function to optimize, must return a scalar score
                and operate over a numpy array of the same dimensions as x_start
            @param x_start (numpy array): initial position
            @param step (float): look-around radius in initial step
            @no_improv_thr,  no_improv_break (float, int): break after no_improv_break iterations with
                an improvement lower than no_improv_thr
            @max_iter (int): always break after this number of iterations.
                Set it to 0 to loop indefinitely.
            @alpha, gamma, rho, sigma (floats): parameters of the algorithm
                (see Wikipedia page for reference)
            return: tuple (best parameter array, best score)
        '''

        index = time % 2
        dim = len(self.var)
        "tell AWG to apply DC offset(x) on I & Q"
        AWG_Sinewave(25, self.IQparams)
        "read signal amplitude at LO frequency in and assign it as score"
        MXA.preamp(mxa, action=['Set', 'OFF'])
        # MXA.preamp_band(mxa, action=['Set','FULL'])
        # MXA.attenuation(mxa, action=['Set','14dB'])
        MXA.attenuation_auto(mxa, action=['Set', 'ON'])
        power = float((MXA.fpower(
            mxa,
            str(5.5 - 0.025 * index) +
            'GHz')).split('dBm')[0]) - index * float(
                (MXA.fpower(mxa,
                            str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
        prev_best = power
        no_improv = 0
        res = [[self.var, prev_best]]

        # while True:
        #     print("LOPower: %s" %power)
        #     if bool(input('hello')): break

        for i in range(dim):
            x = copy.copy(self.var)
            x[i] = x[i] + self.step[i]
            "tell AWG to apply DC offset(x) on I & Q"
            if self.suppression == 'LO': self.IQparams[:2] = x
            elif self.suppression == 'MR': self.IQparams[2:] = x

            AWG_Sinewave(25, self.IQparams)
            "read signal amplitude at LO frequency in and assign it as score"
            power = float(
                (MXA.fpower(mxa,
                            str(5.5 - 0.025 * index) + 'GHz')).split('dBm')[0]
            ) - index * float(
                (MXA.fpower(mxa,
                            str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
            score = power
            res.append([x, score])

        # simplex iter
        iters = 0
        while 1:
            # order
            res.sort(key=lambda x: x[1])
            if self.suppression == 'LO': self.IQparams[:2] = res[0][0]
            elif self.suppression == 'MR': self.IQparams[2:] = res[0][0]
            # print(Fore.YELLOW + "\rProgress time#%s: %s" %(time, self.IQparams), end='\r', flush=True)
            best = res[0][1]

            # break after max_iter
            if max_iter and iters >= max_iter:
                return res[0]
            iters += 1

            # AWG_Sinewave(25, self.IQparams)
            # if float((RSA5.fpower(rsa, str(5.5)+'GHz')).split('dBm')[0]) < -65. and float((RSA5.fpower(rsa, str(5.475)+'GHz')).split('dBm')[0]) < -65.:
            #     return array([self.IQparams, best, 0.])

            if best < prev_best - no_improve_thr or best == prev_best:
                no_improv = 0
                prev_best = best
            else:
                no_improv += 1

            if no_improv >= no_improv_break:
                AWG_Sinewave(25, self.IQparams)
                print("Rest at Optimized IQ Settings: %s" % self.IQparams)
                return array([self.IQparams, best])  # Optimized parameters

            # centroid
            x0 = [0.] * dim
            for tup in res[:-1]:
                for i, c in enumerate(tup[0]):
                    x0[i] += c / (len(res) - 1)

            # reflection
            xr = x0 + alpha * (x0 - res[-1][0])
            if self.suppression == 'LO': self.IQparams[:2] = xr
            elif self.suppression == 'MR': self.IQparams[2:] = xr
            "tell AWG to apply DC offset(x) on I & Q"
            AWG_Sinewave(25, self.IQparams)
            "read signal amplitude at LO frequency in and assign it as score"
            power = float(
                (MXA.fpower(mxa,
                            str(5.5 - 0.025 * index) + 'GHz')).split('dBm')[0]
            ) - index * float(
                (MXA.fpower(mxa,
                            str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
            rscore = power
            if res[0][1] <= rscore < res[-2][1]:
                del res[-1]
                res.append([xr, rscore])
                continue

            # expansion
            if rscore < res[0][1]:
                xe = x0 + gamma * (x0 - res[-1][0])
                if self.suppression == 'LO': self.IQparams[:2] = xe
                elif self.suppression == 'MR': self.IQparams[2:] = xe
                "tell AWG to apply DC offset(x) on I & Q"
                AWG_Sinewave(25, self.IQparams)

                "read signal amplitude at LO frequency in and assign it as score"
                power = float((MXA.fpower(
                    mxa,
                    str(5.5 - 0.025 * index) +
                    'GHz')).split('dBm')[0]) - index * float((MXA.fpower(
                        mxa,
                        str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
                escore = power
                if escore < rscore:
                    del res[-1]
                    res.append([xe, escore])
                    continue
                else:
                    del res[-1]
                    res.append([xr, rscore])
                    continue

            # contraction
            xc = x0 + rho * (x0 - res[-1][0])
            if self.suppression == 'LO': self.IQparams[:2] = xc
            elif self.suppression == 'MR': self.IQparams[2:] = xc
            "tell AWG to apply DC offset(x) on I & Q"
            AWG_Sinewave(25, self.IQparams)

            "read signal amplitude at LO frequency in and assign it as score"
            power = float(
                (MXA.fpower(mxa,
                            str(5.5 - 0.025 * index) + 'GHz')).split('dBm')[0]
            ) - index * float(
                (MXA.fpower(mxa,
                            str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
            cscore = power
            if cscore < res[-1][1]:
                del res[-1]
                res.append([xc, cscore])
                continue

            # reduction
            x1 = res[0][0]
            nres = []
            for tup in res:
                redx = x1 + sigma * (tup[0] - x1)
                if self.suppression == 'LO': self.IQparams[:2] = redx
                elif self.suppression == 'MR': self.IQparams[2:] = redx
                "tell AWG to apply DC offset(x) on I & Q"
                AWG_Sinewave(25, self.IQparams)

                "read signal amplitude at LO frequency in and assign it as score"
                power = float((MXA.fpower(
                    mxa,
                    str(5.5 - 0.025 * index) +
                    'GHz')).split('dBm')[0]) - index * float((MXA.fpower(
                        mxa,
                        str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
                score = power
                nres.append([redx, score])
            res = nres
Ejemplo n.º 2
0
def test():

    LO_0 = float((MXA.fpower(mxa, str(5.5) + 'GHz')).split('dBm')[0])
    Mirror_0 = float((MXA.fpower(mxa, str(5.475) + 'GHz')).split('dBm')[0])
    Initial = [0., 0., 1., 0., 0.]
    time = 0
    OPT = IQ_Cal()
    OPT.IQparams = array(Initial, dtype=float64)  #overwrite initial values
    result = OPT.nelder_mead(time=time)
    prev = result[0]
    no_improv, no_improv_thr, no_improv_break = 0, 1e-5, 4
    LO, Mirror, T = [], [], []
    while True:
        time += 1
        if time % 2: OPT = IQ_Cal('MR', result[0], ratio=time)
        else: OPT = IQ_Cal('LO', result[0], ratio=time)
        result = OPT.nelder_mead(time=time)
        # if len(result) == 3:
        #     print("Optimized IQ parameters:\n %s" %result)
        #     break
        LO.append(
            float((MXA.fpower(mxa,
                              str(5.5) + 'GHz')).split('dBm')[0]) - LO_0)
        Mirror.append(
            float((MXA.fpower(mxa,
                              str(5.475) + 'GHz')).split('dBm')[0]) - Mirror_0)
        print(Back.BLUE + Fore.WHITE +
              "Mirror has been suppressed for %s from %s" %
              (Mirror[-1], Mirror_0))
        T.append(time)
        ssq = sum((result[0] - prev)**2)
        if ssq > no_improv_thr:
            no_improv = 0
            prev = result[0]
        else:
            no_improv += 1

        if no_improv >= no_improv_break:
            AWG_Sinewave(25, OPT.IQparams)
            print(type(OPT.IQparams))
            print("Optimized IQ parameters:\n %s" % result)
            print("Amplitude Imbalance:\n %s" % OPT.IQparams[2])
            if OPT.IQparams[3] > OPT.IQparams[
                    4] and OPT.IQparams[3] - OPT.IQparams[4] < 180:
                print("phase skew I-Q:\n %s" %
                      (OPT.IQparams[3] - OPT.IQparams[4]))
            if OPT.IQparams[3] > OPT.IQparams[
                    4] and OPT.IQparams[3] - OPT.IQparams[4] > 180:
                print("phase skew Q-I:\n %s" %
                      (360 - (OPT.IQparams[3] - OPT.IQparams[4])))
            if (OPT.IQparams[4] > OPT.IQparams[3]
                    and OPT.IQparams[4] - OPT.IQparams[3] < 180) or (
                        OPT.IQparams[3] > OPT.IQparams[4]
                        and OPT.IQparams[3] - OPT.IQparams[4] > 180):
                print("phase skew Q-I:\n %s" %
                      (OPT.IQparams[4] - OPT.IQparams[3]))

            if (OPT.IQparams[2] > -1.0) and (OPT.IQparams[2] < 1.0):
                Iamp = 1
                Qamp = Iamp * OPT.IQparams[2]
            else:
                Qamp = 1
                Iamp = Qamp / OPT.IQparams[2]

            print("Ioffset:\n %s" % OPT.IQparams[0])
            print("Qoffset:\n %s" % OPT.IQparams[1])
            print("Iamp:\n %s" % Iamp)
            print("Qamp:\n %s" % Qamp)
            print("Iphase:\n %s" % OPT.IQparams[3])
            print("Qphase:\n %s" % OPT.IQparams[4])

            break

    curve(T, LO, 'LO Leakage vs time', 'T(#)', 'DLO(dB)')
    curve(T, Mirror, 'Mirror Image vs time', 'T(#)', 'DMirror(dB)')

    # closing instruments:
    ans = input("Press any keys to close AWG, PSGA and RSA-5 ")
    AWG.Abort_Gen(awgsess)
    AWG.close(awgsess)
    PSGA.rfoutput(saga, action=['Set', 0])
    PSGA.close(saga, False)
    MXA.close(mxa, False)
                "read signal amplitude at LO frequency in and assign it as score"
                power = float((MXA.fpower(
                    mxa,
                    str(5.5 - 0.025 * index) +
                    'GHz')).split('dBm')[0]) - index * float((MXA.fpower(
                        mxa,
                        str(5.5 + 0.025 * index) + 'GHz')).split('dBm')[0])
                score = power
                nres.append([redx, score])
            res = nres


if __name__ == "__main__":

    LO_0 = float((MXA.fpower(mxa, str(5.5) + 'GHz')).split('dBm')[0])
    Mirror_0 = float((MXA.fpower(mxa, str(5.475) + 'GHz')).split('dBm')[0])
    Initial = [0., 0., 1., 0., 0.]
    time = 0
    OPT = IQ_Cal()
    OPT.IQparams = array(Initial, dtype=float64)  #overwrite initial values
    result = OPT.nelder_mead(time=time)
    prev = result[0]
    no_improv, no_improv_thr, no_improv_break = 0, 1e-5, 4
    LO, Mirror, T = [], [], []
    while True:
        time += 1
        if time % 2: OPT = IQ_Cal('MR', result[0], ratio=time)
        else: OPT = IQ_Cal('LO', result[0], ratio=time)
        result = OPT.nelder_mead(time=time)
        # if len(result) == 3:
Ejemplo n.º 4
0
    def run(self):
        self.LO_Initial = float(
            (MXA.fpower(self.mxa,
                        str(self.LO_freq) + 'GHz')).split('dBm')[0])
        self.Mirror_Initial = float((MXA.fpower(
            self.mxa,
            str(self.LO_freq - self.IF_freq) + 'GHz')).split('dBm')[0])
        self.settings()
        result = self.nelder_mead()
        prev = result[0]
        no_improv, no_improv_thr, no_improv_break = 0, 1e-5, 6
        time, LO, Mirror, T = 0, [], [], []
        while True:
            time += 1
            if time % 2: self.settings('MR', result[0], logratio=time)
            else: self.settings('LO', result[0], logratio=time)
            result = self.nelder_mead(time=time)
            LO.append(
                float((MXA.fpower(self.mxa,
                                  str(self.LO_freq) +
                                  'GHz')).split('dBm')[0]) - self.LO_Initial)
            Mirror.append(
                float((MXA.fpower(self.mxa,
                                  str(self.LO_freq - self.IF_freq) +
                                  'GHz')).split('dBm')[0]) -
                self.Mirror_Initial)
            print(Back.BLUE + Fore.WHITE +
                  "Mirror has been suppressed for %s from %s" %
                  (Mirror[-1], self.Mirror_Initial))
            T.append(time)
            ssq = sum((result[0] - prev)**2)
            if ssq > no_improv_thr:
                no_improv = 0
                prev = result[0]
            else:
                no_improv += 1

            if no_improv >= no_improv_break:
                print("Calibration completed!")
                AWG_Sinewave(self.awgsess, self.IF_freq * 1000, self.IQparams)
                print(type(self.IQparams))
                print("Optimized IQ parameters:\n %s" % result)
                print("Amplitude Imbalance:\n %s" % self.IQparams[2])
                if self.IQparams[3] > self.IQparams[
                        4] and self.IQparams[3] - self.IQparams[4] < 180:
                    print("phase skew I-Q:\n %s" %
                          (self.IQparams[3] - self.IQparams[4]))
                if self.IQparams[3] > self.IQparams[
                        4] and self.IQparams[3] - self.IQparams[4] > 180:
                    print("phase skew Q-I:\n %s" %
                          (360 - (self.IQparams[3] - self.IQparams[4])))
                if (self.IQparams[4] > self.IQparams[3]
                        and self.IQparams[4] - self.IQparams[3] < 180) or (
                            self.IQparams[3] > self.IQparams[4]
                            and self.IQparams[3] - self.IQparams[4] > 180):
                    print("phase skew Q-I:\n %s" %
                          (self.IQparams[4] - self.IQparams[3]))

                if (self.IQparams[2] > -1.0) and (self.IQparams[2] < 1.0):
                    Iamp = 1
                    Qamp = Iamp * self.IQparams[2]
                else:
                    Qamp = 1
                    Iamp = Qamp / self.IQparams[2]

                print("Ioffset:\n %s" % self.IQparams[0])
                print("Qoffset:\n %s" % self.IQparams[1])
                print("Iamp:\n %s" % Iamp)
                print("Qamp:\n %s" % Qamp)
                print("Iphase:\n %s" % self.IQparams[3])
                print("Qphase:\n %s" % self.IQparams[4])

                break