################################################################################################### # Deployment specific global definitions - executed after startup.py ################################################################################################### ################################################################################################### #Devices for PShell standard scans ################################################################################################### import random #################################################################################################### # Simulated devices #################################################################################################### add_device(DummyMotor("m1"), True) add_device(DummyMotor("m2"), True) add_device(DummyRegister("reg1",3), True) add_device(DummyPositioner("p1"),True) add_device(MotorGroupBase("mg1", m1, m2), True) add_device(MotorGroupDiscretePositioner("dp1", mg1), True) #Initial Configuration if p1.getConfig().unit is None: p1.getConfig().minValue = 0.0 #Not persisted p1.getConfig().maxValue = 1000.0 p1.getConfig().unit = "mm" p1.getConfig().save() p1.initialize() if dp1.getConfig().positions is None: dp1.getConfig().positions = ["Park","Ready","Out","Clear"] dp1.getConfig().motor1 = ["0.0","4.0","8.0" ,"0.0"] dp1.getConfig().motor2 = ["0.0","5.0","3.0" ,"NaN"] dp1.getConfig().save() dp1.initialize() #Update m1.setMonitored(True) m2.setMonitored(True) #################################################################################################### # Readable / Writable objects can be created and used in scans #################################################################################################### class MyWritable(Writable): def write(self, value): #print ("Write: ",value) pass class MyReadable(Readable): def read(self): return random.random() class MyReadableArray(ReadableArray): def read(self): ret = [] for i in range (self.getSize()): ret.append(random.random()) return to_array(ret,'d') def getSize(self): return 20 class MyReadableArrayNumpy(ReadableArray): def read(self): ret = numpy.ones(self.getSize(),'d') return ret def getSize(self): return 20 class MyReadableMatrix(ReadableMatrix): def read(self): ret = [] for i in range (self.getHeight()): ret.append([random.random()] * self.getWidth()) return to_array(ret, 'd') def getWidth(self): return 80 def getHeight(self): return 40 class MyReadableMatrixNumpy(ReadableMatrix): def read(self): ret = numpy.ones((self.getHeight(), self.getWidth()),'d') for i in range(self.getHeight()): ret[i]=i return to_array(ret, 'd') def getWidth(self): return 80 def getHeight(self): return 40 ao1 = MyWritable("ao1") ao2 = MyWritable("ao2") ai1 = MyReadable("ai1") ai2 = MyReadable("ai2") wf1 = MyReadableArray("wf1") wf2 = MyReadableArrayNumpy("wf2") im1 = MyReadableMatrix("im1") im2 = MyReadableMatrixNumpy("im2") #################################################################################################### # Imaging #################################################################################################### configured = os.path.exists(GenericDevice.getConfigFileName("src1")) add_device(RegisterMatrixSource("src1", im1.proxy), True) add_device(RegisterMatrixSource("src2", im2.proxy), True) #src1.setPolling(100) #src2.setPolling(100) #Some configuration for so the imaging will work out of the box if not configured: src1.getConfig().colormapAutomatic = True src1.getConfig().colormap = Colormap.Temperature src1.getConfig().save() src2.getConfig().colormapAutomatic = True src2.getConfig().save() ################################################################################################### #Embedding Bluesky ################################################################################################### import signal signal.signal = lambda *args: None from bluesky import RunEngine from bluesky.callbacks import CallbackBase from bluesky.callbacks.best_effort import BestEffortCallback from bluesky.utils import install_kicker, DuringTask #from bluesky.utils import ProgressBarManager from ophyd.sim import det1, det2, det3, det4, det, motor, motor1, motor2, motor3,img, sig, direct_img, pseudo1x3 from ophyd import Signal from ophyd.signal import EpicsSignal from bluesky.plans import count, scan, rel_scan, list_scan, grid_scan, list_grid_scan from bluesky.simulators import summarize_plan import bluesky.plan_stubs as bps from bluesky.plan_stubs import mv import bluesky.preprocessors as bpp from bluesky.preprocessors import SupplementalData #import databroker from databroker import Broker #import suitcase #import suitcase.csv CAN_PAUSE=True #def on_ctrl_cmd(cmd): def on_abort(parent_thread): global RE # print ("Control command: ", cmd) # if cmd=="abort": if "RE" in globals(): if RE.state not in ['idle','paused', 'pausing']: if CAN_PAUSE: print ("Abort command: Run Engine aborted") sys.stderr=None RE.abort("User abort") return else: print ("Abort command: Run Engine pause request") RE.request_pause() return _default_abort(parent_thread) def on_close(parent_thread): on_abort(parent_thread) from collections import deque is_scan_paused = False class MyHandler(CallbackBase): def __init__(self): self.queue= deque(maxlen=1000) def clear(self): self.queue.append(("clear",None)) def start(self, doc): self.queue.append(("start",doc)) def stop(self, doc): self.queue.append(("stop",doc)) def descriptor(self, doc): self.queue.append(("descriptor",doc)) def resource(self, doc): self.queue.append(("resource",doc)) def event(self, doc): self.queue.append(("event",doc)) while is_scan_paused: time.sleep(0.1) def datum(self, doc): self.queue.append(("datum",doc)) def event_page(self, doc): self.queue.append(("event_page",doc)) def datum_page(self, doc): self.queue.append(("datum_page",doc)) handler= MyHandler() re_scan=re_res=None class EventProcessingTask(DuringTask): def __init__(self): pass def block(self, blocking_event): global start_doc,descriptor_coc, stop_doc, event_doc, re_scan, re_res, __return__,__exception__ re_scan=None while True: done = blocking_event.wait(.1) if done: return try: check_pause() while len(handler.queue): (msg, doc) = handler.queue.popleft() #print("-> " ,msg) if msg=="start": global start_doc start_doc=doc writables=doc.get('motors',[]) readables=doc.get('detectors',[]) start,stop, steps=-1,-1,doc.get('num_intervals',-1) try: if doc.get("plan_name","")=="grid_scan": steps=[x-1 for x in doc['shape']] start=[x[0] for x in doc['extents']] stop=[x[1] for x in doc['extents']] elif doc.get("plan_name","")=="list_grid_scan": steps=[-1 for x in doc['shape']] start=[x[0] for x in doc['extents']] stop=[x[1] for x in doc['extents']] elif doc.get("plan_name","")=="scan": _,start,stop = doc['plan_args']['args'] elif doc.get("plan_name","")=="list_scan": _,positions=doc['plan_args']['args'] start = min(positions) stop = max(positions) except: pass diags=None monitors=None meta={} for k in start_doc.keys(): o=start_doc[k] if o is not None: if k=="extents": o = str(o) elif type(o) in (list, tuple): o=to_array(o,'s') elif type(o) == dict: o=str(o) meta[k]=o re_res = None re_scan = ManualScan(writables, readables ,start, stop, steps, diags=diags, monitors=monitors, meta=meta) re_scan.scan.setCanPause(CAN_PAUSE) re_scan.start() elif msg=="stop": global stop_doc stop_doc=doc if re_scan is not None: if not re_scan.scan.isCompleted(): re_scan.end() re_res = re_scan.scan.getResult() sys.stderr=jep_stderr elif msg=="descriptor": global descriptor_doc descriptor_doc=doc elif msg=="event": global event_doc event_doc=doc if (re_scan is not None) and not (re_scan.scan.isCompleted()): setpoints=[] readbacks=[] detectors=[] data=doc['data'] for dev in start_doc.get("motors",[]): readbacks.append(data[dev]) try: setpoints.append(data[dev+"_setpoint"]) except: setpoints.append(data[dev]) for dev in start_doc.get("detectors",[]): v=data[dev] if str(type(v))=="": v=numpy.array(v) detectors.append(v) re_scan.append (setpoints, readbacks, detectors) elif msg=="resource": pass elif msg=="datum": pass elif msg=="event_page": pass elif msg=="datum_page": pass elif msg=="clear": pass elif msg=="check_pause": pass elif msg=="read": try: (dev)=doc __return__ = dev.read() except Exception as e: __exception__ = e elif msg=="write": try: (dev, value)=doc dev.write(value) __return__ = True except Exception as e: __exception__ = e except Exception as e: #print (e) pass def check_pause(): try: global RE, re_scan, is_scan_paused if CAN_PAUSE: if ("RE" in globals()) and (re_scan is not None) and not (re_scan.scan.isCompleted()): is_scan_paused =re_scan.scan.isPaused() and not re_scan.scan.isAborted() else: is_scan_paused = False #if re_scan.scan.isAborted(): # if RE.state not in ['idle','paused', 'pausing']: # print ("Scan abort") # RE.abort("Scan abort") """ if re_scan.scan.isPaused(): if RE.state not in ['idle','paused', 'pausing']: print ("Scan paused: Run Engine pause request") RE.request_pause() is_scan_paused = True else: if RE.state in ['paused', 'pausing']: print ("Scan resumed: Run Engine resuming") #RE.resume() """ except: pass class ReaderWrapper(): def __init__(self, dev): self.dev=dev self.name=dev.getName() self.parent = None try: self.source = self.dev.getChannelName() except: self.source = "Unknown" try: try: self.shape = [self.dev.getHeight(), self.dev.getWidth()] self.shape_str = "["+str(self.shape[0])+"]"+"["+str(self.shape[1])+"]" except: self.shape = [self.dev.getSize()] self.shape_str = "["+str(self.shape[0])+"]" except: self.shape = [] self.shape_str="" try: self.precision = self.dev.getPrecision() except: self.precision = None self.dtype = 'number' self.cfg_description = {"shape_str":{"dtype":"string", 'shape':(len(self.shape_str),), "source":""}, } self.configuration = {"shape_str":{"value":self.shape_str, "timestamp":time.time()}} self.name = self.name+self.shape_str def read(self): if is_main_thread(): return {self.name:{"value":self.dev.read(), "timestamp":time.time()}} global __return__,__exception__ __return__ = __exception__ = None handler.queue.append(("read", (self.dev))) while (__return__ is None) and (__exception__ is None): time.sleep(0.01) if __exception__ is not None: raise __exception__ return {self.name:{"value":__return__, "timestamp":time.time()}} def describe(self): self.description = {self.name: { \ 'dtype':self.dtype , \ 'shape': self.shape, \ 'source': self.source, \ 'precision': self.precision \ }} return self.description def describe_configuration(self): return self.cfg_description def read_configuration(self): return self.configuration class NullStatus: "a simple Status object that is always immediately done" def __init__(self): self._cb = None self.done = True self.success = True @property def finished_cb(self): return self._cb @finished_cb.setter def finished_cb(self, cb): cb() self._cb = cb class MoverWrapper(ReaderWrapper): def set(self, value): if is_main_thread(): self.dev.write(value) else: global __return__,__exception__ __return__ = __exception__ = None handler.queue.append(("write", (self.dev, value))) while (__return__ is None) and (__exception__ is None): time.sleep(0.01) if __exception__ is not None: raise __exception__ self.dev.waitReady(-1) return NullStatus() @property def position(self): return self.dev.getPosition() def stop(self, *, success=False): self.dev.stop() #Wraps an Ophyd device as a Readable, so can be used in *scan commands class Ophyd(Readable): def __init__(self, dev): for k in dev.describe().keys(): Nameable.__init__(self, k, Readable.__interfaces__ ) break self.dev=dev def read(self): v = self.dev.read() if (v is None) or (len(v)==0): return None v = v[self.getName()] try: timestamp = int(v["timestamp"]*1000) except: timestamp = time.time() ret = TimestampedValue (v["value"], timestamp) return ret RE = RunEngine({}, during_task=EventProcessingTask()) if CAN_PAUSE: RE.pause_msg="User abort" bec = BestEffortCallback() bec.disable_plots() RE.subscribe(bec) RE.subscribe(handler) motor.delay = 1.1 # simulate slow motor movement ch1 = EpicsSignal("TESTIOC:TESTSINUS:SinCalc") #TODO: DEmonstrate use of waveform and areadetector (Manual scan setup with the indexes in name) #ch2 = EpicsSignal("TESTIOC:TESTWF2:MyWF", name="arr[10]") #ch3 = EpicsSignal("TESTIOC:TESTWF2:MyWF", name="img[3][2]")det3=ReaderWrapper(sin) dets = [det1, det2]