Skip to content

Commit 8023bed

Browse files
author
Kay Kasemir (ky9)
committed
Alignment wrapup
1 parent d520e5b commit 8023bed

File tree

5 files changed

+79
-40
lines changed

5 files changed

+79
-40
lines changed

doc/alignment_scan_commands.png

41 KB
Loading

doc/getting_started.rst

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -293,23 +293,23 @@ CS-Studio GUI combined with PyScanClient
293293

294294
End users can assemble recipes for a scan by writing python
295295
scripts similar to the ones shown so far.
296-
In practice, however, it is more likely for experts to prepare such scripts
297-
and end users then simply adjust key parameters and execute the script.
296+
In practice, however, it is more likely for experts to prepare such scripts.
297+
End users then adjust key parameters and execute the script.
298298

299299
For frequently used recipes, a GUI can be added.
300300
Instead of editing a script and executing it in a terminal window,
301301
users can then set parameters and submit a scan from the GUI.
302302

303-
In CS-Studio, use the menu `File`, `Open`` to open `PyScanClient/example/opi/2_XYScan.bob`.
303+
In CS-Studio, use the menu `File`, `Open` to open `PyScanClient/example/opi/2_XYScan.bob`.
304304
In addition to the beam, shutter and X/Y motors that we've already seen,
305305
it adds a "Scan" section. By default, it will scan both motors from 0 to 5,
306-
and at each position await 3 neutrons.
306+
awaiting 3 neutrons at each position.
307307

308308
Press "Go!" and note how the Scan Monitor now shows a running "XY Scan".
309309
Right-click on the scan in the monitor, open the "Scan Data Table"
310-
and watch it add new data for each scanned position.
310+
and watch it grow by a row for each scanned position.
311311
Close the data table and instead open the "Scan Data Plot".
312-
From the "X Axis" drop-down, select "xpos", and from the "Value 1" drop-down select "ypos".
312+
From the "X Axis" drop-down, select "motor_x", and from the "Value 1" drop-down select "motor_y".
313313

314314
.. image:: scan_xy.png
315315

@@ -354,7 +354,7 @@ as in the second row which will create nested loops setting
354354
`motor_x` to 1, 3, 5, while an inner loop will set
355355
`motor_y` to 1, 1.5, 2, ..., 4.5, 5.0.
356356

357-
The triplet "Wait For", "Value" and "Or Time" columns have a special meaning.
357+
The triplet of columns "Wait For", "Value" and "Or Time" has special meaning.
358358
In the first row, after setting the motor positions, we wait for 5 seconds.
359359
In the second, we wait for the proton charge to increment by 1e9,
360360
or move on after 1 minute, whichever comes first.
@@ -364,7 +364,7 @@ Each PV that is used in a table row is logged at the end of each row.
364364

365365
Finally, the list of commands created for a table scan start with `Pre()` commands and end with `Post()`
366366
commands. In the `beamline_setup.py` shown above those are used to open and then close the shutter.
367-
The created list of commands can be seen in the scan editor:
367+
The resulting list of commands can be checked by opening the submitted scan in the scan editor:
368368

369369
.. image:: table_scan_commands.png
370370

@@ -386,7 +386,7 @@ without manual conversion to CSV.
386386
Alignment Scan
387387
--------------
388388

389-
One fairly common beamline procedure is the alignment.
389+
One fairly common beamline procedure is an alignment.
390390
For example, a slit or sample is moved across a range of positions,
391391
the intensity of a signal is noted at each position,
392392
and we try to locate the maximum of that signal.
@@ -395,23 +395,72 @@ In CS-Studio, use the menu `File`, `Open` to open
395395
`PyScanClient/example/opi/1_BeamLine.bob`
396396
and in there set the "Y" motor to 3.0.
397397
Now open `PyScanClient/example/opi/4_Alignment_Scan.bob`.
398-
Adjust the settings as shown the following screenshot, then press "Submit".
398+
Adjust the settings as shown in the following screenshot, then press "Submit".
399+
The GUI submits commands for moving the X motor over a range of positions.
400+
At each step we wait for some time, then log the motor position and some signal.
401+
Finally, a gaussian fit is performed to locate the peak in that signal.
399402

400403
.. image:: alignment_scan.png
401404

402-
TODO
403-
Custom script commands
404-
405-
Production Setup
406-
----------------
405+
When inspecting the submitted commands by opening them from the scan monitor
406+
into the scan editor, the commands for moving the motor and logging
407+
the signal are quite straight forward.
408+
In addition, there are "script" commands.
409+
410+
.. image:: alignment_scan_commands.png
411+
412+
Script commands can invoke jython code within the scan server.
413+
These scripts have access to PVs and to the logged data of a scan.
414+
In this alignment scan, a "WriteDataToPV" script command
415+
is invoked to write data from the logged "motor_x" and the logged "signal"
416+
into waveform PVs. Those waveform PVs are then shown in the display
417+
to track the progress of the scan.
418+
Finally, a "FindPeak" command is used to locate the peak in the logged data
419+
and to publish the result via PVs.
420+
421+
For more on the :class:`.Script` command, check its documentation in the
422+
list of :doc:`scan commands <commands>`.
423+
For implementation details of these specific custom scripts,
424+
look for `writedatatopv.py` and `findpeak.py` in the `PyScanClient/example/server` folder.
425+
426+
Note that this example not only introduces script commands but also stretches
427+
their purpose.
428+
The jython code of a script command has access to most of the scan server.
429+
It can implement functionality that is not offered by the basic scan commands.
430+
This is both an opportunity and a risk. The use of script commands should
431+
remain limited. Each script command needs to be well tested to assert that it
432+
is not impacting the robustness of the scan server.
433+
434+
For this specific example of an alignment scan, a better solution is
435+
the implementation of an alignment IOC.
436+
This may be done in python, using a python channel access or PV access server library.
437+
Such an alignment IOC has PVs similar to those shown in this alignment display
438+
to configure which PVs to "move", how to wait at each step, and what signal
439+
to log. Implementing such an alignment IOC in python opens up access
440+
to many types of peak fitting algorithms.
441+
The alignment IOC should have an option to end with positioning the moved
442+
motor at the peak of the signal.
443+
Finally, the alignment IOC should expose a "Run" PV which supports put-callback.
444+
445+
Such an alignment can then be invoked interactively from a GUI,
446+
but it can also be configured and started from a scan,
447+
for example a table scan which configures the alignment PVs
448+
and then writes to the "Run" PV, using completion.
449+
450+
451+
Production Setup Notes
452+
----------------------
407453

408454
In the above example we executed the scan server within a terminal window.
409455
A production setup would typically run it as a Linux service using `procServ`,
410456
https://github.com/ralphlange/procServ
411457

412458
Both the scan server and the CS-Studio GUI are typically started by a site-specific
413-
launcher script that adds `-settings /path/to/site/settings.ini`.
414-
459+
launcher script that adds `-settings /path/to/my_settings.ini`.
415460

416-
TODO: scan server's pre and post commands
461+
By default, the scan server log is stored in the `/tmp` folder.
462+
In the `scan_config.xml`, it should be configured to be in a more permanent location.
417463

464+
The scan config file can also list "pre" and "post" commands that are always
465+
executed at the start and end of each scan. Specifically, the "post" commands
466+
are executed both when a scan completes successfully and when it fails.

example/opi/scripts/xy_scan.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626

2727
# Create scan
2828
cmds =[
29-
Loop('xpos', min(x0, x1), max(x0, x1), max(0.1, abs(dx)),
30-
Loop('ypos', min(y0, y1), max(y0, y1), toggle * max(0.1, abs(dy)),
29+
Loop('motor_x', min(x0, x1), max(x0, x1), max(0.1, abs(dx)),
30+
Loop('motor_y', min(y0, y1), max(y0, y1), toggle * max(0.1, abs(dy)),
3131
[
3232
Wait('neutrons', neutrons, comparison='increase by'),
33-
Log('xpos', 'ypos', 'readback')
33+
Log('motor_x', 'motor_y', 'readback')
3434
]
3535
)
3636
)

example/server/Readme.txt

Lines changed: 0 additions & 15 deletions
This file was deleted.

scan/commands/script.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,21 @@ class Script(Command):
2222
Scripts must derive from `ScanScript`:
2323
2424
>>> class MyScript(ScanScript):
25-
... def __init__(self, name, offset):
25+
... # Script command that gets logged data for a PV,
26+
... # writes the sum to a '.._sum' PV
27+
... def __init__(self, name):
2628
... self.name = name
27-
... self.offset = offset
2829
...
2930
... def getDeviceNames(self):
30-
... return [ "result1" ]
31+
... # PVs that this command needs
32+
... return [ self.name + "_sum" ]
3133
...
3234
... def run(self, context, args):
3335
... [ x ] = context.getData(self.name)
34-
... context.write(self.name + "_offset", x + offset)
36+
... s = 0
37+
... for v in x:
38+
... s += v
39+
... context.write(self.name + "_sum", s)
3540
3641
For details refer to the Javadoc of the Scan Server.
3742

0 commit comments

Comments
 (0)