diff --git a/.gitattributes b/.gitattributes index 0e93fbf274cc4e3c099a1f8f668e12cbffe489fc..528424372af47b09c7fd2c8e3681a850d7d81aca 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2047,6 +2047,7 @@ MAC/APL/APLCommon/src/StartDaemon_Protocol.prot -text svneol=native#application/ MAC/APL/APLCommon/src/run_timeout.sh -text svneol=unset#text/sh-applic MAC/APL/APLCommon/src/swlevel -text MAC/APL/APLCommon/src/swlevel.conf -text +MAC/APL/APLCommon/src/warp -text MAC/APL/APLCommon/test/ControllerProtMenu.cc -text MAC/APL/APLCommon/test/ControllerProtMenu.h -text MAC/APL/APLCommon/test/tAntennaField.cc -text @@ -2889,6 +2890,7 @@ MAC/Deployment/data/StaticMetaData/CableDelays/DE605-CableDelays.conf -text MAC/Deployment/data/StaticMetaData/CableDelays/DE609-CableDelays.conf -text MAC/Deployment/data/StaticMetaData/CableDelays/FI609-CableDelays.conf -text MAC/Deployment/data/StaticMetaData/CableDelays/FR606-CableDelays.conf -text +MAC/Deployment/data/StaticMetaData/CableDelays/IE613-CableDelays.conf -text MAC/Deployment/data/StaticMetaData/CableDelays/PL610-CableDelays.conf -text MAC/Deployment/data/StaticMetaData/CableDelays/PL611-CableDelays.conf -text MAC/Deployment/data/StaticMetaData/CableDelays/PL612-CableDelays.conf -text diff --git a/CMake/LofarPackageList.cmake b/CMake/LofarPackageList.cmake index 44ba1acdfcef453d4077dc7dbcb2e0ec2c2e7331..88cffc67731b534be8e29fccc72b8d8a7b83ebd7 100644 --- a/CMake/LofarPackageList.cmake +++ b/CMake/LofarPackageList.cmake @@ -1,7 +1,7 @@ # - Create for each LOFAR package a variable containing the absolute path to # its source directory. # -# Generated by gen_LofarPackageList_cmake.sh at do 20 apr 2017 15:52:08 CEST +# Generated by gen_LofarPackageList_cmake.sh at do 17 aug 2017 13:32:37 CEST # # ---- DO NOT EDIT ---- # @@ -36,7 +36,6 @@ if(NOT DEFINED LOFAR_PACKAGE_LIST_INCLUDED) set(TestDynDPPP_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/DP3/TestDynDPPP) set(PythonDPPP_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/DP3/PythonDPPP) set(DPPP_AOFlag_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/DP3/DPPP_AOFlag) - set(DPPP_DDECal_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/DP3/DPPP_DDECal) set(SPW_Combine_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/DP3/SPWCombine) set(LofarFT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/Imager/LofarFT) set(AWImager2_SOURCE_DIR ${CMAKE_SOURCE_DIR}/CEP/Imager/AWImager2) @@ -134,7 +133,7 @@ if(NOT DEFINED LOFAR_PACKAGE_LIST_INCLUDED) set(Navigator2_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Navigator2) set(MACTools_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Tools) set(MAC_Services_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Services) - set(PVSS_Datapoints_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Deployment/data/PVSS) + set(WinCC_Datapoints_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Deployment/data/PVSS) set(OTDB_Comps_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Deployment/data/OTDB) set(StaticMetaData_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/Deployment/data/StaticMetaData) set(WinCC_Services_SOURCE_DIR ${CMAKE_SOURCE_DIR}/MAC/WinCCServices) @@ -199,7 +198,7 @@ if(NOT DEFINED LOFAR_PACKAGE_LIST_INCLUDED) set(Offline_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/Offline) set(SAS_OTDB_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/SAS_OTDB) set(SAS_Tools_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/SAS_Tools) - set(PVSS_DB_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/PVSS_DB) + set(WinCC_DB_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/WinCC_DB) set(RAServices_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/RAServices) set(DataManagement_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/DataManagement) set(Dragnet_SOURCE_DIR ${CMAKE_SOURCE_DIR}/SubSystems/Dragnet) diff --git a/LCS/Messaging/python/messaging/Service.py b/LCS/Messaging/python/messaging/Service.py index 034d2c835076b259352137a7512b7887ba0639aa..7efef0ee7051a00e81cf44751c40589ec5000b04 100644 --- a/LCS/Messaging/python/messaging/Service.py +++ b/LCS/Messaging/python/messaging/Service.py @@ -211,7 +211,9 @@ class Service(AbstractBusListener): reply_msg.subject=subject dest.send(reply_msg) except MessageBusError as e: - logger.error("Failed to send reply message to reply address %s on messagebus %s" %(subject,reply_busname)) + logger.error("Failed to send reply message to reply address %s on messagebus %s. Error: %s", subject, + reply_busname, + e) return if isinstance(self.reply_bus,ToBus): @@ -219,7 +221,9 @@ class Service(AbstractBusListener): try: self.reply_bus.send(reply_msg) except MessageBusError as e: - logger.error("Failed to send reply message to reply address %s on messagebus %s" %(reply_to,self.busname)) + logger.error("Failed to send reply message to reply address %s on messagebus %s. Error: %s", reply_to, + self.busname, + e) return else: # the reply address is not in a default known format @@ -229,7 +233,7 @@ class Service(AbstractBusListener): with ToBus(reply_to) as dest: dest.send(reply_msg) except MessageBusError as e: - logger.error("Failed to send reply messgage to reply address %s" %(reply_to)) + logger.error("Failed to send reply messgage to reply address %s. Error: %s", reply_to, e) def _getServiceHandlerForCurrentThread(self): currentThread = threading.currentThread() diff --git a/MAC/APL/APLCommon/src/CMakeLists.txt b/MAC/APL/APLCommon/src/CMakeLists.txt index cc0e8beef5b7440908e97778937e900db791ba15..c8e5c6f7885965835830c161b6f6b9111b023556 100644 --- a/MAC/APL/APLCommon/src/CMakeLists.txt +++ b/MAC/APL/APLCommon/src/CMakeLists.txt @@ -27,6 +27,7 @@ lofar_add_bin_program(versionaplcommon versionaplcommon.cc) lofar_add_bin_scripts( swlevel + warp run_timeout.sh) install(FILES diff --git a/MAC/APL/APLCommon/src/warp b/MAC/APL/APLCommon/src/warp new file mode 120000 index 0000000000000000000000000000000000000000..85bbe190c395b16cc9df28eab9b1d9dc3f547212 --- /dev/null +++ b/MAC/APL/APLCommon/src/warp @@ -0,0 +1 @@ +swlevel \ No newline at end of file diff --git a/MAC/APL/CURTDBDaemons/src/SoftwareMonitor/SoftwareMonitor.conf b/MAC/APL/CURTDBDaemons/src/SoftwareMonitor/SoftwareMonitor.conf index ec4c6b2491cdccdbc6522874ef7d37b70c4ad523..014d8f833bdeaa1f998bab0ad799655b0c81e960 100644 --- a/MAC/APL/CURTDBDaemons/src/SoftwareMonitor/SoftwareMonitor.conf +++ b/MAC/APL/CURTDBDaemons/src/SoftwareMonitor/SoftwareMonitor.conf @@ -3,20 +3,19 @@ # # After how many seconds the software monitor should start a new check. -pollInterval = 15 +pollInterval = 30 # The minimal number of times a program-state may differ from the requested state # before the program is reported suspiscious. -suspisciousThreshold = 2 +suspisciousThreshold = 3 # The minimal number of times a program-state may differ from the requested state # before the program is reported broken. -brokenThreshold = 4 +brokenThreshold = 6 # List of programs that the SoftwareMonitor may restart (by calling swlevel) -restartablePrograms = [MACScheduler,ServiceBroker,SASGateway,MessageRouter,FeedbackService,PVSSGateway,CTStartDaemon,StationControl,BeamServer,CalServer] +restartablePrograms = [MessageRouter,LogProcessor,ServiceBroker,SASGateway,PVSSGateway,FeedbackService,BeamServer,CalServer,HardwareMonitor,CTStartDaemon,MACScheduler,StationControl,ClockControl] # Restart of programs are done every poll during suspicious-mode. When program # reaches the broken state restarting is done less often. -restartIntervalInPolls = 4 - +restartIntervalInPolls = 8 diff --git a/MAC/CMakeLists.txt b/MAC/CMakeLists.txt index c0e44ce516c839cc4a15a826a096446f45ff9df8..fa439a7fca74619b79c7cccfcf49828e67aee5e0 100644 --- a/MAC/CMakeLists.txt +++ b/MAC/CMakeLists.txt @@ -7,7 +7,7 @@ lofar_add_package(Deployment) # Deployment related functions lofar_add_package(Navigator2) lofar_add_package(MACTools Tools) lofar_add_package(MAC_Services Services) -lofar_add_package(PVSS_Datapoints Deployment/data/PVSS) +lofar_add_package(WinCC_Datapoints Deployment/data/PVSS) lofar_add_package(OTDB_Comps Deployment/data/OTDB) lofar_add_package(StaticMetaData Deployment/data/StaticMetaData) lofar_add_package(WinCC_Services WinCCServices) diff --git a/MAC/Deployment/data/PVSS/CMakeLists.txt b/MAC/Deployment/data/PVSS/CMakeLists.txt index 094c8224339927bd189ac95070ec748b8864f066..8f2bcbc404f062167be4eb607e8b1ff53ac3b4a5 100644 --- a/MAC/Deployment/data/PVSS/CMakeLists.txt +++ b/MAC/Deployment/data/PVSS/CMakeLists.txt @@ -1,6 +1,6 @@ # $Id$ -lofar_package(PVSS_Datapoints 1.0) +lofar_package(WinCC_Datapoints 1.0) add_subdirectory(bin) add_subdirectory(data) diff --git a/MAC/Deployment/data/PVSS/data/PVSSDataPoints.base b/MAC/Deployment/data/PVSS/data/PVSSDataPoints.base index 5ba2a2c379d56b821e60fd00e6e62939d07a4bc0..96495c152a65a0d64c89a30c6bea26ba89347a83 100644 --- a/MAC/Deployment/data/PVSS/data/PVSSDataPoints.base +++ b/MAC/Deployment/data/PVSS/data/PVSSDataPoints.base @@ -32,8 +32,10 @@ Station - M Y LOFAR_PermSW_@ring@_@station@ Cluster - M N LOFAR_PermSW_@cluster@ Node - M Y LOFAR_PermSW_@cluster@_@node@ Daemons - M N LOFAR_PermSW_Daemons -PVSS00pmon - M Y LOFAR_PermSW_Daemons_PVSS00pmon #obsolete in 3.14 -WCCILpmon - M Y LOFAR_PermSW_Daemons_WCCILpmon #replacement for the PVSSpmon in 3.14 +#obsolete in 3.14 +#PVSS00pmon - M Y LOFAR_PermSW_Daemons_PVSS00pmon +#replacement for the PVSSpmon in 3.14 +WCCILpmon - M Y LOFAR_PermSW_Daemons_WCCILpmon LogProcessor - M Y LOFAR_PermSW_Daemons_LogProcessor ServiceBroker - M Y LOFAR_PermSW_Daemons_ServiceBroker SASGateway - M Y LOFAR_PermSW_Daemons_SASGateway @@ -57,8 +59,10 @@ StorageHost SHST C Y LOFAR_PIC_@storagehost@ CEPPermSW - C N LOFAR_PermSW CEPHardwareMonitor CHM C Y LOFAR_PermSW_CEPHardwareMonitor Daemons - C N LOFAR_PermSW_Daemons -PVSS00pmon - C Y LOFAR_PermSW_Daemons_PVSS00pmon #obsolete in 3.14 -WCCILpmon - C Y LOFAR_PermSW_Daemons_WCCILpmon #replacement for the PVSSpmon in 3.14 +#obsolete in 3.14 +#PVSS00pmon - C Y LOFAR_PermSW_Daemons_PVSS00pmon +#replacement for the PVSSpmon in 3.14 +WCCILpmon - C Y LOFAR_PermSW_Daemons_WCCILpmon LogProcessor - C Y LOFAR_PermSW_Daemons_LogProcessor ServiceBroker - C Y LOFAR_PermSW_Daemons_ServiceBroker SoftwareMonitor - C Y LOFAR_PermSW_Daemons_SoftwareMonitor @@ -99,8 +103,10 @@ StnPermSW - S N LOFAR_PermSW Cluster - S N LOFAR_PermSW_@cluster@ Node - S Y LOFAR_PermSW_@cluster@_@node@ Daemons - S N LOFAR_PermSW_Daemons -PVSS00pmon - S Y LOFAR_PermSW_Daemons_PVSS00pmon #obsolete in 3.14 -WCCILpmon - S Y LOFAR_PermSW_Daemons_WCCILpmon #replacement for the PVSSpmon in 3.14 +#obsolete in 3.14 +#PVSS00pmon - S Y LOFAR_PermSW_Daemons_PVSS00pmon +#replacement for the PVSSpmon in 3.14 +WCCILpmon - S Y LOFAR_PermSW_Daemons_WCCILpmon LogProcessor LGP S Y LOFAR_PermSW_Daemons_LogProcessor ServiceBroker - S Y LOFAR_PermSW_Daemons_ServiceBroker SASGateway SGW S Y LOFAR_PermSW_Daemons_SASGateway diff --git a/MAC/Deployment/data/StaticMetaData/CableDelays/IE613-CableDelays.conf b/MAC/Deployment/data/StaticMetaData/CableDelays/IE613-CableDelays.conf new file mode 100644 index 0000000000000000000000000000000000000000..772985418d6624b744caa87572b6c023908f6096 --- /dev/null +++ b/MAC/Deployment/data/StaticMetaData/CableDelays/IE613-CableDelays.conf @@ -0,0 +1,210 @@ +# +# CableDelays.conf IE613 +# +# This file contains for each input of each RCU the delay the length of the cable +# connected to it adds to the signal path. +# +# Lenghts are in meters, delays are in ns. +# +# Note: The first order values are: +# 50m 199.2573 +# 80m 326.9640 +# 85m 342.5133 +# 115m 465.5254 +# 130m 530.6981 +# +# LBL LBH HBA +#RCUnr len delay len delay len delay +#----------------------------------------------------------------------- +0 0 0 115 465.5254 85 342.5133 +1 0 0 115 465.5254 85 342.5133 +2 0 0 115 465.5254 85 342.5133 +3 0 0 115 465.5254 85 342.5133 +4 0 0 115 465.5254 85 342.5133 +5 0 0 115 465.5254 85 342.5133 +6 0 0 115 465.5254 85 342.5133 +7 0 0 115 465.5254 85 342.5133 +8 0 0 85 342.5133 85 342.5133 +9 0 0 85 342.5133 85 342.5133 +10 0 0 85 342.5133 85 342.5133 +11 0 0 85 342.5133 85 342.5133 +12 0 0 85 342.5133 85 342.5133 +13 0 0 85 342.5133 85 342.5133 +14 0 0 85 342.5133 85 342.5133 +15 0 0 85 342.5133 85 342.5133 +16 0 0 115 465.5254 85 342.5133 +17 0 0 115 465.5254 85 342.5133 +18 0 0 115 465.5254 85 342.5133 +19 0 0 115 465.5254 85 342.5133 +20 0 0 115 465.5254 85 342.5133 +21 0 0 115 465.5254 85 342.5133 +22 0 0 115 465.5254 115 465.5254 +23 0 0 115 465.5254 115 465.5254 +24 0 0 115 465.5254 85 342.5133 +25 0 0 115 465.5254 85 342.5133 +26 0 0 115 465.5254 85 342.5133 +27 0 0 115 465.5254 85 342.5133 +28 0 0 85 342.5133 85 342.5133 +29 0 0 85 342.5133 85 342.5133 +30 0 0 85 342.5133 85 342.5133 +31 0 0 85 342.5133 85 342.5133 +32 0 0 85 342.5133 85 342.5133 +33 0 0 85 342.5133 85 342.5133 +34 0 0 115 465.5254 85 342.5133 +35 0 0 115 465.5254 85 342.5133 +36 0 0 85 342.5133 85 342.5133 +37 0 0 85 342.5133 85 342.5133 +38 0 0 85 342.5133 85 342.5133 +39 0 0 85 342.5133 85 342.5133 +40 0 0 115 465.5254 115 465.5254 +41 0 0 115 465.5254 115 465.5254 +42 0 0 115 465.5254 85 342.5133 +43 0 0 115 465.5254 85 342.5133 +44 0 0 115 465.5254 85 342.5133 +45 0 0 115 465.5254 85 342.5133 +46 0 0 115 465.5254 85 342.5133 +47 0 0 115 465.5254 85 342.5133 +48 0 0 115 465.5254 85 342.5133 +49 0 0 115 465.5254 85 342.5133 +50 0 0 115 465.5254 85 342.5133 +51 0 0 115 465.5254 85 342.5133 +52 0 0 115 465.5254 85 342.5133 +53 0 0 115 465.5254 85 342.5133 +54 0 0 115 465.5254 85 342.5133 +55 0 0 115 465.5254 85 342.5133 +56 0 0 85 342.5133 85 342.5133 +57 0 0 85 342.5133 85 342.5133 +58 0 0 85 342.5133 115 465.5254 +59 0 0 85 342.5133 115 465.5254 +60 0 0 115 465.5254 115 465.5254 +61 0 0 115 465.5254 115 465.5254 +62 0 0 115 465.5254 115 465.5254 +63 0 0 115 465.5254 115 465.5254 +64 0 0 85 342.5133 85 342.5133 +65 0 0 85 342.5133 85 342.5133 +66 0 0 85 342.5133 85 342.5133 +67 0 0 85 342.5133 85 342.5133 +68 0 0 85 342.5133 85 342.5133 +69 0 0 85 342.5133 85 342.5133 +70 0 0 85 342.5133 85 342.5133 +71 0 0 85 342.5133 85 342.5133 +72 0 0 115 465.5254 85 342.5133 +73 0 0 115 465.5254 85 342.5133 +74 0 0 85 342.5133 85 342.5133 +75 0 0 85 342.5133 85 342.5133 +76 0 0 115 465.5254 85 342.5133 +77 0 0 115 465.5254 85 342.5133 +78 0 0 85 342.5133 115 465.5254 +79 0 0 85 342.5133 115 465.5254 +80 0 0 115 465.5254 115 465.5254 +81 0 0 115 465.5254 115 465.5254 +82 0 0 115 465.5254 115 465.5254 +83 0 0 115 465.5254 115 465.5254 +84 0 0 115 465.5254 115 465.5254 +85 0 0 115 465.5254 115 465.5254 +86 0 0 115 465.5254 85 342.5133 +87 0 0 115 465.5254 85 342.5133 +88 0 0 115 465.5254 85 342.5133 +89 0 0 115 465.5254 85 342.5133 +90 0 0 115 465.5254 85 342.5133 +91 0 0 115 465.5254 85 342.5133 +92 0 0 115 465.5254 85 342.5133 +93 0 0 115 465.5254 85 342.5133 +94 0 0 115 465.5254 85 342.5133 +95 0 0 115 465.5254 85 342.5133 +96 0 0 85 342.5133 115 465.5254 +97 0 0 85 342.5133 115 465.5254 +98 0 0 115 465.5254 115 465.5254 +99 0 0 115 465.5254 115 465.5254 +100 0 0 85 342.5133 115 465.5254 +101 0 0 85 342.5133 115 465.5254 +102 0 0 85 342.5133 115 465.5254 +103 0 0 85 342.5133 115 465.5254 +104 0 0 115 465.5254 130 530.6981 +105 0 0 115 465.5254 130 530.6981 +106 0 0 115 465.5254 85 342.5133 +107 0 0 115 465.5254 85 342.5133 +108 0 0 85 342.5133 85 342.5133 +109 0 0 85 342.5133 85 342.5133 +110 0 0 115 465.5254 85 342.5133 +111 0 0 115 465.5254 85 342.5133 +112 0 0 115 465.5254 85 342.5133 +113 0 0 115 465.5254 85 342.5133 +114 0 0 115 465.5254 85 342.5133 +115 0 0 115 465.5254 85 342.5133 +116 0 0 115 465.5254 115 465.5254 +117 0 0 115 465.5254 115 465.5254 +118 0 0 85 342.5133 115 465.5254 +119 0 0 85 342.5133 115 465.5254 +120 0 0 115 465.5254 115 465.5254 +121 0 0 115 465.5254 115 465.5254 +122 0 0 115 465.5254 115 465.5254 +123 0 0 115 465.5254 115 465.5254 +124 0 0 85 342.5133 130 530.6981 +125 0 0 85 342.5133 130 530.6981 +126 0 0 115 465.5254 130 530.6981 +127 0 0 115 465.5254 130 530.6981 +128 0 0 85 342.5133 85 342.5133 +129 0 0 85 342.5133 85 342.5133 +130 0 0 115 465.5254 85 342.5133 +131 0 0 115 465.5254 85 342.5133 +132 0 0 85 342.5133 85 342.5133 +133 0 0 85 342.5133 85 342.5133 +134 0 0 85 342.5133 85 342.5133 +135 0 0 85 342.5133 85 342.5133 +136 0 0 115 465.5254 115 465.5254 +137 0 0 115 465.5254 115 465.5254 +138 0 0 115 465.5254 115 465.5254 +139 0 0 115 465.5254 115 465.5254 +140 0 0 115 465.5254 115 465.5254 +141 0 0 115 465.5254 115 465.5254 +142 0 0 115 465.5254 115 465.5254 +143 0 0 115 465.5254 115 465.5254 +144 0 0 115 465.5254 130 530.6981 +145 0 0 115 465.5254 130 530.6981 +146 0 0 85 342.5133 130 530.6981 +147 0 0 85 342.5133 130 530.6981 +148 0 0 85 342.5133 130 530.6981 +149 0 0 85 342.5133 130 530.6981 +150 0 0 85 342.5133 85 342.5133 +151 0 0 85 342.5133 85 342.5133 +152 0 0 115 465.5254 85 342.5133 +153 0 0 115 465.5254 85 342.5133 +154 0 0 115 465.5254 115 465.5254 +155 0 0 115 465.5254 115 465.5254 +156 0 0 115 465.5254 115 465.5254 +157 0 0 115 465.5254 115 465.5254 +158 0 0 85 342.5133 115 465.5254 +159 0 0 85 342.5133 115 465.5254 +160 0 0 85 342.5133 115 465.5254 +161 0 0 85 342.5133 115 465.5254 +162 0 0 85 342.5133 115 465.5254 +163 0 0 85 342.5133 115 465.5254 +164 0 0 85 342.5133 130 530.6981 +165 0 0 85 342.5133 130 530.6981 +166 0 0 115 465.5254 130 530.6981 +167 0 0 115 465.5254 130 530.6981 +168 0 0 115 465.5254 85 342.5133 +169 0 0 115 465.5254 85 342.5133 +170 0 0 115 465.5254 115 465.5254 +171 0 0 115 465.5254 115 465.5254 +172 0 0 85 342.5133 115 465.5254 +173 0 0 85 342.5133 115 465.5254 +174 0 0 85 342.5133 115 465.5254 +175 0 0 85 342.5133 115 465.5254 +176 0 0 115 465.5254 115 465.5254 +177 0 0 115 465.5254 115 465.5254 +178 0 0 85 342.5133 115 465.5254 +179 0 0 85 342.5133 115 465.5254 +180 0 0 115 465.5254 130 530.6981 +181 0 0 115 465.5254 130 530.6981 +182 0 0 115 465.5254 115 465.5254 +183 0 0 115 465.5254 115 465.5254 +184 0 0 85 342.5133 115 465.5254 +185 0 0 115 465.5254 115 465.5254 +186 0 0 115 465.5254 115 465.5254 +187 0 0 115 465.5254 115 465.5254 +188 0 0 115 465.5254 115 465.5254 +189 0 0 115 465.5254 115 465.5254 +190 0 0 85 342.5133 130 530.6981 +191 0 0 85 342.5133 130 530.6981 diff --git a/MAC/Navigator2/colorDB/CMakeLists.txt b/MAC/Navigator2/colorDB/CMakeLists.txt index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7ae487b5f72db398a14f8d9484d216c209811fbd 100644 --- a/MAC/Navigator2/colorDB/CMakeLists.txt +++ b/MAC/Navigator2/colorDB/CMakeLists.txt @@ -0,0 +1,5 @@ +# $Id: CMakeLists.txt 29470 2014-06-10 10:11:41Z coolen $ + +install(FILES + Lofar\ colors +DESTINATION pvss/colorDB) diff --git a/RTCP/Cobalt/CoInterface/src/BudgetTimer.cc b/RTCP/Cobalt/CoInterface/src/BudgetTimer.cc index 4d57b3333831afbc59dd81b3f24d971afd5e712b..89ba3fa92e158b002d78b6c049c04f7d6865f1f3 100644 --- a/RTCP/Cobalt/CoInterface/src/BudgetTimer.cc +++ b/RTCP/Cobalt/CoInterface/src/BudgetTimer.cc @@ -66,9 +66,8 @@ namespace LOFAR { if (budget > 0.0 && elapsed > budget) { const double realTimePerc = 100.0 * elapsed / budget; - if (elapsed > 2 * budget) - LOG_ERROR_STR("Run-time budget exceeded: " << itsName << " ran at " << realTimePerc << "% (took " << elapsed << " s, budget is " << budget << " s)"); + LOG_WARN_STR("Run-time budget exceeded: " << itsName << " ran at " << realTimePerc << "% (took " << elapsed << " s, budget is " << budget << " s)"); else LOG_DEBUG_STR("Run-time budget exceeded: " << itsName << " ran at " << realTimePerc << "% (took " << elapsed << " s, budget is " << budget << " s)"); } diff --git a/RTCP/Cobalt/CoInterface/src/StreamableData.h b/RTCP/Cobalt/CoInterface/src/StreamableData.h index 5fe7ec3e223452ab75a27588744030f78770be4b..08c416dfbcddd86bea4a32ac332b34eeeb837c2c 100644 --- a/RTCP/Cobalt/CoInterface/src/StreamableData.h +++ b/RTCP/Cobalt/CoInterface/src/StreamableData.h @@ -90,6 +90,12 @@ namespace LOFAR { } + // Fraction of data that was lost due to output bottlenecks + virtual double outputLossFraction() const + { + return 0.0; + } + uint32_t peerMagicNumber; /// magic number received from peer protected: diff --git a/RTCP/Cobalt/CoInterface/src/TABTranspose.cc b/RTCP/Cobalt/CoInterface/src/TABTranspose.cc index a8bec0461f793c7ef9863845c9b10c69ed1494fd..3b6fbfea096983c1fd9edbda0e1f400a98fe3a35 100644 --- a/RTCP/Cobalt/CoInterface/src/TABTranspose.cc +++ b/RTCP/Cobalt/CoInterface/src/TABTranspose.cc @@ -212,6 +212,14 @@ void Block::write( BeamformedData &output ) { } } + // Update flags + for (size_t sb = 0; sb < subbandCache.size(); sb++) { + output.flags[sb].reset(); + + if (!subbandCache[sb]) + output.flags[sb].include(0, nrSamples); + } + // Report summary if (complete()) LOG_DEBUG_STR("[block " << blockIdx << " stream " << fileIdx << "] [Block] Written " << (nrSubbands - nrSubbandsLeft) << " subbands, lost " << nrSubbandsLeft << " subbands."); @@ -227,9 +235,9 @@ bool Block::complete() const { // The BlockCollector collects blocks from different rtcp processes for a TAB. // More precisely, we have one BlockCollector per file (i.e. part). -BlockCollector::BlockCollector( Pool<BeamformedData> &outputPool, size_t fileIdx, size_t nrSubbands, size_t nrChannels, size_t nrSamples, size_t nrBlocks, size_t maxBlocksInFlight ) +BlockCollector::BlockCollector( Pool<BeamformedData> &outputPool, size_t fileIdx, size_t nrSubbands, size_t nrChannels, size_t nrSamples, size_t nrBlocks, size_t maxBlocksInFlight, const std::string &logPrefix ) : - logPrefix(str(format("[stream %u] [BlockCollector] ") % fileIdx)), + logPrefix(logPrefix + "[BlockCollector] "), nrFullBlocksLost(0), nrBlockSubbandsLost(0), @@ -374,11 +382,11 @@ void BlockCollector::finish() { const float tooLatePerc = 100.0 * nrBlockSubbandsTooLate / nrSubbands / nrBlocks; if (didNotReceivePerc > 0) - LOG_ERROR_STR(logPrefix << "Did not receive " << didNotReceivePerc << "% of the data"); + LOG_WARN_STR(logPrefix << "Did not receive " << didNotReceivePerc << "% of the data"); if (lostPerc > 0) LOG_ERROR_STR(logPrefix << "I lost " << lostPerc << "% of the data"); if (didNotSendPerc > 0) - LOG_ERROR_STR(logPrefix << "Did not send " << didNotSendPerc << "% of the data"); + LOG_WARN_STR(logPrefix << "Did not send " << didNotSendPerc << "% of the data"); if (tooLatePerc > 0) LOG_ERROR_STR(logPrefix << "Received " << tooLatePerc << "% of the data too late. Consider increasing maxBlocksInFlight."); } @@ -635,8 +643,8 @@ MultiSender::MultiSender( const HostMap &hostMap, const Parset &parset, if(find(hosts.begin(), hosts.end(), i->second) == hosts.end()) hosts.push_back(i->second); - // each file gets a drop_rate counter - drop_rates[i->first] = RunningStatistics("%"); + // each host gets a drop_rate counter + drop_rates[i->second] = RunningStatistics("%"); } for (vector<struct Host>::const_iterator i = hosts.begin(); i != hosts.end(); ++i) { @@ -647,17 +655,32 @@ MultiSender::MultiSender( const HostMap &hostMap, const Parset &parset, MultiSender::~MultiSender() { - LOG_DEBUG_STR("MultiSender: realTime = " << itsParset.settings.realTime << ", maxRetentionTime = " << maxRetentionTime); - for (HostMap::const_iterator i = hostMap.begin(); i != hostMap.end(); ++i) { - const float didNotReceivePerc = 0.0; // we receive everythnig - const float didNotSendPerc = drop_rates.at(i->first).mean(); - const float lostPerc = didNotSendPerc - didNotReceivePerc; + // at this point, process() has finished, either gracefully or with an exception + + // drain queues in case process() did not + for (std::map<Host, QueuePtr>::iterator i = queues.begin(); i != queues.end(); ++i) { + QueuePtr &queue = i->second; + + while (!queue->empty()) { + (void)queue->remove(); + + // this is loss, obviously + drop_rates.at(i->first).push(100.0); + } + } + + // report statistics + for (std::map<Host, RunningStatistics>::const_iterator i = drop_rates.begin(); i != drop_rates.end(); ++i) { + const float didNotReceivePerc = 0.0; // no output loss possible so far + const float lostPerc = i->second.mean(); + const float didNotSendPerc = didNotReceivePerc + lostPerc; if (lostPerc > 0) - LOG_ERROR_STR("[stream " << i->first << "] [BeamFormer] I lost " << lostPerc << "% of the data to " << i->second.hostName); + LOG_ERROR_STR("[BeamFormer] I lost " << lostPerc << "% of the data to " << i->first.hostName); if (didNotSendPerc > 0) - LOG_ERROR_STR("[stream " << i->first << "] [BeamFormer] Did not send " << didNotSendPerc << "% of the data to " << i->second.hostName); + LOG_WARN_STR("[BeamFormer] Did not send " << lostPerc << "% of the data to " << i->first.hostName); } + } @@ -685,7 +708,7 @@ void MultiSender::process( OMPThreadSet *threadSet ) LOG_DEBUG_STR(logPrefix << "Connected"); - SmartPtr< Queue< SmartPtr<struct Subband> > > &queue = queues.at(host); + QueuePtr &queue = queues.at(host); SmartPtr<struct Subband> subband; NSTimer sendTimer(str(format("Send Subband to %s") % host.hostName), true, true); @@ -716,13 +739,13 @@ bool MultiSender::append( SmartPtr<struct Subband> &subband ) const size_t fileIdx = subband->id.fileIdx; const struct Host &host = hostMap.at(fileIdx); - SmartPtr< Queue< SmartPtr<struct Subband> > > &queue = queues.at(host); + QueuePtr &queue = queues.at(host); bool dropped = false; // If oldest packet in queue is too old, drop it in lieu of this new one if (itsParset.settings.realTime && TimeSpec::now() - queue->oldest() > maxRetentionTime) { - drop_rates.at(fileIdx).push(100.0); + drop_rates.at(host).push(100.0); // remove oldest item SmartPtr<struct Subband> subband = queue->remove(); @@ -732,7 +755,7 @@ bool MultiSender::append( SmartPtr<struct Subband> &subband ) dropped = true; } else { - drop_rates.at(fileIdx).push(0.0); + drop_rates.at(host).push(0.0); } // Append the data to the respective queue diff --git a/RTCP/Cobalt/CoInterface/src/TABTranspose.h b/RTCP/Cobalt/CoInterface/src/TABTranspose.h index ef33a0d4d21a3ee85fe570694f589d115794d699..46f9466d34640537ccaebf814abb9f5fb7366b8b 100644 --- a/RTCP/Cobalt/CoInterface/src/TABTranspose.h +++ b/RTCP/Cobalt/CoInterface/src/TABTranspose.h @@ -67,7 +67,33 @@ namespace LOFAR std::ostream &operator<<(std::ostream &str, const Subband::BlockID &id); - typedef SampleData<float, 3> BeamformedData; // [nrSubbands][nrChannels][nrSamples] + class BeamformedData: public SampleData<float, 3, 1> { + public: + BeamformedData(size_t nrSubbands, size_t nrChannels, size_t nrSamples, Allocator &allocator = heapAllocator): + // data: [nrSubbands][nrChannels][nrSamples] + // flags: [nrSubbands], and encodes *output data loss*, not flagged input + SampleData<float, 3, 1>(boost::extents[nrSamples][nrSubbands][nrChannels], + boost::extents[nrSubbands], + allocator), + nrSubbands(nrSubbands), + nrChannels(nrChannels), + nrSamples(nrSamples) + { + } + + // fraction of data that is lost due to output bottlenecks + virtual double outputLossFraction() const { + size_t nrFlaggedSamples = 0; + + for (size_t i = 0; i < flags.shape()[0]; i++) + nrFlaggedSamples += flags[i].count(); + + return 1.0 * nrFlaggedSamples / (nrSubbands * nrSamples); + } + + private: + const size_t nrSubbands, nrChannels, nrSamples; + }; /* * A block of data, representing for one time slice all @@ -156,7 +182,7 @@ namespace LOFAR * maxBlocksInFlight: the maximum number of blocks to process in * parallel (or 0 for no limit). */ - BlockCollector( Pool<BeamformedData> &outputPool, size_t fileIdx, size_t nrSubbands, size_t nrChannels, size_t nrSamples, size_t nrBlocks = 0, size_t maxBlocksInFlight = 0 ); + BlockCollector( Pool<BeamformedData> &outputPool, size_t fileIdx, size_t nrSubbands, size_t nrChannels, size_t nrSamples, size_t nrBlocks = 0, size_t maxBlocksInFlight = 0, const std::string &logPrefix = "" ); ~BlockCollector(); @@ -390,7 +416,7 @@ namespace LOFAR const Parset &itsParset; - std::map<size_t, RunningStatistics> drop_rates; // [fileIdx] + std::map<Host, RunningStatistics> drop_rates; // MultiSender has a queue per host it sends to. If it appends an element // to a queue, it will discard the head if it is older than maxRententionTime. @@ -406,7 +432,8 @@ namespace LOFAR std::vector<struct Host> hosts; // A queue for data to be sent to each host - std::map<struct Host, SmartPtr< Queue< SmartPtr<struct Subband> > > > queues; + typedef SmartPtr< Queue< SmartPtr<struct Subband> > > QueuePtr; + std::map<struct Host, QueuePtr> queues; }; } // namespace TABTranspose diff --git a/RTCP/Cobalt/CoInterface/test/tTABTranspose.cc b/RTCP/Cobalt/CoInterface/test/tTABTranspose.cc index d343f370bcbbf5d714f36b2119edff1973ddca19..170110c90c13db8629bb2e35c0cdec50a3e67a77 100644 --- a/RTCP/Cobalt/CoInterface/test/tTABTranspose.cc +++ b/RTCP/Cobalt/CoInterface/test/tTABTranspose.cc @@ -114,9 +114,7 @@ SUITE(Block) { block.addSubband(subband); } - BeamformedData output( - boost::extents[nrSamples][nrSubbands][nrChannels], - boost::extents[nrSubbands][nrChannels]); + BeamformedData output(nrSubbands, nrChannels, nrSamples); NSTimer transposeTimer(str(format("Block::write for %u subbands, %u channels, %u samples") % nrSubbands % nrChannels % nrSamples), true, true); transposeTimer.start(); @@ -143,9 +141,7 @@ struct Fixture { ctr(outputPool, 0, nrSubbands, nrChannels, nrSamples) { for (size_t i = 0; i < nrBlocks; ++i) { - outputPool.free.append(new BeamformedData( - boost::extents[nrSamples][nrSubbands][nrChannels], - boost::extents[nrSubbands][nrChannels]), false); + outputPool.free.append(new BeamformedData(nrSubbands, nrChannels, nrSamples), false); } } }; @@ -405,9 +401,7 @@ SUITE(SendReceive) { for (size_t i = 0; i < nrTABs; ++i) { outputPools[i] = new Pool<BeamformedData>(str(format("OneToOne::outputPool[%u]") % i), true); for (size_t b = 0; b < nrBlocks; ++b) { - outputPools[i]->free.append(new BeamformedData( - boost::extents[nrSamples][nrSubbands][nrChannels], - boost::extents[nrSubbands][nrChannels]), false); + outputPools[i]->free.append(new BeamformedData(nrSubbands, nrChannels, nrSamples), false); } collectors[i] = new BlockCollector(*outputPools[i], i, nrSubbands, nrChannels, nrSamples); @@ -593,9 +587,7 @@ SUITE(MultiReceiver) { outputPools[t] = new Pool<BeamformedData>(str(format("MultiReceiver::Transpose::outputPool[%u]") % t), true); for (size_t i = 0; i < nrBlocks; ++i) { - outputPools[t]->free.append(new BeamformedData( - boost::extents[nrSamples][nrSubbands][nrChannels], - boost::extents[nrSubbands][nrChannels]), false); + outputPools[t]->free.append(new BeamformedData(nrSubbands, nrChannels, nrSamples), false); } collectors[FILEIDX(t)] = new BlockCollector(*outputPools[t], FILEIDX(t), nrSubbands, nrChannels, nrSamples, nrBlocks); } diff --git a/RTCP/Cobalt/GPUProc/doc/data-loss.txt b/RTCP/Cobalt/GPUProc/doc/data-loss.txt new file mode 100644 index 0000000000000000000000000000000000000000..2c4604effe1f600a76df72f2b5d1bf53ede3a5b5 --- /dev/null +++ b/RTCP/Cobalt/GPUProc/doc/data-loss.txt @@ -0,0 +1,158 @@ +This document describes how COBALT logs and processes data loss. Two forms of loss can be distinguished: input data loss and output data loss. + +--------------------- +Input data loss +--------------------- + +The data path for station input is: + + station RSP board --> Ethernet --> COBALT server + +Total input loss occurs when: + + * The station does not emit the datagrams from the RSP boards. See + * "rspctl --datastream" on the station's LCU to see if the data stream is enabled + + * The station does not send the datagrams to the UDP port COBALT listens on: + * $LOFARROOT/etc/parset-additions.d/default/StationStreams.parset contains the addresses COBALT listens to + * $LOFARROOT/etc/RSPDriver.conf (on the station) contains the addresses the station sends to + * MAC, IP and port numbers need to match. Note that each station sends to the following ports for easy identification: + + 16093 + ||_|\_ 1-digit bord number (0..3, and 6..9 for HBA1) + | \___ 3-digit station number + \_____ fixed prefix + + * As root on COBALT, run "tcpdump -i <interface> udp -c 100", and check if the packets are received and correctly addressed. + + * The network drops the datagrams due to routing issues. + +Fractional or total input loss occurs when: + + * The network drops the datagrams due to throughput issues. + + * The COBALT server IP stack drops the datagrams: + * This log line indicates that the packets were received but not processed. + + >>> WARN RTCP.Cobalt.GPUProc - Kernel dropped XXX UDP packets + + - This counter indicates how many UDP packets were listened for but did not reach the application in time. + - This counter is node-specific and is thus reported in pairs as every host runs two instances. + - Each station emits ~50k packets per second, so judge the dropped counter accordingly. + - Possible causes: + * The COBALT server CPUs are overloaded. Run "top" to see if a specific core is loaded >95%. + * COBALT froze, for example due to InfiniBand errors. In that case, the above line is the only one being printed. + * OS scheduling inefficiencies occasionally cause the above log line to appear. + + * The packets are received by COBALT but are not usable in the observation: + * The following log line indicates the packet receive rate and how many packets were discarded: + + >>> INFO RTCP.Cobalt.InputProc - [station CS005LBA] [board 0] [PacketReader] 12207.1 pps: received 131072 packets: 0 bad timestamps, 0 bad clock/bitmode, 1 payload errors, 0 otherwise bad packets + + - "bad timestamps" means the packet has timestamp -1 (0xFFFFFFFF), indicating problems with the station clock. + - "bad clock/bitmode" means the packet does not have the same clock (200/160) or bitmode (16/8/4) as the observation. + - "payload error" means the packet is marked as incomplete by the station. + - "otherwise bad" means the packet header is corrupted. + +Flagging +--------------------- + +Missing and corrupted/unacceptable station input results in those data being flagged. As we employ a conservative flagging strategy, the amount of data flagged is typically a lot higher than the amount of data not received correctly. + +--------------------- +Output data loss +--------------------- + +COBALT strives to write output data regardless of what input actually arrived. The input is collected into /blocks/ of typically ~1s. All blocks travel along the path: + + Ethernet -> CPU (GPUProc) -> InfiniBand -> CPU (GPUProc) -> GPU -> CPU (GPUProc) + +after which the data are forwarded to the storage nodes (OutputProc). From that point on, data can be dropped if the system cannot sustain the data rates involved. Due to the way correlated (interferometry) and beamformed data are collected, we have to distinguish these two cases. + +// NOTES for log-line interpretation: // + + * Each log line is printed as a summary at the end of the observation + * Lines are only printed if any loss occurred. + * Each processing step logs three metrics: + - "WARN - Did not receive XX% of the data ...", indicates how much data arrived at that step. + - "ERROR - I lost XX% of the data ...", indicates how much data was dropped in THIS step. + - "WARN - Did not send XX% of the data ...", indicates how much data was forwarded to the next step. + +Correlated data loss +--------------------- + +Each block represents an integration period of one subband when emitted from GPUProc, typically ~1s in size. Observations consist of at most 488 subbands in the common 8-bit mode (244 in 16-bit mode). The blocks of each subband are sent to the storage node that was assigned to store it. + + >>> ERROR RTCP.Cobalt.GPUProc - [Correlator] I lost 5.1234% of the data for subband 3 to cpu05.cep4.control.lofar + >>> WARN RTCP.Cobalt.GPUProc - [Correlator] Did not send 5.1234% of the data for subband 3 to cpu05.cep4.control.lofar + + The real-time processor produces all blocks, but could not send all of them over the network to the storage node. Reasons include: + * The network cannot sustain the required throughput. + * The receiving storage node or OutputProc instance crashed. + * The receiving storage node or OutputProc instance started too late. + * The receiving storage node cannot sustain the required throughput to disk. + + In the Correlated pipeline, this is the ONLY place in which loss can occur (barring OS/system errors). If the chain downstream (network, + OutputProc) cannot sustain the required rate, this is the place data is dropped. To analyse where the actual bottleneck lies, one needs + to look at the timers (see below). + + >>> WARN RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [InputThread] Did not receive 5.1234% of the data + >>> WARN RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [InputThread] Did not send 5.1234% of the data + + The input side of OutputProc also reports what it does not receive (and thus not forward), but cannot lose data. + + >>> WARN RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [SubbandOutputThread] Did not receive 5.1234% of the data + >>> ERROR RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [SubbandOutputThread] I lost 1.0000% of the data + >>> WARN RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [SubbandOutputThread] Did not send 6.1234% of the data + + In rare cases, OutputProc itself drops data: + * If the target disk is full. + * If writing data to the target disk fails (file-system errors, etc). + + >>> INFO RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [SubbandOutputThread] Total output data loss is 0.0000%. + >>> ERROR RTCP.Cobalt.OutputProc - [stream 3 file L123456_SAP000_SB003.MS] [SubbandOutputThread] Total output data loss is 6.1234%. + + The end-to-end data loss is always printed by OutputProc, at INFO level if there is no loss. Note that this line is NOT printed + if OutputProc did not start or crashed. + + +Beam-formed data loss +--------------------- + +Each block represents an integration period of one subband when emitted from GPUProc, typically ~1s in size. Each TAB generates one block per subband. These blocks are subsequently transposed over the network to the storage nodes. Each storage node process (OutputProc) receives blocks for all the subbands that are part of the TABs that are to be stored on that node. Due to this additional complexity, loss can occur in more places than forr correlated data. + + >>> ERROR RTCP.Cobalt.CoInterface - [BeamFormer] I lost 5.1234% of the data to cpu05.cep4.control.lofar + >>> WARN RTCP.Cobalt.CoInterface - [BeamFormer] Did not send 5.1234% of the data to cpu05.cep4.control.lofar + + This is the amount of data that could not be sent to a specific storage node. As multiple subbands and TABs share the same end points + in GPUProc and OutputProc, only the average loss is printed from GPUProc to each storage node. The reasons for loss are the same as + for correlated data. + + >>> WARN RTCP.Cobalt.CoInterface - [BlockCollector] Did not receive 5.1234% of the data + >>> ERROR RTCP.Cobalt.CoInterface - [BlockCollector] I lost 1.0000% of the data + >>> WARN RTCP.Cobalt.CoInterface - [BlockCollector] Did not send 6.1234% of the data + + These lines represent the receiving side in OutputProc, which collect for each TAB all subbands from (typically) all COBALT GPUProc + processes. As there is a fixed buffer, some subband data could arrive too late or not at all, in which case it is lost here. + + Thus, loss from this stage onwards indicates either all data is lost for a block, or some subbands are. Both are accumulated into + a single loss percentage. + + >>> ERROR RTCP.Cobalt.CoInterface - [BlockCollector] Received 0.500% of the data too late. Consider increasing maxBlocksInFlight. + + An additional hint printed by OutputProc indicating that the network has throughput issues which could be mitigated with + bigger buffers. The reported loss is already included in other figures. + + >>> WARN RTCP.Cobalt.OutputProc - [stream 3 file L123456_S000_B003_P000.h5] [TABOutputThread] Did not receive 5.1234% of the data + >>> ERROR RTCP.Cobalt.OutputProc - [stream 3 file L123456_S000_B003_P000.h5] [TABOutputThread] I lost 1.0000% of the data + >>> WARN RTCP.Cobalt.OutputProc - [stream 3 file L123456_S000_B003_P000.h5] [TABOutputThread] Did not send 6.1234% of the data + + In rare cases, the writer thread to disk drops data: + * If the target disk is full. + * If writing data to the target disk fails (file-system errors, etc). + + >>> INFO RTCP.Cobalt.OutputProc - [stream 3 file L123456_S000_B003_P000.h5] [TABOutputThread] Total output data loss is 0.0000%. + >>> ERROR RTCP.Cobalt.OutputProc - [stream 3 file L123456_S000_B003_P000.hS] [TABOutputThread] Total output data loss is 6.1234%. + + The end-to-end data loss is always printed by OutputProc, at INFO level if there is no loss. Note that this line is NOT printed + if OutputProc did not start or crashed. diff --git a/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/StationCalibration.parset b/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/StationCalibration.parset index 8fe274086055b3bbf4f5112380027872f0339bff..3bfba042bcca70dceb4d083410ffe997a26e248f 100644 --- a/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/StationCalibration.parset +++ b/RTCP/Cobalt/GPUProc/etc/parset-additions.d/default/StationCalibration.parset @@ -4806,3 +4806,1475 @@ PIC.Core.UK608HBA.HBA_DUAL_INNER.HBA_210_250.phase0.X = 0.000000e+00 PIC.Core.UK608HBA.HBA_DUAL_INNER.HBA_210_250.phase0.Y = 0.000000e+00 PIC.Core.UK608HBA.HBA_DUAL_INNER.HBA_210_250.delay.X = 0.000000e+00 PIC.Core.UK608HBA.HBA_DUAL_INNER.HBA_210_250.delay.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 4.674852e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 4.674852e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 4.674852e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 4.674852e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 6.895581e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 6.895581e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 6.895581e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 6.895581e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 5.490185e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 5.490185e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 5.490185e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 5.490185e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 6.471039e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 6.471039e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 6.471039e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 6.471039e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 7.121630e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 7.121630e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 7.121630e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 7.121630e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 6.466862e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 6.466862e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 6.466862e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 6.466862e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 6.495400e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 6.495400e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 6.495400e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 6.495400e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 7.488310e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 7.488310e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 7.488310e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 7.488310e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 8.708511e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 8.708511e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 8.708511e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 8.708511e-06 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.534011e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.534011e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.534011e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.534011e-05 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 5.978842e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 5.978842e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 5.978842e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 5.978842e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 4.573567e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 4.573567e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 4.573567e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 4.573567e-06 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.612964e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.612964e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.612964e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.612964e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.687941e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.687941e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.687941e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.687941e-05 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 9.644413e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 9.644413e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 9.644413e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 9.644413e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 6.283419e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 6.283419e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 6.283419e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 6.283419e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 8.475084e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 8.475084e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 8.475084e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 8.475084e-06 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.507351e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.507351e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.507351e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.507351e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 3.541774e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 3.541774e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 3.541774e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 3.541774e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.737889e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.737889e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.737889e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.737889e-05 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 7.619549e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 7.619549e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 7.619549e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 7.619549e-06 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.224991e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.224991e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.224991e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.224991e-05 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 7.852323e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 7.852323e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 7.852323e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 7.852323e-06 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 1.651265e-05 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_EVEN.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 4.674852e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 4.674852e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 4.674852e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 4.675295e-06 +PIC.Core.CS001LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 4.674852e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 6.895581e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 6.895581e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 6.895581e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 6.895039e-06 +PIC.Core.CS002LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 6.895581e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 5.490185e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 5.490185e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 5.490185e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 5.490480e-06 +PIC.Core.CS003LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 5.490185e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 6.471039e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 6.471039e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 6.471039e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 6.470439e-06 +PIC.Core.CS004LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 6.471039e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 7.121630e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 7.121630e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 7.121630e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 7.121005e-06 +PIC.Core.CS005LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 7.121630e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 6.466862e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 6.466862e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 6.466862e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 6.466453e-06 +PIC.Core.CS006LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 6.466862e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 6.495400e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 6.495400e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 6.495400e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 6.495847e-06 +PIC.Core.CS007LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 6.495400e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 7.488310e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 7.488310e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 7.488310e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 7.487948e-06 +PIC.Core.CS011LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 7.488310e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 8.708511e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 8.708511e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 8.708511e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 8.708485e-06 +PIC.Core.CS013LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 8.708511e-06 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.534011e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.534011e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.534011e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.534158e-05 +PIC.Core.CS017LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.534011e-05 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 5.978842e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 5.978842e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 5.978842e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 5.978107e-06 +PIC.Core.CS021LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 5.978842e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 4.573567e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 4.573567e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 4.573567e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 4.574559e-06 +PIC.Core.CS024LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 4.573567e-06 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.612964e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.612964e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.612964e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.612922e-05 +PIC.Core.CS026LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.612964e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.687941e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.687941e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.687941e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.687817e-05 +PIC.Core.CS028LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.687941e-05 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 9.644413e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 9.644413e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 9.644413e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 9.644541e-06 +PIC.Core.CS030LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 9.644413e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 6.283419e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 6.283419e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 6.283419e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 6.284210e-06 +PIC.Core.CS031LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 6.283419e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 8.475084e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 8.475084e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 8.475084e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 8.475112e-06 +PIC.Core.CS032LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 8.475084e-06 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.507351e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.507351e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.507351e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.507383e-05 +PIC.Core.CS101LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.507351e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 3.541774e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 3.541774e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 3.541774e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 3.541826e-05 +PIC.Core.CS103LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 3.541774e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.737889e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.737889e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.737889e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.737916e-05 +PIC.Core.CS201LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.737889e-05 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 7.619549e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 7.619549e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 7.619549e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 7.618883e-06 +PIC.Core.CS301LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 7.619549e-06 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.224991e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.224991e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.224991e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.225001e-05 +PIC.Core.CS302LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.224991e-05 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 7.852323e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 7.852323e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 7.852323e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 7.852150e-06 +PIC.Core.CS401LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 7.852323e-06 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 1.651265e-05 +PIC.Core.CS501LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 1.651265e-05 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS106LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS205LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS208LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS210LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS305LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS306LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS307LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS310LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS406LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS407LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS409LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS503LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS508LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.RS509LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE601LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE602LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE603LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE604LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.DE605LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.FR606LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.SE607LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_70.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_70.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_70.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_70.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_70.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_70.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_90.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_90.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_10_90.delay.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_90.phase0.Y = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_90.delay.X = 0.000000e+00 +PIC.Core.UK608LBA.LBA_SPARSE_ODD.LBA_30_90.delay.Y = 0.000000e+00 diff --git a/RTCP/Cobalt/GPUProc/src/cuda/Pipelines/Pipeline.cc b/RTCP/Cobalt/GPUProc/src/cuda/Pipelines/Pipeline.cc index 67e24f2d7b520a7a1c15436d2138e7743b5c1664..9d8292a03e51769e8d36c7111cd78e5a10d616e8 100644 --- a/RTCP/Cobalt/GPUProc/src/cuda/Pipelines/Pipeline.cc +++ b/RTCP/Cobalt/GPUProc/src/cuda/Pipelines/Pipeline.cc @@ -786,7 +786,6 @@ namespace LOFAR else LOG_DEBUG_STR("[" << id << "] Done"); } - // report statistics if (ps.settings.correlator.enabled) { const float didNotReceivePerc = 0.0; // no output loss possible so far @@ -794,21 +793,13 @@ namespace LOFAR const float lostPerc = didNotSendPerc - didNotReceivePerc; if (lostPerc > 0) - LOG_ERROR_STR("[Correlator] I lost " << lostPerc << "% of the data for stream " << globalSubbandIdx << " to " << ps.settings.correlator.files[globalSubbandIdx].location.host); + LOG_ERROR_STR("[Correlator] I lost " << lostPerc << "% of the data for subband " << globalSubbandIdx << " to " << ps.settings.correlator.files[globalSubbandIdx].location.host); if (didNotSendPerc > 0) - LOG_ERROR_STR("[Correlator] Did not send " << didNotSendPerc << "% of the data for stream " << globalSubbandIdx << " to " << ps.settings.correlator.files[globalSubbandIdx].location.host); + LOG_WARN_STR("[Correlator] Did not send " << didNotSendPerc << "% of the data for subband " << globalSubbandIdx << " to " << ps.settings.correlator.files[globalSubbandIdx].location.host); } - if (ps.settings.beamFormer.enabled) { - const float didNotReceivePerc = 0.0; // no output loss possible so far - const float didNotSendPerc = 100.0 * beamFormerLoss.blocksDropped / ps.settings.nrBlocks() / multiSender.nrFiles(); - const float lostPerc = didNotSendPerc - didNotReceivePerc; - - if (lostPerc > 0) - LOG_ERROR_STR("[BeamFormer] I lost " << lostPerc << "% of the data of subband " << globalSubbandIdx); - if (didNotSendPerc > 0) - LOG_ERROR_STR("[BeamFormer] Did not send " << didNotSendPerc << "% of the subband " << globalSubbandIdx); - } + // Per-subband loss of the BeamFormer is not really relevant due to the 2nd transpose to OutputProc. + // Instead, we report loss in the TABTranspose::MultiSender. } diff --git a/RTCP/Cobalt/GPUProc/src/scripts/cobalt_functions.sh b/RTCP/Cobalt/GPUProc/src/scripts/cobalt_functions.sh index 263ec2aef3b2e8a34becd1dbf41a4f2384eb7567..bab6f5caa53c886293e87730b28f0af87ff76a34 100755 --- a/RTCP/Cobalt/GPUProc/src/scripts/cobalt_functions.sh +++ b/RTCP/Cobalt/GPUProc/src/scripts/cobalt_functions.sh @@ -58,7 +58,7 @@ function read_cluster_model { RESVNODES=$(ssh $HEADNODE scontrol show res -o $SLURM_RESERVATION | perl -n -e 'm/Nodes=(.*?) .*State=ACTIVE/ ? print STDOUT $1 : die "No active cobalt reservation found"') if [ $? -eq 0 ]; then echo "Active reservation '$SLURM_RESERVATION' found, get online nodes in the reservation" - SINFO_FLAGS="--responding -n $RESVNODES" + SINFO_FLAGS="--responding --states=idle,mixed,alloc,reserved -n $RESVNODES" else echo "WARNING: No reservation '$SLURM_RESERVATION' found, defaulting to all online nodes in partition '$SLURM_PARTITION'" SINFO_FLAGS="--responding --states=idle,mixed,alloc --partition=$SLURM_PARTITION" @@ -84,8 +84,8 @@ function read_cluster_model { SLURM_PARTITION=lofarobs # NOTE: sinfo (without -a) only displays this partition for members of the lofarsys group (+ slurm,root) COMPUTENODES="`ssh $HEADNODE sinfo --responding --states=idle,mixed,alloc --format=%n-ib.dragnet.infiniband.lofar,%T --noheader --partition=$SLURM_PARTITION --sort=N | fgrep -v ,draining | cut -f1 -d,`" if [ -z "$COMPUTENODES" ]; then - echo "ERROR: Could not obtain list of available DRAGNET nodes. Defaulting to drg01 - drg20 -ib.dragnet.infiniband.lofar" - COMPUTENODES="`seq -f "drg%02-ib.dragnet.infiniband.lofar" 1 20`" + echo "ERROR: Could not obtain list of available DRAGNET nodes. Defaulting to drg01 - drg23 -ib.dragnet.infiniband.lofar" + COMPUTENODES="`seq -f "drg%02.0f-ib.dragnet.infiniband.lofar" 1 23`" fi COMPUTENODES=$(echo $COMPUTENODES | sed -e s/dragproc-ib.dragnet.infiniband.lofar/dragproc-10g.online.lofar/g) # dragproc has no infiniband i/f, so use 10g diff --git a/RTCP/Cobalt/GPUProc/src/scripts/watchlogs-multitail.conf b/RTCP/Cobalt/GPUProc/src/scripts/watchlogs-multitail.conf index bba6f803801da3824a3882854451050b9a72fd74..3aa3a05a1c9b82defce4c781b59e95d82eaeb714 100644 --- a/RTCP/Cobalt/GPUProc/src/scripts/watchlogs-multitail.conf +++ b/RTCP/Cobalt/GPUProc/src/scripts/watchlogs-multitail.conf @@ -17,8 +17,10 @@ rule:ev:INFO RTCP.Cobalt.GPUProc - Pipeline: Data flushed succesfully. rule:ev:INFO RTCP.Cobalt.CoInterface - Block: written .* subbands, lost 0 subbands. rule:ev:\[Timer.h:[0-9]+\] -rule:ev:INFO RTCP.Cobalt.GPUProc - Queue -rule:ev:INFO RTCP.Cobalt.GPUProc - BestEffortQueue +rule:ev:\[BudgetTimer.cc:[0-9]+\] +rule:ev:\[PerformanceCounter.cc:[0-9]+\] +rule:ev:INFO RTCP.Cobalt.(GPUProc|OutputProc|CoInterface) - Queue +rule:ev:INFO RTCP.Cobalt.(GPUProc|OutputProc|CoInterface) - BestEffortQueue # ----- remove superfluous flagging lines (since all nodes receive all RSP boards in practice) rule:ev:^rtcp\:0[1-9]+.*Flagging diff --git a/RTCP/Cobalt/InputProc/src/Station/PacketReader.cc b/RTCP/Cobalt/InputProc/src/Station/PacketReader.cc index 1047c1fa2d41a02dcd1ccff83f3b7a76090ca0b0..2eeb2fa2741547c8a0dfce2b0891b28523cfc75f 100644 --- a/RTCP/Cobalt/InputProc/src/Station/PacketReader.cc +++ b/RTCP/Cobalt/InputProc/src/Station/PacketReader.cc @@ -50,6 +50,11 @@ namespace LOFAR nrBadTime(0), nrBadData(0), nrBadOther(0), + totalNrReceived(0), + totalNrBadMode(0), + totalNrBadTime(0), + totalNrBadData(0), + totalNrBadOther(0), hadSizeError(false), lastLogTime(0) { @@ -66,6 +71,25 @@ namespace LOFAR } } + PacketReader::~PacketReader() + { + const size_t totalNrDiscarded = totalNrBadMode + totalNrBadTime + totalNrBadData + totalNrBadOther; + const float lostPerc = totalNrReceived == 0.0 ? 0.0 : 100.0 * totalNrDiscarded / totalNrReceived; + + if (lostPerc > 0) { + LOG_WARN_STR(logPrefix << "Total discarded packets is " << lostPerc << "%."); + + if (totalNrBadMode > 0) + LOG_WARN_STR(logPrefix << "Total discarded packets due to bad clock/bitmode is " << (100.0 * totalNrBadMode / totalNrReceived) << "%."); + if (totalNrBadTime > 0) + LOG_WARN_STR(logPrefix << "Total discarded packets due to bad timestamps is " << (100.0 * totalNrBadTime / totalNrReceived) << "%."); + if (totalNrBadData > 0) + LOG_WARN_STR(logPrefix << "Total discarded packets due to payload errors is " << (100.0 * totalNrBadData / totalNrReceived) << "%."); + if (totalNrBadOther > 0) + LOG_WARN_STR(logPrefix << "Total discarded packets due to other reasons is " << (100.0 * totalNrBadOther / totalNrReceived) << "%."); + } + } + void PacketReader::readPackets( std::vector<struct RSP> &packets ) { @@ -192,6 +216,13 @@ namespace LOFAR mdLogger.log(mdKeyPrefix + streamStr + ".rejected", (int)round(nrBad / interval)); + // Update totals + totalNrReceived += nrReceived; + totalNrBadTime += nrBadTime; + totalNrBadMode += nrBadMode; + totalNrBadData += nrBadData; + totalNrBadOther += nrBadOther; + // Reset counters nrReceived = 0; nrBadTime = 0; diff --git a/RTCP/Cobalt/InputProc/src/Station/PacketReader.h b/RTCP/Cobalt/InputProc/src/Station/PacketReader.h index 2140a4c27172e4ab66cfc089e19976f81e55239c..1c943a3e7cc96b863d351cff52429e32b0d09cee 100644 --- a/RTCP/Cobalt/InputProc/src/Station/PacketReader.h +++ b/RTCP/Cobalt/InputProc/src/Station/PacketReader.h @@ -48,6 +48,8 @@ namespace LOFAR PacketReader( const std::string &logPrefix, Stream &inputStream, const BoardMode &mode = MODE_ANY ); + ~PacketReader(); + // Reads a set of packets from the input stream. Sets the payloadError // flag for all invalid packets. void readPackets( std::vector<struct RSP> &packets ); @@ -81,6 +83,12 @@ namespace LOFAR size_t nrBadData; // nr. of packets with payload errors size_t nrBadOther; // nr. of packets that are bad in another fashion (illegal header, packet size, etc) + size_t totalNrReceived; + size_t totalNrBadMode; + size_t totalNrBadTime; + size_t totalNrBadData; + size_t totalNrBadOther; + bool hadSizeError; // already reported about wrongly sized packets since last logStatistics() double lastLogTime; // time since last log print, to monitor data rates diff --git a/RTCP/Cobalt/OutputProc/src/GPUProcIO.cc b/RTCP/Cobalt/OutputProc/src/GPUProcIO.cc index 649be8f700208df377b46d165e5f706c70154e9e..09fd05e16db7b5668e87b90da74ae9ddd88d8bfb 100644 --- a/RTCP/Cobalt/OutputProc/src/GPUProcIO.cc +++ b/RTCP/Cobalt/OutputProc/src/GPUProcIO.cc @@ -169,17 +169,17 @@ bool process(Stream &controlStream) continue; } - LOG_INFO_STR("starting with fileIdx " << fileIdx); + LOG_DEBUG_STR("starting with fileIdx " << fileIdx); mdLogger.log(mdKeyPrefix + PN_COP_STORAGE_HOST + '[' + lexical_cast<string>(fileIdx) + ']', myHostName); - string logPrefix = str(format("[obs %u correlated stream %3u] ") - % parset.settings.observationID % fileIdx); + string logPrefix = str(format("[stream %3u file %s] ") + % fileIdx % file.location.filename); SubbandWriter *writer = new SubbandWriter(parset, fileIdx, mdLogger, mdKeyPrefix, logPrefix); subbandWriters.push_back(writer); - LOG_INFO_STR("done with fileIdx " << fileIdx); + LOG_DEBUG_STR("done with fileIdx " << fileIdx); } } @@ -201,7 +201,7 @@ bool process(Stream &controlStream) const unsigned allFileIdx = fileIdx + parset.settings.correlator.files.size(); mdLogger.log(mdKeyPrefix + PN_COP_STORAGE_HOST + '[' + lexical_cast<string>(allFileIdx) + ']', myHostName); - LOG_INFO_STR("Allocating transpose buffers for " << file.location.filename); + LOG_DEBUG_STR("Allocating transpose buffers for " << file.location.filename); struct ObservationSettings::BeamFormer::StokesSettings &stokes = file.coherent ? parset.settings.beamFormer.coherentSettings @@ -217,27 +217,22 @@ bool process(Stream &controlStream) arenas[fileIdx] = new MallocedArena(poolSize * (MultiDimArray<float,3>::nrElements(boost::extents[nrSamples][nrSubbands][nrChannels]) * sizeof(float) + alignment), alignment); allocators[fileIdx] = new SparseSetAllocator(*arenas[fileIdx]); - outputPools[fileIdx] = new Pool<TABTranspose::BeamformedData>(str(format("process::outputPool [file %u]") % fileIdx), parset.settings.realTime); + outputPools[fileIdx] = new Pool<TABTranspose::BeamformedData>(str(format("process::outputPool [stream %u]") % fileIdx), parset.settings.realTime); // Create and fill an outputPool for this fileIdx - for (size_t i = 0; i < poolSize; ++i) { - outputPools[fileIdx]->free.append(new TABTranspose::BeamformedData( - boost::extents[nrSamples][nrSubbands][nrChannels], - boost::extents[nrSubbands][nrChannels], - *allocators[fileIdx] - ), false); - } + for (size_t i = 0; i < poolSize; ++i) + outputPools[fileIdx]->free.append(new TABTranspose::BeamformedData(nrSubbands, nrChannels, nrSamples, *allocators[fileIdx]), false); + + string logPrefix = str(format("[stream %3u file %s] ") + % fileIdx % file.location.filename); // Create a collector for this fileIdx // #blocks here is the number of blocks that can be collected in parallel on // the input side (what the correlator sends) collectors[fileIdx] = new TABTranspose::BlockCollector( - *outputPools[fileIdx], fileIdx, nrSubbands, nrChannels, nrSamples, parset.settings.nrBlocks(), parset.settings.realTime ? 5 : 0); - - string logPrefix = str(format("[obs %u beamformed stream %3u] ") - % parset.settings.observationID % fileIdx); + *outputPools[fileIdx], fileIdx, nrSubbands, nrChannels, nrSamples, parset.settings.nrBlocks(), parset.settings.realTime ? 5 : 0, logPrefix); - LOG_INFO_STR("Setting up writer for " << file.location.filename); + LOG_DEBUG_STR("Setting up writer for " << file.location.filename); TABOutputThread *writer = new TABOutputThread(parset, fileIdx, *outputPools[fileIdx], mdLogger, mdKeyPrefix, logPrefix); tabWriters.push_back(writer); diff --git a/RTCP/Cobalt/OutputProc/src/InputThread.cc b/RTCP/Cobalt/OutputProc/src/InputThread.cc index d53c81bac9d82ca51bc1f01c93e2a459afb31d4c..6adfefd062dfb3bc3562c31a7f639914ef843d3c 100644 --- a/RTCP/Cobalt/OutputProc/src/InputThread.cc +++ b/RTCP/Cobalt/OutputProc/src/InputThread.cc @@ -75,9 +75,9 @@ namespace LOFAR const float didNotSendPerc = didNotReceivePerc; if (didNotReceivePerc > 0) - LOG_ERROR_STR(itsLogPrefix << "Did not receive " << didNotReceivePerc << "% of the data"); + LOG_WARN_STR(itsLogPrefix << "Did not receive " << didNotReceivePerc << "% of the data"); if (didNotSendPerc > 0) - LOG_ERROR_STR(itsLogPrefix << "Did not send " << didNotSendPerc << "% of the data"); + LOG_WARN_STR(itsLogPrefix << "Did not send " << didNotSendPerc << "% of the data"); // Append end-of-stream marker itsOutputPool.filled.append(NULL); diff --git a/RTCP/Cobalt/OutputProc/src/MSWriterDAL.cc b/RTCP/Cobalt/OutputProc/src/MSWriterDAL.cc index 8b4aed8d6a14b233ce9ba91b04bd4436d027a3d9..6bf21ba685d6aa00dc89ed3d6395045429b19c5e 100644 --- a/RTCP/Cobalt/OutputProc/src/MSWriterDAL.cc +++ b/RTCP/Cobalt/OutputProc/src/MSWriterDAL.cc @@ -78,8 +78,8 @@ namespace LOFAR // uses global locks too anyway. static Mutex HDF5Mutex; - template <typename T,unsigned DIM> - MSWriterDAL<T,DIM>::MSWriterDAL (const string &filename, + template <typename T,unsigned DIM, unsigned FLAGS_DIM> + MSWriterDAL<T,DIM,FLAGS_DIM>::MSWriterDAL (const string &filename, const Parset &parset, unsigned fileno) : @@ -113,8 +113,8 @@ namespace LOFAR itsConfigurationPrefix = fb.beamFormedPrefix(itsFileNr); } - template <typename T,unsigned DIM> - void MSWriterDAL<T,DIM>::init() + template <typename T,unsigned DIM, unsigned FLAGS_DIM> + void MSWriterDAL<T,DIM,FLAGS_DIM>::init() { string h5filename = forceextension(itsFilename, ".h5"); string rawfilename = forceextension(itsFilename, ".raw"); @@ -451,15 +451,15 @@ namespace LOFAR stokesDS.nofSamples().value = dims[0]; } - template <typename T,unsigned DIM> - MSWriterDAL<T,DIM>::~MSWriterDAL() + template <typename T,unsigned DIM, unsigned FLAGS_DIM> + MSWriterDAL<T,DIM,FLAGS_DIM>::~MSWriterDAL() { } - template <typename T,unsigned DIM> - void MSWriterDAL<T,DIM>::write(StreamableData *data) + template <typename T,unsigned DIM, unsigned FLAGS_DIM> + void MSWriterDAL<T,DIM,FLAGS_DIM>::write(StreamableData *data) { - SampleData<T,DIM> *sdata = dynamic_cast<SampleData<T,DIM> *>(data); + SampleData<T,DIM,FLAGS_DIM> *sdata = dynamic_cast<SampleData<T,DIM,FLAGS_DIM> *>(data); ASSERT( data ); ASSERT( sdata ); diff --git a/RTCP/Cobalt/OutputProc/src/MSWriterDAL.h b/RTCP/Cobalt/OutputProc/src/MSWriterDAL.h index 8f9c552cbde8a5aa01535de8fdab279e0c7b43ab..ca25c939e1f5bda3f25865a58bbe533d31ac5265 100644 --- a/RTCP/Cobalt/OutputProc/src/MSWriterDAL.h +++ b/RTCP/Cobalt/OutputProc/src/MSWriterDAL.h @@ -38,7 +38,7 @@ namespace LOFAR namespace Cobalt { - template<typename T, unsigned DIM> + template<typename T, unsigned DIM, unsigned FLAGS_DIM=1> class MSWriterDAL : public MSWriterFile { public: diff --git a/RTCP/Cobalt/OutputProc/src/OutputThread.cc b/RTCP/Cobalt/OutputProc/src/OutputThread.cc index 5dc58114d21aa178f98c381acfd5fbe1656be921..76325ec033c356190d0bc65f58c9eb0059f5420c 100644 --- a/RTCP/Cobalt/OutputProc/src/OutputThread.cc +++ b/RTCP/Cobalt/OutputProc/src/OutputThread.cc @@ -70,6 +70,8 @@ namespace LOFAR itsTargetDirectory(targetDirectory), itsBlocksWritten(0), itsBlocksDropped(0), + itsBlocksDroppedByMe(0), + itsFractionalBlocksWritten(0.0), itsNrExpectedBlocks(0), itsNextSequenceNumber(0), itsBlockDuration(parset.settings.blockDuration()), @@ -104,6 +106,7 @@ namespace LOFAR itsNextSequenceNumber = data->sequenceNumber() + 1; itsBlocksWritten++; + itsFractionalBlocksWritten += 1.0 - data->outputLossFraction(); // doubles have enough precision for this to go well itsMdLogger.log(itsMdKeyPrefix + PN_COP_DROPPING + streamNrStr, droppedBlocks > 0); // logged too late if dropping: not anymore... @@ -127,6 +130,7 @@ namespace LOFAR itsWriter->write(data); } catch (SystemCallException &ex) { LOG_WARN_STR(itsLogPrefix << "OutputThread caught non-fatal exception: " << ex.what()); + itsBlocksDroppedByMe++; continue; } } else { // no try/catch: any loss (e.g. disk full) is fatal in non-real-time mode @@ -136,7 +140,7 @@ namespace LOFAR checkForDroppedData(data); // print debug info for the other blocks - LOG_DEBUG_STR(itsLogPrefix << "Written block with seqno = " << data->sequenceNumber() << ", " << itsBlocksWritten << " blocks written (" << itsWriter->percentageWritten() << "%), " << itsBlocksDropped << " blocks dropped"); + LOG_DEBUG_STR(itsLogPrefix << "Written block with seqno = " << data->sequenceNumber() << "(which was " << (100.0 - 100.0 * data->outputLossFraction()) << "% complete), " << itsBlocksWritten << " blocks written, " << itsBlocksDropped << " blocks not received"); } } @@ -164,9 +168,24 @@ namespace LOFAR template<typename T> void OutputThread<T>::cleanUp() const { - float dropPercent = itsBlocksWritten + itsBlocksDropped == 0 ? 0.0 : (100.0 * itsBlocksDropped) / (itsBlocksWritten + itsBlocksDropped); - - LOG_INFO_STR(itsLogPrefix << "Finished writing: " << itsBlocksWritten << " blocks written (" << itsWriter->percentageWritten() << "%), " << itsBlocksDropped << " blocks dropped: " << std::setprecision(3) << dropPercent << "% lost" ); + // report statistics + const float lostPerc = 100.0 * itsBlocksDroppedByMe / itsNrExpectedBlocks; + const float didNotSendPerc = itsNrExpectedBlocks == 0 ? 0.0 : 100.0 - 100.0 * itsFractionalBlocksWritten / itsNrExpectedBlocks; + const float didNotReceivePerc = didNotSendPerc + lostPerc; + + if (didNotReceivePerc > 0) + LOG_WARN_STR(itsLogPrefix << "Did not receive " << didNotReceivePerc << "% of the data"); + if (lostPerc > 0) + LOG_ERROR_STR(itsLogPrefix << "I lost " << lostPerc << "% of the data"); + if (didNotSendPerc > 0) + LOG_WARN_STR(itsLogPrefix << "Did not send " << didNotSendPerc << "% of the data"); + + LOG_INFO_STR(itsLogPrefix << "Finished writing " << itsBlocksWritten << " blocks, dropped " << itsBlocksDropped << " blocks."); + + if (didNotSendPerc > 0) + LOG_ERROR_STR(itsLogPrefix << "Total output data loss is " << didNotSendPerc << "%."); + else + LOG_INFO_STR(itsLogPrefix << "Total output data loss is " << didNotSendPerc << "%."); } @@ -250,6 +269,8 @@ namespace LOFAR # pragma omp section init(); } + + LOG_INFO_STR(itsLogPrefix << "Finalised data product."); } // Make required instantiations @@ -357,7 +378,7 @@ namespace LOFAR LOG_INFO_STR(itsLogPrefix << "Writing to " << path); #ifdef HAVE_DAL - itsWriter = new MSWriterDAL<float,3>(path, itsParset, itsStreamNr); + itsWriter = new MSWriterDAL<float,3,1>(path, itsParset, itsStreamNr); #else itsWriter = new MSWriterFile(path); #endif diff --git a/RTCP/Cobalt/OutputProc/src/OutputThread.h b/RTCP/Cobalt/OutputProc/src/OutputThread.h index b272680ba0c4bb8cba890402744745e134a87b37..5264e3dd150a37ee7446abca7752e690bda957d1 100644 --- a/RTCP/Cobalt/OutputProc/src/OutputThread.h +++ b/RTCP/Cobalt/OutputProc/src/OutputThread.h @@ -94,7 +94,8 @@ namespace LOFAR const std::string itsLogPrefix; const std::string itsTargetDirectory; - size_t itsBlocksWritten, itsBlocksDropped; + size_t itsBlocksWritten, itsBlocksDropped, itsBlocksDroppedByMe; + double itsFractionalBlocksWritten; size_t itsNrExpectedBlocks; size_t itsNextSequenceNumber; double itsBlockDuration; // seconds diff --git a/RTCP/Cobalt/OutputProc/test/tMSWriterDAL.cc b/RTCP/Cobalt/OutputProc/test/tMSWriterDAL.cc index c15a2b1a03a621a5f56c7ec603a12c49bc60c43d..3dfc126944eafcea2a95e7000ade4a0f1ec9c231 100644 --- a/RTCP/Cobalt/OutputProc/test/tMSWriterDAL.cc +++ b/RTCP/Cobalt/OutputProc/test/tMSWriterDAL.cc @@ -52,9 +52,9 @@ int main() const size_t nrSubbands = parset.settings.SAPs[file.sapNr].subbands.size(); - SampleData<float,3,2> data( + SampleData<float,3,1> data( boost::extents[sset.nrSamples][nrSubbands][sset.nrChannels], - boost::extents[nrSubbands][sset.nrChannels]); + boost::extents[nrSubbands]); memset(data.samples.origin(), 0, data.samples.num_elements() * sizeof *data.samples.origin()); diff --git a/SAS/CMakeLists.txt b/SAS/CMakeLists.txt index 8c494b2729fb07828d49fb166c9ea848d33cf309..bd958ea2d6baab6bc85a22ea8630924d1b1085a6 100644 --- a/SAS/CMakeLists.txt +++ b/SAS/CMakeLists.txt @@ -11,6 +11,7 @@ lofar_add_package(XML_generator) lofar_add_package(TriggerServices) lofar_add_package(TriggerEmailService) lofar_add_package(SpecificationServices) +lofar_add_package(XSD) add_subdirectory(MoM) add_subdirectory(ResourceAssignment) diff --git a/SAS/DataManagement/DataManagementCommon/path.py b/SAS/DataManagement/DataManagementCommon/path.py index 79fad13232249dfd1ded423f364222e2dc0a86b4..a10309793c0ac8ab6a9457f0e07842ec85a12573 100644 --- a/SAS/DataManagement/DataManagementCommon/path.py +++ b/SAS/DataManagement/DataManagementCommon/path.py @@ -71,9 +71,10 @@ class PathResolver: project_path = result['path'] task = result['task'] task_data_path = os.path.join(project_path, 'L%s' % task['otdb_id']) - logger.info("found path '%s' for otdb_id=%s mom_id=%s radb_id=%s" % (task_data_path, task['otdb_id'], task['mom_id'], task['id'])) + logger.info("constructed path '%s' for otdb_id=%s mom_id=%s radb_id=%s" % (task_data_path, task['otdb_id'], task['mom_id'], task['id'])) - path_result = {'found': True, 'message': '', 'path': task_data_path} + path_result = {'found': True, 'message': '', 'path': task_data_path, + 'radb_id': task.get('id'), 'mom_id': task.get('mom_id'), 'otdb_id': task.get('otdb_id')} if include_scratch_paths and task['type'] == 'pipeline': path_result['scratch_paths'] = [] @@ -91,6 +92,8 @@ class PathResolver: logger.info("result for getPathForTask(radb_id=%s, mom_id=%s, otdb_id=%s): %s", radb_id, mom_id, otdb_id, path_result) return path_result + result = {'found': False, 'message': result.get('message', ''), 'path': '', + 'radb_id': radb_id, 'mom_id': mom_id, 'otdb_id': otdb_id} logger.warn("result for getPathForTask(radb_id=%s, mom_id=%s, otdb_id=%s): %s", radb_id, mom_id, otdb_id, result) return result diff --git a/SAS/DataManagement/StorageQueryService/cache.py b/SAS/DataManagement/StorageQueryService/cache.py index b06e9cc78bf8f3f9c0783824cd213e83997c5c39..87d15ee5102c881cb915059dde3298202e5a26ba 100644 --- a/SAS/DataManagement/StorageQueryService/cache.py +++ b/SAS/DataManagement/StorageQueryService/cache.py @@ -30,7 +30,7 @@ from lofar.mom.momqueryservice.config import DEFAULT_MOMQUERY_BUSNAME, DEFAULT_M logger = logging.getLogger(__name__) -MAX_CACHE_ENTRY_AGE = datetime.timedelta(days=1) +MAX_CACHE_ENTRY_AGE = datetime.timedelta(hours=8) class CacheManager: def __init__(self, @@ -115,7 +115,7 @@ class CacheManager: with open(tmp_path, 'w') as file: with self._cacheLock: file.write(pformat(self._cache) + '\n') - os.replace(tmp_path, self._cache_path) + os.rename(tmp_path, self._cache_path) except Exception as e: logger.error("Error while writing du cache: %s", e) @@ -156,9 +156,6 @@ class CacheManager: self._sendDiskUsageChangedNotification(path, du_result['disk_usage'], otdb_id) - if du_result.get('path') == self.disk_usage.path_resolver.projects_path: - self._updateProjectsDiskUsageInRADB() - def _invalidateCacheEntryForPath(self, path): with self._cacheLock: path_cache = self._cache['path_du_results'] @@ -173,7 +170,7 @@ class CacheManager: result = {} for otdb_id in otdb_ids: - result[otdb_id] = self.getDiskUsageForOTDBId(otdb_id, force_update) + result[otdb_id] = self.getDiskUsageForOTDBId(otdb_id, force_update=force_update) return result @@ -256,13 +253,19 @@ class CacheManager: try: path = cache_entry.get('path') if path: - logger.info('_updateOldEntriesInCache: examining entry %s/%s. timestamp:%s age:%s needs_update:%s path: %s', + logger.info('_updateOldEntriesInCache: examining entry %s/%s. timestamp:%s age:%s needs_update:%s path: \'%s\'', i, len(updateable_entries), cache_entry['cache_timestamp'], format_timedelta(now - cache_entry['cache_timestamp']), cache_entry.get('needs_update', False), path) + + #do a quick update of the entry sy applying the sum of the subdirs to the path's du result... + #this make a best guess immedeiately available... + self._updatePathCacheEntryToSubDirTotal(path, False) + + #...and in the mean time, du a full update from disk, which might be (really) slow. result = du_getDiskUsageForPath(path) logger.debug('trying to update old entry in cache: %s', result) self._updateCache(result) @@ -278,6 +281,9 @@ class CacheManager: logger.info('skipping remaining %s old cache entries updates, they will be updated next time', len(updateable_entries)-i) break + #update the CEP4 capacities in the RADB once in a while... + self._updateCEP4CapacitiesInRADB() + #sleep for a minute, (or stop if requested) for i in range(60): sleep(1) @@ -287,28 +293,48 @@ class CacheManager: except Exception as e: logger.error(str(e)) - def _updateProjectsDiskUsageInRADB(self): + def _updatePathCacheEntryToSubDirTotal(self, path, force_update=False): + sd_result = self.disk_usage.path_resolver.getSubDirectories(path) + + if sd_result['found']: + subdir_paths = [os.path.join(path, sd) for sd in sd_result['sub_directories']] + + subdir_du_results = [self.getDiskUsageForPath(sd, force_update=force_update) for sd in subdir_paths] + sum_du = sum([du['disk_usage'] for du in subdir_du_results]) + + with self._cacheLock: + if path in self._cache['path_du_results']: + path_result = self._cache['path_du_results'][path] + path_result['disk_usage'] = sum_du + path_result['disk_usage_readable'] = humanreadablesize(sum_du) + path_result['needs_update'] = True + self._updateCache(path_result) + + def _updateCEP4CapacitiesInRADB(self): try: - projects_du_result = self.getDiskUsageForPath(self.disk_usage.path_resolver.projects_path) - if projects_du_result['found']: + df_result = self.disk_usage.getDiskFreeSpace() + if df_result['found']: #get the total used space, and update the resource availability in the radb radbrpc = self.disk_usage.path_resolver.radbrpc storage_resources = radbrpc.getResources(resource_types='storage', include_availability=True) cep4_storage_resource = next(x for x in storage_resources if 'CEP4' in x['name']) - total_capacity = cep4_storage_resource.get('total_capacity') - used_capacity = projects_du_result.get('disk_usage') - if total_capacity != None and used_capacity != None: - available_capacity = total_capacity - used_capacity + total_capacity = df_result.get('disk_size') + used_capacity = df_result.get('disk_usage') + available_capacity = df_result.get('disk_free') - logger.info('updating availability capacity for %s (id=%s) to %s in the RADB', - cep4_storage_resource['name'], - cep4_storage_resource['id'], - humanreadablesize(available_capacity)) + logger.info('updating capacities for resource \'%s\' (id=%s) in the RADB: total=%s, used=%s, available=%s', + cep4_storage_resource['name'], + cep4_storage_resource['id'], + humanreadablesize(total_capacity), + humanreadablesize(used_capacity), + humanreadablesize(available_capacity)) - radbrpc.updateResourceAvailability(cep4_storage_resource['id'], available_capacity=available_capacity) + radbrpc.updateResourceAvailability(cep4_storage_resource['id'], + available_capacity=available_capacity, + total_capacity=total_capacity) except Exception as e: - logger.error(e) + logger.error('_updateCEP4CapacitiesInRADB: %s', e) def open(self): self.disk_usage.open() @@ -438,7 +464,7 @@ class CacheManager: return result def getDiskUsageForPath(self, path, force_update=False): - logger.info("cache.getDiskUsageForPath(%s, force_update=%s)", path, force_update) + logger.info("cache.getDiskUsageForPath('%s', force_update=%s)", path, force_update) needs_cache_update = False with self._cacheLock: needs_cache_update |= path not in self._cache['path_du_results'] @@ -457,7 +483,7 @@ class CacheManager: result['message'] = 'No such path: %s' % path result['disk_usage_readable'] = humanreadablesize(result.get('disk_usage', 0)) - logger.info('cache.getDiskUsageForPath result: %s' % result) + logger.info('cache.getDiskUsageForPath(\'%s\') result: %s', path, result) return result def getDiskUsageForTaskAndSubDirectories(self, radb_id=None, mom_id=None, otdb_id=None, force_update=False): diff --git a/SAS/DataManagement/StorageQueryService/diskusage.py b/SAS/DataManagement/StorageQueryService/diskusage.py index d5a0063f588dacfe73d7d6695a26b27d30581694..67a96da340ce7dc21ccf8ff24d68f5cbf7526e49 100644 --- a/SAS/DataManagement/StorageQueryService/diskusage.py +++ b/SAS/DataManagement/StorageQueryService/diskusage.py @@ -17,7 +17,10 @@ from lofar.mom.momqueryservice.config import DEFAULT_MOMQUERY_BUSNAME, DEFAULT_M logger = logging.getLogger(__name__) def getDiskUsageForPath(path): - logger.info('getDiskUsageForPath(%s)', path) + logger.info('getDiskUsageForPath(\'%s\')', path) + + result = {'found': False, 'path': path, 'disk_usage': None, 'name': path.split('/')[-1] } + cmd = ['rbh-du', '-bd', path] hostname = socket.gethostname() if not 'mgmt0' in hostname: @@ -27,51 +30,91 @@ def getDiskUsageForPath(path): proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() + if proc.returncode == 0: + # example of out + # Using config file '/etc/robinhood.d/tmpfs/tmp_fs_mgr_basic.conf'. + # /data/projects/2016LOFAROBS/L522380 + # dir count:3906, size:16048128, spc_used:16052224 + # file count:17568, size:42274164368, spc_used:42327519232 + + #parse out + lines = [l.strip() for l in out.split('\n')] + file_lines = [l for l in lines if 'file count' in l] + if file_lines: + parts = [p.strip() for p in file_lines[0].split(',')] + partsDict = {p.split(':')[0].strip():p.split(':')[1].strip() for p in parts} + + result['found'] = True + + if 'size' in partsDict: + result['disk_usage'] = int(partsDict['size']) + + if 'file count' in partsDict: + result['nr_of_files'] = int(partsDict['file count']) + else: + dir_lines = [l for l in lines if 'dir count' in l] + if dir_lines: + result['found'] = True + result['disk_usage'] = 0 + result['nr_of_files'] = 0 + + try: + path_items = path.rstrip('/').split('/') + if len(path_items) >=3 and path_items[-1].startswith('L') and path_items[-1][1:].isdigit() and 'projects' in path_items[-3]: + logger.info('found path for otdb_id %s %s', path_items[-1][1:], path) + result['otdb_id'] = int(path_items[-1][1:]) + except Exception as e: + logger.error('Could not parse otdb_id from path %s %s', path, e) + else: + logger.error(out + err) + result['message'] = out + + result['disk_usage_readable'] = humanreadablesize(result['disk_usage']) + + logger.info('getDiskUsageForPath(\'%s\') returning: %s', path, result) + return result + +def getDiskFreeSpaceForMountpoint(mountpoint=CEP4_DATA_MOUNTPOINT): + logger.info('getDiskFreeSpaceForMountpoint(\'%s\')', mountpoint) + + result = {'found': False, 'mountpoint': mountpoint } + + cmd = ['df', mountpoint] + hostname = socket.gethostname() + if not 'mgmt0' in hostname: + cmd = ['ssh', 'lofarsys@mgmt01.cep4.control.lofar'] + cmd + logger.info(' '.join(cmd) + ' ...waiting for result...') + + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate() + if proc.returncode != 0: logger.error(out + err) - return {'found': False, 'path': path, 'message': out} + result['message'] = out + return result # example of out - # Using config file '/etc/robinhood.d/tmpfs/tmp_fs_mgr_basic.conf'. - # /data/projects/2016LOFAROBS/L522380 - # dir count:3906, size:16048128, spc_used:16052224 - # file count:17568, size:42274164368, spc_used:42327519232 + # Filesystem 1K-blocks Used Available Use% Mounted on + # 10.134.233.65@o2ib:10.134.233.66@o2ib:/cep4-fs 3369564904320 1460036416928 1737591103048 46% /data #parse out lines = [l.strip() for l in out.split('\n')] - file_lines = [l for l in lines if 'file count' in l] - if file_lines: - parts = [p.strip() for p in file_lines[0].split(',')] - partsDict = {p.split(':')[0].strip():p.split(':')[1].strip() for p in parts} + data_line = next(l for l in lines if mountpoint in l) + if data_line: + parts = [p.strip() for p in data_line.split(' ')] - result = {'found': True, 'disk_usage': None, 'path': path, 'name': path.split('/')[-1]} - - if 'size' in partsDict: - result['disk_usage'] = int(partsDict['size']) - - if 'file count' in partsDict: - result['nr_of_files'] = int(partsDict['file count']) + result['found'] = True + result['disk_size'] = 1024*int(parts[1]) + result['disk_usage'] = 1024*int(parts[2]) + result['disk_free'] = 1024*int(parts[3]) + result['disk_size_readable'] = humanreadablesize(result['disk_size']) result['disk_usage_readable'] = humanreadablesize(result['disk_usage']) - else: - dir_lines = [l for l in lines if 'dir count' in l] - if dir_lines: - result = {'found': True, 'disk_usage': 0, 'nr_of_files': 0, 'path': path, 'name': path.split('/')[-1]} - else: - result = {'found': False, 'path': path } + result['disk_free_readable'] = humanreadablesize(result['disk_free']) - try: - path_items = path.rstrip('/').split('/') - if len(path_items) >=3 and path_items[-1].startswith('L') and path_items[-1][1:].isdigit() and 'projects' in path_items[-3]: - logger.info('found path for otdb_id %s %s', path_items[-1][1:], path) - result['otdb_id'] = int(path_items[-1][1:]) - except Exception as e: - logger.error('Could not parse otdb_id from path %s %s', path, e) - - logger.info('returning: %s' % result) + logger.info('getDiskFreeSpaceForMountpoint(\'%s\') returning: %s', mountpoint, result) return result - class DiskUsage: def __init__(self, mountpoint=CEP4_DATA_MOUNTPOINT, @@ -149,6 +192,9 @@ class DiskUsage: return path_result + def getDiskFreeSpace(self): + return getDiskFreeSpaceForMountpoint(self.path_resolver.mountpoint) + def main(): # Check the invocation arguments parser = OptionParser("%prog [options] <path>", diff --git a/SAS/MoM/MoMQueryService/MoMQueryServiceClient/momqueryrpc.py b/SAS/MoM/MoMQueryService/MoMQueryServiceClient/momqueryrpc.py index 98ba9594d53337acd4f4e99913c57ab632b3efe0..6f09ea5ee587d12618b900fff0ed728261c8f2af 100644 --- a/SAS/MoM/MoMQueryService/MoMQueryServiceClient/momqueryrpc.py +++ b/SAS/MoM/MoMQueryService/MoMQueryServiceClient/momqueryrpc.py @@ -153,7 +153,7 @@ class MoMQueryRPC(RPCWrapper): ids = [str(x) for x in ids] ids_string = ', '.join(ids) - logger.info("Requesting details for mom objects: %s", (str(ids_string))) + logger.info("Requesting details for %s mom objects", len(ids)) result = self.rpc('GetObjectDetails', mom_ids=ids_string) result = convertStringDigitKeysToInt(result) logger.info("Received details for %s mom objects" % (len(result))) diff --git a/SAS/ResourceAssignment/ResourceAssigner/lib/assignment.py b/SAS/ResourceAssignment/ResourceAssigner/lib/assignment.py index 80475ecd80b6da65e85cab232579439e76df18fa..0e2c834d20b8866d646e542fce5fa8dc94e8fbc8 100755 --- a/SAS/ResourceAssignment/ResourceAssigner/lib/assignment.py +++ b/SAS/ResourceAssignment/ResourceAssigner/lib/assignment.py @@ -354,8 +354,43 @@ class ResourceAssigner(): conflictingClaims = self.radbrpc.getResourceClaims(task_ids=taskId, status='conflict') if conflictingClaims: # Will do _announceStateChange(task, 'conflict'), and radb sets task status to conflict automatically - logger.error('doAssignment: Task cannot be scheduled, because of %d conflicting claims: %s' % - (len(conflictingClaims), conflictingClaims)) + logger.error('doAssignment: Task cannot be scheduled, because of %d conflicting claims: %s', + len(conflictingClaims), conflictingClaims) + + try: + for conflictingClaim in conflictingClaims: + #gather some info on this resource, and log the reasons why this claim has a conflict with others + resource_id = conflictingClaim['resource_id'] + resource = self.radbrpc.getResources(resource_ids=[resource_id], + include_availability=True)[0] + max_resource_usage = self.radbrpc.get_max_resource_usage_between(resource_id, + conflictingClaim['starttime'], + conflictingClaim['endtime']) + claimable_capacity = self.radbrpc.get_resource_claimable_capacity(resource_id, + conflictingClaim['starttime'], + conflictingClaim['endtime'])['claimable_capacity'] + conflictingCausingClaims = self.radbrpc.get_overlapping_claims(conflictingClaim['id']) + conflictingCausingTasks = self.radbrpc.getTasks(task_ids=list(set(c['task_id'] for c in conflictingCausingClaims))) + + logger.info("doAssignment: Task cannot be scheduled: claim with id=%s, size=%s, start='%s', end='%s' on resource id=%s, name='%s', total_cap=%s, used(claimed)_cap=%s, misc_used_cap=%s, available_cap=%s, claimable_cap=%s has a conflict with %s other claims with max_resource_usage=%s at '%s' on the same resource for otdb_ids=%s", + conflictingClaim['id'], + conflictingClaim['claim_size'], + conflictingClaim['starttime'], + conflictingClaim['endtime'], + resource['id'], + resource['name'], + resource['total_capacity'], + resource['used_capacity'], + resource['misc_used_capacity'], + resource['available_capacity'], + claimable_capacity, + len(conflictingCausingClaims), + max_resource_usage['usage'], + max_resource_usage['as_of_timestamp'], + ','.join(str(t['otdb_id']) for t in conflictingCausingTasks)) + except Exception as e: + logger.error(e) + self._announceStateChange(task, 'conflict') return diff --git a/SAS/ResourceAssignment/ResourceAssigner/test/t_schedulechecker.py b/SAS/ResourceAssignment/ResourceAssigner/test/t_schedulechecker.py index 8ef2c28b74b984cf695425a5781b29524c80b7a3..fdb3f3c7f9992458c176e3523c0e608b933663e4 100755 --- a/SAS/ResourceAssignment/ResourceAssigner/test/t_schedulechecker.py +++ b/SAS/ResourceAssignment/ResourceAssigner/test/t_schedulechecker.py @@ -30,11 +30,12 @@ ra_notification_prefix = "ra_notification_prefix" class TestingScheduleChecker(ScheduleChecker): - def __init__(self, rarpc, momrpc, curpc): + def __init__(self, rarpc, momrpc, curpc, otdbrpc): # super gets not done to be able to insert mocks as early as possible otherwise the RPC block unittesting self._radbrpc = rarpc self._momrpc = momrpc self._curpc = curpc + self._otdbrpc = otdbrpc class ScheduleCheckerTest(unittest.TestCase): @@ -55,6 +56,10 @@ class ScheduleCheckerTest(unittest.TestCase): self.addCleanup(curpc_patcher.stop) self.curpc_mock = curpc_patcher.start() + otdbrpc_patcher = mock.patch('lofar.sas.otdb.otdbrpc.OTDBRPC') + self.addCleanup(otdbrpc_patcher.stop) + self.otdbrpc_mock = otdbrpc_patcher.start() + # Default return values self.rarpc_mock.getTasks.return_value = [ { 'id': 'id', 'mom_id': '1', 'otdb_id': 'otdb_id', 'status': 'approved', 'type': 'observation', 'specification_id': 'specification_id' } ] self.momrpc_mock.getObjectDetails.return_value = { 1: { 'object_status': 'approved' } } @@ -74,7 +79,7 @@ class ScheduleCheckerTest(unittest.TestCase): self.assertTrue(self.curpc_mock.close.called, "CURPC.close was not called") def test_contextManager_opens_and_closes_all_services(self): - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock): + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock): self.assert_all_services_opened() self.assert_all_services_closed() @@ -120,7 +125,7 @@ class ScheduleCheckerTest(unittest.TestCase): self.rarpc_mock.getTasks.return_value = [ { 'id': 'id', 'status': 'scheduled', 'type': 'pipeline', 'starttime': datetime.datetime.utcnow() } ] self.rarpc_mock.getTask.return_value = { 'id': 'id', 'status': 'scheduled', 'type': 'pipeline', 'starttime': datetime.datetime.utcnow() } - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock) as schedulechecker: + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock) as schedulechecker: schedulechecker.checkScheduledAndQueuedPipelines() self.assertTrue(movePipeline_mock.called, "Pipeline was not moved.") @@ -130,7 +135,7 @@ class ScheduleCheckerTest(unittest.TestCase): self.rarpc_mock.getTasks.return_value = [ { 'id': 'id', 'mom_id': '1', 'otdb_id': 'otdb_id', 'status': 'active', 'type': 'pipeline', 'specification_id': 'specification_id', 'endtime': datetime.datetime.utcnow() } ] - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock) as schedulechecker: + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock) as schedulechecker: schedulechecker.checkRunningPipelines() self.assertTrue(self.rarpc_mock.updateTaskAndResourceClaims.called, "Task was not updated.") @@ -140,7 +145,7 @@ class ScheduleCheckerTest(unittest.TestCase): """ Test if a MoM task on 'opened' and in OTDB on 'approved' causes the task to be deleted. """ self.momrpc_mock.getObjectDetails.return_value = { 1: { 'object_status': 'opened' } } - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock) as schedulechecker: + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock) as schedulechecker: schedulechecker.checkUnRunTasksForMoMOpenedStatus() self.assertTrue(self.curpc_mock.removeTaskData.called, "Task output was not deleted from disk") @@ -150,7 +155,7 @@ class ScheduleCheckerTest(unittest.TestCase): """ Test if a MoM task on 'approved' and in OTDB on 'approved' causes the task NOT to be deleted. """ self.momrpc_mock.getObjectDetails.return_value = { 1: { 'object_status': 'approved' } } - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock) as schedulechecker: + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock) as schedulechecker: schedulechecker.checkUnRunTasksForMoMOpenedStatus() self.assertFalse(self.curpc_mock.removeTaskData.called, "Task output was deleted from disk") @@ -160,7 +165,7 @@ class ScheduleCheckerTest(unittest.TestCase): """ Test if a task is not in MoM, and 'approved' in OTDB. This causes the task to be deleted. """ self.momrpc_mock.getObjectDetails.return_value = {} - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock) as schedulechecker: + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock) as schedulechecker: schedulechecker.checkUnRunTasksForMoMOpenedStatus() self.assertTrue(self.rarpc_mock.deleteSpecification.called, "Object was not removed from RADB") @@ -168,7 +173,7 @@ class ScheduleCheckerTest(unittest.TestCase): def test_checkUnRunTasksForMoMOpenedStatus_only_observations_pipelines(self): """ Test if only observations and pipelines are compared against the MoMDB (and not maintenance or reservation tasks, for example). """ - with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock) as schedulechecker: + with TestingScheduleChecker(self.rarpc_mock, self.momrpc_mock, self.curpc_mock, self.otdbrpc_mock) as schedulechecker: schedulechecker.checkUnRunTasksForMoMOpenedStatus() self.assertEquals(self.rarpc_mock.getTasks.call_args[1]["task_type"], ['observation', 'pipeline'], "Only observations and pipelines must be matched against MoMDB") diff --git a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py index 14f3e7599d3da19583db355cce1abcb99254b214..118bacccc64b385d2a9b89803f6abad740d2793d 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py +++ b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py @@ -71,13 +71,16 @@ class RADatabase: def _executeQuery(self, query, qargs=None, fetch=_FETCH_NONE): ''' Execute the query and reconnect upon OperationalError ''' - if self.log_queries: - logger.info('executing query: %s' % self._queryAsSingleLine(query, qargs)) - # Allow for 5 connection retries for i in range(5): try: + start = datetime.utcnow() self.cursor.execute(query, qargs) + if self.log_queries: + elapsed = datetime.utcnow() - start + logger.info('executed query in %.1fms yielding %s rows: %s', 1000.0*totalSeconds(elapsed), + self.cursor.rowcount, + self._queryAsSingleLine(query, qargs)) break except (psycopg2.OperationalError, AttributeError) as e: if isinstance(e, psycopg2.OperationalError): @@ -89,14 +92,12 @@ class RADatabase: logger.info("connected to radb") time.sleep(i*i) except (psycopg2.IntegrityError, psycopg2.ProgrammingError, psycopg2.InternalError, psycopg2.DataError)as e: + self._log_database_notifications() logger.error("Rolling back query=\'%s\' due to error: \'%s\'" % (self._queryAsSingleLine(query, qargs), e)) self.rollback() return [] - if self.conn.notices: - for notice in self.conn.notices: - logger.info('database log message %s', notice.strip()) - del self.conn.notices[:] + self._log_database_notifications() if fetch == _FETCH_ONE: return self.cursor.fetchone() @@ -104,6 +105,11 @@ class RADatabase: if fetch == _FETCH_ALL: return self.cursor.fetchall() + def _log_database_notifications(self): + if self.conn.notices: + for notice in self.conn.notices: + logger.info('database log message %s', notice.strip()) + del self.conn.notices[:] def commit(self): logger.info('commit') @@ -482,6 +488,36 @@ class RADatabase: return self.cursor.rowcount > 0 + def updateTaskStartEndTimes(self, task_id, starttime=None, endtime=None, commit=True): + fields = [] + values = [] + + if starttime: + fields.append('starttime') + values.append(starttime) + + if endtime: + fields.append('endtime') + values.append(endtime) + + if not fields: + return False + + values.append(task_id) + + query = '''UPDATE resource_allocation.specification + SET ({fields}) = ({value_placeholders}) + WHERE resource_allocation.specification.id in + (SELECT t.specification_id FROM resource_allocation.task + t WHERE t.id={id_placeholder});'''.format(fields=', '.join(fields), + value_placeholders=', '.join('%s' for x in fields), + id_placeholder='%s') + self._executeQuery(query, values) + if commit: + self.commit() + + return self.cursor.rowcount > 0 + def getTaskPredecessorIds(self, id=None): query = '''SELECT * from resource_allocation.task_predecessor tp''' @@ -576,7 +612,7 @@ class RADatabase: query = '''SELECT * from resource_allocation.specification spec WHERE spec.id = (%s);''' - return list(self._executeQuery(query, [specification_id], fetch=_FETCH_ALL)) + return self._executeQuery(query, [specification_id], fetch=_FETCH_ONE) def insertSpecification(self, starttime, endtime, content, cluster, commit=True): logger.info('insertSpecification starttime=%s, endtime=%s cluster=%s' % (starttime, endtime, cluster)) @@ -763,6 +799,36 @@ class RADatabase: return resources + def get_current_resource_usage(self, resource_id, claim_status='claimed'): + if isinstance(claim_status, basestring): + claim_status_id = self.getResourceClaimStatusId(claim_status) + else: + claim_status_id = claim_status + + query = '''SELECT * from resource_allocation.get_current_resource_usage(%s, %s)''' + result = self._executeQuery(query, (resource_id, claim_status_id), fetch=_FETCH_ONE) + + if result is None or result.get('usage') is None: + #return a nice default + result = {'usage': 0, 'status_id': claim_status_id, 'id': None, 'as_of_timestamp': timestamp, 'resource_id': resource_id} + + return result + + def get_resource_usage_at_or_before(self, resource_id, timestamp, claim_status='claimed', exactly_at=False, only_before=False): + if isinstance(claim_status, basestring): + claim_status_id = self.getResourceClaimStatusId(claim_status) + else: + claim_status_id = claim_status + + query = '''SELECT * from resource_allocation.get_resource_usage_at_or_before(%s, %s, %s, %s, %s, %s)''' + result = self._executeQuery(query, (resource_id, claim_status_id, timestamp, exactly_at, only_before, True), fetch=_FETCH_ONE) + + if result is None or result.get('usage') is None: + #return a nice default + result = {'usage': 0, 'status_id': claim_status_id, 'id': None, 'as_of_timestamp': timestamp, 'resource_id': resource_id} + + return result + def updateResourceAvailability(self, resource_id, active=None, available_capacity=None, total_capacity=None, commit=True): if active is not None: query = '''UPDATE resource_monitoring.resource_availability @@ -1295,8 +1361,6 @@ class RADatabase: When one or more claims of a task are in conflict status, then its task is set to conflict as well, and hence cannot be scheduled. When all claims of a task are not in conflict status anymore, then the task is set to approved, and hence it is possible the schedule the task. ''' - logger.info("updateResourceClaims") - status_id = status if status is not None and isinstance(status, basestring): #convert status string to status.id @@ -1412,39 +1476,41 @@ class RADatabase: user_id=user_id, commit=False) + if starttime or endtime: + updated &= self.updateTaskStartEndTimes(task_id, starttime=starttime, endtime=endtime, commit=False) + if task_status is not None : updated &= self.updateTask(task_id, task_status=task_status, commit=False) - if starttime or endtime: - task = self.getTask(task_id) - if task == None: - return False - updated &= self.updateSpecification(task['specification_id'], starttime=starttime, endtime=endtime, commit=False) - if commit: self.commit() return updated - def get_conflicting_overlapping_claims(self, claim_id): + def get_overlapping_claims(self, claim_id, claim_status='claimed'): '''returns a list of claimed claims which overlap with given claim and which prevent the given claim to be claimed (cause it to be in conflict)''' - query = '''SELECT * from resource_allocation.get_conflicting_overlapping_claims(%s)''' - return list(self._executeQuery(query, (claim_id,), fetch=_FETCH_ALL)) + if isinstance(claim_status, basestring): + claim_status_id = self.getResourceClaimStatusId(claim_status) + else: + claim_status_id = claim_status - def get_conflicting_overlapping_tasks(self, claim_id): + query = '''SELECT * from resource_allocation.get_overlapping_claims(%s, %s)''' + return list(self._executeQuery(query, (claim_id, claim_status_id), fetch=_FETCH_ALL)) + + def get_overlapping_tasks(self, claim_id, claim_status='claimed'): '''returns a list of tasks which overlap with given claim(s) and which prevent the given claim(s) to be claimed (cause it to be in conflict)''' - conflicting_claims = self.get_conflicting_overlapping_claims(claim_id) + conflicting_claims = self.get_overlapping_claims(claim_id, claim_status) task_ids = set([c['task_id'] for c in conflicting_claims]) return self.getTasks(task_ids=task_ids) def get_max_resource_usage_between(self, resource_id, lower_bound, upper_bound, claim_status='claimed'): - result = {'usage': 0, 'status_id': claim_status_id, 'as_of_timestamp': lower_bound, 'resource_id': resource_id} - if isinstance(claim_status, basestring): claim_status_id = self.getResourceClaimStatusId(claim_status) else: claim_status_id = claim_status + result = {'usage': 0, 'status_id': claim_status_id, 'as_of_timestamp': lower_bound, 'resource_id': resource_id} + query = '''SELECT * from resource_allocation.get_max_resource_usage_between(%s, %s, %s, %s)''' qresult = self._executeQuery(query, (resource_id, claim_status_id, lower_bound, upper_bound), fetch=_FETCH_ONE) @@ -1613,12 +1679,12 @@ class RADatabase: self.commit() return ids - def getResourceUsages(self, lower_bound=None, upper_bound=None, resource_ids=None, resource_types=None, claim_statuses=None): - """ Get the resource usages over time within the optionally given time window, resource_ids, resource_types, and/or claim_statuses. + def getResourceUsages(self, lower_bound=None, upper_bound=None, resource_ids=None, claim_statuses=None): + """ Get the resource usages over time within the optionally given time window, resource_ids, +and/or claim_statuses. :param lower_bound: filter for usages newer than lower_bound :param upper_bound: filter for usages older than upper_bound :param resource_ids: filter for usages for the given resource id(s) - :param resource_types: filter for usages for the given resource type(s) :param claim_statuses: filter for usages for the given claim status(es) :return: a nested dict with resource_id at the first level, then claim_status(name) at the second level, and then a list of time ordered usages. """ @@ -1644,24 +1710,6 @@ class RADatabase: conditions.append('resource_id in %s') qargs.append(tuple(resource_ids)) - if resource_types is not None: - if isinstance(resource_types, basestring): - resource_types = [resource_types] - elif not isinstance(resource_types, collections.Iterable): - resource_types = [resource_types] - - # convert any resource_type name to id - resource_type_names = set([x for x in resource_types if isinstance(x, basestring)]) - if resource_type_names: - resource_type_name_to_id = {x['name']:x['id'] for x in self.getResourceTypes()} - resource_type_ids = [resource_type_name_to_id[x] if isinstance(x, basestring) else x - for x in resource_types] - else: - resource_type_ids = [x for x in resource_types] - - conditions.append('type_id in %s') - qargs.append(tuple(resource_type_ids)) - if claim_statuses is not None: if isinstance(claim_statuses, basestring): claim_statuses = [claim_statuses] diff --git a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql index e8389aeea5d35fe4362529e576e6c3dacf847f90..b9656b4f5014e8876cf147b9df0b6918310d0226 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql +++ b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql @@ -264,23 +264,9 @@ DECLARE usage_at_or_before_end RECORD; intermediate_usage RECORD; BEGIN - -- find last known resource_usage at or before claim starttime - SELECT * FROM resource_allocation.resource_usage ru - WHERE ru.resource_id = new_claim.resource_id - AND ru.status_id = new_claim.status_id - AND ru.as_of_timestamp <= new_claim.starttime - ORDER BY ru.as_of_timestamp DESC - LIMIT 1 - INTO usage_at_or_before_start; - - -- find last known resource_usage before claim endtime - SELECT * FROM resource_allocation.resource_usage ru - WHERE ru.resource_id = new_claim.resource_id - AND ru.status_id = new_claim.status_id - AND ru.as_of_timestamp <= new_claim.endtime - ORDER BY ru.as_of_timestamp DESC - LIMIT 1 - INTO usage_at_or_before_end; + -- find resource_usage at claim starttime + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(new_claim.resource_id, new_claim.status_id, new_claim.starttime, false, false, false) into usage_at_or_before_start; + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(new_claim.resource_id, new_claim.status_id, new_claim.endtime, false, false, false) into usage_at_or_before_end; --add new_claim.claim_size at claim starttime to resource_usage depending on state of usage_at_or_before_start IF usage_at_or_before_start IS NOT NULL THEN @@ -333,21 +319,40 @@ COMMENT ON FUNCTION resource_allocation.process_new_claim_into_resource_usages(n CREATE OR REPLACE FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims() RETURNS void AS $$ +DECLARE + resource virtual_instrument.resource; +BEGIN + FOR resource IN (SELECT * FROM virtual_instrument.resource ORDER BY id) LOOP + --TODO: permance boost possible when taking advantage of fact that we are looping in time sequential order. (less seeks (selects) needed) + PERFORM resource_allocation.rebuild_resource_usages_table_from_claims_for_resource(resource.id); + END LOOP; +END; +$$ LANGUAGE plpgsql; +ALTER FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims() OWNER TO resourceassignment; +COMMENT ON FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims() + IS 'function which truncates the resource_usages table, and repopulates it by calling process_new_claim_into_resource_usages for each known claim.'; + +--------------------------------------------------------------------------------------------------------------------- + +CREATE OR REPLACE FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims_for_resource(_resource_id int) + RETURNS void AS +$$ DECLARE claim resource_allocation.resource_claim; + usage resource_allocation.resource_usage; BEGIN - LOCK TABLE resource_allocation.resource_claim IN EXCLUSIVE MODE; + LOCK TABLE resource_allocation.resource_claim IN ACCESS SHARE MODE; LOCK TABLE resource_allocation.resource_usage IN EXCLUSIVE MODE; - TRUNCATE TABLE resource_allocation.resource_usage RESTART IDENTITY CASCADE; + DELETE FROM resource_allocation.resource_usage WHERE resource_id = _resource_id; - FOR claim IN SELECT * FROM resource_allocation.resource_claim LOOP + FOR claim IN (SELECT * FROM resource_allocation.resource_claim WHERE resource_id = _resource_id ORDER BY starttime, endtime) LOOP PERFORM resource_allocation.process_new_claim_into_resource_usages(claim); END LOOP; END; $$ LANGUAGE plpgsql; -ALTER FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims() OWNER TO resourceassignment; -COMMENT ON FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims() - IS 'function which truncates the resource_usages table, and repopulates it by calling process_new_claim_into_resource_usages for each known claim.'; +ALTER FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims_for_resource(_resource_id int) OWNER TO resourceassignment; +COMMENT ON FUNCTION resource_allocation.rebuild_resource_usages_table_from_claims_for_resource(_resource_id int) + IS 'function which rebuilds the resource_usages table for a specific resource.'; --------------------------------------------------------------------------------------------------------------------- @@ -361,39 +366,25 @@ DECLARE intermediate_usage RECORD; BEGIN -- find resource_usage at claim starttime - SELECT * FROM resource_allocation.resource_usage ru - WHERE ru.resource_id = old_claim.resource_id - AND ru.status_id = old_claim.status_id - AND ru.as_of_timestamp = old_claim.starttime - LIMIT 1 - INTO usage_at_start; + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(old_claim.resource_id, old_claim.status_id, old_claim.starttime, true, false, true) into usage_at_start; - -- find last known resource_usage at claim endtime - SELECT * FROM resource_allocation.resource_usage ru - WHERE ru.resource_id = old_claim.resource_id - AND ru.status_id = old_claim.status_id - AND ru.as_of_timestamp = old_claim.endtime - LIMIT 1 - INTO usage_at_end; - - -- both usage_at_start and usage_at_end should exist (NOT NULL) IF usage_at_start IS NULL THEN - RAISE EXCEPTION 'resource_allocation.on_delete_claim_update_resource_usages: usage_at_start should not be NULL.'; + RAISE EXCEPTION 'process_old_claim_outof_resource_usages(%) cannot find usage_at_start', old_claim; END IF; + + + -- and find resource_usage at claim endtime + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(old_claim.resource_id, old_claim.status_id, old_claim.endtime, true, false, true) into usage_at_end; + IF usage_at_end IS NULL THEN - RAISE EXCEPTION 'resource_allocation.on_delete_claim_update_resource_usages: usage_at_end should not be NULL.'; + RAISE EXCEPTION 'process_old_claim_outof_resource_usages(%) cannot find usage_at_end', old_claim; END IF; + IF usage_at_start.usage = old_claim.claim_size THEN IF usage_at_end.usage = 0 THEN -- find resource_usage before claim starttime - SELECT * FROM resource_allocation.resource_usage ru - WHERE ru.resource_id = old_claim.resource_id - AND ru.status_id = old_claim.status_id - AND ru.as_of_timestamp < old_claim.starttime - ORDER BY ru.as_of_timestamp DESC - LIMIT 1 - INTO usage_before_start; + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(old_claim.resource_id, old_claim.status_id, old_claim.starttime, false, true, false) into usage_before_start; IF usage_before_start IS NULL OR (usage_before_start IS NOT NULL AND usage_before_start.usage = 0) THEN --usage_at_start was 'caused' by this deleted claim only, so delete it @@ -434,28 +425,90 @@ COMMENT ON FUNCTION resource_allocation.process_old_claim_outof_resource_usages( --------------------------------------------------------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION resource_allocation.get_resource_usage_at(_resource_id int, _claim_status_id int, _timestamp timestamp) +CREATE OR REPLACE FUNCTION resource_allocation.get_resource_usage_at_or_before(_resource_id int, _claim_status_id int, _timestamp timestamp, exactly_at boolean default false, only_before boolean default false, rebuild_usage_when_not_found boolean default false) RETURNS resource_allocation.resource_usage AS $$ DECLARE - result record; + result resource_allocation.resource_usage; BEGIN SELECT * FROM resource_allocation.resource_usage ru WHERE ru.resource_id = _resource_id AND ru.status_id = _claim_status_id - AND ru.as_of_timestamp < _timestamp + AND ru.as_of_timestamp <= _timestamp ORDER BY ru.as_of_timestamp DESC LIMIT 1 INTO result; + -- check if as_of_timestamp is exactly_at _timestamp + IF exactly_at AND result IS NOT NULL THEN + IF result.as_of_timestamp <> _timestamp THEN + result := NULL; + END IF; + END IF; + + -- check if as_of_timestamp is before _timestamp + IF only_before AND result IS NOT NULL THEN + IF result.as_of_timestamp >= _timestamp THEN + result := NULL; + END IF; + END IF; + + -- rebuild usage when not found + IF rebuild_usage_when_not_found AND result IS NULL THEN + RAISE NOTICE 'get_resource_usage_at_or_before(_resource_id=%, status_id=%, timestamp=%, exactly_at=%, only_before=%, rebuild_usage_when_not_found=%): result should not be NULL. Rebuilding usages table for resource %.', _resource_id, _claim_status_id, _timestamp, exactly_at, only_before, rebuild_usage_when_not_found, _resource_id; + PERFORM resource_allocation.rebuild_resource_usages_table_from_claims_for_resource(_resource_id); + RAISE NOTICE 'get_resource_usage_at_or_before(_resource_id=%, status_id=%, timestamp=%, exactly_at=%, only_before=%, rebuild_usage_when_not_found=%): Finished rebuilding usages table for resource %.', _resource_id, _claim_status_id, _timestamp, exactly_at, only_before, rebuild_usage_when_not_found, _resource_id; + + -- try again, but now without the option to rebuild_usage_when_not_found (to prevent endless recursion) + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(_resource_id, _claim_status_id, _timestamp, exactly_at, only_before, false) INTO result; + RAISE NOTICE 'get_resource_usage_at_or_before(_resource_id=%, status_id=%, timestamp=%, exactly_at=%, only_before=%, rebuild_usage_when_not_found=%): after rebuild, result=%.', _resource_id, _claim_status_id, _timestamp, exactly_at, only_before, rebuild_usage_when_not_found, result; + END IF; + + IF result IS NULL THEN + -- if result is still null (after possible rebuild etc), then return a 'default' usage of 0 + result.resource_id = _resource_id; + result.status_id = _claim_status_id; + result.as_of_timestamp = _timestamp; + result.usage = 0; + END IF; + RETURN result; END; $$ LANGUAGE plpgsql; -ALTER FUNCTION resource_allocation.get_resource_usage_at(_resource_id int, _claim_status_id int, _timestamp timestamp) OWNER TO resourceassignment; -COMMENT ON FUNCTION resource_allocation.get_resource_usage_at(_resource_id int, _claim_status_id int, _timestamp timestamp) +ALTER FUNCTION resource_allocation.get_resource_usage_at_or_before(int, int, timestamp, boolean, boolean, boolean) OWNER TO resourceassignment; +COMMENT ON FUNCTION resource_allocation.get_resource_usage_at_or_before(int, int, timestamp, boolean, boolean, boolean) IS 'get the resource usage for the given _resource_id for claims with given _claim_status_id at the given _timestamp'; --------------------------------------------------------------------------------------------------------------------- +CREATE FUNCTION utcnow() + RETURNS timestamp AS +$$ + SELECT NOW() AT TIME ZONE 'UTC'; +$$ LANGUAGE SQL; +ALTER FUNCTION utcnow() OWNER TO resourceassignment; +COMMENT ON FUNCTION utcnow() + IS 'get the current time in utc timezone as timestamp (without timezone)'; + +--------------------------------------------------------------------------------------------------------------------- + +CREATE OR REPLACE FUNCTION resource_allocation.get_current_resource_usage(_resource_id int, _claim_status_id int) + RETURNS resource_allocation.resource_usage AS +$$ +DECLARE + result resource_allocation.resource_usage; + now timestamp; +BEGIN + SELECT * FROM utcnow() INTO now; + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(_resource_id, _claim_status_id, now, false, false, false) into result; + RETURN result; +END; +$$ LANGUAGE plpgsql; +ALTER FUNCTION resource_allocation.get_current_resource_usage(_resource_id int, _claim_status_id int) OWNER TO resourceassignment; +COMMENT ON FUNCTION resource_allocation.get_current_resource_usage(_resource_id int, _claim_status_id int) + IS 'get the current resource usage for the given _resource_id for claims with given _claim_status_id'; + +--------------------------------------------------------------------------------------------------------------------- + CREATE OR REPLACE FUNCTION resource_allocation.get_max_resource_usage_between(_resource_id int, _claim_status_id int, _lower timestamp, _upper timestamp) RETURNS resource_allocation.resource_usage AS $$ @@ -466,10 +519,16 @@ BEGIN WHERE ru.resource_id = _resource_id AND ru.status_id = _claim_status_id AND ru.as_of_timestamp >= _lower - AND ru.as_of_timestamp <= _upper + AND ru.as_of_timestamp < _upper ORDER BY ru.usage DESC LIMIT 1 INTO result; + IF result IS NULL THEN + -- apparently there are no resource_usage rows between _lower and _upper + -- so, take the first before _lower, as that value is still valid between _lower and _upper in this case. + SELECT * FROM resource_allocation.get_resource_usage_at_or_before(_resource_id, _claim_status_id, _lower, false, false, false) into result; + END IF; + RETURN result; END; $$ LANGUAGE plpgsql; @@ -497,6 +556,7 @@ BEGIN END IF; SELECT available FROM resource_monitoring.resource_capacity WHERE resource_id = _resource_id LIMIT 1 INTO available_capacity; + RETURN available_capacity - max_resource_usage_value; END; $$ LANGUAGE plpgsql; @@ -510,34 +570,11 @@ CREATE OR REPLACE FUNCTION resource_allocation.has_conflict_with_overlapping_cla RETURNS boolean AS $$ DECLARE - claim_claimed_status_id int := 1; --beware: hard coded instead of lookup for performance free_claimable_capacity bigint; - overlapping_claims_min_starttime timestamp; - overlapping_claims_max_endtime timestamp; BEGIN - -- this function is quite similar to resource_allocation.get_conflicting_overlapping_claims - -- for performance reasons we repeat the common code here instead of wrapping the common code in a function - - --get all overlapping_claims, check whether they cause a conflict or not. - SET LOCAL client_min_messages=warning; --prevent "table overlapping_claims does not exist, skipping" message - DROP TABLE IF EXISTS overlapping_claims; -- TODO: use CREATE TEMPORARY TABLE IF NOT EXISTS when we will use postgres 9.5+ - SET LOCAL client_min_messages=info; --back to normal log level - CREATE TEMPORARY TABLE overlapping_claims - ON COMMIT DROP - AS SELECT * FROM resource_allocation.resource_claim rc - WHERE rc.resource_id = claim.resource_id - AND rc.status_id = claim_claimed_status_id - AND rc.id <> claim.id - AND rc.endtime >= claim.starttime - AND rc.starttime < claim.endtime; - - --get the full time window of the overlapping claims - SELECT min(starttime) FROM overlapping_claims INTO overlapping_claims_min_starttime; - SELECT max(endtime) FROM overlapping_claims INTO overlapping_claims_max_endtime; - - -- get the free free_claimable_capacity for this resource for the full overlapping claim time window + -- get the free free_claimable_capacity for this resource for the claim's time window -- this does not include the current claim which is (or at least should be) tentative. - SELECT * FROM resource_allocation.get_resource_claimable_capacity_between(claim.resource_id, overlapping_claims_min_starttime, overlapping_claims_max_endtime) INTO free_claimable_capacity; + SELECT * FROM resource_allocation.get_resource_claimable_capacity_between(claim.resource_id, claim.starttime, claim.endtime) INTO free_claimable_capacity; return claim.claim_size > free_claimable_capacity; END; @@ -548,7 +585,7 @@ COMMENT ON FUNCTION resource_allocation.has_conflict_with_overlapping_claims(cla --------------------------------------------------------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION resource_allocation.get_conflicting_overlapping_claims(claim_id int) +CREATE OR REPLACE FUNCTION resource_allocation.get_overlapping_claims(claim_id int, status int default 1) --beware: hard coded status=1 for claimed claims RETURNS SETOF resource_allocation.resource_claim AS $$ DECLARE @@ -559,44 +596,34 @@ BEGIN LIMIT 1 INTO claim; - RETURN QUERY SELECT * FROM resource_allocation.get_conflicting_overlapping_claims(claim); + RETURN QUERY SELECT * FROM resource_allocation.get_overlapping_claims(claim, status); END; $$ LANGUAGE plpgsql; -ALTER FUNCTION resource_allocation.get_conflicting_overlapping_claims(claim_id int) OWNER TO resourceassignment; -COMMENT ON FUNCTION resource_allocation.get_conflicting_overlapping_claims(claim_id int) +ALTER FUNCTION resource_allocation.get_overlapping_claims(int, int) OWNER TO resourceassignment; +COMMENT ON FUNCTION resource_allocation.get_overlapping_claims(int, int) IS 'get set of (claimed) claims which cause the given claim to have conflict status.'; --------------------------------------------------------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION resource_allocation.get_conflicting_overlapping_claims(claim resource_allocation.resource_claim) +CREATE OR REPLACE FUNCTION resource_allocation.get_overlapping_claims(claim resource_allocation.resource_claim, status int default 1) --beware: hard coded status=1 for claimed claims RETURNS SETOF resource_allocation.resource_claim AS $$ -DECLARE - claim_claimed_status_id int := 1; --beware: hard coded instead of lookup for performance BEGIN -- this function is quite similar to resource_allocation.has_conflict_with_overlapping_claims -- for performance reasons we repeat the common code here instead of wrapping the common code in a function --get all overlapping_claims, check whether they cause a conflict or not. - SET LOCAL client_min_messages=warning; --prevent "table overlapping_claims does not exist, skipping" message - DROP TABLE IF EXISTS overlapping_claims; -- TODO: use CREATE TEMPORARY TABLE IF NOT EXISTS when we will use postgres 9.5+ - CREATE TEMPORARY TABLE overlapping_claims - ON COMMIT DROP - AS SELECT * FROM resource_allocation.resource_claim rc + RETURN QUERY SELECT * FROM resource_allocation.resource_claim rc WHERE rc.resource_id = claim.resource_id - AND rc.status_id = claim_claimed_status_id + AND rc.status_id = status AND rc.id <> claim.id AND rc.endtime >= claim.starttime AND rc.starttime < claim.endtime; - - RETURN QUERY SELECT * - FROM overlapping_claims oc - WHERE (SELECT * FROM resource_allocation.get_resource_claimable_capacity_between(claim.resource_id, oc.starttime, oc.endtime)) < claim.claim_size; END; $$ LANGUAGE plpgsql; -ALTER FUNCTION resource_allocation.get_conflicting_overlapping_claims(claim resource_allocation.resource_claim) OWNER TO resourceassignment; -COMMENT ON FUNCTION resource_allocation.get_conflicting_overlapping_claims(claim resource_allocation.resource_claim) - IS 'get set of (claimed) claims which cause the given claim to have conflict status.'; +ALTER FUNCTION resource_allocation.get_overlapping_claims(resource_allocation.resource_claim, int) OWNER TO resourceassignment; +COMMENT ON FUNCTION resource_allocation.get_overlapping_claims(resource_allocation.resource_claim, int) + IS 'get set of claims (with given status) which overlap with the given claim.'; --------------------------------------------------------------------------------------------------------------------- @@ -619,7 +646,7 @@ BEGIN -- bounce any inserted claim which is not tentative IF TG_OP = 'INSERT' THEN IF NEW.status_id <> claim_tentative_status_id THEN - RAISE EXCEPTION 'newly inserted claims should not have status other than tentative; claim: %', NEW; + RAISE EXCEPTION 'newly inserted claims should not have status other than tentative (%); new claim: % has status %', claim_tentative_status_id, NEW, NEW.status_id; END IF; END IF; @@ -646,6 +673,13 @@ BEGIN END IF; END IF; + IF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN + --update the resource usages affected by this claim + --do this before we check for conflicts, because this claim might be shifted for example + --which might influence the resource_usages which determine wheter a claim fits. + PERFORM resource_allocation.process_old_claim_outof_resource_usages(OLD); + END IF; + --only check claim if status and/or claim_size and/or start/end time changed IF TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND (OLD.status_id <> NEW.status_id OR OLD.claim_size <> NEW.claim_size OR @@ -708,10 +742,8 @@ DECLARE affected_claim resource_allocation.resource_claim; claim_has_conflicts boolean; BEGIN - IF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN - --update the resource usages affected by this claim - PERFORM resource_allocation.process_old_claim_outof_resource_usages(OLD); - END IF; + --do not process_old_claim_outof_resource_usages(OLD) + --because that has been done already in before_claim_insertupdatedelete IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN --update the resource usages affected by this claim diff --git a/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py b/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py index 156a34b6802b04833e74b1c2c70d86ab83c44d3b..f2c4a5296916dd03466b25d3b0e6f2ccf4160b9d 100755 --- a/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py +++ b/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py @@ -25,6 +25,7 @@ import os from datetime import datetime, timedelta from dateutil import parser import logging +from pprint import pformat logger = logging.getLogger(__name__) @@ -159,7 +160,7 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): # --- tests start here - # + # integrity tests of postgres database itself # # Note: These are meant to make sure the setup generally works and all sql scripts were applied. @@ -998,13 +999,14 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual(len(specifications), 2) def test_getSpecification_normal_use_select_one_succeeds(self): - """ Verify if radb.getSpecification() returns a list containing a single specification """ + """ Verify if radb.getSpecification() returns a single single specification """ spec_ids = [self._insert_test_spec(), self._insert_test_spec(), self._insert_test_spec()] - specifications = self.radb.getSpecification(spec_ids[1]) + specification = self.radb.getSpecification(spec_ids[1]) - self.assertEqual(len(specifications), 1) + self.assertTrue(specification) + self.assertEqual(spec_ids[1], specification['id']) def test_task_and_claim_conflicts(self): # TODO: split up once the test setup is faster (not creating a new db for each test method) @@ -1013,7 +1015,7 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual(100, self.radb.getResources(117, include_availability=True)[0]['total_capacity']) now = datetime.utcnow() - now -= timedelta(seconds=now.second, microseconds=now.microsecond) + now -= timedelta(minutes=now.minute, seconds=now.second, microseconds=now.microsecond) # round to full hour result = self.radb.insertSpecificationAndTask(0, 0, 'approved', 'observation', now, now+timedelta(hours=1), 'foo', 'CEP4') self.assertTrue(result['inserted']) @@ -1079,11 +1081,10 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertTrue(self.radb.updateTask(task_id1, task_status='scheduled')) self.assertEqual('scheduled', self.radb.getTask(task_id1)['status']) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_claims(t1_claim_ids[0]))) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_tasks(t1_claim_ids[0]))) + self.assertEqual(0, len(self.radb.get_overlapping_claims(t1_claim_ids[0]))) + self.assertEqual(0, len(self.radb.get_overlapping_tasks(t1_claim_ids[0]))) self.assertEqual(40, self.radb.get_max_resource_usage_between(117, task1['starttime'], task1['starttime'], 'claimed')['usage']) - self.assertEqual(0, self.radb.get_max_resource_usage_between(117, task1['starttime']-timedelta(hours=2), task1['starttime']-timedelta(hours=1), 'claimed')['usage']) logger.info('------------------------------ concludes task 1 ------------------------------') @@ -1115,9 +1116,9 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual('conflict', self.radb.getTask(task_id2)['status']) self.assertEqual(set([t1_claim_ids[0]]), set(c['id'] for c in - self.radb.get_conflicting_overlapping_claims(t2_claim_ids[0]))) + self.radb.get_overlapping_claims(t2_claim_ids[0]))) self.assertEqual(set([task_id1]), set(t['id'] for t in - self.radb.get_conflicting_overlapping_tasks(t2_claim_ids[0]))) + self.radb.get_overlapping_tasks(t2_claim_ids[0]))) #try to connect this claim to task1, should fail self.assertFalse(self.radb.updateResourceClaims(t2_claim_ids, task_id=task_id1)) @@ -1141,8 +1142,8 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual('tentative', self.radb.getResourceClaim(t2_claim_ids[0])['status']) self.assertEqual('approved', self.radb.getTask(task_id2)['status']) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_claims(t2_claim_ids[0]))) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_tasks(t2_claim_ids[0]))) + self.assertEqual(0, len(self.radb.get_overlapping_claims(t2_claim_ids[0]))) + self.assertEqual(0, len(self.radb.get_overlapping_tasks(t2_claim_ids[0]))) # try to update the claim status to claimed, should succeed now self.assertTrue(self.radb.updateResourceClaims(t2_claim_ids, status='claimed')) @@ -1152,8 +1153,8 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertTrue(self.radb.updateTask(task_id2, task_status='scheduled')) self.assertEqual('scheduled', self.radb.getTask(task_id2)['status']) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_claims(t2_claim_ids[0]))) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_tasks(t2_claim_ids[0]))) + self.assertEqual(0, len(self.radb.get_overlapping_claims(t2_claim_ids[0]))) + self.assertEqual(0, len(self.radb.get_overlapping_tasks(t2_claim_ids[0]))) # updating task/claim start/endtime should work, even for scheduled tasks with claimed claims # effect might be that a scheduled tasks goes to conflict @@ -1172,7 +1173,11 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): # updating task/claim start/endtime should work, even for scheduled tasks with claimed claims # effect might be that a scheduled tasks goes to conflict # now, make simple endtime adjustment, task should stay scheduled + + logger.info("resource usages:\n%s", pformat(self.radb.getResourceUsages(now-timedelta(days=1.0), now+timedelta(days=2.0), 117))) self.assertTrue(self.radb.updateTaskAndResourceClaims(task_id2, endtime=now+timedelta(hours=2.75))) + logger.info("resource usages:\n%s", pformat(self.radb.getResourceUsages(now-timedelta(days=1.0), now+timedelta(days=2.0), 117))) + # now the task and claim status should still be scheduled/claimed self.assertEqual('scheduled', self.radb.getTask(task_id2)['status']) self.assertEqual('claimed', self.radb.getResourceClaim(t2_claim_ids[0])['status']) @@ -1228,9 +1233,9 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): # and the task's status should be conflict as well self.assertEqual('conflict', self.radb.getTask(task_id3)['status']) self.assertEqual(set([t1_claim_ids[0], t2_claim_ids[0]]), set(c['id'] for c in - self.radb.get_conflicting_overlapping_claims(t3_claim_ids[0]))) + self.radb.get_overlapping_claims(t3_claim_ids[0]))) self.assertEqual(set([task_id1, task_id2]), set(t['id'] for t in - self.radb.get_conflicting_overlapping_tasks(t3_claim_ids[0]))) + self.radb.get_overlapping_tasks(t3_claim_ids[0]))) # try to update the task status to scheduled, should not succeed, since it's claims are not 'claimed' yet. self.assertFalse(self.radb.updateTask(task_id3, task_status='scheduled')) @@ -1248,9 +1253,9 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual('conflict', self.radb.getTask(task_id3)['status']) self.assertEqual(set([t2_claim_ids[0]]), set(c['id'] for c in - self.radb.get_conflicting_overlapping_claims(t3_claim_ids[0]))) + self.radb.get_overlapping_claims(t3_claim_ids[0]))) self.assertEqual(set([task_id2]), set(t['id'] for t in - self.radb.get_conflicting_overlapping_tasks(t3_claim_ids[0]))) + self.radb.get_overlapping_tasks(t3_claim_ids[0]))) # do conflict resolution, reduce claim size (but keep overlapping with task2) self.assertTrue(self.radb.updateResourceClaim(t3_claim_ids[0], claim_size=5)) @@ -1259,8 +1264,9 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual('tentative', self.radb.getResourceClaim(t3_claim_ids[0])['status']) self.assertEqual('approved', self.radb.getTask(task_id3)['status']) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_claims(t3_claim_ids[0]))) - self.assertEqual(0, len(self.radb.get_conflicting_overlapping_tasks(t3_claim_ids[0]))) + self.assertEqual(1, len(self.radb.get_overlapping_claims(t3_claim_ids[0]))) + self.assertEqual(1, len(self.radb.get_overlapping_tasks(t3_claim_ids[0]))) + self.assertEqual(task2['id'], self.radb.get_overlapping_tasks(t3_claim_ids[0])[0]['id']) # try to update the claim status to claimed, should succeed now self.assertTrue(self.radb.updateResourceClaims(t3_claim_ids, status='claimed')) @@ -1291,6 +1297,256 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): self.assertEqual(0, self.radb.get_max_resource_usage_between(117, task1['starttime']-timedelta(hours=2), task1['starttime']-timedelta(hours=1), 'claimed')['usage']) + def test_overlapping_claims(self): + # this is a special testcase to prove a bug found at 2017-08-16 + # the bug was that a claim that should fit, does not fit according to the radb claim-methods. + # first, we'll prove that the bug exists (and that this test fails), + # and then, we'll fix the code, (so this test succeeds) + + # for testing purposous let's give CEP4 storage a total size of 100 + self.assertTrue(self.radb.updateResourceAvailability(117, available_capacity=100, total_capacity=100)) + self.assertEqual(100, self.radb.getResources(117, include_availability=True)[0]['total_capacity']) + + now = datetime.utcnow() + now -= timedelta(minutes=now.minute, seconds=now.second, microseconds=now.microsecond) # round to full hour + + #insert one task, and reuse that for multiple overlapping claims + result = self.radb.insertSpecificationAndTask(0, 0, 'approved', 'observation', now, now+timedelta(hours=1), 'foo', 'CEP4') + self.assertTrue(result['inserted']) + task_id = result['task_id'] + + task = self.radb.getTask(task_id) + self.assertTrue(task) + self.assertEqual(task_id, task['id']) + + #create two overlapping claims + claims = [ { 'resource_id': 117, + 'starttime': now, + 'endtime': now+timedelta(hours=0.75), + 'status': 'tentative', + 'claim_size': 40 }, + {'resource_id': 117, + 'starttime': now+timedelta(hours=0.25), + 'endtime': now + timedelta(hours=1), + 'status': 'tentative', + 'claim_size': 40} ] + + # insert the claims + claim_ids = self.radb.insertResourceClaims(task_id, claims, 'foo', 1, 1) + self.assertEqual(2, len(claim_ids)) + claims_org = claims + + #get claim using t1_claim_ids, and check if db version is equal to original + claims = self.radb.getResourceClaims(claim_ids=claim_ids) + self.assertEqual(2, len(claims)) + for claim, claim_org in zip(claims, claims_org): + for key, value in claim_org.items(): + if key != 'status': + self.assertEqual(value, claim_org[key]) + + # try to update the claim status to claimed, should succeed. + self.assertTrue(self.radb.updateResourceClaims(claim_ids, status='claimed')) + for claim in self.radb.getResourceClaims(claim_ids=claim_ids): + self.assertEqual('claimed', claim['status']) + + # check the resource usage trend + logger.info("resource usages:\n%s", pformat(self.radb.getResourceUsages(now-timedelta(hours=1.0), now+timedelta(hours=2.0), 117))) + self.assertEqual(0, self.radb.get_max_resource_usage_between(117, now-timedelta(hours=1.0), now-timedelta(hours=0.01), 'claimed')['usage']) + self.assertEqual(40, self.radb.get_max_resource_usage_between(117, now+timedelta(hours=0.0), now+timedelta(hours=0.2), 'claimed')['usage']) + self.assertEqual(80, self.radb.get_max_resource_usage_between(117, now+timedelta(hours=0.3), now+timedelta(hours=0.6), 'claimed')['usage']) + self.assertEqual(40, self.radb.get_max_resource_usage_between(117, now+timedelta(hours=0.80), now+timedelta(hours=1.0), 'claimed')['usage']) + + #check for a time range encapsulating the full task + self.assertEqual(80, self.radb.get_max_resource_usage_between(117, now+timedelta(hours=-0.1), now+timedelta(hours=1.1), 'claimed')['usage']) + + #check for a time range not including the task + self.assertEqual(0, self.radb.get_max_resource_usage_between(117, now+timedelta(hours=1.1), now+timedelta(hours=2.0), 'claimed')['usage']) + self.assertEqual(0, self.radb.get_max_resource_usage_between(117, now-timedelta(hours=1.1), now-timedelta(hours=1.0), 'claimed')['usage']) + + # check that there are no overlapping conflicting claims/tasks + for claim in claims: + #both claims should overlap with one (the other) claim + self.assertEqual(1, len(self.radb.get_overlapping_claims(claim['id'], 'claimed'))) + self.assertEqual(1, len(self.radb.get_overlapping_tasks(claim['id'], 'claimed'))) + + #and there should be no overlapping claims of other status + self.assertEqual(0, len(self.radb.get_overlapping_claims(claim['id'], 'tentative'))) + self.assertEqual(0, len(self.radb.get_overlapping_tasks(claim['id'], 'tentative'))) + + #check claimable_capacity for various timestamps + self.assertEqual(100, self.radb.get_resource_claimable_capacity(117, now-timedelta(hours=1.0), now-timedelta(hours=1.0))['claimable_capacity']) + self.assertEqual(60, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=0.0), now+timedelta(hours=0.0))['claimable_capacity']) + self.assertEqual(60, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=0.2), now+timedelta(hours=0.2))['claimable_capacity']) + self.assertEqual(20, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=0.3), now+timedelta(hours=0.3))['claimable_capacity']) + self.assertEqual(20, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=0.5), now+timedelta(hours=0.5))['claimable_capacity']) + self.assertEqual(60, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=0.75), now+timedelta(hours=0.75))['claimable_capacity']) + self.assertEqual(60, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=0.8), now+timedelta(hours=0.8))['claimable_capacity']) + self.assertEqual(100, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=1.0), now+timedelta(hours=1.0))['claimable_capacity']) + self.assertEqual(100, self.radb.get_resource_claimable_capacity(117, now+timedelta(hours=10.0), now+timedelta(hours=10.0))['claimable_capacity']) + + #check claimable_capacity for full task's timewindow (+extra) + self.assertEqual(20, self.radb.get_resource_claimable_capacity(117, now-timedelta(hours=10.0), now+timedelta(hours=10.0))['claimable_capacity']) + + + #add an extra claim, overlapping with only the last claim of size 40. So it should fit (100-40=60 and 60>30). + extra_claim = { 'resource_id': 117, + 'starttime': now+timedelta(hours=0.8), + 'endtime': now+timedelta(hours=0.9), + 'status': 'tentative', + 'claim_size': 30 } + extra_claim_ids = self.radb.insertResourceClaims(task_id, [extra_claim], 'foo', 1, 1) + self.assertEqual(1, len(extra_claim_ids)) + + #check the extra_claim's status, should be tentative. (used to be conflict before bug of 2017-08-16) + for claim in self.radb.getResourceClaims(claim_ids=extra_claim_ids): + self.assertEqual('tentative', claim['status']) + + # update the extra_claim status to 'claimed'. Should succeed. + self.assertTrue(self.radb.updateResourceClaims(extra_claim_ids, status='claimed')) #(used to fail before bug of 2017-08-16) + for claim in self.radb.getResourceClaims(claim_ids=extra_claim_ids): + self.assertEqual('claimed', claim['status']) #(used to be conflict before bug of 2017-08-16) + + #and finally, the task should be able to be scheduled as well. + self.assertTrue(self.radb.updateTask(task_id, task_status='scheduled')) + self.assertEqual('scheduled', self.radb.getTask(task_id)['status']) + + def test_reinsert_task(self): + # this is a special testcase to prove a bug found at 2017-08-28 + # the bug was that a specification is re-inserted, which causes the original spec to be deleted... + # ... wich cascades, and deletes the task, and its claims, and it's usages, but that failed on the usages. + # I've tried to reproduce the above bug which we see in production, + # but unfortunately, I cannot reproduce it. The code just works as intended. + # So, after consulting with JDM and AR, we decided to keep this test, and develop a consistency-check-method on the usage table. + # We'll keep this new test anyway, just to prove that these cases work as expected. + + # for testing purposous let's give CEP4 storage a total size of 100 + self.assertTrue(self.radb.updateResourceAvailability(117, available_capacity=100, total_capacity=100)) + self.assertEqual(100, self.radb.getResources(117, include_availability=True)[0]['total_capacity']) + + now = datetime.utcnow() + now -= timedelta(minutes=now.minute, seconds=now.second, microseconds=now.microsecond) # round to full hour + + # insert one task, and reuse that for multiple overlapping claims + result = self.radb.insertSpecificationAndTask(0, 0, 'approved', 'observation', now, now + timedelta(hours=1), 'first content', + 'CEP4') + self.assertTrue(result['inserted']) + task_id = result['task_id'] + + task = self.radb.getTask(task_id) + self.assertTrue(task) + self.assertEqual(task_id, task['id']) + self.assertEqual('first content', self.radb.getSpecification(task['specification_id'])['content']) + + # prove that we can re-insert the spec/task, and that the new task is indeed inserted and new + result = self.radb.insertSpecificationAndTask(0, 0, 'approved', 'observation', now, now + timedelta(hours=1), 'second content', + 'CEP4') + self.assertTrue(result['inserted']) + self.assertNotEqual(task_id, result['task_id']) # we should have a new id because it was re-inserted + task_id = result['task_id'] + + task = self.radb.getTask(task_id) + self.assertTrue(task) + self.assertEqual(task_id, task['id']) + self.assertEqual('second content', self.radb.getSpecification(task['specification_id'])['content']) #spec content should have been renewed + + # create and insert a claim + claim = {'resource_id': 117, + 'starttime': task['starttime'], + 'endtime': task['endtime'], + 'status': 'tentative', + 'claim_size': 40} + claim_ids = self.radb.insertResourceClaims(task_id, [claim], 'foo', 1, 1) + self.assertEqual(1, len(claim_ids)) + self.assertEqual(1, len(self.radb.getResourceClaims(claim_ids=claim_ids))) + + #check the extra_claim's status, should be tentative. + for claim in self.radb.getResourceClaims(claim_ids=claim_ids): + self.assertEqual('tentative', claim['status']) + + # update the extra_claim status to 'claimed'. Should succeed. + self.assertTrue(self.radb.updateResourceClaims(claim_ids, status='claimed')) + self.assertEqual(1, len(self.radb.getResourceClaims(claim_ids=claim_ids))) + for claim in self.radb.getResourceClaims(claim_ids=claim_ids): + self.assertEqual('claimed', claim['status']) + + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now-timedelta(hours=0.5), 'claimed')['usage']) + self.assertEqual(40, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=0.5), 'claimed')['usage']) + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=1.5), 'claimed')['usage']) + + # prove again that we can re-insert the spec/task (now with claims), and that the new task is indeed inserted and new, + # and that the claim(s) and usage(s) were actually deleted (via cascading deletes) + result = self.radb.insertSpecificationAndTask(0, 0, 'approved', 'observation', now, now + timedelta(hours=1), 'third content', + 'CEP4') + self.assertTrue(result['inserted']) + self.assertNotEqual(task_id, result['task_id']) # we should have a new id because it was re-inserted + task_id = result['task_id'] + + task = self.radb.getTask(task_id) + self.assertTrue(task) + self.assertEqual(task_id, task['id']) + self.assertEqual('third content', self.radb.getSpecification(task['specification_id'])['content']) #spec content should have been renewed + + # this newly inserted spec/task should have no claims anymore + self.assertEqual( 0, len(self.radb.getResourceClaims())) + # and all usages should now be 0 + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now-timedelta(hours=0.5), 'claimed')['usage']) + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=0.5), 'claimed')['usage']) + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=1.5), 'claimed')['usage']) + + # 2017-08-29: ok, we could not reproduce the bug found on production, + # so it seems there is a strange corner case which caused the usages table to become inconsistent. + # after consulting with JDM and AR, we decided to mimic this inconsistency by 'corrupting' the table manually in this test, + # and then act on the inconsistent table by detecting the inconsistency, and automatically repairing the usages table. + # so, let's do that in the remainder of this test. + + #insert a claim again (cause we don't have a claim anymore since we inserted the spec/taks above) + claim = {'resource_id': 117, + 'starttime': task['starttime'], + 'endtime': task['endtime'], + 'status': 'tentative', + 'claim_size': 40} + claim_ids = self.radb.insertResourceClaims(task_id, [claim], 'foo', 1, 1) + self.assertEqual(1, len(claim_ids)) + self.assertEqual(1, len(self.radb.getResourceClaims(claim_ids=claim_ids))) + + # usages should be ok + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now-timedelta(hours=0.5), 'tentative')['usage']) + self.assertEqual(40, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=0.5), 'tentative')['usage']) + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=1.5), 'tentative')['usage']) + + # now let's break the usages table (intentionally, to mimic the production inconsistenty) + # we shift one entry (where the claim starts) by one minute + # result should be that when we change the claim (or delete the claim cause it's task/spec was deleted), + # that the associated usage at the claim's starttime cannot be found anymore (which is the bug on production). + self.radb._executeQuery("UPDATE resource_allocation.resource_usage SET as_of_timestamp = %s WHERE as_of_timestamp = %s;", (now+timedelta(minutes=1), now)) + + # check that the usages were indeed changed (the first one shifted in time) + usages = self.radb.getResourceUsages()[117]['tentative'] + self.assertEqual({'usage': 40, 'as_of_timestamp': now+timedelta(minutes=1)}, usages[0]) + self.assertEqual({'usage': 0, 'as_of_timestamp': task['endtime']}, usages[1]) + + # and prove again that we can re-insert the spec/task (now with claims and a corrupted usage table), and that the new task is indeed inserted and new, + # and that the claim(s) and usage(s) were actually deleted (via cascading deletes) + # 2017-08-29: YEAH! the insert fails just like on production. Now we can start making a fix! + result = self.radb.insertSpecificationAndTask(0, 0, 'approved', 'observation', now, now + timedelta(hours=1), 'fourth content', + 'CEP4') + self.assertTrue(result['inserted']) + self.assertNotEqual(task_id, result['task_id']) # we should have a new id because it was re-inserted + task_id = result['task_id'] + + task = self.radb.getTask(task_id) + self.assertTrue(task) + self.assertEqual(task_id, task['id']) + self.assertEqual('fourth content', self.radb.getSpecification(task['specification_id'])['content']) #spec content should have been renewed + + # this newly inserted spec/task should have no claims anymore + self.assertEqual( 0, len(self.radb.getResourceClaims())) + # and all usages should now be 0 + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now-timedelta(hours=0.5), 'tentative')['usage']) + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=0.5), 'tentative')['usage']) + self.assertEqual( 0, self.radb.get_resource_usage_at_or_before(117, now+timedelta(hours=1.5), 'tentative')['usage']) + + if __name__ == "__main__": os.environ['TZ'] = 'UTC' logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO) diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/mom.py b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/mom.py index 6134a9152f2a6663b2f494b2115d2aa21b9615a7..b59b5ef705b9a1e75d4373880153fe9bfcb3606a 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/mom.py +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/mom.py @@ -71,6 +71,9 @@ def updateTaskMomDetails(task, momrpc): t['mom_object_group_mom2object_id'] = m.get('object_group_mom2objectid') t['mom_object_parent_group_id'] = m['parent_group_mom2id'] t['mom_object_parent_group_name'] = m['parent_group_name'] + elif t['type'] == 'reservation': + t['project_name'] = 'Reservations' + t['project_mom_id'] = -97 else: t['project_name'] = 'OTDB Only' t['project_mom_id'] = -98 diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/chartresourceusagecontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/chartresourceusagecontroller.js index de53c8935453539e956a1c2ae562ee44f877b138..443eca9eaa32ca8425c95577a4c1b35e90d815e7 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/chartresourceusagecontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/chartresourceusagecontroller.js @@ -86,6 +86,17 @@ chartResourceUsageControllerMod.controller('ChartResourceUsageController', ['$sc } var selected_resource_id = $scope.dataService.selected_resource_id; + if(selected_resource_id === undefined) { + //try to select first storage resource as default selected_resource_id + var storageResources = $scope.dataService.resources.filter(function(r) { return r.type_name == 'storage'; }); + if(storageResources.length > 0) { + $scope.dataService.selected_resource_id = storageResources[0].id; + } else { + //else, just the first resource + $scope.dataService.selected_resource_id = self.resources[0].id; + } + } + if(selected_resource_id === undefined) return; @@ -168,7 +179,16 @@ chartResourceUsageControllerMod.controller('ChartResourceUsageController', ['$sc value = usage.usage; } } - usage_data.push([timestamp.getTime(), value]); + if(usage_data.length > 0) { + //overwrite last value if timestamps are equal, otherwise append + if(usage_data[usage_data.length-1][0] == timestamp.getTime()) { + usage_data[usage_data.length-1][1] = value; + } else { + usage_data.push([timestamp.getTime(), value]); + } + } else { + usage_data.push([timestamp.getTime(), value]); + } t_idx += 1; } @@ -246,7 +266,6 @@ chartResourceUsageControllerMod.controller('ChartResourceUsageController', ['$sc } }; - $scope.$watch('dataService.selected_resource_id', updateChartDataAsync); $scope.$watch('dataService.resourceUsagesForSelectedResource', updateChartDataAsync); $scope.$watch('dataService.viewTimeSpan', updateChartDataAsync, true); $scope.$watch('$parent.enabled', function() { setTimeout(updateChartDataAsync, 500); } ); diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js index 5ccd61567093a89b30b436d434a4f1c524be721c..e973db2bd649e778de1b06d5b526ebe0ad28e213 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js @@ -382,14 +382,6 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$m loading: false } - $scope.totalDiskUsageChartSeries = []; - - var cep4storage_resource = dataService.resources.find(function(r) { return r.name == 'CEP4_storage:/data'; }); - if(cep4storage_resource) { - $scope.totalDiskUsageChartSeries = [{name:'Free', data:[100.0*cep4storage_resource.available_capacity/cep4storage_resource.total_capacity], color:'#a3f75c'}, - {name:'Used', data:[100.0*cep4storage_resource.used_capacity/cep4storage_resource.total_capacity], color:'#f45b5b'}]; - } - $scope.totalDiskUsageChartConfig = { options: { chart: { @@ -437,7 +429,7 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$m pointFormat: '{point.name}: <b>{point.percentage:.1f}%</b>' }, }, - series: $scope.totalDiskUsageChartSeries, + series: [], title: { text: 'CEP4 total disk usage' }, @@ -447,6 +439,27 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$m loading: false } + var cep4storage_resource = dataService.resources.find(function(r) { return r.name == 'CEP4_storage:/data'; }); + if(cep4storage_resource) { + dataService.getProjectsDiskUsage().then(function(result) { + if(result.found) { + var projects_du = result.projectdir.disk_usage; + var misc_du = cep4storage_resource.used_capacity - projects_du; + var total_cap = cep4storage_resource.total_capacity; + + $scope.totalDiskUsageChartConfig.series = [{name:'Free ' + dataService.humanreadablesize(cep4storage_resource.available_capacity, 1) + 'B', + data:[100.0*cep4storage_resource.available_capacity/total_cap], + color:'#66ff66'}, + {name:'Misc ' + dataService.humanreadablesize(misc_du, 1) + 'B', + data:[100.0*misc_du/total_cap], + color:'#aaaaff'}, + {name:'Projects ' + dataService.humanreadablesize(projects_du, 1) + 'B', + data:[100.0*projects_du/total_cap], + color:'#ff6666'}]; + } + }); + } + var loadTaskDiskUsage = function(otdb_id, force) { $scope.current_otdb_id = otdb_id; $scope.current_project_name = undefined; diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js index c4f6bbc54d0f4ae2e9c2870a568edc805254c9a3..88fee8beb924f412664c11aff40efb4e27068ae6 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js @@ -25,6 +25,7 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, self.resourcesWithClaims = []; self.filteredTasks = []; + self.filteredTasksDict = {}; self.taskTimes = {}; self.resourceClaimTimes = {}; @@ -60,15 +61,15 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, //loadResourceClaims is enabled when any controller using resourceclaims is enabled self.loadResourceClaims = false; - self.humanreadablesize = function(num) { + self.humanreadablesize = function(num, num_digits=3) { var units = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']; for(unit of units) { if(Math.abs(num) < 1000.0) { - return num.toPrecision(4).toString() + unit; + return num.toFixed(num_digits).toString() + unit; } num /= 1000.0; } - return num.toPrecision(5).toString() + 'Y'; + return num.toFixed(num_digits).toString() + 'Y'; } self.isTaskIdSelected = function(task_id) { @@ -222,28 +223,31 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, //only keep the currently loading chunks self.loadingChunksQueue = self.loadingChunksQueue.filter(function(c) { return c.loading; }); - var chunkFactor = self.projectMode ? 7 : 1; + var chunkFactor = self.projectMode ? 4 : 1; var hourInmsec = 3600000; - var dayInmsec = 24*hourInmsec; + var quartDayInmsec = 6*hourInmsec; for (var timestamp = lowerTS; timestamp < upperTS; ) { if(self.loadedHours.hasOwnProperty(timestamp)) { timestamp += hourInmsec; } else { - var chuckUpperLimit = Math.min(upperTS, timestamp + chunkFactor*dayInmsec); + var chuckUpperLimit = Math.min(upperTS, timestamp + chunkFactor*quartDayInmsec); for (var chunkTimestamp = timestamp; chunkTimestamp < chuckUpperLimit; chunkTimestamp += hourInmsec) { if(self.loadedHours.hasOwnProperty(chunkTimestamp)) break; - - self.loadedHours[chunkTimestamp] = true; } var hourLower = new Date(timestamp); var hourUpper = new Date(chunkTimestamp); if(hourUpper > hourLower) { var chunk = { lower: hourLower, upper: hourUpper, loaded: false, loading: false }; - self.loadingChunksQueue.push(chunk); + if(hourLower < self.lofarTime) { + //prepend at beginning of queue, so we load most recent data first + self.loadingChunksQueue.unshift(chunk); + } else { + self.loadingChunksQueue.push(chunk); + } } timestamp = chunkTimestamp; } @@ -255,6 +259,11 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, for(var i = 0; i < Math.min(3, self.loadingChunksQueue.length); i++) { setTimeout(self.loadNextChunk, i*250); } + + //load the usages as well, if needed. + if (self.loadResourceClaims) { + self.getUsagesForSelectedResource(); + } }; self.loadNextChunk = function() { @@ -282,6 +291,10 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, self.nrOfLoadingChunks -= 1; self.nrOfLoadedChunks += 1; + for (var timestamp = chunk.lower.getTime(); timestamp < chunk.upper.getTime(); timestamp += 3600000) { + self.loadedHours[timestamp] = true; + } + self.loadNextChunk(); }); } else { @@ -629,18 +642,12 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, self.getResources = function() { var defer = $q.defer(); $http.get('/rest/resources').success(function(result) { - self.resources = result.resources; + //at this moment, we have way too many resources to show in a gantt-tree. + //this make the webscheduler way too slow. + //so, only show the relevant resources, 116 and 117 which are CEP4 bandwith and storage. + self.resources = result.resources.filter(function(r) { return r.id==116 || r.id==117;}); self.resourceDict = self.toIdBasedDict(self.resources); - //try to select first storage resource as default selected_resource_id - var storageResources = self.resources.filter(function(r) { return r.type_name == 'storage'; }); - if(storageResources.length > 0) { - self.selected_resource_id = storageResources[0].id; - } else { - //else, just the first resource - self.selected_resource_id = self.resources[0].id; - } - defer.resolve(); }); @@ -759,7 +766,10 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http, self.getResourceGroups = function() { var defer = $q.defer(); $http.get('/rest/resourcegroups').success(function(result) { - self.resourceGroups = result.resourcegroups; + //at this moment, we have way too many resources to show in a gantt-tree. + //this make the webscheduler way too slow. + //so, only show the relevant resource groups, 1, which is the CEP4 group. + self.resourceGroups = result.resourcegroups.filter(function(r) { return r.id==1;}); self.resourceGroupsDict = self.toIdBasedDict(self.resourceGroups); defer.resolve(); @@ -1331,7 +1341,10 @@ dataControllerMod.controller('DataController', }); }, true); - $scope.$watch('dataService.filteredTaskChangeCntr', dataService.computeMinMaxTaskTimes); + $scope.$watch('dataService.filteredTaskChangeCntr', function() { + dataService.computeMinMaxTaskTimes(); + dataService.filteredTasksDict = dataService.toIdBasedDict(dataService.filteredTasks); + }); $scope.$watch('dataService.lofarTime', function() { if(dataService.autoFollowNow && (Math.round(dataService.lofarTime.getTime()/1000))%5==0) { @@ -1377,13 +1390,6 @@ dataControllerMod.controller('DataController', } }); - $scope.$watch('dataService.claimChangeCntr', function() { - $scope.$evalAsync(function() { - $scope.dataService.getUsagesForSelectedResource(); - $scope.dataService.getResource($scope.dataService.selected_resource_id); - }); - }); - $scope.$watch('dataService.selected_resource_id', function() { $scope.$evalAsync(function() { $scope.dataService.getUsagesForSelectedResource(); diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js index 4ebca480cf38a38e819ff72e7901e846d9dde4c5..debb2c8afb8ef9d67c572f1c3183a45b1aaeacdf 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js @@ -161,7 +161,7 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS //start with aggregating all tasks per type, //and plot these in the upper rows, //so we can see the observartion and pipeline scheduling usage/efficiency - for(var type of ['observation', 'pipeline']) { + for(var type of ['observation', 'pipeline', 'reservation']) { var typeTasks = tasks.filter(function(t) { return t.type == type;}).sort(function(a, b) { return a.starttime.getTime() - b.starttime.getTime(); });; var numTypeTasks = typeTasks.length; @@ -265,6 +265,10 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS tasks: [] }; + if(task.type == 'reservation' && project.name.toLowerCase().includes('reservation')) { + availableRow.name = project.name; + } + ganttProjectTypeRows.push(availableRow); ganttRows.push(availableRow); } diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js index 6df74997511eed35e938da801069f054ce7281fe..37006404dcb1c7441c09ff1df3eb99d629afd3de 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js @@ -153,7 +153,7 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat var resourceGroupMemberships = $scope.dataService.resourceGroupMemberships; - var taskDict = $scope.dataService.taskDict; + var tasksDict = $scope.dataService.filteredTasksDict; var numTasks = $scope.dataService.filteredTasks.length; var resourceClaimDict = $scope.dataService.resourceClaimDict; @@ -316,7 +316,7 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat //and finally assign each resourceclaim to its resource in each group for(var claim of resourceClaims) { var resourceId = claim.resource_id; - var task = taskDict[claim.task_id]; + var task = tasksDict[claim.task_id]; if(!task) { continue; @@ -368,24 +368,26 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat if(claims) { for(var claim of claims) { var taskId = claim.task_id; - var task = taskDict[taskId]; - if(taskId in aggregatedClaims) { - if(claim.starttime < aggregatedClaims[taskId].starttime) { - aggregatedClaims[taskId].starttime = claim.starttime.getTime() > task.starttime.getTime() ? claim.starttime : task.starttime; - } - if(claim.endtime > aggregatedClaims[taskId].endtime) { - aggregatedClaims[taskId].endtime = claim.endtime.getTime() < task.endtime.getTime() ? claim.endtime: task.endtime; - } - if(claim.status == 'conflict') { - aggregatedClaims[taskId].status = 'conflict'; - } else if(claim.status != aggregatedClaims[taskId].status && aggregatedClaims[taskId].status != 'conflict') { - aggregatedClaims[taskId].status = 'mixed'; + var task = tasksDict[taskId]; + if(task) { + if(taskId in aggregatedClaims) { + if(claim.starttime < aggregatedClaims[taskId].starttime) { + aggregatedClaims[taskId].starttime = claim.starttime.getTime() > task.starttime.getTime() ? claim.starttime : task.starttime; + } + if(claim.endtime > aggregatedClaims[taskId].endtime) { + aggregatedClaims[taskId].endtime = claim.endtime.getTime() < task.endtime.getTime() ? claim.endtime: task.endtime; + } + if(claim.status == 'conflict') { + aggregatedClaims[taskId].status = 'conflict'; + } else if(claim.status != aggregatedClaims[taskId].status && aggregatedClaims[taskId].status != 'conflict') { + aggregatedClaims[taskId].status = 'mixed'; + } + } else { + aggregatedClaims[taskId] = { starttime: claim.starttime, + endtime: claim.endtime, + status: claim.status + }; } - } else { - aggregatedClaims[taskId] = { starttime: claim.starttime, - endtime: claim.endtime, - status: claim.status - }; } } } @@ -424,7 +426,7 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat for(var ganttRow of ganttRows) { for(var taskId in aggregatedClaims) { var aggClaimForTask = aggregatedClaims[taskId]; - var task = taskDict[taskId]; + var task = tasksDict[taskId]; if(task) { var claimTask = { id: 'aggregatedClaimForTask_' + taskId + '_' + ganttRow.id, diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js index b0ac221dddb8ddf0bbc54e5b3da6c73513c2dc1c..e0c916cbdfd29ee745e1e7295950f20e40c567e5 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js @@ -765,6 +765,27 @@ gridControllerMod.directive('contextMenu', ['$document', '$window', function($do }); } + var selected_post_approved_observations = selected_tasks.filter(function(t) { return t.type == +'observation' && t.status != 'approved'; }); + + if(selected_post_approved_observations.length > 0 && dataService.config.sky_view_base_url) { + var liElement = angular.element('<li><a href="#">Sky view</a></li>'); + ulElement.append(liElement); + liElement.on('click', function() { + closeContextMenu(); + + var window_cntr = 0; + for(var obs of selected_post_approved_observations) { + var url = dataService.config.sky_view_base_url + '/' + obs.otdb_id; + url = row.grid.appScope.sanitize_url(url); + setTimeout(function(url_arg) { + $window.open(url_arg, '_blank'); + }, window_cntr*750, url); + window_cntr += 1; + } + }); + } + var ingest_tasks = selected_tasks.filter(function(t) { return t.ingest_status != undefined; }); if(ingest_tasks.length > 0 && dataService.config.lta_base_url) { @@ -851,30 +872,30 @@ gridControllerMod.directive('contextMenu', ['$document', '$window', function($do }); } - var schedulable_cep4_tasks = selected_cep4_tasks.filter(function(t) { return t.status == 'approved' || t.status == 'conflict' || t.status == 'error'; }); + var schedulable_tasks = selected_tasks.filter(function(t) { return t.status == 'approved' || t.status == 'conflict' || t.status == 'error'; }); - if(schedulable_cep4_tasks.length > 0) { - var liContent = '<li><a href="#">Schedule CEP4 task(s)</a></li>' + if(schedulable_tasks.length > 0) { + var liContent = '<li><a href="#">(Re)schedule CEP4 task(s)</a></li>' var liElement = angular.element(liContent); ulElement.append(liElement); liElement.on('click', function() { closeContextMenu(); - for(var pl of schedulable_cep4_tasks) { + for(var pl of schedulable_tasks) { var newTask = { id: pl.id, status: 'prescheduled' }; dataService.putTask(newTask); } }); } - var unschedulable_selected_cep4_tasks = selected_cep4_tasks.filter(function(t) { return t.status == 'prescheduled' || t.status == 'scheduled' || t.status == 'queued' || t.status == 'error'; }); + var unschedulable_selected_tasks = selected_tasks.filter(function(t) { return t.status == 'prescheduled' || t.status == 'scheduled' || t.status == 'queued' || t.status == 'error' || t.status == 'conflict'; }); - if(unschedulable_selected_cep4_tasks.length > 0) { - var liContent = '<li><a href="#">Unschedule (pre)scheduled/queued/error tasks</a></li>' + if(unschedulable_selected_tasks.length > 0) { + var liContent = '<li><a href="#">Unschedule (pre)scheduled/queued/error/conflict tasks</a></li>' var liElement = angular.element(liContent); ulElement.append(liElement); liElement.on('click', function() { closeContextMenu(); - for(var pl of unschedulable_selected_cep4_tasks) { + for(var pl of unschedulable_selected_tasks) { if(pl.status == 'queued') { var newTask = { id: pl.id, status: 'aborted' }; dataService.putTask(newTask); diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html index 480d94528976999431d1dab12fdee15f378ee4a3..e984e7f3e4fbe60cad50edfdc16d8d5cc1013877 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html @@ -150,7 +150,7 @@ </md-tab> </div> -<!-- <div ng-controller="GanttResourceController as ganttResourceCtrl" ng-init="enabled=false"> + <div ng-controller="GanttResourceController as ganttResourceCtrl" ng-init="enabled=false"> <md-tab label="Resources" md-on-select="enabled=true" md-on-deselect="enabled=false"> <div gantt data=ganttData api=options.api @@ -174,7 +174,7 @@ <highchart id="chart_resource_usage" config="chartConfig" style="margin: 12px;" ></highchart> </div> </md-tab> - </div>--> + </div> </md-tabs> </md-content> <div ng-controller="EventGridController as eventGridCtrl" ui-layout-init-height="250px"> diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py index ece9a2b8e80c3cb18eb7725e5dee84e45589bbc3..461f8860c5130c9854abff54e09ac904a6dd4bf0 100755 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py @@ -189,7 +189,8 @@ def projects(): def config(): config = {'mom_base_url':'', 'lta_base_url':'', - 'inspection_plots_base_url':'https://proxy.lofar.eu/inspect/HTML/'} + 'inspection_plots_base_url':'https://proxy.lofar.eu/inspect/HTML/', + 'sky_view_base_url':'http://dop344.astron.nl:5000/uvis/id'} if isProductionEnvironment(): config['mom_base_url'] = 'https://lofar.astron.nl/mom3' @@ -214,6 +215,32 @@ def resource(resource_id): return jsonify(result[0]) return jsonify({}) +@app.route('/rest/resources/<int:resource_id>/resourceclaims') +@gzipped +def resourceclaimsForResource(resource_id): + return resourceclaimsForResourceFromUntil(resource_id, None, None) + +@app.route('/rest/resources/<int:resource_id>/resourceclaims/<string:fromTimestamp>') +@gzipped +def resourceclaimsForResourceFrom(resource_id, fromTimestamp=None): + return resourceclaimsForResourceFromUntil(resource_id, fromTimestamp, None) + +@app.route('/rest/resources/<int:resource_id>/resourceclaims/<string:fromTimestamp>/<string:untilTimestamp>') +@gzipped +def resourceclaimsForResourceFromUntil(resource_id, fromTimestamp=None, untilTimestamp=None): + if fromTimestamp and isinstance(fromTimestamp, basestring): + fromTimestamp = asDatetime(fromTimestamp) + + if untilTimestamp and isinstance(untilTimestamp, basestring): + untilTimestamp = asDatetime(untilTimestamp) + + claims = radb().getResourceClaims(lower_bound=fromTimestamp, + upper_bound=untilTimestamp, + resource_ids=[resource_id], + extended=False, + include_properties=True) + return jsonify({'resourceclaims': claims}) + @app.route('/rest/resourcegroups') @gzipped def resourcegroups(): @@ -312,12 +339,41 @@ def getTasksFromUntil(fromTimestamp=None, untilTimestamp=None): untilTimestamp = asDatetime(untilTimestamp) tasks = radb().getTasks(fromTimestamp, untilTimestamp) - - updateTaskMomDetails(tasks, momqueryrpc) - updateTaskStorageDetails(tasks, sqrpc, curpc) + updateTaskDetails(tasks) return jsonify({'tasks': tasks}) +def updateTaskDetails(tasks): + #update the mom details and the storage details in parallel + t1 = Thread(target=updateTaskMomDetails, args=(tasks, momqueryrpc)) + t2 = Thread(target=updateTaskStorageDetails, args=(tasks, sqrpc, curpc)) + t1.daemon = True + t2.daemon = True + t1.start() + t2.start() + + #wait for mom details thread to finish + t1.join() + + #task details (such as name/description) from MoM are done + #get extra details on reserved resources for reservations (while the storage details still run in t2) + reservationTasks = [t for t in tasks if t['type'] == 'reservation'] + if reservationTasks: + reservationClaims = radb().getResourceClaims(task_ids=[t['id'] for t in reservationTasks], extended=True, include_properties=False) + task2claims = {} + for claim in reservationClaims: + if claim['task_id'] not in task2claims: + task2claims[claim['task_id']] = [] + task2claims[claim['task_id']].append(claim) + for task in reservationTasks: + claims = task2claims.get(task['id'], []) + task['name'] = ', '.join(c['resource_name'] for c in claims) + task['description'] = 'Reservation on ' + task['name'] + + #wait for storage details thread to finish + t2.join() + + @app.route('/rest/tasks/<int:task_id>', methods=['GET']) @gzipped def getTask(task_id): @@ -328,8 +384,7 @@ def getTask(task_id): abort(404) task['name'] = 'Task %d' % task['id'] - updateTaskMomDetails(task, momqueryrpc) - updateTaskStorageDetails(task, sqrpc, curpc) + updateTaskDetails([task]) return jsonify({'task': task}) except Exception as e: abort(404) @@ -346,8 +401,7 @@ def getTaskByOTDBId(otdb_id): abort(404) task['name'] = 'Task %d' % task['id'] - updateTaskMomDetails(task, momqueryrpc) - updateTaskStorageDetails(task, sqrpc, curpc) + updateTaskDetails([task]) return jsonify({'task': task}) except Exception as e: abort(404) @@ -364,8 +418,7 @@ def getTaskByMoMId(mom_id): abort(404) task['name'] = 'Task %d' % task['id'] - updateTaskMomDetails(task, momqueryrpc) - updateTaskStorageDetails(task, sqrpc, curpc) + updateTaskDetails([task]) return jsonify({'task': task}) except Exception as e: abort(404) @@ -378,10 +431,7 @@ def getTasksByMoMGroupId(mom_group_id): try: mom_ids = momqueryrpc.getTaskIdsInGroup(mom_group_id)[str(mom_group_id)] tasks = radb().getTasks(mom_ids=mom_ids) - - updateTaskMomDetails(tasks, momqueryrpc) - updateTaskStorageDetails(tasks, sqrpc, curpc) - + updateTaskDetails(tasks) return jsonify({'tasks': tasks}) except Exception as e: abort(404) @@ -392,10 +442,7 @@ def getTasksByMoMParentGroupId(mom_parent_group_id): try: mom_ids = momqueryrpc.getTaskIdsInParentGroup(mom_parent_group_id)[str(mom_parent_group_id)] tasks = radb().getTasks(mom_ids=mom_ids) - - updateTaskMomDetails(tasks, momqueryrpc) - updateTaskStorageDetails(tasks, sqrpc, curpc) - + updateTaskDetails(tasks) return jsonify({'tasks': tasks}) except Exception as e: abort(404) @@ -618,7 +665,7 @@ def getParsetByOTDBId(otdb_id): @app.route('/rest/tasks/<int:task_id>/resourceclaims') @gzipped def taskResourceClaims(task_id): - return jsonify({'taskResourceClaims': radb().getResourceClaims(task_id=task_id, include_properties=True)}) + return jsonify({'taskResourceClaims': radb().getResourceClaims(task_ids=[task_id], include_properties=True)}) @app.route('/rest/tasktypes') @gzipped @@ -662,6 +709,7 @@ def getProjects(): projects.append({'name':'<unknown>', 'mom_id':-99, 'description': 'Container project for tasks for which we could not find a MoM project'}) projects.append({'name':'OTDB Only', 'mom_id':-98, 'description': 'Container project for tasks which exists only in OTDB'}) + projects.append({'name':'Reservations', 'mom_id':-97, 'description': 'Container project for reservation tasks'}) return jsonify({'momprojects': projects}) @app.route('/rest/projects/<int:project_mom2id>') @@ -696,10 +744,7 @@ def getProjectTasksFromUntil(project_mom2id, fromTimestamp=None, untilTimestamp= task_mom2ids = momqueryrpc.getProjectTaskIds(project_mom2id)['task_mom2ids'] tasks = radb().getTasks(mom_ids=task_mom2ids, lower_bound=fromTimestamp, upper_bound=untilTimestamp) - - updateTaskMomDetails(tasks, momqueryrpc) - updateTaskStorageDetails(tasks, sqrpc, curpc) - + updateTaskDetails(tasks) return jsonify({'tasks': tasks}) except Exception as e: logger.error(e) @@ -805,8 +850,7 @@ def getTasksHtml(): if not tasks: abort(404) - updateTaskMomDetails(tasks, momqueryrpc) - updateTaskStorageDetails(tasks, sqrpc, curpc) + updateTaskDetails(tasks) html = '<!DOCTYPE html><html><head><title>Tasks</title><style>table, th, td {border: 1px solid black; border-collapse: collapse; padding: 4px;}</style></head><body><table style="width:100%">\n' @@ -837,8 +881,7 @@ def getTaskHtml(task_id): abort(404, 'No such task %s' % task_id) task['name'] = 'Task %d' % task['id'] - updateTaskMomDetails(task, momqueryrpc) - updateTaskStorageDetails(task, sqrpc, curpc) + updateTaskDetails([task]) html = '<!DOCTYPE html><html><head><title>Tasks</title><style>table, th, td {border: 1px solid black; border-collapse: collapse; padding: 4px;}</style></head><body><table style="">\n' diff --git a/SAS/ResourceAssignment/ResourceAssignmentService/rpc.py b/SAS/ResourceAssignment/ResourceAssignmentService/rpc.py index 41573604cec7b245d5a4db2b72166bf324d1a2d4..6bbd5e3934e08e0f189b7be2c2d2856fc4a400f0 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentService/rpc.py +++ b/SAS/ResourceAssignment/ResourceAssignmentService/rpc.py @@ -130,19 +130,20 @@ class RARPC(RPCWrapper): user_id=user_id, where_resource_types=where_resource_types) - def getResourceUsages(self, claim_ids=None, lower_bound=None, upper_bound=None, resource_ids=None, task_ids=None, status=None, resource_type=None): + + def getResourceUsages(self, lower_bound=None, upper_bound=None, resource_ids=None, status=None): all_usages = self.rpc('GetResourceUsages', lower_bound=lower_bound, upper_bound=upper_bound, resource_ids=resource_ids, - task_ids=task_ids, - status=status, - resource_type=resource_type) + status=status) + + all_usages = convertStringDigitKeysToInt(all_usages) - for resource_usages in all_usages: - for status, usages in resource_usages['usages'].items(): + for resource_id, resource_usages_per_status in all_usages.items(): + for status, usages in resource_usages_per_status.items(): for usage in usages: - usage['timestamp'] = usage['timestamp'].datetime() + usage['as_of_timestamp'] = usage['as_of_timestamp'].datetime() return all_usages @@ -300,20 +301,22 @@ class RARPC(RPCWrapper): def get_conflicting_overlapping_claims(self, claim_id): '''returns a list of claimed claims which overlap with given claim(s) and which prevent the given claim(s) to be claimed (cause it to be in conflict)''' - return self.rpc('get_conflicting_overlapping_claims', + return self.rpc('get_overlapping_claims', claim_id=claim_id) - def get_conflicting_overlapping_tasks(self, claim_ids): + def get_conflicting_overlapping_tasks(self, claim_id): '''returns a list of tasks which overlap with given claim(s) and which prevent the given claim(s) to be claimed (cause it to be in conflict)''' - return self.rpc('get_conflicting_overlapping_tasks', - claim_ids=claim_ids) + return self.rpc('get_overlapping_tasks', + claim_id=claim_id) def get_max_resource_usage_between(self, resource_id, lower_bound, upper_bound, claim_status='claimed'): - return self.rpc('get_max_resource_usage_between', - resource_id=resource_id, - lower_bound=lower_bound, - upper_bound=upper_bound, - claim_status=claim_status) + result = self.rpc('get_max_resource_usage_between', + resource_id=resource_id, + lower_bound=lower_bound, + upper_bound=upper_bound, + claim_status=claim_status) + result['as_of_timestamp'] = result['as_of_timestamp'].datetime() + return result def get_resource_claimable_capacity(self, resource_id, lower_bound, upper_bound): '''get the claimable capacity for the given resource within the timewindow given by lower_bound and upper_bound. diff --git a/SAS/ResourceAssignment/ResourceAssignmentService/service.py b/SAS/ResourceAssignment/ResourceAssignmentService/service.py index 57917be37b5493c3a6cc5c2c89db9b6044fb27cb..dd7e6a47a86fde3fe29a5a8b041eafd91aa7ec8e 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentService/service.py +++ b/SAS/ResourceAssignment/ResourceAssignmentService/service.py @@ -83,8 +83,8 @@ class RADBHandler(MessageHandlerInterface): 'UpdateSpecification': self._updateSpecification, 'GetUnits': self._getUnits, 'GetResourceAllocationConfig': self._getResourceAllocationConfig, - 'get_conflicting_overlapping_claims': self._get_conflicting_overlapping_claims, - 'get_conflicting_overlapping_tasks': self._get_conflicting_overlapping_tasks, + 'get_overlapping_claims': self._get_overlapping_claims, + 'get_overlapping_tasks': self._get_overlapping_tasks, 'get_max_resource_usage_between': self._get_max_resource_usage_between, 'get_resource_claimable_capacity': self._get_resource_claimable_capacity } @@ -227,14 +227,11 @@ class RADBHandler(MessageHandlerInterface): 'updated': updated} def _getResourceUsages(self, **kwargs): - usages = self.radb.getResourceUsages(claim_ids=kwargs.get('claim_ids'), - lower_bound=kwargs.get('lower_bound').datetime() if kwargs.get('lower_bound') else None, + usages = self.radb.getResourceUsages(lower_bound=kwargs.get('lower_bound').datetime() if kwargs.get('lower_bound') else None, upper_bound=kwargs.get('upper_bound').datetime() if kwargs.get('upper_bound') else None, resource_ids=kwargs.get('resource_ids'), - task_ids=kwargs.get('task_ids'), - status=kwargs.get('status'), - resource_type=kwargs.get('resource_type')) - return usages + claim_statuses=kwargs.get('status')) + return convertIntKeysToString(usages) def _getResourceGroupTypes(self): return self.radb.getResourceGroupTypes() @@ -387,11 +384,11 @@ class RADBHandler(MessageHandlerInterface): def _getResourceAllocationConfig(self, **kwargs): return self.radb.getResourceAllocationConfig(sql_like_name_pattern=kwargs.get('sql_like_name_pattern')) - def _get_conflicting_overlapping_claims(self, **kwargs): - return self.radb.get_conflicting_overlapping_claims(claim_id=kwargs.get('claim_id')) + def _get_overlapping_claims(self, **kwargs): + return self.radb.get_overlapping_claims(claim_id=kwargs.get('claim_id')) - def _get_conflicting_overlapping_tasks(self, **kwargs): - return self.radb.get_conflicting_overlapping_tasks(claim_ids=kwargs.get('claim_ids')) + def _get_overlapping_tasks(self, **kwargs): + return self.radb.get_overlapping_tasks(claim_id=kwargs.get('claim_id')) def _get_max_resource_usage_between(self, **kwargs): logger.info('get_max_resource_usage_between: %s' % kwargs) diff --git a/SAS/XML_generator/src/xmlgen.py b/SAS/XML_generator/src/xmlgen.py index eed2804ebda128b4222d5311273a61bed9f82608..982b1f9d6cc6c2e952163f35ce0a167b434715c4 100755 --- a/SAS/XML_generator/src/xmlgen.py +++ b/SAS/XML_generator/src/xmlgen.py @@ -52,7 +52,7 @@ ALL_STATIONS = 'CS001,CS002,CS003,CS004,CS005,CS006,CS007,CS011,CS013,CS017,CS02 CORE_STATIONS = 'CS001,CS002,CS003,CS004,CS005,CS006,CS007,CS011,CS013,CS017,CS021,CS024,CS026,CS028,CS030,CS031,CS032,CS101,CS103,CS201,CS301,CS302,CS401,CS501' SUPERTERP_STATIONS = 'CS002,CS003,CS004,CS005,CS006,CS007' REMOTE_STATIONS = 'RS106,RS205,RS208,RS210,RS305,RS306,RS307,RS310,RS406,RS407,RS409,RS503,RS508,RS509' -INTERNATIONAL_STATIONS = 'DE601,DE602,DE603,DE604,DE605,FR606,SE607,UK608,DE609,PL610,PL611,PL612' +INTERNATIONAL_STATIONS = 'DE601,DE602,DE603,DE604,DE605,FR606,SE607,UK608,DE609,PL610,PL611,PL612,IE613' NL_STATIONS = 'CS001,CS002,CS003,CS004,CS005,CS006,CS007,CS011,CS013,CS017,CS021,CS024,CS026,CS028,CS030,CS031,CS032,CS101,CS103,CS201,CS301,CS302,CS401,CS501,RS106,RS205,RS208,RS210,RS305,RS306,RS307,RS310,RS406,RS407,RS409,RS503,RS508,RS509' RED_COLOR = '\033[91m' diff --git a/SubSystems/CMakeLists.txt b/SubSystems/CMakeLists.txt index 1856e7ed83992c2a191f1ad87f9590efdc2b54dd..5624ba9bf4c198dc7f739aeccbef1f4b8fbe208c 100644 --- a/SubSystems/CMakeLists.txt +++ b/SubSystems/CMakeLists.txt @@ -10,7 +10,7 @@ lofar_add_package(ST_MAC) lofar_add_package(Offline) lofar_add_package(SAS_OTDB) lofar_add_package(SAS_Tools) -lofar_add_package(PVSS_DB) +lofar_add_package(WinCC_DB) lofar_add_package(RAServices) lofar_add_package(DataManagement) lofar_add_package(Dragnet) diff --git a/SubSystems/PVSS_DB/CMakeLists.txt b/SubSystems/PVSS_DB/CMakeLists.txt deleted file mode 100644 index 4bfccc2f5c43bec8a40aaae5662adac150f502fc..0000000000000000000000000000000000000000 --- a/SubSystems/PVSS_DB/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# $Id$ - -lofar_package(PVSS_DB - DEPENDS PVSS_Datapoints Navigator2) - diff --git a/SubSystems/SAS_OTDB/CMakeLists.txt b/SubSystems/SAS_OTDB/CMakeLists.txt index a28eb766c6f49932b466d44bfdc4e5c7feccae4b..4a7756ce69b62d257a03e30114319e55c0a48856 100644 --- a/SubSystems/SAS_OTDB/CMakeLists.txt +++ b/SubSystems/SAS_OTDB/CMakeLists.txt @@ -1,4 +1,4 @@ # $Id$ lofar_package(SAS_OTDB - DEPENDS Deployment OTDB_Comps OTDB_SQL StaticMetaData PVSS_Datapoints) + DEPENDS Deployment OTDB_Comps OTDB_SQL StaticMetaData WinCC_Datapoints) diff --git a/SubSystems/WinCC_DB/CMakeLists.txt b/SubSystems/WinCC_DB/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1c0ede97be40b9318e428edbb136425105f5d01d --- /dev/null +++ b/SubSystems/WinCC_DB/CMakeLists.txt @@ -0,0 +1,5 @@ +# $Id$ + +lofar_package(WinCC_DB + DEPENDS WinCC_Datapoints Navigator2) +