From 7f1a3577377f138247808d4eae9313c6e6232a51 Mon Sep 17 00:00:00 2001 From: Thomas Juerges <4-jurges@users.noreply.git.astron.nl> Date: Wed, 20 May 2020 18:21:55 +0200 Subject: [PATCH] Display visibilities as 2d real and imaginary plots Also remove all the locking that somehow blocked the entire Python program. --- StatsCrosslet-DS/StatsCrosslet.py | 154 ++++++++++++----------------- StatsCrosslet-DS/StatsCrosslet.xmi | 22 ++--- 2 files changed, 75 insertions(+), 101 deletions(-) diff --git a/StatsCrosslet-DS/StatsCrosslet.py b/StatsCrosslet-DS/StatsCrosslet.py index 335c3783e..23db5fe49 100644 --- a/StatsCrosslet-DS/StatsCrosslet.py +++ b/StatsCrosslet-DS/StatsCrosslet.py @@ -16,7 +16,7 @@ import tango from tango import DebugIt from tango.server import run from tango.server import Device -from tango.server import attribute, command, pipe +from tango.server import attribute, command from tango.server import device_property from tango import AttrQuality, DispLevel, DevState from tango import AttrWriteType, PipeWriteType @@ -26,7 +26,7 @@ import opcua import numpy import traceback import threading -import time +from datetime import datetime # PROTECTED REGION END # // StatsCrosslet.additionnal_import __all__ = ["StatsCrosslet", "main"] @@ -42,8 +42,8 @@ class StatsCrosslet(Device): - Type:'DevString' OPC_Server_Port - Type:'DevULong' - OPC_time_out - - Type:'DevULong' + OPC_Time_out + - Type:'DevDouble' Default_pause_time - Type:'DevDouble' Default_subband @@ -56,32 +56,36 @@ class StatsCrosslet(Device): ns = 0 obj = 0 record_cross = 0 - data = [] - data_lock = threading.Lock() - stop_data_read_loop = threading.Event() - data_acquisition_is_active = threading.Event() + stop_data_read_loop = False + data_acquisition_is_active = False data_read_loop = threading.Thread() def read_data(self): # This is the the thread that continuously reads the crosslet # statistics from the station and feeds it into the Tango # property system. - while self.stop_data_read_loop.is_set() is False: - time.sleep(self._pause_time) - if self.data_acquisition_is_active.is_set() is True: - data = [] + self.debug_stream("Entering read_data loop.") + while self.stop_data_read_loop is False: + self.debug_stream("read_data is running...") + threading.Event().wait(self._pause_time) + if self.data_acquisition_is_active is True: try: - timestamp, visibilities, rcu_modes = self.obj.call_method(self.record_cross, self._subband, self._integration_time) - self.data_lock.acquire() - self._time_stamp = timestamp - self._raw_visibilities = visibilities - self._visibilities = numpy.array(visibilities)[0] + 1j * numpy.array(visibilities[1]) + self.debug_stream("fetching data: subband = %d, integration_time = %d", self._subband, self._integration_time) + t, visibilities_list, rcu_modes = self.obj.call_method(self.record_cross, self._subband, self._integration_time) + self.debug_stream("fetching data done") + time_stamp = datetime(t[0], t[1], t[2], t[3], t[4], t[5]) + self._time_stamp = time_stamp.isoformat() + visibilities = numpy.array(visibilities_list)[0] + 1j * numpy.array(visibilities_list[1]) + self._visibilities_real = visibilities.real + self._visibilities_imag = visibilities.imag self._rcu_modes = rcu_modes - self.data_lock.release() - + self.debug_stream("timestamp = %s, visibilities_real [0][0] = %f", self._time_stamp, self._visibilities_real[0][0]) + except KeyboardInterrupt: + self.debug_stream("KBD interrupt caught, leaving data read loop.") + self.stop_data_read_loop = True except Exception as e: - print("Cannot call the method %s in the OPC-UA server %s. Trace: %s" % (self.record_cross, self.OPC_Server_Name, traceback.format_exc -())) + self.error_stream("Exception: %s. Cannot call the method %s in the OPC-UA server %s. Trace: %s", e, self.record_cross, self.OPC_Server_Name, traceback.format_exc()) + # PROTECTED REGION END # // StatsCrosslet.class_variable # ----------------- @@ -98,14 +102,14 @@ class StatsCrosslet(Device): default_value=55556 ) - OPC_time_out = device_property( - dtype='DevULong', - default_value=1000 + OPC_Time_out = device_property( + dtype='DevDouble', + default_value=1.0 ) Default_pause_time = device_property( dtype='DevDouble', - default_value=60.0 + default_value=1.0 ) Default_subband = device_property( @@ -132,7 +136,7 @@ class StatsCrosslet(Device): ) time_stamp = attribute( - dtype='DevDouble', + dtype='DevString', ) pause_time = attribute( @@ -140,28 +144,19 @@ class StatsCrosslet(Device): access=AttrWriteType.READ_WRITE, ) - visibilities = attribute( - dtype=('DevDouble',), - max_dim_x=96, - ) - rcu_modes = attribute( dtype=('DevString',), max_dim_x=96, ) - raw_visibilities = attribute( + visibilities_imag = attribute( dtype=(('DevDouble',),), max_dim_x=96, max_dim_y=96, ) - # ----- - # Pipes - # ----- - - pipe_visibilities = pipe( - ) - pipe_raw_visibilities = pipe( + visibilities_real = attribute( + dtype=(('DevDouble',),), + max_dim_x=96, max_dim_y=96, ) # --------------- @@ -172,25 +167,26 @@ class StatsCrosslet(Device): """Initialises the attributes and properties of the StatsCrosslet.""" Device.init_device(self) # PROTECTED REGION ID(StatsCrosslet.init_device) ENABLED START # - self._visibilities = (0.0,) try: - self.client = opcua.Client("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_time_out) + self.debug_stream("Connecting to OPC-UA server %s:%d...", self.OPC_Server_Name, self.OPC_Server_Port) + self.client = opcua.Client("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), self.OPC_Time_out) self.client.connect() ns = self.client.get_namespace_index("http://lofar.eu") self.obj = self.client.get_root_node().get_child(["0:Objects", "{}:StationMetrics".format(ns), "{}:RCU".format(ns)]) self.record_cross = "{}:record_cross".format(ns) - - # Set default values in the read/write attributes + self.debug_stream("Connecting to OPC-UA server %s:%d done.", self.OPC_Server_Name, self.OPC_Server_Port) + # Set default values in the read/write attributes. self._pause_time = self.Default_pause_time self._integration_time = self.Default_integration_time self._subband = self.Default_subband self.data_read_loop = threading.Thread(target = self.read_data) - self.data_acquisition_is_active.set() - self.stop_data_read_loop.clear() + self.data_acquisition_is_active = False + self.stop_data_read_loop = False self.data_read_loop.start() except Exception as e: - print("Cannot connect to the OPC-UA server %s. Trace: %s" % (self.OPC_Server_Name, traceback.format_exc())) + self.error_stream("Cannot connect to the OPC-UA server %s. Trace: %s" % (self.OPC_Server_Name, traceback.format_exc())) + raise e # PROTECTED REGION END # // StatsCrosslet.init_device def always_executed_hook(self): @@ -206,12 +202,16 @@ class StatsCrosslet(Device): destructor and by the device Init command. """ # PROTECTED REGION ID(StatsCrosslet.delete_device) ENABLED START # - self.data_acquisition_is_active.clear() - self.stop_data_read_loop.set() + self.debug_stream("Shutting down...") + self.data_acquisition_is_active = False + self.stop_data_read_loop = True + self.debug_stream("Waiting for data acquisition thread to shut down...") self.data_read_loop.join() + self.debug_stream("Waiting for data acquisition thread to shut down, done") if self.client is not Null: self.client.close_session() self.client_secure_channel() + self.debug_stream("Shutdown done.") # PROTECTED REGION END # // StatsCrosslet.delete_device # ------------------ # Attributes methods @@ -238,10 +238,7 @@ class StatsCrosslet(Device): def read_time_stamp(self): # PROTECTED REGION ID(StatsCrosslet.time_stamp_read) ENABLED START # """Return the time_stamp attribute.""" - self.data_lock.acquire() - time_stamp = self._time_stamp - self.data_lock.release() - return time_stamp + return self._time_stamp # PROTECTED REGION END # // StatsCrosslet.time_stamp_read def read_pause_time(self): @@ -256,46 +253,23 @@ class StatsCrosslet(Device): self._pause_time = value # PROTECTED REGION END # // StatsCrosslet.pause_time_write - def read_visibilities(self): - # PROTECTED REGION ID(StatsCrosslet.visibilities_read) ENABLED START # - """Return the visibilities attribute.""" - self.data_lock.acquire() - visibilities = self._visibilities - self.data_lock.release() - return visibilities - # PROTECTED REGION END # // StatsCrosslet.visibilities_read - def read_rcu_modes(self): # PROTECTED REGION ID(StatsCrosslet.rcu_modes_read) ENABLED START # """Return the rcu_modes attribute.""" - self.data_lock.acquire() - rcu_modes = self._rcu_modes - self.data_lock.release() - return rcu_modes + return self._rcu_modes # PROTECTED REGION END # // StatsCrosslet.rcu_modes_read - def read_raw_visibilities(self): - # PROTECTED REGION ID(StatsCrosslet.raw_visibilities_read) ENABLED START # - """Return the raw_visibilities attribute.""" - self.data_lock.acquire() - raw_visibilities = self._raw_visibilities - self.data_lock.release() - return raw_visibilities - # PROTECTED REGION END # // StatsCrosslet.raw_visibilities_read - - # ------------- - # Pipes methods - # ------------- - - def read_pipe_visibilities(self): - # PROTECTED REGION ID(StatsCrosslet.pipe_visibilities_read) ENABLED START # - return dict(x=0, y=0) - # PROTECTED REGION END # // StatsCrosslet.pipe_visibilities_read - - def read_pipe_raw_visibilities(self): - # PROTECTED REGION ID(StatsCrosslet.pipe_raw_visibilities_read) ENABLED START # - return dict(x=0, y=0) - # PROTECTED REGION END # // StatsCrosslet.pipe_raw_visibilities_read + def read_visibilities_imag(self): + # PROTECTED REGION ID(StatsCrosslet.visibilities_imag_read) ENABLED START # + """Return the visibilities_imag attribute.""" + return self._visibilities_imag + # PROTECTED REGION END # // StatsCrosslet.visibilities_imag_read + + def read_visibilities_real(self): + # PROTECTED REGION ID(StatsCrosslet.visibilities_real_read) ENABLED START # + """Return the visibilities_real attribute.""" + return self._visibilities_real + # PROTECTED REGION END # // StatsCrosslet.visibilities_real_read # -------- # Commands @@ -313,7 +287,8 @@ class StatsCrosslet(Device): :return:None """ - self.data_acquisition_is_active.set() +# self.data_acquisition_is_active.set() + self.data_acquisition_is_active = True # PROTECTED REGION END # // StatsCrosslet.start_acquisition @command( @@ -326,7 +301,8 @@ class StatsCrosslet(Device): :return:None """ - self.data_acquisition_is_active.clear() +# self.data_acquisition_is_active.clear() + self.data_acquisition_is_active = False # PROTECTED REGION END # // StatsCrosslet.stop_acquisition # ---------- diff --git a/StatsCrosslet-DS/StatsCrosslet.xmi b/StatsCrosslet-DS/StatsCrosslet.xmi index 6f8c58792..7ce474dbf 100644 --- a/StatsCrosslet-DS/StatsCrosslet.xmi +++ b/StatsCrosslet-DS/StatsCrosslet.xmi @@ -15,15 +15,15 @@ <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <DefaultPropValue>55556</DefaultPropValue> </deviceProperties> - <deviceProperties name="OPC_time_out" description=""> - <type xsi:type="pogoDsl:UIntType"/> + <deviceProperties name="OPC_Time_out" description=""> + <type xsi:type="pogoDsl:DoubleType"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> - <DefaultPropValue>1000</DefaultPropValue> + <DefaultPropValue>1.0</DefaultPropValue> </deviceProperties> <deviceProperties name="Default_pause_time" description=""> <type xsi:type="pogoDsl:DoubleType"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> - <DefaultPropValue>60.0</DefaultPropValue> + <DefaultPropValue>1.0</DefaultPropValue> </deviceProperties> <deviceProperties name="Default_subband" description=""> <type xsi:type="pogoDsl:UIntType"/> @@ -88,7 +88,7 @@ <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> <attributes name="time_stamp" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> - <dataType xsi:type="pogoDsl:DoubleType"/> + <dataType xsi:type="pogoDsl:StringType"/> <changeEvent fire="false" libCheckCriteria="false"/> <archiveEvent fire="false" libCheckCriteria="false"/> <dataReadyEvent fire="false" libCheckCriteria="true"/> @@ -103,23 +103,23 @@ <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> - <attributes name="visibilities" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="96" maxY="" allocReadMember="true" isDynamic="false"> - <dataType xsi:type="pogoDsl:DoubleType"/> + <attributes name="rcu_modes" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="96" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:StringType"/> <changeEvent fire="false" libCheckCriteria="false"/> <archiveEvent fire="false" libCheckCriteria="false"/> <dataReadyEvent fire="false" libCheckCriteria="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> - <attributes name="rcu_modes" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="96" maxY="" allocReadMember="true" isDynamic="false"> - <dataType xsi:type="pogoDsl:StringType"/> + <attributes name="visibilities_imag" attType="Image" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="96" maxY="96" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:DoubleType"/> <changeEvent fire="false" libCheckCriteria="false"/> <archiveEvent fire="false" libCheckCriteria="false"/> <dataReadyEvent fire="false" libCheckCriteria="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> - <attributes name="raw_visibilities" attType="Image" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="96" maxY="96" allocReadMember="true" isDynamic="false"> + <attributes name="visibilities_real" attType="Image" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="96" maxY="96" allocReadMember="true" isDynamic="false"> <dataType xsi:type="pogoDsl:DoubleType"/> <changeEvent fire="false" libCheckCriteria="false"/> <archiveEvent fire="false" libCheckCriteria="false"/> @@ -127,8 +127,6 @@ <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> </attributes> - <pipes name="pipe_visibilities" description="" label="" rwType="READ" displayLevel="OPERATOR"/> - <pipes name="pipe_raw_visibilities" description="" label="" rwType="READ" displayLevel="OPERATOR"/> <preferences docHome="./doc_html" makefileHome="/usr/local/share/pogo/preferences"/> </classes> </pogoDsl:PogoSystem> -- GitLab