Experimental Physics and
| |||||||||||||||||
|
Adam, 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() 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:
| ||||||||||||||||
ANJ, 15 Apr 2021 |
·
Home
·
News
·
About
·
Base
·
Modules
·
Extensions
·
Distributions
·
Download
·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing · |