From 3f4f3798c85d0f5aa35f3e06b23c3416f7d6f553 Mon Sep 17 00:00:00 2001
From: Elisabetta Giani <elisabetta.giani@inaf.it>
Date: Tue, 5 May 2020 11:20:51 -0400
Subject: [PATCH] AT5-374: Updated SubElement Subarray documentation.

---
 cspse/lmc/decorators.py          |  19 +-
 cspse/lmc/subelement_subarray.py | 302 +++++++++++++++++++++++++------
 docs/src/README.md               |   1 +
 docs/src/index.rst               |  23 ++-
 docs/src/package/guide.rst       |   4 -
 5 files changed, 270 insertions(+), 79 deletions(-)
 create mode 120000 docs/src/README.md

diff --git a/cspse/lmc/decorators.py b/cspse/lmc/decorators.py
index 22366bb..c9e440e 100644
--- a/cspse/lmc/decorators.py
+++ b/cspse/lmc/decorators.py
@@ -147,7 +147,7 @@ class IsMasterCommandAllowed(object):
             num_of_devices = len(input_arg)
             dev_instance.logger.info("num_of_devices:{}".format(num_of_devices))
             if num_of_devices == 0:
-                # check the device State: if it not the proper value the command is
+                # check the device State: if not the proper value the command is
                 # not executed
                 if not is_command_allowed(dev_instance, cmd_to_exec.lower()):
                     msg = "Command {} can't be executed when the device is {}".format(cmd_to_exec,
@@ -160,30 +160,27 @@ class IsMasterCommandAllowed(object):
 
 class IsSubarrayCommandAllowed(object):
     """
-    Class designed to be a decorator for the Master power methods.
-    The *decorator function* performs a check on the input argument
-    to control if the command is issued on the whole sub-element.
-    If this is the case, it checks the State of the sub-element Master
-    device and rejects the command accordingly to the State
-    machine setting.
-
+    Class designed to be a decorator for the Subarray methods.
+    The *decorator function* performs a check on the State of 
+    the sub-element Subarray device and rejects the command accordingly
+    to the State machine setting.
+    
     :raise: tango.DevFailed exception if the command can't be executed 
     """
     def __call__(self, f):
         @functools.wraps(f)
         def input_args_check(*args, **kwargs):
-            # the Master device instance
+            # the Subarray device instance
             dev_instance = args[0]
             # the command name
             cmd_to_exec = f.__name__
-            dev_instance.logger.info("Isallo Sono qui!!")
             # check the device State: if it not the proper value the command is
             # not executed
             if not is_command_allowed(dev_instance, cmd_to_exec.lower()):
                 msg = "Command {} can't be executed when the device is {}".format(cmd_to_exec,
                                                                                    dev_instance.get_state())
                 tango.Except.throw_exception("Command failure",msg,
-                                         "IsCommandAllowed decorator",
+                                         "IsSubarrayCommandAllowed decorator",
                                          tango.ErrSeverity.ERR)
             return f(*args, **kwargs)
         return input_args_check
diff --git a/cspse/lmc/subelement_subarray.py b/cspse/lmc/subelement_subarray.py
index a0aa95b..f04b541 100644
--- a/cspse/lmc/subelement_subarray.py
+++ b/cspse/lmc/subelement_subarray.py
@@ -88,7 +88,7 @@ class CspSubElementSubarray(SKASubarray):
 
     numOfDevCompletedTask = attribute(
         dtype=(('DevString',),),
-        max_dim_x=10, max_dim_y=2,
+        max_dim_x=2, max_dim_y=10,
         label="Number of devices that completed the task",
         doc="Number of devices that completed the task",
     )
@@ -133,7 +133,7 @@ class CspSubElementSubarray(SKASubarray):
 
     failureMessage = attribute(
         dtype=(('DevString',),),
-        max_dim_x=10, max_dim_y=2,
+        max_dim_x=2, max_dim_y=10,
         label="The failure message",
         doc="The failure message",
     )
@@ -152,7 +152,7 @@ class CspSubElementSubarray(SKASubarray):
 
     listOfDevCompletedTask = attribute(
         dtype=(('DevString',),),
-        max_dim_x=10, max_dim_y=2,
+        max_dim_x=2, max_dim_y=10,
         label="List of devices that completed the task",
         doc="List of devices that completed the task",
     )
@@ -162,7 +162,7 @@ class CspSubElementSubarray(SKASubarray):
     # ---------------
 
     def init_device(self):
-        """Initialises the attributes and properties of the CspSubElementSubarray."""
+        """Initialise the attributes and properties of the CspSubElementSubarray."""
         SKASubarray.init_device(self)
         self.set_state(tango.DevState.INIT)
         # PROTECTED REGION ID(CspSubElementSubarray.init_device) ENABLED START #
@@ -231,7 +231,6 @@ class CspSubElementSubarray(SKASubarray):
         # values: the number of components completed the task (stored as string).
         self._num_dev_completed_task = defaultdict(lambda:'0')
 
-
         # _valid_scan_coniguration: store the last valid scan configuration (json format)
         # Impemented as a string.
         self._valid_scan_configuration = ''
@@ -269,37 +268,82 @@ class CspSubElementSubarray(SKASubarray):
 
     def read_validScanConfiguration(self):
         # PROTECTED REGION ID(CspSubElementSubarray.validScanConfiguration_read) ENABLED START #
-        """Return the validScanConfiguration attribute."""
+        """
+        Return the validScanConfiguration attribute.
+        
+        *validScanConfiguration* attribute stores the last scan configuration
+        programmed for the sub-element.
+        """
         return self._valid_scan_configuration
         # PROTECTED REGION END #    //  CspSubElementSubarray.validScanConfiguration_read
 
     def read_goToIdleDurationExpected(self):
         # PROTECTED REGION ID(CspSubElementSubarray.goToIdleDurationExpected_read) ENABLED START #
-        """Return the goToIdleDurationExpected attribute."""
+        """
+        Return the goToIdleDurationExpected attribute.
+        
+        *goToIdleDurationExpected* attribute reports the time expected (in sec) for the
+        execution of the *GoToIdle* command.
+        
+        The value for this attribute can be configured via the associate *write* method.
+        """
         return self._cmd_duration_expected['gotoidle']
         # PROTECTED REGION END #    //  CspSubElementSubarray.goToIdleDurationExpected_read
 
     def write_goToIdleDurationExpected(self, value):
         # PROTECTED REGION ID(CspSubElementSubarray.goToIdleDurationExpected_write) ENABLED START #
-        """Set the goToIdleDurationExpected attribute."""
+        """
+        Set the goToIdleDurationExpected attribute.
+        
+        Configure the time expected (in sec) for the execution of the *GoToIdle* command.
+        """
+        
         self._cmd_duration_expected['gotoidle'] = value
         # PROTECTED REGION END #    //  CspSubElementSubarray.goToIdleDurationExpected_write
 
     def read_goToIdleDurationMeasured(self):
         # PROTECTED REGION ID(CspSubElementSubarray.goToIdleDurationMeasured_read) ENABLED START #
-        """Return the goToIdleDurationMeasured attribute."""
+        """Return the goToIdleDurationMeasured attribute.
+        
+        *goToIdleDurationMeasured* attribute reports the effective execution time for the
+        *GoToIdle* command.
+        """
+        
         return self._cmd_duration_measured['gotoidle']
         # PROTECTED REGION END #    //  CspSubElementSubarray.goToIdleDurationMeasured_read
 
     def read_numOfDevCompletedTask(self):
         # PROTECTED REGION ID(CspSubElementSubarray.numOfDevCompletedTask_read) ENABLED START #
-        """Return the numOfDevCompletedTask attribute.
-           The attribute value is returned as a nested listed (TANGO image attribute):
-           - x index: addresses the command name
-           - y index: addresses the number (string) of completed task 
-
-           Es:
-           [['gotoidle','3'],['configurescan': '10']]
+        """
+        Return the numOfDevCompletedTask attribute.
+
+        The TANGO attribute *numOfDevCompletedTask* is an Image type attribute of strings.
+        It is represented as a matrix of *(N_rows, N_cols)* where:
+           
+        - N_rows = image max_dim_y
+        - N_cols = image max_dim_x
+           
+        Examples:
+           
+            *server side*
+            
+            self._num_dev_completed_task = {'gotoidle':'3', 'configurescan':'10', ...}
+            image_attr = [[gotoidle','3'], ['configurescan','10']...]
+           
+            *client side*
+            
+            >>> num_of_dev_completed_task = proxy.numOfDevCompletedTask
+            >>> num_of_dev_completed_task
+            ((gotoidle','3'), ('configurescan','10')...)
+            >>> num_of_dev_completed_task[0][0]
+            'gotoidle'
+            >>> num_of_dev_completed_task[0][1]
+            '3'
+                    
+            num_of_dev_completed_task is a Python nested tuple
+                
+            - row_index addresses the command name
+            - col_index addresses the number (string) of completed tasks
         """
         image_attr = [[cmd_name, dev_num] for cmd_name, dev_num in self._num_dev_completed_task.items()]
         return image_attr
@@ -307,69 +351,178 @@ class CspSubElementSubarray(SKASubarray):
 
     def read_goToIdleCmdProgress(self):
         # PROTECTED REGION ID(CspSubElementSubarray.goToIdleCmdProgress_read) ENABLED START #
-        """Return the goToIdleCmdProgress attribute."""
+        """
+        Return the goToIdleCmdProgress attribute.
+        
+        *goToIdleCmdProgress* attribute stores the execution percentage of the
+        *GoToIdle* command.
+        
+        The CSP Subarray device can subscribe to this attribute to monitor and report 
+        the command execution progress.
+         
+        The attribute assumes values in the range [0, 100].
+        """
+        
         return self._cmd_progress['gotoidle']
         # PROTECTED REGION END #    //  CspSubElementSubarray.goToIdleCmdProgress_read
 
     def read_endScanCmdProgress(self):
         # PROTECTED REGION ID(CspSubElementSubarray.endScanCmdProgress_read) ENABLED START #
-        """Return the endScanCmdProgress attribute."""
+        """
+        Return the endScanCmdProgress attribute.
+        
+        *endScanCmdProgres* attribute stores the execution percentage of the
+        *EndScan* command.
+        
+        The CSP Subarray device can subscribe to this attribute to monitor and report 
+        the command execution progress.
+         
+        The attribute assumes values in the range [0, 100].
+        """
+        
         return self._cmd_progress['endscan']
         # PROTECTED REGION END #    //  CspSubElementSubarray.endScanCmdProgress_read
 
     def read_scanCmdProgress(self):
         # PROTECTED REGION ID(CspSubElementSubarray.scanCmdProgress_read) ENABLED START #
-        """Return the scanCmdProgress attribute."""
+        """
+        Return the scanCmdProgress attribute.
+        
+        *scanCmdProgress* attribute stores the execution percentage of the
+        *Scan* command.
+        
+        The CSP Subarray device can subscribe to this attribute to monitor and report 
+        the command execution progress.
+         
+        The attribute assumes values in the range [0, 100].
+        """
+        
         return self._cmd_progress['scan']
         # PROTECTED REGION END #    //  CspSubElementSubarray.scanCmdProgress_read
 
     def read_timeoutExpiredFlag(self):
         # PROTECTED REGION ID(CspSubElementSubarray.timeoutExpiredFlag_read) ENABLED START #
-        """Return the timeoutExpiredFlag attribute."""
+        """
+        Return the timeoutExpiredFlag attribute.
+        
+        *timeoutExpiredFlag* attribute is of type DevBoolean. 
+        
+        Its value is True when a timeout condition occurs during the execution of
+        a command.
+        
+        The Csp Subarray device can subscribe to this attribute to monitor a timeout
+        condition.
+        """
+        
         return self._timeout_expired
         # PROTECTED REGION END #    //  CspSubElementSubarray.timeoutExpiredFlag_read
 
     def read_failureRaisedFlag(self):
         # PROTECTED REGION ID(CspSubElementSubarray.failureRaisedFlag_read) ENABLED START #
-        """Return the failureRaisedFlag attribute."""
+        """
+        Return the failureRaisedFlag attribute.
+        
+        *failureRaisedFlag* attribute is of type DevBoolean. 
+        
+        Its value is True when a failure condition occurs during the execution of
+        a command.
+        
+        The Sub-element AlarmHandler, as well the Csp Subarray can subscribe to this attribute
+        to monitor failures during command execution.
+        """
+        
         return self._failure_raised
         # PROTECTED REGION END #    //  CspSubElementSubarray.failureRaisedFlag_read
 
     def read_failureMessage(self):
         # PROTECTED REGION ID(CspSubElementSubarray.failureMessage_read) ENABLED START #
-        """Return the failureMessage attribute.
-           For each failed commad, it reports the associated failure message.
-           Es: 
-           self._failure_message = {'gotoidle': 'Device XXX can't execute the command when in SCANNING'}
-           image_attr = [['gotoidle', 'Device XXX can't execute the command when in SCANNING']]
         """
+        Return the failureMessage attribute.
+           
+        *failureMessage* attribute reports the failure message associated to each failed commad. 
+        
+        Example:
+            *server side*
+               
+            self._failure_message = {'gotoidle': 'Device XXX can't execute the command when in SCANNING', ..}
+            image_attr = [['gotoidle', 'Device XXX can't execute the command when in SCANNING'],...]
+            
+            *client side*
+            
+            >>> failure_message = proxy.failureMessage
+            >>> failureMessage
+            (('gotoidle', 'Device XXX can't execute the command when in SCANNING'),...))
+            >>> failureMessage[0][0]
+            'gotoidle'
+            >>> failureMessage[0][1]
+            'Device XXX can't execute the command when in SCANNING'
+            
+            - row_index addresses the command name
+            - col_index addresses the number (string) of completed tasks
+        """
+        
         image_attr = [[cmd_name, message] for cmd_name, message in self._failure_message.items()]
         return image_attr
         # PROTECTED REGION END #    //  CspSubElementSubarray.failureMessage_read
 
     def read_configureScanCmdProgress(self):
         # PROTECTED REGION ID(CspSubElementSubarray.configureScanProgress_read) ENABLED START #
-        """Return the configureScanProgress attribute."""
+        """
+        Return the configureScanProgress attribute.
+        
+        *configureScanProgress* attribute stores the execution percentage of the
+        *ConfigureScan* command.
+        
+        The CSP Subarray device can subscribe to this attribute to monitor and report 
+        the command execution progress.
+         
+        The attribute assumes values in the range [0, 100].
+        """
+        
         return self._cmd_progress['configurescan']
         # PROTECTED REGION END #    //  CspSubElementSubarray.configureScanProgress_read
 
     def read_configureScanDurationMeasured(self):
         # PROTECTED REGION ID(CspSubElementSubarray.configureScanDurationMeasured_read) ENABLED START #
-        """Return the configureScanDurationMeasured attribute."""
+        """
+        Return the configureScanDurationMeasured attribute.
+        
+        *configureScanDurationMeasured* attribute reports the effective execution time for the
+        *ConfigureScan* command.
+        """
+        
         return self._cmd_duration_measured['configurescan']
         # PROTECTED REGION END #    //  CspSubElementSubarray.configureScanDurationMeasured_read
 
     def read_listOfDevCompletedTask(self):
         # PROTECTED REGION ID(CspSubElementSubarray.listOfDevCompletedTask_read) ENABLED START #
-        """Return the listOfDevCompletedTask attribute."""
-        # build the content of the TANGO attribute listOfDevCompletedTask 
-        # (type Image of DevString) as a nested list.
-        # x element: the command name
-        # y element: the number of devices (stored as a string) that completed the task
-        #
-        # Es:
-        # self._list_dev_completed_task = {'gotoidle': '3', 'configurescan': '10'}
-        # image_attr = [['gotoidle','3'], ['configurescan':'10']]
+        """Return the listOfDevCompletedTask attribute.
+        
+        build the content of the TANGO attribute listOfDevCompletedTask 
+        (type Image of DevString) as a nested list.
+        x element: the command name
+        y element: the list of devices that completed the task
+        
+        Example:
+            *server side*
+            
+            self._list_dev_completed_task = {'gotoidle': 'device, device2, device3', 'configurescan': 'device1, device2'}
+            image_attr = [['gotoidle',''], ['device, device2, deviceconfigurescan':''device1, device2']]*client side*
+            
+            *client side*
+            
+            >>> list_dev_completed_task = proxy.listOfDevCompletedTask
+            >>> list_dev_completed_task
+            (('gotoidle', 'Device XXX can't execute the command when in SCANNING'),...))
+            >>> list_dev_completed_task[0][0]
+            'gotoidle'
+            >>> list_dev_completed_task[0][1]
+            'device, device2, device3''
+            
+            - row_index addresses the command name
+            - col_index addresses the list of devices that completed tasks
+        """
+        
         image_attr = [[cmd_name, dev_list] for cmd_name, dev_list in self._list_dev_completed_task.items()]
         return image_attr
         # PROTECTED REGION END #    //  CspSubElementSubarray.listOfDevCompletedTask_read
@@ -384,9 +537,10 @@ class CspSubElementSubarray(SKASubarray):
     def Abort(self):
         # PROTECTED REGION ID(CspSubElementSubarray.Abort) ENABLED START #
         """
-        Change obsState to ABORTED.
+        Stop abruptly the execution of a command.
+        After execution, the subarray obsState moves to ABORTED.
 
-        :return:None
+        :return: None
         """
         pass
         # PROTECTED REGION END #    //  CspSubElementSubarray.Abort
@@ -399,9 +553,19 @@ class CspSubElementSubarray(SKASubarray):
     def EndScan(self):
         # PROTECTED REGION ID(CspSubElementSubarray.EndScan) ENABLED START #
         """
-        Change obsState to IDLE.
-
-        :return:None
+        Stop the execution of the current scan.
+        
+        The command is processed when the subarray is in ON State and its obsState value
+        is SCANNING.
+        On success, the device obsState moves to READY.
+        The *EndScan* class method behavior is modified by two Python decorators:
+        *IsSubarrayCommandAllowed* and *ObsStateCheck*.
+        These decorators respectively verify if the subarray is the required State and observing
+        state.
+        
+        :return: None
+        :raises: tango.DevFailed exception when the subarray is not in the proper State or
+                obsState value.
         """
         pass
         # PROTECTED REGION END #    //  CspSubElementSubarray.EndScan
@@ -415,11 +579,22 @@ class CspSubElementSubarray(SKASubarray):
     def Scan(self, argin):
         # PROTECTED REGION ID(CspSubElementSubarray.Scan) ENABLED START #
         """
-        Starts the scan.
-
-        :param argin: 'DevVarStringArray'
+        Start the execution of the scan.
+        The command can be issued only when the subarray State is ON and its obsState
+        is READY.
+        On success, the subarray obsState moves to SCANNING.
+        The *Scan* class method behavior is modified by two Python decorators:
+        *IsSubarrayCommandAllowed* and *ObsStateCheck*.
+        These decorators respectively verify if the subarray is the required State and observing
+        state.
+        
+        :param argin: the scan id (integer number) 
+        :type: DevVarStringArray
+        
+        :return: None
+        :raises: tango.DevFailed exception when the subarray is not in the proper State or
+                obsState value.
 
-        :return:None
         """
         pass
         # PROTECTED REGION END #    //  CspSubElementSubarray.Scan
@@ -435,11 +610,21 @@ class CspSubElementSubarray(SKASubarray):
         # PROTECTED REGION ID(CspSubElementSubarray.ConfigureScan) ENABLED START #
         """
         Configure a complete scan for the subarray.
-
-        :param argin: 'DevString'
-        A Json-encoded string with the scan configuration.
-
-        :return:None
+        The command is processed when the subarray is in ON State and its obsState value
+        is IDLE or READY (re-configuration).
+        The subarray obsState moves to CONFIGURING during the configuration process and then to 
+        READY when the command ends with success.
+        The *ConfigureScan* class method behavior is modified by two Python decorators:
+        *IsSubarrayCommandAllowed* and *ObsStateCheck*.
+        These decorators respectively verify if the subarray is the required State and observing
+        state.
+        
+        :param argin: a Json-encoded string with the scan configuration
+        :type: DevString
+
+        :return: None
+        :raises: tango.DevFailed exception when the subarray is not in the proper State or
+                observing state value.
         """
         pass
         # PROTECTED REGION END #    //  CspSubElementSubarray.ConfigureScan
@@ -449,13 +634,21 @@ class CspSubElementSubarray(SKASubarray):
     @DebugIt()
     @IsSubarrayCommandAllowed()
     @ObsStateCheck('gotoidle')
-    @SubarrayRejectCmd('Configure', 'Scan')
+    @SubarrayRejectCmd('ConfigureScan', 'Scan')
     def GoToIdle(self):
         # PROTECTED REGION ID(CspSubElementSubarray.GoToIdle) ENABLED START #
         """
         Set the Subarray obsState to IDLE.
-
-        :return:None
+        The *GoToIdle* class method behavior is modified by three Python decorators:
+        *IsSubarrayCommandAllowed* and *ObsStateCheck* decorators respectively verify 
+        if the subarray is the required State and observing state.
+        *SubarrayRejectCmd* decorator checks if there is another command is already running.
+        In this the case, the current command is rejected throwing an exception.
+           
+        :return: None
+        :raises: tango.DevFailed exception when the subarray:
+                - is not in the proper State or observing state value
+                - is running the *ConfigureScan* or *Scan* command
         """
         pass
         # PROTECTED REGION END #    //  CspSubElementSubarray.GoToIdle
@@ -464,7 +657,6 @@ class CspSubElementSubarray(SKASubarray):
 # Run server
 # ----------
 
-
 def main(args=None, **kwargs):
     """Main function of the CspSubElementSubarray module."""
     # PROTECTED REGION ID(CspSubElementSubarray.main) ENABLED START #
diff --git a/docs/src/README.md b/docs/src/README.md
new file mode 120000
index 0000000..fe84005
--- /dev/null
+++ b/docs/src/README.md
@@ -0,0 +1 @@
+../../README.md
\ No newline at end of file
diff --git a/docs/src/index.rst b/docs/src/index.rst
index 4b79b17..23812df 100644
--- a/docs/src/index.rst
+++ b/docs/src/index.rst
@@ -13,10 +13,15 @@
   :caption: Home
   :hidden:
 
-SKA CSP-LMC-SUBELEMENT Abstract Class
-=====================================
+SKA CSP.LMC SubElement Base Classes
+=======================================
+
+This project provides a limited set of base classes to be extended by each CSP.LMC
+SubElement class. 
 
-This project contains the `CSP.LMC.SUBELEMENT` abstract classes prototype. 
+The scope of the CSP.LMC SubElement Base classes is to provide to a CSP.LMC Element 
+a common set of TANGO methods and attributes to access its SubElements in an uniform
+way.
 
 .. README =============================================================
 
@@ -24,9 +29,9 @@ This project contains the `CSP.LMC.SUBELEMENT` abstract classes prototype.
 
 .. toctree::
    :maxdepth: 2
-   :caption: Introduction
+   :caption: Introduction 
 
-   ../../README
+   README
 
 .. COMMUNITY SECTION ==================================================
 
@@ -34,18 +39,18 @@ This project contains the `CSP.LMC.SUBELEMENT` abstract classes prototype.
 
 .. toctree::
   :maxdepth: 2
-  :caption: Csp.LMC SubElement TANGO Classes 
+  :caption: CSP.LMC SubElement TANGO Classes 
   :hidden:
 
   package/guide
 
 
-Detailed Abstract Class Documentation
+Detailed Class Documentation
 =====================================
 
 
 We report here the detailed descriptions of the component that form part of the project.
-This project includes few classes: the `CspSubElementMaster`, the `CspSubElementSubarray` and
-the `Rack` device drivers.
+This project includes few TANGO Device Classes: the `CspSubElementMaster`, the `CspSubElementSubarray`.
+
 
 - :doc:`package/guide`
diff --git a/docs/src/package/guide.rst b/docs/src/package/guide.rst
index 6513f5f..8eabc31 100644
--- a/docs/src/package/guide.rst
+++ b/docs/src/package/guide.rst
@@ -1,10 +1,6 @@
 .. doctest-skip-all
 .. _package-guide:
 
-.. todo::
-    - write documentation for private and protected attributes and methods of
-      the CSP.LMC Subelement classes.
-
 ************************
 Public API documentation
 ************************
-- 
GitLab