diff --git a/CDB/LOFAR_ConfigDb.json b/CDB/LOFAR_ConfigDb.json index 97de683bb7ebd6bc26b9e357812aaddd11b3d344..d5d1ad78ba3f14d3c64711f6e2b0d85a5b99e597 100644 --- a/CDB/LOFAR_ConfigDb.json +++ b/CDB/LOFAR_ConfigDb.json @@ -22,8 +22,7 @@ "STAT/Configuration/1", "STAT/ObservationControl/1", "STAT/TemperatureManager/1", - "STAT/Calibration/1", - "STAT/Boot/1" + "STAT/Calibration/1" ], "Control_Children": [ @@ -36,7 +35,6 @@ "STAT/TemperatureManager/1", "STAT/Calibration/1", "STAT/Configuration/1", - "STAT/Boot/1", "STAT/RECVL/1" ] } @@ -44,14 +42,6 @@ } } }, - "Boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - } - } - } - }, "CCD": { "STAT": { "CCD": { diff --git a/CDB/integrations/digitalbeam_cluster_ConfigDb.json b/CDB/integrations/digitalbeam_cluster_ConfigDb.json index cdb1eb1625cdc50adef0b08e6229f3c22930673c..c45565db5ac20015829900d2b6aa895c1b3a385e 100644 --- a/CDB/integrations/digitalbeam_cluster_ConfigDb.json +++ b/CDB/integrations/digitalbeam_cluster_ConfigDb.json @@ -419,12 +419,6 @@ "DigitalBeam": { "STAT/DigitalBeam/HBA0": { "properties": { - "AntennaField_Device": [ - "STAT/AntennaField/HBA0" - ], - "Beamlet_Device": [ - "STAT/Beamlet/HBA0" - ], "Beam_tracking_interval": [ "1.0" ], @@ -438,12 +432,6 @@ }, "STAT/DigitalBeam/HBA1": { "properties": { - "AntennaField_Device": [ - "STAT/AntennaField/HBA1" - ], - "Beamlet_Device": [ - "STAT/Beamlet/HBA1" - ], "Beam_tracking_interval": [ "1.0" ], @@ -457,12 +445,6 @@ }, "STAT/DigitalBeam/LBA": { "properties": { - "AntennaField_Device": [ - "STAT/AntennaField/LBA" - ], - "Beamlet_Device": [ - "STAT/Beamlet/LBA" - ], "Beam_tracking_interval": [ "1.0" ], @@ -488,7 +470,7 @@ ], "Control_Children": [ "STAT/SDPFirmware/LBA", - "STAT/digitalbeam/LBA", + "STAT/DigitalBeam/LBA", "STAT/RECVL/L0", "STAT/RECVL/L1" ], @@ -593,108 +575,108 @@ "3826989.173", "460890.761", "5064596.467", "3826990.269", "460895.632", "5064595.204" ], - "HBAT_PQR_rotation_angles_deg": [ - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24", - "24" - ], "PQR_to_ETRS_rotation_matrix": [ "-0.1195951054", "-0.7919544517", "0.5987530018", " 0.9928227484", "-0.0954186800", "0.0720990002", " 0.0000330969", " 0.6030782884", "0.7976820024" + ], + "Frequency_Band_RW_default": [ + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90", + "LBA_30_90", "LBA_30_90" ] } }, @@ -911,6 +893,104 @@ "-0.1195951054", "-0.7919544517", "0.5987530018", " 0.9928227484", "-0.0954186800", "0.0720990002", " 0.0000330969", " 0.6030782884", "0.7976820024" + ], + "Frequency_Band_RW_default": [ + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190" ] } }, @@ -1127,6 +1207,104 @@ "-0.1195951054", "-0.7919544517", "0.5987530018", " 0.9928227484", "-0.0954186800", "0.0720990002", " 0.0000330969", " 0.6030782884", "0.7976820024" + ], + "Frequency_Band_RW_default": [ + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190" ] } } diff --git a/CDB/stations/DTS.json b/CDB/stations/DTS.json index dc00315f489b8cfdd6b83c30e02aabc642568d45..e1fad56c4e9c09aec5ac325321fa75e2a03599c6 100644 --- a/CDB/stations/DTS.json +++ b/CDB/stations/DTS.json @@ -11,7 +11,6 @@ "STAT/Calibration/1", "STAT/ObservationControl/1", "STAT/TemperatureManager/1", - "STAT/Boot/1", "STAT/AntennaField/LBA", "STAT/AntennaField/HBA" ], @@ -24,7 +23,6 @@ "STAT/Calibration/1", "STAT/ObservationControl/1", "STAT/TemperatureManager/1", - "STAT/Boot/1", "STAT/AntennaField/LBA", "STAT/AntennaField/HBA", "STAT/APS/L0", @@ -70,50 +68,6 @@ } } }, - "boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - "Device_Names": [ - "STAT/Configuration/1", - "STAT/PSOC/1", - "STAT/PCON/1", - "STAT/APSPU/L0", - "STAT/APSCT/L0", - "STAT/RECVL/L0", - "STAT/UNB2/L0", - "STAT/APSPU/L1", - "STAT/APSCT/L1", - "STAT/RECVL/L1", - "STAT/UNB2/L1", - "STAT/APSPU/H0", - "STAT/APSCT/H0", - "STAT/RECVH/H0", - "STAT/UNB2/H0", - "STAT/CCD/1", - "STAT/SDP/HBA", - "STAT/BST/HBA", - "STAT/SST/HBA", - "STAT/XST/HBA", - "STAT/Beamlet/HBA", - "STAT/AntennaField/HBA", - "STAT/TileBeam/HBA", - "STAT/DigitalBeam/HBA", - "STAT/SDP/LBA", - "STAT/BST/LBA", - "STAT/SST/LBA", - "STAT/XST/LBA", - "STAT/Beamlet/LBA", - "STAT/AntennaField/LBA", - "STAT/DigitalBeam/LBA", - "STAT/TemperatureManager/1" - ] - } - } - } - } - }, "CCD": { "STAT": { "CCD": { diff --git a/CDB/stations/LTS_ConfigDb.json b/CDB/stations/LTS_ConfigDb.json index 65333660b47151ea7b6b86ea6c34937a7cc47799..fd98d77501860cc79646c43a009e71371925e248 100644 --- a/CDB/stations/LTS_ConfigDb.json +++ b/CDB/stations/LTS_ConfigDb.json @@ -16,19 +16,6 @@ } } }, - "boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - "Initialise_Hardware": [ - "True" - ] - } - } - } - } - }, "Beamlet": { "STAT": { "Beamlet": { diff --git a/CDB/stations/README.md b/CDB/stations/README.md index 7180538d09e73375c99e28723398bdbff5d313bf..1de4fa4d37d85d22dfd54769ceae042bdb73a0d7 100644 --- a/CDB/stations/README.md +++ b/CDB/stations/README.md @@ -21,7 +21,6 @@ These are the required changes that need to be made in order to support multiple ##### In the config file: - add all the new devices under the "STAT/DEVICE/2" name with the correct IP addresses, ports and other properties. This includes: APSCT, APSPU, RECV and UNB2. - - Put the new devices in the "Device_Names" list for the boot devices - Set the first 8 bools in "STAT/SDPFirmware/1" ... "TR_fpga_mask_RW_default" to True (instead of the first 4 with 1 subrack). This enables the new FPGA's ##### In the jupyter startup script diff --git a/CDB/stations/common.json b/CDB/stations/common.json index 45768cf244203c86e94ca786550ae669aaf30e96..652b10d7981d566a601f6f27a62e1e92aaff1b46 100644 --- a/CDB/stations/common.json +++ b/CDB/stations/common.json @@ -10,8 +10,7 @@ "STAT/Configuration/1", "STAT/Calibration/1", "STAT/ObservationControl/1", - "STAT/TemperatureManager/1", - "STAT/Boot/1" + "STAT/TemperatureManager/1" ], "Control_Children": [ "STAT/CCD/1", @@ -20,24 +19,13 @@ "STAT/Configuration/1", "STAT/Calibration/1", "STAT/ObservationControl/1", - "STAT/TemperatureManager/1", - "STAT/Boot/1" + "STAT/TemperatureManager/1" ] } } } } }, - "boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - } - } - } - } - }, "Calibration": { "STAT": { "Calibration": { @@ -196,16 +184,6 @@ } } } - }, - "Boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - } - } - } - } } } } diff --git a/CDB/stations/cs001.json b/CDB/stations/cs001.json index 36e7806652952e23883874399685b0b83d89d41a..f806983a1a2167184bc43436b5767d24dc2b49cb 100644 --- a/CDB/stations/cs001.json +++ b/CDB/stations/cs001.json @@ -8,7 +8,6 @@ "Power_Children": [ "STAT/EC/1", "STAT/TemperatureManager/1", - "STAT/Boot/1", "STAT/AntennaField/LBA", "STAT/AntennaField/HBA0", "STAT/AntennaField/HBA1", @@ -25,7 +24,6 @@ "STAT/Calibration/1", "STAT/ObservationControl/1", "STAT/TemperatureManager/1", - "STAT/Boot/1", "STAT/APS/L0", "STAT/APS/L1", "STAT/APS/H0", @@ -72,58 +70,6 @@ } } }, - "boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - "Device_Names": [ - "STAT/Configuration/1", - "STAT/PSOC/1", - "STAT/PCON/1", - "STAT/APSPU/L0", - "STAT/APSCT/L0", - "STAT/RECVL/L0", - "STAT/UNB2/L0", - "STAT/APSPU/L1", - "STAT/APSCT/L1", - "STAT/RECVL/L1", - "STAT/UNB2/L1", - "STAT/APSPU/H0", - "STAT/APSCT/H0", - "STAT/RECVH/H0", - "STAT/UNB2/H0", - "STAT/CCD/1", - "STAT/SDP/LBA", - "STAT/BST/LBA", - "STAT/SST/LBA", - "STAT/XST/LBA", - "STAT/Beamlet/LBA", - "STAT/AntennaField/LBA", - "STAT/DigitalBeam/LBA", - "STAT/SDP/HBA0", - "STAT/BST/HBA0", - "STAT/SST/HBA0", - "STAT/XST/HBA0", - "STAT/Beamlet/HBA0", - "STAT/AntennaField/HBA0", - "STAT/TileBeam/HBA0", - "STAT/DigitalBeam/HBA0", - "STAT/SDP/HBA1", - "STAT/BST/HBA1", - "STAT/SST/HBA1", - "STAT/XST/HBA1", - "STAT/Beamlet/HBA1", - "STAT/AntennaField/HBA1", - "STAT/TileBeam/HBA1", - "STAT/DigitalBeam/HBA1", - "STAT/TemperatureManager/1" - ] - } - } - } - } - }, "EC": { "STAT": { "EC": { diff --git a/CDB/stations/hba_core.json b/CDB/stations/hba_core.json index 051bf2968c5836827c4611d4258879f37052bb7e..1fff270bbc411d8390294c19fca9dceccb04df8d 100644 --- a/CDB/stations/hba_core.json +++ b/CDB/stations/hba_core.json @@ -169,6 +169,32 @@ "5", "5", "3", "13", "10", "3", "12", "2", "7", "15", "6", "14", "7", "5", "7", "9", "0", "15" + ], + "Frequency_Band_RW_default": [ + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190" ] } }, @@ -194,6 +220,32 @@ "5", "5", "3", "13", "10", "3", "12", "2", "7", "15", "6", "14", "7", "5", "7", "9", "0", "15" + ], + "Frequency_Band_RW_default": [ + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190" ] } } diff --git a/CDB/stations/hba_remote.json b/CDB/stations/hba_remote.json index 1c31f41f71a0863157e5a7327a8c69253f683060..e094e2b9112a94dda37885920fb88345df5825ea 100644 --- a/CDB/stations/hba_remote.json +++ b/CDB/stations/hba_remote.json @@ -110,6 +110,56 @@ "8", "2", "12", "13", "9", "13", "4", "5", "5", "12", "5", "5", "9", "11", "15", "12", "2", "15" + ], + "Frequency_Band_RW_default": [ + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190", + "HBA_110_190", "HBA_110_190" ] } } diff --git a/CDB/stations/lba.json b/CDB/stations/lba.json index f0b37aed72a7d535ef4587c38580b3565a23a283..5a689fff6622b8e78ef7821b8352316645cef966 100644 --- a/CDB/stations/lba.json +++ b/CDB/stations/lba.json @@ -89,6 +89,104 @@ ], "Antenna_Type": [ "LBA" + ], + "Frequency_Band_RW_default": [ + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90", + "LBA_10_90", "LBA_10_90" ] } } diff --git a/CDB/stations/simulators_ConfigDb.json b/CDB/stations/simulators_ConfigDb.json index e298e70aec6729b537cd7a2b6fcaa80f8b0dbe12..6ce4102b6ae394ebbd930f03138c1a4227dc1487 100644 --- a/CDB/stations/simulators_ConfigDb.json +++ b/CDB/stations/simulators_ConfigDb.json @@ -1,18 +1,5 @@ { "servers": { - "Boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - "Initialise_Hardware": [ - "False" - ] - } - } - } - } - }, "APSCT": { "STAT": { "APSCT": { diff --git a/CDB/stations/testenv_cs001.json b/CDB/stations/testenv_cs001.json index 6bf8d12a9634b50792f34d68180fe7bd6e038647..33bfdb2e053659e535755c5b64b78185ebfef18f 100644 --- a/CDB/stations/testenv_cs001.json +++ b/CDB/stations/testenv_cs001.json @@ -1,18 +1,5 @@ { "servers": { - "Boot": { - "STAT": { - "Boot": { - "STAT/Boot/1": { - "properties": { - "Initialise_Hardware": [ - "False" - ] - } - } - } - } - }, "APSCT": { "STAT": { "APSCT": { diff --git a/README.md b/README.md index 3e697d952c0f1a624b1243d87ecfa5163d7d6773..e1204001a65ecfdc0e62d244514f859c7db5cd9a 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ Next change the version in the following places: # Release Notes * 0.22.0 Migrate execution environment to nomad +* 0.21.2 Removed deprecated "Boot" device (use StationManager now) * 0.21.1 Implement multi project integration downstream pipeline * 0.21.0 Use radians instead of degrees when interpreting pointings * 0.20.5 Manage both polarisations in RCU_band_select_R(W), Antenna_Loss_R, and Frequency_Band_RW diff --git a/docker-compose/device-boot.yml b/docker-compose/device-boot.yml deleted file mode 100644 index 24fac88e7082f7bfa12071e3f319d1110394c312..0000000000000000000000000000000000000000 --- a/docker-compose/device-boot.yml +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2022 ASTRON (Netherlands Institute for Radio Astronomy) -# SPDX-License-Identifier: Apache-2.0 -# -# Docker compose file that launches a LOFAR2.0 station's -# ObservationControl device. It also runs the dynamically -# created Observation devices. -# -# Defines: -# - device-observation-control: LOFAR2.0 station ObvservationControl -# -# Requires: -# - lofar-device-base.yml -# -version: '2.1' - -services: - device-boot: - image: ${LOCAL_DOCKER_REGISTRY_HOST}/${LOCAL_DOCKER_REGISTRY_USER}/lofar-device-base:${TAG} - hostname: device-boot - container_name: device-boot - logging: - driver: "json-file" - options: - max-size: "100m" - max-file: "10" - networks: - - control - dns: ${DNS} - ports: - - "5708:5708" # unique port for this DS - - "5808:5808" # ZeroMQ event port - - "5908:5908" # ZeroMQ heartbeat port - extra_hosts: - - "host.docker.internal:host-gateway" - volumes: - - ..:/opt/lofar/tango:rw - environment: - - TANGO_HOST=${TANGO_HOST} - - TANGO_ZMQ_EVENT_PORT=5808 - - TANGO_ZMQ_HEARTBEAT_PORT=5908 - healthcheck: - test: l2ss-health dserver/BOOT/STAT - interval: 1m - timeout: 30s - retries: 3 - start_period: 30s - working_dir: /opt/lofar/tango - entrypoint: - - bin/start-ds.sh - # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA - # can't know about our Docker port forwarding - - l2ss-boot Boot STAT -v -ORBendPoint giop:tcp:0:5708 -ORBendPointPublish giop:tcp:${HOSTNAME}:5708 - restart: on-failure - stop_signal: SIGINT # request a graceful shutdown of Tango - stop_grace_period: 2s diff --git a/docker-compose/jupyter-lab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py b/docker-compose/jupyter-lab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py index 36179e8ceabf679aa860da7575a8d6b8e86efd07..c3a4210e1752e29983a4b2a0ccc8fa1b37b8a730 100644 --- a/docker-compose/jupyter-lab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py +++ b/docker-compose/jupyter-lab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py @@ -70,7 +70,6 @@ tilebeam_h1 = OptionalDeviceProxy("STAT/TileBeam/HBA1") antennafield_h1 = OptionalDeviceProxy("STAT/AntennaField/HBA1") stationmanager = OptionalDeviceProxy("STAT/StationManager/1") -boot = OptionalDeviceProxy("STAT/Boot/1") ccd = OptionalDeviceProxy("STAT/CCD/1") ec = OptionalDeviceProxy("STAT/EC/1") pcon = OptionalDeviceProxy("STAT/PCON/1") @@ -83,7 +82,6 @@ configuration = OptionalDeviceProxy("STAT/Configuration/1") devices = ( [ stationmanager, - boot, ccd, ec, pcon, diff --git a/docker-compose/object-storage.yml b/docker-compose/object-storage.yml index bf840d2d45daaedf79dcdec0bb0b130fc5aeafef..5d48af9acef8cbb6a480bf5536bb7da5548f8237 100644 --- a/docker-compose/object-storage.yml +++ b/docker-compose/object-storage.yml @@ -43,11 +43,13 @@ services: command: > sh -c "until [ \"$(curl -s -w '%{http_code}' -o /dev/null http://object-storage:9000/minio/health/live)\" -eq \"200\" ] do - sleep 1 - done + sleep 1 + done mc alias set object-storage http://object-storage:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD mc mb --with-versioning object-storage/caltables - mc cp --recursive /opt/lofar/tango/docker-compose/object-storage/caltables/ object-storage/caltables/" + mc cp --recursive /opt/lofar/tango/docker-compose/object-storage/caltables/ object-storage/caltables/ + date +'%F %T' + echo 'Initialisation completed'" volumes: object-storage: diff --git a/docker-compose/tango-prometheus-exporter/lofar2-fast-policy.json b/docker-compose/tango-prometheus-exporter/lofar2-fast-policy.json index ef26b8bd9d15492b7fd2add30d659f7408e42e4a..fe6010562b48d3ae6e78b70c46befe4a17c462d5 100644 --- a/docker-compose/tango-prometheus-exporter/lofar2-fast-policy.json +++ b/docker-compose/tango-prometheus-exporter/lofar2-fast-policy.json @@ -18,8 +18,6 @@ }, "stat/beamlet/*": { }, - "stat/boot/1": { - }, "stat/stationmanager/1": { }, "stat/digitalbeam/*": { diff --git a/docker-compose/tango-prometheus-exporter/lofar2-policy.json b/docker-compose/tango-prometheus-exporter/lofar2-policy.json index d6a867b7cf268556e73c0c0ac662fb73c6771df8..27a43c2757467e21dd052d454b120cb5bd5afca9 100644 --- a/docker-compose/tango-prometheus-exporter/lofar2-policy.json +++ b/docker-compose/tango-prometheus-exporter/lofar2-policy.json @@ -46,8 +46,6 @@ "FPGA_bf_weights_*" ] }, - "stat/boot/1": { - }, "stat/bst/*": { "exclude": [ "bst_R", diff --git a/docker-compose/tango-prometheus-exporter/lofar2-slow-policy.json b/docker-compose/tango-prometheus-exporter/lofar2-slow-policy.json index f05afaf8f253767f63bcd6c8154b64b0c51e1aaf..4e65340d110e507e33e84f9ed502cda994ed37a0 100644 --- a/docker-compose/tango-prometheus-exporter/lofar2-slow-policy.json +++ b/docker-compose/tango-prometheus-exporter/lofar2-slow-policy.json @@ -26,8 +26,6 @@ }, "stat/beamlet/*": { }, - "stat/boot/1": { - }, "stat/stationmanager/1": { }, "stat/digitalbeam/*": { diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh index 05019444099176022c707fbc56e88de950195793..e39c081533b1edaaaf45f3cbb4f712f243877452 100755 --- a/sbin/run_integration_test.sh +++ b/sbin/run_integration_test.sh @@ -164,7 +164,7 @@ cd "$LOFAR20_DIR/docker-compose" || exit 1 # Devices list is used to explitly word split when supplied to commands, must # disable shellcheck SC2086 for each case. -DEVICES=(device-station-manager device-boot device-aps device-apsct device-ccd device-ec device-apspu device-sdpfirmware device-sdp device-recvh device-recvl device-bst device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-psoc device-pcon device-antennafield device-temperature-manager device-observation-control device-configuration device-calibration) +DEVICES=(device-station-manager device-aps device-apsct device-ccd device-ec device-apspu device-sdpfirmware device-sdp device-recvh device-recvl device-bst device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-psoc device-pcon device-antennafield device-temperature-manager device-observation-control device-configuration device-calibration) SIMULATORS=(sdptr-sim recvh-sim recvl-sim unb2-sim apsct-sim apspu-sim ccd-sim ec-sim) diff --git a/tangostationcontrol/docs/source/devices/boot.rst b/tangostationcontrol/docs/source/devices/boot.rst deleted file mode 100644 index c5d351fc89a6d1c35aa9123d81d9ef0c55003ca5..0000000000000000000000000000000000000000 --- a/tangostationcontrol/docs/source/devices/boot.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. _boot: - -Boot -==================== - -The ``boot == DeviceProxy("STAT/Boot/1")`` device is responsible for (re)starting and initialising the other devices. Devices which are not reachable, for example because their docker container is explicitly stopped, are skipped during initialisation. It is the only device that starts in the ``ON`` state, so it can be used immediately to initialise other devices. - -This device provides the following commands: - -:boot(): Start the other devices in the correct order, if they are not ON. Set their default values, and command them to initialise their hardware. This procedure runs asynchronously, causing this command to return immediately. Use the attributes defined below to track the boot progress. - - :returns: ``None`` - -:warm_boot(): Like ``boot()``, but do not initialise the hardware. Just start our software devices. - - :returns: ``None`` - -:reboot(): Like ``boot()``, but turn off all other devices first. - - :returns: ``None`` - -The initialisation process can subsequently be followed through monitoring the following attributes: - -:booting_R: Whether the initialisation procedure is still ongoing. - - :type: ``bool`` - -:progress_R: Percentage completeness of the initialisation procedure. Each succesfully configured device increments progress. - - :type: ``int`` - -:status_R: A description of what the device is currently trying to do. If an error occurs, this will hint towards the cause. - - :type: ``str`` - -:initialised_devices_R: Which devices were initialised succesfully. - - :type: ``str[]`` - -:uninitialised_devices_R: Which devices have not yet been initialised, or failed to initialiase. - - :type: ``str[]`` - -A useful pattern is thus to call ``boot()``, wait for ``booting_R == False``, and then check whether the initalisation was succesful, if ``uninitialised_devices_R == []``. If a device fails to initialise, check its status (``<device>.status()``), or consult the :doc:`../interfaces/logs`. diff --git a/tangostationcontrol/docs/source/devices/overview.rst b/tangostationcontrol/docs/source/devices/overview.rst index c1db108117f629507f59dc9f4ebcdf57c46e6396..cdfced254406b66474750e67b0da0a30d48c3ea2 100644 --- a/tangostationcontrol/docs/source/devices/overview.rst +++ b/tangostationcontrol/docs/source/devices/overview.rst @@ -99,5 +99,4 @@ Auxilliary devices that control hardware are: Finally, the stack holds the auxilliary devices that control the software devices. They connect to too many devices to draw: * `Docker` device controls the Docker containers of the software stack, -* `Boot` device controls the proces for booting up the devices and initialising the hardware, * `TemperatureManager` device acts on temperature alarms originating from the hardware. diff --git a/tangostationcontrol/docs/source/devices/using.rst b/tangostationcontrol/docs/source/devices/using.rst index 9a95ab24e182ac3f3d0c4032d0a0053ec59914b9..c23f3e60ab34ebef04de4db9f3e5324ee6b9f69f 100644 --- a/tangostationcontrol/docs/source/devices/using.rst +++ b/tangostationcontrol/docs/source/devices/using.rst @@ -115,8 +115,6 @@ Most devices provide the following commands, in order to configure the hardware :on(): Mark the device as operational. Moves from ``STANDBY`` to ``ON``. -See also :ref:`boot`, which provides functionality to initialise all the devices. - .. _attributes: Attributes diff --git a/tangostationcontrol/docs/source/index.rst b/tangostationcontrol/docs/source/index.rst index 8fe720c9ff899d84cd9f035b5dce0259cdb4ed3d..261a62f2668e848c06e44303f1aeca0f2b9811a3 100644 --- a/tangostationcontrol/docs/source/index.rst +++ b/tangostationcontrol/docs/source/index.rst @@ -27,7 +27,6 @@ Even without having access to any LOFAR2.0 hardware, you can install the full st devices/sdpfirmware devices/sdp devices/bst-sst-xst - devices/boot devices/station-manager devices/docker devices/psoc diff --git a/tangostationcontrol/docs/source/installation.rst b/tangostationcontrol/docs/source/installation.rst index c30706928eda3b3fa99f3064eb5da6b92f0fa8af..f7f11a4ca192adcf1d074857912ba165257bcca9 100644 --- a/tangostationcontrol/docs/source/installation.rst +++ b/tangostationcontrol/docs/source/installation.rst @@ -40,29 +40,13 @@ After bootstrapping, and after a reboot, the software and hardware of the statio The following commands start all the software devices to control the station hardware, and initialise the hardware with the configured default settings. Go to http://localhost:8888, start a new *Station Control* notebook, and initiate the software boot sequence:: # start and initialise the other devices - boot.boot() - - # wait for the devices to be initialised - import time - - while boot.booting_R: - print(f"Still initialising station. {boot.progress_R}% complete. State: {boot.status_R}") - time.sleep(1) - - # print conclusion - if boot.progress_R == 100: - print("Done initialising station.") - else: - print(f"Failed to initialise station: {boot.status_R}") - - # print what did and did not get initialised - print(f"Initialised devices: {boot.initialised_devices_R}") - print(f"Uninitialised devices: {boot.uninitialised_devices_R}") - -See :ref:`boot` for more information on the ``boot`` device. + # go through the full startup sequence + # OFF -> HIBERNATE -> STANDBY -> ON + stationmanager.station_hibernate() + stationmanager.station_standby() + stationmanager.station_on() Configuration --------------------------- These sections are optional, to configure specific functionality you may or may not want to use. - diff --git a/tangostationcontrol/integration_test/default/devices/base_device_classes/test_power_hierarchy.py b/tangostationcontrol/integration_test/default/devices/base_device_classes/test_power_hierarchy.py index d311d8da88729e4ba335741dbf3f806f0ce9b182..b8330acf06c20d324a03dd773e514f22eebd510a 100644 --- a/tangostationcontrol/integration_test/default/devices/base_device_classes/test_power_hierarchy.py +++ b/tangostationcontrol/integration_test/default/devices/base_device_classes/test_power_hierarchy.py @@ -9,6 +9,7 @@ from integration_test import base from integration_test.device_proxy import TestDeviceProxy from tango import DevState, DeviceProxy +from tangostationcontrol.common.constants import N_rcu, N_rcu_inp from tangostationcontrol.common.case_insensitive_string import CaseInsensitiveString from tangostationcontrol.devices.base_device_classes.hierarchy_device import ( NotFoundException, @@ -160,7 +161,8 @@ class TestPowerHierarchyDevice(base.IntegrationTestCase): self.assertEqual(self.ccd_proxy.state(), DevState.ON) logger.info( - f"Exceptions suppressed in test_off_to_hibernate: {self.stationmanager_proxy.last_requested_transition_exceptions_R}" + "Exceptions suppressed in test_off_to_hibernate: %s", + self.stationmanager_proxy.last_requested_transition_exceptions_R, ) self.assertListEqual([], self._unacceptable_exceptions()) @@ -204,7 +206,8 @@ class TestPowerHierarchyDevice(base.IntegrationTestCase): ) logger.info( - f"Exceptions suppressed: {self.stationmanager_proxy.last_requested_transition_exceptions_R}" + "Exceptions suppressed: %s", + self.stationmanager_proxy.last_requested_transition_exceptions_R, ) self.assertListEqual([], self._unacceptable_exceptions()) @@ -227,8 +230,19 @@ class TestPowerHierarchyDevice(base.IntegrationTestCase): self.assertEqual(self.sdp_proxy.state(), DevState.ON) self.assertEqual(self.antennafield_proxy.state(), DevState.ON) + # Test if DTH and DAB are disabled + self.assertListEqual( + self.recvh_proxy.RCU_DTH_on_R.tolist(), + [[False] * N_rcu_inp] * N_rcu, + ) + self.assertListEqual( + self.antennafield_proxy.RCU_DAB_filter_on_RW.tolist(), + [False] * self.antennafield_proxy.nr_antennas_R, + ) + logger.info( - f"Exceptions suppressed: {self.stationmanager_proxy.last_requested_transition_exceptions_R}" + "Exceptions suppressed: %s", + self.stationmanager_proxy.last_requested_transition_exceptions_R, ) self.assertListEqual([], self._unacceptable_exceptions()) @@ -252,7 +266,8 @@ class TestPowerHierarchyDevice(base.IntegrationTestCase): self.assertEqual(self.antennafield_proxy.state(), DevState.OFF) logger.info( - f"Exceptions suppressed: {self.stationmanager_proxy.last_requested_transition_exceptions_R}" + "Exceptions suppressed: %s", + self.stationmanager_proxy.last_requested_transition_exceptions_R, ) self.assertListEqual([], self._unacceptable_exceptions()) @@ -281,7 +296,8 @@ class TestPowerHierarchyDevice(base.IntegrationTestCase): self.assertEqual(self.sdpfirmware_proxy.state(), DevState.OFF) logger.info( - f"Exceptions suppressed: {self.stationmanager_proxy.last_requested_transition_exceptions_R}" + "Exceptions suppressed: %s", + self.stationmanager_proxy.last_requested_transition_exceptions_R, ) self.assertListEqual([], self._unacceptable_exceptions()) diff --git a/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py b/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py index d79c50d30b744382aad905dcea75c4a2f41385ff..d7995d502e9212acf9bbe2f12b0c49eedc431932 100644 --- a/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py +++ b/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py @@ -27,13 +27,21 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): def setUp(self): self.stationmanager_proxy = self.setup_stationmanager_proxy() super().setUp("STAT/AntennaField/HBA0") + + # Typical tests emulate 'CS001_TILES' number of antennas in + # the AntennaField. 'MAX_ANTENNA' is the number of inputs + # offered by a backing RECV device. Each antenna has + # N_pol (2) inputs. self.proxy.put_property( { "Power_to_RECV_mapping": numpy.array( - [[1, x * 2 + 0] for x in range(MAX_ANTENNA // 2)] + [[1, x * 2 + 0] for x in range(CS001_TILES)] ).flatten(), "Control_to_RECV_mapping": numpy.array( - [[1, x * 2 + 1] for x in range(MAX_ANTENNA // 2)] + [[1, x * 2 + 1] for x in range(CS001_TILES)] + ).flatten(), + "Frequency_Band_RW_default": numpy.array( + [["HBA_110_190", "HBA_110_190"]] * CS001_TILES ).flatten(), } ) @@ -105,9 +113,9 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): numpy.array([[True] * N_rcu_inp] * N_rcu), self.recv_proxy.ANT_mask_RW ) - antenna_qualities = numpy.array([AntennaQuality.OK] * MAX_ANTENNA) + antenna_qualities = numpy.array([AntennaQuality.OK] * CS001_TILES) antenna_use = numpy.array( - [AntennaUse.ON] + [AntennaUse.AUTO] * (MAX_ANTENNA - 1) + [AntennaUse.ON] + [AntennaUse.AUTO] * (CS001_TILES - 1) ) antenna_properties = { "Antenna_Quality": antenna_qualities, @@ -127,7 +135,7 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): # Verify all antennas are indicated to work numpy.testing.assert_equal( - numpy.array([True] * MAX_ANTENNA), antennafield_proxy.Antenna_Usage_Mask_R + numpy.array([True] * CS001_TILES), antennafield_proxy.Antenna_Usage_Mask_R ) # Verify only connected inputs + Antenna_Usage_Mask_R are true @@ -154,9 +162,9 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): antenna_qualities = numpy.array( [AntennaQuality.BROKEN] + [AntennaQuality.OK] - + [AntennaQuality.BROKEN] * (MAX_ANTENNA - 2) + + [AntennaQuality.BROKEN] * (CS001_TILES - 2) ) - antenna_use = numpy.array([AntennaUse.AUTO] * MAX_ANTENNA) + antenna_use = numpy.array([AntennaUse.AUTO] * CS001_TILES) antenna_properties = { "Antenna_Quality": antenna_qualities, "Antenna_Use": antenna_use, @@ -167,7 +175,7 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): "Power_to_RECV_mapping": [-1, -1] * CS001_TILES, "Control_to_RECV_mapping": # [1, 0, 1, 1, 1, 2, 1, x ... 1, 95] - numpy.array([[1, x] for x in range(0, MAX_ANTENNA)]).flatten(), + numpy.array([[1, x] for x in range(CS001_TILES)]).flatten(), } # Cycle device and set properties @@ -179,18 +187,23 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): # Antenna_Usage_Mask_R should be false except one numpy.testing.assert_equal( - numpy.array([False] + [True] + [False] * (MAX_ANTENNA - 2)), + numpy.array([False] + [True] + [False] * (CS001_TILES - 2)), antennafield_proxy.Antenna_Usage_Mask_R, ) # device.power_hardware_on() writes Antenna_Usage_Mask_R to ANT_mask_RW numpy.testing.assert_equal( - numpy.array([False] + [True] + [False] * (MAX_ANTENNA - 2)), + numpy.array([False] + [True] + [False] * (CS001_TILES - 2)), antennafield_proxy.ANT_mask_RW, ) # ANT_mask_RW on antennafield writes to configured recv devices for all - # mapped inputs + # mapped inputs. Unmapped values at the end remain at True. numpy.testing.assert_equal( - numpy.array([False] + [True] + [False] * (MAX_ANTENNA - 2)), + numpy.array( + [False] + + [True] + + [False] * (CS001_TILES - 2) + + [True] * (MAX_ANTENNA - CS001_TILES) + ), self.recv_proxy.ANT_mask_RW.flatten(), ) @@ -272,7 +285,7 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): "Power_to_RECV_mapping": [-1, -1] * CS001_TILES, "Control_to_RECV_mapping": # [1, 0, 1, 1, 1, 2, 1, x ... 1, 95] - numpy.array([[1, x] for x in range(0, MAX_ANTENNA)]).flatten(), + numpy.array([[1, x] for x in range(CS001_TILES)]).flatten(), } antennafield_proxy = self.proxy @@ -286,11 +299,20 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): try: antennafield_proxy.write_attribute( - "HBAT_PWR_on_RW", [[True] * N_elements * N_pol] * MAX_ANTENNA + "HBAT_PWR_on_RW", [[True] * N_elements * N_pol] * CS001_TILES ) + + # Mapped values went to True numpy.testing.assert_equal( - numpy.array([[True] * N_elements * N_pol] * MAX_ANTENNA), - self.recv_proxy.read_attribute("HBAT_PWR_on_RW").value, + numpy.array([[True] * N_elements * N_pol] * CS001_TILES), + self.recv_proxy.read_attribute("HBAT_PWR_on_RW").value[:CS001_TILES], + ) + # Unmapped values went to False + numpy.testing.assert_equal( + numpy.array( + [[False] * N_elements * N_pol] * (MAX_ANTENNA - CS001_TILES) + ), + self.recv_proxy.read_attribute("HBAT_PWR_on_RW").value[CS001_TILES:], ) finally: # Always restore recv again @@ -306,10 +328,10 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): mapping_properties = { "Power_to_RECV_mapping": numpy.array( # X maps on power - [[1, x * 2 + 1] for x in range(MAX_ANTENNA // 2)] + [[1, x * 2 + 1] for x in range(CS001_TILES)] ).flatten(), "Control_to_RECV_mapping": numpy.array( # Y maps on control - [[1, x * 2 + 0] for x in range(MAX_ANTENNA // 2)] + [[1, x * 2 + 0] for x in range(CS001_TILES)] ).flatten(), } @@ -324,12 +346,24 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase): antennafield_proxy.write_attribute( # [X, Y] "RCU_band_select_RW", - [[1, 2]] * MAX_ANTENNA, + [[1, 2]] * CS001_TILES, + ) + + # Mapped values were overwritten + numpy.testing.assert_equal( + # [Power, Control] + numpy.array([2, 1] * CS001_TILES), + self.recv_proxy.read_attribute("RCU_band_select_RW").value.flatten()[ + : (CS001_TILES * 2) + ], ) + # Unmapped values remain at 0 numpy.testing.assert_equal( # [Power, Control] - numpy.array([2, 1] * (MAX_ANTENNA // 2)), - self.recv_proxy.read_attribute("RCU_band_select_RW").value.flatten(), + numpy.array([0] * (MAX_ANTENNA - CS001_TILES * 2)), + self.recv_proxy.read_attribute("RCU_band_select_RW").value.flatten()[ + (CS001_TILES * 2) : + ], ) finally: # Always restore recv again diff --git a/tangostationcontrol/integration_test/default/devices/test_device_boot.py b/tangostationcontrol/integration_test/default/devices/test_device_boot.py deleted file mode 100644 index dc91a137272b0729390c1d1d4cafb4b8db8513cc..0000000000000000000000000000000000000000 --- a/tangostationcontrol/integration_test/default/devices/test_device_boot.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (C) 2022 ASTRON (Netherlands Institute for Radio Astronomy) -# SPDX-License-Identifier: Apache-2.0 - -import time - -from integration_test import base -from integration_test.device_proxy import TestDeviceProxy - -from tango import DevState - -from tangostationcontrol.common.constants import DEFAULT_POLLING_PERIOD - - -CS001_DEVICES = [ - "STAT/Configuration/1", - "STAT/PSOC/1", - "STAT/PCON/1", - "STAT/APSPU/L0", - "STAT/APSCT/L0", - "STAT/RECVL/L0", - "STAT/UNB2/L0", - "STAT/APSPU/L1", - "STAT/APSCT/L1", - "STAT/RECVL/L1", - "STAT/UNB2/L1", - "STAT/APSPU/H0", - "STAT/APSCT/H0", - "STAT/RECVH/H0", - "STAT/UNB2/H0", - "STAT/CCD/1", - "STAT/SDP/LBA", - "STAT/BST/LBA", - "STAT/SST/LBA", - "STAT/XST/LBA", - "STAT/Beamlet/LBA", - "STAT/AntennaField/LBA", - "STAT/DigitalBeam/LBA", - "STAT/SDP/HBA0", - "STAT/BST/HBA0", - "STAT/SST/HBA0", - "STAT/XST/HBA0", - "STAT/Beamlet/HBA0", - "STAT/AntennaField/HBA0", - "STAT/TileBeam/HBA0", - "STAT/DigitalBeam/HBA0", - "STAT/SDP/HBA1", - "STAT/BST/HBA1", - "STAT/SST/HBA1", - "STAT/XST/HBA1", - "STAT/Beamlet/HBA1", - "STAT/AntennaField/HBA1", - "STAT/TileBeam/HBA1", - "STAT/DigitalBeam/HBA1", - "STAT/TemperatureManager/1", -] - - -class TestDeviceBoot(base.IntegrationTestCase): - def setUp(self): - self.proxy = TestDeviceProxy("STAT/Boot/1") - self.proxy.put_property({"Device_Names": CS001_DEVICES}) - - def test_start_in_on(self): - """Test whether we start in the ON state""" - - self.assertEqual(DevState.ON, self.proxy.state()) - - def test_reboot(self): - """Test if we can reinitialise the station""" - - # This attribute needs to be polled for the - # TemperatureManager test to succesfully initialise - TestDeviceProxy("STAT/RECVH/H0").poll_attribute( - "HBAT_LED_on_RW", DEFAULT_POLLING_PERIOD - ) - - self.proxy.reboot() - - # wait for a few seconds for the station to initialise - timeout = 10 - while self.proxy.booting_R and timeout: - time.sleep(1) - - # check whether initialisation succeeded - self.assertEqual( - 100, - self.proxy.progress_R, - msg=f"Initialisation of station failed. Status: {self.proxy.status_R}", - ) diff --git a/tangostationcontrol/integration_test/default/devices/test_device_calibration.py b/tangostationcontrol/integration_test/default/devices/test_device_calibration.py index 12fd195830600f310d03562cf0420831cd8acc84..3d9329525be4078999fd0d03f89f0b539b09d890 100644 --- a/tangostationcontrol/integration_test/default/devices/test_device_calibration.py +++ b/tangostationcontrol/integration_test/default/devices/test_device_calibration.py @@ -70,21 +70,30 @@ class TestCalibrationDevice(AbstractTestBases.TestDeviceBase): def setUp(self): self.stationmanager_proxy = self.setup_stationmanager_proxy() super().setUp("STAT/Calibration/1") + + self.recv_proxy = self.setup_recv_proxy() + self.sdpfirmware_proxy = self.setup_sdpfirmware_proxy() + self.sdp_proxy = self.setup_sdp_proxy() + self.antennafield_proxy = self.setup_proxy("STAT/AntennaField/HBA0") + + # make sure we restore any properties we modify + self.original_antennafield_properties = self.antennafield_proxy.get_property( + self.antennafield_proxy.get_property_list("*") + ) + self.addCleanup(self.restore_antennafield) + self.antennafield_proxy.put_property( { "Power_to_RECV_mapping": [1, 1, 1, 0] + [-1] * ((DEFAULT_N_HBA_TILES * 2) - 4), "Antenna_Sets": ["ALL"], "Antenna_Set_Masks": ["1" * DEFAULT_N_HBA_TILES], + "Frequency_Band_RW_default": ["HBA_110_190"] + * (DEFAULT_N_HBA_TILES * 2), } ) - self.recv_proxy = self.setup_recv_proxy() - self.sdpfirmware_proxy = self.setup_sdpfirmware_proxy() - self.sdp_proxy = self.setup_sdp_proxy() - - self.addCleanup(self.shutdown_recv) - self.addCleanup(self.shutdown_sdp) + self.antennafield_proxy.boot() # configure the frequencies, which allows access # to the calibration attributes and commands @@ -92,22 +101,7 @@ class TestCalibrationDevice(AbstractTestBases.TestDeviceBase): self.recv_proxy.RCU_band_select_RW = [[1] * N_rcu_inp] * N_rcu def restore_antennafield(self): - self.proxy.put_property( - { - "Power_to_RECV_mapping": [-1, -1] * DEFAULT_N_HBA_TILES, - "Control_to_RECV_mapping": [-1, -1] * DEFAULT_N_HBA_TILES, - } - ) - - @staticmethod - def shutdown_recv(): - recv_proxy = TestDeviceProxy("STAT/RECVH/H0") - recv_proxy.off() - - @staticmethod - def shutdown_sdp(): - sdp_proxy = TestDeviceProxy("STAT/SDP/HBA0") - sdp_proxy.off() + self.proxy.put_property(self.original_antennafield_properties) @staticmethod def shutdown(device: str): @@ -119,45 +113,38 @@ class TestCalibrationDevice(AbstractTestBases.TestDeviceBase): def setup_recv_proxy(self): # setup RECV - recv_proxy = TestDeviceProxy("STAT/RECVH/H0") - recv_proxy.off() + recv_proxy = self.setup_proxy("STAT/RECVH/H0") recv_proxy.boot() - recv_proxy.set_defaults() return recv_proxy def setup_sdpfirmware_proxy(self): # setup SDP - sdpfirmware_proxy = TestDeviceProxy("STAT/SDPFirmware/HBA0") - sdpfirmware_proxy.off() + sdpfirmware_proxy = self.setup_proxy("STAT/SDPFirmware/HBA0") sdpfirmware_proxy.boot() return sdpfirmware_proxy def setup_sdp_proxy(self): # setup SDP - sdp_proxy = TestDeviceProxy("STAT/SDP/HBA0") - sdp_proxy.off() + sdp_proxy = self.setup_proxy("STAT/SDP/HBA0") sdp_proxy.boot() return sdp_proxy def setup_proxy(self, dev: str): - # setup SDP proxy = TestDeviceProxy(dev) proxy.off() - proxy.boot() self.addCleanup(self.shutdown(dev)) return proxy def setup_stationmanager_proxy(self): """Setup StationManager""" - stationmanager_proxy = TestDeviceProxy("STAT/StationManager/1") - stationmanager_proxy.off() + stationmanager_proxy = self.setup_proxy("STAT/StationManager/1") stationmanager_proxy.boot() self.assertEqual(stationmanager_proxy.state(), DevState.ON) return stationmanager_proxy def test_calibrate_recv(self): calibration_properties = { - "Antenna_Type": ["LBA"], + "Antenna_Type": ["HBA"], "Antenna_Cables": ["50m", "80m"] * (DEFAULT_N_HBA_TILES // 2), "Control_to_RECV_mapping": # [1, 0, 1, 1, 1, 2, 1, x ... 1, 47] @@ -168,15 +155,14 @@ class TestCalibrationDevice(AbstractTestBases.TestDeviceBase): # [1, 48, 1, 49, x ... 1, 95] } - self.antennafield_proxy = self.setup_proxy("STAT/AntennaField/HBA0") - self.antennafield_proxy.off() + self.antennafield_proxy = self.setup_proxy("STAT/AntennaField/LBA") self.antennafield_proxy.put_property(calibration_properties) self.antennafield_proxy.boot() self.proxy.boot() # calibrate - self.proxy.calibrate_recv("STAT/AntennaField/HBA0") + self.proxy.calibrate_recv("STAT/AntennaField/LBA") # check the results rcu_attenuator_db_pwr = self.antennafield_proxy.RCU_attenuator_dB_RW[:, 0] @@ -230,7 +216,6 @@ class TestCalibrationDevice(AbstractTestBases.TestDeviceBase): } self.antennafield_proxy = self.setup_proxy("STAT/AntennaField/HBA0") - self.antennafield_proxy.off() self.antennafield_proxy.put_property(calibration_properties) self.antennafield_proxy.boot() diff --git a/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py b/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py index 9ecbe0382a39417cb1478891cc44af899464d387..9c996a70636f1b1ef5fe189e2e659610056b3fdb 100644 --- a/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py +++ b/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py @@ -105,6 +105,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase): "1" + ("0" * (NR_TILES - 1)), "1" * NR_TILES, ], + "Antenna_Type": "HBA", } ) antennafield_proxy.off() diff --git a/tangostationcontrol/integration_test/digitalbeam_performance/test_digitalbeam_performance.py b/tangostationcontrol/integration_test/digitalbeam_performance/test_digitalbeam_performance.py index 4ed1e4e4aa2cd2fc6854b11724c73a7d647daab8..8034af77013f7bb936bf75813a32baa9d6974416 100644 --- a/tangostationcontrol/integration_test/digitalbeam_performance/test_digitalbeam_performance.py +++ b/tangostationcontrol/integration_test/digitalbeam_performance/test_digitalbeam_performance.py @@ -54,19 +54,21 @@ class TestDigitalbeamPerformance(base.IntegrationTestCase): proxy.off() self.assertTrue(proxy.state() is DevState.OFF) proxy.boot() - proxy.set_defaults() self.assertTrue(proxy.state() is DevState.ON) - for n in range(1, 3): - proxy = antenna_field_proxies[n - 1] + for proxy in antenna_field_proxies: # setup AntennaField control_mapping = [[1, i] for i in range(MAX_ANTENNA)] + power_mapping = [[1, i] for i in range(MAX_ANTENNA)] + sdp_mapping = [[i // 6, i % 6] for i in range(MAX_ANTENNA)] antenna_qualities = numpy.array([AntennaQuality.OK] * MAX_ANTENNA) antenna_use = numpy.array([AntennaUse.AUTO] * MAX_ANTENNA) antenna_set_mask = "1" * MAX_ANTENNA proxy.put_property( { "Control_to_RECV_mapping": numpy.array(control_mapping).flatten(), + "Power_to_RECV_mapping": numpy.array(power_mapping).flatten(), + "Antenna_to_SDP_Mapping": numpy.array(sdp_mapping).flatten(), "Antenna_Quality": antenna_qualities, "Antenna_Use": antenna_use, "Antenna_Sets": ["ALL"], @@ -82,9 +84,9 @@ class TestDigitalbeamPerformance(base.IntegrationTestCase): proxy.off() self.assertTrue(proxy.state() is DevState.OFF) proxy.boot() - proxy.set_defaults() proxy.Tracking_enabled_RW = tracking self.assertTrue(proxy.state() is DevState.ON) + self.assertEqual(MAX_ANTENNA, proxy.nr_antennas_R) # Insert verify that all attributes have been set across # one another~ diff --git a/tangostationcontrol/tangostationcontrol/common/calibration.py b/tangostationcontrol/tangostationcontrol/common/calibration.py index 9cd7d6e8f332ebfce204fa7507004729ff4bd8b0..d484c1d8762337e54e1746de4f21a63aee2d4151 100644 --- a/tangostationcontrol/tangostationcontrol/common/calibration.py +++ b/tangostationcontrol/tangostationcontrol/common/calibration.py @@ -53,7 +53,7 @@ class CalibrationManager: self._url = url self._station_name = station_name self._tmp_dir = tempfile.TemporaryDirectory(ignore_cleanup_errors=True) - self.bucket_name = "caltabules" + self.bucket_name = "caltables" self.prefix = self._station_name self._init_minio() self.sync_calibration_tables() @@ -66,6 +66,8 @@ class CalibrationManager: if len(bucket_name) > 0: self.bucket_name = bucket_name + logger.info(f"Derived {self.prefix=} {self.bucket_name=} from {self._url=}") + self._storage = Minio( result.netloc, access_key=os.getenv("MINIO_ROOT_USER"), @@ -82,11 +84,18 @@ class CalibrationManager: objects = self._storage.list_objects(self.bucket_name, prefix=f"{self.prefix}/") for obj in objects: filename = os.path.basename(obj.object_name) - self._storage.fget_object( - self.bucket_name, - obj.object_name, - os.path.join(self._tmp_dir.name, filename), - ) + try: + self._storage.fget_object( + self.bucket_name, + obj.object_name, + os.path.join(self._tmp_dir.name, filename), + ) + except Exception as ex: + raise IOError( + f"Failed to download {self.bucket=} {obj.object_name=}" + ) from ex + + logger.info(f"Downloaded {filename} from {obj.object_name}") @staticmethod def _band_to_reference_frequency(is_hba, rcu_band): diff --git a/tangostationcontrol/tangostationcontrol/devices/antennafield.py b/tangostationcontrol/tangostationcontrol/devices/antennafield.py index 4c1cb078051576c7de02b1ea0b8e32e37ae17d51..37309355de3390a6791d60d060b5df5ec0dd93e3 100644 --- a/tangostationcontrol/tangostationcontrol/devices/antennafield.py +++ b/tangostationcontrol/tangostationcontrol/devices/antennafield.py @@ -355,6 +355,13 @@ class AntennaField(LOFARDevice): default_value=[-1] * MAX_ANTENNA * 2, ) + # ----- Defaults + + Frequency_Band_RW_default = device_property( + dtype=(str,), + mandatory=False, + ) + # ----- Generic information Antenna_Type_R = attribute( @@ -1004,6 +1011,7 @@ class AntennaField(LOFARDevice): recv_mapping, self.get_mapped_dimensions("RECV"), number_of_receivers, + antenna_type=self.read_attribute("Antenna_Type_R"), ) def __setup_sdp_mapper(self): @@ -1075,6 +1083,12 @@ class AntennaField(LOFARDevice): # Configure the devices that process our antennas self.configure_recv() self.configure_sdp() + # Disable DAB filters for HBAs + if self.Antenna_Type == "HBA": + self.proxy.write_attribute( + "RCU_DAB_filter_on_RW", + [False] * self.read_nr_antennas_R(), + ) def _power_hardware_off(self): # Save actual mask values diff --git a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py index 116cd4299e287d4122999282f8f2977fe85a732a..61ac4db5663ea7873948faa97404fe665e250dff 100644 --- a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/lofar_device.py @@ -469,6 +469,13 @@ class LOFARDevice(Device): try: default_value = getattr(self, f"{name}_default") + if default_value is None: + # Attribute allows a default setting, but none + # is configured (f.e. because mandatory=False + # and no useful default exists that can be + # provided in the code). Just skip this attribute. + continue + # properties are always 0D or 1D, but arrays can be 2D. # in the latter case, we need to reshape the default. attr = getattr(self, name) @@ -476,9 +483,12 @@ class LOFARDevice(Device): if max_dim_y > 1: # 2D array -> reshape 1D default - default_value = numpy.array(default_value).reshape( - max_dim_y, max_dim_x - ) + # This is needed because Tango properties cannot be 2D, so we + # cannot specify them in their actual shape. + # + # We assume the length of the y dimension to be variable, + # as some attributes (and thus defaults) have a varying size. + default_value = numpy.array(default_value).reshape(-1, max_dim_x) # set the attribute to the configured default. Shorten after 150 characters logger.debug( diff --git a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/mapper.py b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/mapper.py index 1af7d34c06f5a59725d1a04a483a0e542902e04d..9e3bd89d0431a118416866d2ca014c4284008469 100644 --- a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/mapper.py +++ b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/mapper.py @@ -55,7 +55,7 @@ class MappedAttribute(attribute): cast_type = dtype while not type_not_sequence(cast_type): cast_type = cast_type[0] - write_func = device.set_mapped_attribute( + _write_func = device.set_mapped_attribute( mapping_attribute, value, cast_type, mapping_device ) @@ -84,6 +84,7 @@ class AntennaMapper: self, mapping_dict: Dict[str, numpy.ndarray], num_devices: Optional[int] = 1, + antenna_type: str = "HBA", ) -> None: self._mapping_dict = mapping_dict self._num_devices = num_devices @@ -94,6 +95,8 @@ class AntennaMapper: self._reshape_attributes_out = {} self._fill_attributes_in = {} self._empty_attributes_out = {} + self._antenna_type = antenna_type + self._pwr_mapping = [] def map_read(self, mapped_attribute: str, device_values: List[any]) -> List[any]: """Perform a mapped read for the attribute using the device_results @@ -119,7 +122,11 @@ class AntennaMapper: ) return self._mapped_r_values( - device_values, default_values, self._value_mapper[mapped_attribute] + device_values, + default_values, + self._value_mapper[mapped_attribute], + self._antenna_type, + mapped_attribute in self._pwr_mapping, ) def map_write(self, mapped_attribute: str, set_values: List[any]) -> List[any]: @@ -133,7 +140,11 @@ class AntennaMapper: default_values = self._masked_value_mapping_write[mapped_attribute] mapped_values = self._mapped_rw_values( - set_values, default_values, self._value_mapper[mapped_attribute] + set_values, + default_values, + self._value_mapper[mapped_attribute], + self._antenna_type, + mapped_attribute in self._pwr_mapping, ) # Attributes which need to be reshaped with removing a part of their duplicated @@ -160,6 +171,8 @@ class AntennaMapper: device_values: List[any], default_values: List[any], value_mapping: List[any], + antenna_type: str, + pwr_attribute: bool, ): """Mapping for read operation""" mapped_values = numpy.array(default_values) @@ -189,15 +202,24 @@ class AntennaMapper: (dev_power, dev_input_power), (dev_control, dev_input_control), ) in enumerate(zip(power_mapping, control_mapping)): - # Insert the two values in the mapped array - if dev_power > 0: - mapped_values[idx][0] = device_values[dev_power - 1][ - dev_input_power - ] - if dev_control > 0: - mapped_values[idx][1] = device_values[dev_control - 1][ - dev_input_control - ] + if antenna_type == "LBA" and pwr_attribute: + # We should report the value of both mappings for each antenna (2 values), + # but for now we pick only one to keep the resulting array of similar + # dimension compared to HBA + if dev_power > 0 and dev_control > 0: + mapped_values[idx] = device_values[dev_power - 1][ + dev_input_power + ] + else: + # Insert the two values in the mapped array + if dev_power > 0: + mapped_values[idx][0] = device_values[dev_power - 1][ + dev_input_power + ] + if dev_control > 0: + mapped_values[idx][1] = device_values[dev_control - 1][ + dev_input_control + ] return mapped_values @@ -206,6 +228,8 @@ class AntennaMapper: set_values: List[any], default_values: List[any], value_mapping: List[any], + antenna_type: str, + pwr_attribute: bool, ): if MappingKeys.CONTROL in list(self._mapping_dict.keys()): mapped_values = [] @@ -234,13 +258,18 @@ class AntennaMapper: (dev_power, dev_input_power), (dev_control, dev_input_control), ) in enumerate(zip(power_mapping, control_mapping)): - if dev_power > 0: - mapped_values[dev_power - 1, dev_input_power] = set_values[idx][0] - if dev_control > 0: - mapped_values[dev_control - 1, dev_input_control] = set_values[idx][ - 1 - ] - + if antenna_type == "LBA" and pwr_attribute: + if dev_power > 0 and dev_control > 0: + mapped_values[dev_power] = set_values[idx] + else: + if dev_power > 0: + mapped_values[dev_power - 1, dev_input_power] = set_values[idx][ + 0 + ] + if dev_control > 0: + mapped_values[dev_control - 1, dev_input_control] = set_values[ + idx + ][1] return mapped_values def _init_reshape_out(self, mapped_attributes: List[str], device_type: str): @@ -296,8 +325,10 @@ class AntennaToRecvMapper(AntennaMapper): _VALUE_MAP_NONE_96_32 = numpy.full((MAX_ANTENNA, N_elements * N_pol), None) _VALUE_MAP_NONE_96_2 = numpy.full((MAX_ANTENNA, 2), None) - def __init__(self, mapping_dict, mapped_dimensions, number_of_receivers): - super().__init__(mapping_dict, number_of_receivers) + def __init__( + self, mapping_dict, mapped_dimensions, number_of_receivers, antenna_type + ): + super().__init__(mapping_dict, number_of_receivers, antenna_type) self._power_mapping = self._mapping_dict[MappingKeys.POWER] self._control_mapping = self._mapping_dict[MappingKeys.CONTROL] @@ -315,7 +346,7 @@ class AntennaToRecvMapper(AntennaMapper): self._mapped_attributes = list(mapped_dimensions) - self._value_mapper = self._init_value_mapper() + self._value_mapper = self._init_value_mapper(antenna_type) self._default_value_mapping_read = { "ANT_mask_RW": value_map_ant_bool, @@ -402,10 +433,10 @@ class AntennaToRecvMapper(AntennaMapper): masked_write[attr] = AntennaToRecvMapper._VALUE_MAP_NONE_96_32 return masked_write - def _init_value_mapper(self): + def _init_value_mapper(self, antenna_type: str): """Create the value mapping dictionary""" value_mapper = {} - double_mapping = [ + self._double_mapping = [ "RCU_attenuator_dB_R", "RCU_attenuator_dB_RW", "RCU_band_select_R", @@ -413,12 +444,15 @@ class AntennaToRecvMapper(AntennaMapper): "RCU_PCB_ID_R", "RCU_PCB_version_R", ] - pwr_mapping = ["RCU_PWR_ANT_on_R", "RCU_PWR_ANT_on_RW"] + self._pwr_mapping = ["RCU_PWR_ANT_on_R", "RCU_PWR_ANT_on_RW"] for attr in self._mapped_attributes: - if attr in double_mapping: + if attr in self._double_mapping: value_mapper[attr] = [self._power_mapping, self._control_mapping] - elif attr in pwr_mapping: - value_mapper[attr] = [self._power_mapping] + elif attr in self._pwr_mapping: + if antenna_type == "LBA": + value_mapper[attr] = [self._power_mapping, self._control_mapping] + elif antenna_type == "HBA": + value_mapper[attr] = [self._power_mapping] else: value_mapper[attr] = [self._control_mapping] return value_mapper @@ -435,7 +469,8 @@ class RecvDeviceWalker(object): self.antenna_usage_mask = antenna_usage_mask def recv_ant_masks(self) -> numpy.ndarray: - """Return the antenna mask for the control inputs of the antennas enabled in Antenna_Usage_Mask_R.""" + """Return the antenna mask for the control inputs of the antennas enabled + in Antenna_Usage_Mask_R.""" nr_recv_devices = max(self.control_to_recv_mapping[:, 0]) diff --git a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/recv_device.py b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/recv_device.py index 1b8a8c5cb60e14ac50f9a7566870861e0b2119ad..b8e6ad462ad19ce2db7af798bf0af2fa682b317e 100644 --- a/tangostationcontrol/tangostationcontrol/devices/base_device_classes/recv_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/base_device_classes/recv_device.py @@ -388,6 +388,10 @@ class RECVDevice(OPCUADevice): self.RCU_on() self.wait_attribute("RECVTR_translator_busy_R", False, self.RCU_On_Off_timeout) + self.RCU_DTH_off() + self.wait_attribute( + "RECVTR_translator_busy_R", False, self.RCU_DTH_On_Off_timeout + ) def _power_hardware_off(self): """Turns off the RCUs.""" diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py deleted file mode 100644 index f08f23d702119ff15b2e314b55fc076dbeda0b55..0000000000000000000000000000000000000000 --- a/tangostationcontrol/tangostationcontrol/devices/boot.py +++ /dev/null @@ -1,424 +0,0 @@ -# Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy) -# SPDX-License-Identifier: Apache-2.0 - -""" Boot Device Server for LOFAR2.0 - -Boots the rest of the station software. - -""" - -import logging - -# Additional import -import numpy -from tango import AttrWriteType, DevState - -# PyTango imports -from tango import DebugIt -from tango.server import command -from tango.server import device_property, attribute - -from tangostationcontrol.common.entrypoint import entry -from tangostationcontrol.common.lofar_logging import ( - device_logging_to_python, - log_exceptions, -) -from tangostationcontrol.common.proxy import create_device_proxy -from tangostationcontrol.common.states import OPERATIONAL_STATES -from tangostationcontrol.devices.device_decorators import only_in_states -from tangostationcontrol.devices.base_device_classes.lofar_device import LOFARDevice - -logger = logging.getLogger() - -from threading import Thread - -__all__ = ["Boot", "main"] - - -class InitialisationException(Exception): - pass - - -class DevicesInitialiser(object): - """ - Initialise devices on this station which are not already on (reboot=False), - or all of them (reboot=True). - - Devices which are unreachable are assumed to be brought down explicitly, - and are ignored. - - Initialisation happens in a separate thread. It is started by calling - the start() method, and progress can be followed by inspecting the - members progress (0-100), status (string), and is_running() (bool). - """ - - def __init__( - self, device_names, reboot=False, initialise_hardware=True, proxy_timeout=60.0 - ): - self.reboot = reboot - self.initialise_hardware = initialise_hardware - - self.device_names = device_names - self.proxy_timeout = proxy_timeout - - # setup initial state - self.thread = None - self.progress = 0 - self.devices = [] - self.device_initialised = {name: False for name in device_names} - self.set_status("Initialisation not started yet") - - def _get_device_proxies(self): - """Obtain the Device Proxies to all the devices we are to initialise.""" - - # Since Python3.7+, the insertion order equals the iteration order, - # which is what we depend on to process the devices in the same order as in device_names. - self.set_status("Obtaining DeviceProxies") - devices = {} - for name in self.device_names: - self.set_status(f"Obtaining a DeviceProxy to {name}") - devices[name] = create_device_proxy(name, int(self.proxy_timeout * 1000)) - - return devices - - def run(self): - self.set_status("Starting initialisation") - - try: - # get the device proxies if we didn't already - self.devices = self.devices or self._get_device_proxies() - - # initialise the devices - self.set_status("Initialisation started") - self.initialise_devices() - - # if we get here without throwing an exception, we're done - self.set_status("Initialisation completed") - except Exception as _e: - logger.exception("Failed to initialise station") - - # add the exception to the status - self.set_status( - f"ERROR: {self.status} [{_e.__class__.__name__}: {str(_e)}]" - ) - - # we keep the status stuck at the last thing it tried - - def is_running(self): - return self.thread and self.thread.is_alive() - - def start(self): - if self.is_running(): - # still busy, don't start - return - - if self.thread: - # done, but thread still exist. reap it first - self.stop() - - self.thread = Thread(target=self.run) - self.thread.start() - - def stop(self): - if not self.is_running(): - return - - # Just wait for the current initialisation to finish. It's a finite process. - self.thread.join() - - self.thread = None - - def set_status(self, status): - self.status = status - - logger.info(status) - - def initialise_devices(self): - """ - Initialise or re-initialise all devices on the station. - - If a device fails to initialise, the process is stopped. Calling - this function again will resume initialisation from the failed device. - - :return:None - """ - - # reset initialisation parameters - self.progress = 0 - - logger.debug(self.devices.keys()) - # restart devices in order - for num_restarted_devices, device in enumerate(self.devices.keys(), 1): - # allow resuming by skipping already initialised devices - if self.device_initialised[device]: - logger.debug("%s already initialised", device) - continue - - if self.is_available(device): - logger.debug("%s available", device) - if ( - self.reboot - or self.devices[device].state() not in OPERATIONAL_STATES - ): - self.stop_device(device) - self.boot_device(device) - - # mark device as initialised - self.device_initialised[device] = True - - self.progress = 100.0 * num_restarted_devices / len(self.devices) - - # make sure we always finish at 100% in case of success - self.progress = 100 - - def is_available(self, device_name: str): - """Return whether the device 'device_name' is actually available on this server.""" - - proxy = self.devices[device_name] - try: - proxy.state() - except Exception as _e: - return False - - return True - - def stop_device(self, device_name: str): - """Stop device 'device_name'.""" - - proxy = self.devices[device_name] - - if proxy.state() == DevState.OFF: - # already off - return - - self.set_status(f"[stopping {device_name}] Stopping device.") - - proxy.Off() - if proxy.state() != DevState.OFF: - raise InitialisationException( - f"Could not turn off device {device_name}. It reports status: {proxy.status()}" - ) - - self.set_status(f"[stopping {device_name}] Stopped device.") - - def boot_device(self, device_name: str): - """Run the startup sequence for device 'device_name'.""" - - proxy = self.devices[device_name] - - self.set_status(f"[restarting {device_name}] Booting device.") - proxy.boot() - if self.initialise_hardware: - proxy.power_hardware_on() - - if proxy.state() not in OPERATIONAL_STATES: - raise InitialisationException( - f"Could not boot device {device_name}. It reports status: {proxy.status()}" - ) - - self.set_status(f"[restarting {device_name}] Succesfully booted.") - - -@device_logging_to_python() -class Boot(LOFARDevice): - # maximum number of devices boot.py supports - MAX_BOOT_DEVICES = 128 - - # ----------------- - # Device Properties - # ----------------- - - DeviceProxy_Time_Out = device_property( - dtype="DevDouble", - mandatory=False, - default_value=60.0, - ) - - # Initialise the hardware when initialising a station. Can end badly when using simulators. - Initialise_Hardware = device_property( - dtype="DevBoolean", - mandatory=False, - default_value=True, - ) - - # Which devices to initialise, and in which order - Device_Names = device_property( - dtype="DevVarStringArray", - mandatory=False, - default_value=[ - # "STAT/Docker/1", # TODO(JDM): disabled as it doesn't work in gitlab CI/CD dind. - # Docker controls the device containers, so it goes before anything else - "STAT/Configuration/1", - # Configuration device loads and update station configuration - "STAT/PSOC/1", - # PSOC boot early to detect power delivery failure as fast as possible - "STAT/PCON/1", - # PCON boot early because it is responsible for power delivery. - "STAT/APSPU/1", - # APS Power Units control other hardware we want to initialise - "STAT/APSCT/1", - "STAT/CCD/1", - # RCUs are input for SDP, so initialise them first - "STAT/RECVH/1", - "STAT/RECVL/1", - "STAT/UNB2/1", # Uniboards host SDP, so initialise them first - "STAT/SDPFirmware/HBA", - "STAT/SDP/HBA", - # SDP controls the mask for SST/XST/BST/Beamlet, so initialise it first - "STAT/BST/HBA", - "STAT/SST/HBA", - "STAT/XST/HBA", - "STAT/Beamlet/HBA", - "STAT/AntennaField/HBA", # Accesses RECVH - # "STAT/AntennaField/LBA", # Accesses RECVL - "STAT/TileBeam/HBA", # Accesses AntennaField - # "STAT/TileBeam/LBA", # Accesses AntennaField - "STAT/DigitalBeam/HBA", # Accessed SDP and Beamlet - # "STAT/DigitalBeam/LBA", # Accessed SDP and Beamlet - "STAT/TemperatureManager/1", - "STAT/Calibration/1", - # Calibration device loads and update station calibration - ], - ) - - # ---------- - # Attributes - # ---------- - booting_R = attribute( - dtype=bool, - access=AttrWriteType.READ, - fget=lambda self: self.initialiser.is_running(), - doc="Whether booting is in progress.", - ) - progress_R = attribute( - dtype=numpy.int32, - access=AttrWriteType.READ, - fget=lambda self: numpy.int32(self.initialiser.progress), - doc="Percentage of devices that was initialised", - ) - status_R = attribute( - dtype=str, - access=AttrWriteType.READ, - fget=lambda self: self.initialiser.status, - doc="Description of current boot activity", - ) - initialised_devices_R = attribute( - dtype=(str,), - max_dim_x=MAX_BOOT_DEVICES, - access=AttrWriteType.READ, - fget=lambda self: [ - name - for name, initialised in self.initialiser.device_initialised.items() - if initialised - ], - doc="Which devices were initialised succesfully", - ) - uninitialised_devices_R = attribute( - dtype=(str,), - max_dim_x=MAX_BOOT_DEVICES, - access=AttrWriteType.READ, - fget=lambda self: [ - name - for name, initialised in self.initialiser.device_initialised.items() - if not initialised - ], - doc="Which devices have not been initialised or failed to initialise", - ) - - # -------- - # overloaded functions - # -------- - def init_device(self): - super().init_device() - - # always turn on automatically, so the user doesn't have to boot the boot device - self.Initialise() - self.On() - - # Override to avoid having this called during Initialise, which we call - # from init_device. The original clear_poll_cache requires a functioning - # self.proxy, which is not yet the case during init_device. The proxy - # needs a running server_loop, which is started after init_device. - def clear_poll_cache(self): - pass - - @log_exceptions() - def configure_for_off(self): - """user code here. is called when the state is set to OFF""" - try: - self.initialiser.stop() - except Exception as _e: - logger.warning( - "Exception while stopping OPC ua connection in configure_for_off function: %s. \ - Exception ignored", - _e, - ) - - @log_exceptions() - def configure_for_initialise(self): - # create an initialiser object so we can query it - # even before starting the (first) initialisation - self.initialiser = DevicesInitialiser( - self.Device_Names, - False, - self.Initialise_Hardware, - self.DeviceProxy_Time_Out, - ) - - def _boot(self, reboot=False, initialise_hardware=True): - """ - Initialise all devices on the station that are not yet on (reboot=False), - or shut them down first (reboot=True). - - If initialise_hardware is set, the hardware behind the devices is also - explicitly reinitialised. Turn this off to perform a warm boot. - - This command will take a while to execute, so should be called asynchronously. - - :return:None - """ - - if self.initialiser.is_running(): - # already initialising - return - - # join any previous attempt, if any - try: - self.initialiser.stop() - except RuntimeError: - pass - - # start new initialisation attempt - self.initialiser = DevicesInitialiser( - self.Device_Names, reboot, initialise_hardware, self.DeviceProxy_Time_Out - ) - self.initialiser.start() - - @command() - @DebugIt() - @only_in_states(OPERATIONAL_STATES) - @log_exceptions() - def boot(self): - self._boot(reboot=False, initialise_hardware=self.Initialise_Hardware) - - @command() - @DebugIt() - @only_in_states(OPERATIONAL_STATES) - @log_exceptions() - def reboot(self): - self._boot(reboot=True, initialise_hardware=self.Initialise_Hardware) - - @command() - @DebugIt() - @only_in_states([DevState.ON]) - @log_exceptions() - def warm_boot(self): - self._boot(reboot=False, initialise_hardware=False) - - -# ---------- -# Run server -# ---------- -def main(**kwargs): - """Main function of the Boot module.""" - return entry(Boot, **kwargs) diff --git a/tangostationcontrol/tangostationcontrol/devices/calibration.py b/tangostationcontrol/tangostationcontrol/devices/calibration.py index b295a47bce3be34d6d3ae170135e02c93385cd97..df7c1ec31a3b50be659989098addc3f40c824502 100644 --- a/tangostationcontrol/tangostationcontrol/devices/calibration.py +++ b/tangostationcontrol/tangostationcontrol/devices/calibration.py @@ -16,6 +16,7 @@ from tangostationcontrol.common.calibration import ( calibrate_RCU_attenuator_dB, calibrate_input_samples_delay, ) +from tangostationcontrol.common.case_insensitive_dict import CaseInsensitiveDict from tangostationcontrol.common.entrypoint import entry from tangostationcontrol.common.lofar_logging import ( device_logging_to_python, @@ -41,29 +42,31 @@ class Calibration(LOFARDevice): def __init__(self, cl, name): self._calibration_manager: CalibrationManager = None self.event_subscriptions: list = [] - self.sdpfirmware_proxies: dict = {} - self.sdp_proxies: dict = {} - self.ant_proxies: dict = {} - self.last_ant_calibration_timestamp: dict[str, datetime.datetime | None] = {} + self.sdpfirmware_proxies: CaseInsensitiveDict = CaseInsensitiveDict() + self.sdp_proxies: CaseInsensitiveDict = CaseInsensitiveDict() + self.ant_proxies: CaseInsensitiveDict = CaseInsensitiveDict() + self.last_ant_calibration_timestamp: CaseInsensitiveDict[ + str, datetime.datetime | None + ] = CaseInsensitiveDict() # Super must be called after variable assignment due to executing init_device! super().__init__(cl, name) - def _calibrate_antenna_field(self, ant_proxy): + def _calibrate_antenna_field(self, device): """Recalibrate a specific AntennaField.""" + ant_proxy = self.ant_proxies[device] + if ant_proxy.state() not in DEFAULT_COMMAND_STATES: - logger.warning( - f"Device {ant_proxy.name()} not active. Forgoing calibration." - ) + logger.warning(f"Device {device} not active. Forgoing calibration.") return - logger.info("Re-calibrate antenna field %s", ant_proxy.name()) + logger.info("Re-calibrate antenna field %s", device) - self.last_ant_calibration_timestamp[ant_proxy] = datetime.datetime.now() + self.last_ant_calibration_timestamp[device] = datetime.datetime.now() - self.calibrate_recv(ant_proxy) - self.calibrate_sdp(ant_proxy) + self.calibrate_recv(device) + self.calibrate_sdp(device) @log_exceptions() def _antennafield_changed_event(self, event): @@ -86,7 +89,7 @@ class Calibration(LOFARDevice): return # frequencies changed, so we need to recalibrate - self._calibrate_antenna_field(event.device) + self._calibrate_antenna_field(event.device.name()) @log_exceptions() def _clock_changed_event(self, event): @@ -109,7 +112,7 @@ class Calibration(LOFARDevice): for k, ant in self.ant_proxies.items(): # Recalibrate associated AntennaFields - sdpfirmware_device = ant.SDPFirmware_device_R.casefold() + sdpfirmware_device = ant.SDPFirmware_device_R sdp_device = self.sdpfirmware_proxies[sdpfirmware_device].SDP_device_R if device_name_matches(sdp_device, event.device.name()): @@ -172,9 +175,6 @@ class Calibration(LOFARDevice): antennafield.RCU_band_select_RW """ - # sanitize device name - device = device.casefold() - # ----------------------------------------------------------- # Set signal-input attenuation to compensate for # differences in cable length. @@ -196,14 +196,11 @@ class Calibration(LOFARDevice): antennafield.RCU_band_select_RW """ - # sanitize device name - device = device.casefold() - if device not in self.ant_proxies: raise ValueError(f"Could not find {device} in {self.ant_proxies}") ant_proxy = self.ant_proxies[device] - sdpfirmware_device = str(ant_proxy.SDPFirmware_device_R).casefold() + sdpfirmware_device = ant_proxy.SDPFirmware_device_R if sdpfirmware_device not in self.sdpfirmware_proxies: raise ValueError( @@ -212,7 +209,7 @@ class Calibration(LOFARDevice): sdpfirmware_proxy = self.sdpfirmware_proxies[sdpfirmware_device] - sdp_device = str(sdpfirmware_proxy.SDP_device_R).casefold() + sdp_device = sdpfirmware_proxy.SDP_device_R if sdp_device not in self.sdp_proxies: raise ValueError(f"Could not find {sdp_device} in {self.sdp_proxies}") @@ -248,21 +245,22 @@ class Calibration(LOFARDevice): db = Database() devices = db.get_device_exported_for_class(AntennaField.__name__) for d in devices: - logger.debug("found antenna field device %s", str(d)) - self.ant_proxies = {d.casefold(): create_device_proxy(d) for d in devices} - self.last_ant_calibration_timestamp = {d.casefold(): None for d in devices} + logger.debug(f"Found antenna field device {d}") + + self.ant_proxies[d] = create_device_proxy(d) + self.last_ant_calibration_timestamp[d] = None devices = db.get_device_exported_for_class(SDPFirmware.__name__) for d in devices: - logger.debug("found SDP firmware device %s", str(d)) - self.sdpfirmware_proxies = { - d.casefold(): create_device_proxy(d) for d in devices - } + logger.debug(f"Dound SDP firmware device {d}") + + self.sdpfirmware_proxies[d] = create_device_proxy(d) devices = db.get_device_exported_for_class(SDP.__name__) for d in devices: - logger.debug("found SDP device %s", str(d)) - self.sdp_proxies = {d.casefold(): create_device_proxy(d) for d in devices} + logger.debug(f"Found SDP device {d}") + + self.sdp_proxies[d] = create_device_proxy(d) # subscribe to events to notice setting changes in SDP that determine the # input frequency diff --git a/tangostationcontrol/test/devices/base_device_classes/test_mapper.py b/tangostationcontrol/test/devices/base_device_classes/test_mapper.py new file mode 100644 index 0000000000000000000000000000000000000000..9dc78b7f2c4a5263a18548e74646d97b115ad1cc --- /dev/null +++ b/tangostationcontrol/test/devices/base_device_classes/test_mapper.py @@ -0,0 +1,142 @@ +# Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy) +# SPDX-License-Identifier: Apache-2.0 + +from test import base +import numpy + +from tangostationcontrol.common.constants import N_rcu +from tangostationcontrol.devices.base_device_classes.mapper import RecvDeviceWalker + + +class TestRecvDeviceWalker(base.TestCase): + """Test class for RecvDeviceWalker""" + + class MockDeviceProxy: + """Mock of DeviceProxy that simulates recv.ANT_mask_RW.""" + + @property + def ANT_mask_RW(self): + return self.ant_mask + + @ANT_mask_RW.setter + def ANT_mask_RW(self, value): + self.ant_mask = value + + def __init__(self, index): + self.visited = False + self.index = index + + # fill with a value we don't use, to make sure + # there will be a difference when set + self.ant_mask = numpy.array([[False, True, True]] * N_rcu) + + # save the value we originally use + self.original_ant_mask = self.ant_mask + + def test_recv_masks_identity_mapping(self): + """Test whether a straight setup works.""" + + control_to_recv_mapping = numpy.array([[1, 0], [1, 1], [1, 2]]) + antenna_usage_mask = numpy.array([True, True, True]) + + sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) + + expected = numpy.array( + [[[True, True, True]] + [[False, False, False]] * (N_rcu - 1)] + ) + numpy.testing.assert_equal(expected, sut.recv_ant_masks()) + + def test_recv_masks_antenna_usage_mask(self): + """Test whether the antenna_usage_mask is respected.""" + + control_to_recv_mapping = numpy.array([[1, 0], [1, 1], [1, 2]]) + antenna_usage_mask = numpy.array([False, True, False]) + + sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) + + expected = numpy.array( + [[[False, True, False]] + [[False, False, False]] * (N_rcu - 1)] + ) + numpy.testing.assert_equal(expected, sut.recv_ant_masks()) + + def test_recv_masks_control_to_recv_mapping(self): + """Test whether control_to_recv_mapping is respected.""" + + control_to_recv_mapping = numpy.array([[1, 0], [2, 1], [1, 2]]) + antenna_usage_mask = numpy.array([True, True, True]) + + sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) + + expected = numpy.array( + [ + [[True, False, True]] + [[False, False, False]] * (N_rcu - 1), + [[False, True, False]] + [[False, False, False]] * (N_rcu - 1), + ] + ) + numpy.testing.assert_equal(expected, sut.recv_ant_masks()) + + def test_walk_receivers(self): + """Test walk_receivers on multiple recv_proxies.""" + + control_to_recv_mapping = numpy.array([[1, 0], [2, 1], [1, 2]]) + antenna_usage_mask = numpy.array([True, True, True]) + + sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) + + recv_proxies = [TestRecvDeviceWalker.MockDeviceProxy(n + 1) for n in range(2)] + + def visitor(recv_proxy): + recv_proxy.visited = True + + # is our mask set correctly? + if recv_proxy.index == 1: + expected = numpy.array( + [[True, False, True]] + [[False, False, False]] * (N_rcu - 1) + ) + elif recv_proxy.index == 2: + expected = numpy.array( + [[False, True, False]] + [[False, False, False]] * (N_rcu - 1) + ) + + numpy.testing.assert_equal(expected, recv_proxy.ANT_mask_RW) + + sut.walk_receivers(recv_proxies, visitor) + + # make sure both recv_proxies were visited + self.assertTrue(recv_proxies[0].visited) + self.assertTrue(recv_proxies[1].visited) + + # make sure both masks were restored + numpy.testing.assert_equal( + recv_proxies[0].original_ant_mask, recv_proxies[0].ant_mask + ) + numpy.testing.assert_equal( + recv_proxies[1].original_ant_mask, recv_proxies[1].ant_mask + ) + + def test_walk_receivers_restores_mask_on_exception(self): + """Test whether walk_receivers() also restores the recv_proxy.ANT_mask_RW + if the visitor function throws.""" + control_to_recv_mapping = numpy.array([[1, 0], [2, 1], [1, 2]]) + antenna_usage_mask = numpy.array([True, True, True]) + + sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) + + recv_proxies = [TestRecvDeviceWalker.MockDeviceProxy(n + 1) for n in range(2)] + + class MyException(Exception): + """A exception noone can raise but us.""" + + def visitor(recv_proxy): + raise MyException("foo") + + with self.assertRaises(MyException): + sut.walk_receivers(recv_proxies, visitor) + + # make sure no mask was disturbed + numpy.testing.assert_equal( + recv_proxies[0].original_ant_mask, recv_proxies[0].ant_mask + ) + numpy.testing.assert_equal( + recv_proxies[1].original_ant_mask, recv_proxies[1].ant_mask + ) diff --git a/tangostationcontrol/test/devices/test_antennafield_device.py b/tangostationcontrol/test/devices/test_antennafield_device.py index 0ce70d37a2b9af165372f63fc2bed2ef9e370ae7..685e3fceaa17a95bd06160ec468f6e57489c64e0 100644 --- a/tangostationcontrol/test/devices/test_antennafield_device.py +++ b/tangostationcontrol/test/devices/test_antennafield_device.py @@ -30,7 +30,6 @@ from tangostationcontrol.devices.base_device_classes.mapper import ( MappingKeys, AntennaToRecvMapper, AntennaToSdpMapper, - RecvDeviceWalker, ) logger = logging.getLogger() @@ -38,6 +37,8 @@ logger = logging.getLogger() SDP_MAPPED_ATTRS = AntennaField.get_mapped_dimensions("SDP") RECV_MAPPED_ATTRS = AntennaField.get_mapped_dimensions("RECV") +DEFAULT_N_LBA = DEFAULT_N_HBA_TILES # 48 antennas + class TestAntennaToSdpMapper(base.TestCase): """Test class for AntennaToSDPMapper""" @@ -151,7 +152,106 @@ class TestAntennaToSdpMapper(base.TestCase): numpy.testing.assert_equal(expected, actual) -class TestAntennaToRecvMapper(base.TestCase): +class TestLBAToRecvMapper(base.TestCase): + """Test class for AntennaToRecvMapper with LBA AntennaType""" + + # A mapping where Antennas are all not mapped to power RCUs + POWER_NOT_CONNECTED = [[-1, -1]] * 2 * DEFAULT_N_LBA + # A mapping where Antennas are all not mapped to control RCUs + CONTROL_NOT_CONNECTED = [[-1, -1]] * 2 * DEFAULT_N_LBA + # 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. + POWER_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1 = ( + [[1, 1], [1, 0]] + + [[-1, -1]] * (DEFAULT_N_LBA - 2) + + [[2, 1], [2, 0]] + + [[-1, -1]] * (DEFAULT_N_LBA - 2) + ) + CONTROL_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1 = ( + POWER_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1 + ) + ANTENNA_TYPE = "LBA" + + def test_map_write_rcu_pwr_ant_on_no_mapping_and_one_receiver(self): + recv_mapping = { + MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, + MappingKeys.POWER: self.POWER_NOT_CONNECTED, + } + mapper = AntennaToRecvMapper( + recv_mapping, + RECV_MAPPED_ATTRS, + 1, + self.ANTENNA_TYPE, + ) + + set_values = [None] * DEFAULT_N_LBA + expected = [[[None, None, None]] * N_rcu] + actual = mapper.map_write("RCU_PWR_ANT_on_RW", set_values) + numpy.testing.assert_equal(expected, actual) + + def test_map_write_rcu_pwr_ant_on_no_mapping_and_two_receivers(self): + recv_mapping = { + MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, + MappingKeys.POWER: self.POWER_NOT_CONNECTED, + } + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) + + set_values = [None] * DEFAULT_N_LBA + expected = [[[None, None, None]] * N_rcu] * 2 + actual = mapper.map_write("RCU_PWR_ANT_on_RW", set_values) + numpy.testing.assert_equal(expected, actual) + + def test_map_write_rcu_pwr_ant_on_hba_0_and_1_on_rcu_1_and_0_of_recv_1_and_no_ctrl( + self, + ): + recv_mapping = { + MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, + MappingKeys.POWER: self.POWER_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, + } + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) + + set_values = [1, 0] + [None] * (DEFAULT_N_LBA - 2) + expected = [[[None, None, None]] + [[None, None, None]] * (N_rcu - 1)] + actual = mapper.map_write("RCU_PWR_ANT_on_RW", set_values) + numpy.testing.assert_equal(expected, actual) + + def test_map_read_rcu_pwr_ant_on_hba_0_and_1_on_rcu_1_and_0_of_recv_1(self): + recv_mapping = { + MappingKeys.CONTROL: self.CONTROL_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, + MappingKeys.POWER: self.POWER_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, + } + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) + + receiver_values = [[False, True] + [False] * (MAX_ANTENNA - 2)] * 2 + expected = ([True, False] + [False] * (int(MAX_ANTENNA / 2) - 2)) * 2 + actual = mapper.map_read("RCU_PWR_ANT_on_R", receiver_values) + numpy.testing.assert_equal(expected, actual) + + def test_map_write_rcu_pwr_ant_on_hba_0_and_1_on_rcu_1_and_0_of_recv_1(self): + recv_mapping = { + MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, + MappingKeys.POWER: self.POWER_LBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, + } + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) + + set_values = [1, 0] + [None] * (DEFAULT_N_LBA - 2) + expected = [[[None, None, None]] * N_rcu] + actual = mapper.map_write("RCU_PWR_ANT_on_RW", set_values) + numpy.testing.assert_equal(expected, actual) + + +class TestHBAToRecvMapper(base.TestCase): + """Test class for AntennaToRecvMapper with HBA AntennaType""" + # A mapping where Antennas are all not mapped to power RCUs POWER_NOT_CONNECTED = [[-1, -1]] * DEFAULT_N_HBA_TILES # A mapping where Antennas are all not mapped to control RCUs @@ -168,13 +268,16 @@ class TestAntennaToRecvMapper(base.TestCase): CONTROL_HBA_0_AND_1_ON_RCU_3_AND_2_OF_RECV_1 = [[1, 3], [1, 2]] + [[-1, -1]] * ( DEFAULT_N_HBA_TILES - 2 ) + ANTENNA_TYPE = "HBA" def test_ant_read_mask_r_no_mapping(self): recv_mapping = { MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [False] * MAX_ANTENNA, @@ -190,7 +293,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [False, True, False] + [False, False, False] * (N_rcu - 1), @@ -207,7 +312,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [[0] * MAX_ANTENNA, [0] * MAX_ANTENNA, [0] * MAX_ANTENNA] expected = [[0, 0]] * DEFAULT_N_HBA_TILES actual = mapper.map_read("RCU_band_select_RW", receiver_values) @@ -218,7 +325,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[0] * N_rcu] * MAX_ANTENNA, @@ -234,7 +343,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[2] * N_rcu, [1] * N_rcu] + [[0] * N_rcu] * (MAX_ANTENNA - 2), @@ -253,7 +364,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[0] * N_rcu] * MAX_ANTENNA, @@ -269,7 +382,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[2] * N_rcu, [1] * N_rcu] + [[0] * N_rcu] * (MAX_ANTENNA - 2), @@ -288,7 +403,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False] * N_rcu] * MAX_ANTENNA, @@ -304,7 +421,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False, True] * 16, [True, False] * 16] @@ -324,7 +443,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False] * N_rcu] * MAX_ANTENNA, @@ -340,7 +461,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False, True] * 16, [True, False] * 16] @@ -360,7 +483,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False] * N_rcu] * MAX_ANTENNA, @@ -376,7 +501,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False, True] * 16, [True, False] * 16] @@ -396,7 +523,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False] * N_rcu] * MAX_ANTENNA, @@ -412,7 +541,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False, True] * 16, [True, False] * 16] @@ -432,7 +563,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False] * N_rcu] * MAX_ANTENNA, @@ -448,7 +581,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False, True] * 16, [True, False] * 16] @@ -468,7 +603,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False] * N_rcu] * MAX_ANTENNA, @@ -484,7 +621,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ [[False, True] * 16, [True, False] * 16] @@ -505,7 +644,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [list(range(32)), [0] * 32, [0] * 32] expected = [[0] * 2] * DEFAULT_N_HBA_TILES actual = mapper.map_read("RCU_PCB_ID_R", receiver_values) @@ -518,7 +659,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_3_AND_2_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [list(range(32)), [0] * 32, [0] * 32] expected = [[0, 3], [0, 2]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) actual = mapper.map_read("RCU_PCB_ID_R", receiver_values) @@ -531,7 +674,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [list(range(32)), [0] * 32, [0] * 32] expected = [[1, 0], [0, 0]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) actual = mapper.map_read("RCU_PCB_ID_R", receiver_values) @@ -544,7 +689,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_3_AND_2_OF_RECV_1, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [list(range(32)), [0] * 32, [0] * 32] expected = [[1, 3], [0, 2]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) actual = mapper.map_read("RCU_PCB_ID_R", receiver_values) @@ -556,7 +703,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 3) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 3, self.ANTENNA_TYPE + ) receiver_values = [ list(range(MAX_ANTENNA)), [0] * MAX_ANTENNA, @@ -573,7 +722,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) receiver_values = [list(range(MAX_ANTENNA))] expected = [[0, 1], [0, 0]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) actual = mapper.map_read("RCU_attenuator_dB_R", receiver_values) @@ -586,7 +737,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) receiver_values = [list(range(MAX_ANTENNA))] expected = [[1, 0], [0, 0]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) actual = mapper.map_read("RCU_attenuator_dB_R", receiver_values) @@ -599,7 +752,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_3_AND_2_OF_RECV_1, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) receiver_values = [list(range(MAX_ANTENNA))] expected = [[1, 3], [0, 2]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) actual = mapper.map_read("RCU_attenuator_dB_R", receiver_values) @@ -613,7 +768,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [None] * DEFAULT_N_HBA_TILES expected = [[[None, None, None]] * N_rcu] @@ -626,7 +783,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [None] * DEFAULT_N_HBA_TILES expected = [[[None, None, None]] * N_rcu] * 2 @@ -638,7 +797,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [True, False] + [None] * (DEFAULT_N_HBA_TILES - 2) expected = [[[False, True, None]] + [[None, None, None]] * (N_rcu - 1)] @@ -650,7 +811,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [None] * DEFAULT_N_HBA_TILES expected = [[[None, None, None]] * N_rcu] @@ -662,7 +825,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [None] * DEFAULT_N_HBA_TILES expected = [[[None, None, None]] * N_rcu] * 2 @@ -674,7 +839,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [1, 0] + [None] * (DEFAULT_N_HBA_TILES - 2) expected = [[[0, 1, None]] + [[None, None, None]] * (N_rcu - 1)] @@ -686,7 +853,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [None] * DEFAULT_N_HBA_TILES expected = [[[None, None, None]] * N_rcu] @@ -698,7 +867,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [None] * DEFAULT_N_HBA_TILES expected = [[[None, None, None]] * N_rcu] * 2 @@ -710,7 +881,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[1, 1], [0, 0]] + [[None, None]] * (DEFAULT_N_HBA_TILES - 2) expected = [[[0, 1, None]] + [[None, None, None]] * (N_rcu - 1)] @@ -722,7 +895,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[1] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA] @@ -734,7 +909,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [[1] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA, [[None] * N_rcu] * MAX_ANTENNA] @@ -746,7 +923,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[1] * N_rcu, [2] * N_rcu] + [[None] * N_rcu] * ( DEFAULT_N_HBA_TILES - 2 @@ -760,7 +939,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[None] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA] @@ -772,7 +953,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [[None] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA, [[None] * N_rcu] * MAX_ANTENNA] @@ -784,7 +967,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[False, True] * 16, [True, False] * 16] + [[None] * N_rcu] * ( DEFAULT_N_HBA_TILES - 2 @@ -801,7 +986,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[None] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA] @@ -813,7 +1000,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [[None] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA, [[None] * N_rcu] * MAX_ANTENNA] @@ -825,7 +1014,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[False, True] * 16, [True, False] * 16] + [[None] * N_rcu] * ( DEFAULT_N_HBA_TILES - 2 @@ -842,7 +1033,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[None] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA] actual = mapper.map_write("HBAT_PWR_on_RW", set_values) @@ -853,7 +1046,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 2) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 2, self.ANTENNA_TYPE + ) set_values = [[None] * N_rcu] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu] * MAX_ANTENNA, [[None] * N_rcu] * MAX_ANTENNA] @@ -865,7 +1060,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[False, True] * 16, [True, False] * 16] + [[None] * N_rcu] * ( DEFAULT_N_HBA_TILES - 2 @@ -883,7 +1080,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[1, 1]] * DEFAULT_N_HBA_TILES expected = [[[None] * N_rcu_inp] * N_rcu] @@ -898,7 +1097,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, MappingKeys.POWER: self.POWER_NOT_CONNECTED, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = [[1, 2], [3, 4]] + [[0, 0]] * (DEFAULT_N_HBA_TILES - 2) expected = [[[4, 2, None]] + [[None] * N_rcu_inp] * (N_rcu - 1)] @@ -913,7 +1114,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_NOT_CONNECTED, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = set_values = [[1, 2], [3, 4]] + [[0, 0]] * ( DEFAULT_N_HBA_TILES - 2 @@ -930,7 +1133,9 @@ class TestAntennaToRecvMapper(base.TestCase): MappingKeys.CONTROL: self.CONTROL_HBA_0_AND_1_ON_RCU_3_AND_2_OF_RECV_1, MappingKeys.POWER: self.POWER_HBA_0_AND_1_ON_RCU_1_AND_0_OF_RECV_1, } - mapper = AntennaToRecvMapper(recv_mapping, RECV_MAPPED_ATTRS, 1) + mapper = AntennaToRecvMapper( + recv_mapping, RECV_MAPPED_ATTRS, 1, self.ANTENNA_TYPE + ) set_values = set_values = [[1, 2], [3, 4]] + [[0, 0]] * ( DEFAULT_N_HBA_TILES - 2 @@ -942,6 +1147,8 @@ class TestAntennaToRecvMapper(base.TestCase): class TestAntennafieldDevice(device_base.DeviceTestCase): + """Test class for AntennaField device""" + # some dummy values for mandatory properties AT_PROPERTIES = { "OPC_Server_Name": "example.com", @@ -954,11 +1161,16 @@ class TestAntennafieldDevice(device_base.DeviceTestCase): ANTENNA_PROPERTIES = { "Antenna_Sets": ["INNER", "OUTER", "SPARSE_EVEN", "SPARSE_ODD", "ALL"], "Antenna_Set_Masks": [ - "111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111", - "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010", - "010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101", - "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "111111111111111111111111111111111111111111111111" + + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000" + + "111111111111111111111111111111111111111111111111", + "101010101010101010101010101010101010101010101010" + + "101010101010101010101010101010101010101010101010", + "010101010101010101010101010101010101010101010101" + + "010101010101010101010101010101010101010101010101", + "111111111111111111111111111111111111111111111111" + + "111111111111111111111111111111111111111111111111", ], } @@ -1107,137 +1319,3 @@ class TestAntennafieldDevice(device_base.DeviceTestCase): ) as proxy: expected = [True] * int(MAX_ANTENNA / 2) + [False] * int(MAX_ANTENNA / 2) numpy.testing.assert_equal(expected, proxy.antenna_set_to_mask("INNER")) - - -class TestRecvDeviceWalker(base.TestCase): - class MockDeviceProxy: - """Mock of DeviceProxy that simulates recv.ANT_mask_RW.""" - - @property - def ANT_mask_RW(self): - return self.ant_mask - - @ANT_mask_RW.setter - def ANT_mask_RW(self, value): - self.ant_mask = value - - def __init__(self, index): - self.visited = False - self.index = index - - # fill with a value we don't use, to make sure - # there will be a difference when set - self.ant_mask = numpy.array([[False, True, True]] * N_rcu) - - # save the value we originally use - self.original_ant_mask = self.ant_mask - - def test_recv_masks_identity_mapping(self): - """Test whether a straight setup works.""" - - control_to_recv_mapping = numpy.array([[1, 0], [1, 1], [1, 2]]) - antenna_usage_mask = numpy.array([True, True, True]) - - sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) - - expected = numpy.array( - [[[True, True, True]] + [[False, False, False]] * (N_rcu - 1)] - ) - numpy.testing.assert_equal(expected, sut.recv_ant_masks()) - - def test_recv_masks_antenna_usage_mask(self): - """Test whether the antenna_usage_mask is respected.""" - - control_to_recv_mapping = numpy.array([[1, 0], [1, 1], [1, 2]]) - antenna_usage_mask = numpy.array([False, True, False]) - - sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) - - expected = numpy.array( - [[[False, True, False]] + [[False, False, False]] * (N_rcu - 1)] - ) - numpy.testing.assert_equal(expected, sut.recv_ant_masks()) - - def test_recv_masks_control_to_recv_mapping(self): - """Test whether control_to_recv_mapping is respected.""" - - control_to_recv_mapping = numpy.array([[1, 0], [2, 1], [1, 2]]) - antenna_usage_mask = numpy.array([True, True, True]) - - sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) - - expected = numpy.array( - [ - [[True, False, True]] + [[False, False, False]] * (N_rcu - 1), - [[False, True, False]] + [[False, False, False]] * (N_rcu - 1), - ] - ) - numpy.testing.assert_equal(expected, sut.recv_ant_masks()) - - def test_walk_receivers(self): - """Test walk_receivers on multiple recv_proxies.""" - - control_to_recv_mapping = numpy.array([[1, 0], [2, 1], [1, 2]]) - antenna_usage_mask = numpy.array([True, True, True]) - - sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) - - recv_proxies = [TestRecvDeviceWalker.MockDeviceProxy(n + 1) for n in range(2)] - - def visitor(recv_proxy): - recv_proxy.visited = True - - # is our mask set correctly? - if recv_proxy.index == 1: - expected = numpy.array( - [[True, False, True]] + [[False, False, False]] * (N_rcu - 1) - ) - elif recv_proxy.index == 2: - expected = numpy.array( - [[False, True, False]] + [[False, False, False]] * (N_rcu - 1) - ) - - numpy.testing.assert_equal(expected, recv_proxy.ANT_mask_RW) - - sut.walk_receivers(recv_proxies, visitor) - - # make sure both recv_proxies were visited - self.assertTrue(recv_proxies[0].visited) - self.assertTrue(recv_proxies[1].visited) - - # make sure both masks were restored - numpy.testing.assert_equal( - recv_proxies[0].original_ant_mask, recv_proxies[0].ant_mask - ) - numpy.testing.assert_equal( - recv_proxies[1].original_ant_mask, recv_proxies[1].ant_mask - ) - - def test_walk_receivers_restores_mask_on_exception(self): - """Test whether walk_receivers() also restores the recv_proxy.ANT_mask_RW - if the visitor function throws.""" - control_to_recv_mapping = numpy.array([[1, 0], [2, 1], [1, 2]]) - antenna_usage_mask = numpy.array([True, True, True]) - - sut = RecvDeviceWalker(control_to_recv_mapping, antenna_usage_mask) - - recv_proxies = [TestRecvDeviceWalker.MockDeviceProxy(n + 1) for n in range(2)] - - class MyException(Exception): - """A exception noone can raise but us.""" - - pass - - def visitor(recv_proxy): - raise MyException("foo") - - with self.assertRaises(MyException): - sut.walk_receivers(recv_proxies, visitor) - - # make sure no mask was disturbed - numpy.testing.assert_equal( - recv_proxies[0].original_ant_mask, recv_proxies[0].ant_mask - ) - numpy.testing.assert_equal( - recv_proxies[1].original_ant_mask, recv_proxies[1].ant_mask - )