Original Design#
Note
This page was the initial plan for what PVI would do. The produce features have now been removed and only direct conversion to a Device representation and then formatting of UIs is supported now. This page is kept now to record the design in case full integration into areaDetector is revisited in the future.
Aim |
Description |
---|---|
Reduce boilerplate |
At the moment you can write a simple asyn port driver in code, but there is a lot of boilerplate to connect it to the outside world. The createParam section, the database template records, and the lowest level screens are all quite repetitive and each layer looks like it could be autogenerated without much extra information |
Reduce copy paste errors |
At the moment it is easy to create screens and database templates via copy and paste, but not changing a record name or parameter leads to hard to track down errors |
Support site specific styles for screens |
Each site has their own style for screens, and many sites have their own site specific display manager. Rather than start with one display manager and convert, PVI takes a cut down Channel description (just a type, pv and widget), and lets the site specific template generate the screen according to local styles |
How it works#
The YAML file contains information about each asyn parameter that will be exposed by the driver, it’s name, type, description, initial value, which record type it uses, whether it is writeable or read only, which widget should be used, etc. PVI reads these and passes them to Producer that creates intermediate Record, Channel and AsynParam objects. These are passed to a site specific Formatter which takes the tree of intermediate objects and writes a parameter CPP file, database template, and site specific screens to disk.
YAML file#
The YAML file is formed of a number of sections:
Section |
Description |
---|---|
includes |
The YAML files to use as base classes for superclasses |
local |
A local override YAML file for site specific changes |
producer |
Producer that knows how to create Records and Channels from the Components |
formatter |
Site specific Formatter which can format the output files |
components |
Tree of Components for each logical asyn parameter arranged in logical GUI groups |
The Components are created from the YAML file with local overrides (also incorporating the base classes for screens). These are passed to the Producer which produces AsynParameters, Records and Channels. These are then passed to the Formatter which outputs them to file:
Here’s a cut down pilatus.yaml file that might describe a parameter in a detector:
type: AsynProducer
prefix: $(P)$(R)
label: pilatus
asyn_port: $(PORT)
address: $(ADDR)
timeout: $(TIMEOUT)
parent: ADDriver
parameters:
- type: Group
name: ComponentGroupOne
layout:
type: Grid
children:
- type: AsynBinary
name: ResetPower
description: ResetPower
index_name: PilatusResetPower
drv_info: RESET_POWER
access: W
record_fields:
ZNAM: Done
ONAM: Reset
- type: AsynBusy
name: ThresholdApply
description: ThresholdApply
index_name: PilatusThresholdApply
drv_info: THRESHOLD_APPLY
access: W
initial: "0"
record_fields:
ZNAM: Done
ONAM: Apply
- type: AsynFloat64
name: ImageFileTmot
description: Timeout for image file
index_name: PilatusImageFileTmot
drv_info: IMAGE_FILE_TMOT
access: W
initial: "20"
record_fields:
PREC: "3"
EGU: s
- type: AsynFloat64
name: Wavelength
description: Wavelength
index_name: PilatusWavelength
drv_info: WAVELENGTH
access: W
initial: "1.54"
record_fields:
PREC: "4"
EGU: Angstroms
- type: AsynFloat64
name: EnergyLow
description: EnergyLow
index_name: PilatusEnergyLow
drv_info: ENERGY_LOW
access: W
initial: "0"
record_fields:
PREC: "3"
EGU: eV
- type: AsynFloat64
name: EnergyHigh
description: EnergyHigh
index_name: PilatusEnergyHigh
drv_info: ENERGY_HIGH
access: W
initial: "0"
record_fields:
PREC: "3"
EGU: eV
- type: AsynFloat64
name: DetDist
description: DetDist
index_name: PilatusDetDist
drv_info: DET_DIST
access: W
initial: "1000"
record_fields:
PREC: "3"
EGU: mm
- type: AsynFloat64
name: DetVOffset
description: DetVOffset
index_name: PilatusDetVOffset
drv_info: DET_VOFFSET
access: W
initial: "0"
record_fields:
PREC: "3"
EGU: mm
- type: AsynFloat64
name: BeamX
description: BeamX
index_name: PilatusBeamX
drv_info: BEAM_X
access: W
initial: "0"
record_fields:
PREC: "3"
EGU: pixels
- type: AsynFloat64
name: BeamY
description: BeamY
index_name: PilatusBeamY
drv_info: BEAM_Y
access: W
initial: "0"
record_fields:
PREC: "3"
EGU: pixels
- type: AsynFloat64
name: Flux
description: Flux
index_name: PilatusFlux
drv_info: FLUX
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: ph/s
- type: AsynFloat64
name: FilterTransm
description: FilterTransm
index_name: PilatusFilterTransm
drv_info: FILTER_TRANSM
access: W
initial: "1.0"
record_fields:
PREC: "4"
- type: AsynFloat64
name: StartAngle
description: StartAngle
index_name: PilatusStartAngle
drv_info: START_ANGLE
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: AngleIncr
description: AngleIncr
index_name: PilatusAngleIncr
drv_info: ANGLE_INCR
access: W
initial: "0.1"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: Det2theta
description: Det2theta
index_name: PilatusDet2theta
drv_info: DET_2THETA
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: Polarization
description: Polarization
index_name: PilatusPolarization
drv_info: POLARIZATION
access: W
initial: "0.99"
record_fields:
PREC: "4"
- type: AsynFloat64
name: Alpha
description: Alpha
index_name: PilatusAlpha
drv_info: ALPHA
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: Kappa
description: Kappa
index_name: PilatusKappa
drv_info: KAPPA
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: Phi
description: Phi
index_name: PilatusPhi
drv_info: PHI
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: PhiIncr
description: PhiIncr
index_name: PilatusPhiIncr
drv_info: PHI_INCR
access: W
initial: "0.1"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: Chi
description: Chi
index_name: PilatusChi
drv_info: CHI
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: ChiIncr
description: ChiIncr
index_name: PilatusChiIncr
drv_info: CHI_INCR
access: W
initial: "0.1"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: Omega
description: Omega
index_name: PilatusOmega
drv_info: OMEGA
access: W
initial: "0"
record_fields:
PREC: "4"
EGU: deg
- type: AsynFloat64
name: OmegaIncr
description: OmegaIncr
index_name: PilatusOmegaIncr
drv_info: OMEGA_INCR
access: W
initial: "0.1"
record_fields:
PREC: "4"
EGU: deg
- type: AsynString
name: OscillAxis
description: OscillAxis
index_name: PilatusOscillAxis
drv_info: OSCILL_AXIS
access: W
initial: X, CW
- type: AsynLong
name: NumOscill
description: NumOscill
index_name: PilatusNumOscill
drv_info: NUM_OSCILL
access: W
initial: "1"
- type: AsynWaveform
name: BadPixelFile
description: BadPixelFile
index_name: PilatusBadPixelFile
drv_info: BAD_PIXEL_FILE
access: W
record_fields:
NELM: "256"
FTVL: CHAR
- type: AsynWaveform
name: FlatFieldFile
description: FlatFieldFile
index_name: PilatusFlatFieldFile
drv_info: FLAT_FIELD_FILE
access: W
record_fields:
NELM: "256"
FTVL: CHAR
- type: AsynWaveform
name: CbfTemplateFile
description: CbfTemplateFile
index_name: PilatusCbfTemplateFile
drv_info: CBFTEMPLATEFILE
access: W
record_fields:
NELM: "256"
FTVL: CHAR
- type: AsynWaveform
name: HeaderString
description: HeaderString
index_name: PilatusHeaderString
drv_info: HEADERSTRING
access: W
record_fields:
NELM: "68"
FTVL: CHAR
- type: AsynBinary
name: Armed
description: Armed
index_name: PilatusArmed
drv_info: ARMED
access: R
read_record_suffix: Armed
record_fields:
SCAN: I/O Intr
ZNAM: Unarmed
ONAM: Armed
- type: AsynLong
name: NumBadPixels
description: Number of bad pixels
index_name: PilatusNumBadPixels
drv_info: NUM_BAD_PIXELS
access: R
read_record_suffix: NumBadPixels
record_fields:
SCAN: I/O Intr
- type: AsynBinary
name: FlatFieldValid
description: Flat field valid
index_name: PilatusFlatFieldValid
drv_info: FLAT_FIELD_VALID
access: R
read_record_suffix: FlatFieldValid
record_fields:
SCAN: I/O Intr
ZNAM: No
ONAM: Yes
- type: AsynInt32
name: PixelCutOff
description: PixelCutOff_RBV
index_name: PilatusPixelCutOff
drv_info: PIXEL_CUTOFF
access: R
record_fields:
SCAN: I/O Intr
EGU: counts
- type: AsynFloat64
name: Temp0
description: Temp0_RBV
index_name: PilatusThTemp0
drv_info: TH_TEMP_0
access: R
record_fields:
SCAN: I/O Intr
PREC: "1"
EGU: C
- type: AsynFloat64
name: Temp1
description: Temp1_RBV
index_name: PilatusThTemp1
drv_info: TH_TEMP_1
access: R
record_fields:
SCAN: I/O Intr
PREC: "1"
EGU: C
- type: AsynFloat64
name: Temp2
description: Temp2_RBV
index_name: PilatusThTemp2
drv_info: TH_TEMP_2
access: R
record_fields:
SCAN: I/O Intr
PREC: "1"
EGU: C
- type: AsynFloat64
name: Humid0
description: Humid0_RBV
index_name: PilatusThHumid0
drv_info: TH_HUMID_0
access: R
record_fields:
SCAN: I/O Intr
PREC: "1"
EGU: "%"
- type: AsynFloat64
name: Humid1
description: Humid1_RBV
index_name: PilatusThHumid1
drv_info: TH_HUMID_1
access: R
record_fields:
SCAN: I/O Intr
PREC: "1"
EGU: "%"
- type: AsynFloat64
name: Humid2
description: Humid2_RBV
index_name: PilatusThHumid2
drv_info: TH_HUMID_2
access: R
record_fields:
SCAN: I/O Intr
PREC: "1"
EGU: "%"
- type: AsynString
name: TVXVersion
description: TVXVersion_RBV
index_name: PilatusTvxVersion
drv_info: TVXVERSION
access: R
record_fields:
SCAN: I/O Intr
- type: AsynLong
name: ResetPowerTime
description: Reset module power wait time
index_name: PilatusResetPowerTime
drv_info: RESET_POWER_TIME
initial: "1"
record_fields:
SCAN: I/O Intr
EGU: Seconds
- type: AsynFloat64
name: DelayTime
description: DelayTime
index_name: PilatusDelayTime
drv_info: DELAY_TIME
initial: "0"
record_fields:
SCAN: I/O Intr
PREC: "6"
EGU: s
- type: AsynFloat64
name: ThresholdEnergy
description: Energy threshold
index_name: PilatusThreshold
drv_info: THRESHOLD
initial: "10.000"
record_fields:
SCAN: I/O Intr
PREC: "3"
EGU: keV
- type: AsynBinary
name: ThresholdAutoApply
description: ThresholdAutoApply
index_name: PilatusThresholdAutoApply
drv_info: THRESHOLD_AUTO_APPLY
initial: "1"
record_fields:
SCAN: I/O Intr
ZNAM: No
ONAM: Yes
- type: AsynFloat64
name: Energy
description: X-ray Energy
index_name: PilatusEnergy
drv_info: ENERGY
initial: "20.000"
record_fields:
SCAN: I/O Intr
PREC: "3"
EGU: keV
- type: AsynLong
name: MinFlatField
description: Minimum flat field value
index_name: PilatusMinFlatField
drv_info: MIN_FLAT_FIELD
initial: "100"
record_fields:
SCAN: I/O Intr
EGU: Counts
- type: AsynMultiBitBinary
name: GapFill
description: GapFill
index_name: PilatusGapFill
drv_info: GAP_FILL
initial: "0"
record_fields:
SCAN: I/O Intr
ZRVL: "2"
ONVL: "0"
TWVL: "-1"
ZRST: N.A.
ONST: "0"
TWST: "-1"
- type: AsynFloat64
name: ProgressBarTest
description: ProgressBar
drv_info: PROGRESS
access: R
read_widget:
type: ProgressBar
initial: 50.0
record_fields:
EGU: deg
PREC: 4
index_name: ProgressBarTest
Screen files#
The intermediate objects are a number of Channel instances. These contain basic types (like Combo, TextInput, TextUpdate, LED, Group) and some creation hints (like label, grouping, description, display_form), but no X, Y, Width, Height or colour information. They may represent either a single widget or pair of demand/readback widgets.
The site-specific Formatter consumes these Channel objects, then produces a screen with style, sizing and layout that can be customized to the site. This means that the default layout (big screen with lots of widgets arranged in group boxes) could be produced for one site, then another site could make lots of little screens with one group per screen. Styling is also covered, so the blue/grey MEDM screens and green/grey EDM screens can be customized to fit the site style guide.
HTML Documentation#
The Parameter and record sections of the existing documentation could be reproduced, in tabular form as a csv file that can be included in rst docs:
Parameter Index Variable |
Asyn Interface |
Access |
drvInfo String |
Record Names |
Record Types |
Description |
---|---|---|---|---|---|---|
ComponentGroupOne |
||||||
PilatusResetPower |
asynInt32 |
W |
RESET_POWER |
$(P)$(R)ResetPower |
bo |
ResetPower |
PilatusThresholdApply |
asynInt32 |
W |
THRESHOLD_APPLY |
$(P)$(R)ThresholdApply |
busy |
ThresholdApply |
PilatusImageFileTmot |
asynFloat64 |
W |
IMAGE_FILE_TMOT |
$(P)$(R)ImageFileTmot |
ao |
Timeout for image file |
PilatusWavelength |
asynFloat64 |
W |
WAVELENGTH |
$(P)$(R)Wavelength |
ao |
Wavelength |
PilatusEnergyLow |
asynFloat64 |
W |
ENERGY_LOW |
$(P)$(R)EnergyLow |
ao |
EnergyLow |
PilatusEnergyHigh |
asynFloat64 |
W |
ENERGY_HIGH |
$(P)$(R)EnergyHigh |
ao |
EnergyHigh |
PilatusDetDist |
asynFloat64 |
W |
DET_DIST |
$(P)$(R)DetDist |
ao |
DetDist |
PilatusDetVOffset |
asynFloat64 |
W |
DET_VOFFSET |
$(P)$(R)DetVOffset |
ao |
DetVOffset |
PilatusBeamX |
asynFloat64 |
W |
BEAM_X |
$(P)$(R)BeamX |
ao |
BeamX |
PilatusBeamY |
asynFloat64 |
W |
BEAM_Y |
$(P)$(R)BeamY |
ao |
BeamY |
PilatusFlux |
asynFloat64 |
W |
FLUX |
$(P)$(R)Flux |
ao |
Flux |
PilatusFilterTransm |
asynFloat64 |
W |
FILTER_TRANSM |
$(P)$(R)FilterTransm |
ao |
FilterTransm |
PilatusStartAngle |
asynFloat64 |
W |
START_ANGLE |
$(P)$(R)StartAngle |
ao |
StartAngle |
PilatusAngleIncr |
asynFloat64 |
W |
ANGLE_INCR |
$(P)$(R)AngleIncr |
ao |
AngleIncr |
PilatusDet2theta |
asynFloat64 |
W |
DET_2THETA |
$(P)$(R)Det2theta |
ao |
Det2theta |
PilatusPolarization |
asynFloat64 |
W |
POLARIZATION |
$(P)$(R)Polarization |
ao |
Polarization |
PilatusAlpha |
asynFloat64 |
W |
ALPHA |
$(P)$(R)Alpha |
ao |
Alpha |
PilatusKappa |
asynFloat64 |
W |
KAPPA |
$(P)$(R)Kappa |
ao |
Kappa |
PilatusPhi |
asynFloat64 |
W |
PHI |
$(P)$(R)Phi |
ao |
Phi |
PilatusPhiIncr |
asynFloat64 |
W |
PHI_INCR |
$(P)$(R)PhiIncr |
ao |
PhiIncr |
PilatusChi |
asynFloat64 |
W |
CHI |
$(P)$(R)Chi |
ao |
Chi |
PilatusChiIncr |
asynFloat64 |
W |
CHI_INCR |
$(P)$(R)ChiIncr |
ao |
ChiIncr |
PilatusOmega |
asynFloat64 |
W |
OMEGA |
$(P)$(R)Omega |
ao |
Omega |
PilatusOmegaIncr |
asynFloat64 |
W |
OMEGA_INCR |
$(P)$(R)OmegaIncr |
ao |
OmegaIncr |
PilatusOscillAxis |
asynOctetWrite |
W |
OSCILL_AXIS |
$(P)$(R)OscillAxis |
stringout |
OscillAxis |
PilatusNumOscill |
asynInt32 |
W |
NUM_OSCILL |
$(P)$(R)NumOscill |
longout |
NumOscill |
PilatusBadPixelFile |
asynOctetWrite |
W |
BAD_PIXEL_FILE |
$(P)$(R)BadPixelFile |
waveform |
BadPixelFile |
PilatusFlatFieldFile |
asynOctetWrite |
W |
FLAT_FIELD_FILE |
$(P)$(R)FlatFieldFile |
waveform |
FlatFieldFile |
PilatusCbfTemplateFile |
asynOctetWrite |
W |
CBFTEMPLATEFILE |
$(P)$(R)CbfTemplateFile |
waveform |
CbfTemplateFile |
PilatusHeaderString |
asynOctetWrite |
W |
HEADERSTRING |
$(P)$(R)HeaderString |
waveform |
HeaderString |
PilatusArmed |
asynInt32 |
R |
ARMED |
$(P)$(R)Armed |
bi |
Armed |
PilatusNumBadPixels |
asynInt32 |
R |
NUM_BAD_PIXELS |
$(P)$(R)NumBadPixels |
longin |
Number of bad pixels |
PilatusFlatFieldValid |
asynInt32 |
R |
FLAT_FIELD_VALID |
$(P)$(R)FlatFieldValid |
bi |
Flat field valid |
PilatusPixelCutOff |
asynInt32 |
R |
PIXEL_CUTOFF |
$(P)$(R)PixelCutOff_RBV |
ai |
PixelCutOff_RBV |
PilatusThTemp0 |
asynFloat64 |
R |
TH_TEMP_0 |
$(P)$(R)Temp0_RBV |
ai |
Temp0_RBV |
PilatusThTemp1 |
asynFloat64 |
R |
TH_TEMP_1 |
$(P)$(R)Temp1_RBV |
ai |
Temp1_RBV |
PilatusThTemp2 |
asynFloat64 |
R |
TH_TEMP_2 |
$(P)$(R)Temp2_RBV |
ai |
Temp2_RBV |
PilatusThHumid0 |
asynFloat64 |
R |
TH_HUMID_0 |
$(P)$(R)Humid0_RBV |
ai |
Humid0_RBV |
PilatusThHumid1 |
asynFloat64 |
R |
TH_HUMID_1 |
$(P)$(R)Humid1_RBV |
ai |
Humid1_RBV |
PilatusThHumid2 |
asynFloat64 |
R |
TH_HUMID_2 |
$(P)$(R)Humid2_RBV |
ai |
Humid2_RBV |
PilatusTvxVersion |
asynOctetRead |
R |
TVXVERSION |
$(P)$(R)TVXVersion_RBV |
stringin |
TVXVersion_RBV |
PilatusResetPowerTime |
asynInt32 |
RW |
RESET_POWER_TIME |
$(P)$(R)ResetPowerTime, $(P)$(R)ResetPowerTime_RBV |
longout, longin |
Reset module power wait time |
PilatusDelayTime |
asynFloat64 |
RW |
DELAY_TIME |
$(P)$(R)DelayTime, $(P)$(R)DelayTime_RBV |
ao, ai |
DelayTime |
PilatusThreshold |
asynFloat64 |
RW |
THRESHOLD |
$(P)$(R)ThresholdEnergy, $(P)$(R)ThresholdEnergy_RBV |
ao, ai |
Energy threshold |
PilatusThresholdAutoApply |
asynInt32 |
RW |
THRESHOLD_AUTO_APPLY |
$(P)$(R)ThresholdAutoApply, $(P)$(R)ThresholdAutoApply_RBV |
bo, bi |
ThresholdAutoApply |
PilatusEnergy |
asynFloat64 |
RW |
ENERGY |
$(P)$(R)Energy, $(P)$(R)Energy_RBV |
ao, ai |
X-ray Energy |
PilatusMinFlatField |
asynInt32 |
RW |
MIN_FLAT_FIELD |
$(P)$(R)MinFlatField, $(P)$(R)MinFlatField_RBV |
longout, longin |
Minimum flat field value |
PilatusGapFill |
asynInt32 |
RW |
GAP_FILL |
$(P)$(R)GapFill, $(P)$(R)GapFill_RBV |
mbbo, mbbi |
GapFill |
ProgressBarTest |
asynFloat64 |
R |
PROGRESS |
$(P)$(R)ProgressBarTest_RBV |
ai |
ProgressBar |
Questions#
I am fairly happy with the scheme set out above, but there are a lot of implementation questions. Here are the most pressing:
One-time generation and checked into source control or generated by Makefile?#
The process would probably be:
If pvi cli tool available, build products as part of make
Check in products to source control
End users will only regenerate build products if pvi tool installed
ADGenICam would be supported by building a GenICamProducer which took no components, just a path to a GenICam XML file
Which screen tools to support?#
I suggest creating adl and edl files initially, following the example of makeAdl.py in ADGenICam, then expanding to support opi, bob and ui files natively. This would avoid needing screen converters installed
Drivers#
The generated header file contains the string parameters, and defines the parameters to make the interface. In this example we have a header file pilatusDetectorParamSet.h:
#ifndef PilatusDetectorParamSet_H
#define PilatusDetectorParamSet_H
#include "ADDriverParamSet.h"
#define PilatusResetPowerString "RESET_POWER"
#define PilatusThresholdApplyString "THRESHOLD_APPLY"
#define PilatusImageFileTmotString "IMAGE_FILE_TMOT"
#define PilatusWavelengthString "WAVELENGTH"
#define PilatusEnergyLowString "ENERGY_LOW"
#define PilatusEnergyHighString "ENERGY_HIGH"
#define PilatusDetDistString "DET_DIST"
#define PilatusDetVOffsetString "DET_VOFFSET"
#define PilatusBeamXString "BEAM_X"
#define PilatusBeamYString "BEAM_Y"
#define PilatusFluxString "FLUX"
#define PilatusFilterTransmString "FILTER_TRANSM"
#define PilatusStartAngleString "START_ANGLE"
#define PilatusAngleIncrString "ANGLE_INCR"
#define PilatusDet2thetaString "DET_2THETA"
#define PilatusPolarizationString "POLARIZATION"
#define PilatusAlphaString "ALPHA"
#define PilatusKappaString "KAPPA"
#define PilatusPhiString "PHI"
#define PilatusPhiIncrString "PHI_INCR"
#define PilatusChiString "CHI"
#define PilatusChiIncrString "CHI_INCR"
#define PilatusOmegaString "OMEGA"
#define PilatusOmegaIncrString "OMEGA_INCR"
#define PilatusOscillAxisString "OSCILL_AXIS"
#define PilatusNumOscillString "NUM_OSCILL"
#define PilatusBadPixelFileString "BAD_PIXEL_FILE"
#define PilatusFlatFieldFileString "FLAT_FIELD_FILE"
#define PilatusCbfTemplateFileString "CBFTEMPLATEFILE"
#define PilatusHeaderStringString "HEADERSTRING"
#define PilatusArmedString "ARMED"
#define PilatusNumBadPixelsString "NUM_BAD_PIXELS"
#define PilatusFlatFieldValidString "FLAT_FIELD_VALID"
#define PilatusPixelCutOffString "PIXEL_CUTOFF"
#define PilatusThTemp0String "TH_TEMP_0"
#define PilatusThTemp1String "TH_TEMP_1"
#define PilatusThTemp2String "TH_TEMP_2"
#define PilatusThHumid0String "TH_HUMID_0"
#define PilatusThHumid1String "TH_HUMID_1"
#define PilatusThHumid2String "TH_HUMID_2"
#define PilatusTvxVersionString "TVXVERSION"
#define PilatusResetPowerTimeString "RESET_POWER_TIME"
#define PilatusDelayTimeString "DELAY_TIME"
#define PilatusThresholdString "THRESHOLD"
#define PilatusThresholdAutoApplyString "THRESHOLD_AUTO_APPLY"
#define PilatusEnergyString "ENERGY"
#define PilatusMinFlatFieldString "MIN_FLAT_FIELD"
#define PilatusGapFillString "GAP_FILL"
#define ProgressBarTestString "PROGRESS"
const std::string pilatusParamTree = \
"{\"parameters\":[{\"type\": \"Group\", \"name\": \"ComponentGroupOne\", \"label\": \"\", \"layout\": {\"type\": \"Grid\", \"labelled\": true}, \"children\": [{\"type\": \"SignalW\", \"name\": \"WaitForPlugins\", \"label\": \"\", \"pv\": \"WaitForPlugins\", \"widget\": {\"type\": \"CheckBox\"}}, {\"type\": \"SignalW\", \"name\": \"EmptyFreeList\", \"label\": \"\", \"pv\": \"EmptyFreeList\", \"widget\": {\"type\": \"CheckBox\"}}, {\"type\": \"SignalW\", \"name\": \"NDAttributesMacros\", \"label\": \"\", \"pv\": \"NDAttributesMacros\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"NDAttributesFile\", \"label\": \"\", \"pv\": \"NDAttributesFile\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ADCoreVersion\", \"label\": \"\", \"pv\": \"ADCoreVersion_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"DriverVersion\", \"label\": \"\", \"pv\": \"DriverVersion_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"PortName\", \"label\": \"\", \"pv\": \"PortName_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Manufacturer\", \"label\": \"\", \"pv\": \"Manufacturer_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Model\", \"label\": \"\", \"pv\": \"Model_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"SerialNumber\", \"label\": \"\", \"pv\": \"SerialNumber_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"SDKVersion\", \"label\": \"\", \"pv\": \"SDKVersion_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"FirmwareVersion\", \"label\": \"\", \"pv\": \"FirmwareVersion_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"AcquireBusyCB\", \"label\": \"\", \"pv\": \"AcquireBusyCB\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"BayerPattern\", \"label\": \"\", \"pv\": \"BayerPattern_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ArraySizeX\", \"label\": \"\", \"pv\": \"ArraySizeX_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ArraySizeY\", \"label\": \"\", \"pv\": \"ArraySizeY_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ArraySizeZ\", \"label\": \"\", \"pv\": \"ArraySizeZ_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ArraySize\", \"label\": \"\", \"pv\": \"ArraySize_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Codec\", \"label\": \"\", \"pv\": \"Codec_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"CompressedSize\", \"label\": \"\", \"pv\": \"CompressedSize_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"UniqueId\", \"label\": \"\", \"pv\": \"UniqueId_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"TimeStamp\", \"label\": \"\", \"pv\": \"TimeStamp_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"EpicsTSSec\", \"label\": \"\", \"pv\": \"EpicsTSSec_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"EpicsTSNsec\", \"label\": \"\", \"pv\": \"EpicsTSNsec_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"NDAttributesStatus\", \"label\": \"\", \"pv\": \"NDAttributesStatus\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"PoolMaxMem\", \"label\": \"\", \"pv\": \"PoolMaxMem\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"PoolUsedMem\", \"label\": \"\", \"pv\": \"PoolUsedMem\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"PoolAllocBuffers\", \"label\": \"\", \"pv\": \"PoolAllocBuffers\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"PoolFreeBuffers\", \"label\": \"\", \"pv\": \"PoolFreeBuffers\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"NumQueuedArrays\", \"label\": \"\", \"pv\": \"NumQueuedArrays\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"Acquire\", \"label\": \"\", \"pv\": \"Acquire\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"\", \"read_widget\": null}, {\"type\": \"SignalRW\", \"name\": \"NDimensions\", \"label\": \"\", \"pv\": \"NDimensions\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"NDimensions_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"Dimensions\", \"label\": \"\", \"pv\": \"Dimensions\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"Dimensions_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"DataType\", \"label\": \"\", \"pv\": \"DataType\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"DataType_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ColorMode\", \"label\": \"\", \"pv\": \"ColorMode\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"ColorMode_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ArrayCounter\", \"label\": \"\", \"pv\": \"ArrayCounter\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"ArrayCounter_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ArrayCallbacks\", \"label\": \"\", \"pv\": \"ArrayCallbacks\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"ArrayCallbacks_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"FilePathExists\", \"label\": \"\", \"pv\": \"FilePathExists_RBV\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"FullFileName\", \"label\": \"\", \"pv\": \"FullFileName_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"NumCaptured\", \"label\": \"\", \"pv\": \"NumCaptured_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"WriteStatus\", \"label\": \"\", \"pv\": \"WriteStatus\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"WriteMessage\", \"label\": \"\", \"pv\": \"WriteMessage\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"FilePath\", \"label\": \"\", \"pv\": \"FilePath\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"FilePath_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"CreateDirectory\", \"label\": \"\", \"pv\": \"CreateDirectory\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"CreateDirectory_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"FileName\", \"label\": \"\", \"pv\": \"FileName\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"FileName_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"FileNumber\", \"label\": \"\", \"pv\": \"FileNumber\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"\", \"read_widget\": null}, {\"type\": \"SignalRW\", \"name\": \"AutoIncrement\", \"label\": \"\", \"pv\": \"AutoIncrement\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"AutoIncrement_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"FileTemplate\", \"label\": \"\", \"pv\": \"FileTemplate\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"FileTemplate_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"AutoSave\", \"label\": \"\", \"pv\": \"AutoSave\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"AutoSave_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"WriteFile\", \"label\": \"\", \"pv\": \"WriteFile\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"WriteFile_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"ReadFile\", \"label\": \"\", \"pv\": \"ReadFile\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"ReadFile_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"FileFormat\", \"label\": \"\", \"pv\": \"FileFormat\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"FileFormat_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"FileWriteMode\", \"label\": \"\", \"pv\": \"FileWriteMode\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"FileWriteMode_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"Capture\", \"label\": \"\", \"pv\": \"Capture\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"Capture_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"NumCapture\", \"label\": \"\", \"pv\": \"NumCapture\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"NumCapture_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"DeleteDriverFile\", \"label\": \"\", \"pv\": \"DeleteDriverFile\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"DeleteDriverFile_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"LazyOpen\", \"label\": \"\", \"pv\": \"LazyOpen\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"LazyOpen_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"TempSuffix\", \"label\": \"\", \"pv\": \"TempSuffix\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"TempSuffix_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"ReadStatus\", \"label\": \"\", \"pv\": \"ReadStatus\", \"widget\": {\"type\": \"CheckBox\"}}, {\"type\": \"SignalR\", \"name\": \"MaxSizeX\", \"label\": \"\", \"pv\": \"MaxSizeX_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"MaxSizeY\", \"label\": \"\", \"pv\": \"MaxSizeY_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"TimeRemaining\", \"label\": \"\", \"pv\": \"TimeRemaining_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"NumExposuresCounter\", \"label\": \"\", \"pv\": \"NumExposuresCounter_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"NumImagesCounter\", \"label\": \"\", \"pv\": \"NumImagesCounter_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"DetectorState\", \"label\": \"\", \"pv\": \"DetectorState_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"StatusMessage\", \"label\": \"\", \"pv\": \"StatusMessage_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"StringToServer\", \"label\": \"\", \"pv\": \"StringToServer_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"StringFromServer\", \"label\": \"\", \"pv\": \"StringFromServer_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ShutterStatus\", \"label\": \"\", \"pv\": \"ShutterStatus_RBV\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"ShutterControlEPICS\", \"label\": \"\", \"pv\": \"ShutterControlEPICS\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"TemperatureActual\", \"label\": \"\", \"pv\": \"TemperatureActual\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"BinX\", \"label\": \"\", \"pv\": \"BinX\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"BinX_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"BinY\", \"label\": \"\", \"pv\": \"BinY\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"BinY_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"MinX\", \"label\": \"\", \"pv\": \"MinX\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"MinX_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"MinY\", \"label\": \"\", \"pv\": \"MinY\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"MinY_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"SizeX\", \"label\": \"\", \"pv\": \"SizeX\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"SizeX_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"SizeY\", \"label\": \"\", \"pv\": \"SizeY\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"SizeY_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ReverseX\", \"label\": \"\", \"pv\": \"ReverseX\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"ReverseX_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"ReverseY\", \"label\": \"\", \"pv\": \"ReverseY\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"ReverseY_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"AcquireTime\", \"label\": \"\", \"pv\": \"AcquireTime\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"AcquireTime_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"AcquirePeriod\", \"label\": \"\", \"pv\": \"AcquirePeriod\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"AcquirePeriod_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"Gain\", \"label\": \"\", \"pv\": \"Gain\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"Gain_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"FrameType\", \"label\": \"\", \"pv\": \"FrameType\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"FrameType_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ImageMode\", \"label\": \"\", \"pv\": \"ImageMode\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"ImageMode_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"TriggerMode\", \"label\": \"\", \"pv\": \"TriggerMode\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"TriggerMode_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"NumExposures\", \"label\": \"\", \"pv\": \"NumExposures\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"NumExposures_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"NumImages\", \"label\": \"\", \"pv\": \"NumImages\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"NumImages_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ShutterMode\", \"label\": \"\", \"pv\": \"ShutterMode\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"ShutterMode_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ShutterControl\", \"label\": \"\", \"pv\": \"ShutterControl\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"ShutterControl_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"ShutterOpenDelay\", \"label\": \"\", \"pv\": \"ShutterOpenDelay\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"ShutterOpenDelay_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ShutterCloseDelay\", \"label\": \"\", \"pv\": \"ShutterCloseDelay\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"ShutterCloseDelay_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"Temperature\", \"label\": \"\", \"pv\": \"Temperature\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"Temperature_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"ResetPower\", \"label\": \"\", \"pv\": \"ResetPower\", \"widget\": {\"type\": \"CheckBox\"}}, {\"type\": \"SignalW\", \"name\": \"ThresholdApply\", \"label\": \"\", \"pv\": \"ThresholdApply\", \"widget\": {\"type\": \"CheckBox\"}}, {\"type\": \"SignalW\", \"name\": \"ImageFileTmot\", \"label\": \"\", \"pv\": \"ImageFileTmot\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Wavelength\", \"label\": \"\", \"pv\": \"Wavelength\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"EnergyLow\", \"label\": \"\", \"pv\": \"EnergyLow\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"EnergyHigh\", \"label\": \"\", \"pv\": \"EnergyHigh\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"DetDist\", \"label\": \"\", \"pv\": \"DetDist\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"DetVOffset\", \"label\": \"\", \"pv\": \"DetVOffset\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"BeamX\", \"label\": \"\", \"pv\": \"BeamX\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"BeamY\", \"label\": \"\", \"pv\": \"BeamY\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Flux\", \"label\": \"\", \"pv\": \"Flux\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"FilterTransm\", \"label\": \"\", \"pv\": \"FilterTransm\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"StartAngle\", \"label\": \"\", \"pv\": \"StartAngle\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"AngleIncr\", \"label\": \"\", \"pv\": \"AngleIncr\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Det2theta\", \"label\": \"\", \"pv\": \"Det2theta\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Polarization\", \"label\": \"\", \"pv\": \"Polarization\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Alpha\", \"label\": \"\", \"pv\": \"Alpha\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Kappa\", \"label\": \"\", \"pv\": \"Kappa\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Phi\", \"label\": \"\", \"pv\": \"Phi\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"PhiIncr\", \"label\": \"\", \"pv\": \"PhiIncr\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Chi\", \"label\": \"\", \"pv\": \"Chi\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"ChiIncr\", \"label\": \"\", \"pv\": \"ChiIncr\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"Omega\", \"label\": \"\", \"pv\": \"Omega\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"OmegaIncr\", \"label\": \"\", \"pv\": \"OmegaIncr\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"OscillAxis\", \"label\": \"\", \"pv\": \"OscillAxis\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"NumOscill\", \"label\": \"\", \"pv\": \"NumOscill\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"BadPixelFile\", \"label\": \"\", \"pv\": \"BadPixelFile\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"FlatFieldFile\", \"label\": \"\", \"pv\": \"FlatFieldFile\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"CbfTemplateFile\", \"label\": \"\", \"pv\": \"CbfTemplateFile\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalW\", \"name\": \"HeaderString\", \"label\": \"\", \"pv\": \"HeaderString\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Armed\", \"label\": \"\", \"pv\": \"Armed\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"NumBadPixels\", \"label\": \"\", \"pv\": \"NumBadPixels\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"FlatFieldValid\", \"label\": \"\", \"pv\": \"FlatFieldValid\", \"widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalR\", \"name\": \"PixelCutOff\", \"label\": \"\", \"pv\": \"PixelCutOff_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Temp0\", \"label\": \"\", \"pv\": \"Temp0_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Temp1\", \"label\": \"\", \"pv\": \"Temp1_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Temp2\", \"label\": \"\", \"pv\": \"Temp2_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Humid0\", \"label\": \"\", \"pv\": \"Humid0_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Humid1\", \"label\": \"\", \"pv\": \"Humid1_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"Humid2\", \"label\": \"\", \"pv\": \"Humid2_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"TVXVersion\", \"label\": \"\", \"pv\": \"TVXVersion_RBV\", \"widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ResetPowerTime\", \"label\": \"\", \"pv\": \"ResetPowerTime\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"ResetPowerTime_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"DelayTime\", \"label\": \"\", \"pv\": \"DelayTime\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"DelayTime_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ThresholdEnergy\", \"label\": \"\", \"pv\": \"ThresholdEnergy\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"ThresholdEnergy_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"ThresholdAutoApply\", \"label\": \"\", \"pv\": \"ThresholdAutoApply\", \"widget\": {\"type\": \"CheckBox\"}, \"read_pv\": \"ThresholdAutoApply_RBV\", \"read_widget\": {\"type\": \"LED\"}}, {\"type\": \"SignalRW\", \"name\": \"Energy\", \"label\": \"\", \"pv\": \"Energy\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"Energy_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"MinFlatField\", \"label\": \"\", \"pv\": \"MinFlatField\", \"widget\": {\"type\": \"TextWrite\", \"lines\": 1}, \"read_pv\": \"MinFlatField_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalRW\", \"name\": \"GapFill\", \"label\": \"\", \"pv\": \"GapFill\", \"widget\": {\"type\": \"ComboBox\", \"choices\": []}, \"read_pv\": \"GapFill_RBV\", \"read_widget\": {\"type\": \"TextRead\", \"lines\": 1}}, {\"type\": \"SignalR\", \"name\": \"ProgressBarTest\", \"label\": \"\", \"pv\": \"ProgressBarTest_RBV\", \"widget\": {\"type\": \"ProgressBar\"}}]}]}";
class pilatusDetectorParamSet : public virtual ADDriverParamSet {
public:
pilatusDetectorParamSet() {
this->add(PilatusResetPowerString, asynParamInt32, &PilatusResetPower);
this->add(PilatusThresholdApplyString, asynParamInt32, &PilatusThresholdApply);
this->add(PilatusImageFileTmotString, asynParamFloat64, &PilatusImageFileTmot);
this->add(PilatusWavelengthString, asynParamFloat64, &PilatusWavelength);
this->add(PilatusEnergyLowString, asynParamFloat64, &PilatusEnergyLow);
this->add(PilatusEnergyHighString, asynParamFloat64, &PilatusEnergyHigh);
this->add(PilatusDetDistString, asynParamFloat64, &PilatusDetDist);
this->add(PilatusDetVOffsetString, asynParamFloat64, &PilatusDetVOffset);
this->add(PilatusBeamXString, asynParamFloat64, &PilatusBeamX);
this->add(PilatusBeamYString, asynParamFloat64, &PilatusBeamY);
this->add(PilatusFluxString, asynParamFloat64, &PilatusFlux);
this->add(PilatusFilterTransmString, asynParamFloat64, &PilatusFilterTransm);
this->add(PilatusStartAngleString, asynParamFloat64, &PilatusStartAngle);
this->add(PilatusAngleIncrString, asynParamFloat64, &PilatusAngleIncr);
this->add(PilatusDet2thetaString, asynParamFloat64, &PilatusDet2theta);
this->add(PilatusPolarizationString, asynParamFloat64, &PilatusPolarization);
this->add(PilatusAlphaString, asynParamFloat64, &PilatusAlpha);
this->add(PilatusKappaString, asynParamFloat64, &PilatusKappa);
this->add(PilatusPhiString, asynParamFloat64, &PilatusPhi);
this->add(PilatusPhiIncrString, asynParamFloat64, &PilatusPhiIncr);
this->add(PilatusChiString, asynParamFloat64, &PilatusChi);
this->add(PilatusChiIncrString, asynParamFloat64, &PilatusChiIncr);
this->add(PilatusOmegaString, asynParamFloat64, &PilatusOmega);
this->add(PilatusOmegaIncrString, asynParamFloat64, &PilatusOmegaIncr);
this->add(PilatusOscillAxisString, asynParamOctet, &PilatusOscillAxis);
this->add(PilatusNumOscillString, asynParamInt32, &PilatusNumOscill);
this->add(PilatusBadPixelFileString, asynParamOctet, &PilatusBadPixelFile);
this->add(PilatusFlatFieldFileString, asynParamOctet, &PilatusFlatFieldFile);
this->add(PilatusCbfTemplateFileString, asynParamOctet, &PilatusCbfTemplateFile);
this->add(PilatusHeaderStringString, asynParamOctet, &PilatusHeaderString);
this->add(PilatusArmedString, asynParamInt32, &PilatusArmed);
this->add(PilatusNumBadPixelsString, asynParamInt32, &PilatusNumBadPixels);
this->add(PilatusFlatFieldValidString, asynParamInt32, &PilatusFlatFieldValid);
this->add(PilatusPixelCutOffString, asynParamInt32, &PilatusPixelCutOff);
this->add(PilatusThTemp0String, asynParamFloat64, &PilatusThTemp0);
this->add(PilatusThTemp1String, asynParamFloat64, &PilatusThTemp1);
this->add(PilatusThTemp2String, asynParamFloat64, &PilatusThTemp2);
this->add(PilatusThHumid0String, asynParamFloat64, &PilatusThHumid0);
this->add(PilatusThHumid1String, asynParamFloat64, &PilatusThHumid1);
this->add(PilatusThHumid2String, asynParamFloat64, &PilatusThHumid2);
this->add(PilatusTvxVersionString, asynParamOctet, &PilatusTvxVersion);
this->add(PilatusResetPowerTimeString, asynParamInt32, &PilatusResetPowerTime);
this->add(PilatusDelayTimeString, asynParamFloat64, &PilatusDelayTime);
this->add(PilatusThresholdString, asynParamFloat64, &PilatusThreshold);
this->add(PilatusThresholdAutoApplyString, asynParamInt32, &PilatusThresholdAutoApply);
this->add(PilatusEnergyString, asynParamFloat64, &PilatusEnergy);
this->add(PilatusMinFlatFieldString, asynParamInt32, &PilatusMinFlatField);
this->add(PilatusGapFillString, asynParamInt32, &PilatusGapFill);
this->add(ProgressBarTestString, asynParamFloat64, &ProgressBarTest);
this->paramTree = pilatusParamTree;
}
int PilatusResetPower;
#define FIRST_PILATUSDETECTORPARAMSET_PARAM PilatusResetPower
int PilatusThresholdApply;
int PilatusImageFileTmot;
int PilatusWavelength;
int PilatusEnergyLow;
int PilatusEnergyHigh;
int PilatusDetDist;
int PilatusDetVOffset;
int PilatusBeamX;
int PilatusBeamY;
int PilatusFlux;
int PilatusFilterTransm;
int PilatusStartAngle;
int PilatusAngleIncr;
int PilatusDet2theta;
int PilatusPolarization;
int PilatusAlpha;
int PilatusKappa;
int PilatusPhi;
int PilatusPhiIncr;
int PilatusChi;
int PilatusChiIncr;
int PilatusOmega;
int PilatusOmegaIncr;
int PilatusOscillAxis;
int PilatusNumOscill;
int PilatusBadPixelFile;
int PilatusFlatFieldFile;
int PilatusCbfTemplateFile;
int PilatusHeaderString;
int PilatusArmed;
int PilatusNumBadPixels;
int PilatusFlatFieldValid;
int PilatusPixelCutOff;
int PilatusThTemp0;
int PilatusThTemp1;
int PilatusThTemp2;
int PilatusThHumid0;
int PilatusThHumid1;
int PilatusThHumid2;
int PilatusTvxVersion;
int PilatusResetPowerTime;
int PilatusDelayTime;
int PilatusThreshold;
int PilatusThresholdAutoApply;
int PilatusEnergy;
int PilatusMinFlatField;
int PilatusGapFill;
int ProgressBarTest;
};
#endif // PilatusDetectorParamSet_H
The existing pilatus.cpp is then modified to remove these parameters definitions and use the param set API.
Database Template File#
According to the demand and readback properties of the component, the following records are created:
# This file was automatically generated
# *** Please do not edit this file: edit the source file instead. ***
# Group: ComponentGroupOne
record(bo, "$(P)$(R)ResetPower")
{
field(DESC, "ResetPower")
field(DTYP, "asynInt32")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))RESET_POWER")
field(ZNAM, "Done")
field(ONAM, "Reset")
}
record(busy, "$(P)$(R)ThresholdApply")
{
field(DESC, "ThresholdApply")
field(PINI, "YES")
field(DTYP, "asynInt32")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))THRESHOLD_APPLY")
field(ONAM, "Apply")
}
record(ao, "$(P)$(R)ImageFileTmot")
{
field(DESC, "Timeout for image file")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "20")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))IMAGE_FILE_TMOT")
field(PREC, "3")
field(EGU, "s")
}
record(ao, "$(P)$(R)Wavelength")
{
field(DESC, "Wavelength")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "1.54")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))WAVELENGTH")
field(PREC, "4")
field(EGU, "Angstroms")
}
record(ao, "$(P)$(R)EnergyLow")
{
field(DESC, "EnergyLow")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ENERGY_LOW")
field(PREC, "3")
field(EGU, "eV")
}
record(ao, "$(P)$(R)EnergyHigh")
{
field(DESC, "EnergyHigh")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ENERGY_HIGH")
field(PREC, "3")
field(EGU, "eV")
}
record(ao, "$(P)$(R)DetDist")
{
field(DESC, "DetDist")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "1000")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DET_DIST")
field(PREC, "3")
field(EGU, "mm")
}
record(ao, "$(P)$(R)DetVOffset")
{
field(DESC, "DetVOffset")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DET_VOFFSET")
field(PREC, "3")
field(EGU, "mm")
}
record(ao, "$(P)$(R)BeamX")
{
field(DESC, "BeamX")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))BEAM_X")
field(PREC, "3")
field(EGU, "pixels")
}
record(ao, "$(P)$(R)BeamY")
{
field(DESC, "BeamY")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))BEAM_Y")
field(PREC, "3")
field(EGU, "pixels")
}
record(ao, "$(P)$(R)Flux")
{
field(DESC, "Flux")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))FLUX")
field(PREC, "4")
field(EGU, "ph/s")
}
record(ao, "$(P)$(R)FilterTransm")
{
field(DESC, "FilterTransm")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "1.0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))FILTER_TRANSM")
field(PREC, "4")
}
record(ao, "$(P)$(R)StartAngle")
{
field(DESC, "StartAngle")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))START_ANGLE")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)AngleIncr")
{
field(DESC, "AngleIncr")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0.1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ANGLE_INCR")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)Det2theta")
{
field(DESC, "Det2theta")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DET_2THETA")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)Polarization")
{
field(DESC, "Polarization")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0.99")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))POLARIZATION")
field(PREC, "4")
}
record(ao, "$(P)$(R)Alpha")
{
field(DESC, "Alpha")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ALPHA")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)Kappa")
{
field(DESC, "Kappa")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))KAPPA")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)Phi")
{
field(DESC, "Phi")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PHI")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)PhiIncr")
{
field(DESC, "PhiIncr")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0.1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PHI_INCR")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)Chi")
{
field(DESC, "Chi")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))CHI")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)ChiIncr")
{
field(DESC, "ChiIncr")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0.1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))CHI_INCR")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)Omega")
{
field(DESC, "Omega")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))OMEGA")
field(PREC, "4")
field(EGU, "deg")
}
record(ao, "$(P)$(R)OmegaIncr")
{
field(DESC, "OmegaIncr")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0.1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))OMEGA_INCR")
field(PREC, "4")
field(EGU, "deg")
}
record(stringout, "$(P)$(R)OscillAxis")
{
field(DESC, "OscillAxis")
field(PINI, "YES")
field(DTYP, "asynOctetWrite")
field(VAL, "X, CW")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))OSCILL_AXIS")
}
record(longout, "$(P)$(R)NumOscill")
{
field(DESC, "NumOscill")
field(PINI, "YES")
field(DTYP, "asynInt32")
field(VAL, "1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))NUM_OSCILL")
}
record(waveform, "$(P)$(R)BadPixelFile")
{
field(DESC, "BadPixelFile")
field(DTYP, "asynOctetWrite")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))BAD_PIXEL_FILE")
field(NELM, "256")
field(FTVL, "CHAR")
}
record(waveform, "$(P)$(R)FlatFieldFile")
{
field(DESC, "FlatFieldFile")
field(DTYP, "asynOctetWrite")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))FLAT_FIELD_FILE")
field(NELM, "256")
field(FTVL, "CHAR")
}
record(waveform, "$(P)$(R)CbfTemplateFile")
{
field(DESC, "CbfTemplateFile")
field(DTYP, "asynOctetWrite")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))CBFTEMPLATEFILE")
field(NELM, "256")
field(FTVL, "CHAR")
}
record(waveform, "$(P)$(R)HeaderString")
{
field(DESC, "HeaderString")
field(DTYP, "asynOctetWrite")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))HEADERSTRING")
field(NELM, "68")
field(FTVL, "CHAR")
}
record(bi, "$(P)$(R)Armed")
{
field(DESC, "Armed")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ARMED")
field(ZNAM, "Unarmed")
field(ONAM, "Armed")
}
record(longin, "$(P)$(R)NumBadPixels")
{
field(DESC, "Number of bad pixels")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))NUM_BAD_PIXELS")
}
record(bi, "$(P)$(R)FlatFieldValid")
{
field(DESC, "Flat field valid")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))FLAT_FIELD_VALID")
field(ZNAM, "No")
field(ONAM, "Yes")
}
record(ai, "$(P)$(R)PixelCutOff_RBV")
{
field(DESC, "PixelCutOff_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PIXEL_CUTOFF")
field(EGU, "counts")
}
record(ai, "$(P)$(R)Temp0_RBV")
{
field(DESC, "Temp0_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TH_TEMP_0")
field(PREC, "1")
field(EGU, "C")
}
record(ai, "$(P)$(R)Temp1_RBV")
{
field(DESC, "Temp1_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TH_TEMP_1")
field(PREC, "1")
field(EGU, "C")
}
record(ai, "$(P)$(R)Temp2_RBV")
{
field(DESC, "Temp2_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TH_TEMP_2")
field(PREC, "1")
field(EGU, "C")
}
record(ai, "$(P)$(R)Humid0_RBV")
{
field(DESC, "Humid0_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TH_HUMID_0")
field(PREC, "1")
field(EGU, "%")
}
record(ai, "$(P)$(R)Humid1_RBV")
{
field(DESC, "Humid1_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TH_HUMID_1")
field(PREC, "1")
field(EGU, "%")
}
record(ai, "$(P)$(R)Humid2_RBV")
{
field(DESC, "Humid2_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TH_HUMID_2")
field(PREC, "1")
field(EGU, "%")
}
record(stringin, "$(P)$(R)TVXVersion_RBV")
{
field(DESC, "TVXVersion_RBV")
field(SCAN, "I/O Intr")
field(DTYP, "asynOctetRead")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TVXVERSION")
}
record(longin, "$(P)$(R)ResetPowerTime_RBV")
{
field(DESC, "Reset module power wait time")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))RESET_POWER_TIME")
field(EGU, "Seconds")
}
record(longout, "$(P)$(R)ResetPowerTime")
{
field(DESC, "Reset module power wait time")
field(PINI, "YES")
field(DTYP, "asynInt32")
field(VAL, "1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))RESET_POWER_TIME")
field(EGU, "Seconds")
}
record(ai, "$(P)$(R)DelayTime_RBV")
{
field(DESC, "DelayTime")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DELAY_TIME")
field(PREC, "6")
field(EGU, "s")
}
record(ao, "$(P)$(R)DelayTime")
{
field(DESC, "DelayTime")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DELAY_TIME")
field(PREC, "6")
field(EGU, "s")
}
record(ai, "$(P)$(R)ThresholdEnergy_RBV")
{
field(DESC, "Energy threshold")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))THRESHOLD")
field(PREC, "3")
field(EGU, "keV")
}
record(ao, "$(P)$(R)ThresholdEnergy")
{
field(DESC, "Energy threshold")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "10.000")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))THRESHOLD")
field(PREC, "3")
field(EGU, "keV")
}
record(bi, "$(P)$(R)ThresholdAutoApply_RBV")
{
field(DESC, "ThresholdAutoApply")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))THRESHOLD_AUTO_APPLY")
field(ZNAM, "No")
field(ONAM, "Yes")
}
record(bo, "$(P)$(R)ThresholdAutoApply")
{
field(DESC, "ThresholdAutoApply")
field(PINI, "YES")
field(DTYP, "asynInt32")
field(VAL, "1")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))THRESHOLD_AUTO_APPLY")
field(ZNAM, "No")
field(ONAM, "Yes")
}
record(ai, "$(P)$(R)Energy_RBV")
{
field(DESC, "X-ray Energy")
field(SCAN, "I/O Intr")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ENERGY")
field(PREC, "3")
field(EGU, "keV")
}
record(ao, "$(P)$(R)Energy")
{
field(DESC, "X-ray Energy")
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(VAL, "20.000")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))ENERGY")
field(PREC, "3")
field(EGU, "keV")
}
record(longin, "$(P)$(R)MinFlatField_RBV")
{
field(DESC, "Minimum flat field value")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))MIN_FLAT_FIELD")
field(EGU, "Counts")
}
record(longout, "$(P)$(R)MinFlatField")
{
field(DESC, "Minimum flat field value")
field(PINI, "YES")
field(DTYP, "asynInt32")
field(VAL, "100")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))MIN_FLAT_FIELD")
field(EGU, "Counts")
}
record(mbbi, "$(P)$(R)GapFill_RBV")
{
field(DESC, "GapFill")
field(SCAN, "I/O Intr")
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))GAP_FILL")
field(ZRVL, "2")
field(ONVL, "0")
field(TWVL, "-1")
field(ZRST, "N.A.")
field(ONST, "0")
field(TWST, "-1")
}
record(mbbo, "$(P)$(R)GapFill")
{
field(DESC, "GapFill")
field(PINI, "YES")
field(DTYP, "asynInt32")
field(VAL, "0")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))GAP_FILL")
field(ZRVL, "2")
field(ONVL, "0")
field(TWVL, "-1")
field(ZRST, "N.A.")
field(ONST, "0")
field(TWST, "-1")
}
record(ai, "$(P)$(R)ProgressBarTest_RBV")
{
field(DESC, "ProgressBar")
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROGRESS")
field(PREC, "4")
field(EGU, "deg")
}
The top level pilatus.template includes this file, as well as records that provide logic (for things like the arrayRate and EPICSShutter in areaDetector).
UI#
Finally, UI elements can be generated for each component for multiple graphical applications. For example, the following EDM screen is generated:
This can serve as a low level overview of the entire system, as well as a convenient pallette for constructing higher level, more structured screens.
Ongoing Development#
Once a module is working with PVI (either an existing module after the YAML is created from the templates using the one time generation script, or a newly written module) it will then be necessary to update the YAML file in future development. Here is an example of necessary changes to add a new parameter, with and without PVI:
With PVI#
Update YAML file:
- type: AsynFloat64
name: DelayTime
description: Delay in seconds between the external trigger and the start of image acquisition
role: Setting
initial: 0
record_fields:
PREC: 3
EGU: s
And then run pvi (or possibly just make, if it is integrated into a Makefile). It can then be shared with other sites who can generate their own required files.
Without PVI#
Update template:
# Delay time in External Trigger mode.
record(ao, "$(P)$(R)DelayTime")
{
field(PINI, "YES")
field(DTYP, "asynFloat64")
field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DELAY_TIME")
field(EGU, "s")
field(VAL, "0")
field(PREC, "6")
}
record(ai, "$(P)$(R)DelayTime_RBV")
{
field(DTYP, "asynFloat64")
field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))DELAY_TIME")
field(EGU, "s")
field(PREC, "6")
field(SCAN, "I/O Intr")
}
Update header file:
...
#define PilatusDelayTimeString "DELAY_TIME"
...
createParam(PilatusDelayTimeString, asynParamFloat64, &PilatusDelayTime);
...
int PilatusDelayTime;
...
Update docs:
* - Delay in seconds between the external trigger and the start of image acquisition
- DELAY_TIME
- $(P)$(R)DelayTime
- ao
Update screens (of course, this will actually involve editing with a graphical interface):
"text update" {
object {
x=604
y=146
width=80
height=18
}
monitor {
chan="$(P)$(R)DelayTime_RBV"
clr=54
bclr=4
}
align="horiz. centered"
limits {
}
}
"text entry" {
object {
x=540
y=145
width=59
height=20
}
control {
chan="$(P)$(R)DelayTime"
clr=14
bclr=51
}
limits {
}
}
text {
object {
x=435
y=145
width=100
height=20
}
"basic attribute" {
clr=14
}
textix="Delay time"
align="horiz. right"
}
Then either add equivalent changes to other screen types or use autoconvert, if available, and add any site specific details to any of these files (such as autosave and archiver tags).
Class Hierarchy#
Drivers will access their parameters via a param set, either using inheritance or
composition. The class hierarchy for param sets mirrors the drivers. Each of the ‘base’
classes (classes not instantiated directly) has-a paramSet containing its parameters in
addition to its parent class(es). The most derived classes inherit their param sets
so that they have direct access to all parameter indexes (and so that the source code
does not have to change to insert paramSet->
to access them).
There is a new method asynPortDriver::createParams
that iterates the member vector
of asynParamSet
storing parameter definitions and calls
asynPortDriver::createParam
(no ‘s’) on each of them. If the vector is empty
(i.e. if it only has the default asynParamSet
and not a specific implementation)
it has no effect. This means asynPortDriver
can be inherited from as before with
no change.
Virtual inheritance is required for two reasons. Primarily, it ensures only a single
instance of asynParamSet
is created and it is shared throughout the class
hierarchy to ensure asynPortDriver can find the child parameters. It also means that
the most derived class must call the constructors for all virtual base classes before
the non-virtual base classes. This means the constructors are called in the correct
order such that when the asynPortDriver constructor the asynParamSet
parameterDefinitions
is fully populated when createParams
is called.
Change Summary#
asyn : - Created
asynParamSet
New overloaded asynPortDriver constructor that takes an
asynParamSet*
and calls createParams()ADCore : -
asynNDArrayDriver
parameters split intoasynNDArrayDriverParamSet
: Constructor updated to take anasynNDArrayDriverParamSet*
. Updated to access parameters viaparamSet->
ADDriver
parameters split intoADDriverParamSet
: Constructor updated to take anADDriverParamSet*
. Updated to access parameters viaparamSet->
NDPluginDriver
inheritsasynNDArrayDriverParamSet
in addition toasynNDArrayDriver
: Updated to access parameters viaparamSet->
. Child classes work with no changesSome trivial updates to the tests
ADSimDetector : -
simDetector
parameters split intosimDetectorParamSet
simDetector
inherits fromsimDetectorParamSet
in addition toADDriver
Can access parameters as before
ADPilatus : - Equivalent to ADSimDetector changes
motor : -
asynMotorController
parameters split intoasynMotorControllerParamSet
Updated to access parameters via
paramSet->
pmac : -
pmacController
parameters split intopmacControllerParamSet
pmacCSController
sameEach inherit from their own param set (which inherits
asynMotorControllerParamSet
) in addition toasynMotorController
Can access parameters as before
Caveats#
There are some changes that are unavoidable without inserting edge cases into the generation logic and making the YAML schema more complicated. Some examples are:
The first param index used for calling base class methods is inconsistently named, so we will have to agree a consistent way to generate them and make them the same.
Any readback parameters will have an _RBV suffix added. Some existing readbacks do not have this, e.g. Armed in pilatusDetector.
FIRST_DRIVER_PARAM needs to be defined in the main header file based on the FIRST_DRIVER_PARAM_INDEX defined in the param set header file, appending
paramSet->
or not depending on whether it inherits the param set or not. (This could possibly be handled in a better way by adding more logic to theasynParamSet
- see [Possible Further Work])Asyn parameter names will be the same as the name of the index variable. The value can be overridden to define drvInfo for drvUserCreate dynamic parameters.
Next Steps#
A script is in development to perform the generation of an initial YAML file from a template. The idea being that after this point, everything is generated from the YAML file and any changes are made there and everything regenerated. New drivers can use a YAML file from the start.
The current hierarchy (base classes have-a param set while the most derived class
is-a param set) is inconsistent and confusing, but it has the benefit that people are
not forced to change drivers inheriting from these base classes to access parameters
via paramSet->
, they just need to inherit the parent param set. It also means that
the most derived classes cannot be inherited from alongside an extended param set
(this is not necessarily a problem, but it seems like an unnecessary restriction).
It would be clearer to remove this and require all child classes to use the param set
explicitly, removing the need for virtual inheritance. This would just need an addition
to the extern C calls to create the param set and pass it into the constructor of the
driver. Another option is to create a class that inherits from the driver and the param
set, with no additional logic. This could then instantiate the param set and pass it to
the driver constructor. Either solution would resolve caveat 3, because all classes
will access FIRST_DRIVER_PARAM via paramSet->
.
Possible Further Work#
Adopting this framework could make it easier to make other improvements to the C++ code, such as:
Move some asynPortDriver functionality into
asynParamSet
/asynParam
(See ADEiger eigerParam) : - Reduce the size ofasynPortDriver
Possibility of typed subclasses of
asynParam
to reduce if statements for handling the manyasynParamType
values in slightly different waysSimplify the sharing of file writing functionality between some drivers : - ADPilatus and NDPluginFile-derived classes - Parameters could be split out of
asynNDArrayDriver
into aFileWriterParamSet
, which could then be included via composition only where required, rather than every driver and plugin underasynNDArrayDriver
having these parameters.