diff --git a/tangostationcontrol/tangostationcontrol/beam/delays.py b/tangostationcontrol/tangostationcontrol/beam/delays.py index 7ed8dced892fc70df5c75edc387b45ee5bba686c..4bbbe78968cdc7292ae1b271d31e866886f6e47d 100644 --- a/tangostationcontrol/tangostationcontrol/beam/delays.py +++ b/tangostationcontrol/tangostationcontrol/beam/delays.py @@ -68,7 +68,7 @@ class Delays: These are the delays that have to be applied to the signal chain in order to line up the signal. Positions closer to the source will result in a positive delay. - + Returns delays[antenna]. """ return self.delays_bulk([direction], numpy.array(antenna_absolute_itrf) - self.reference_itrf).flatten() @@ -78,7 +78,7 @@ class Delays: These are the delays that have to be applied to the signal chain in order to line up the signal. Positions closer to the source will result in a positive delay. - + Returns delays[antenna][direction]. """ # obtain the direction vector for each pointing diff --git a/tangostationcontrol/tangostationcontrol/beam/geo.py b/tangostationcontrol/tangostationcontrol/beam/geo.py index a861ef66110bc92ea861b93ccb50b80eda41e518..97e964dfd2b36a9305367d496c0ed65fd0f06c22 100644 --- a/tangostationcontrol/tangostationcontrol/beam/geo.py +++ b/tangostationcontrol/tangostationcontrol/beam/geo.py @@ -21,11 +21,11 @@ import geohash def _apply_fn_on_one_element_or_array(fn, array: numpy.array) -> numpy.array: if array.ndim == 1: - # convert a single coordinate triple - return fn(array) + # convert a single coordinate triple + return fn(array) else: - # convert each coordinate triple - return numpy.apply_along_axis(fn, 1, array) + # convert each coordinate triple + return numpy.apply_along_axis(fn, 1, array) def ETRS_to_ITRF(ETRS_coordinates: numpy.array, ITRF_reference_frame: str = "ITRF2005", ITRF_reference_epoch: float = 2015.5) -> numpy.array: """ Convert an array of coordinate triples from ETRS to ITRF, in the given reference frame and epoch. """ diff --git a/tangostationcontrol/tangostationcontrol/beam/hba_tile.py b/tangostationcontrol/tangostationcontrol/beam/hba_tile.py index 40bb34d686ffaf9cd71b1cb8c5a6f42f96e2197e..14475cf2ab561db97801758e471d032e0894ec42 100644 --- a/tangostationcontrol/tangostationcontrol/beam/hba_tile.py +++ b/tangostationcontrol/tangostationcontrol/beam/hba_tile.py @@ -8,11 +8,11 @@ class HBATAntennaOffsets(object): """ This class helps calculate the absolute offsets of the antennas within a tile, based on their relative orientation to ETRS. - + These offsets are Known in LOFAR1 as "iHBADeltas". Within LOFAR, we use a relative "PQR" coordinate system for each station: - + * The origin is the same as the ETRS reference position of the station, * "Q" points to true North as seen from CS002LBA, the center of LOFAR, * "P" points (roughly) east, @@ -27,7 +27,7 @@ class HBATAntennaOffsets(object): ` relative positions of each antenna element within a tile in ETRS space. The relative ITRF positions are subsequently equal to the relative ETRS positions. - + For reference, see: https://git.astron.nl/RD/lofar-referentie-vlak/-/blob/master/data/dts/dts.ipynb https://git.astron.nl/ro/lofar/-/blob/master/MAC/Deployment/data/Coordinates/calc_hba_deltas.py diff --git a/tangostationcontrol/tangostationcontrol/clients/comms_client.py b/tangostationcontrol/tangostationcontrol/clients/comms_client.py index b59d1f611707b5dfa6109ca7de144217e70667ba..d18c3e47e02bd113aa2954f406d1f863f383983f 100644 --- a/tangostationcontrol/tangostationcontrol/clients/comms_client.py +++ b/tangostationcontrol/tangostationcontrol/clients/comms_client.py @@ -17,7 +17,7 @@ class AbstractCommClient(ABC): def ping(self): """ Check whether the connection is still alive. - + Clients that override this method must raise an Exception if the connection died. """ pass @@ -31,7 +31,7 @@ class AbstractCommClient(ABC): as well as a reference to the attribute itself. The read_function must return a single value, representing the current value of the attribute. - + The write_function must take a single value, write it, and return None. Examples: @@ -105,7 +105,7 @@ class CommClient(AbstractCommClient, Thread): def ping(self): """ Check whether the connection is still alive. - + Clients that override this method must raise an Exception if the connection died. """ pass diff --git a/tangostationcontrol/tangostationcontrol/clients/statistics/client.py b/tangostationcontrol/tangostationcontrol/clients/statistics/client.py index afbf93840499f0ddd8c85c8dbbda4fa626705402..8cbcffc445fc2d3124e11f1f1f42ced225860c23 100644 --- a/tangostationcontrol/tangostationcontrol/clients/statistics/client.py +++ b/tangostationcontrol/tangostationcontrol/clients/statistics/client.py @@ -131,7 +131,7 @@ class StatisticsClient(AsyncCommClient): return self.collector.parameters[parameter].reshape(attribute.dim_x) else: return self.collector.parameters[parameter] - + def _process_replicator_annotation(): parameters_dict = {"clients": numpy.array(self.tcp.clients(),dtype=str), "nof_bytes_sent": numpy.uint64(self.tcp.nof_bytes_sent), @@ -141,7 +141,7 @@ class StatisticsClient(AsyncCommClient): if parameter == k: return v raise ValueError(f"Unknown replicator parameter requested: {parameter}") - + def write_function(value): """ Not used here @@ -149,4 +149,4 @@ class StatisticsClient(AsyncCommClient): pass return read_function, write_function - + diff --git a/tangostationcontrol/tangostationcontrol/common/measures.py b/tangostationcontrol/tangostationcontrol/common/measures.py index 596e0ff4e9c229a6ea848e0ac40c2a3edddc27e4..fd9438caa492940de222043ff0f18c7193be6b54 100644 --- a/tangostationcontrol/tangostationcontrol/common/measures.py +++ b/tangostationcontrol/tangostationcontrol/common/measures.py @@ -55,7 +55,7 @@ def get_measures_directory(): def use_measures_directory(newdir): """ Select a new set of measures tables to use. - + NOTE: Python must be restarted if the 'casacore.measures' module already loaded the measures table before this switch. @@ -83,7 +83,7 @@ def use_measures_directory(newdir): def restart_python(): """ Force a restart this python program. - + This function does not return. """ exe_path = pathlib.Path(sys.executable) diff --git a/tangostationcontrol/tangostationcontrol/devices/antennafield.py b/tangostationcontrol/tangostationcontrol/devices/antennafield.py index e3289b9b7df79719cfdf56e3508a66bcaeb869db..b0a48fe25bf083bf7024fed5d9fcf0babedb49dd 100644 --- a/tangostationcontrol/tangostationcontrol/devices/antennafield.py +++ b/tangostationcontrol/tangostationcontrol/devices/antennafield.py @@ -61,10 +61,10 @@ class mapped_attribute(attribute): return device.get_mapped_attribute(mapping_attribute) self.fget = read_func_wrapper - + super().__init__(dtype=dtype, max_dim_y=max_dim_y, max_dim_x=max_dim_x, access=access, fisallowed="is_attribute_access_allowed", **kwargs) - + @device_logging_to_python() class AntennaField(lofar_device): @@ -143,7 +143,7 @@ class AntennaField(lofar_device): dtype='DevVarFloatArray', mandatory=False ) - + Antenna_Reference_ETRS = device_property( doc="ETRS position (XYZ) of each Antenna", dtype='DevVarFloatArray', @@ -188,7 +188,7 @@ class AntennaField(lofar_device): ) # ----- RECV mapping - + Power_to_RECV_mapping = device_property( dtype=(numpy.int32,), doc='The mapping of Antenna power lines to RECV mapping. Each RECV can handle 96 inputs. The Antenna number is the index and the value shows to which receiver device it is connected and on which input. The first integer is the input. The second integer is the RECV id. Example: [0, 3] = first receiver of property RECV_devices with input 3. -1 means that the Antenna is not connected. The property is stored in a one dimensional structure. It needs to be reshaped to a list of lists of two items.', @@ -280,16 +280,16 @@ class AntennaField(lofar_device): def read_Antenna_Names_R(self): return self.Antenna_Names - + def read_Antenna_Use_R(self): return self.Antenna_Use - + def read_Antenna_Quality_R(self): return self.Antenna_Quality def read_Antenna_Use_str_R(self): return [AntennaUse(x).name for x in self.Antenna_Use] - + def read_Antenna_Quality_str_R(self): return [AntennaQuality(x).name for x in self.Antenna_Quality] @@ -312,7 +312,7 @@ class AntennaField(lofar_device): # # Parsing a property here is quickest, so we chose that. return len(self.Control_to_RECV_mapping) // 2 - + def read_Antenna_Field_Reference_ITRF_R(self): # provide ITRF field coordinates if they were configured if self.Antenna_Field_Reference_ITRF: @@ -321,7 +321,7 @@ class AntennaField(lofar_device): # calculate them from ETRS coordinates if not, using the configured ITRF reference ETRS_coordinates = numpy.array(self.Antenna_Field_Reference_ETRS).reshape(3) return ETRS_to_ITRF(ETRS_coordinates, self.ITRF_Reference_Frame, self.ITRF_Reference_Epoch) - + def read_Antenna_Field_Reference_GEO_R(self): return ITRF_to_GEO(self.read_Antenna_Field_Reference_ITRF_R()) @@ -339,7 +339,7 @@ class AntennaField(lofar_device): and finally translated into global ETRS coordinates using the HBAT_PQR_to_ETRS_rotation_matrix. The relative ITRF offsets are the same as relative ETRS offsets. - + NB: In all of this, the absolute position of each tile is actually irrelevant, as all the tiles lie on the same plane in ITRF. """ @@ -357,7 +357,7 @@ class AntennaField(lofar_device): for angle_deg in self.HBAT_PQR_rotation_angles_deg]) return all_offsets.reshape(-1, NUMBER_OF_ELEMENTS_PER_TILE * 3) - + def read_Antenna_Reference_ITRF_R(self): # provide ITRF coordinates if they were configured if self.Antenna_Reference_ITRF: @@ -399,7 +399,7 @@ class AntennaField(lofar_device): mapped_values = self.__mapper.map_read(mapped_point, recv_results) return mapped_values - + def set_mapped_attribute(self, mapped_point: str, value, cast_type: type): """Set the attribute to new value only for controlled points @@ -418,7 +418,7 @@ class AntennaField(lofar_device): self.atomic_read_modify_write_attribute( new_values, recv_proxy, mapped_point, cast_type=cast_type ) - + # -------- # Overloaded functions # -------- @@ -428,7 +428,7 @@ class AntennaField(lofar_device): super().configure_for_initialise() self.__setup_all_receiver_proxies() self.__setup_mapper() - + @log_exceptions() def _prepare_hardware(self): usage_mask = self.read_attribute('Antenna_Usage_Mask_R') @@ -464,7 +464,7 @@ class AntennaField(lofar_device): # convert them into delay steps flatten_delay_steps = numpy.array(recv_proxy.calculate_HBAT_bf_delay_steps(recv_delays.flatten()), dtype=numpy.int64) delay_steps = numpy.reshape(flatten_delay_steps,(-1, NUMBER_OF_ELEMENTS_PER_TILE * 2)) - + # write back into same positions we collected them from result_values[recv_result_indices] = delay_steps @@ -533,9 +533,9 @@ class AntennaToRecvMapper(object): if mapped_attribute in self._reshape_attributes_in: recv_results = numpy.reshape(recv_results, (self._number_of_receivers,) + self._reshape_attributes_in[mapped_attribute]) - + return self._mapped_r_values(recv_results, default_values) - + def map_write(self, mapped_attribute: str, set_values: List[any]) -> List[any]: """Perform a mapped write for the attribute using the set_values diff --git a/tangostationcontrol/tangostationcontrol/devices/beam_device.py b/tangostationcontrol/tangostationcontrol/devices/beam_device.py index 46f8ef4e01c56c4f88c3a8566afa33a85e354dfe..03349211b468c1556ed234a1ac81b2774ba359da 100644 --- a/tangostationcontrol/tangostationcontrol/devices/beam_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/beam_device.py @@ -64,7 +64,7 @@ class beam_device(lofar_device): mandatory=False, default_value=True ) - + # ---------- # Attributes # ---------- @@ -299,7 +299,7 @@ class beam_device(lofar_device): self._set_pointing(pointing_direction, timestamp) - + @command(dtype_in=DevVarStringArray, dtype_out=DevVarDoubleArray) @DebugIt() @log_exceptions() @@ -331,18 +331,18 @@ class beam_device(lofar_device): @log_exceptions() def download_measures(self): """ Download new measures tables into /opt/IERS, but do not activate them. - + NOTE: This may take a while to complete. You are advised to increase the timeout of the proxy using `my_device.set_timeout_millis(10000)`. """ return download_measures() - + @command(dtype_in=str, doc_in="Measures directory to activate") @DebugIt() @log_exceptions() def use_measures(self, newdir): """ Activate a downloaded set of measures tables. - + NOTE: This will turn off and restart this device!! """ # switch to requested measures @@ -369,7 +369,7 @@ def main(**kwargs): # ---------- class BeamTracker(): - + DISCONNECT_TIMEOUT = 3.0 """ Object that encapsulates a Thread, resposible for beam tracking operations """ @@ -386,7 +386,7 @@ class BeamTracker(): # Whether the pointing has to be forced updated self.stale_pointing = True - + def start(self): """ Starts the Beam Tracking thread """ if self.thread: @@ -398,7 +398,7 @@ class BeamTracker(): self.thread.start() logger.info("BeamTracking thread started") - + def is_alive(self): """ Returns True just before the Thread run() method starts until just after the Thread run() method terminates. """ return self.thread and self.thread.is_alive() @@ -413,13 +413,13 @@ class BeamTracker(): # inform the thread to stop waiting with self.update_lock: self.update_condition.notify() - + def stop(self): """ Stops the Beam Tracking loop """ if not self.thread: return - + logger.info("BeamTracking thread stopping") self.done = True @@ -432,9 +432,9 @@ class BeamTracker(): logger.error("BeamTracking Thread did not properly terminate") self.thread = None - + logger.info("BeamTracking thread stopped") - + def _get_sleep_time(self): """ Computes the sleep time (in seconds) that needs to be waited for the next beam tracking update """ now = datetime.datetime.now().timestamp() @@ -453,7 +453,7 @@ class BeamTracker(): # @fault_on_error routes errors here. we forward them to our device def Fault(self, msg): self.fault_callback(msg) - + @log_exceptions() @fault_on_error() def _update_pointing_direction(self): diff --git a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py index f950ad142ed6070ec5303223769cf77e189578db..b3b9d2bfa469d19f8aa58b4e7b253b015c18e438 100644 --- a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py @@ -207,7 +207,7 @@ class lofar_device(Device, metaclass=DeviceMeta): Device.init_device(self) self.properties_changed() - + self.set_state(DevState.OFF) self.set_status("Device is in the OFF state.") @@ -250,7 +250,7 @@ class lofar_device(Device, metaclass=DeviceMeta): :return:None """ - + self.set_state(DevState.INIT) self.set_status("Device is in the INIT state.") @@ -449,7 +449,7 @@ class lofar_device(Device, metaclass=DeviceMeta): # This is just the command version of _prepare_hardware(). self._prepare_hardware() - + @only_in_states(INITIALISED_STATES) @fault_on_error() @command() @@ -467,7 +467,7 @@ class lofar_device(Device, metaclass=DeviceMeta): # Set state to DISABLE self.set_state(DevState.DISABLE) self.set_status("Device is in the DISABLE state.") - + @only_in_states(DEFAULT_COMMAND_STATES) @command(dtype_out = DevDouble) def max_archiving_load(self): diff --git a/tangostationcontrol/tangostationcontrol/devices/observation.py b/tangostationcontrol/tangostationcontrol/devices/observation.py index d2b22f4a91b211792b1bc9a08f32c590db6292ef..56b55a40288d7f483cc04f3185cfbc51ebabdc91 100644 --- a/tangostationcontrol/tangostationcontrol/devices/observation.py +++ b/tangostationcontrol/tangostationcontrol/devices/observation.py @@ -58,7 +58,7 @@ class Observation(lofar_device): first_beamlet_R = attribute(dtype=numpy.int64, access=AttrWriteType.READ) observation_settings_RW = attribute(dtype=str, access=AttrWriteType.READ_WRITE) - + def init_device(self): """Setup some class member variables for observation state""" @@ -163,42 +163,42 @@ class Observation(lofar_device): def read_stop_time_R(self): """Return the stop_time_R attribute.""" return self._stop_time.timestamp() - + @only_in_states([DevState.STANDBY, DevState.ON]) @fault_on_error() @log_exceptions() def read_antenna_mask_R(self): """Return the antenna_mask_R attribute.""" return self._antenna_mask - + @only_in_states([DevState.STANDBY, DevState.ON]) @fault_on_error() @log_exceptions() def read_filter_R(self): """Return the filter_R attribute.""" return self._filter - + @only_in_states([DevState.STANDBY, DevState.ON]) @fault_on_error() @log_exceptions() def read_saps_subband_R(self): """Return the saps_subband_R attribute.""" return self._saps_subband - + @only_in_states([DevState.STANDBY, DevState.ON]) @fault_on_error() @log_exceptions() def read_saps_pointing_R(self): """Return the saps_pointing_R attribute.""" return self._saps_pointing - + @only_in_states([DevState.STANDBY, DevState.ON]) @fault_on_error() @log_exceptions() def read_tile_beam_R(self): """Return the tile_beam_R attribute.""" return self._tile_beam - + @only_in_states([DevState.STANDBY, DevState.ON]) @fault_on_error() @log_exceptions() @@ -240,7 +240,7 @@ class Observation(lofar_device): """ Build the sap pointing array preserving the correct order from JSON """ pointing_direction = parameters["tile_beam"] return [str(pointing_direction['direction_type']), f"{pointing_direction['angle1']}deg", f"{pointing_direction['angle2']}deg"] - + def _apply_antennafield_settings(self, antenna_mask:list, filter_name:str): """ Convert an array of antenna indexes into a boolean mask array and retrieve the RCU band from filter name, returning the correct format for @@ -253,7 +253,7 @@ class Observation(lofar_device): ANT_mask_RW[a] = True RCU_band_select_RW[a] = rcu_band return numpy.array(ANT_mask_RW), numpy.array(RCU_band_select_RW) - + def _apply_saps_subbands(self, sap_subbands:list): """ Convert an array of subbands into the correct format for Beamlet device""" subband_select = self.beamlet_proxy.subband_select_RW @@ -262,7 +262,7 @@ class Observation(lofar_device): sap_subbands = numpy.array(sap_subbands).flatten() subband_select[first_beamlet:len(sap_subbands)] = sap_subbands return subband_select - + def _apply_saps_pointing(self, sap_pointing:list): """ Convert an array of string directions into the correct format for DigitalBeam device""" pointing_direction = list(self.digitalbeam_proxy.Pointing_direction_RW) # convert to list to allows item assignment @@ -270,7 +270,7 @@ class Observation(lofar_device): # Insert pointing values starting from the first beamlet pointing_direction[first_beamlet:len(sap_pointing)] = sap_pointing return tuple(pointing_direction) - + def _apply_saps_antenna_select(self, antenna_mask:list): """ Convert an array of antenna indexes into a boolean select array""" antenna_select = numpy.array([[False] * self.NUM_BEAMLETS] * self._num_inputs) diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py index a1bae7c07266e4b37a7993a5472886f74424737c..fc1b8fcb110dc99fcfd80538707d45ef6b6534de 100644 --- a/tangostationcontrol/tangostationcontrol/devices/recv.py +++ b/tangostationcontrol/tangostationcontrol/devices/recv.py @@ -44,7 +44,7 @@ class RECV(opcua_device): "HBA_110_190": 2, "HBA_210_250": 4 } - + # ----------------- # Device Properties # ----------------- @@ -110,7 +110,7 @@ class RECV(opcua_device): ) # ----- Calibration values - + HBAT_bf_delay_step_delays = device_property( dtype="DevVarFloatArray", mandatory=False, @@ -136,7 +136,7 @@ class RECV(opcua_device): # Attributes # ---------- ANT_mask_RW = attribute_wrapper(comms_annotation=["ANT_mask_RW" ],datatype=bool , dims=(96,), access=AttrWriteType.READ_WRITE) - + # The HBAT beamformer delays represent 32 delays for each of the 96 inputs. # The 32 delays deconstruct as delays[polarisation][dipole], and each delay is the number of 'delay steps' to apply (0.5ns for HBAT1). HBAT_BF_delay_steps_R = attribute_wrapper(comms_annotation=["HBAT_BF_delay_steps_R" ],datatype=numpy.int64 , dims=(96,2,16)) @@ -242,7 +242,7 @@ class RECV(opcua_device): # by a fixed amount, the average of all steps. Doing so should result # in positive delays regardless of the pointing direction. self.HBAT_bf_delay_offset = numpy.mean(self.HBAT_bf_delay_step_delays) - + def _prepare_hardware(self): """ Initialise the RCU hardware. """ @@ -251,7 +251,7 @@ class RECV(opcua_device): self.wait_attribute("RECVTR_translator_busy_R", False, self.RCU_On_Off_timeout) self.RCU_on() self.wait_attribute("RECVTR_translator_busy_R", False, self.RCU_On_Off_timeout) - + def _disable_hardware(self): """ Disable the RECV hardware. """ @@ -294,15 +294,15 @@ class RECV(opcua_device): @command(dtype_in=DevVarFloatArray, dtype_out=DevVarFloatArray) def calculate_HBAT_bf_delay_steps(self, delays: numpy.ndarray): """ converts a signal path delay (in seconds) to an analog beam weight """ - + # Reshape the flatten input array, into whatever how many tiles we get delays = numpy.array(delays).reshape(-1,16) - + # Calculate the beam weight array HBAT_bf_delay_steps = self._calculate_HBAT_bf_delay_steps(delays) - + return HBAT_bf_delay_steps.flatten() - + @command(dtype_in=DevString, dtype_out=DevLong) def get_rcu_band_from_filter(self, filter_name: str): """ return the rcu band given the filter name""" diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py b/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py index e77459a88e69b285c95ad2ac22948f359fe60afb..24dda0332e8711ffd5b67226f4a7d4b1bdc1e2d3 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/beamlet.py @@ -167,7 +167,7 @@ class Beamlet(opcua_device): FPGA_bf_rx_align_nof_valid_R = attribute_wrapper(comms_annotation=["FPGA_bf_rx_align_nof_valid_R"], datatype=numpy.int32, dims=(N_PN, N_BEAMSETS_CTRL, P_SUM)) FPGA_bf_rx_align_latency_R = attribute_wrapper(comms_annotation=["FPGA_bf_rx_align_latency_R"], datatype=numpy.int32, dims=(N_PN, N_BEAMSETS_CTRL, P_SUM)) FPGA_bf_rx_align_nof_replaced_packets_R = attribute_wrapper(comms_annotation=["FPGA_bf_rx_align_nof_replaced_packets_R"], datatype=numpy.int32, dims=(N_PN, N_BEAMSETS_CTRL, P_SUM)) - + subband_select_RW = attribute(dtype=(numpy.uint32,), max_dim_x=N_BEAMLETS_CTRL, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed") def read_subband_select_RW(self): @@ -316,7 +316,7 @@ class Beamlet(opcua_device): @staticmethod def _calculate_bf_weights(delays: numpy.ndarray, beamlet_frequencies: numpy.ndarray): """ Helper function that converts a series of delays into FPGA_bf_weights_xx_yy. - + All input and output arrays have the same dimensionality. """ diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py index 1ec2a46f1442d11295b916be55167559e51f2af3..19504e7087884e0ce1b677387e76543f7abb5c6f 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py @@ -78,7 +78,7 @@ class BST(Statistics): FPGA_bst_offload_hdr_udp_destination_port_RW = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_bst_offload_hdr_udp_destination_port_RW"], datatype=numpy.uint16, dims=(16,), access=AttrWriteType.READ_WRITE) FPGA_bst_offload_hdr_udp_destination_port_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_bst_offload_hdr_udp_destination_port_R"], datatype=numpy.uint16, dims=(16,)) FPGA_bst_offload_bsn_R = attribute_wrapper(comms_id=OPCUAConnection, comms_annotation=["FPGA_bst_offload_bsn_R"], datatype=numpy.int64, dims=(16,)) - + FPGA_bst_offload_nof_packets_R = attribute_wrapper(comms_annotation=["FPGA_bst_offload_nof_packets_R"], datatype=numpy.int32, dims=(16,)) FPGA_bst_offload_nof_valid_R = attribute_wrapper(comms_annotation=["FPGA_bst_offload_nof_valid_R"], datatype=numpy.int32, dims=(16,)) diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py index a87c6b6e00b06ccfe4275055db5772b036dd8995..88191f1cc552d2576853bdfa04bf2b98364bb5a7 100644 --- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py +++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py @@ -168,7 +168,7 @@ class SDP(opcua_device): TR_start_time_R = attribute_wrapper(comms_annotation=["TR_start_time_R"], datatype=numpy.int64) TR_tod_R = attribute_wrapper(comms_annotation=["TR_tod_R"], datatype=numpy.int64, dims=(2,)) TR_tod_pps_delta_R = attribute_wrapper(comms_annotation=["TR_tod_pps_delta_R"], datatype=numpy.double) - + # OPC-UA MP only points for AIT FPGA_signal_input_mean_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_mean_R"], datatype=numpy.double , dims=(N_pn, S_pn)) FPGA_signal_input_rms_R = attribute_wrapper(comms_annotation=["FPGA_signal_input_rms_R"], datatype=numpy.double, dims=(N_pn, S_pn)) @@ -200,7 +200,7 @@ class SDP(opcua_device): The Nyquist zone determines the frequency offset of the antennas. - + NOTE: Only 160 and 200 MHz clocks are supported. """ # (AntennaType, clockMHz) -> Nyquist zone @@ -283,7 +283,7 @@ class SDP(opcua_device): # Wait for the firmware to be loaded (ignoring masked out elements) self.wait_attribute("FPGA_boot_image_R", lambda attr: ((attr == 1) | ~wait_for).all(), 60) - + def _disable_hardware(self): """ Disable the SDP hardware. """ # Save actual mask values diff --git a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py index 75339492ab82353cbc3b2d3a14b7ef262f8b46d4..8c35b22d2655338b9e23d47cc670b497b0a4dddb 100644 --- a/tangostationcontrol/tangostationcontrol/devices/tilebeam.py +++ b/tangostationcontrol/tangostationcontrol/devices/tilebeam.py @@ -97,13 +97,13 @@ class TileBeam(beam_device): # Retrieve delays from casacore delays = self._delays(pointing_direction, timestamp) - + # Convert delays into beam weights delays = delays.flatten() bf_delay_steps = self.antennafield_proxy.calculate_HBAT_bf_delay_steps(delays) return bf_delay_steps - + @TimeIt() def _apply_weights(self, pointing_direction: numpy.array, timestamp: datetime.datetime, bf_delay_steps: numpy.array): # Write weights to RECV through the AntennaToRecvMapper @@ -121,7 +121,7 @@ class TileBeam(beam_device): # -------- # Commands # -------- - + # ---------- # Run server # ---------- diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py index 7a2609e811432a8c772a239186e16f2f442ba7a3..a38fa52aa1814501d2eaa429e258cf6d960c05d8 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/base.py @@ -77,7 +77,7 @@ class AbstractTestBases: def test_device_read_all_attributes(self): """Test if we can read all of the exposed attributes in the ON state. - + This test covers the reading logic of all attributes. """ self.proxy.initialise() diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py index 7d071bc8350f82d9b288fd4cfe45bb7ea0bdf88c..cfec09cb457b2039be8feec2fd20d0f45ef3ed04 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py @@ -59,7 +59,7 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): numpy.testing.assert_equal( numpy.array([True] * 96), self.recv_proxy.ANT_mask_RW ) - + antenna_qualities = numpy.array([AntennaQuality.OK] * 96) antenna_use = numpy.array([AntennaUse.ON] + [AntennaUse.AUTO] * 95) antenna_properties = { diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py index b5d7c9f85e4051e7bcd1f7bc5482166583fb1939..f6658bb714e7c8edf659fd36eda73e889bad955a 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py @@ -27,7 +27,7 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase): self.sdp_proxy = self.setup_sdp() super().test_device_read_all_attributes() - + def setup_sdp(self): # setup SDP, on which this device depends sdp_proxy = TestDeviceProxy("STAT/SDP/1") diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_bst.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_bst.py index 5e00f0b961f769c6fb5867cb40eb7448a05b2234..c049a7befb1d9ebbaeeb2714b088058f36a983aa 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_bst.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_bst.py @@ -15,13 +15,13 @@ class TestDeviceBST(AbstractTestBases.TestDeviceBase): def setUp(self): """Intentionally recreate the device object in each test""" super().setUp("STAT/BST/1") - + def test_device_read_all_attributes(self): # We need to connect to SDP first to read some of our attributes self.sdp_proxy = self.setup_sdp() super().test_device_read_all_attributes() - + def setup_sdp(self): # setup SDP, on which this device depends sdp_proxy = TestDeviceProxy("STAT/SDP/1") diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py index f905e72ec57463ea5c7a41abc5b5a40c31582303..9a7cdd068e9ea34c155e7423ec0816996f8a0fc4 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py @@ -49,7 +49,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase): beamlet_proxy.warm_boot() beamlet_proxy.set_defaults() return beamlet_proxy - + def setup_sdp_proxy(self): # setup SDP, on which this device depends sdp_proxy = TestDeviceProxy(self.sdp_iden) @@ -57,7 +57,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase): sdp_proxy.warm_boot() sdp_proxy.set_defaults() return sdp_proxy - + def setup_antennafield_proxy(self, antenna_qualities, antenna_use): # setup AntennaField NR_TILES = 48 @@ -156,7 +156,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase): numpy.testing.assert_equal( non_zeros, self.beamlet_proxy.FPGA_bf_weights_xx_yy_RW ) - + def test_input_select_with_all_antennas_ok(self): """Verify if input and antenna select are correctly calculated following Antennafield.Antenna_Usage_Mask""" @@ -172,7 +172,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase): numpy.testing.assert_equal(expected_input_select, self.proxy.input_select_RW) expected_antenna_select = numpy.array([[True] * 488 ] * 48) numpy.testing.assert_equal(expected_antenna_select, self.proxy.antenna_select_RW) - + def test_input_select_with_only_second_antenna_ok(self): """Verify if input and antenna select are correctly calculated following Antennafield.Antenna_Usage_Mask""" diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation.py index 4376781d4644ea8b07b07d21d3717c928a89a432..8a4a2b1c65323a83f216c386130de66eb903f07e 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation.py @@ -50,7 +50,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): self.sdp_proxy = self.setup_sdp_proxy() self.digitalbeam_proxy = self.setup_digitalbeam_proxy() self.tilebeam_proxy = self.setup_tilebeam_proxy() - + def setup_recv_proxy(self): # setup RECV recv_proxy = TestDeviceProxy("STAT/RECV/1") @@ -58,14 +58,14 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): recv_proxy.warm_boot() recv_proxy.set_defaults() return recv_proxy - + def setup_sdp_proxy(self): # setup SDP sdp_proxy = TestDeviceProxy("STAT/SDP/1") sdp_proxy.off() sdp_proxy.warm_boot() return sdp_proxy - + def setup_antennafield_proxy(self): # setup AntennaField antennafield_proxy = TestDeviceProxy("STAT/AntennaField/1") @@ -78,7 +78,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): antennafield_proxy.off() antennafield_proxy.boot() return antennafield_proxy - + def setup_beamlet_proxy(self): # setup Digitalbeam beamlet_proxy = TestDeviceProxy("STAT/Beamlet/1") @@ -95,7 +95,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): digitalbeam_proxy.warm_boot() digitalbeam_proxy.set_defaults() return digitalbeam_proxy - + def setup_tilebeam_proxy(self): # Setup Tilebeam tilebeam_proxy = TestDeviceProxy("STAT/TileBeam/1") @@ -103,7 +103,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): tilebeam_proxy.warm_boot() tilebeam_proxy.set_defaults() return tilebeam_proxy - + def test_init_valid(self): """Initialize an observation with valid JSON""" @@ -111,7 +111,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): self.proxy.observation_settings_RW = self.VALID_JSON self.proxy.Initialise() self.assertEqual(DevState.STANDBY, self.proxy.state()) - + def test_init_invalid(self): """Initialize an observation with _invalid_ JSON""" @@ -120,7 +120,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): with self.assertRaises(DevFailed): self.proxy.Initialise() self.assertEqual(DevState.FAULT, self.proxy.state()) - + def test_prohibit_rewriting_settings(self): """Test that changing observation settings is disallowed once init""" @@ -131,7 +131,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): with self.assertRaises(DevFailed): self.proxy.write_attribute( "observation_settings_RW", self.VALID_JSON) - + def test_attribute_match(self): """Test that JSON data is exposed to attributes""" @@ -161,7 +161,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): self.assertListEqual(saps_pointing, list(self.proxy.saps_pointing_R)) self.assertListEqual(tile_beam, list(self.proxy.tile_beam_R)) self.assertEqual(first_beamlet, self.proxy.first_beamlet_R) - + def test_apply_antennafield_settings(self): """Test that attributes antenna_mask and filter are correctly applied""" self.setup_recv_proxy() @@ -178,7 +178,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): self.assertListEqual(antennafield_proxy.ANT_mask_RW.tolist(), expected_masks) expected_bands = [2, 2, 2] + [0] * 6 + [2] + [0] * 38 self.assertListEqual(antennafield_proxy.RCU_band_select_RW.tolist(), expected_bands) - + def test_apply_subbands(self): """Test that attribute sap subbands is correctly applied""" beamlet_proxy = self.setup_beamlet_proxy() @@ -191,7 +191,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): self.proxy.On() expected_subbands = [10,20,30] + [0] * (self.NUM_BEAMLETS_CTRL-3) self.assertListEqual(beamlet_proxy.subband_select_RW.tolist(), expected_subbands) - + def test_apply_pointing(self): """Test that attribute sap pointing is correctly applied""" digitalbeam_proxy = self.setup_digitalbeam_proxy() @@ -204,7 +204,7 @@ class TestDeviceObservation(AbstractTestBases.TestDeviceBase): self.proxy.On() expected_pointing = [("J2000","1.5deg","0deg")] + [("AZELGEO","0deg","90deg")] * 487 self.assertListEqual(list(digitalbeam_proxy.Pointing_direction_RW), expected_pointing) - + def test_apply_antenna_select(self): """Test that antenna selection is correctly applied""" digitalbeam_proxy = self.setup_digitalbeam_proxy() diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation_control.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation_control.py index 0787b10da277311bdc7b53f08d9169c78c24268f..1e6aff8eff8870e2bc224c9ca3e0c7908363c69f 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation_control.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_observation_control.py @@ -52,7 +52,7 @@ class TestObservationControlDevice(AbstractTestBases.TestDeviceBase): self.sdp_proxy = self.setup_sdp_proxy() self.digitalbeam_proxy = self.setup_digitalbeam_proxy() self.tilebeam_proxy = self.setup_tilebeam_proxy() - + def setup_recv_proxy(self): # setup RECV recv_proxy = TestDeviceProxy("STAT/RECV/1") @@ -60,14 +60,14 @@ class TestObservationControlDevice(AbstractTestBases.TestDeviceBase): recv_proxy.warm_boot() recv_proxy.set_defaults() return recv_proxy - + def setup_sdp_proxy(self): # setup SDP sdp_proxy = TestDeviceProxy("STAT/SDP/1") sdp_proxy.off() sdp_proxy.warm_boot() return sdp_proxy - + def setup_antennafield_proxy(self): # setup AntennaField antennafield_proxy = TestDeviceProxy("STAT/AntennaField/1") @@ -78,7 +78,7 @@ class TestObservationControlDevice(AbstractTestBases.TestDeviceBase): antennafield_proxy.warm_boot() antennafield_proxy.set_defaults() return antennafield_proxy - + def setup_beamlet_proxy(self): # setup Digitalbeam beamlet_proxy = TestDeviceProxy("STAT/Beamlet/1") @@ -95,7 +95,7 @@ class TestObservationControlDevice(AbstractTestBases.TestDeviceBase): digitalbeam_proxy.warm_boot() digitalbeam_proxy.set_defaults() return digitalbeam_proxy - + def setup_tilebeam_proxy(self): # Setup Tilebeam tilebeam_proxy = TestDeviceProxy("STAT/TileBeam/1") @@ -132,7 +132,7 @@ class TestObservationControlDevice(AbstractTestBases.TestDeviceBase): parameters = json.loads(self.VALID_JSON) parameters['observation_id'] = -1 - + self.on_device_assert(self.proxy) self.assertRaises( DevFailed, self.proxy.start_observation, json.dumps(parameters)) diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py index 2398206083533a5fcc40051b6a80e42923a38347..80f8d70ffac1346a09a070c1bc645eb0f691c03d 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_sst.py @@ -28,7 +28,7 @@ class TestDeviceSST(AbstractTestBases.TestDeviceBase): self.sdp_proxy = self.setup_sdp() super().test_device_read_all_attributes() - + def setup_sdp(self): # setup SDP, on which this device depends sdp_proxy = TestDeviceProxy("STAT/SDP/1") diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py index e31697646e769d6e98ae835eb8e58522816637bd..44dcfdcf1e02afb14ac80de0d79416a46144fc8e 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_temperature_manager.py @@ -51,7 +51,7 @@ class TestDeviceTemperatureManager(AbstractTestBases.TestDeviceBase): self.proxy.put_property({"Alarm_Error_List": ["RECV, HBAT_LED_on_RW"]}) self.proxy.put_property({"Shutdown_Device_List": ["STAT/SDP/1"]}) devices = [DeviceProxy("STAT/SDP/1")] - + self.proxy.off() self.proxy.initialise() self.proxy.on() @@ -67,7 +67,7 @@ class TestDeviceTemperatureManager(AbstractTestBases.TestDeviceBase): dev.warm_boot() self.assertEqual(self.proxy.get_property('Shutdown_Device_List')['Shutdown_Device_List'][0], "STAT/SDP/1") - + # Here we trigger our own change event by just using an RW attribute self.recv_proxy.HBAT_LED_on_RW = [[False] * 32] * 96 time.sleep(2) @@ -79,7 +79,7 @@ class TestDeviceTemperatureManager(AbstractTestBases.TestDeviceBase): # the TEMP_MANAGER_is_alarming_R should now be True, since it should have detected the temperature alarm. self.assertTrue(self.proxy.is_alarming_R) - + # make sure all the hardware devices are in the DISABLE state for dev in devices: self.assertEqual(DevState.DISABLE, dev.state()) diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py index cfe5f42231e96bd16899734662af00078d78573d..541e04bc4e878043dfa80569b4342712be22cf0e 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_tilebeam.py @@ -33,7 +33,7 @@ class TestDeviceTileBeam(AbstractTestBases.TestDeviceBase): def setUp(self): super().setUp("STAT/TileBeam/1") - + def setup_recv_proxy(self): # setup RECV recv_proxy = TestDeviceProxy("STAT/RECV/1") @@ -41,7 +41,7 @@ class TestDeviceTileBeam(AbstractTestBases.TestDeviceBase): recv_proxy.warm_boot() recv_proxy.set_defaults() return recv_proxy - + def setup_antennafield_proxy(self): # setup AntennaField antennafield_proxy = TestDeviceProxy("STAT/AntennaField/1") @@ -57,7 +57,7 @@ class TestDeviceTileBeam(AbstractTestBases.TestDeviceBase): # check if AntennaField really exposes the expected number of tiles self.assertEqual(self.NR_TILES, antennafield_proxy.nr_antennas_R) return antennafield_proxy - + def test_delays_dims(self): """Verify delays are retrieved with correct dimensions""" self.setup_recv_proxy() @@ -69,7 +69,7 @@ class TestDeviceTileBeam(AbstractTestBases.TestDeviceBase): # verify delays method returns the correct dimensions delays = self.proxy.delays(self.POINTING_DIRECTION) self.assertEqual(self.NR_TILES*16, len(delays)) - + def test_set_pointing(self): """Verify if set pointing procedure is correctly executed""" antennafield_proxy = self.setup_antennafield_proxy() @@ -83,7 +83,7 @@ class TestDeviceTileBeam(AbstractTestBases.TestDeviceBase): self.assertIsNotNone(delays_r1) time.sleep(3) - + # Verify writing operation does not lead to errors self.proxy.set_pointing(self.POINTING_DIRECTION) # write values to RECV delays_r2 = numpy.array(antennafield_proxy.read_attribute('HBAT_BF_delay_steps_RW').value) diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py index 071108ee57e025c30fc423d7ce2312b66d5012a7..abccb44def53f76a0838bef18c6778622f9212db 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_xst.py @@ -22,7 +22,7 @@ class TestDeviceSST(AbstractTestBases.TestDeviceBase): self.sdp_proxy = self.setup_sdp() super().test_device_read_all_attributes() - + def setup_sdp(self): # setup SDP, on which this device depends sdp_proxy = TestDeviceProxy("STAT/SDP/1") diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py index 8187216ca293fc79c4537eafcf8b061b49023611..e1d3256b937f9d859b108ef76db3cf8cc9f861a8 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_lofar_device.py @@ -22,7 +22,7 @@ class TestProxyAttributeAccess(base.IntegrationTestCase): # an attribute to access ATTRIBUTE_NAME = "ANT_mask_RW" - + def setUp(self): self.proxy = TestDeviceProxy(self.DEVICE_NAME) self.proxy.off() @@ -45,14 +45,14 @@ class TestProxyAttributeAccess(base.IntegrationTestCase): # read the attribute -- shouldn't throw _ = self.proxy.read_attribute(self.ATTRIBUTE_NAME) - + def test_fast_setup_polled_attribute(self): """ Setup a device as fast as possible and access its attributes immediately. """ self.poll_attribute() self.read_attribute() - + def test_slow_setup_polled_attribute(self): """ Have the device be off for a while, allowing Tango to poll. Then, Setup a device as fast as possible and access its attributes immediately. """ diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/prometheus/test_tango_prometheus_client.py b/tangostationcontrol/tangostationcontrol/integration_test/default/prometheus/test_tango_prometheus_client.py index f0d1354f6ce9779d3585bd1119f2820652651810..c632a00520e3ba2e54ae7c29264bec3db317b1bf 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/prometheus/test_tango_prometheus_client.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/prometheus/test_tango_prometheus_client.py @@ -33,17 +33,17 @@ class TestPrometheusClient(BaseIntegrationTestCase): config_path = os.path.join(os.path.realpath('..'), 'docker-compose/tango-prometheus-exporter/lofar2-policy.json') CONFIG = tpc_policy.ArchiverPolicy.load_config(config_path) - + def setUp(self): super().setUp() - + def initialise_collector(self): db = Database() station = db.get_property("station","name")["name"][0] custom_collector = tpc_cc.CustomCollector(self.CONFIG, station) self.assertIsNotNone(custom_collector) return custom_collector - + def setup_recv_proxy(self, device_name='stat/recv/1'): # setup RECV recv_proxy = TestDeviceProxy(device_name) @@ -51,13 +51,13 @@ class TestPrometheusClient(BaseIntegrationTestCase): recv_proxy.warm_boot() recv_proxy.set_defaults() return recv_proxy - + def test_tango_db_devices(self): """ Test if device names are correctly retrieved from Tango DB """ policy = tpc_policy.ArchiverPolicy(self.CONFIG) db_devices = policy.device_list() self.assertNotEqual(len(db_devices), 0) - + def test_policy_devices(self): """ Test if device names are correctly filtered with policy file """ policy = tpc_policy.ArchiverPolicy(self.CONFIG) @@ -68,7 +68,7 @@ class TestPrometheusClient(BaseIntegrationTestCase): for d in config_retrieved_devices: if '*' not in d: # filter out wildcards self.assertIn(d, policy_devices) - + def test_archiver_policy_attribute_list(self): """ Test if the full set of archiving policy for the given device is retrieved """ device_name = 'stat/recv/1' @@ -83,7 +83,7 @@ class TestPrometheusClient(BaseIntegrationTestCase): for e in exclude: if '*' not in e: # exclude wildcard self.assertNotIn(e, attribute_list) - + def test_label_metric_list(self): """ Test whether the metric label list matches up with the ones defined in the GaugeMetricFamily constructor""" collector = self.initialise_collector() @@ -92,7 +92,7 @@ class TestPrometheusClient(BaseIntegrationTestCase): expected_scraping_labels = ['station', 'device'] numpy.testing.assert_equal([*attribute_metrics.samples[0].labels.keys()], expected_attribute_labels) numpy.testing.assert_equal([*scraping_metrics.samples[0].labels.keys()], expected_scraping_labels) - + def test_collector_metrics_with_devices_in_off(self): """ Test if the metrics are exposed even if devices are in OFF state """ device_name = 'stat/recv/1' diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/statistics/test_writer_sst.py b/tangostationcontrol/tangostationcontrol/integration_test/default/statistics/test_writer_sst.py index f1cf4f3154cbdbe75e8abb96994e2c5e0ecc1f98..cf730e6461dfc4e438fc77ea8d8150cb59dfa90f 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/statistics/test_writer_sst.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/statistics/test_writer_sst.py @@ -39,13 +39,13 @@ class TestStatisticsWriterSST(BaseIntegrationTestCase): recv_proxy.warm_boot() recv_proxy.set_defaults() return recv_proxy - + def test_retrieve_data_from_RECV(self): self.assertEqual(DevState.ON, self.recv_proxy.state()) self.assertIsNotNone(self.recv_proxy.RCU_Attenuator_dB_R) self.assertIsNotNone(self.recv_proxy.RCU_Band_Select_R) self.assertIsNotNone(self.recv_proxy.RCU_DTH_on_R) - + def test_header_info(self): """ Test whether the header info are inserted and collected in the proper way""" with TemporaryDirectory() as tmpdir: @@ -63,7 +63,7 @@ class TestStatisticsWriterSST(BaseIntegrationTestCase): with mock.patch.object(entry.sys, 'argv', new_sys_argv): with self.assertRaises(SystemExit): entry.main() - + # check if file was written self.assertTrue(isfile(f"{tmpdir}/SST_2021-09-20-12-17-40.h5")) @@ -84,7 +84,7 @@ class TestStatisticsWriterSST(BaseIntegrationTestCase): self.assertIsNotNone(stat) self.assertEqual("0.1.1", stat.station_version_id) self.assertEqual("0.1", stat.writer_version_id) - + def test_insert_tango_SST_statistics(self): self.assertEqual(DevState.ON, self.recv_proxy.state()) collector = StationSSTCollector(device=self.recv_proxy) @@ -121,7 +121,7 @@ class TestStatisticsWriterSST(BaseIntegrationTestCase): # check if file was written self.assertTrue(isfile(f"{tmpdir}/SST_2021-09-20-12-17-40.h5")) - + # test statistics reader new_sys_argv = [ sys.argv[0], @@ -160,7 +160,7 @@ class TestStatisticsWriterSST(BaseIntegrationTestCase): with mock.patch.object(entry.sys, 'argv', new_sys_argv): with self.assertRaises(SystemExit): entry.main() - + # check if file was written self.assertTrue(isfile(f"{tmpdir}/SST_2021-09-20-12-17-40.h5")) @@ -185,7 +185,7 @@ class TestStatisticsWriterSST(BaseIntegrationTestCase): self.assertEqual(stat.rcu_attenuator_dB, None) self.assertEqual(stat.rcu_band_select, None) self.assertEqual(stat.rcu_dth_on, None) - + def test_SST_statistics_with_device_in_off(self): self.setup_recv_proxy() self.recv_proxy.Off() diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py index 5d281f763a84a6f72e7dc19b03663555eadbb36e..37fab6821952b5d0b19988c92d48ab77b2fb8c4e 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/toolkit/test_archiver_util.py @@ -20,7 +20,7 @@ class TestArchiverUtil(BaseIntegrationTestCase): def setUp(self): super().setUp() self.config_dict = json.load(pkg_resources.resource_stream('tangostationcontrol.toolkit', f'archiver_config/lofar2_dev.json')) - + def test_get_attributes_from_suffix(self): """Test if attributes are correctly matched with the defined global suffixes""" device_name = 'STAT/RECV/1' @@ -31,7 +31,7 @@ class TestArchiverUtil(BaseIntegrationTestCase): recv_proxy.off() self.assertEqual(DevState.OFF, recv_proxy.state()) self.assertIn(attribute_name, get_attributes_from_suffix(device_name,dev_suffixes)) - + def test_retrieve_attributes_from_wildcards(self): """Test if attributes are correctly retrieved with wildcards matching""" device_name = 'STAT/SDP/1' diff --git a/tangostationcontrol/tangostationcontrol/integration_test/observations/test_archiver.py b/tangostationcontrol/tangostationcontrol/integration_test/observations/test_archiver.py index 85d2811fd9063a784fc722bb568d8b62dac26558..b5d8c93b4fc550d2e524f64a43a021e8e8818028 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/observations/test_archiver.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/observations/test_archiver.py @@ -17,14 +17,14 @@ class TestArchiver(BaseIntegrationTestCase): super().setUp() self.archiver = Archiver() self.assertIsNotNone(self.archiver) - + def test_archiver_initialisation(self): """Test archiver main attributes""" self.assertEqual(self.archiver.cm_name,"archiving/hdbppts/confmanager01") self.assertTrue(len(self.archiver.es_list)) # subscribers list not empty """Test if there is an available subscriber""" self.assertIsNotNone(self.archiver.get_next_subscriber()) - + def test_get_multimember_devices(self): """Test if multimember devices are correctly identified""" config_dict = self.archiver.get_configuration() diff --git a/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py b/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py index e6c77e3998fbcceacce5611b42c91988a55258c0..6c7aad92b3df90414633109bcd049162a6aec05e 100644 --- a/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py +++ b/tangostationcontrol/tangostationcontrol/integration_test/recv_cluster/test_recv_cluster.py @@ -48,7 +48,7 @@ class TestRecvCluster(base.IntegrationTestCase): proxy.warm_boot() proxy.set_defaults() self.assertTrue(proxy.state() is DevState.ON) - + for n in range(1, 5): proxy = antenna_field_proxies[n-1] # setup AntennaField diff --git a/tangostationcontrol/tangostationcontrol/statistics/reader.py b/tangostationcontrol/tangostationcontrol/statistics/reader.py index 1ab326db03bf8fdb1b773ce3471cb0ddbe287846..b0b1ff4e6f2b7f67a14f8045c589dc7815d55232 100644 --- a/tangostationcontrol/tangostationcontrol/statistics/reader.py +++ b/tangostationcontrol/tangostationcontrol/statistics/reader.py @@ -169,7 +169,7 @@ class statistics_data: # get all the general header info self.version_id = file[group_key].attrs["version_id"] self.station_id = file[group_key].attrs["station_id"] - + # get software version info self.station_version_id = file[group_key].attrs["station_version_id"] self.writer_version_id = file[group_key].attrs["writer_version_id"] diff --git a/tangostationcontrol/tangostationcontrol/statistics/udp_dev/udp_server.py b/tangostationcontrol/tangostationcontrol/statistics/udp_dev/udp_server.py index aab1365dfa661b0bef5ab280f1fe0f32ebbb493a..413633f34713ad24e6225fd086e98a9241970d12 100644 --- a/tangostationcontrol/tangostationcontrol/statistics/udp_dev/udp_server.py +++ b/tangostationcontrol/tangostationcontrol/statistics/udp_dev/udp_server.py @@ -22,7 +22,7 @@ class UDP_Server: print(f"\n\n####### Server is listening on {self.ip} - port {self.port} #######") while True: - + self.recv_data, self.recv_addr = s.recvfrom(self.buffer_size) print("\n\n 2. Server received at: ", datetime.now(), "\n\n") @@ -34,12 +34,12 @@ class UDP_Server: #time.sleep(10) #s.close() - + break # close the socket s.close() - + def get_recv_data(self): return self.recv_data diff --git a/tangostationcontrol/tangostationcontrol/statistics/writer/entry.py b/tangostationcontrol/tangostationcontrol/statistics/writer/entry.py index 0b3c60484c893d76918e0e926cd1a9c8114974d8..171db69eb0d5ff25c420a7c9bba3336d9268e50d 100644 --- a/tangostationcontrol/tangostationcontrol/statistics/writer/entry.py +++ b/tangostationcontrol/tangostationcontrol/statistics/writer/entry.py @@ -146,7 +146,7 @@ def _receive_packets(receiver, writer, reconnect, filename): def main(): - + parser = _create_parser() args = parser.parse_args() @@ -176,7 +176,7 @@ def main(): if debug: logger.setLevel(logging.DEBUG) logger.debug("Setting loglevel to DEBUG") - + # sets the Tango connection in order to retrieve attribute values if tango_disabled: logger.warning("Tango connection is DISABLED") diff --git a/tangostationcontrol/tangostationcontrol/statistics/writer/hdf5.py b/tangostationcontrol/tangostationcontrol/statistics/writer/hdf5.py index f1da6a4c5930599973b9f18ad17e8b6f2a28fc9f..4d84e39c90b574d29119192d345a9be45957d86f 100644 --- a/tangostationcontrol/tangostationcontrol/statistics/writer/hdf5.py +++ b/tangostationcontrol/tangostationcontrol/statistics/writer/hdf5.py @@ -245,7 +245,7 @@ class HDF5Writer(ABC): @abstractmethod def retrieve_attribute_values(self): pass - + @abstractmethod def write_values_matrix(self, current_group): pass @@ -330,7 +330,7 @@ class SstHdf5Writer(HDF5Writer): def new_collector(self): return StationSSTCollector(self.device) - + def retrieve_attribute_values(self): attribute_names = ["rcu_attenuator_dB", "rcu_band_select", "rcu_dth_on"] attribute_types = {"rcu_attenuator_dB": numpy.int64, "rcu_band_select" : numpy.int64, "rcu_dth_on" : bool} @@ -373,7 +373,7 @@ class BstHdf5Writer(HDF5Writer): def new_collector(self): return BSTCollector() - + def retrieve_attribute_values(self): pass @@ -416,7 +416,7 @@ class XstHdf5Writer(HDF5Writer): f"{self.file_location}/{self.mode}_SB{self.subband_index}_" f"{time_str}{suffix}" ) - + def retrieve_attribute_values(self): pass diff --git a/tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py b/tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py index 6381db2d7c4cc6e02cf891b761addacfe37064f1..218f34d73c85fe2eaf55ac68ae645bd329e8f114 100644 --- a/tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_attr_wrapper.py @@ -448,10 +448,10 @@ class TestAttributeTypes(base.TestCase): else: # if the test isn't scalar/spectrum or image its wrong self.assertEqual(1,2, " {} is not a valid test_type. please use either scalar, spectrum or image".format(test_type)) - + return result_R, result_RW, val - + def readback_test(self, dev, dtype, test_type): '''Test device''' try: diff --git a/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py index 055a01430bb31617967bbacafe97ec3ede81a809..a33226898d681520849609e85606b015583da488 100644 --- a/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py @@ -157,7 +157,7 @@ class TestOPCua(base.AsyncTestCase): def _get_test_value(self, dims, n_type): """ get numpy array of the test value """ return numpy.zeros(dims, n_type) - + def _wrap_dims(self, value, dims): """ Wrap a value in the current number of dimensions """ if dims == 0: @@ -166,11 +166,11 @@ class TestOPCua(base.AsyncTestCase): return [value] elif dims == 2: return [[value]] - + def _get_mock_value(self, value, n_type): """ get opcua Varianttype array of the test value """ return asyncua.ua.uatypes.Variant(Value=value, VariantType=opcua_client.numpy_to_OPCua_dict[n_type]) - + async def test_read(self): """ This tests the read functions. @@ -201,7 +201,7 @@ class TestOPCua(base.AsyncTestCase): """ async def get_unicode_value(dims): return self._wrap_dims(b'foo \xef\xbf\xbd bar'.decode('utf-8'), dims) - + # test 0-2 dimensions of strings for dims in range(0,2): @@ -219,14 +219,14 @@ class TestOPCua(base.AsyncTestCase): for numpy_type, opcua_type in opcua_client.numpy_to_OPCua_dict.items(): # derive a default value that can get lost in a type translation if numpy_type is str: - default_value = "foo" + default_value = "foo" elif numpy_type == bool: - default_value = True + default_value = True else: - # integer or float type - # integers: numpy will drop the decimals for us - # floats: make sure we chose a value that has an exact binary representation - default_value = 42.25 + # integer or float type + # integers: numpy will drop the decimals for us + # floats: make sure we chose a value that has an exact binary representation + default_value = 42.25 # apply our mapping v = asyncua.ua.uatypes.Variant(Value=numpy_type(default_value), VariantType=opcua_type) diff --git a/tangostationcontrol/tangostationcontrol/test/clients/test_snmp_client.py b/tangostationcontrol/tangostationcontrol/test/clients/test_snmp_client.py index e0ec059f440b0cbd79f9205f62ecc9c78ce582d1..8cc912c5f43a457f807769a3fa6d3c867b104e32 100644 --- a/tangostationcontrol/tangostationcontrol/test/clients/test_snmp_client.py +++ b/tangostationcontrol/tangostationcontrol/test/clients/test_snmp_client.py @@ -72,7 +72,7 @@ class server_imitator: read_val.append((None, snmp_type(1))) return read_val - + def val_check(self, snmp_type : type, dims : tuple): """ provides the values we expect and would provide to the attribute after converting the diff --git a/tangostationcontrol/tangostationcontrol/test/common/test_measures.py b/tangostationcontrol/tangostationcontrol/test/common/test_measures.py index bb22bedafafe5a62155000beb51b9e7ae05928bb..858290947d6eed755f0656ebfbc49ac84fba3a61 100644 --- a/tangostationcontrol/tangostationcontrol/test/common/test_measures.py +++ b/tangostationcontrol/tangostationcontrol/test/common/test_measures.py @@ -30,7 +30,7 @@ class TestMeasures(base.TestCase): with tempfile.TemporaryDirectory() as tmpdirname, \ mock.patch('tangostationcontrol.common.measures.IERS_ROOTDIR', tmpdirname) as rootdir, \ mock.patch('tangostationcontrol.common.measures.DOWNLOAD_DIR', tmpdirname) as downloaddir: - + # emulate the download m_urlretrieve.side_effect = lambda *args, **kw: shutil.copyfile(FAKE_MEASURES, tmpdirname + "/WSRT_Measures.ztar") @@ -51,7 +51,7 @@ class TestMeasures(base.TestCase): with tempfile.TemporaryDirectory() as tmpdirname, \ mock.patch('tangostationcontrol.common.measures.IERS_ROOTDIR', tmpdirname) as rootdir, \ mock.patch('tangostationcontrol.common.measures.DOWNLOAD_DIR', tmpdirname) as downloaddir: - + # 'download' two measures with different timestamps m_urlretrieve.side_effect = lambda *args, **kw: shutil.copyfile(FAKE_MEASURES, tmpdirname + "/WSRT_Measures.ztar") newdir1 = measures.download_measures() diff --git a/tangostationcontrol/tangostationcontrol/test/devices/random_data.py b/tangostationcontrol/tangostationcontrol/test/devices/random_data.py index 52f65ff2edceb86f44f3cd40784428aca6894b30..bafa9ca40b74753dd5c149ee8eaab601d9549d0b 100644 --- a/tangostationcontrol/tangostationcontrol/test/devices/random_data.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/random_data.py @@ -23,7 +23,7 @@ class Random_Data(Device): def read(self): return random.random() - + def read_array(self): return random.rand(self.DIM_ARRAY).astype(double) @@ -407,7 +407,7 @@ class Random_Data(Device): min_warning = 0.98, fget = read_array, ) - + # General methods def init_device(self): """ diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py index 23e08c71bb07db68319b8795d90cfcacc0846810..c614ea34a4a4c2fef8c75e3f719c88b8c59bc352 100644 --- a/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/test_antennafield_device.py @@ -33,7 +33,7 @@ class TestAntennaToRecvMapper(base.TestCase): # A mapping where first two Antennas are mapped on the first Receiver. # The first Antenna control line on RCU 1 and the second Antenna control line on RCU 0. CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1 = [[1, 1], [1, 0]] + [[-1, -1]] * 46 - + def test_ant_read_mask_r_no_mapping(self): mapper = AntennaToRecvMapper(self.CONTROL_NOT_CONNECTED, self.POWER_NOT_CONNECTED, 3) @@ -50,7 +50,7 @@ class TestAntennaToRecvMapper(base.TestCase): actual = mapper.map_read("ANT_mask_RW", receiver_values) numpy.testing.assert_equal(expected, actual) - + def test_rcu_band_select_no_mapping(self): mapper = AntennaToRecvMapper(self.CONTROL_NOT_CONNECTED, self.POWER_NOT_CONNECTED, 3) receiver_values = [[0] * 96, [0] * 96, [0] * 96] @@ -223,7 +223,7 @@ class TestAntennaToRecvMapper(base.TestCase): expected = [[False, True] + [None] * 94] actual = mapper.map_write("ANT_mask_RW", set_values) numpy.testing.assert_equal(expected, actual) - + def test_map_write_rcu_band_select_no_mapping_and_one_receiver(self): mapper = AntennaToRecvMapper(self.CONTROL_NOT_CONNECTED, self.POWER_NOT_CONNECTED, 1) @@ -231,7 +231,7 @@ class TestAntennaToRecvMapper(base.TestCase): expected = [[None] * 96] actual = mapper.map_write("RCU_band_select_RW", set_values) numpy.testing.assert_equal(expected, actual) - + def test_map_write_rcu_band_select_no_mapping_and_two_receivers(self): mapper = AntennaToRecvMapper(self.CONTROL_NOT_CONNECTED, self.POWER_NOT_CONNECTED, 2) @@ -239,7 +239,7 @@ class TestAntennaToRecvMapper(base.TestCase): expected = [[None] * 96] * 2 actual = mapper.map_write("RCU_band_select_RW", set_values) numpy.testing.assert_equal(expected, actual) - + def test_map_write_rcu_band_select_hba_0_and_1_on_rcu_1_and_0_of_recv_1(self): mapper = AntennaToRecvMapper(self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, self.POWER_NOT_CONNECTED, 1) @@ -406,19 +406,19 @@ class TestAntennafieldDevice(device_base.DeviceTestCase): at_properties_v2 = {'OPC_Server_Name': 'example.com', 'OPC_Server_Port': 4840, 'OPC_Time_Out': 5.0, 'Antenna_Field_Reference_ETRS' : [7.0, 7.0, 7.0]} with DeviceTestContext(antennafield.AntennaField, properties=at_properties_v2, process=True) as proxy: self.assertNotEqual(3.0, proxy.Antenna_Field_Reference_ITRF_R[0]) # value = 6.948998835785814 - + def test_read_Antenna_Quality(self): """ Verify if Antenna_Quality_R is correctly retrieved """ antenna_qualities = numpy.array([AntennaQuality.OK] * 96) with DeviceTestContext(antennafield.AntennaField, properties=self.AT_PROPERTIES, process=True) as proxy: numpy.testing.assert_equal(antenna_qualities, proxy.Antenna_Quality_R) - + def test_read_Antenna_Use(self): """ Verify if Antenna_Use_R is correctly retrieved """ antenna_use = numpy.array([AntennaUse.AUTO] * 96) with DeviceTestContext(antennafield.AntennaField, properties=self.AT_PROPERTIES, process=True) as proxy: numpy.testing.assert_equal(antenna_use, proxy.Antenna_Use_R) - + def test_read_Antenna_Usage_Mask(self): """ Verify if Antenna_Usage_Mask_R is correctly retrieved """ antenna_qualities = numpy.array([AntennaQuality.OK] * 96) @@ -434,14 +434,14 @@ class TestAntennafieldDevice(device_base.DeviceTestCase): antenna_properties = {'Antenna_Quality': antenna_qualities, 'Antenna_Use': antenna_use} with DeviceTestContext(antennafield.AntennaField, properties={**self.AT_PROPERTIES, **antenna_properties}, process=True) as proxy: numpy.testing.assert_equal(numpy.array([True] + [False] * 95), proxy.Antenna_Usage_Mask_R) - + def test_read_Antenna_Names(self): - """ Verify if Antenna_Names_R is correctly retrieved """ - antenna_names = ["C0","C1","C2","C3","C4"] - antenna_properties = {'Antenna_Names' : antenna_names} - with DeviceTestContext(antennafield.AntennaField, properties={**self.AT_PROPERTIES, **antenna_properties}, process=True) as proxy: - for i in range(len(antenna_names)): - self.assertTrue(proxy.Antenna_Names_R[i]==f"C{i}") + """ Verify if Antenna_Names_R is correctly retrieved """ + antenna_names = ["C0","C1","C2","C3","C4"] + antenna_properties = {'Antenna_Names' : antenna_names} + with DeviceTestContext(antennafield.AntennaField, properties={**self.AT_PROPERTIES, **antenna_properties}, process=True) as proxy: + for i in range(len(antenna_names)): + self.assertTrue(proxy.Antenna_Names_R[i]==f"C{i}") @unittest.skip("Test for manual use, enable at most one (process=false)") @mock.patch.object(antennafield, "DeviceProxy") diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py index 3c66e6176d127acd1120f7da2f7373f37d095651..a57a2846a18580e3752b175ee82a9a649d752c09 100644 --- a/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/test_lofar_device.py @@ -21,14 +21,14 @@ class TestLofarDevice(device_base.DeviceTestCase): def setUp(self): # DeviceTestCase setUp patches lofar_device DeviceProxy super(TestLofarDevice, self).setUp() - + def test_read_attribute(self): """ Test whether read_attribute really returns the attribute. """ class MyLofarDevice(lofar_device.lofar_device): @attribute(dtype=float) def A(self): - return 42.0 + return 42.0 @attribute(dtype=float) def read_attribute_A(self): @@ -36,7 +36,7 @@ class TestLofarDevice(device_base.DeviceTestCase): @attribute(dtype=(float,), max_dim_x=2) def B_array(self): - return [42.0, 43.0] + return [42.0, 43.0] @attribute(dtype=(float,), max_dim_x=2) def read_attribute_B_array(self): @@ -46,7 +46,7 @@ class TestLofarDevice(device_base.DeviceTestCase): proxy.initialise() self.assertEqual(42.0, proxy.read_attribute_A) self.assertListEqual([42.0, 43.0], proxy.read_attribute_B_array.tolist()) - + def test_disable_state(self): with DeviceTestContext(lofar_device.lofar_device, process=True, timeout=10) as proxy: proxy.initialise() @@ -55,7 +55,7 @@ class TestLofarDevice(device_base.DeviceTestCase): self.assertEqual(DevState.ON, proxy.state()) proxy.disable_hardware() self.assertEqual(DevState.DISABLE, proxy.state()) - + def test_disable_state_transitions(self): with DeviceTestContext(lofar_device.lofar_device, process=True, timeout=10) as proxy: proxy.off() diff --git a/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py b/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py index fe53bc69729aa809dcbddc9bec410a7bcde69330..a0f85653cd55aa2b6a60dd61c4b7194eea237f9c 100644 --- a/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py +++ b/tangostationcontrol/tangostationcontrol/test/devices/test_recv_device.py @@ -24,17 +24,17 @@ class TestRecvDevice(device_base.DeviceTestCase): def setUp(self): # DeviceTestCase setUp patches lofar_device DeviceProxy super(TestRecvDevice, self).setUp() - + def test_calculate_HBAT_bf_delay_steps(self): """Verify HBAT beamforming calculations are correctly executed""" with DeviceTestContext(recv.RECV, properties=self.RECV_PROPERTIES, process=True) as proxy: delays = numpy.random.rand(96,16).flatten() HBAT_bf_delay_steps = proxy.calculate_HBAT_bf_delay_steps(delays) self.assertEqual(3072, len(HBAT_bf_delay_steps)) # 96x32=3072 - + def test_get_rcu_band_from_filter(self): """Verify filter lookup table values are correctly retrieved""" with DeviceTestContext(recv.RECV, properties=self.RECV_PROPERTIES, process=True) as proxy: - filter_name = "HBA_170_230" - self.assertEqual(1, proxy.get_rcu_band_from_filter(filter_name)) - self.assertEqual(-1, proxy.get_rcu_band_from_filter('MOCK_FILTER')) + filter_name = "HBA_170_230" + self.assertEqual(1, proxy.get_rcu_band_from_filter(filter_name)) + self.assertEqual(-1, proxy.get_rcu_band_from_filter('MOCK_FILTER')) diff --git a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_config_file.py b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_config_file.py index 06a2bb67238a514cd6d82be1cd3bba8c3a3758eb..9dde30edebcf991fb335bf6643c071188f564acd 100644 --- a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_config_file.py +++ b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_config_file.py @@ -21,7 +21,7 @@ class TestArchiverConfigFile(base.TestCase): def test_separate_config_files(self): self.assertIsNotNone(self.dev_config_dict) self.assertIsNotNone(self.prod_config_dict) - + def test_get_global_variables(self): config_dicts = [self.dev_config_dict, self.prod_config_dict] for d in config_dicts: @@ -32,7 +32,7 @@ class TestArchiverConfigFile(base.TestCase): self.assertEqual(type(archive_period),int) self.assertEqual(type(event_period),int) self.assertEqual(type(strategy),str) - + def test_get_parameters_from_infixes_list(self): device_name = 'STAT/RECV/1' attribute_name = 'RCU_TEMP_R' @@ -41,7 +41,7 @@ class TestArchiverConfigFile(base.TestCase): self.assertEqual(event_period,1000) self.assertEqual(abs_change,0.5) self.assertEqual(rel_change,5.0) - + def test_get_parameters_from_suffixes_list(self): device_name = 'STAT/RECV/1' attribute_name = 'RECVTR_I2C_error_R' diff --git a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_configurator.py b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_configurator.py index aaf8a622faf044362c2ff13b931ecad30b8bd327..3b2227cc156ff2ee3f9eaad26af681c2bde2b5db 100644 --- a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_configurator.py +++ b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_configurator.py @@ -40,7 +40,7 @@ class TestArchiverConfigurator(base.TestCase): self.assertEqual(event_period,int(self.PROD_INFIXES[2]['event_period'])) self.assertEqual(abs_change,float(self.PROD_INFIXES[2]['abs_change'])) self.assertEqual(rel_change,self.PROD_INFIXES[2]['rel_change'] and int(self.PROD_INFIXES[2]['rel_change'])) - + def test_get_global_env_parameters(self): """Test if the include attribute list is correctly retrieved from the JSON config file""" self.assertIsNotNone(self.PROD_CONFIG_DICT) diff --git a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py index 1d2f92b754620969a63669ea27a0e075381efb88..2fbe8c69fc09decdbc4849efcd9b581f0483eb36 100644 --- a/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py +++ b/tangostationcontrol/tangostationcontrol/test/toolkit/test_archiver_util.py @@ -14,12 +14,12 @@ class TestArchiverUtil(base.TestCase): DEVICE_NAME = 'STAT/RECV/1' ATTRIBUTE_NAME = 'ant_mask_rw' - + def test_get_attribute_from_fqdn(self): """Test if a Tango attribute name is correctly retrieved from a Tango FQDN""" fqdn = f"tango://databaseds:10000/{self.DEVICE_NAME}/{self.ATTRIBUTE_NAME}" self.assertEqual('STAT/RECV/1/ant_mask_rw', get_attribute_from_fqdn(fqdn)) - + def test_device_fqdn(self): """Test if a device name is correctly converted in a Tango FQDN""" self.assertEqual(f"tango://databaseds:10000/{self.DEVICE_NAME}".lower(), device_fqdn(self.DEVICE_NAME, "databaseds:10000")) @@ -29,12 +29,12 @@ class TestArchiverUtil(base.TestCase): self.assertEqual(f"tango://databaseds:10000/{self.DEVICE_NAME}/{self.ATTRIBUTE_NAME}".lower(), attribute_fqdn(f"{self.DEVICE_NAME}/{self.ATTRIBUTE_NAME}", "databaseds:10000")) self.assertRaises(ValueError, lambda: attribute_fqdn(self.ATTRIBUTE_NAME)) - + def test_split_tango_name(self): """Test if the Tango full qualified domain names are correctly splitted""" self.assertEqual(('STAT','RECV','1'), split_tango_name(self.DEVICE_NAME, 'device')) self.assertEqual(('STAT','RECV','1', 'ant_mask_rw'), split_tango_name(f"{self.DEVICE_NAME}/{self.ATTRIBUTE_NAME}", 'attribute')) - + def test_get_size_from_datatype(self): """Test if the bytesize of a certain datatype is correctly retrieved""" datatype_boolean = 1 # 1 byte diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py index 4e40ebeab891fca63f20708348f456cc4dd6de5c..aaf013ce2df0f3f9f2d1e39bc949da4489acbd8c 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py @@ -13,7 +13,7 @@ import pkg_resources from functools import wraps logger = logging.getLogger() - + def warn_if_attribute_not_found(): """ Log a warning if an exception is thrown indicating access to an non-existing attribute @@ -72,7 +72,7 @@ class Archiver(): raise Exception(f"Connection failed with Configuration Manager {cm_name}") from e self.es_list = [es_name for es_name in self.get_subscribers(from_db=False)] self.cm.write_attribute('Context',context) # Set default Context Archiving for all the subscribers - + def get_hdbpp_libname(self, device_name:str): """ Get the hdbpp library name used by the Configuration Manager or by the EventSubscribers @@ -80,7 +80,7 @@ class Archiver(): """ config = get_db_config(device_name) return config["libname"] - + def get_subscribers(self, from_db:bool=False): """ Get the list of Event Subscribers managed by the Configuration Manager. @@ -92,7 +92,7 @@ class Archiver(): else: es_list = self.cm.ArchiverList or [] return es_list - + def get_next_subscriber(self): """ Return the first available Event Subscriber for archiving operations @@ -325,7 +325,7 @@ class Archiver(): """ attribute_name = attribute_fqdn(attribute_name) self.cm.AttributeStart(attribute_name) - + @warn_if_attribute_not_found() def stop_archiving_attribute(self, attribute_name:str): """ @@ -334,7 +334,7 @@ class Archiver(): """ attribute_name = attribute_fqdn(attribute_name) self.cm.AttributeStop(attribute_name) - + def is_attribute_archived(self, attribute_name:str): """ Check if an attribute is in the archiving list @@ -345,7 +345,7 @@ class Archiver(): # search returns all matches in which attribute_name is part of the name, # so check whether an exact match is included. return any(attribute_name == a for a in attributes) - + def update_archiving_attribute(self, attribute_name: str, polling_period: int, archive_period: int, strategy: str = 'RUN'): """ Update the archiving properties of an attribute already in a subscriber list @@ -357,7 +357,7 @@ class Archiver(): time.sleep(3.) self.start_archiving_attribute(attribute_name) logger.info(f"Attribute {attribute_name} successfully updated!") - + def get_subscriber_attributes(self, es_name:str = None): """ Return the list of attributes managed by the event subscribers @@ -371,7 +371,7 @@ class Archiver(): es = DeviceProxy(es_name) attrs.extend(list(es.AttributeList or [])) return attrs - + def get_subscriber_errors(self, es_name:str = None): """ Return a dictionary of the attributes currently in error, defined as AttributeName -> AttributeError @@ -385,7 +385,7 @@ class Archiver(): attrs.extend(list(es.AttributeList or [])) errs.extend(list(es.AttributeErrorList or [])) return {a: e for a,e in zip(attrs,errs) if e} - + def get_attribute_errors(self,attribute_name:str): """ Return the error related to the attribute @@ -396,7 +396,7 @@ class Archiver(): if attribute_name == e: return errs_dict[e] return None - + def get_subscriber_load(self,use_freq:bool=True, es_name:str = None): """ Return the estimated load of an archiver, in frequency of records or number @@ -416,7 +416,7 @@ class Archiver(): attribute_list = es.AttributeStartedList or [] pattern = re.compile(regex) return [a for a in attribute_list if pattern.search(a)] - + def get_attribute_subscriber(self, attribute_name:str): """ Given an attribute name, return the event subscriber associated with it @@ -435,7 +435,7 @@ class Archiver(): return self.get_next_subscriber() else: logger.warning(f"Attribute {attribute_name} not found!") - + def get_attribute_freq(self, attribute_name:str): """ Return the attribute archiving frequency in events/minute @@ -449,7 +449,7 @@ class Archiver(): return freq_dict[f] else: logger.warning(f"Attribute {attribute_name} not found!") - + def get_attribute_failures(self, attribute_name:str): """ Return the attribute failure archiving frequency in events/minute @@ -463,7 +463,7 @@ class Archiver(): return fail_dict[f] else: logger.warning(f"Attribute {attribute_name} not found!") - + def get_maximum_device_load(self, device_name:str): """ Compute maximum archiving load (bytes/second) based on device configuration """ load_list = [] diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py index 801ba8634209b73918b54e6f3fb716563cb73b1b..4ff60af76115cc3128d9efe955d89356d97ae8ae 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py @@ -235,7 +235,7 @@ class Attribute(Base): """ __tablename__ = 'att_conf' __table_args__ = {'extend_existing': True} - + att_conf_id = Column(Integer, primary_key=True) att_name = Column(String) att_conf_type_id = Column(Integer) @@ -247,20 +247,20 @@ class Attribute(Base): member = Column(String) name = Column(String) ttl = Column(Integer) - + def __repr__(self): return f"<Attribute(fullname='{self.att_name}',data_type ='{self.att_conf_type_id}',format='{self.att_conf_format_id}',table_name='{self.table_name}',cs_name ='{self.cs_name}',domain ='{self.domain}',family ='{self.family}',member ='{self.member}',name ='{self.name}'),ttl='{self.ttl}'>" - + class DataType(Base): """ Class that represents a Tango Data Type mapped to table 'att_conf_data_type' """ __tablename__ = 'att_conf_type' __table_args__ = {'extend_existing': True} - + att_conf_type_id = Column(Integer, primary_key=True) type = Column(String) - + def __repr__(self): return f"<DataType(type='{self.type}')>" @@ -868,7 +868,7 @@ def build_array_from_record(rows: List[Array], dim_x: int): result = numpy.transpose(matrix) #transpose -> each row is a distinct array of value list_result = result.tolist() return list_result - + def get_values_from_record(data_matrix: List[Array]): """ Returns a matrix of values from a matrix of Array records diff --git a/tangostationcontrol/tangostationcontrol/toolkit/retriever.py b/tangostationcontrol/tangostationcontrol/toolkit/retriever.py index c0364882ea635f715a0beabc3b91b96eecb017fc..bb1e2d4ef8a85820b0f327ac597e267defb1d718 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/retriever.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/retriever.py @@ -17,7 +17,7 @@ class Retriever(ABC): def __init__(self): self.session = self.connect_to_archiving_db() self.ab = self.set_archiver_base() - + def create_session(self, creds): """ Returns a session to a DBMS using the given credentials. @@ -33,11 +33,11 @@ class Retriever(ABC): engine = create_engine(connection_string) Session = sessionmaker(bind=engine) return Session - + @abstractmethod def set_archiver_base(self): return - + @abstractmethod def connect_to_archiving_db(self): return @@ -71,11 +71,11 @@ class Retriever(ABC): return result[0] except (TypeError, NoResultFound) as e: raise ValueError(f"Attribute {attribute_fqname} not found!") from e - + @abstractmethod def get_attribute_datatype(self,attribute_fqname: str): return - + def get_attribute_value_by_hours(self, attribute_fqname: str, hours: float, tablename:str): """ Takes as input the attribute fully-qualified name and the number of past hours since the actual time @@ -119,12 +119,12 @@ class Retriever(ABC): return result class RetrieverTimescale(Retriever): - + def __init__(self, cm_name: str = 'archiving/hdbppts/confmanager01'): self.cm_name = cm_name super().__init__() - + def connect_to_archiving_db(self): """ Returns a session to a TimescaleDB using default credentials. @@ -139,13 +139,13 @@ class RetrieverTimescale(Retriever): Session = self.create_session(creds) return Session() - + def set_archiver_base(self): """ Sets the right mapper class following the DBMS connection """ return importlib.import_module('.archiver_base_ts', package=__package__) - + def get_attribute_datatype(self,attribute_fqname: str): """ Takes as input the fully-qualified name of an attribute and returns its Data-Type. @@ -159,7 +159,7 @@ class RetrieverTimescale(Retriever): return result[0] except (AttributeError, TypeError, NoResultFound) as e: raise ValueError(f"Attribute {attribute_fqname} not found!") from e - + def get_attribute_format(self,attribute_fqname: str): """ Takes as input the fully-qualified name of an attribute and returns its format. @@ -173,7 +173,7 @@ class RetrieverTimescale(Retriever): return result[0] except (AttributeError, TypeError, NoResultFound) as e: raise ValueError(f"Attribute {attribute_fqname} not found!") from e - + def get_attribute_tablename(self,attribute_fqname: str): """ Takes as input the fully-qualified name of an attribute and returns the tablename where it is stored. @@ -186,7 +186,7 @@ class RetrieverTimescale(Retriever): return result[0] except (AttributeError, TypeError, NoResultFound) as e: raise ValueError(f"Attribute {attribute_fqname} not found!") from e - + def get_attribute_value_by_hours(self, attribute_fqname: str, hours: float = 1.0): """ Takes as input the attribute fully-qualified name and the number of past hours since the actual time @@ -195,7 +195,7 @@ class RetrieverTimescale(Retriever): """ tablename = self.get_attribute_tablename(attribute_fqname) return super().get_attribute_value_by_hours(attribute_fqname,hours,tablename) - + def get_attribute_value_by_interval(self,attribute_fqname: str, start_time: datetime, stop_time: datetime): """ Takes as input the attribute name and a certain starting and ending point-time. @@ -204,7 +204,7 @@ class RetrieverTimescale(Retriever): """ tablename = self.get_attribute_tablename(attribute_fqname) return super().get_attribute_value_by_interval(attribute_fqname,start_time,stop_time,tablename) - + def get_lofar_attribute(self,attribute_fqname: str): """ Takes as input the attribute fully-qualified name and queries the customized lofar attribute views