r39 - 28 Nov 2012 - 15:31:55 - XiaoqiangWangYou are here: TWiki >  Main Web > ProjectsPortal > NewPythonEpicsInterface

New Python EPICS Interface

Motivation

History

Geoff Savage created caPython(CaChannel) and Mark Rivers extended it to epicsPV and upon that created device support modules, epicsMotor, epicsLogger, epicsScaler, epicsMed, epicsMca. In today's point of view, it has the following limitations:
  • Based on EPICS 3.13. Using APIs obsoleted in EPICS 3.14.
  • For the same reason, no thread support.
  • It is not actively maintained.
  • The code is wrapped by SWIG-1.1 and requires extra work to be used by SWIG-1.3.
On the other hand, Noboru Yamamoto created and still maintains PythonCA. It has been brought up to date with EPICS 3.14. It has the following advantages:
  • With thread support.
  • Preemptive callback is enabled by default, which does not require periodic calls to poll() to process background CA activities.
  • Wrapped with Python/C API, no SWIG dependency.
Indeed there is a third development from Matthew Newville, formerly known as Ezca and has evolved into EpicsCA.
  • EPICS 3.14 compatible.
  • Lacks thread support and disables preemptive callback.
  • Caches all connected PV channels in the C extension level.
  • Wrapped with SWIG 1.3.

Update: From the same author, PyEpics3 is a complete rewrite:

  • EPICS 3.14 compatible using preemptive callback.
  • ctypes is used to wrap ca library.
  • Requires Python 2.5+.
  • Multiple thread support by function decorators.
  • wx integration.

What is in SLS

  • The Python scripts use the CaChannel/epicsPV interface. Most of them are command line programs without the need for multi-threading. Rarely but certainly true, in a GUI program like CVS:G/KEITHLEY, thread support is necessary.
  • For historical reasons, many different copies of the CaChannel library have be installed to:
    /work/sls/lib/python
    /work/sls/lib/python15
    /work/sls/lib/python22
    /work/sls/lib/SL-3/python15
    /work/sls/lib/SL-3/python22
    /work/sls/lib/SL-5/epics-python2.4
    
    But with the upgrade to Scientific Linux 5, the only valid place of this library is /usr/local/epics/extensions/lib/SL5-x86/python2.4/.
  • As of Oct. 24, 2008, this new implementation has been installed to the above mentioned path, and replaces the old files.

Our Approach

PythonCA is chosen as the low-level implementation of the Python to EPICS interface. After a thorough analysis of the API of both CaPython and PythonCA, we rebuilt the CaChannel implementation. The results are the following files:
  • _ca_fnal.py: holds all namespace from _ca and add necessary functions(mostly data type related) not directly implemented in _ca but existing in CaPython.
  • CaChannel.py: CaChannel class interface

Our modification of PythonCA has been kindly accepted into the main release, since 1.20.1.beta2.

Regression Test

ca_cb_gr.py and ca_wf.py are two unmodified test programs from CaPython. The new interface passes all test. However there are subtle differences, see blow.

How to Convert Old Codes

If you only use searchw(), getw(), putw() function calls either using CaChannel or epicsPV classes, then you can safely skip the following discussions. Continue reading if you worry about the internals.

  • In CaPython one needs to call poll() periodically for CA library to process callback functions. This is not needed in PythonCA because preemptive callback is enabled by default.
  • In CaPython, CaChannelException has a member variable status to hold the integer CA error code, ECA_NORMAL etc. In PythonCA, it has been used to hold the string message. But in both cases, print will show the error message.
  • In PythonCA version 1.7 and below, add_masked_array_event ignores the req_type parameter, which means only native field type is supported.
  • In PythonCA, ca.get is always asynchronous. So CaChannel?.array_get is simulated by calling getw. If one calls array_get on a lot of channels and then call pend_io, one would expect all values are got at one shot. But this is not supported. Instead the get request are sent out immediately following array_get call.

Test Suite

Here we demonstrate two typical usage, one is for command line based program and one is for graphical based program with multithread capability.

  • Before Start
    1. Load CVS:/G/EPICS/extensions/src/PythonCA/test/test.db to an IOC:
      iocsh>  dbLoadRecords("test.db")
      It provides the following records,
      • catest - ao
      • castr - stringout
      • cabo - bo
      • cawave - waveform of double
      • cawavec - waveform of char
      • cawaves - waveform of string
    2. Point your Python package search path to the new module,
      export PYTHONPATH=/somewhere/to/be/decided:$PYTHONPATH
  • CVS:G/EPICS/extensions/src/PythonCA/test/test.py is a command line program doing synchronous CA get/put calls.
  • CVS:G/EPICS/extensions/src/PythonCA/test/thread.py is a multithread GUI program using asynchronous CA calls. It spawns a thread to calculate the Fibonacci numbers and put it to PV catest. In the main thread PV catest is monitored and displayed in a Tkinter Label widget.
  • CaChannel has doctest built in. See the test results with command,
    python CaChannel.py -v

Documentation

Basically the CaChannel? API is the same as CaPython, so the documentation of CaChannel is still valid. In the meantime, docstring is fully implemented in CaChannel?. While for the 'ca' API, the compatibilty has been achieved for those functions/definitions without requiring a channel access id, i.e. pend_io, test_io, pend_event, pend_io, poll, alarmStatusString, alarmSeverityString, dbf_type_to_DBR_XXX, dbr_type_is_XXX, dbr_text, dbf_text.

Enhancement

With version 1.8, we have added the following features while keeping backwards compatible,
  • Before that getw accepts only plain request type i.e. DBR_XXX and return a single value or a list. In the new version, it accepts also DBR_CTRL_XXX etc. It returns a dictionary having the following keys,
    Key Request Type Description
    pv_value All a single value or a list
    pv_severity All alarm severity
    pv_status All alarm status
    pv_seconds DBR_TIME_XXX time stamp in seconds.nanoseconds format.
    Note that EPICS epoch is January 1, 1990
    pv_units DBR_GR_XXX and DBR_CTRL_XXX units string
    pv_updislim DBR_GR_XXX and DBR_CTRL_XXX upper display limit
    pv_lodislim DBR_GR_XXX and DBR_CTRL_XXX lower display limit
    pv_upalarmlim DBR_GR_XXX and DBR_CTRL_XXX upper alarm limit
    pv_loalarmlim DBR_GR_XXX and DBR_CTRL_XXX lower alarm limit
    pv_upwarnlim DBR_GR_XXX and DBR_CTRL_XXX upper warning limit
    pv_lowarnlim DBR_GR_XXX and DBR_CTRL_XXX lower warning limit
    pv_precision DBR_GR_XXX and DBR_CTRL_XXX precision
    pv_nostrings DBR_GR_XXX and DBR_CTRL_XXX number of enum states
    pv_statestrings DBR_GR_XXX and DBR_CTRL_XXX list of strings, representation of enum states
    pv_upctrllim DBR_CTRL_XXX upper control limit
    pv_loxtrllim DBR_CTRL_XXX lower ontrol limit
  • numpy support will be enabled at compile time if $NUMPY_MODULE/core/include/numpy/arrayobject.h is found. At runtime numpy can be enabled for numeric waveform PVs,
    • at module level, for all following function calls,
      import CaChannel
      CaChannel.USE_NUMPY=True
      
    • at function level,
      import CaChannel
      chan = CaChannel.CaChannel('myPV')
      chan.searchw()
      chan.getw(use_numpy=True)
      

Known Problems

  • With EPICS base < 3.14.11 on Linux, message "epicsThreadOnceOsd epicsMutexLock failed." randomly appears after scripts finish running and while CA context is destroyed. This sometimes result in exit code 255.
  • In version 1.5 and below, long type field is not converted properly, which cause problems under 64 bit system, see http://www.aps.anl.gov/epics/tech-talk/2010/msg02077.php.
  • Not compatible with Python 3.0, yet.

Install

The releases can be downloaded from https://sourceforge.net/downloads/igor2epics/CaChannel/.

Binary:

OS Python EPICS GCC
Windows 2.6 3.14.11 MinGW 3.4.5
Linux 2.4 3.14.8.2 GCC 4.1.2

Sources: Since release 1.5, it also includes the source from PythonCA, so just run make to build. On the other hand, one can always use the following

  • Download PythonCA from http://www-acc.kek.jp/EPICS_Gr/products.html and untar it, resulting a directory like PythonCA-1.20.2.
  • Download the source package and extract the python scripts to PythonCA-1.20.2.
  • Edit EPICS_config_XXX.py to setup your EPICS environment variables.
  • Edit ca.py, at the bottom of the file, replace from _ca_kek import * with from _ca_fnal import *
  • Run python setup.py build.

Notes: On Microsoft Windows, if statically compiled, then the compiler version must be the same as used to compile Python.

FAQ

Simple use in a one-shot script

Use ca_util,
import ca_util
ca_util.caput('myPV', 12)
print ca_util.caget('myPV')

Get the string representation of a enum PV (menu choice)

import CaChannel
chan=CaChannel.CaChannel('myPV')
chan.searhw()
print chan.getw(CaChannel.ca.DBR_STRING)

Get a PV's control information, high/low limits, units?

  • Use CaChannel, version 1.8+,
    import CaChannel
    chan = CaChannel.CaChannel('myPV')
    chan.searhw()
    print chan.getw(CaChannel.ca.dbf_type_to_CTRL(chan.field_type()))
    
  • Use epicsPV,
    import epicsPV
    pv = epicsPV.epicsPV('myPV')
    pv.getControl()
    for field in dir(pv.callBack):
        print field, ':', getattr(pv.callBack, field)
    

How to move a motor and wait until it finishes moving?

  • Use epicsMotor,
    import epicsMotor
    m = epicsMotor.epicsMotor('myMotor')
    m.move(10)
    m.wait()
    print m.get_position()
    
  • Use epicsPV,
    import epicsPV
    pv = epicsMotor.epicsMotor('myMotor')
    pv.putWait(10)
    

How to connect to thousands of channels quickly?

  • Use CaChannel,
    import CaChannel
    pvs = {}
    for pvName in pvNames:
        pv = CaChannel.CaChannel(pvName)
        pv.search()
        pvs[pvName] = pv
    pvs['FOO'].pend_io()
    
  • User epicsPV,
    import epicsPV
    pvs = {}
    for pvName in pvNames:
        pv = epicsPV.epicsPV(pvName, wait=0)
        pvs[pvName] = pv
    pvs['FOO'].pend_io()
    

-- XiaoqiangWang - 22 Aug 2008

keywords: Python CaChannel? PythonCA?

ProjectForm
Category EpicsProgrammingInterfaceCategory
Goal Create a middle layer to interface CaChannel/epicsPV to KEK's thread safe PythonCA extension.
Originator

Responsible XiaoqiangWang
Crew GaudenzJud
Clients

Status Supported
Work

Start 22 Aug 2008
End

Budget

Problems

Documentation

CVS Location CVS:G/EPICS/extensions/src/PythonCA
Comments

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r39 < r38 < r37 < r36 < r35 | More topic actions
 
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback