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)
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
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),
# 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:
# 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()
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)))
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
# 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:
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,
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(), ))
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')