[docs]classBeamstopPosition(StrictEnum):IN_POSITION="In position"OUT_OF_POSITION="Out of position"
[docs]classReadOnlyBeamstop(Device):"""Reads from 2 motors to work out if the beamstop is in position. E.g. bps.rd(beamstop.position) """def__init__(self,name=""):# Raw signalsself.x=soft_signal_rw(float)self.y=soft_signal_rw(float)# Derived signalsself.position=derived_signal_r(self._get_position,x=self.x,y=self.y)super().__init__(name=name)def_get_position(self,x:float,y:float)->BeamstopPosition:ifabs(x)<1andabs(y)<2:returnBeamstopPosition.IN_POSITIONelse:returnBeamstopPosition.OUT_OF_POSITION
[docs]classMovableBeamstop(Device):"""As well as reads, this one allows you to move it. E.g. bps.mv(beamstop.position, BeamstopPosition.IN_POSITION) """def__init__(self,name=""):# Raw signalsself.x=soft_signal_rw(float)self.y=soft_signal_rw(float)# Derived signalsself.position=derived_signal_rw(self._get_position,self._set_from_position,x=self.x,y=self.y)super().__init__(name=name)def_get_position(self,x:float,y:float)->BeamstopPosition:ifabs(x)<1andabs(y)<2:returnBeamstopPosition.IN_POSITIONelse:returnBeamstopPosition.OUT_OF_POSITIONasyncdef_set_from_position(self,position:BeamstopPosition)->None:ifposition==BeamstopPosition.IN_POSITION:awaitasyncio.gather(self.x.set(0),self.y.set(0))else:awaitasyncio.gather(self.x.set(3),self.y.set(5))
[docs]classExploder(StandardReadable):"""This one takes a value and sets all its signal to that value. This allows convenience "set all" functions, while the individual signals are still free to be set to different values. """def__init__(self,num_signals:int,name=""):withself.add_children_as_readables():self.signals=DeviceVector({i:soft_signal_rw(int,units="cts")foriinrange(1,num_signals+1)})self.set_all=derived_signal_w(self._set_all,derived_units="cts")super().__init__(name=name)asyncdef_set_all(self,value:int)->None:coros=[sig.set(value)forsiginself.signals.values()]awaitasyncio.gather(*coros)