4. 用Jython和Java编写新设备类¶
4.1. 介绍¶
可以使用GDA中的核心类编写新设备。这些代码可以用Jython或Java编写。
对于Jython和Java:
在代码中定义新设备
加载到服务器(对象服务器)
对于Jython:
在扩展ScanableMotionBase的Jython脚本中定义类
通过导入Jython模块将它们加载到对象服务器,并创建Jython定义的设备的实例
对于Java:
用Java编写实现不同设备接口的新设备。在这里,我们通过编写新的可扫描设备来说明
导入Spring Bean配置文件中定义的类的实例
为了说明用Java开发新设备并将它们合并到GDA中的过程,我们描述了几个实现Scanable接口的新设备的开发过程。然后,通过编辑服务器在启动时读取的配置文件,将这些设备包括在系统中。然后可以从Jython终端在GDA中扫描和操作这些设备。
在使用GDA的每个站点上,为GDA的新设备开发软件可能是一个要求,以便将特定的光束线组件容纳到GDA软件框架中。
用户应该首先阅读GDA用户手册中的“第5章:扫描”,了解GDA中使用的基本数据采集技术的介绍。下面,我们将描述开发实现Scanable接口的新类。这可能需要在每个站点使用GDA进行开发,以便将特定的光束线组件容纳到GDA软件框架中。
4.2. Scanable接口和ScanableBase类¶
所有Scanable类都实现Scanable接口。实现Scanable接口的核心基类在GDA中作为类gda.devive.scannable.ScanableBase提供。新的用户定义的可扫描实现应该扩展ScanableBase。发出命令‘ls Scanable’后,这些实例将在GDA终端中可见。
Scanable实现的最重要方法是:
getPosition()
异步移动到()
isBusy()
扫描对象中必须定义的其他字段包括:
名称
初始位置
inputNames
外部名称
输出格式
单位
有关可扫描实现中可用参数的完整描述,请参阅“GDA用户手册”的“第5章:扫描”。
文档配置源目录中提供了一个测试类,它具有用于构造几种不同类型的“虚拟”或可测试软件扫描对象的实例的静电方法:org.myls.gda.device.scannable.ScannableClassGenerator.它有几种方法:
genarateScanable高斯()
生成可扫描高斯(高斯)
GenerateScanableSine()
GenerateScanableSine(正弦波)
此生成器构造两个可扫描类ScanableGauss和ScanableSine的实例。这些可扫描类在getPosition()返回的值上有所不同。对于ScanableGauss,该方法返回指定位置、宽度和高度为1的高斯的值,如果定义了附加噪声,则返回指定x值处的值:
@Override
public Object getPosition() throws DeviceException {
// we assume the position is a double - it is only for testing
double x = (Double) super.getPosition();
double x2 = x - centre;
double sigma = 0.425 * width // FWHM -> sd
double noiseVal = height * (Math.random() * noise;
double y = Math.exp(-(x2 * x2) / (sigma * sigma)) + noiseVal;
return new Double[] { x, y };
}
4.3. 关于可扫描特性的描述及其之间的关系¶
(本材料来源于GDA用户手册中的“第5章:扫描”;为方便起见,在此重复)
必须在所有扫描对象的构造函数中设置多个字段的值。这些必填字段是:
名称
inputNames
外部名称
输出格式
当前位置
字段“inputNames”、“outputNames”和“outputFormat”一起定义此Scanable表示的数字、它们的名称以及将它们的值打印到文件或控制台的格式。
“”inputNames“”数组定义此Scanable的rawAchronousMoveTo预期的数组大小。inputNames数组的每个元素都是该元素的标签,用于文件头等。请注意,如果需要,此数组可以为空(大小为0)。
ExtraNames‘’数组的使用方式与inputNames数组类似,但列出了Scanable的rawGetPosition()方法返回的数组中的其他元素,即getRawPosition()返回的数组可能大于rawAsynousMoveTo()所需的数组。这允许Scanable保存和返回比移动pr所需更多的信息,以便在其rawAchronousMoveTo()方法内执行任何操作。此数组通常为空(大小为0)。
“”outputFormat“”数组列出了inputNames和ExtraNames数组元素的格式字符串。将rawGetPosition()方法的输出打印到控制台和日志文件时使用。
注解
绝对要求outputFormat数组的长度是inputNames和outputNames数组的长度之和,这样Scanable才能正常工作。‘“’
4.4. 向服务器添加新设备¶
通过将新设备定义为Spring beans配置文件中的bean,将其添加到服务器。在发行版中,此文件为‘xml’目录中的‘server_beans.xml’。有关在Spring bean配置文件中将新对象实例定义为bean的语法,可以参考此文件。此文件中定义的bean在服务器启动时加载到对象服务器中,并且可以由GDA客户端访问和操作。
可以使用getter和构造函数依赖注入。服务器上的每个对象都必须有一个“name”属性,该属性是其在服务器对象命名空间中的唯一标识符。作为示例,我们使用不同的bean定义定义了ScanableGauss类的几个实例:
scannableGaussian0-Bean定义中设置的所有属性
scannableGaussian1-仅在bean中设置高斯属性。其他属性(如输入和额外名称以及输出格式)在Java构造函数中设置为默认值
scannableGaussian2-使用构造函数参数定义scannable,该参数是Spring配置文件中定义的测试高斯bean。这演示了Spring的构造函数依赖项注入
scannableGaussian3-Bean中没有定义任何属性或构造函数参数。scannable是使用默认的无参数构造函数构造的。在Java类中,所有必需的属性都设置为默认值。
Spring配置文件中的scannableSine类的几个实例提供了类似的示例:
scannableSine0-正弦的名称和属性在bean定义中设置。其他属性(如输入和额外名称以及输出格式)的默认值在Java类中定义。
scannableSine1-正弦的属性由Bean配置文件中定义的测试正弦Bean(‘testSineWave’Bean)分配给对象
scannableSine2-在bean定义中没有定义除名称之外的任何属性。所有其他属性都在Java类的零参数构造函数中设置。
4.4.1. 示例:带有设置器注入的可扫描高斯¶
Scanable高斯的字段在Spring bean配置文件中设置为属性,并定义默认值。原子字段使用‘name’和‘value’属性字段定义;数组字段使用‘list’标记定义:
<bean id='scannableGaussian1' class='org.myls.gda.device.scannable.ScannableGaussian'>
<property name='name' valuew='simpleScannable1'/>
<property name='position' value='0.0'/>
<property name='inputNames'>
<list>
<value>x</value>
</list>
</property>
<property name='extraNames'>
<list>
<value>y</value>
</list>
</property>
<property name='level' value='3'/>
<property name='outputFormat'>
<list>
<value>%5.5G</value>
<value>%5.5G</value>
</list>
</property>
<property name='units'>
<list>
<value>mm</value>
<value>counts</value>
</list>
</property>
</bean>
现在使用预定义的高斯Spring bean实例化ScanableGaussbean。测试高斯对象的Spring Bean定义:
<bean id='testGaussian' class='org.myls.gda.device.scannable.Gaussian'>
<property name='testGaussian' value='testGaussian'/>
<property name='centre' value='0.0'/>
<property name='width' value='1.0'/>
<property name='height' value='1.0'/>
<property name='noise' value='0.1'/>
</bean>
此测试高斯bean可用于使用构造函数注入(将测试高斯作为构造函数参数)创建ScanableGauss的实例:
<bean id='scannableGaussian2'>
<property name='name' value='scannableGassian2'/>
<constructor-arg ref='testGaussian'/>
</bean>
4.4.2. 锻炼¶
从一个空的server_beans.xml文件开始,逐个添加可扫描组件,并在GDA Jython控制台中测试它们(需要重新启动服务器才能合并新组件)。
4.5. GDA中其他可扫描类和测试的示例¶
DummyMotor:来自核心:gda.device.Motor.DummyMotor
ScanableMotorTest:来自core/test:gda.device.scannable.ScanableMotorTest
内核中的TotalDummyMotor(测试使用):gda.device.Motor.TotalDummyMotor
4.6. 演示终端中扫描仪的使用¶
现在可以从GDA客户端控制新组件。
4.6.1. 扫描1D¶
可以从GDA GUI中的Jython终端扫描和操作示例扫描。
按步骤0.01::扫描示例scannable scannableGaussian0,从-2到2。
>>> scan scannableGaussian0 -2.0 2.0 0.1
将scannableGaussian0的宽度从1更改为2,然后重新扫描::
>>> scannableGaussian0.setWidth(2)
>>> scan scannableGaussian0 -2.0 2.0 0.1
将scannableGaussian0的中心更改为-1.0并重新扫描::
>>> scannableGaussian0.setCentre(-1)
>>> scan scannableGaussian0 -2.0 2.0 0.1
4.6.2. 嵌套扫描¶
导入用户演示模块scannableClasses.py(位于‘Documentation/Users/Script’中,可从JythonEditor视图查看)中定义的演示可扫描类:
>>> import scannableClasses
>>> from scannableClasses import *
>>> sgw = ScannableGaussianWidth('sgw', scannableGaussian0)
>>> scan sgw 0.2 2.0 0.2 scannableGaussian0 -1.0 1.0 0.02
该嵌套扫描具有外部扫描,该外部扫描以0.2为步长将所包含的可扫描高斯的宽度设置为从0.2到2.0的不同值。然后,以0.02的步长绘制从-1.0到1.0的每个宽度的内部可扫描图像