Scan Client¶
This example shows how to connect to the scan server, submit a scan, and monitor its progress using the basic API, without using site-specific settings or abstractions like the table-based scan.
Example¶
import time
from scan import *
client = ScanClient('localhost')
print(client)
print(client.serverInfo())
# Assemble commands for a scan
# Much more on that later...
cmds = [ Comment('Hello'), Set('motor_x', 10) ]
# Optionally, request a simulation that shows
# how 'Include' and 'Loop' commands get expanded.
info = client.simulate(cmds)
print(info['simulation'])
# Submit scan for execution
id = client.submit(cmds, 'My First Scan')
print(id)
# Fetch information about scan
info = client.scanInfo(id)
print(info)
# Could poll scanInfo until info.isDone().
# Shortcut:
info = client.waitUntilDone(id)
print(info)
# A submitted scan can be paused..
id = client.submit([ Delay(5) ], 'Not sure about this one')
client.pause(id)
print(client.scanInfo(id))
client.resume(id)
print(client.scanInfo(id))
# .. or even aborted & deleted
client.abort(id)
print(client.scanInfo(id))
print("Before deleting scan %d:" % id)
for info in client.scanInfos():
print(info)
client.delete(id)
print("After deleting scan %d:" % id)
for info in client.scanInfos():
print(info)
# To a limited extend, it is possible to change a running scan:
# Parameters of commands that have not been executed can be adjusted
id = client.submit([ Delay(5), Set('motor_x', 10) ], 'Changing...')
client.pause(id)
# Want to set 'motor_x' to 5 instead of 10
client.patch(id, 1, 'value', 5)
client.resume(id)
client.abort(id)
try:
client.waitUntilDone(id)
except Exception as e:
print("Waiting for an aborted scan will result in an exception: ", e)
try:
# This scan will time out
id = client.submit( [ Wait("motor_x", 60, timeout=1)], "Timeout Test")
client.waitUntilDone(id)
except Exception as e:
print("Waiting for a failed scan will result in an exception: ", e)
# Log data during scan
cmds = [ Loop('motor_x', 1, 10, 1,
[
Set('neutrons', 0),
Loop('motor_y', 1, 3, 1,
[
Delay(1),
Log('motor_y')
]),
Log('motor_x', 'neutrons')
])
]
id = client.submit(cmds, 'Data Demo')
info = client.waitUntilDone(id)
print("Number of log calls: %d" % client.lastSerial(id))
# Fetch data
data = client.getData(id)
# Create table for motor_x and neutrons
table = createTable(data, 'motor_x', 'neutrons')
print("Positions: ", table[0])
print("Counts : ", table[1])
for (pos, count) in zip(*table):
print("Counts at motor position %g: %g" % (pos, count))
# Could plot this with numpy/scipy: plot(table[0], table[1]) etc.
# Remove information for all completed scans
client.clear()
API¶
-
class
scan.client.scanclient.
ScanClient
(host='localhost', port=4810)¶ Client interface to the scan server
- Parameters
host – The IP address or name of scan server host.
port – The TCP port of the scan server.
Example:
>>> client = ScanClient('localhost')
-
abort
(scanID=- 1)¶ Abort a running or paused scan
- Parameters
scanID – ID of scan or -1 to abort current scan
Using PUT {BaseURL}/scan/{id}/abort
Example:
>>> id = client.submit(commands) >>> client.abort(id)
-
clear
()¶ Remove all completed scans.
Using DELETE {BaseURL}/scans/completed
Usage:
>>> client.clear()
-
delete
(scanID)¶ Remove a completed scan.
Using DELETE {BaseURL}/scan/{id}
- Parameters
scanID – The id of scan you want to delete.
Example:
>>> id = client.submit(commands) >>> client.abort(id) >>> client.delete(id)
-
getData
(scanID)¶ Fetch logged data of a scan
- Parameters
scanID – ID of scan
- Returns
Data dictionary
- Example:
>>> data = client.getData(id) >>> print data
Format of the data:
{ 'device1': {'id': [0, 1, 2, 3, 4 ], 'value': [2.0, 3.0, 4.0, 2.0, 4.0], 'time': [1427913270352, 1427913270470, 1427913270528, 1427913270596, 1427913270695] }, 'device2': {'id': [0, 3, 6, 9, 12], 'value': [1.0, 2.0, 3.0, 4.0, 5.0], 'time': [1427913270351, 1427913270595, 1427913270795, 1427913271076, 1427913271393] } }
The data dictionary has one entry per logged device. Its value is again a dictionary with entries
- id:
Sample IDs, starting from 0
- value:
Sample values
- time:
Times in Posix milliseconds
-
lastSerial
(scanID)¶ Get the last log data serial.
Obtains the serial ID of the last logged sample of a scan. Allows clients which monitor the progress of a scan to poll for changes in the logged data without always having to pull the complete data log.
- Parameters
scanID – The ID of scan for which to fetch information.
- Returns
Id of last logged sample of the scan.
Example:
>>> last_log_fetched = -1 >>> while not client.scanInfo(id).isDone: >>> last_logged = client.lastSerial(id) >>> if last_log_fetched != last_logged: >>> # .. fetch logged data, because it has changed.. >>> last_log_fetched = last_logged >>> time.sleep(10
-
patch
(scanID, address, property, value)¶ Update scan on server.
This can be used to update parameters of an existing command in an existing scan on the server.
In case the command had already been executed, the change has no effect.
Using PUT {BaseURL}/scan/{id}/patch
- Parameters
scanID – The id of scan you want to update.
address – Address of the command to update. Counted within the scan starting at 0.
property – The property of the command to update.
value – The new value for that property.
Example:
>>> id = client.submit([ Delay(5), Set('motor_x', 10) ], 'Changing...') >>> client.pause(id) >>> # Want to set 'motor_x' to 5 instead of 10 >>> client.patch(id, 1, 'value', 5) >>> client.resume(id)
-
pause
(scanID=- 1)¶ Pause a running scan
- Parameters
scanID – ID of scan or -1 to pause current scan
Using PUT {BaseURL}/scan/{id}/pause
Example:
>>> id = client.submit(commands) >>> client.pause(id)
-
resume
(scanID=- 1)¶ Resume a paused scan
- Parameters
scanID – ID of scan or -1 to resume current scan
Using PUT {BaseURL}/scan/{id}/resume
Example:
>>> id = client.submit(commands) >>> client.pause(id) >>> client.resume(id)
-
scanCmds
(scanID)¶ Get the commands of scan.
Reads scan commands from scan server. Only possible for scans that are still available on the server, not for older scans that only have logged data but no command detail.
- Parameters
scanID: – The ID of scan for which to fetch information.
- Returns
Scan commands in XML format of a scan.
Example:
>>> client = ScanClient() >>> scanid = client.submit(...someCMDs...) >>> # Submit it again: >>> client.submit(client.scanCmds(scanid))
-
scanDevices
(scanID=- 1)¶ Get list of devices used by scan.
- Parameters
scanID – The ID of scan that is still held in scan server, -1 to fetch default devices.
Provides a list of devices used by a scan. For a running scan, this includes devices accessed in the pre- and post-scan. Also includes devices configured with alias names, but not necessarily used by the scan.
- Returns
XML with info about devices.
-
scanInfo
(scanID, timeout=10)¶ Get information for a scan
Using GET {BaseURL}/scan/{id}
- Parameters
scanID – The ID of scan for which to fetch information.
timeout – Throws exception when no reply within that time in seconds
- Returns
Example:
>>> client = ScanClient() >>> print client.scanInfo(42)
-
scanInfos
(timeout=20)¶ Get information of all scans
Using GET {BaseURL}/scans
- Parameters
timeout – Throws exception when no reply within that time in seconds
- Returns
List of
ScanInfo
Example:
>>> infos = client.scanInfos() >>> print [ str(info) for info in infos ]
-
serverInfo
()¶ Get scan server information
Provides version number, configuration, … of current server
Using GET {BaseURL}/server/info
- Returns
XML with server info
Usage:
>>> client = ScanClient() >>> print client.serverInfo()
-
simulate
(cmds)¶ Submit scan to scan server for simulation
- Parameters
cmds – List of commands,
CommandSequence
or text with raw XML format.- Returns
Simulation result as dictionary { ‘simulation’: “Printable text”, ‘seconds’: 193.0 }
Example:
>>> result = client.simulate([ Set('x', 5), Delay(2) ]) >>> print result['simulation']
-
submit
(cmds, name='UnNamed', queue=True, timeout=0, deadline=None, pre_post=True)¶ Submit scan to scan server for execution
- Parameters
cmds – List of commands,
CommandSequence
or text with raw XML format.name – Name of scan
queue – Submit to scan server queue, or execute as soon as possible?
timeout – Timeout in seconds after which scan will self-abort
deadline – Execution deadline in “yyyy-MM-dd HH:mm:ss” format when scan will self-abort
pre_post – Execute pre- and post-scan commands (default: True)
- Returns
ID of submitted scan
By default, a submitted scan will be queued. One scan is then executed at a time, in order of submission. Each scan is allowed to run until all its commands complete.
The ‘queue’ parameter allows submitting scans for immediate execution, i.e. in parallel to the queued commands.
Either the ‘timeout’ or the ‘deadline’ might be used to limit the execution time.
Examples:
>>> cmds = [ Comment('Hello'), Set('x', 10) ] >>> id = client.submit(cmds, "My First Scan")
>>> cmds = CommandSequence(Comment('Hello')) >>> cmds.append(Set('x', 10)) >>> id = client.submit(cmds, "My Second Scan")
>>> cmds = CommandSequence(Delay(600)) >>> id = client.submit(cmds, "Timeout", timeout=10)
-
waitUntilDone
(scanID)¶ Wait until scan finishes.
On return, the scan has finished successfully. Can also be used for an older scan that has logged data, whereupon this call will return immediately.
In case the scan failed or was aborted, an exception is raised.
If scan information is not available (timeout while requesting it), keep checking.
- Parameters
scanID – ID of scan on which to wait
- Returns
Scan info
- Raises
Exception – If scan was aborted or failed.