This commit is contained in:
gac-x05la
2021-05-20 15:42:59 +02:00
parent 6f30d641d3
commit 2a65e100ea
13 changed files with 1124 additions and 15 deletions

View File

@@ -1,34 +1,45 @@
#Thu Feb 13 11:01:45 CET 2020
autoSaveScanData=true
simulation=false
commandExecutionEvents=false
logDaysToLive=7
userAuthenticator=
logLevelConsole=Off
scanStreamerPort=-1
parallelInitialization=false
versionTrackingManual=true
#Thu May 20 15:37:42 CEST 2021
hostName=null
userManagement=false
instanceName=MicroXAS
disableEmbeddedAttributes=true
autoSaveScanData=true
simulation=false
dataServerPort=-1
serverPort=8080
hideServerMessages=false
versionTrackingEnabled=true
dataPath={data}/{year}_{month}/{date}/{date}{time}_{name}
serverEnabled=false
commandExecutionEvents=false
logDaysToLive=7
dataScanReleaseRecords=false
depthDimension=0
dataScanPreserveTypes=false
dataScanSaveOutput=false
logLevel=Info
dataScanFlushRecords=true
logPath={logs}/{date}_{time}
dataLayout=fda
disableDataFileLogs=false
sessionHandling=On
terminalEnabled=false
notificationLevel=Off
userAuthenticator=
logLevelConsole=Off
terminalPort=3579
scanStreamerPort=-1
dataScanSaveScript=false
dataTransferUser=
dataScanSaveSetpoints=false
notifiedTasks=null
parallelInitialization=false
dataTransferPath=
createSessionFiles=false
saveConsoleSessionFiles=false
versionTrackingLogin={context}/svcusr-hlapp_robot
versionTrackingManual=true
versionTrackingRemote=git@git.psi.ch\:pshell_config/x05la.git
dataProvider=fda
dataTransferMode=Off
saveCommandStatistics=false

11
config/scicat.properties Normal file
View File

@@ -0,0 +1,11 @@
#Thu May 20 14:49:07 CEST 2021
environment=prod
testParameters=-testenv -user slssim\:slssim
sourceFolder=.
prodParameters=\ -user slssim\:slssim
devParameters=-devenv -user slssim\:slssim
ownerGroup=
type=raw
parameters=-ingest -allowexistingsource -noninteractive -autoarchive
creationLocation=/PSI
principalInvestigator=

View File

@@ -0,0 +1,3 @@
#Thu May 20 15:32:22 CEST 2021
Energy=Double
Sample=String

View File

@@ -0,0 +1,3 @@
#Thu May 20 14:45:31 CEST 2021
SessionCounter=1
CurrentSession=1

View File

@@ -1,2 +1,2 @@
#Tue Jul 28 09:52:01 CEST 2020
#Thu May 20 14:45:13 CEST 2021
FdaBrowser=true

View File

@@ -1,13 +1,16 @@
#Thu Feb 13 10:13:17 CET 2020
scriptPath={home}/script
#Wed May 19 14:57:57 CEST 2021
sessionsPath={outp}/sessions
scriptPath={home}/script
pluginsPath={home}/plugins
configFileDevices={config}/devices.properties
consoleSessionsPath={sessions}/console
libraryPath={script}; {script}/Lib
configFilePlugins={config}/plugins.properties
contextPath={outp}/context
extensionsPath={home}/extensions
configPath={home}/config
configFileSessions={config}/sessions.properties
userSessionsPath={sessions}/user
dataPath={outp}/data
devicesPath={home}/devices
configFileVariables={config}/variables.properties

1
config/tasks.properties Normal file
View File

@@ -0,0 +1 @@
Tasks/DetectorsCheck=10.0

View File

@@ -1,2 +1,3 @@
#Thu Feb 27 09:28:05 CET 2020
FileSequentialNumber=20
#Thu May 20 15:37:42 CEST 2021
FileSequentialNumber=24
DaySequentialNumber=0

515
script/Devices/Eiger.py Normal file
View File

@@ -0,0 +1,515 @@
"""
class DEigerClient provides an interface to the EIGER API
Author: Volker Pilipp
Contact: support@dectris.com
Version: 1.0
Date: 13/11/2014
Copyright See General Terms and Conditions (GTC) on http://www.dectris.com
"""
import base64
import os.path
import httplib
import json
import re
import sys
import socket
import fnmatch
Version = '1.6.0'
class DEigerClient(object):
"""
class DEigerClient provides a low level interface to the EIGER API
"""
def __init__(self, host = '127.0.0.1', port = 80, verbose = False, urlPrefix = None, user = None):
"""
Create a client object to talk to the EIGER API.
Args:
host: hostname of the detector computer
port: port usually 80 (http)
verbose: bool value
urlPrefix: String prepended to the urls. Should be None.
user: "username:password". Should be None.
"""
super(DEigerClient,self).__init__()
self._host = host
self._port = port
self._version = Version
self._verbose = verbose
self._urlPrefix = ""
self._user = None
self._connectionTimeout = 900
self._connection = httplib.HTTPConnection(self._host,self._port, timeout = self._connectionTimeout)
self.setUrlPrefix(urlPrefix)
self.setUser(user)
def setVerbose(self,verbose):
""" Switch verbose mode on and off.
Args:
verbose: bool value
"""
self._verbose = bool(verbose)
def setConnectionTimeout(self, timeout):
"""
If DEigerClient has not received an reply from EIGER after
timeout seconds, the request is aborted. timeout should be at
least as long as the triggering command takes.
Args:
timeout timeout in seconds
"""
self._connectionTimeout = timeout
def setUrlPrefix(self, urlPrefix):
"""Set url prefix, which is the string that is prepended to the
urls. There is usually no need to call the command explicitly.
Args:
urlPrefix: String
"""
if urlPrefix is None:
self._urlPrefix = ""
else:
self._urlPrefix = str(urlPrefix)
if len(self._urlPrefix) > 0 and self._urlPrefix[-1] != "/":
self._urlPrefix += "/"
def setUser(self, user):
"""
Set username and password for basic authentication.
There is usually no need to call the command explicitly.
Args:
user: String of the form username:password
"""
if user is None:
self._user = None
else:
self._user = base64.encodestring(user).replace('\n', '')
def version(self,module = 'detector'):
"""Get version of a api module (i.e. 'detector', 'filewriter')
Args:
module: 'detector' or 'filewriter'
"""
return self._getRequest(url = '/{0}{1}/api/version/'.format(self._urlPrefix,module))
def listDetectorConfigParams(self):
"""Get list of all detector configuration parameters (param arg of configuration() and setConfiguration()).
Convenience function, that does detectorConfig(param = 'keys')
Returns:
List of parameters.
"""
return self.detectorConfig('keys')
def detectorConfig(self,param = None, dataType = None):
"""Get detector configuration parameter
Args:
param: query the configuration parameter param, if None get full configuration, if 'keys' get all configuration parameters.
dataType: None (= 'native'), 'native' ( return native python object) or 'tif' (return tif data).
Returns:
If param is None get configuration, if param is 'keys' return list of all parameters, else return the value of
the parameter. If dataType is 'native' a dictionary is returned that may contain the keys: value, min, max,
allowed_values, unit, value_type and access_mode. If dataType is 'tif', tiff formated data is returned as a python
string.
"""
return self._getRequest(self._url('detector','config',param),dataType)
def setDetectorConfig(self, param, value, dataType = None):
"""
Set detector configuration parameter param.
Args:
param: Parameter
value: Value to set. If dataType is 'tif' value may be a string containing the tiff data or
a file object pointing to a tiff file.
dataType: None, 'native' or 'tif'. If None, the data type is auto determined. If 'native' value
may be a native python object (e.g. int, float, str), if 'tif' value shell contain a
tif file (python string or file object to tif file).
Returns:
List of changed parameters.
"""
return self._putRequest(self._url('detector','config',param), dataType, value)
def setDetectorConfigMultiple(self,*params):
"""
Convenience function that calls setDetectorConfig(param,value,dataType = None) for
every pair param, value in *params.
Args:
*params: List of successive params of the form param0, value0, param1, value1, ...
The parameters are set in the same order they appear in *params.
Returns:
List of changed parameters.
"""
changeList = []
p = None
for x in params:
if p is None:
p = x
else:
data = x
changeList += self.setDetectorConfig(param = p, value = data, dataType = None)
p = None
return list(set(changeList))
def listDetectorCommands(self):
"""
Get list of all commands that may be sent to Eiger via command().
Returns:
List of commands
"""
return self._getRequest(self._url('detector','command','keys'))
def sendDetectorCommand(self, command, parameter = None):
"""
Send command to Eiger. The list of all available commands is obtained via listCommands().
Args:
command: Detector command
parameter: Call command with parameter. If command = "trigger" a float parameter may be passed
Returns:
The commands 'arm' and 'trigger' return a dictionary containing 'sequence id'.
"""
return self._putRequest(self._url('detector','command',command), dataType = 'native', data = parameter)
def detectorStatus(self, param = 'keys'):
"""Get detector status information
Args:
param: query the status parameter param, if 'keys' get all status parameters.
Returns:
If param is None get configuration, if param is 'keys' return list of all parameters, else return dictionary
that may contain the keys: value, value_type, unit, time, state, critical_limits, critical_values
"""
return self._getRequest(self._url('detector','status',parameter = param))
def fileWriterConfig(self,param = 'keys'):
"""Get filewriter configuration parameter
Args:
param: query the configuration parameter param, if 'keys' get all configuration parameters.
Returns:
If param is None get configuration, if param is 'keys' return list of all parameters, else return dictionary
that may contain the keys: value, min, max, allowed_values, unit, value_type and access_mode
"""
return self._getRequest(self._url('filewriter','config',parameter = param))
def setFileWriterConfig(self,param,value):
"""
Set file writer configuration parameter param.
Args:
param: parameter
value: value to set
Returns:
List of changed parameters.
"""
return self._putRequest(self._url('filewriter','config',parameter = param), dataType = 'native', data = value)
def sendFileWriterCommand(self, command):
"""
Send filewriter command to Eiger.
Args:
command: Command to send (up to now only "clear")
Returns:
Empty string
"""
return self._putRequest(self._url("filewriter","command",parameter = command), dataType = "native")
def fileWriterStatus(self,param = 'keys'):
"""Get filewriter status information
Args:
param: query the status parameter param, if 'keys' get all status parameters.
Returns:
If param is None get configuration, if param is 'keys' return list of all parameters, else return dictionary
that may contain the keys: value, value_type, unit, time, state, critical_limits, critical_values
"""
return self._getRequest(self._url('filewriter','status',parameter = param))
def fileWriterFiles(self, filename = None, method = 'GET'):
"""
Obtain file from detector.
Args:
filename: Name of file on the detector side. If None return list of available files
method: Eiger 'GET' (get the content of the file) or 'DELETE' (delete file from server)
Returns:
List of available files if 'filename' is None,
else if method is 'GET' the content of the file.
"""
if method == 'GET':
if filename is None:
return self._getRequest(self._url('filewriter','files'))
else:
return self._getRequest(url = '/{0}data/{1}'.format(self._urlPrefix, filename), dataType = 'hdf5')
elif method == 'DELETE':
return self._delRequest(url = '/{0}data/{1}'.format(self._urlPrefix,filename))
else:
raise RuntimeError('Unknown method {0}'.format(method))
def fileWriterSave(self,filename,targetDir,regex = False):
"""
Saves filename in targetDir. If regex is True, filename is considered to be a regular expression.
Save all files that match filename
Args:
filename: Name of source file, evtl. regular expression
targetDir: Directory, where to store the files
"""
if regex:
pattern = re.compile(filename)
[ self.fileWriterSave(f,targetDir) for f in self.fileWriterFiles() if pattern.match(f) ]
elif any([ c in filename for c in ['*','?','[',']'] ] ):
# for f in self.fileWriterFiles():
# self._log('DEBUG ', f, ' ', fnmatch.fnmatch(f,filename))
[ self.fileWriterSave(f,targetDir) for f in self.fileWriterFiles() if fnmatch.fnmatch(f,filename) ]
else:
targetPath = os.path.join(targetDir,filename)
with open(targetPath,'wb') as targetFile:
self._log('Writing ', targetPath)
self._getRequest(url = '/{0}data/{1}'.format(self._urlPrefix, filename), dataType = 'hdf5',fileId = targetFile)
# targetFile.write(self.fileWriterFiles(filename))
assert os.access(targetPath,os.R_OK)
return
def monitorConfig(self,param = 'keys'):
"""Get monitor configuration parameter
Args:
param: query the configuration parameter param, if 'keys' get all configuration parameters.
Returns:
If param is 'keys' return list of all parameters, else return dictionary
that may contain the keys: value, min, max, allowed_values, unit, value_type and access_mode
"""
return self._getRequest(self._url('monitor','config',parameter = param))
def setMonitorConfig(self,param,value):
"""
Set monitor configuration parameter param.
Args:
param: parameter
value: value to set
Returns:
List of changed parameters.
"""
return self._putRequest(self._url('monitor','config',parameter = param), dataType = 'native', data = value)
def monitorImages(self, param = None):
"""
Obtain file from detector.
Args:
param: Either None (return list of available frames) or "monitor" (return latest frame),
"next" (next image from buffer) or tuple(sequence id, image id) (return specific image)
Returns:
List of available frames (param = None) or tiff content of image file (param = "next", "monitor", (seqId,imgId))
"""
if param is None:
return self._getRequest(self._url('monitor','images',parameter = None) )
elif param == "next":
return self._getRequest(self._url('monitor',"images", parameter = "next"), dataType = "tif")
elif param == "monitor":
return self._getRequest(self._url('monitor','images',parameter = "monitor"), dataType = "tif")
else:
try:
seqId = int(param[0])
imgId = int(param[1])
return self._getRequest(self._url('monitor',"images", parameter = "{0}/{1}".format(seqId,imgId) ), dataType = 'tif')
except (TypeError, ValueError):
pass
raise RuntimeError('Invalid parameter {0}'.format(param))
def monitorSave(self, param, path):
"""
Save frame to path as tiff file.
Args:
param: same as monitorImages()
Returns:
None
"""
data = None
if param in ["next","monitor"]:
data = self.monitorImages(param)
else :
try:
int(param[0])
int(param[1])
data = self.monitorImages(param)
except (TypeError, ValueError):
pass
if data is None:
raise RuntimeError('Invalid parameter {0}'.format(param))
else:
with open(path,'wb') as f:
self._log('Writing ', path)
f.write(data)
assert os.access(path,os.R_OK)
return
def monitorStatus(self, param):
"""Get monitor status information
Args:
param: query the status parameter param, if 'keys' get all status parameters.
Returns:
Dictionary that may contain the keys: value, value_type, unit, time, state,
critical_limits, critical_values
"""
return self._getRequest(self._url('monitor','status',parameter = param))
def sendMonitorCommand(self, command):
"""
Send monitor command to Eiger.
Args:
command: Command to send (up to now only "clear")
Returns:
Empty string
"""
return self._putRequest(self._url("monitor","command",parameter = command), dataType = "native")
def streamConfig(self,param = 'keys'):
"""Get stream configuration parameter
Args:
param: query the configuration parameter param, if 'keys' get all configuration parameters.
Returns:
If param is 'keys' return list of all parameters, else return dictionary
that may contain the keys: value, min, max, allowed_values, unit, value_type and access_mode
"""
return self._getRequest(self._url('stream','config',parameter = param))
def setStreamConfig(self,param,value):
"""
Set stream configuration parameter param.
Args:
param: parameter
value: value to set
Returns:
List of changed parameters.
"""
return self._putRequest(self._url('stream','config',parameter = param), dataType = 'native', data = value)
def streamStatus(self, param):
"""Get stream status information
Args:
param: query the status parameter param, if 'keys' get all status parameters.
Returns:
Dictionary that may contain the keys: value, value_type, unit, time, state,
critical_limits, critical_values
"""
return self._getRequest(self._url('stream','status',parameter = param))
#
#
# Private Methods
#
#
def _log(self,*args):
if self._verbose:
print ' '.join([ str(elem) for elem in args ])
def _url(self,module,task,parameter = None):
url = "/{0}{1}/api/{2}/{3}/".format(self._urlPrefix, module, self._version, task)
if not parameter is None:
url += '{0}'.format(parameter)
return url
def _getRequest(self,url,dataType = 'native', fileId = None):
if dataType is None:
dataType = 'native'
if dataType == 'native':
mimeType = 'application/json; charset=utf-8'
elif dataType == 'tif':
mimeType = 'application/tiff'
elif dataType == 'hdf5':
mimeType = 'application/hdf5'
return self._request(url,'GET',mimeType, fileId = fileId)
def _putRequest(self,url,dataType,data = None):
data, mimeType = self._prepareData(data,dataType)
return self._request(url,'PUT',mimeType, data)
def _delRequest(self,url):
self._request(url,'DELETE',mimeType = None)
return None
def _request(self, url, method, mimeType, data = None, fileId = None):
if data is None:
body = ''
else:
body = data
headers = {}
if method == 'GET':
headers['Accept'] = mimeType
elif method == 'PUT':
headers['Content-type'] = mimeType
if not self._user is None:
headers["Authorization"] = "Basic {0}".format(self._user)
self._log('sending request to {0}'.format(url))
numberOfTries = 0
response = None
while response is None:
try:
self._connection.request(method,url, body = data, headers = headers)
response = self._connection.getresponse()
except Exception as e:
numberOfTries += 1
if numberOfTries == 50:
self._log("Terminate after {0} tries\n".format(numberOfTries))
raise e
self._log("Failed to connect to host. Retrying\n")
self._connection = httplib.HTTPConnection(self._host,self._port, timeout = self._connectionTimeout)
continue
status = response.status
reason = response.reason
if fileId is None:
data = response.read()
else:
bufferSize = 8*1024
while True:
data = response.read(bufferSize)
if len(data) > 0:
fileId.write(data)
else:
break
mimeType = response.getheader('content-type','text/plain')
self._log('Return status: ', status, reason)
if not response.status in range(200,300):
raise RuntimeError((reason,data))
if 'json' in mimeType:
return json.loads(data)
else:
return data
def _prepareData(self,data, dataType):
if data is None:
return '', 'text/html'
if dataType != 'native':
if type(data) == file:
data = data.read()
if dataType is None:
mimeType = self._guessMimeType(data)
if not mimeType is None:
return data, mimeType
elif dataType == 'tif':
return data, 'application/tiff'
mimeType = 'application/json; charset=utf-8'
return json.dumps({'value':data}), mimeType
def _guessMimeType(self,data):
if type(data) == str:
if data.startswith('\x49\x49\x2A\x00') or data.startswith('\x4D\x4D\x00\x2A'):
self._log('Determined mimetype: tiff')
return 'application/tiff'
if data.startswith('\x89\x48\x44\x46\x0d\x0a\x1a\x0a'):
self._log('Determined mimetype: hdf5')
return 'application/hdf5'
return None

508
script/Devices/EigerTest.py Normal file
View File

@@ -0,0 +1,508 @@
"""
EigerTest extends the functionality of DEigerClient for convenient
interactive work in a python shell. It should be used only for this
intended purpose or as an example how to use DEigerClient in your own
code. The ipython shell is highly recommended.
!Do NOT use this code in non-interactive scripts, python modules
or subclasses! Kittens will die and the detector may behave erratic!
For such purposes, please use DEigerClient or EIGER's REST API directly.
This code is
- NOT official DECTRIS code but written for personal use by the author
- NOT part of the software of EIGER detector systems.
- NOT well tested.
- only provided as is. Do not expect bug fixes, new features or any
support or maintanence by DECTRIS.
- NOT to be distributed without consent of the author!
- not particularly well documented. Be prepared to read the code
and simply try things out.
Modified: SteB
Version: 20150131
Author: Marcus Mueller
Contact: marcus.mueller@dectris.com
Version: 20140922
"""
import os
import re
import sys
import time, datetime
sys.path.insert(0,"/usr/local/dectris/python")
from eigerclient import DEigerClient
try:
import dectris.albula
from quickstart import Monitor
MONITOR_AVAILABLE = True
except ImportError:
MONITOR_AVAILABLE = False
#############################################################
### Configure IP and PORT of the EIGER system that you are
### accessing with this code below.
# DMZ system
#~ IP = "62.12.129.162"
#~ PORT = "4010"
#~
# fixed IP, direct connection
try:
IP = sys.argv[1]
except:
IP = "129.129.106.139"
#print "IP", IP
PORT = "80"
# for printing detector config and values
LISTED_DETECTOR_PARAMS = [
u'description',
u'detector_number',
u'data_collection_date',
u'frame_time',
u'nimages',
u'ntrigger',
u'trigger_mode',
u'photon_energy',
u'threshold_energy',
u'element',
u'count_time',
u'detector_readout_time',
u'nframes_sum',
u'frame_count_time',
u'frame_period',
#u'sub_image_count_time',
u'auto_summation',
u'summation_nimages',
u'bit_depth_readout',
u'efficiency_correction_applied',
u'flatfield_correction_applied',
u'number_of_excluded_pixels',
u'calibration_type',
u'countrate_correction_applied',
u'countrate_correction_bunch_mode',
u'pixel_mask_applied',
#u'pixel_mask',
u'virtual_pixel_correction_applied',
u'software_version',
u'sensor_material',
u'sensor_thickness',
u'x_pixels_in_detector',
u'y_pixels_in_detector',
u'x_pixel_size',
u'y_pixel_size',
u'wavelength',
u'detector_distance',
u'beam_center_x',
u'beam_center_y',
u'detector_translation',
u'detector_orientation']
CHECK_DOWNLOAD="/tmp/check_download"
# for filewriter config to have data bundles of ~ 1GB
# 16M = 20 (45MB x 20)
# 4M = 80 (12MB x 80)
# 1M = 320 ( ?MB x 320)
NIMAGES_PER_FILE=10000
class EigerTest(DEigerClient):
def setEnergy(self, photon_energy, threshold_ratio=0.5):
self.setDetectorConfig("photon_energy", photon_energy)
self.setDetectorConfig("threshold_energy", photon_energy * threshold_ratio)
def setElement(self, element='Cu'):
self.setDetectorConfig(u'element', element)
def imageSeries(self, expp, nimages, auto_sum=False, ff_corr=True,
pixel_mask=True):
self.setDetectorConfig("auto_summation", auto_sum)
self.setDetectorConfig("frame_time", expp)
# to avoid warm pixels in center of module
if expp > 0.099:
readout_time = 5.0e-04 # no simultaneous read/write
else:
# simultaneous read/write will give high duty cycle but also warm pixels
readout_time = self.detectorConfig('detector_readout_time')['value']
self.setDetectorConfig("count_time", expp - readout_time)
self.setDetectorConfig("nimages", nimages)
self.setDetectorConfig("flatfield_correction_applied", ff_corr)
self.setDetectorConfig("pixel_mask_applied", pixel_mask)
def imageSeries2(self, expp, nimages, auto_sum=True, ff_corr=True,
pixel_mask=True):
self.setDetectorConfig("auto_summation", auto_sum)
self.setDetectorConfig("frame_time", expp)
# to avoid warm pixels in center of module
if expp > 0.099:
readout_time = 5.0e-04 # no simultaneous read/write
else:
# simultaneous read/write will give high duty cycle but also warm pixels
readout_time = self.detectorConfig('detector_readout_time')['value']
self.setDetectorConfig("count_time", expp - readout_time)
self.setDetectorConfig("nimages", nimages)
self.setDetectorConfig("ntrigger", nimages)
self.setDetectorConfig("flatfield_correction_applied", ff_corr)
self.setDetectorConfig("pixel_mask_applied", pixel_mask)
# self.printConf('time|image')
def printConf(self, regex='', full=0):
for param in LISTED_DETECTOR_PARAMS:
if full:
if re.search(regex, param):
try:
print str(param).ljust(35), ' = ', str(eiger.detectorConfig(param)['value']).ljust(35),' ', str(eiger.detectorConfig(param)['min']).ljust(35),' ', str(eiger.detectorConfig(param)['max']).ljust(35)
except:
print ""
pass
#print str(param).ljust(35), ' = ', str(eiger.detectorConfig(param)['value']).ljust(35)
else:
if eiger.search(regex, param):
print str(param).ljust(35), ' = ', eiger.detectorConfig(param)['value']
def setFileNameBase(self, fnBase):
self.setFileWriterConfig("name_pattern", fnBase)
def setImagesPerFile(self, nimages=1000):
self.setFileWriterConfig("nimages_per_file", nimages)
def pHello(self, z="today"):
print "Hello " + z
def printFileWriterConfig(self):
for param in self.fileWriterConfig():
try:
print param, ' = ', self.fileWriterConfig(param)['value']
except RuntimeError as e:
print "RuntimeError accessing %s: %s" % (param, e)
def printFileWriterStatus(self):
for param in self.fileWriterStatus():
try:
print param, ' = ', self.fileWriterStatus(param)['value']
except RuntimeError as e:
print "RuntimeError accessing %s: %s" % (param, e)
def printTempHum(self, all_data=0):
for param in self.detectorStatus():
if all_data:
if re.search("temp|humidity", param):
print (param).ljust(35), ' = ', self.detectorStatus(param)['value']
else:
if re.search("th0", param):
print (param).ljust(35), ' = ', self.detectorStatus(param)['value']
def printFW(self):
for param in self.detectorStatus():
if re.search("fw", param):
print (param).ljust(35), ' = ', self.detectorStatus(param)['value']
def printDetectorState(self):
print "State: %s" % self.detectorStatus('state')['state']
print "Error: %s" % self.detectorStatus('error')
def setDetConMultiple(self, **params):
"""
Convenience function to set a single or multiple detector
configuration parameters in the form (parameter=value[, ...]).
Multiple parameters are set in arbitrary order!
You have to check the print output of this function whether
you obtain the desired detector configuration
"""
for p, data in params.items():
changeList = self.setDetectorConfig(param=p, value=data, dataType=None)
changes = ''
for changed_param in changeList:
changed_value = self.detectorConfig(changed_param)['value']
changes += '%s = %s ; ' % (changed_param, str(changed_value))
print "Setting: %s = %s" % (p, str(data))
print "Changing: " + changes[:-2]
def purgeFiles(self, force=False):
f_list = self.fileWriterFiles()
if not force:
print "Files on the detector control unit:"
#~ [print(f) for f in f_list]
for f in f_list:
print f
if force == True or raw_input('Do you really want to purge all '
'these files? \n'
'Then enter y. ') == 'y':
[self.fileWriterFiles(f, 'DELETE') for f in f_list]
#~ for f in f_list:
#~ self.fileWriterFiles(f, 'DELETE')
else:
print "Aborting without deleting files."
def startMonitor(self):
m = None
if not MONITOR_AVAILABLE:
print "Monitor nor available. Check dependencies."
print "Returning None."
else:
m = Monitor(self)
m.start()
print "Monitor started and monitor object returned."
self._monitor = m
return m
def arm(self):
self.sendDetectorCommand(u'arm')
def trigger(self):
self.sendDetectorCommand(u'trigger')
def disarm(self):
self.sendDetectorCommand(u'disarm')
def initialize(self, element=None, energy=None):
self.sendDetectorCommand(u'initialize')
if element is not None and energy is not None:
print "You cannot give element AND energy."
elif element is not None:
self.setElement(element)
elif energy is not None:
self.setEnergy(energy)
def exposure(self, fnBase=None):
"""
tvx style exposure command
"""
if fnBase is not None:
self.setFileNameBase(fnBase=fnBase)
self.setDetectorConfig('data_collection_date',
self.fileWriterStatus('time')['value'])
print "Arm ..."
self.arm()
print "Trigger ..."
self.trigger()
print "Disarm ..."
time.sleep(1)
self.disarm()
print "DONE!"
def download(self, downloadpath="/tmp"):
try:
matching = self.fileWriterFiles()
except:
print "could not get file list"
if len(matching):
try:
[self.fileWriterSave(i, downloadpath) for i in matching]
except:
print "error saveing - noting deleted"
else:
print "Downloaded ..."
for i in matching:
print i + " to " + str(downloadpath)
[self.fileWriterFiles(i, method = 'DELETE') for i in matching]
print "Deteted " + str(len(matching)) + " file(s)"
def downloadD(self, downloadpath="/tmp"):
if not os.path.exists(downloadpath):
os.makedirs(downloadpath)
open(CHECK_DOWNLOAD, 'a').close()
while os.path.exists(CHECK_DOWNLOAD):
try:
matching = self.fileWriterFiles()
except:
print "could not get file list"
time.sleep(1)
if len(matching)>0:
try:
[self.fileWriterSave(i, downloadpath) for i in matching]
except:
print "error saveing - noting deleted"
else:
print "Downloaded ..."
for i in matching:
print i
[self.fileWriterFiles(i, method = 'DELETE') for i in matching]
print "Deteted " + str(len(matching)) + " file(s)"
def stopDownloadD(self):
os.remove(CHECK_DOWNLOAD)
def setup_bt_Nov_2016(self):
"""
setup the beamtime for operation
"""
self.setDetectorConfig("photon_energy", 15000)
print "Photon energy set to: " + str(self.detectorConfig("photon_energy")["value"])
self.setDetectorConfig("threshold_energy", 10000)
print "Threshold energy set to: " + str(self.detectorConfig("threshold_energy")["value"])
self.setDetectorConfig("ntrigger",1e6)
self.setDetectorConfig("nimages", 1)
self.setFileWriterConfig("compression_enabled",False)
print "Compression set to: " + str(self.fileWriterConfig("compression_enabled")['value'])
self.setFileWriterConfig("nimages_per_file",20)
def config_bt_Nov_2016(self,file_name="series",count_time=1):
"""
configure one run - set name and count time (assume that you record 1e6 triggerd images)
"""
readout_time = self.detectorConfig('detector_readout_time')['value']
self.setDetectorConfig("count_time", count_time)
self.setDetectorConfig("frame_time", count_time + readout_time)
self.setFileWriterConfig("name_pattern", file_name + "_$id")
print "Images with " + str(self.detectorConfig("count_time")["value"]) + " s"
print "Named to " + str(self.fileWriterConfig("name_pattern")["value"])
def setup_of(self):
"""
setup the beamtime for operation
"""
self.setDetectorConfig("photon_energy", 19000)
print "Photon energy set to: " + str(self.detectorConfig("photon_energy")["value"])
self.setDetectorConfig("threshold_energy", 5000)
print "Threshold energy set to: " + str(self.detectorConfig("threshold_energy")["value"])
self.setDetectorConfig("ntrigger",1e6)
self.setDetectorConfig("nimages", 1)
self.setDetectorConfig("trigger_mode", 'exts')
self.setFileWriterConfig("compression_enabled",False)
print "Compression set to: " + str(self.fileWriterConfig("compression_enabled")['value'])
self.setFileWriterConfig("nimages_per_file",20)
def setup_of_exte(self):
"""
setup the beamtime for operation
"""
self.setDetectorConfig("photon_energy", 19000)
print "Photon energy set to: " + str(self.detectorConfig("photon_energy")["value"])
self.setDetectorConfig("threshold_energy", 5000)
print "Threshold energy set to: " + str(self.detectorConfig("threshold_energy")["value"])
self.setDetectorConfig("ntrigger",1e6)
self.setDetectorConfig("nimages", 1)
self.setDetectorConfig("trigger_mode", 'exte')
self.setFileWriterConfig("compression_enabled",False)
print "Compression set to: " + str(self.fileWriterConfig("compression_enabled")['value'])
self.setFileWriterConfig("nimages_per_file",20)
def setup_sg(self):
"""
setup the beamtime for operation
"""
self.setDetectorConfig("photon_energy", 19000)
print "Photon energy set to: " + str(self.detectorConfig("photon_energy")["value"])
self.setDetectorConfig("threshold_energy", 5000)
print "Threshold energy set to: " + str(self.detectorConfig("threshold_energy")["value"])
self.setDetectorConfig("ntrigger",1e6)
self.setDetectorConfig("nimages", 1)
self.setDetectorConfig("trigger_mode", 'ints')
self.setFileWriterConfig("compression_enabled",False)
print "Compression set to: " + str(self.fileWriterConfig("compression_enabled")['value'])
self.setFileWriterConfig("nimages_per_file",20)
def config_filename_countime(self,file_name="series",count_time=1):
"""
configure one run - set name and count time (assume that you record 1e6 triggerd images)
"""
readout_time = self.detectorConfig('detector_readout_time')['value']
self.setDetectorConfig("count_time", count_time)
self.setDetectorConfig("frame_time", count_time + readout_time)
self.setFileWriterConfig("name_pattern", file_name + "_$id")
print "Images with " + str(self.detectorConfig("count_time")["value"]) + " s"
print "Named to " + str(self.fileWriterConfig("name_pattern")["value"])
def exp(self,frame_time=1,nimages=1,ntrigger=1000):
"""
tvx style exposure command
"""
self.setDetectorConfig("frame_time", frame_time)
readout_time = self.detectorConfig('detector_readout_time')['value']
self.setDetectorConfig("count_time", frame_time - readout_time)
self.setDetectorConfig("nimages", nimages)
self.setDetectorConfig("ntrigger",ntrigger)
if nimages < NIMAGES_PER_FILE:
nipf = nimages
else:
nipf = NIMAGES_PER_FILE
self.setFileWriterConfig("nimages_per_file",nipf+1)
print "Arm ..."
self.arm()
print "Trigger ..."
print(datetime.datetime.now().strftime("%H:%M:%S.%f"))
self.trigger()
print(datetime.datetime.now().strftime("%H:%M:%S.%f"))
print "Disarm ..."
time.sleep(1)
self.disarm()
print "DONE!"
self.printConf('time|image')
def hdf_file_check(self):
"""
tvx style exposure command
"""
self.setDetectorConfig("omega_range_average",0.1)
self.setDetectorConfig("frame_time", 1)
readout_time = self.detectorConfig('detector_readout_time')['value']
self.setDetectorConfig("count_time", 1 - readout_time)
self.setDetectorConfig("nimages", 1)
self.setDetectorConfig("ntrigger",1)
self.setFileWriterConfig("nimages_per_file",1+1)
print "Arm ..."
self.arm()
print "Trigger ..."
self.trigger()
print "Disarm ..."
time.sleep(1)
self.disarm()
print "DONE!"
self.printConf('time|image')
def testLoop(self, nloops, purge=True, **kwargs):
print "#" * 72 + "\nRunning test loop with %d series.\n" % nloops
self.imageSeries(**kwargs)
print "-" * 72
for n in range(nloops):
print "Running series %d" % (n + 1)
self.exposure()
if purge:
print "Purging files."
time.sleep(1)
self.purgeFiles(force=True)
print "-" * 72
print "Finished %d series." % nloops
print "#" * 72 + "\n"
if __name__ == '__main__':
print "EIGER test client - running at " + str(IP)
eiger = EigerTest(host=IP, port=PORT, verbose=False)
state_now = eiger.detectorStatus("state")["value"]
print "Detector: " + eiger.detectorStatus("state")["value"]
if state_now is "na":
print "!!! initalize by typing: eiger.initialize() !!!"
print ""
eiger.printTempHum()
#~ e.setDetectorConfig('auto_summation', False)
#~ e.setDetectorConfig('countrate_correction_applied', True)
#~ e.setDetectorConfig('element', 'Cu')
#~ e.sendDetectorCommand(u'initialize')
#~ e.setEnergy(12400)
#~ e.imageSeries(expp=0.2, nimages=5)
#~ e.printTempHum()
# ~ e.setImagesPerFile(100)
#~ e.printDetectorConfig()
#~ e.printFileWriterConfig()
#~ print "Exposure ..."
#~ e.exposure(fnBase='test')
#~ print "... done"
#~ e.fileWriterSave(filename='test*', targetDir=os.path.curdir)

View File

@@ -0,0 +1,16 @@
#print "Detectors Check"
for name, info in DETECTORS.items():
path = info["path"]
try:
#print path,
caget_str(path)
info["enabled"] = True
#print " ok"
except:
info["enabled"] = False
#print " error"

View File

@@ -21,6 +21,12 @@ crlogic_config["class"] = "ch.psi.pshell.crlogic.CrlogicScan"
run("CPython/wrapper")
DETECTORS={ \
'Eiger4m': {"path":"X05LA-ES1-EIGER1:cam1:FilePath", "enabled": False}, \
'XRayEye': {"path":"X05LA-ES2-GIGE01:TIFF1:FilePath", "enabled": False} \
}
###################################################################################################
# EPICS utilities
###################################################################################################
@@ -45,3 +51,34 @@ def run_fda(file_name, arguments={}):
Run FDA loop
"""
ProcessorFDA().execute(file_name,arguments)
###################################################################################################
# System callbaks
###################################################################################################
def on_command_started(info):
pass
def on_command_finished(info):
pass
def on_change_data_path(path):
if path is not None:
print "Data path: " + str(path)
raw_data_folder = path + "/raw_data"
os.makedirs(raw_data_folder)
#with open(raw_data_folder + "/test.txt", "w") as f:
# f.write("Success")
for name, info in DETECTORS.items():
log(name + " enabled = " + str(info["enabled"]))
if info["enabled"]:
channel_path = info["path"]
caput_str(channel_path, raw_data_folder + "/" + name)
def on_session_started(id):
pass
def on_session_finished(id):
pass