DevWare Python
- 1 Overview
- 2 Tutorial
- 3 Ini File Equivalents
- 4 ApBase Module Reference
- 4.1 Camera Class
- 4.2 Sensor Class
- 4.3 Chip Class
- 4.4 RegisterSet Class
- 4.5 Register Class
- 4.6 Bitfield Class
- 4.7 Console Class
- 4.8 Apbase Methods
- 4.9 Apbase Constants
- 5 DevWare Module Reference
- 5.1 DevWare Methods
- 6 Custom Register Dialog Definition via "Register Tabs" preset
- 6.1 Command Syntax
Overview
DevWare embeds Python as its built-in scripting language.
Within a Python script, access to the sensor and DevWare features is through built-in extension modules called Devware and ApBase (Note that this used to be Midlib which has been replaced by ApBase). Functions that correspond to ApBase API calls are in the ApBase module. (ApBase is the library that does all I/O to the sensor including register access and acquiring images. See the ApBase API document.) All other functions are in the DevWare module. The reason for the split is so scripts can work in other ApBase-based applications besides DevWare as long as they don't depend on DevWare-specific features.
To enable Python in DevWareX, you will be prompted with the URL for the 64-bit version.
Here isthe direct link:
https://www.python.org/ftp/python/3.8.2/python-3.8.2-amd64.exe
You can manage the environment as well; see page Python Environment Selection for details.
There is a simple Python console window in DevWare. On the main window select the menu View -> Python Console. The output from executing Python code appears in the upper text box. Commands for immediate execution may be entered in the lower edit box. The command entry window keeps a command history; use the up and down arrows to select a previous command.
The usual way to run Python code within DevWare is to put the code in an ini file and execute it like any other ini file preset. It's also possible to send code to the Python interpreter through the COM interface and from a plug-in.
To run embedded Python from the COM interface, use the RunPython() method. See DevWare COM Interface.
To run embedded Python from a plug-in, use the RunPython() callback. See the Plugin Dialog Development Guide.
Both INI file and Python samples can be found in the installation folder under "samples\Python_Samples" with a description found here.
Tutorial
This is a quick tutorial on using the Python extensions in DevWare. If you are familiar with DevWare ini file commands see also the Ini File Equivalents chapter below.
Python Console Window
DevWare has a simple Python console window. Select the menu item View->Python Console to show the window.
All output directed to stdout or stderr (print() calls and error messages) goes to the top part of the window. In the bottom portion of the window you can type any command or expression for immediate execution.
The Python input() function (sys.stdin.readline()) causes a small pop-up dialog to appear where the user can enter the requested data.
You can put Python code in an ini file, and use the Presets dialog or User Toolbar to execute it.
There are two ways to embed Python in ini files. To execute single Python lines mixed with other ini file commands use a PYTHON= command.
[my preset]
REG= 0x3012, 0
PYTHON= print('set 0x3012 to 0')
Output from Python commands shows up in the Python Console window.
To execute a block of Python code of any size, create a preset with only Python in it. So the ini file interpreter knows to expect Python syntax instead of ini syntax you must have the string 'Python:' somewhere in the name of the preset.
[Python: clear some regs]
for addr in range(0x3600, 0x3800, 2):
reg.reg(addr).value = 0
Python code executes in the context of the _main_ module. DevWare automatically does an import sys, import apbase and import devware, and adds the directory of the ini file to sys.path. It creates a variable called reg that gives convenient access to sensor registers (more on this shortly), and a variable called demo2 (if you are running on a DEMO2 or DEMO2X) or demo3 (if you are using a DEMO3 board) for camera board FPGA registers. You can easily create these variables in your own modules too.
If there is a preset called only [Python:], DevWare will automatically execute it when it loads the ini file. This gives you a convenient place to put additional import statements, function definitions, or any other one-time-execute code. You can use "Hidden:" as with other presets if desired. Example:
[Python:]
import os.path
import re
def image_size_a(w, h):
reg.PRI_A_IMAGE_WIDTH = w
reg.PRI_A_IMAGE_HEIGHT = h
reg.SEQ_CMD = 6
If there is a preset called [Python: Unload], DevWare will automatically execute it when the corresponding ini file window is closed, or when DevWare exits. This can be used to clean up background threads.
DevWare only executes [Python:] when the ini file is opened in a Presets window. In scripts you have to execute [Python:] explicitly if the file isn't in a window, or in applications outside of DevWare.
You can load an ini file into a DevWare Presets window with:
devware.open_ini_file(inifilepath)
This will run [Python:].
DevWare automatically creates a variable called __IniFileName. When the execution of an ini file preset begins, DevWare sets the contents of this variable to the full path to the ini file. This is useful for accessing other files in the same directory as the current ini file. Note that when execution of the preset ends, the variable reverts back to its previous value, so the variable is not meaningful if accessed from a background thread that remains running after the preset that launched it is finished. If the ini file path is needed in a thread function, then it must be passed to the thread function as a parameter.
Aborting a running script
If a Python script is running in the main DevWare UI thread, then the DevWare user interface is not responsive while the script is running. This is the typical case when the user initiates a script in an ini file. In order to allow interrupting a script and aborting its execution, DevWare includes a mechanism which monitors the amount of time the script is running. If the script runs for more than the timeout time, DevWare will show a dialog window allowing the user to abort it. This is useful for cases where the script is running longer than intended, or is in an infinite loop.
In order for this option to work, the library signal has to be imported. This can be done either at the beginning of the individual script, or at the beginning of the default Python preset [Python:] (see section Python in Ini Files).
The following example shows a script with an infinite loop, which can be aborted by the user if the timeout has been set:
[Python: infinite loop]
import signal
i = 0
while i < 1:
i = 0
You set the timeout value by using the DevWare option variable Script Timeout: devware.setoption('Script Timeout', 10). Assigning this variable an integer number would set the timeout to the specified value in seconds. It is not possible to set a timeout in fractions of seconds.
Disable the timeout completely by setting the variable to the value 0.
Once the value has been set, it can always be modified to a new timeout value at any time during the execution of the Python script. DevWare checks whether a different timeout value has been set every 1 second.
ApBase is the library that all DevSuite applications use to access the camera devices. The apbase module provides classes that represent the physical devices on the camera or emulator platform, and classes to represent registers and register bitfields. I/O to the devices is performed by using methods and attributes on instances of these classes that correspond to specific chips and registers.
Accessing Registers
To read or write a register, create an apbase.Register object connected to the desired register and then get or set its value attribute. To illustrate, this example explicitly calls the apbase.Register constructor to create a Register object, and then writes to the register.
blacklevel = apbase.Register(symbol='DATA_PEDESTAL').value # read
apbase.Register(symbol='DATA_PEDESTAL').value = 42 # write
By default the apbase.Register() constructor looks for registers on the sensor. You can also specify another chip (if there's a chip data (.cdat) file loaded for it). You can alternately specify the register by address instead of name.
Explicitly calling the apbase.Register constructor is cumbersome, so for convenience there is the RegisterSet class. The RegisterSet class has helpful attributes and methods for constructing Register objects and writing to registers with short, simple syntax.
A RegisterSet object automatically has attributes corresponding to each of the registers. The predefined variable reg is the register set for the sensor, so reg.DATA_PEDESTAL implicitly calls the Register constructor to construct a Register object for the DATA_PEDESTAL register. The above example can be written as:
blacklevel = reg.DATA_PEDESTAL.value # read
reg.DATA_PEDESTAL.value = 42 # write
As further shorthand, assigning to the register symbol attribute is equivalent to assigning to the value (or float_value) attribute of the register object.
reg.DATA_PEDESTAL = 42
But understand that reg.DATA_PEDESTAL on the right hand side of an assignment or in an expression is the Register object. So
a = reg.DATA_PEDESTAL
sets a to the Register object, not the value of the register. To use the value of the register in an assignment or any expression, either use the value or float_value attribute, or explicitly cast the Register object to an int or float.
a = int(reg.DATA_PEDESTAL)
Note: ApBase Caches Register Values
ApBase keeps the last value read or written to a register in a cache. As an optimization, the value attribute does a cached read. That is, it normally just returns the last read or written value without doing any I/O to the device. So doing a register read like this is very cheap and there is no need for you to cache register values in your Python code. But sometimes you do need to re-do I/O, for example to read a status register that changes automatically. In that case use the uncached_value attribute.
a = reg.JPEG_STATUS.uncached_value # force reading the hardware