Beispiel #1
0
def set_equal_beamformer_weights(stream, ants):
    """Set weights for beamformer `stream` to sum `ants` equally (zero the rest)."""
    user_logger.info('Setting beamformer weights for stream %r:', stream.name)
    for inp in stream.inputs:
        # Divide by sqrt(# ants) to maintain a constant power level in output
        weight = 1.0 / np.sqrt(len(ants)) if inp[:-1] in ants else 0.0
        reply = stream.req.weights(inp, weight)
        if reply.succeeded:
            user_logger.info('  input %r got weight %f', inp, weight)
        else:
            user_logger.warning('  input %r weight could not be set', inp)
Beispiel #2
0
def calculate_corrections(G_gains, B_gains, delays, cal_channel_freqs,
                          random_phase, flatten_bandpass,
                          target_average_correction):
    """Turn cal pipeline products into corrections to be passed to F-engine."""
    average_gain = {}
    gain_corrections = {}
    # First find relative corrections per input with arbitrary global average
    for inp in G_gains:
        # Combine all calibration products for input into single array of gains
        K_gains = np.exp(-2j * np.pi * delays[inp] * cal_channel_freqs)
        gains = K_gains * B_gains[inp] * G_gains[inp]
        if np.isnan(gains).all():
            average_gain[inp] = gain_corrections[inp] = 0.0
            continue
        abs_gains = np.abs(gains)
        # Track the average gain to fix overall power level (and as diagnostic)
        average_gain[inp] = np.nanmedian(abs_gains)
        corrections = 1.0 / gains
        if not flatten_bandpass:
            # Let corrections have constant magnitude equal to 1 / (avg gain),
            # which ensures that power levels are still equalised between inputs
            corrections *= abs_gains / average_gain[inp]
        if random_phase:
            corrections *= np.exp(2j * np.pi * np.random.rand(len(corrections)))
        gain_corrections[inp] = np.nan_to_num(corrections)
    # All invalid gains (NaNs) have now been turned into zeros
    valid_average_gains = [g for g in average_gain.values() if g > 0]
    if not valid_average_gains:
        raise ValueError("All gains invalid and beamformer output will be zero!")
    global_average_gain = np.median(valid_average_gains)

    # Iterate over inputs again and fix average values of corrections
    for inp in sorted(G_gains):
        relative_gain = average_gain[inp] / global_average_gain
        if relative_gain == 0.0:
            user_logger.warning("%s has no valid gains and will be zeroed", inp)
            continue
        # This ensures that input at the global average gets target correction
        gain_corrections[inp] *= target_average_correction * global_average_gain
        safe_relative_gain = np.clip(relative_gain, 0.5, 2.0)
        if relative_gain == safe_relative_gain:
            user_logger.info("%s: average gain relative to global average = %5.2f",
                             inp, relative_gain)
        else:
            user_logger.warning("%s: average gain relative to global average "
                                "= %5.2f out of range, clipped to %.1f",
                                inp, relative_gain, safe_relative_gain)
            gain_corrections[inp] *= relative_gain / safe_relative_gain
    return gain_corrections
Beispiel #3
0
def save_pointing_offsets(session, pointing_offsets, middle_time):
    """Save pointing offsets to telstate and display to user.

    Parameters
    ----------
    session : :class:`katcorelib.observe.CaptureSession` object
        The active capture session
    pointing_offsets : dict mapping receptor name to offset data (10 floats)
        Pointing offsets per receptor, in degrees
    middle_time : float
        Unix timestamp at the middle of sequence of offset pointings

    """
    # Pointing adjustments go into root view as other capture blocks need it
    telstate = session.telstate.root()
    user_logger.info("Ant  refracted (az, el)     relative adjustment")
    user_logger.info("---- --------------------   --------------------")
    for ant in sorted(session.observers):
        try:
            offsets = pointing_offsets[ant.name].copy()
        except KeyError:
            user_logger.warn('%s had no valid primary beam fitted', ant.name)
        else:
            sensor_name = '%s_pointing_offsets' % (ant.name, )
            telstate.add(sensor_name, offsets, middle_time)
            # Display all offsets in arcminutes
            offsets[2:] *= 60.
            user_logger.info("%s (%+6.2f, %5.2f) deg -> (%+7.2f', %+7.2f')",
                             ant.name, *offsets[[0, 1, 6, 7]])
                     "('J1939-6342'), description ('radec, 19:39, -63:42') or "
                     "catalogue file name ('three_calib.csv')")

# ND states
nd_off = {'diode': 'coupler', 'on': 0., 'off': 0., 'period': -1.}
nd_on = {
    'diode': 'coupler',
    'on': opts.track_duration,
    'off': 0.,
    'period': 0.
}

# Check options and build KAT configuration, connecting to proxies and devices
with verify_and_connect(opts) as kat:
    observation_sources = collect_targets(kat, args)
    user_logger.info(observation_sources.visibility_list())
    # Start capture session, which creates HDF5 file
    with start_session(kat, **vars(opts)) as session:
        # Quit early if there are no sources to observe or not enough antennas
        if len(session.ants) < 4:
            raise ValueError('Not enough receptors to do calibration - you '
                             'need 4 and you have %d' % (len(session.ants), ))
        sources_above_horizon = observation_sources.filter(
            el_limit_deg=opts.horizon)
        if not sources_above_horizon:
            raise NoTargetsUpError("No targets are currently visible - "
                                   "please re-run the script later")
        # Pick the first source that is up (this assumes that the sources in
        # the catalogue are ordered from highest to lowest priority)
        target = sources_above_horizon.targets[0]
        target.add_tags('bfcal single_accumulation')
    # check for PTUSE proxies in the subarray
    ptuses = [
        kat.children[name] for name in sorted(kat.children)
        if name.startswith('ptuse')
    ]
    if len(ptuses) == 0:
        raise ValueError("This script requires a PTUSE proxy")
    elif len(ptuses) > 1:
        # for now keep script simple and only use first proxy
        ptuse = ptuses[0]
        user_logger.warning('Found PTUSE proxies: %s - only using: %s', ptuses,
                            ptuse.name)
    else:
        ptuse = ptuses[0]
        user_logger.info('Using PTUSE proxy: %s', ptuse.name)

    bf_ants = opts.ants.split(',') if opts.ants else [
        ant.name for ant in kat.ants
    ]
    cbf = SessionCBF(kat)
    # Special hack for Lab CBF - set to zero on site
    # TODO: stop hacking, or make this a command line option
    freq_delta_hack = 0
    if freq_delta_hack:
        user_logger.warning(
            'Hack: Adjusting beam centre frequency by %s MHz for lab',
            freq_delta_hack)
    for stream in cbf.beamformers:
        reply = stream.req.passband(
            int((opts.beam_bandwidth) * 1e6),
Beispiel #6
0
# Set default value for any option (both standard and experiment-specific options)
parser.set_defaults(observer='comm_test', nd_params='off', project_id='COMMTEST',
                    description='Phase-up observation that sets F-engine gains')
# Parse the command line
opts, args = parser.parse_args()

if len(args) == 0:
    raise ValueError("Please specify at least one target argument via name "
                     "('J1939-6342'), description ('radec, 19:39, -63:42') or "
                     "catalogue file name ('three_calib.csv')")

# Check options and build KAT configuration, connecting to proxies and devices
with verify_and_connect(opts) as kat:
    observation_sources = collect_targets(kat, args)
    if opts.reconfigure_sdp:
        user_logger.info("Reconfiguring SDP subsystem")
        sdp = SessionSDP(kat)
        sdp.req.product_reconfigure()
    # Start capture session
    with start_session(kat, **vars(opts)) as session:
        session.standard_setup(**vars(opts))
        # Reset F-engine to a known good state first
        if opts.fft_shift is not None:
            session.set_fengine_fft_shift(opts.fft_shift)
        fengine_gain = session.set_fengine_gains(opts.fengine_gain)
        # Quit if there are no sources to observe or not enough antennas for cal
        if len(session.ants) < 4:
            raise ValueError('Not enough receptors to do calibration - you '
                             'need 4 and you have %d' % (len(session.ants),))
        sources_above_horizon = observation_sources.filter(el_limit_deg=opts.horizon)
        if not sources_above_horizon:
Beispiel #7
0
        # Quit early if there are no sources to observe or not enough antennas
        if len(session.ants) < 4:
            raise ValueError('Not enough receptors to do calibration - you '
                             'need 4 and you have %d' % (len(session.ants), ))
        if len(observation_sources.filter(el_limit_deg=opts.horizon)) == 0:
            raise NoTargetsUpError("No targets are currently visible - "
                                   "please re-run the script later")
        session.standard_setup(**vars(opts))
        session.capture_start()

        # XXX Eventually pick closest source as our target, now take first one
        target = observation_sources.targets[0]
        target.add_tags('bfcal single_accumulation')
        session.label('interferometric_pointing')
        user_logger.info(
            "Initiating interferometric pointing scan on target "
            "'%s' (%d pointings of %g seconds each)", target.name,
            len(offsets), opts.track_duration)
        session.track(target, duration=0, announce=False)
        # Point to the requested offsets and collect extra data at middle time
        for n, offset in enumerate(offsets):
            user_logger.info("initiating track on offset of (%g, %g) degrees",
                             *offset)
            session.ants.req.offset_fixed(offset[0], offset[1],
                                          opts.projection)
            session.track(target, duration=opts.track_duration, announce=False)
            offset_end_times[n] = time.time()
            if not kat.dry_run and n == len(offsets) // 2 - 1:
                # Get weather data for refraction correction at middle time
                temperature = kat.sensor.anc_air_temperature.get_value()
                pressure = kat.sensor.anc_air_pressure.get_value()
                humidity = kat.sensor.anc_air_relative_humidity.get_value()
Beispiel #8
0
 for stream in cbf.beamformers:
     # ROACH implementation only, need to set passband and centerfrequency
     # Values hard coded: CBF is expecting values
     # (856000000.00 - 2250000.0, 1284000000.000)
     # Hardcoded and magic number usage to be removed in future update
     reply = stream.req.passband(int(opts.beam_bandwidth * 1e6),
                                 int(opts.beam_centre_freq * 1e6))
     if reply.succeeded:
         try:
             actual_bandwidth = float(reply.messages[0].arguments[2])
             actual_centre_freq = float(reply.messages[0].arguments[3])
         except IndexError:
             # In a dry run the reply will succeed but with no return values
             actual_bandwidth = actual_centre_freq = 0.0
         user_logger.info(
             "Beamformer %r has bandwidth %g Hz and centre freq %g Hz",
             stream.name, actual_bandwidth, actual_centre_freq)
     else:
         # SKARAB no longer has bandwidth and centre freq registers
         if str(reply.messages[0]).find('AttributeError'):
             # will be replaced with a "unimplemented" response
             user_logger.info(
                 "SKARAB, skipping bandwidth and centre freq setting")
         else:  # ROACH setting error
             raise ValueError(
                 "Could not set beamformer %r passband - (%s)" %
                 (stream.name, ' '.join(reply.messages[0].arguments)))
     user_logger.info('Setting beamformer weights for stream %r:',
                      stream.name)
     weights = []
     for inp in stream.inputs:
                for target in targets.iterfilter(el_limit_deg=opts.horizon):
                    duration = opts.track_duration
                    if opts.max_duration is not None:
                        time_left = opts.max_duration - (time.time() -
                                                         start_time)
                        # Cut the track short if time runs out
                        if time_left <= 0.:
                            user_logger.warning(
                                "Maximum duration of %g seconds "
                                "has elapsed - stopping script",
                                opts.max_duration)
                            keep_going = False
                            break
                        duration = min(duration, time_left)
                    # Set the b-gain
                    session.label('track_bgain, %g' % bgain)
                    for stream in cbf.beamformers:
                        stream.req.quant_gains(bgain)
                        user_logger.info(
                            "B-engine %s quantisation gain set to %g", stream,
                            bgain)
                    if session.track(target, duration=duration):
                        targets_observed.append(target.description)
                if keep_going and len(targets_observed) == targets_before_loop:
                    user_logger.warning(
                        "No targets are currently visible - "
                        "stopping script instead of hanging around")
                    keep_going = False
        user_logger.info("Targets observed : %d (%d unique)",
                         len(targets_observed), len(set(targets_observed)))
Beispiel #10
0
if len(args) == 0:
    raise ValueError("Please specify the target")

with verify_and_connect(opts) as kat:
    bf_ants = opts.ants.split(',') if opts.ants else [
        ant.name for ant in kat.ants
    ]
    cbf = SessionCBF(kat)
    for stream in cbf.beamformers:
        reply = stream.req.passband(int((opts.beam_bandwidth) * 1e6),
                                    int((opts.beam_centre_freq) * 1e6))
        if reply.succeeded:
            actual_bandwidth = float(reply.messages[0].arguments[2])
            actual_centre_freq = float(reply.messages[0].arguments[3])
            user_logger.info(
                "Beamformer %r has bandwidth %g Hz and centre freq %g Hz",
                stream, actual_bandwidth, actual_centre_freq)
        else:
            raise ValueError("Could not set beamformer %r passband - (%s)" %
                             (stream, ' '.join(reply.messages[0].arguments)))
        user_logger.info('Setting beamformer weights for stream %r:', stream)
        for inp in stream.inputs:
            weight = 1.0 / np.sqrt(
                len(bf_ants)) if inp[:-1] in bf_ants else 0.0
            reply = stream.req.weights(inp, weight)
            if reply.succeeded:
                user_logger.info('  input %r got weight %f', inp, weight)
            else:
                user_logger.warning('  input %r weight could not be set', inp)

    # We are only interested in first target
Beispiel #11
0
# Set default value for any option (both standard and experiment-specific options)
parser.set_defaults(observer='comm_test',nd_params='off',project_id='COMMTEST',description='Phaseup observation setting f-engine weights',dump_rate=1.0)
# Parse the command line
opts, args = parser.parse_args()


# Check options and build KAT configuration, connecting to proxies and devices
with verify_and_connect(opts) as kat:
    ants = kat.ants
    obs_ants = [ant.name for ant in ants]
    observation_sources = collect_targets(kat,args)
    # Find out what inputs are curremtly active
    reply = kat.data.req.dbe_label_input()
    inputs = [m.arguments[0] for m in reply.messages[3:]]
    user_logger.info("Resetting f-engine gains to 160 to allow phasing up")
    for inp in inputs:
       kat.data.req.dbe_k7_gain(inp,160)

    # Quit early if there are no sources to observe
    if len(observation_sources.filter(el_limit_deg=opts.horizon)) == 0:
        user_logger.warning("No targets are currently visible - please re-run the script later")
    else:
        # Start capture session, which creates HDF5 file
        with start_session(kat, **vars(opts)) as session:
            session.standard_setup(**vars(opts))
            session.capture_start()

            start_time = time.time()
            targets_observed = []
            # Keep going until the time is up
 session.adjust_fengine_delays(0)
 # Quit if there are no sources to observe or not enough antennas for cal
 if len(session.ants) < 4:
     raise ValueError('Not enough receptors to do calibration - you '
                      'need 4 and you have %d' % (len(session.ants), ))
 sources_above_horizon = observation_sources.filter(
     el_limit_deg=opts.horizon)
 if not sources_above_horizon:
     raise NoTargetsUpError("No targets are currently visible - "
                            "please re-run the script later")
 # Pick the first source that is up (this assumes that the sources in
 # the catalogue are ordered from highest to lowest priority)
 target = sources_above_horizon.targets[0]
 target.add_tags('bfcal single_accumulation')
 session.capture_init()
 user_logger.info(
     "Only calling capture_start on correlator stream directly")
 session.cbf.correlator.req.capture_start()
 user_logger.info("Initiating %g-second track on target %r",
                  opts.track_duration, target.description)
 session.label('un_corrected')
 # Get onto the source
 session.track(target, duration=0)
 # Fire noise diode during track
 session.fire_noise_diode(on=opts.track_duration, off=0)
 # Attempt to jiggle cal pipeline to drop its delay solutions
 session.stop_antennas()
 user_logger.info("Waiting for delays to materialise in cal pipeline")
 hv_delays = session.get_cal_solutions('KCROSS_DIODE', timeout=300.)
 delays = session.get_cal_solutions('K')
 # Add HV delay to total delay
 for inp in delays:
Beispiel #13
0
if len(args) == 0:
    raise ValueError("Please specify the target")

with verify_and_connect(opts) as kat:
    bf_ants = opts.ants.split(',') if opts.ants else [
        ant.name for ant in kat.ants
    ]
    cbf = SessionCBF(kat)
    for stream in cbf.beamformers:
        reply = stream.req.passband(int((opts.beam_bandwidth) * 1e6),
                                    int((opts.beam_centre_freq) * 1e6))
        if reply.succeeded:
            actual_bandwidth = float(reply.messages[0].arguments[2])
            actual_centre_freq = float(reply.messages[0].arguments[3])
            user_logger.info(
                "Beamformer %r has bandwidth %g Hz and centre freq %g Hz",
                stream, actual_bandwidth, actual_centre_freq)
        else:
            raise ValueError("Could not set beamformer %r passband - (%s)" %
                             (stream, ' '.join(reply.messages[0].arguments)))
        user_logger.info('Setting beamformer weights for stream %r:', stream)
        for inp in stream.inputs:
            weight = 1.0 / np.sqrt(
                len(bf_ants)) if inp[:-1] in bf_ants else 0.0
            reply = stream.req.weights(inp, weight)
            if reply.succeeded:
                user_logger.info('  input %r got weight %f', inp, weight)
            else:
                user_logger.warning('  input %r weight could not be set', inp)

    # We are only interested in first target
Beispiel #14
0
    usage="%prog [opts]",
    description=
    "This automatically max's out  RFE5 and RFE7 attenuator settings "
    "to achieve safe levels for work on the antenna. Some options are **required**."
)

# Parse the command line
opts, args = parser.parse_args()
# The standard option verification routine below requires this option (otherwise ignored)
opts.observer = 'Max Attenuator'

with verify_and_connect(opts) as kat:

    # Create device array of antennas, based on specification string
    ants = kat.ants  #ant_array(kat, opts.ants)
    user_logger.info('Using antennas: %s' %
                     (' '.join([ant.name for ant in ants]), ))

    inputs = []
    for ant in ants:
        for pol in ('h', 'v'):
            inputs.append([ant.name, pol.upper()])

    # Get stage 5 attenuation Set it to max and check it
    rfe5_att = get_rfe5_attenuation(kat, inputs)
    rfe5_att = np.clip(rfe5_att, rfe5_max_att, rfe5_max_att)
    set_rfe5_attenuation(kat, inputs, rfe5_att)
    #rfe5_att = get_rfe5_attenuation(kat, inputs)

    # Get stage 7 attenuation Set it to max and check it
    rfe7_att = get_rfe7_attenuation(kat, inputs)
    rfe7_att = np.clip(rfe7_att, rfe7_max_att,
Beispiel #15
0
    if opts.reset and not opts.sb_id_code:
        raise ValueError(
            "To reset system to defaults you need to specify the schedule block: use --sb-id-code, or run without --reset"
        )

    # Try to build the  KAT configuration
    # This connects to all the proxies and devices and queries their commands and sensors
    try:
        kat = verify_and_connect(opts)
    except ValueError, err:
        raise ValueError("Could not build host for sb-id-code %s (%s)" %
                         (opts.sb_id_code, err))
    print "Using KAT connection with configuration: %s" % (kat.system, )

    user_logger.info("defaults.py: start")
    smsg = "Checking current settings....."
    user_logger.info(smsg)
    print smsg

    check_sensors(kat, defaults)

    if opts.reset:
        smsg = "Resetting to default settings..."
        user_logger.info(smsg)
        print "\n" + smsg
        reset_defaults(kat, defaults)
        smsg = "Rechecking settings...."
        user_logger.info(smsg)
        print "\n" + smsg
        time.sleep(1.5)  # wait a little time for sensor to update
opts, args = parser.parse_args()
opts.description = 'Auto atten'

with verify_and_connect(opts) as kat:
    try:
        # In the past there was a command line option to select dbe
        # (fringe finder) / dbe7, but since fringe finder has been
        # decommisioned that option has been removed
        selected_dbe = kat.dbe7
    except NameError:
        raise RuntimeError(
            "Unknown dbe device (%s) specified. Typically it should be either 'dbe' or 'dbe7'"
        )
    with start_session(kat, **vars(opts)) as session:
        # If centre frequency is specified, set it accordingly
        user_logger.info('Current centre frequency: %s MHz' %
                         (session.get_centre_freq(), ))
        if not kat.dry_run and opts.centre_freq and not session.get_centre_freq(
        ) == opts.centre_freq:
            session.set_centre_freq(opts.centre_freq)
            time.sleep(1.0)
            user_logger.info('Updated centre frequency: %s MHz' %
                             (session.get_centre_freq(), ))
            if np.abs(session.get_centre_freq() -
                      opts.centre_freq) > 2e-5:  # we have 10 HZ resolution
                user_logger.warning(
                    'Failed to updated centre frequency to %s MHz, it is currently set to %s MHz waning is due to the difference between actual & spcified frequency is larger that 10 Hz'
                    % (
                        opts.centre_freq,
                        session.get_centre_freq(),
                    ))
Beispiel #17
0
J1934 = 'PKS 1934-63 | J1939-6342, radec, 19:39:25.03, -63:42:45.7, (200.0 12000.0 -30.7667 26.4908 -7.0977 0.605334)' 
#J0408 = 'PKS 0408-65 | J0408-6545, radec, 4:08:20.38, -65:45:09.1, (800.0 8400.0 -3.708 3.807 -0.7202)'
#J1331 = '3C286      | J1331+3030, radec, 13:31:08.29, +30:30:33.0,(800.0 43200.0 0.956 0.584 -0.1644)'


# Check options and build KAT configuration, connecting to proxies and devices
with verify_and_connect(opts) as kat:
    if len(args) == 0:
        observation_sources = katpoint.Catalogue(antenna=kat.sources.antenna)
        observation_sources.add(J1934)
#        observation_sources.add(J0408)
#        observation_sources.add(J1331)
    else:
        observation_sources = collect_targets(kat, args)
    if opts.reconfigure_sdp:
        user_logger.info("Reconfiguring SDP subsystem")
        sdp = SessionSDP(kat)
        sdp.req.data_product_reconfigure()
    # Start capture session, which creates HDF5 file
    with start_session(kat, **vars(opts)) as session:
        # Quit early if there are no sources to observe
        if len(observation_sources.filter(el_limit_deg=opts.horizon)) == 0:
            raise NoTargetsUpError("No targets are currently visible - "
                                   "please re-run the script later")
        session.standard_setup(**vars(opts))
        if opts.fft_shift is not None:
            session.cbf.fengine.req.fft_shift(opts.fft_shift)
        session.cbf.correlator.req.capture_start()

        for target in [observation_sources.sort('el').targets[-1]]:
            target.add_tags('bfcal single_accumulation')