def update(self, timestamp): elapsed_time = timestamp - self._last_update if self._last_update else 0.0 self._last_update = timestamp if self.mode not in ('POINT', 'SCAN', 'STOW'): return az, el = self.pos_actual_scan_azim, self.pos_actual_scan_elev target = construct_azel_target(deg2rad(az), deg2rad(90.0)) \ if self.mode == 'STOW' else self._target if not target: return requested_az, requested_el = target.azel(timestamp, self.ant) requested_az = rad2deg(wrap_angle(requested_az)) requested_el = rad2deg(requested_el) delta_az = wrap_angle(requested_az - az, period=360.) delta_el = requested_el - el # Truncate velocities to slew rate limits and update position max_delta_az = self.max_slew_azim_dps * elapsed_time max_delta_el = self.max_slew_elev_dps * elapsed_time az += min(max(delta_az, -max_delta_az), max_delta_az) el += min(max(delta_el, -max_delta_el), max_delta_el) # Truncate coordinates to antenna limits az = min(max(az, self.real_az_min_deg), self.real_az_max_deg) el = min(max(el, self.real_el_min_deg), self.real_el_max_deg) # Check angular separation to determine lock dish = construct_azel_target(deg2rad(az), deg2rad(el)) error = rad2deg(target.separation(dish, timestamp, self.ant)) self.lock = error < self.lock_threshold # Update position sensors self.pos_request_scan_azim = requested_az self.pos_request_scan_elev = requested_el self.pos_actual_scan_azim = az self.pos_actual_scan_elev = el
def track_line(linepoints, duration): target = construct_azel_target(deg2rad(linepoints[0][0]), deg2rad(linepoints[0][1])) mode = obs_mode('Line', linePoints=linepoints, observationDuration=duration) return trackq.track(target, duration, mode=mode)
def setUp(self): self.target1 = katpoint.construct_azel_target('45:00:00.0', '75:00:00.0') self.target2 = katpoint.Target('Sun, special') self.ant1 = katpoint.Antenna('A1, -31.0, 18.0, 0.0, 12.0, 0.0 0.0 0.0') self.ant2 = katpoint.Antenna( 'A2, -31.0, 18.0, 0.0, 12.0, 10.0 -10.0 0.0') self.ant3 = katpoint.Antenna( 'A3, -31.0, 18.0, 0.0, 12.0, 5.0 10.0 3.0') self.ts = katpoint.Timestamp('2013-08-14 08:25') self.delays = katpoint.DelayCorrection([self.ant2, self.ant3], self.ant1, 1.285e9)
def test_offset(self): """Test target offset.""" az, el = self.target1.azel(self.ts, self.ant1) offset = dict(projection_type='SIN') target3 = katpoint.construct_azel_target(az - katpoint.deg2rad(1.0), el - katpoint.deg2rad(1.0)) x, y = target3.sphere_to_plane(az, el, self.ts, self.ant1, **offset) offset['x'] = x offset['y'] = y extra_delay = self.delays.extra_delay delay0, phase0 = self.delays.corrections(target3, self.ts, offset=offset) delay1, phase1 = self.delays.corrections(target3, self.ts, self.ts + 1.0, offset) # Conspire to return to special target1 self.assertEqual(delay0['A2h'], extra_delay, 'Delay for ant2h should be zero') self.assertEqual(delay0['A2v'], extra_delay, 'Delay for ant2v should be zero') self.assertEqual(delay1['A2h'][0], extra_delay, 'Delay for ant2h should be zero') self.assertEqual(delay1['A2v'][0], extra_delay, 'Delay for ant2v should be zero') self.assertEqual(delay1['A2h'][1], 0.0, 'Delay rate for ant2h should be zero') self.assertEqual(delay1['A2v'][1], 0.0, 'Delay rate for ant2v should be zero') # Now try (ra, dec) coordinate system ra, dec = self.target1.radec(self.ts, self.ant1) offset = dict(projection_type='ARC', coord_system='radec') target4 = katpoint.construct_radec_target(ra - katpoint.deg2rad(1.0), dec - katpoint.deg2rad(1.0)) x, y = target4.sphere_to_plane(ra, dec, self.ts, self.ant1, **offset) offset['x'] = x offset['y'] = y extra_delay = self.delays.extra_delay delay0, phase0 = self.delays.corrections(target4, self.ts, offset=offset) delay1, phase1 = self.delays.corrections(target4, self.ts, self.ts + 1.0, offset) # Conspire to return to special target1 np.testing.assert_almost_equal(delay0['A2h'], extra_delay, decimal=15) np.testing.assert_almost_equal(delay0['A2v'], extra_delay, decimal=15) np.testing.assert_almost_equal(delay1['A2h'][0], extra_delay, decimal=15) np.testing.assert_almost_equal(delay1['A2v'][0], extra_delay, decimal=15) np.testing.assert_almost_equal(delay1['A2h'][1], 0.0, decimal=15) np.testing.assert_almost_equal(delay1['A2v'][1], 0.0, decimal=15)
def drift_pointing_offset(target, duration=60.): obs_start_ts = target.antenna.observer.date transit_time = obs_start_ts + duration / 2.0 # Stationary transit point becomes new target antenna = target.antenna az, el = target.azel(timestamp=transit_time) target = katpoint.construct_azel_target(katpoint.wrap_angle(az), el) # katpoint destructively set dates and times during calculation # restore datetime before continuing target.antenna = antenna target.antenna.observer.date = obs_start_ts return target
def drift_pointing_offset(ref_antenna, target, duration=60.0): """Drift pointing offset observation. Parameters ---------- target: katpoint.Target duration: float """ obs_start_ts = ref_antenna.observer.date transit_time = obs_start_ts + duration / 2.0 # Stationary transit point becomes new target az, el = target.azel(timestamp=transit_time, antenna=ref_antenna) target = katpoint.construct_azel_target(katpoint.wrap_angle(az), el) # katpoint destructively set dates and times during calculation # restore datetime before continuing target.antenna = ref_antenna target.antenna.observer.date = obs_start_ts return target
def select_and_average(filename, average_time): # Read a file into katdal, and average the data to the prescribed averaging time # Returns the weather data and timestamps with the correct averaging interval data = katdal.open(filename) raw_timestamps = data.sensor.timestamps raw_wind_speed = data.wind_speed raw_temperature = data.temperature raw_dumptime = data.dump_period # Get azel of each antenna and separation of each antenna sun = katpoint.Target('Sun, special', antenna=data.ants[0]) alltimestamps = data.timestamps[:] solar_seps = np.zeros_like(alltimestamps) for dumpnum, timestamp in enumerate(alltimestamps): azeltarget = katpoint.construct_azel_target( katpoint.deg2rad(data.az[dumpnum, 0]), katpoint.deg2rad(data.el[dumpnum, 0])) azeltarget.antenna = data.ants[0] solar_seps[dumpnum] = katpoint.rad2deg( azeltarget.separation(sun, timestamp)) #Determine number of dumps to average num_average = max(int(np.round(average_time / raw_dumptime)), 1) #Array of block indices indices = list( range(min(num_average, raw_timestamps.shape[0]), raw_timestamps.shape[0] + 1, min(num_average, raw_timestamps.shape[0]))) timestamps = np.average(np.array(np.split(raw_timestamps, indices)[:-1]), axis=1) wind_speed = np.average(np.array(np.split(raw_wind_speed, indices)[:-1]), axis=1) temperature = np.average(np.array(np.split(raw_temperature, indices)[:-1]), axis=1) dump_time = raw_dumptime * num_average return (timestamps, alltimestamps, wind_speed, temperature, dump_time, solar_seps, data.ants[0])
start_time = time.time() while once or time.time() < start_time + opts.max_duration: once = False moon = katpoint.Target('Moon, special') moon.antenna = katpoint.Antenna( 'ant1, -30:43:17.3, 21:24:38.5, 1038.0, 12.0, 18.4 -8.7 0.0, -0:05:30.6 0 -0:00:03.3 0:02:14.2 0:00:01.6 -0:01:30.6 0:08:42.1, 1.22' ) off1 = katpoint.construct_radec_target( moon.azel()[0] + np.radians(10), moon.azel()[1]) off1.antenna = katpoint.Antenna( 'ant1, -30:43:17.3, 21:24:38.5, 1038.0, 12.0, 18.4 -8.7 0.0, -0:05:30.6 0 -0:00:03.3 0:02:14.2 0:00:01.6 -0:01:30.6 0:08:42.1, 1.22' ) off1.name = 'off' off2 = katpoint.construct_azel_target( moon.azel()[0] - np.radians(10), moon.azel()[1]) off2.antenna = katpoint.Antenna( 'ant1, -30:43:17.3, 21:24:38.5, 1038.0, 12.0, 18.4 -8.7 0.0, -0:05:30.6 0 -0:00:03.3 0:02:14.2 0:00:01.6 -0:01:30.6 0:08:42.1, 1.22' ) off2.name = 'off' sources = katpoint.Catalogue(add_specials=False) sources.add(moon) off1_T = Data[dec(np.degrees(off1.radec()[1])), ra(np.degrees(off1.radec()[0]))] off2_T = Data[dec(np.degrees(off2.radec()[1])), ra(np.degrees(off2.radec()[0]))] if off1_T > off2_T: sources.add(off2) else: sources.add(off1)
# Edit out some RFI d.scans = d.compscans[0].scans d.scans[37] = d.scans[37].select(timekeep=range(76), copy=True) d.scans[38] = d.scans[38].select(timekeep=range(12, len(d.scans[38].timestamps)), copy=True) d.scans[72] = d.scans[72].select(timekeep=range(2, len(d.scans[72].timestamps)), copy=True) # Replace target coordinates with (ra,dec) offsets instead of (az,el) offsets target = d.compscans[0].target for scan in d.scans: ra_dec = np.array([ katpoint.construct_azel_target(az, el).radec(t, d.antenna) for az, el, t in zip(scan.pointing['az'], scan.pointing['el'], scan.timestamps) ]) scan.target_coords = np.array( target.sphere_to_plane(ra_dec[:, 0], ra_dec[:, 1], scan.timestamps, coord_system='radec')) # Fit standard Gaussian beam and baselines d.fit_beams_and_baselines(circular_beam=False) # Fit linear baselines for all scans that did not get refined baselines in the standard fit for n, scan in enumerate(d.scans): if scan.baseline is None: scan_power = scan.pol('I').squeeze() # Get confidence interval based on radiometer equation
session.capture_start() start_time = time.time() targets_observed = [] # Keep going until the time is up keep_going = True while keep_going: keep_going = (opts.max_duration is not None) and opts.repeat targets_before_loop = len(targets_observed) # Iterate through source list, picking the next one that is up for target in observation_sources.iterfilter( el_limit_deg=opts.horizon): target_future_azel = target.azel(timestamp=time.time() + opts.track_duration / 2) target = katpoint.construct_azel_target( katpoint.wrap_angle(target_future_azel[0]), katpoint.wrap_angle(target_future_azel[1])) session.label('track') user_logger.info( "Initiating %g-second drift scan on target '%s'", opts.track_duration, target.name) # Split the total track on one target into segments lasting as long as the noise diode period # This ensures the maximum number of noise diode firings total_track_time = 0. while total_track_time < opts.track_duration: next_track = opts.track_duration - total_track_time # Cut the track short if time ran out if opts.max_duration is not None: next_track = min( next_track, opts.max_duration - (time.time() - start_time))
def daq_pos(self, name=None, daq_attrs=None): ''' Creates a hdf5 file for every day and stores the position of the current session in the group 'name' :param name: string name of the datagroup in the hdf file. If None it will use the format "positions_'start Timestamp of record'" ''' # One hdf file for one day: 'positions_YYYY_MM_DD.h5' data_dict = {} for i, ant in enumerate(self.antennaList): data_dict[ant] = [] self.daq = True self.data_saved = False # Start data acquisition while self.daq: pos = self.get_pos() for i, ant in enumerate(self.antennaList): target = construct_azel_target(deg2rad(pos[i][1]), deg2rad(pos[i][2])) radec = target.astrometric_radec(timestamp=pos[i][0], antenna=ant) data_dict[ant].append((pos[i][0], pos[i][1], pos[i][2], radec[0], radec[1])) time.sleep(1) # If task is done, safe the data in an hdf5 file if not name: new_name = '%s_positions' % Timestamp().local()[11:19] # positions_HH:MM:SS else: new_name = name used = True date = datetime.today().date().strftime('%Y_%m_%d') i = 1 # Define column names and data types dtype = np.dtype([ ('Timestamp', np.float), ('Azimuth', np.float), ('Elevation', np.float), ('RA (J2000)', h5py.special_dtype(vlen=str)), ('DEC (J2000)', h5py.special_dtype(vlen=str)) ]) with h5py.File(self.daq_dirpath + '/positions_%s.h5' % date, 'a') as hdf: while used: try: G = hdf.create_group(new_name) used = False except ValueError: new_name = name + '_' + str(i) i += 1 for i, ant in enumerate(self.antennaList): data_array = np.array(data_dict[ant], dtype=dtype) dset = G.create_dataset('%s' % ant.name, data=data_array) dset.attrs.update({ 'Antenna name': ant.name, 'Antenna latitude': ant.observer.lat, 'Antenna longitude': ant.observer.long, 'Antenna altitude': ant.observer.elevation }) if isinstance(daq_attrs, dict): for key, val in daq_attrs.iteritems(): dset.attrs[key] = val print 'Data saved!' self.data_saved = True
else: # Get current position of first antenna in the list (assume the rest are the same or close) if kat.dry_run: current_az, current_el = session._fake_ants[0][2:] else: current_az = session.ants[0].sensor.pos_actual_scan_azim.get_value() current_el = session.ants[0].sensor.pos_actual_scan_elev.get_value() if current_az is None: user_logger.warning("Sensor kat.%s.sensor.pos_actual_scan_azim failed - using default azimuth" % (session.ants[0].name)) current_az = 0. if current_el is None: user_logger.warning("Sensor kat.%s.sensor.pos_actual_scan_elev failed - using default elevation" % (session.ants[0].name)) current_el = 30. current_pos = katpoint.construct_azel_target(katpoint.deg2rad(current_az), katpoint.deg2rad(current_el)) # Get closest strong source that is up strong_sources = kat.sources.filter(el_limit_deg=[15, 75], flux_limit_Jy=100, flux_freq_MHz=opts.centre_freq) target = strong_sources.targets[np.argmin([t.separation(current_pos) for t in strong_sources])] user_logger.info("No target specified, picked the closest strong source") session.label('raster') session.fire_noise_diode('coupler', 4, 4) session.raster_scan(target, num_scans=3, scan_duration=15, scan_extent=5.0, scan_spacing=0.5) if not kat.dry_run: # Wait until desired HDF5 file appears in the archive (this could take quite a while...) if not session.output_file: raise RuntimeError('Could not obtain name of HDF5 file that was recorded') user_logger.info("Waiting for HDF5 file '%s' to appear in archive" % (session.output_file,)) h5file = session.get_archived_product(download_dir=os.path.abspath(os.path.curdir)) if not os.path.isfile(h5file):
moon = kat.sources.lookup['moon'] with start_session(kat, **vars(opts)) as session: session.standard_setup(**vars(opts)) session.nd_params = nd_off session.capture_start() once = True start_time = time.time() while once or time.time() < start_time + opts.max_duration: once = False moon = katpoint.Target('Moon, special') antenna = katpoint.Antenna( 'ant1, -30:43:17.3, 21:24:38.5, 1038.0, 12.0, 18.4 -8.7 0.0, -0:05:30.6 0 -0:00:03.3 0:02:14.2 0:00:01.6 -0:01:30.6 0:08:42.1, 1.22' ) # find some way of getting this from session moon.antenna = antenna off1_azel = katpoint.construct_azel_target( wrap_angle(moon.azel()[0] + np.radians(10)), moon.azel()[1]) off1_azel.antenna = antenna off1 = katpoint.construct_radec_target(off1_azel.radec()[0], off1_azel.radec()[1]) off1.antenna = antenna off1.name = 'off1' off2_azel = katpoint.construct_azel_target( wrap_angle(moon.azel()[0] - np.radians(10)), moon.azel()[1]) off2_azel.antenna = antenna off2 = katpoint.construct_radec_target(off2_azel.radec()[0], off2_azel.radec()[1]) off2.antenna = antenna off2.name = 'off2'
def reversescan(session, target, nd_period=None, lead_time=None, **kwargs): """Reverse scan observation. This scan is done in "Reverse" This means that it is given an area to scan (via kwargs) rather that a target and parameters Parameters ---------- session: `CaptureSession` target: katpoint.Target nd_period: float noisediode period lead_time: float noisediode trigger lead time """ # trigger noise diode if set trigger(session.kat, duration=nd_period, lead_time=lead_time) if 'radec_p1' in kwargs and 'radec_p2' in kwargs: # means that there is a target area # find lowest setting part or # highest rising part antenna = copy.copy(target.antenna) target_list = [] for i in range(1, _MAX_POINTS_IN_SCAN_AREA_POLYGON + 1): key = 'radec_p%i' % i if key in kwargs: target_list.append( katpoint.Target( 't%i,radec,%s' % (i, kwargs[key]), antenna=target.antenna, )) else: user_logger.error( "No scan area defined - require radec_p1 and radec_p2") return False direction = kwargs.get("direction", False) scan_speed = kwargs.get("scan_speed", _DEFAULT_SCAN_SPEED_ARCMIN_PER_SEC) obs_start_ts = katpoint.Timestamp(time.time()).to_ephem_date() # use 1 deg offset to pre-position >4 min in the future to take into account slewing el, az_min, az_max, t_start, t_end = _get_scan_area_extents(target_list, antenna, obs_start_ts, offset_deg=1) # TODO: get horizon limit from observation - may want to pass limits of # the "acceptable elevation extent" into _get_scan_area_extents. if _MIN_HORIZON_EL_FOR_SCAN_DEG > np.degrees(el): user_logger.warning( "Source and scan below horizon: %s < %s", np.degrees(el), _MIN_HORIZON_EL_FOR_SCAN_DEG, ) return False scan_target = katpoint.construct_azel_target(katpoint.wrap_angle(az_min), el) scan_target.name = target.name # katpoint destructively set dates and times during calculation # restore datetime before continuing scan_target.antenna = antenna scan_target.antenna.observer.date = obs_start_ts user_logger.info("Slew to scan start") # slew to target. target_visible = session.track(scan_target, duration=0.0, announce=False) if not target_visible: user_logger.warning( "Start of scan is not visible! Elevation: %.1f deg.", np.degrees(el)) return False # This is the real scan obs_start_ts = katpoint.Timestamp(time.time()).to_ephem_date() el, az_min, az_max, t_start, t_end = _get_scan_area_extents( target_list, antenna, obs_start_ts) scan_target = katpoint.construct_azel_target( katpoint.wrap_angle((az_min + az_max) / 2.), el) scan_target.name = target.name # katpoint destructively set dates and times during calculation # restore datetime before continuing scan_target.antenna = antenna scan_target.antenna.observer.date = obs_start_ts scan_start = np.degrees(az_min - (az_min + az_max) / 2.) scan_end = np.degrees(az_max - (az_min + az_max) / 2.) scanargs = {} if "projection" in kwargs: scanargs["projection"] = kwargs["projection"] # take into account projection effects of the sky and convert to degrees per second # E.g., 5 arcmin/s should translate to 5/60/cos(el) deg/s scan_speed = (scan_speed / 60.0) / np.cos(el) scanargs["duration"] = abs(scan_start - scan_end) / scan_speed # Duration in seconds user_logger.info("Scan duration is %.2f and scan speed is %.2f deg/s", scanargs["duration"], scan_speed) user_logger.info("Start Time: %s", t_start) user_logger.info("End Time: %s", t_end) num_scan_lines = 0 while time.time() <= t_end.secs: if direction: scanargs["start"] = scan_start, 0.0 scanargs["end"] = scan_end, 0.0 else: scanargs["start"] = scan_end, 0.0 scanargs["end"] = scan_start, 0.0 user_logger.info("Azimuth scan extent [%.1f, %.1f]" % (scanargs["start"][0], scanargs["end"][0])) target_visible = scan(session, scan_target, nd_period=nd_period, lead_time=lead_time, **scanargs) direction = not direction if target_visible: num_scan_lines += 1 user_logger.info("Scan completed - %s scan lines", num_scan_lines) return num_scan_lines > 0
print targetName print "newra %f newdec %f" % (katpoint.rad2deg(ra), katpoint.rad2deg(dec)) Starget = katpoint.construct_radec_target(ra, dec2) Starget.antenna = bf_ants Starget.name = targetName + '_S' sources.add(Starget) # Get onto beamformer target session.track(target, duration=5) # Perform a drift scan if selected if opts.drift_scan: transit_time = katpoint.Timestamp() + opts.target_duration / 2.0 # Stationary transit point becomes new target az, el = target.azel(timestamp=transit_time) target = katpoint.construct_azel_target(katpoint.wrap_angle(az), el) # Go to transit point so long session.track(target, duration=0) # Only start capturing once we are on target session.capture_start() user_logger.info("sleeping 10 secs, will be removed later in dpc " "is not asynchronous") time.sleep(10) # for targets in list user_logger.info("ptuse.req.ptuse_target_start(%s)", target.name) reply = ptuse.req.ptuse_target_start(target.name) user_logger.info("ptuse.req.ptuse_target_start returned %s", reply) # start PTUSE via the handles in the kat.ant.reqptuse
#!/usr/bin/python # Write raw data packets from correlator to disk (not HDF5 file). Used for RFI mitigation code testing. import katpoint import katuilib from katuilib import CaptureSession import uuid import math kat = katuilib.tbuild('cfg-local.ini', 'local_ff') targets = [ kat.sources["Fornax A"], kat.sources["J0440-4333"], kat.sources["Zenith"], katpoint.construct_azel_target(math.radians(0.0), math.radians(45.0)), katpoint.construct_azel_target(math.radians(0.0), math.radians(20.0)), ] with CaptureSession(kat, str(uuid.uuid1()), 'ffuser', 'RFI data collection', kat.ants) as session: session.standard_setup() kat.dbe.req.k7w_write_raw(1) for target in targets: session.track(target, duration=300.0, drive_strategy='shortest-slew')
def move_to_pos(self, az, el=None, for_track=False, azel_off=[0,0]): ''' moves the telescopes to a specific azel or radec or to a target position :param az: float/int, string if float/int: az if string: ra when in format ('HH:MM:SS') otherwise search for target :param el: float/int, string if float/int: el, if string: declination in degree ''' if self.error: print "Error has occured. Can not move at %s."%Timestamp().to_string() elif self.halt: print "Halt has occured. Can not move at %s."%Timestamp().to_string() # Important if you choose another telescope while another is moving antennas = self.active_antennas # Checks whether azel, radec or a target is given if isinstance(az, (int, float)) and isinstance(el, (int, float)): az = az % 360 target = construct_azel_target(deg2rad(az), deg2rad(el)) target.name = 'Moving to az: %d, el: % d at %s' % (az, el, Timestamp().to_string()) elif isinstance(az, str) and isinstance(el, str): target = construct_radec_target(az, el) target.name = 'Moving to ra: %s, dec: %s at %s' % (az, el, Timestamp().to_string()) elif isinstance(az, str) and not el: if ',' in az: target = Target(az) else: target = self.Catalogue[az] elif isinstance(az, Target): target = az else: raise AttributeError('Wrong format') try: azel = check_target(self, target) except LookupError: return 'Target with position az: %s, el: %s is out of telescope range' % (az, el) self.enableTelescopes() self.inSafetyPosition = False moveIncrementalAdapter(self, target, antennas=antennas, azElOff=azel_off) #inRange = [[False]*2]*len(antennas) inRange = [] for i in antennas: # list of Booleans which show if the antennas are at the right position inRange.append([False, False]) all_inRange = False azel = np.add(azel,azel_off) while ((self.CurrentSystemStatus.value() == 5 or (not all_inRange)) and not self.error and not self.halt): for n, ant in enumerate(antennas): for i, az_el in enumerate(azel[n]): # check if antenna is range if az_el-0.5 <= ant.azElPos[i].value() <= az_el+0.5: inRange[n][i] = True all_inRange = all(i == [True]*2 for i in inRange) time.sleep(1) if (not all_inRange and not self.CurrentMotionCommand.value() == self.moveIncrementalValue and not self.error and not self.halt): moveIncrementalAdapter(self, target, antennas=antennas, azElOff=azel_off) # Get position of all Telescopes pos = self.get_pos() if not for_track: if inRange: print 'Telescopes are in position at %s:'% Timestamp().to_string() for i, azel in enumerate(pos): print '%s \t Azimuth: %s \t Elevation: %s' % (self.antennaList[i].name, azel[1], azel[2]) self.disableTelescopes()