Why is something the way it is ============================== .. digraph:: pvi_flowchart bgcolor=transparent rankdir=LR node [fontname=Arial fontsize=10 shape=box style=filled fillcolor="#8BC4E9"] edge [fontname=Arial fontsize=10 arrowhead=vee] { rank=same; "pilatus.pvi.yaml" "pilatus.cpp" "pilatus.h" } PVI [shape=doublecircle] "pilatus.local.yaml" -> PVI "pilatus.pvi.yaml" -> PVI PVI -> "pilatus_parameters.h" PVI -> "pilatus_parameters.template" PVI -> "pilatus_parameters.opi" PVI -> "pilatus_parameters.adl" PVI -> "pilatus_parameters.edl" PVI -> "pilatus_parameters.csv" "pilatus_parameters.template" -> "pilatus.template" [label="included in"] "pilatus_parameters.h" -> "pilatus.h" [label="included in"] "pilatus.cpp" -> "libPilatus.so" "pilatus.h" -> "libPilatus.so" "pilatus_parameters.csv" -> "pilatus.rst" [label="included in"] "pilatus_parameters.adl" -> "pilatus.adl" [label="linked from"] "pilatus_parameters.edl" -> "pilatus.edl" [label="linked from"] "pilatus_parameters.opi" -> "pilatus.opi" [label="linked from"] .. list-table:: Aims of PVI :widths: 20, 80 :header-rows: 1 * - 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: .. list-table:: :widths: 20, 80 :header-rows: 1 * - 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: .. digraph:: pvi_products bgcolor=transparent node [fontname=Arial fontsize=10 shape=box style=filled fillcolor="#8BC4E9"] edge [fontname=Arial fontsize=10 arrowhead=vee] Intermediate [label="[Record(),\n Channel(),\n AsynParameter()]"] Products [label="Template\nScreens\nDriver Params\nDocumentation"] {rank=same; Components -> Producer -> Intermediate -> Formatter -> Products} Here's a cut down pilatus.yaml file that might describe a parameter in a detector: .. literalinclude:: ../../tests/produce_format/input/pilatusDetector.pvi.producer.yaml :language: yaml 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: .. csv-table:: Pilatus Parameters :file: ../../tests/produce_format/output/pilatusParameters.csv :widths: 15, 25, 60 :header-rows: 1 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 .. _YAML: https://en.wikipedia.org/wiki/YAML