toPyspMonitor(), toPyspLocal()

The function toPyspMonitor() sends commands and data to a detached pyspMonitor processes. The function toPyspLocal() uses the same syntax but generates graphics within the dame process.

To find the information about toPyspMonitor():

 
In [1]: import PySpectra, HasyUtils
In [2]: PySpectra.toPyspMonitor?
In [3]: PySpectra.toPyspLocal?

The commands above should produce the information which is up-to-date. Below you find the output of toPyspMonitor? and toPyspLocal? as from September 20, 2022:

In [3]: PySpectra.toPyspMonitor?

    ”'
    def toPyspMonitor( hsh, node = None, testAlive = False, zmqPort = None, singleMonitor = False): 

    Send a dictionary to one or more pyspMonitor processes via ZMQ. 

    If singleMonitor == True, no Macroserver I/O about registered monitors is involved. 
    The data is just sent to a single pyspMonitor. Use this option, if you know that
    your are running one pyspMonitor only. 

    The receiving pyspMonitors register to the Macroserver. The environment 
    variable RegisteredPyspMonitors keeps track of the connected pyspMonitors.
    This way the Macroserver, identified by TANGO_HOST, becomes a central
    part of the communication.

    In general toPyspMonitor() talks to pyspMonitor processes running
    under the same TANGO_HOST. However, it is possible to launch a 
    pyspMonitor on a different host connecting it to a remote Macroserver:
      $ export TANFO_HOST=<targetHost>:10000 && pyspMonitor3.py

    Likewise, applications using toPyspMonitor() can also run on a remote host
    but still feed pyspMonitors connected to some Macroserver:
      $ export TANFO_HOST=<targetHost>:10000 && python myApp.py

    pyspMonitor processes the dictionary by calling PySpectra.toPyspLocal()

    toPyspMonitor() operation: 
    - If node or zmqPort are not None: the dictionary is sent to a specific 
      pyspMonitor. 

    - If RegisteredPyspMonitors does not exist or is empty and testAlive==False, 
      { 'result': 'notAlive'} is returned. If testAlive==True a pyspMonitor
      process is created and the dictionary is sent to the newly created
      pyspMonitor.

    - Otherwiese the dictionary is sent to all pyspMonitor processes 
      stored in RegisteredPyspMonitors. Due to performance reasons, 
      this variable is translated at most every 3 seconds.

    PySpectra.toPyspMonitor() can also invoked by HasyUtils.toPyspMonitor().
    This way the PySpectra PyQt initializations are avoided which may
    lead to conflicts, if called from a macro (the Macroserver also 
    imports PyQt)

    testAlive = True
        if a pyspMonitor is not running, it is launched, on the local host only.

    zmqPort = 7780
        send the dictionary to a pyspMonitor connected to a specific zmq port:
          pyspMonitor3.py -p 7780 

Example 

#!/usr/bin/env python3
import PySpectra, HasyUtils
import random, time
import numpy as np

def main(): 
    #
    # make sure that a pyspMonitor is running, launch an instance, if not.
    #
    ( ret, wasLaunched) = PySpectra.assertPyspMonitorRunning()

    MAX = 25
    #
    # create some data
    #
    pos = [float(n)/MAX for n in range( MAX)]
    d1 = [random.random() for n in range( MAX)]
    d2 = [random.random() for n in range( MAX)]
    #
    # colors: 'RED', 'GREEN', 'BLUE','YELLOW', 'CYAN', 'MAGENTA', 'BLACK', 'WHITE', 'NONE', 
    # lineStyles: 'SOLID', 'DASHED', 'DOTTED', 'DASHDOTTED'
    # symbols: 'o', 's', 'd', '+'
    #
    #
    # send the data 
    #
    hsh = { 'putData': 
            {'title': "Important Data", 
             'comment': "a comment", 
             'columns': 
             [ { 'name': "eh_mot01", 'data' : pos},
               { 'name': "eh_c01", 'data' : d1},
               { 'name': "eh_c02", 'data' : d2, 
                 'symbolColor': 'blue', 'symbol': '+', 'symbolSize': 5, 
                 'xLog': False, 'yLog': False, 
                 'showGridX': False, 'showGridY': False},
             ]}}

    hsh = PySpectra.toPyspMonitor( hsh)
    print( "exampleDataVia_toPyspLocal: putData returns %s" % repr( hsh) )
    
    print( "Press <space> to quit")
    while 1:
        key = HasyUtils.inkey()
        if key == 32:
            break
        time.sleep( 0.1)
    #
    # cleanup, stop pyspMonitor, if we created it
    #
    if wasLaunched:
        hsh = PySpectra.toPyspMonitor( { 'command': ['exit']})
        
    return

if __name__ == "__main__":
    main()

In [4]: PySpectra.toPyspLocal?

    toPyspLocal executes dictionaries which are received 
      - from toPyspMonitor()
      - from a Queue, from pyspDoor
      - from an application directly, maybe to simulate the toPyspMonitor interface

       Command, see PySpectra.ipython.ifc?
         {'command': ['delete']}
           delete all internal data

         {'command': ['cls']}
           clear the screen

         {'command': ['delete', 'cls']}
           deletes all internal data and clears the screen

         {'command': ['display']}
           display all GQEs

         { 'command': ['setArrowCurrent sig_gen position 1.234']}
         { 'command': ['setArrowCurrent sig_gen show']}
         { 'command': ['setArrowCurrent sig_gen hide']}
           handle the arrow pointing to the current position. sig_gen is
           the Scan containing data from the SignalCounter (MS env. variable)

         { 'command': ['setArrowSetPoint sig_gen position 1.234']}
         { 'command': ['setArrowSetPoint sig_gen show']}
         { 'command': ['setArrowSetPoint sig_gen hide']}
           handle the arrow pointing to the setpoint

         { 'command': ['setArrowMisc sig_gen position 1.234']}
         { 'command': ['setArrowMisc sig_gen show']}
         { 'command': ['setArrowMisc sig_gen hide']}
           handle the arrow pointing to a position defined e.g. by mvsa

         { 'command': ['setCurrentIndex sig_gen 0']}
           set the current index of sig_gen to 0, nothing to be displayed

         {'command': [u'setTitle "ascan exp_dmy01 0.0 1.0 3 0.2"']}
           set the title for the whole widget
         {'command': [u'setComment "tst_01366.fio, Wed Dec 18 10:02:09 2019"']}
           set the comment for the whole widget

         {'spock': [ 'umv eh_mot69 51']}

       Misc:
         {'isAlive': True}
           return values:
             { 'result': 'done'}
             { 'result': 'notAlive'}

         {'getDoorState': True}
           returns:
             { 'result': 'ON'}

       Scan, see PySpectra.Scan?
         {'Scan': {'name': 'eh_c01', 'xMax': 1.0, 'autoscaleX': False, 'lineColor': 'red', 'xMin': 0.0, 'nPts': 6}}
           create an empty scan. Notice, the inner dictionary is passed to the Scan constructor

         {'Scan': {'yMax': 2.0, 'symbol': '+', 'autoscaleY': False, 'autoscaleX': False, 
                   'xMax': 1.0, 'nPts': 24, 'symbolColor': 'red', 'name': 'MeshScan', 
                   'symbolSize': 5, 'lineColor': 'None', 'xMin': 0.0, 'yMin': 1.0}}
           create an empty scan setting more attributes.

         {'Scan': {'name': 'eh_mca01', 'flagMCA': True, 'lineColor': 'blue', 
                   'y': array([  0., ..., 35.,  30.]), 
                   'x': array([  0.0, ..., 2.047e+03])}}
           create an MCA scan, which is re-used

         {'command': ['setY eh_c01 0 71.41']}
           set a y-value of eh_c01, index 0

         {'command': ['setX eh_c01 0 0.0']}
           set a x-value of eh_c01, index 0

         {'command': ['setXY eh_c01 0 0.0 1.0']}
           set the x- and y-value by a single call, index is 0, 
           the currentIndex, pointing to the last valid data, is set to 0

         {'putData': { 'columns': [{'data': [0.0, ..., 0.96], 'name': 'eh_mot01'}, 
                                  {'data': [0.39623, ... 0.01250], 'name': 'eh_c01'}, 
                                  {'showGridY': False, 'symbolColor': 'blue', 'showGridX': False, 
                                   'name': 'eh_c02', 'yLog': False, 'symbol': '+', 
                                   'data': [0.1853, ... 0.611], 
                                   'xLog': False, 'symbolSize': 5}], 
                      'title': 'a title', 
                      'comment': 'a comment'}}
           The data are sent as a list of dictionaries containing columns. The first column 
           is the common x-axis. All columns have to have the same length. 
           In this example, the Scans eh_c01 and eh_c02 are created. The common x-axis is given by eh_mot01

         { 'putData': {'gqes': [ {'x': x, 'y': tan, 'name': 'tan'},
                                 {'x': x, 'y': cos, 'name': 'cos'},
                                 {'x': x, 'y': sin, 'name': 'sin', 
                                  'showGridY': False, 'symbolColor': 'blue', 'showGridX': True, 
                                  'yLog': False, 'symbol': '+', 
                                  'xLog': False, 'symbolSize':5}],
                       'title': 'a title', 
                       'comment': 'a comment'}}
           The data are sent as a list of dictionaries containg the x- and y-data and other
           parameters describing the Scans.

       Image, see PySPectra.PySpectra.Image?
         {'Image': {'name': 'MandelBrot', 
                    'height': 5, 'width': 5, 
                    'xMax': -0.5, 'xMin': -2.0, 
                    'yMin': 0, 'yMax': 1.5}}
           create an empty image

         { 'Image': { 'name': "MandelBrot", 'data': data, 
                      'xMin': xmin, 'xMax': xmax, 
                      'yMin': ymin, 'yMax': ymax}})
           pass the entire image data

         { 'putData': { 'images': [{'name': "Mandelbrot", 'data': data,
                                    'xMin': xmin, 'xMax': xmax, 
                                    'yMin': ymin, 'yMax': ymax}]}}
           data is a numpy array, e.g.: data = np.ndarray( (width, height), np.float64)

         {'command': ['setPixelImage Mandelbrot 1 3 200']}
           set a pixel value. the position is specified by indices

         {'command': ['setPixelWorld Mandelbrot 0.5 1.5 200']}
           set a pixel value. the position is specified by world coordinate

         Text
         {'command': ['setText MeshScan comment string "Sweep: 1/4" x 0.05 y 0.95']}
           create a text GQE for the scan MeshScan, the name of the text is comment

       Retrieve data:
         {'getData': True}
           {'getData': {'EH_C02': {'y': [0.3183, ... 0.6510], 'x': [0.0, ... 0.959]}, 
                        'EH_C01': {'y': [0.0234, ... 0.4918], 'x': [0.0, ... 0.959]}}, 
            'result': 'done'}

#!/usr/bin/env python3
# 
# this is an example of how to use toPyspLocal() to  
# display data locally
#
import PySpectra, HasyUtils, time, random
import numpy as np

def main():
    MAX = 25
    pos = [float(n)/MAX for n in range( MAX)]
    rd = [random.random() for n in range( MAX)]

    hsh = { 'putData': 
            {'title': "Important Data", 
             'columns': 
             [ { 'name': "eh_mot01", 'data' : pos},
               { 'name': "eh_c01", 'data' : rd},
             ]}}

    hsh = PySpectra.toPyspLocal( hsh)

    print( "Press <space> to quit")
    while 1:
        PySpectra.processEvents()
        key = HasyUtils.inkey()
        if key == 32:
            return 
        time.sleep( 0.1)
    
    return 

if __name__ == "__main__":
    main()