509 lines
19 KiB
Python
509 lines
19 KiB
Python
"""
|
|
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)
|
|
|
|
|