Ejemplo n.º 1
0
    def print_info(self):
        """Print information about the embedding circuit to the terminal."""

        print(self)

        str1 = "   f={0}, p={1}\t\t\tvph = {2:.4f} x {1}\t\t{3}"
        str2 = "   f={0}, p={1}\t\t\t{2:.1f} GHz x {1}\t\t{3}"
        str3 = "\tThev. voltage:\t\t{:.4f} * Vgap"
        str6 = "\t              \t\t{:.4f} * Vph"
        str4 = "\tThev. impedance:\t{:.2f} * Rn"
        str7 = "\tAvail. power:   \t{:.2E} W"
        str8 = "\t                \t{:.3f} dBm"

        if self.fgap is None or self.vgap is None or self.rn is None:
            for f in range(1, self.num_f + 1):
                for p in range(1, self.num_p + 1):
                    vph = self.vph[f]
                    vt = self.vt[f, p]
                    zt = self.zt[f, p]
                    cprint(str1.format(f, p, vph, self.comment[f][p]), 'GREEN')
                    print(str3.format(float(vt.real)))
                    print(str4.format(zt))
        else:
            for f in range(1, self.num_f + 1):
                for p in range(1, self.num_p + 1):
                    fq = self.vph[f] * self.fgap / 1e9
                    vt = self.vt[f, p]
                    zt = self.zt[f, p]
                    with np.errstate(divide='ignore'):
                        power_w = self.available_power(f, p, units='W')
                        power_dbm = self.available_power(f, p, units='dBm')
                    cprint(str2.format(f, p, fq, self.comment[f][p]), 'GREEN')
                    print(str3.format(float(vt.real)))
                    print(str6.format(float(vt.real / (self.vph[f] * p))))
                    print(str4.format(zt))
                    print(str7.format(power_w))
                    print(str8.format(power_dbm))
        print("")
Ejemplo n.º 2
0
def dciv_curve(ivdata, **kwargs):
    """Import and analyze DC I-V data (a.k.a., the unpumped I-V curve).

    Args:
        ivdata: DC I-V data. A Numpy array. The data
            should have two columns: the first for voltage, and the second
            for current.

    Keyword Args:
        v_fmt (str): Units for voltage ('uV', 'mV', or 'V').
        i_fmt (str): Units for current ('uA', 'mA', or 'A').
        vmax (float): Maximum voltage to import in units [V].
        npts (int): Number of points to have in I-V interpolation.
        debug (bool): Plot each step of the I-V processing procedure.
        voffset (float): Voltage offset, in units [V].
        ioffset (float): Current offset, in units [A].
        voffset_range (list): Voltage range over which to search for offset,
            in units [V].
        voffset_sigma (float): Standard deviation of Gaussian filter when
            searching for offset.
        rseries (float): Series resistance in experimental measurement
            system, in units [ohms].
        i_multiplier (float): Multiply the imported current by this value.
        v_multiplier (float): Multiply the imported voltage by this value.
        filter_data (bool): Filter data
        vgap_guess (float): Guess of gap voltage. Used to temporarily
            normalize while filtering. Given in units [V].
        igap_guess (float): Guess of gap current. Used to temporarily
            normalize while filtering. Given in units [A].
        filter_theta (float): Angle by which to the rotate data while
            filtering. Given in radians.
        filter_nwind (int): Window size for Savitsky-Golay filter.
        filter_npoly (int): Order of Savitsky-Golay filter.
        vrn (list): Voltage range over which to calculate the normal
            resistance, in units [V]
        rn_vmin (float): Lower voltage range to determine the normal
            resistance, in units [V] (DEPRECATED)
        rn_vmax (float): Upper voltage range to determine the normal
            resistance, in units [V] (DEPRECATED)
        vrsg (float): The voltage at which to calculate the subgap
            resistance.
        vleak (float): The voltage at which to calculate the subgap leakage
            current.

    Returns:
        tuple: normalized voltage, normalized current, DC I-V metadata

    """

    # Unpack keyword arguments
    # Use default values from qmix.exp.parameters if they aren't provided
    v_multiplier = kwargs.get('v_multiplier', PARAMS['v_multiplier'])
    i_multiplier = kwargs.get('i_multiplier', PARAMS['i_multiplier'])
    filter_data = kwargs.get('filter_data', PARAMS['filter_data'])
    rseries = kwargs.get('rseries', PARAMS['rseries'])
    debug = kwargs.get('debug', PARAMS['debug'])
    vmax = kwargs.get('vmax', PARAMS['vmax'])
    npts = kwargs.get('npts', PARAMS['npts'])

    # Import and do some basic cleaning (remove nans, sort by voltage, etc.)
    # voltage in V, current in A
    volt_v, curr_a = _load_iv(ivdata, **kwargs)

    if debug:  # pragma: no cover
        plt.figure()
        plt.plot(volt_v * 1e3, curr_a * 1e6)
        plt.title('Initial import (raw data)')
        plt.xlabel("Voltage (mV)")
        plt.ylabel("Current (uA)")
        plt.grid()
        plt.show()

    # Correct for DC gain errors in experimental system (if required)
    volt_v *= v_multiplier
    curr_a *= i_multiplier

    # Correct offsets in I-V data
    volt_v, curr_a, offset = _correct_offset(volt_v, curr_a, **kwargs)

    if debug:  # pragma: no cover
        plt.figure()
        plt.plot(volt_v * 1e3, curr_a * 1e6)
        plt.title('After correcting for the I/V offset')
        plt.xlabel("Voltage (mV)")
        plt.ylabel("Current (uA)")
        plt.grid()
        plt.show()

    # Filter I-V data
    volt_v, curr_a = _filter_iv_data(volt_v, curr_a, **kwargs)

    if debug and filter_data:  # pragma: no cover
        plt.figure()
        plt.plot(volt_v * 1e3, curr_a * 1e6)
        plt.title('After filtering I-V curve')
        plt.xlabel("Voltage (mV)")
        plt.ylabel("Current (uA)")
        plt.grid()
        plt.show()

    # Save uncorrected data
    vraw, iraw = volt_v.copy(), curr_a.copy()

    # Correct for series resistances in DC biasing system
    volt_v, curr_a = _correct_series_resistance(volt_v, curr_a, **kwargs)

    if debug:  # pragma: no cover
        plt.figure()
        plt.plot(volt_v * 1e3, curr_a * 1e6)
        plt.title('After correcting for the series resistance')
        plt.xlabel("Voltage (mV)")
        plt.ylabel("Current (uA)")
        plt.grid()
        plt.show()

    # Analyze properties of DC I-V curve
    vgap = _find_gap_voltage(volt_v, curr_a, **kwargs)
    rn, vint = _find_normal_resistance(volt_v, curr_a, **kwargs)
    rsg = _find_subgap_resistance(volt_v, curr_a, **kwargs)
    fgap = sc.e * vgap / sc.h
    igap = vgap / rn

    # Warnings
    if rn < 1:
        cprint('\nWarning: Normal resistance is very low...', 'RED')
        cprint('         Are you sure you have the right units?\n', 'RED')
    if rn > 50:
        cprint('\nWarning: Normal resistance is very high...', 'RED')
        cprint('         Are you sure you have the right units?\n', 'RED')

    # Normalize I-V curve
    voltage = volt_v / vgap
    current = curr_a / igap

    # Re-sample I-V curve
    v_temp = np.linspace(-vmax, vmax, npts) / vgap
    current = np.interp(v_temp, voltage, current)
    voltage = v_temp

    # Save DC I-V curve metadata
    dc = DCIVData(vraw=vraw,     iraw=iraw,
                  vnorm=voltage, inorm=current,
                  vgap=vgap,     igap=igap,
                  fgap=fgap,     rn=rn,
                  rsg=rsg,       offset=offset,
                  vint=vint,     rseries=rseries)

    return voltage, current, dc
Ejemplo n.º 3
0
def _find_if_noise(if_data, dc, **kw):
    """Determine IF noise from shot noise slope.

    Uses Woody's method (Woody 1985).

    Args:
        if_data: IF data, 2-column numpy array: voltage x power
        dc: DC I-V metadata

    Keyword Args:
        vshot (list): Voltage range over which to fit shot noise slope, in
            units [V]. Can be a list of lists to define multiple ranges.

    Returns:
        tuple: IF noise, correction factor, linear fit

    """

    # Unpack keyword arguments
    vshot = kw.get('vshot', PARAMS['vshot'])

    # This is relatively tricky to automate
    # It still makes mistakes occasionally, make sure to check/plot your data

    # TODO: Sort out this function

    # Unpack
    x = if_data[:, 0]
    y = if_data[:, 1]

    # DEBUG
    # import matplotlib.pyplot as plt
    # plt.plot(x, y)
    # plt.show()

    if vshot is None:
        # Find linear region where spikes due to Josephson effect are not present
        # Begin by filtering and calculating the first/second derivative
        y_filt = savgol_filter(y, 21, 3)
        first_der = slope_span_n(x, y_filt, 11)
        first_der = savgol_filter(first_der, 51, 3)
        second_der = slope_span_n(x, first_der, 11)
        second_der = savgol_filter(np.abs(second_der), 51, 3)
        # First criteria: x>1.7 and second derivative must be small
        condition1 = np.max(np.abs(second_der)) * 1e-2
        mask = (x > 1.7) & (np.abs(second_der) < condition1)
        # Second criteria: first derivative must be similar to bulk value
        med_der = np.median(first_der[mask])
        mask_tmp = (0. < first_der) & (first_der < med_der * 2)
        mask = mask & mask_tmp
        # Third criteria: must be at least two values clumped together
        mask_tmp = np.zeros_like(mask, dtype=bool)
        mask_tmp[:-1] = mask[:-1] & mask[1:]
        mask = mask & mask_tmp
    else:
        # Make vshot a list of lists
        assert isinstance(vshot, tuple) or isinstance(vshot, list)
        if not isinstance(vshot[0], tuple) and not isinstance(vshot[0], list):
            vshot = (vshot,)
        # Build mask
        mask = np.zeros_like(x, dtype=bool)
        for vrange in vshot:
            mask_tmp = (vrange[0] < x * dc.vgap) & (x * dc.vgap < vrange[1])
            mask = mask | mask_tmp

    if np.sum(mask) < 5:  # pragma: no cover
        cprint('\t\tShot noise fit failed.', 'RED')
        cprint('\t\tSelecting all voltages above 2*Vgap.', 'RED')
        mask = x > 2.

    # Combine criteria
    x_red, y_red = x[mask], y[mask]

    # Find slope of shot noise
    slope, intercept, _, _, _ = stats.linregress(x_red, y_red)
    i_slope = slope * x + intercept

    # # Normal resistance in this region
    # volt_v = x_red * dc.vgap
    # curr_a = np.interp(x_red, dc.vnorm, dc.inorm) * dc.igap
    # rn_slope = (curr_a[-1] - curr_a[0]) / (volt_v[-1] - volt_v[0])
    # vint = curr_a[0] - rn_slope * volt_v[0]
    # if vint < 0:
    #     vint = 0

    # # Plot for debugging
    # import matplotlib.pyplot as plt
    # plt.figure()
    # plt.plot(x, y, 'k')
    # plt.plot(x_red, y_red, 'r')
    # plt.plot(x, i_slope, 'g--')
    # plt.ylim([0, i_slope.max() * 1.05])
    # plt.show()

    # Correct shot noise slope to 5.8/mV
    # gamma = (dc.rn - 50.) / (dc.rn + 50.)
    # trans = (1 - gamma**2)
    corr = 5.8 / slope * dc.vgap * 1e3  # * trans
    i_slope *= corr

    # IF noise contribution
    if_noise = np.interp(dc.vint / dc.vgap, x, i_slope)
    # if_noise = np.interp(vint, x, i_slope)

    # Is it a reasonable IF noise estimate?
    good_if_noise_fit = 0 < if_noise < 50

    return if_noise, corr, i_slope, good_if_noise_fit