コード例 #1
0
ファイル: util.py プロジェクト: eaobservatory/namakanui
def _try_att(cart, photonics, lo_ghz, voltage, att, skip_servo_pa, lock_only, delay_secs, sleep, log):
    '''Helper function used by tune(); set a new attenuation and retune if needed.'''
    photonics.set_attenuation(att)
    sleep(delay_secs)
    photonics.update()
    cart.update_all()
    if cart.state['pll_unlock']:
        _try_tune(cart, lo_ghz, voltage, 'att %d'%(att), skip_servo_pa, lock_only, log)
コード例 #2
0
ファイル: util.py プロジェクト: eaobservatory/namakanui
def _try_dbm(cart, agilent, lo_ghz, voltage, dbm, skip_servo_pa, lock_only, delay_secs, sleep, log):
    '''Helper function used by tune(); set a new dbm and retune if needed.'''
    agilent.set_dbm(dbm)
    sleep(delay_secs)
    agilent.update()
    cart.update_all()
    if cart.state['pll_unlock']:
        _try_tune(cart, lo_ghz, voltage, 'dbm %.2f'%(dbm), skip_servo_pa, lock_only, log)
コード例 #3
0
ファイル: util.py プロジェクト: eaobservatory/namakanui
def _try_tune(cart, lo_ghz, voltage, msg, skip_servo_pa, lock_only, log):
    '''Helper function used by tune() to catch and log exceptions.
       NOTE: Any error except BadLock should set power to safe levels.
    '''
    log.info('cart.tune %.3f ghz, %s', lo_ghz, msg)
    try:
        cart.tune(lo_ghz, voltage, skip_servo_pa=skip_servo_pa, lock_only=lock_only)
    except namakanui.cart.BadLock as e:
        log.error('tune failed at %.3f ghz, %s', lo_ghz, msg)
    cart.update_all()
コード例 #4
0
def iv(target, rows):
    if target == 'hot':
        p_index = hot_p_index
    else:
        p_index = sky_p_index
    load.move('b%d_%s' % (band, target))

    if target == 'hot':
        cart.tune(lo_ghz, 0.0, skip_servo_pa=True)
        cart._set_pa([pas[0], pas[1]])
        cart.update_all()
        if namakanui.util.iftask_setup(2, 1000, 6, dcms):  # level only
            return 1

    sys.stderr.write('%s: ' % (target))
    sys.stderr.flush()

    mult = 1.0
    if band == 6:
        mult = -1.0
    cart._ramp_sis_bias_voltages(
        [mult * mvs[0], mvs[0], mult * mvs[0], mvs[0]])
    for i, mv in enumerate(mvs):
        if (i + 1) % 20 == 0:
            sys.stderr.write('%.2f%% ' % (0.0 + 50 * i / len(mvs)))
            sys.stderr.flush()
            cart.update_all()  # for anyone monitoring
        for po in range(2):
            cart.femc.set_sis_voltage(cart.ca, po, 0, mult * mv)
            cart.femc.set_sis_voltage(cart.ca, po, 1, mv)
        rows[i][mv_index] = mv
        # start IFTASK action while we average the mixer current readings
        transid = drama.obey("IFTASK@if-micro",
                             "WRITE_TP2",
                             FILE="NONE",
                             ITIME=0.1)
        # TODO: separate hot/cold mixer currents, or only calc hot
        for j in range(ua_n):
            for po in range(2):
                for sb in range(2):
                    ua = cart.femc.get_sis_current(cart.ca, po, sb) * 1e3
                    rows[i][ua_avg_index + po * 2 + sb] += abs(
                        ua)  # for band 6
                    rows[i][ua_dev_index + po * 2 + sb] += ua * ua
        # get IFTASK reply
        msg = transid.wait(5)
        if msg.reason != drama.REA_COMPLETE or msg.status != 0:
            logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
            return 1
        for j, dcm in enumerate(dcms):
            rows[i][p_index + j] = msg.arg['POWER%d' % (dcm)]

    sys.stderr.write('\n')
    sys.stderr.flush()
    return 0
コード例 #5
0
def loop():
    global i, prev_powers
    while i < 23:
        time.sleep(1)
        i += 1
        if i < 0:
            sys.stderr.write('.')
        else:
            sys.stderr.write('%d ' % (i))
        sys.stderr.flush()
        if i % 5 == 4:
            # retune the cart; make sure it loses the lock
            dbm = agilent.state['dbm']
            while dbm > agilent.safe_dbm and not cart.state['pll_unlock']:
                agilent.set_dbm(dbm)
                cart.update_all()
                dbm -= 0.1
            dbm = agilent.safe_dbm
            agilent.set_dbm(dbm)
            agilent.set_output(0)
            time.sleep(0.05)
            agilent.set_output(1)
            agilent.set_dbm(orig_dbm)
            time.sleep(0.05)
            cart.tune(lo_ghz, 0.0)
            time.sleep(0.05)
        transid = drama.obey("IFTASK@if-micro",
                             "WRITE_TP2",
                             FILE="NONE",
                             ITIME=0.1)
        cart.update_all()
        msg = transid.wait(5)
        if msg.reason != drama.REA_COMPLETE or msg.status != 0:
            logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
            return
        if cart.state['pll_unlock']:
            logging.error('failed to tune')
            return
        powers = []
        for dcm in dcms:
            powers.append(msg.arg['POWER%d' % (dcm)])
        for j, (prev, curr) in enumerate(zip(prev_powers, powers)):
            pdiff = abs((prev - curr) / min(prev, curr)) * 100.0
            if pdiff > 1.5:
                logging.info('%.2f%% jump in DCM %d', pdiff, dcms[j])
                # let's write to the output file too, might come in handy
                sys.stdout.write('# jump DCM %d, %.2f%%\n' % (dcms[j], pdiff))
                if i < 0:
                    i = 0  # collect a bit more data, then quit
        prev_powers = powers
        output(powers)
コード例 #6
0
def print_dbm(i, dbm):
    #logging.info('%d dbm %.2f', i, dbm)
    transid = drama.obey("IFTASK@if-micro", "WRITE_TP2", FILE="NONE", ITIME=0.1)
    cart.update_all()
    logging.info('%d dbm %.2f, pll_if %.3f', i, dbm, cart.state['pll_if_power'])
    msg = transid.wait(5)
    if msg.reason != drama.REA_COMPLETE or msg.status != 0:
        logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
        return False
    if cart.state['pll_unlock']:
        return False
    sys.stdout.write('%.2f %.3f'%(dbm, cart.state['pll_if_power']))
    for dcm in dcms:
            sys.stdout.write(' %.3f'%(msg.arg['POWER%d'%(dcm)]))
    sys.stdout.write('\n')
    sys.stdout.flush()
    return True
コード例 #7
0
ファイル: yfactor_pa.py プロジェクト: eaobservatory/namakanui
def ip(target, rows, pas):
    if target == 'hot':
        p_index = hot_p_index
    else:
        p_index = sky_p_index
    load.move('b%d_%s' % (band, target))

    sys.stderr.write('%s: ' % (target))
    sys.stderr.flush()

    for i, pa in enumerate(pas):
        if (i + 1) % 20 == 0:
            sys.stderr.write('%.2f%% ' % (100.0 * i / len(pas)))
            sys.stderr.flush()
            cart.update_all()

        cart._set_pa([pa, pa])
        rows[i][pa_index] = pa

        # start IFTASK action while we average the mixer current readings
        transid = drama.obey("IFTASK@if-micro",
                             "WRITE_TP2",
                             FILE="NONE",
                             ITIME=0.1)
        for j in range(ua_n):
            for po in range(2):
                for sb in range(2):
                    ua = cart.femc.get_sis_current(cart.ca, po, sb) * 1e3
                    rows[i][ua_avg_index + po * 2 + sb] += abs(
                        ua)  # for band 6
                    rows[i][ua_dev_index + po * 2 + sb] += ua * ua
        # get IFTASK reply
        msg = transid.wait(5)
        if msg.reason != drama.REA_COMPLETE or msg.status != 0:
            logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
            return 1

        for j, dcm in enumerate(dcm_0 + dcm_1):
            rows[i][p_index + j] = msg.arg['POWER%d' % (dcm)]

    sys.stderr.write('\n')
    sys.stderr.flush()
    return 0
コード例 #8
0
def main_loop():
    random.seed()
    lock_only = 1
    sys.stderr.write('starting %d iters\n' % (args.iters))
    sys.stderr.flush()
    for i in range(args.iters):
        sys.stderr.write('%d ' % (i))
        sys.stderr.flush()
        if i == args.iters // 2:
            lock_only = 0
            sys.stderr.write('\nhalfway\n')
            sys.stderr.flush()
        lo_ghz = random.uniform(args.lo_ghz - args.off_ghz,
                                args.lo_ghz + args.off_ghz)
        if not util.tune(cart, agilent, photonics, lo_ghz,
                         lock_only=lock_only):
            logging.error('failed to tune to %.6f ghz', lo_ghz)
            return
        transid = drama.obey("IFTASK@if-micro",
                             "WRITE_TP2",
                             FILE="NONE",
                             ITIME=0.1)
        cart.update_all()
        msg = transid.wait(5)
        if msg.reason != drama.REA_COMPLETE or msg.status != 0:
            logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
            return
        if cart.state['pll_unlock']:
            logging.error('lost lock at %.6f GHz', lo_ghz)
            return
        sys.stdout.write('%.6f %d' % (lo_ghz, lock_only))
        for key in state_keys:
            if key not in cart.state:
                key, sep, index = key.rpartition('_')
                index = int(index)
                sys.stdout.write(' %s' % (cart.state[key][index]))
            else:
                sys.stdout.write(' %s' % (cart.state[key]))
        for dcm in dcms:
            sys.stdout.write(' %.5f' % (msg.arg['POWER%d' % (dcm)]))
        sys.stdout.write('\n')
        sys.stdout.flush()
コード例 #9
0
load = namakanui.load.Load(datapath+'load.ini', time.sleep, namakanui.nop)
load.move('b%d_hot'%(band))

# tune cartridge, adjusting power as needed
if not util.tune(cart, agilent, photonics, lo_ghz):
    logging.error('failed to tune to %.3f ghz', lo_ghz)
    sys.exit(1)

# determine dbm limits
dbm = agilent.state['dbm']
orig_dbm = dbm
while dbm < agilent.max_dbm and cart.state['pll_if_power'] > -2.5 and not cart.state['pll_unlock']:
    dbm += 0.1
    agilent.set_dbm(dbm)
    time.sleep(0.05)
    cart.update_all()
    logging.info('+ dbm %.2f, pll_if %.3f', dbm, cart.state['pll_if_power'])
dbm = agilent.state['dbm']
hi_dbm = dbm
while dbm > agilent.safe_dbm and cart.state['pll_if_power'] < -0.5 and not cart.state['pll_unlock']:
    dbm -= 0.1
    agilent.set_dbm(dbm)
    time.sleep(0.05)
    cart.update_all()
    logging.info('- dbm %.2f, pll_if %.3f', dbm, cart.state['pll_if_power'])
lo_dbm = dbm + 0.2
logging.info('dbm limits: [%.2f, %.2f]', lo_dbm, hi_dbm)
if lo_dbm >= hi_dbm:
    logging.error('bad dbm limits, bailing out.')
    agilent.set_dbm(agilent.safe_dbm)
    photonics.set_attenuation(photonics.max_att) if photonics else None
コード例 #10
0
ファイル: util.py プロジェクト: eaobservatory/namakanui
def setup_script(band, lock_side, sleep=time.sleep, publish=namakanui.nop):
    '''
    Perform common setup for a standalone script:
        - Create agilent and set to safe levels with output enabled.
        - Create photonics (if in namaknui.ini) and set max attenuation.
        - Create cart(band) and set given lock side.
        - Zero out pa/lna on unused bands.
        - Set ifswitch to given band.
        - Check reference (floog) power level.
    Returns cart, agilent, photonics.
    '''
    import namakanui.ini
    import namakanui.cart
    import namakanui.agilent
    import namakanui.photonics
    import namakanui.ifswitch
    
    binpath, datapath = get_paths()
    
    agilent = namakanui.agilent.Agilent(datapath+'agilent.ini', sleep, publish)
    agilent.set_dbm(agilent.safe_dbm)
    agilent.set_output(1)
    
    photonics = None
    nconfig = namakanui.ini.IncludeParser(datapath+'namakanui.ini')
    if 'photonics_ini' in nconfig['namakanui']:
        pini = nconfig['namakanui']['photonics_ini']
        photonics = namakanui.photonics.Photonics(datapath+pini, sleep, publish)
        photonics.set_attenuation(photonics.max_att)
    
    ifswitch = namakanui.ifswitch.IFSwitch(datapath+'ifswitch.ini', sleep, publish)
    ifswitch.set_band(band)
    ifswitch.close()  # done with ifswitch
    
    cart = namakanui.cart.Cart(band, datapath+'band%d.ini'%(band), sleep, publish)
    cart.power(1)
    if lock_side is not None:
        lock_side = lock_side.lower() if hasattr(lock_side, 'lower') else lock_side
        lock_side = {0:0, 1:1, 'below':0, 'above':1}[lock_side]
        cart.femc.set_cartridge_lo_pll_sb_lock_polarity_select(cart.ca, lock_side)
        cart.state['pll_sb_lock'] = lock_side  # cart never updates this
    
    # zero out unused carts
    femc = cart.femc
    for b in [3,6,7]:
        if b == band:
            continue
        ca = b-1
        if not femc.get_pd_enable(ca):
            continue
        for po in range(2):
            femc.set_cartridge_lo_pa_pol_drain_voltage_scale(ca, po, 0)
            femc.set_cartridge_lo_pa_pol_gate_voltage(ca, po, 0)
            for sb in range(2):
                femc.set_lna_enable(ca, po, sb, 0)
    
    # this mainly checks that the IF switch really has this band selected
    cart.update_all()
    rp = cart.state['pll_ref_power']
    if rp < -3.0:
        raise RuntimeError('PLL ref (FLOOG 31.5 MHz) power high (%.2fV), needs padding'%(rp))
    if rp > -0.5:
        raise RuntimeError('PLL ref (FLOOG 31.5 MHz) power low (%.2fV), check IF switch'%(rp))
    
    return cart, agilent, photonics
コード例 #11
0
ファイル: yfactor.py プロジェクト: eaobservatory/namakanui
def iv(target, rows, pa):
    if target == 'hot':
        p_index = hot_p_index
    else:
        p_index = sky_p_index
    load.move('b%d_%s' % (band, target))

    # TODO Maybe it's wrong to relevel for each PA; it makes it harder
    # to compare power between PAs if the leveling is slightly different.
    # Ambient temperature shouldn't be changing much compared to the
    # difference between hot load and sky, either.

    # at the start of a HOT row, re-tune and re-level the power meters
    # at the nominal values.  do not relevel on SKY or y-factor won't work.
    # actually re-leveling makes it difficult to compare power levels
    # across sweeps, so skip it.  retuning is fine though.
    # 20200221 but ACTUALLY we're having problems with saturating power levels,
    # so DO relevel the detectors here.  we won't be able to see
    # relative power levels, but we mostly only do 2 PAs these days and care
    # more about Y-factor values anyway.
    if target == 'hot':
        # dbm/att should already be set from namakanui.util.tune
        cart.tune(lo_ghz, 0.0, skip_servo_pa=True)
        cart._set_pa([pa, pa])
        cart.update_all()
        if namakanui.util.iftask_setup(2, 1000, 6, dcms):  # level only
            return 1

    sys.stderr.write('%s: ' % (target))
    sys.stderr.flush()

    # NOTE: The two SIS mixers in each polarization module are not really USB and LSB.
    # Rather the input to one is phase-shifted relative to the other, and their
    # signals are then combined to produce USB and LSB outputs.  So to check the
    # power output and Y-factor from each mixer individually, the other one needs
    # to have its output disabled by setting its bias voltage to zero.
    # Since we still need to smoothly ramp SIS bias voltage for large changes,
    # we therefore do two separate loops for sis1 and sis2.

    # TODO: Once we have the mixers optimized individually, we might still need
    # to optimize their combined outputs.  This will require a 2D scan of
    # mixer bias voltage for each PA setting.

    # sis1
    sb = 0
    mult = 1.0
    if band == 6:
        mult = -1.0
    if args.zero:
        cart._ramp_sis_bias_voltages([mult * mvs[0], 0.0, mult * mvs[0], 0.0])
    else:
        cart._ramp_sis_bias_voltages(
            [mult * mvs[0], nom_v[1], mult * mvs[0], nom_v[3]])
    for i, mv in enumerate(mvs):
        if (i + 1) % 20 == 0:
            sys.stderr.write('%.2f%% ' % (0.0 + 50 * i / len(mvs)))
            sys.stderr.flush()
            cart.update_all()  # for anyone monitoring
        for po in range(2):
            cart.femc.set_sis_voltage(cart.ca, po, sb, mult * mv)
        rows[i][mv_index] = mv
        # start IFTASK action while we average the mixer current readings
        transid = drama.obey("IFTASK@if-micro",
                             "WRITE_TP2",
                             FILE="NONE",
                             ITIME=0.1)
        for j in range(ua_n):
            for po in range(2):
                ua = cart.femc.get_sis_current(cart.ca, po, sb) * 1e3
                rows[i][ua_avg_index + po * 2 + sb] += abs(ua)  # for band 6
                rows[i][ua_dev_index + po * 2 + sb] += ua * ua
        # get IFTASK reply
        msg = transid.wait(5)
        if msg.reason != drama.REA_COMPLETE or msg.status != 0:
            logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
            return 1

        for j, dcm in enumerate(dcm_0):
            rows[i][p_index + j + 0] = msg.arg['POWER%d' % (dcm)]
        for j, dcm in enumerate(dcm_1):
            rows[i][p_index + j + 16] = msg.arg['POWER%d' % (dcm)]

    # sis2
    sb = 1
    if args.zero:
        cart._ramp_sis_bias_voltages([0.0, mvs[0], 0.0, mvs[0]])
    else:
        cart._ramp_sis_bias_voltages([nom_v[0], mvs[0], nom_v[2], mvs[0]])
    for i, mv in enumerate(mvs):
        if (i + 1) % 20 == 0:
            sys.stderr.write('%.2f%% ' % (50.0 + 50 * i / len(mvs)))
            sys.stderr.flush()
            cart.update_all()  # for anyone monitoring
        for po in range(2):
            cart.femc.set_sis_voltage(cart.ca, po, sb, mv)
        rows[i][mv_index] = mv
        # start IFTASK action while we average the mixer current readings
        transid = drama.obey("IFTASK@if-micro",
                             "WRITE_TP2",
                             FILE="NONE",
                             ITIME=0.1)
        for j in range(ua_n):
            for po in range(2):
                ua = cart.femc.get_sis_current(cart.ca, po, sb) * 1e3
                rows[i][ua_avg_index + po * 2 + sb] += ua
                rows[i][ua_dev_index + po * 2 + sb] += ua * ua
        # get IFTASK reply
        msg = transid.wait(5)
        if msg.reason != drama.REA_COMPLETE or msg.status != 0:
            logging.error('bad reply from IFTASK.WRITE_TP2: %s', msg)
            return 1

        for j, dcm in enumerate(dcm_0):
            rows[i][p_index + j + 8] = msg.arg['POWER%d' % (dcm)]
        for j, dcm in enumerate(dcm_1):
            rows[i][p_index + j + 24] = msg.arg['POWER%d' % (dcm)]

    sys.stderr.write('\n')
    sys.stderr.flush()
    return 0