lavue-org / lavue

Lightweight Live Viewer
GNU General Public License v2.0
8 stars 3 forks source link

Sardana Integration #234

Closed dschick closed 4 years ago

dschick commented 4 years ago

hi @jkotan

many thanks for this great piece of software.

We would like to use the ROIs of LaVue as counters in Sardana. Is there already some driver available?

Best

Daniel

jkotan commented 4 years ago

Thanks.

At DESY we use lavue to define bounds of RoIs and pass them into a tango server which calculates RoI sums. We have a few ways to implement it, it depends on how fast are the scans and what kind of detector is used.

For passing RoIs bounds we provide the following options: 1) use RoIs attribute of the Tango server - lavue can be started with

lavue -n \<tango device name with a spectrum "RoIs" attribute\>

then after clicking the Add button in the "ROI" tool the current bounds of RoIs are written into this RoIs attribute of the tango device in a numpy slice convention. In this case Tango Server could be

2) use DetectorROIs MacroServer environment variables -- after clicking the Add button in the "ROI" tool the current bounds of RoIs are written into the DetectorROIs MacroServer environment variables. Then user tango server can fetch this ROI bounds, calulate the roi sums provide the results in its tango attribute.

3) use LavueController server -- lavue can be started with

lavue -a \<LavueController tango device name\>

when you start also instance of LavueController (https://confluence.desy.de/display/FSEC/LaVue+-+LavueController+server) and every time use changes ROI bounds the DetectorROIs attribute of LC server is updated. In this case user tango server can fetch this ROI bounds from the DetectorROIs attribute, calulate the roi sums provide the results in its tango attribute.

In all this cases the user tango server can be also a sardana pool device (at DESY we create pool devices for user tango attributes with use of tangoattributectctrl controllers).

dschick commented 4 years ago

Hi @jkotan ,

thank you very much. I think we actually did something like this:

* user server which fetch informations about images from a detector server and provides results in its scalar attributes (solution for fast detectors in slow scans, i.e. https://www.tango-controls.org/developers/dsc/ds/31/)

So we defined a pseudoCounter in Sardana which has the TwoDExperimentalChannel (this one interacts with the Camera Tango DS) as input role and multiple scalars for each ROI integral as output roles. Then we defined an extra controller attribute for the pseudoCounter controller named rois and started LaVue with the according address of this Tango attribute. This allows as to calculate the ROI integrals in Sardana accessing the ROI coordinates from LaVue

In all this cases the user tango server can be also a sardana pool device (at DESY we create pool devices for user tango attributes with use of tangoattributectctrl controllers).

Is this meant when starting Lavue with a Door device -d option?

jkotan commented 4 years ago

Great it works for you.

At DESY we have two layers: original tango servers and sardana controllers which server a role of adapters fro tango servers , so the tangoattributectctrl controller allows to access any attribute from tango server (not too much related to -d option).

The "-d" option allows for additional communication with MacroServer, e.g. 1) it sets ROIs parameters in sardana environment variables by pressing the Add button (ROI tool)

       DetectorROIs             {'rois': [[142, 233, 196, 318], [10, 10, 60, 60]]}   dict
  DetectorROIsOrder                                                       ['rois']   list
 DetectorROIsParams                                                             []   list

2) if macros nxsadd and nxsrm add defined and Add ROIs to MG: is checked in the lavue configuration it adds ROI aliases to the current MG group (ROI tool)
3) it reads back ROIs parameters from sardana environment variables by pressing the Fetch button (ROI tool) 4) it performs the sardana mesh scan of selected ROI (MeshScan tool)

LaVue stores in its configuration the last used door (defined by -d). The currently selected door device can be seen in Configuration -> General -> Sardana ->Door in the expert mode: lavue -m expert

dschick commented 4 years ago

I am currently trying the first thing

The "-d" option allows for additional communication with MacroServer, e.g.

1. it sets ROIs parameters in sardana environment variables by pressing the `Add` button (`ROI` tool)

shall I link the Door or Macroserver of that door with the -d option? Do I have to do anything else with the Door/Macroserver? Somehow, I cannot see the ROIs appearing in the Environment

jkotan commented 4 years ago

I've forgotten to write you that in order to send ROIs to the Environment you need also to define label(s) in ROI alias(es): , e.g.

rois pilatusroi1 pilatusroi2

which will appear in the DetectorROIs dictionary

In -d option you put your door device name

In Configuration->General-> Sardana you should have something like

Enabled: Y
Door: p09/door/haso000jk.02
dschick commented 4 years ago

Hi @jkotan ,

I tried the settings as you described:

rois pilatusroi1 pilatusroi2

I can only but in one line, such as pilatusroi1 pilatusroi2 is that fine?

I enabled the door and added mine like door/imaging/1

But I do get the following error when trying to add the ROIs:

lavue: Error in connecting to Door or MacroServer
'NoneType' object has no attribute 'Environment'

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/lavuelib/imageWidget.py", line 1179, in applyROIs
    str(self.__settings.doorname), ["DetectorROIs"]))
  File "/usr/local/lib/python2.7/dist-packages/lavuelib/sardanaUtils.py", line 146, in getScanEnv
    rec = msp.Environment
AttributeError: 'NoneType' object has no attribute 'Environment'

Then I tried setting the FQDN for the door like tango://localhost:10000/door/imaging/1 and get the following error

lavue: Error in connecting to Door or MacroServer
invalid literal for int() with base 10: ''

I was wondering where the log-files are written to? changing the debug option did not changed anything in the terminal output so far.

Thanks

Daniel

jkotan commented 4 years ago

Hello Daniel,

You are right. The logger needs to be improved. For aliases it is needed only one line (anything). If you use provide TangoHost in the door device name (not needed) it should be without tango://

Just to see what is going on could you please clone debug branch and start lavue in debug mode., e.g.


git clone -b debug https://github.com/jkotan/lavue
cd lavue
./lavue --log debug

Best, Jan

dschick commented 4 years ago

I did as you said, but again same error as before

lavue: Error in connecting to Door or MacroServer
'NoneType' object has no attribute 'Environment'

and only once an output in the terminal: WARNING:lavuelib.imageWidget:'NoneType' object has no attribute 'get_property'

dschick commented 4 years ago

maybe a bit off-topic, but do you have also an example for this case:

* user server which  fetch informations about images from a detector server and provides results in its spectrum attributes after scan in finished (solution for fast detectors)
jkotan commented 4 years ago

Hi Daniel,

that is weird. Before this error getMacroServer() should be called. Using debug branch I get the following debug information from getMacroServer() in my terminal

jkotan@haso000jk:~/ndts/lavue$ ./lavue --log debug

DEBUG:lavuelib.sardanaUtils:Door: p09/door/haso000jk.01
DEBUG:lavuelib.sardanaUtils:Tango Host: None
DEBUG:lavuelib.sardanaUtils:Database: Database(haso000jk.desy.de, 10000)
DEBUG:lavuelib.sardanaUtils:MacroSevers: ['p09/macroserver/haso000jk.01']
DEBUG:lavuelib.sardanaUtils:DoorList: ('p09/door/haso000jk.01', 'p09/door/haso000jk.02', 'p09/door/haso000jk.03')
DEBUG:lavuelib.sardanaUtils:Door MacroServer: MacroServer(p09/macroserver/haso228jk.01)

It looks like lavue cannot find you MacroServer assigned to your Door. Could you please run

import PyTango

door = "door/imaging/1"

print("Door: %s" % door)
sdoor = door.split("/")
tangohost = None

if len(sdoor) > 1 and ":" in sdoor[0]:
    door = "/".join(sdoor[1:])
    tangohost = sdoor[0]
print("Tango Host: %s" % tangohost)

if tangohost:
    host, port = tangohost.split(":")
    db = PyTango.Database(host, int(port))
else:
    db = PyTango.Database()
print("Database: %s" % str(db))

servers = db.get_device_exported_for_class("MacroServer").value_string
print("MacroSevers: %s" % str(servers))
ms = None

for server in servers:
    dp = None
    if tangohost and ":" not in server:
        msname = "%s/%s" % (tangohost, server)
    else:
        msname = str(server)
    try:
        dp = PyTango.DeviceProxy(msname)
    except Exception as e:
        print(str(e))
        dp = None
    if hasattr(dp, "DoorList"):
        lst = dp.DoorList
        print("DoorList: %s" % str(lst))
        if lst and (door in lst or
                    ("%s/%s" % (tangohost, door) in lst)):
            ms = dp
            print("Door MacroServer: %s" % str(ms))
            break
print(ms)

which is more or less content of getMacroServer() with print() statements.

jkotan commented 4 years ago

maybe a bit off-topic, but do you have also an example for this case:

* user server which  fetch informations about images from a detector server and provides results in its spectrum attributes after scan in finished (solution for fast detectors)

This can be done with sardana only for specific FileRecorders, i.e. recorders with can record data at the end of the scan. Thus you cannot use text file formats like spec or fio. You can do it with Nexus files but I'm afraid not with NeXus ALBA recorder distributed with sardana (PrescanSnapShot is stored only at the beginning of the scan ). At DESY we use our own Sardana NeXus recorder NXS_FileRecorder which can do it but it requires more complicated setup SDM workshop. On our beamlines we have similar application (e.g. append images after scan to the master file) but we have not used yet for ROIs.

dschick commented 4 years ago

okay, I was in the develop not debug branch, sorry.

Here is the output (from another door, named scattering not imaging):

ampere.sxr.lab:10000/door/scattering/1
DEBUG:lavuelib.sardanaUtils:Door: ampere.sxr.lab:10000/door/scattering/1
DEBUG:lavuelib.sardanaUtils:Tango Host: ampere.sxr.lab:10000
DEBUG:lavuelib.sardanaUtils:Database: Database(ampere.sxr.lab, 10000)
DEBUG:lavuelib.sardanaUtils:MacroSevers: ['MacroServer/scattering/1']
DEBUG:lavuelib.sardanaUtils:DoorList: ('Door/scattering/1',)

but again the error.

Your script give the output:

Door: door/scattering/1
Tango Host: None
Database: Database(ampere.sxr.lab, 10000)
MacroSevers: ['MacroServer/scattering/1']
DoorList: ('Door/scattering/1',)
None

The problem arises from the lastif-clause:

if lst and (door in lst or
                   ("%s/%s" % (tangohost, door) in lst)):

The issue is with the capitalization of the door names.

So when changing the Door name from door/scattering/1 to Door/scattering/1 it works and the rois are finally written to the environment.

I am just wondering, that there is always one entry called roi in the environment, altough I called my two rois roi1 and roi2:

DetectorROIs   {'rois': [[0, 0, 50, 50]], 'roi1': [[578, 183, 802, 347]], 'roi2': [[276,  [...]   dict
DetectorROIsOrder                                                                   ['roi1', 'roi2']   list
jkotan commented 4 years ago

Great it works ! DetectorROIs is used to keep all ROIs (also previous). In this way you can save various ROI aliases for different image sources. To get the latter on you can find them in DetectorROIsOrder

dschick commented 4 years ago

many thanks for all the inputs and help. are you planning to git rid of the capitalization issue, since it actually does not matter in tango, right?

I am closing, anyhow

jkotan commented 4 years ago

Yes sure #244. Thanks for tests.