EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Python Script call from Button press, module not found
From: Matt Newville via Tech-talk <tech-talk at aps.anl.gov>
To: "Johnson, Andrew N." <anj at anl.gov>
Cc: EPICS tech-talk <tech-talk at aps.anl.gov>
Date: Thu, 15 Apr 2021 11:55:04 -0500
Hi Andrew, Michael, 


On Thu, Apr 15, 2021 at 11:18 AM Johnson, Andrew N. <anj at anl.gov> wrote:
Hi Matt,

On Apr 15, 2021, at 10:47 AM, Matt Newville wrote:
>
> You could just write a simple plain python script that performed some action when the PV changed by button push happened.   That can be as simple as
>
> while True:
>     epics.poll(0.025)
>     if epics.caget('button_push'):
>        do_something()


Does pyepics use a CA monitor behind the scenes to implement that epics.caget() call? If it doesn't that example would be hitting the IOC with a get at up to 40Hz, which isn’t something I’d recommend. I’m guessing it probably does which is fine when using pyepics, but translating the above code into some other scripting language and calling the caget program from Base in a fast loop like that would not be advisable.

Yes, pyepics will (by default) set up connection and monitor callbacks on every channel it defines.  That epics.poll() is really just "ca_pend_event(0.025) ; ca_pend_io(1.0)" and should not be a resource burden.  It can also just be replaced by a Python "time.sleep(0.025)".  



Just wanting to make sure readers understand if there is some magic going on there!

Yes, it is not doing piles of ca_get() at 40 Hz.  It is expecting values to be updated by callbacks running in background CA threads.

In fact, that callback on the button push PV is deliberately not doing much work besides setting a flag because that *will* be called by the CA thread (in a sense "inside pend_event"), so we set the flag in the callback and then check that in the main Python thread in the main loop.  The "real work" part, which might do other CA calls and/or complex calculations should not be done in that callback.


- Andrew


> A slightly more complex version, using a pyepics Device might look like the script below.   This assumes there is a set of pre-defined PVs that control the calculation/work to be done and that these are loaded into an IOC.  That is different for pcaspy, where the PVs could be defined on the fly (but then you have to figure out how the Display Manager exposes them).
>
> It really isn't very much different from a seq state-notation program except that the PVs live in a soft IOC and the logic happens in a separate process.  This approach allows the logic of the program to be in python and can be changed without restarting the IOC (or the sequence process in the IOC).   The trade-off is that the script needs to be running in addition to the IOC.  procServ or screen can help with that. 
>
> ####
> import numpy as np
> import epics
>
> DSPACES = {'Si': 5.4309, 'Ge': 5.658}
> HC = 12398.419
>
> class Analyzer(epics.Device):
>     "Simple Device to set analyzer angle from energy, crystal, h, k, l"
>     attrs = ('go_button', 'energy',
>              'h', 'k', 'l', 'xtal', 'theta', 'moving')
>     _nonpvs = ('_prefix', '_pvs', '_delim', 'do_calc', 'en_val')
>
>     def __init__(self, prefix='Analyzer:'):
>         epics.Device.__init__(self, prefix, attrs=self.attrs)
>         self.needs_calc = 0
>         self.moving = 0
>         self.add_callback('go_button', self.onButtonPush)
>
>     def onButtonPush(self, value, **kws):
>         self.needs_calc = True if value == 1 else False
>
>     def do_work(self):
>         self.go_button = 0
>         self.moving = 1  # Set "in progress"
>
>         ## real code here:
>         xtal_name = self._pvs('xtal').get(as_string=True)
>         dspace = DSPACES[xtal_name]
>         hkl    = np.array([self.h, self.k, self.l])
>         theta  = np.arcsin(np.sqrt(hkl**2).sum() * HC/(2*dspace*self.energy))
>
>         self._pvs['theta'].put(theta, wait=True)
>         self.moving = 0  # Set "not in progress"
>
>     def run(self):
>         while True:
>             epics.poll(0.05)
>             if self.needs_calc:
>                 self.do_work()
>
> if __name__ == '__main__':
>     Analyzer(prefix='XXAnalyzer:').run()
> ####
>
> Slightly off-topic, but for clarity here: pyepics Devices will map the PV "prefix" and "suffix" to Python variable names, so that in the code below, using prefix='XXAnalyzer:' assumes that the PVs are named 'XXAnalyzer:go_button' (probably a 'bo')  'XXAnalyzer:energy', 'XXAnalyzer:h', 'XXAnalyzer:k', and so on. Those will get mapped in the code so that reading or writing to "self.h" will really connect to and get()/put() the PV value, or you can get to the real pyepics PV object with "self._pvs['energy']", which is needed to do things like setting a (monitor) callback, getting the string representation of the value, or doing a put with a simple callback to wait for the processing to complete.
>
> Anyway, that's all to say that it is possible to have a "plain" pyepics script that reacts to a button push on a Display Screen that then does some non-trivial calculation (or triggers some motor movement or detector, etc).
>
> --Matt
>
>
>
> On Thu, Apr 15, 2021 at 12:59 AM Manoussakis, Adamandios via Tech-talk <tech-talk at aps.anl.gov> wrote:
> Hi Kay,
>

>
> Thanks for the link, I tried adding to my settings.ini file but still doesn’t seem to be finding the packages I am importing in my script (pandas, numpy).
>

>
> org.csstudio.display.builder.runtime/python_path=C:\Users\PC\AppData\Local\Programs\Python\Python39\
>

>
> I did find a fairly old post by you on tech talk and was wondering if this still applied to Phoebus/Jython (seems like jython still doesn’t work with numpy from looking around)
>

>
> “CSS BOY scripts are executed in jython, not python.
>
> Most of the default python modules are also available in jython, but when you install python modules with binary dependencies like numpy, MySQL_python, .. those are not available in jython.”
>

>
> If this is the case, it seems like I might have to go the pythonIoc route but I really just wanted to have the script get called when a pv changed value (was using the button to write a value change causing the script to trigger).
>

>

>

>
> Thanks,
>
> Adam
>

>

>

>

>

>

>
> From: Kasemir, Kay <kasemirk at ornl.gov>
> Sent: Wednesday, April 14, 2021 10:41 AM
> To: tech-talk at aps.anl.gov; Manoussakis, Adamandios <manoussakis1 at llnl.gov>
> Subject: Re: Python Script call from Button press, module not found
>

>
> See python_path in https://control-system-studio.readthedocs.io/en/latest/preference_properties.html#display-builder-runtime
>

>
>

--
Complexity comes for free, simplicity you have to work for.



Replies:
Re: Python Script call from Button press, module not found Johnson, Andrew N. via Tech-talk
References:
Python Script call from Button press, module not found Manoussakis, Adamandios via Tech-talk
Re: Python Script call from Button press, module not found Kasemir, Kay via Tech-talk
RE: Python Script call from Button press, module not found Manoussakis, Adamandios via Tech-talk
Re: Python Script call from Button press, module not found Matt Newville via Tech-talk
Re: Python Script call from Button press, module not found Johnson, Andrew N. via Tech-talk

Navigate by Date:
Prev: Re: Python Script call from Button press, module not found Johnson, Andrew N. via Tech-talk
Next: Re: Python Script call from Button press, module not found Johnson, Andrew N. via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
Navigate by Thread:
Prev: RE: Python Script call from Button press, module not found Manoussakis, Adamandios via Tech-talk
Next: Re: Python Script call from Button press, module not found Johnson, Andrew N. via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
ANJ, 16 Apr 2021 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·