Source code for contrast.environment.scheduling
"""
Module which provides Scheduler classes, which help the acquisition
system determine whether the instrument is ready to acquire, and if
there are any deadlines coming up that have to be avoided.
"""
import time
from threading import Thread
try:
import tango
except:
pass # makes building docs easier
[docs]class DummyScheduler(object):
"""
Dummy base class to define the API.
"""
@property
def ready(self):
"""
Whether or not the system is available now.
"""
return self._ready()
@property
def limit(self):
"""
Time left (in seconds) until the next deadline, None for no deadline.
"""
return self._limit()
def _ready(self):
return True
def _limit(self):
return None
[docs]class DummyInjectionScheduler(DummyScheduler):
"""
Dummy that does injection for one minute every five minutes.
"""
def _ready(self):
return time.localtime().tm_min % 5
def _limit(self):
whole_mins = 4 - (time.localtime().tm_min % 5)
whole_secs = 60 - time.localtime().tm_sec
return whole_mins * 60 + whole_secs
[docs]class TangoShutterChecker(Thread):
"""
Helper class which asynchronously checks the status of a number of
shutters and keeps their last statuses in a GIL-protected list,
which can be accessed at any time.
"""
def __init__(self, *shutter_devs):
super().__init__()
self.device_list = [tango.DeviceProxy(name) for name in shutter_devs]
self.status_list = [True, ] * len(shutter_devs)
self.stopped = False
def run(self):
while not self.stopped:
for i, dev in enumerate(self.device_list):
try:
status = 'OPEN' in dev.status()
except:
print('there was a problem reading shutter %s'
% dev.name())
status = True
self.status_list[i] = status
time.sleep(3)
def stop(self):
self.stopped = True
[docs]class MaxivScheduler(DummyScheduler):
"""
Scheduler to keep track of shutter status and the MAX IV injection system.
NOTE: Using threaded status checkers here to avoid polling a large
number of potentially slow shutter devices on a different control system.
At MAX IV, there is a local proxy device with countdown and ring
current attributes.
"""
def __init__(self,
proxy_device,
shutter_list,
avoid_injections=True,
respect_countdown=True):
try:
self.shutter_checker = TangoShutterChecker(*shutter_list)
self.shutter_checker.start()
self.proxy = tango.DeviceProxy(proxy_device)
self.injection_device = tango.DeviceProxy(
'g-v-csproxy-0:10303/R3-319S2/DIA/DCCT-01') # awaiting a local proxy solution
self.disabled = False
self.avoid_injections = avoid_injections
self.respect_countdown = respect_countdown
except Exception as e:
print('Failed to initialize scheduler:')
print(e)
def _ready(self):
if self.disabled:
return True
else:
shutters_ok = False not in self.shutter_checker.status_list
try:
if self.avoid_injections:
# negative when refilling:
injection_ok = (self.injection_device.lifetime > 0)
else:
injection_ok = True
except:
print("Couldn't reach the injection device %s, ignoring"
% self.injection_device.name())
injection_ok = True
return (shutters_ok and injection_ok)
def _limit(self):
if not self.respect_countdown:
return None
try:
dl = self.proxy.countdowndevice # this is an int
dl = 1 if (dl < 0) else dl
return dl
except:
print('MaxivScheduler: Problem getting the topup countdown value')
return None