Source code for py4syn.epics.PilatusClass

"""Dectris Pilatus X-ray camera class

Python class for Pilatus X-ray cameras using EPICS area detector
IOC.

:platform: Unix
:synopsis: Python class for Pilatus X-ray cameras

.. moduleauthor:: Henrique Dante de Almeida <henrique.almeida@lnls.br>

"""
from threading import Event

from py4syn.epics.StandardDevice import StandardDevice
from py4syn.epics.ICountable import ICountable
from py4syn.utils.timer import Timer
from epics import PV, ca, caput

[docs]class Pilatus(StandardDevice, ICountable): """ Class to control Pilatus cameras via EPICS. Examples -------- >>> from shutil import move >>> from py4syn.epics.PilatusClass import Pilatus >>> from py4syn.epics.ShutterClass import SimpleShutter >>> >>> def getImage(pv, fileName='image.tif', shutter=''): ... shutter = SimpleShutter(shutter, shutter) ... camera = Pilatus('pilatus', pv) ... camera.setImageName('/remote/' + fileName) ... camera.setCountTime(10) ... camera.startCount() ... shutter.open() ... camera.wait() ... camera.stopCount() ... shutter.close() ... move('/remote/' + fileName, '/home/user/' + fileName) ... camera.close() ... """ RESPONSE_TIMEOUT = 15 def __init__(self, mnemonic, pv): """ **Constructor** See :class:`py4syn.epics.StandardDevice` Parameters ---------- mnemonic : `string` A mnemonic for the camera pv : `string` Base name of the EPICS process variable """ super().__init__(mnemonic) self.acquireChanged = Event() self.acquiring = False self.pvAcquire = PV(pv + ':Acquire') self.pvAcquire.add_callback(self.statusChange) caput(pv + ':FileTemplate', '%s%s\0') caput(pv + ':FilePath', '\0') self.pvAcquireTime = PV(pv + ':AcquireTime') self.pvFilePath = PV(pv + ':FileName') self.timer = Timer(self.RESPONSE_TIMEOUT)
[docs] def setImageName(self, name): """ Sets the output image file name. The image will be saved with this name after the acquisition. Parameters ---------- name : `string` The full pathname of the image. """ self.pvFilePath.put(name + "\0", wait=True)
[docs] def statusChange(self, value, **kw): """ Helper callback used to wait for the end of the acquisition. """ self.acquiring = value self.acquireChanged.set()
[docs] def close(self): """ Stops an ongoing acquisition, if any, and puts the EPICS IOC in idle state. """ self.pvAcquire.put(0, wait=True)
[docs] def getValue(self, **kwargs): """ This is a dummy method that always returns zero, which is part of the :class:`py4syn.epics.ICountable` interface. Pilatus does not return a value while scanning. Instead, it stores a file with the resulting image. """ return 0
[docs] def setCountTime(self, t): """ Sets the image acquisition time. Parameters ---------- t : `float` Acquisition time """ self.pvAcquireTime.put(t, wait=True) self.timer = Timer(t + self.RESPONSE_TIMEOUT)
[docs] def setPresetValue(self, channel, val): """ Dummy method to set initial counter value. """ pass
[docs] def startCount(self): """ Starts acquiring an image. It will acquire for the duration set with :meth:`setCountTime`. The resulting file will be stored in the file set with :meth:`setImageName`. See: :meth:`setCountTime`, :meth:`setImageName` Examples -------- >>> def acquire(pilatus, time, filename): ... pilatus.setCountTime(time) ... pilatus.setImageName(filename) ... pilatus.startCount() ... pilatus.wait() ... pilatus.stopCount() ... """ if self.acquiring: raise RuntimeError('Already counting') self.acquiring = True self.pvAcquire.put(1) self.timer.mark()
[docs] def stopCount(self): """ Stops acquiring the image. This method simply calls :meth:`close`. See: :meth:`close` """ self.close()
[docs] def canMonitor(self): """ Returns false indicating that Pilatus cannot be used as a counter monitor. """ return False
[docs] def canStopCount(self): """ Returns true indicating that Pilatus has a stop command. """ return True
[docs] def isCounting(self): """ Returns true if the camera is acquiring an image, or false otherwise. Returns ------- `bool` """ return self.acquiring
[docs] def wait(self): """ Blocks until the acquisition completes. """ if self.acquiring == False: return self.acquireChanged.clear() while self.acquiring and self.timer.check(): self.acquireChanged.wait(5) self.acquireChanged.clear() if self.timer.expired(): raise RuntimeError('Camera is not answering')