def addDeviceDataAsStream(devices, label): """ plan: add an ophyd Device as an additional document stream Use this within a custom plan, such as this example:: from apstools.plans import addDeviceStream ... yield from bps.open_run() # ... yield from addDeviceDataAsStream(prescanDeviceList, "metadata_prescan") # ... yield from custom_scan_procedure() # ... yield from addDeviceDataAsStream(postscanDeviceList, "metadata_postscan") # ... yield from bps.close_run() """ yield from bps.create(name=label) if not isinstance(devices, list): # just in case... devices = [devices] for d in devices: yield from bps.read(d) yield from bps.save()
def fly_body(): yield from bps.trigger_and_read([E_centers], name='energy_bins') for y in range(num_scans): # go to start of row yield from bps.mv(mono.linear, l_start) # set the fly speed yield from bps.mv(mono.linear.velocity, flyspeed) yield from bps.trigger_and_read([mono], name='row_ends') for v in ['p1600=0', 'p1600=1']: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the struck yield from bps.trigger(sclr, group=f'fly_energy_{y}') # fly the motor yield from bps.abs_set(mono.linear, l_stop + a_l_step_size, group=f'fly_energy_{y}') yield from bps.wait(group=f'fly_energy_{y}') yield from bps.trigger_and_read([mono], name='row_ends') yield from bps.mv(mono.linear.velocity, 0.5) # hard coded to let the sclr count its fingers and toes yield from bps.sleep(.1) # read and save the struck yield from bps.create(name='primary') yield from bps.read(sclr) yield from bps.save()
def _plan(self): yield from bps.open_run() # stash numcapture and shutter_enabled num_capture = yield from bps.rd(self.device.hdf5.num_capture) shutter_enabled = yield from bps.rd(self.device.dg1.shutter_enabled) # set to 1 temporarily self.device.hdf5.num_capture.put(1) # Restage to ensure that dark frames goes into a separate file. yield from bps.stage(self.device) yield from bps.mv(self.device.dg1.shutter_enabled, 2) # The `group` parameter passed to trigger MUST start with # bluesky-darkframes-trigger. yield from bps.trigger_and_read([self.device], name='dark') # Restage. yield from bps.unstage(self.device) # restore numcapture and shutter_enabled yield from bps.mv(self.device.hdf5.num_capture, num_capture) yield from bps.mv(self.device.dg1.shutter_enabled, shutter_enabled) # Dark frames finished, moving on to data yield from bps.stage(self.device) status = yield from bps.trigger(self.device, group='primary-trigger') while not status.done: yield from bps.trigger_and_read(self.async_poll_devices, name='labview') yield from bps.sleep(1) yield from bps.create('primary') yield from bps.read(self.device) yield from bps.save() yield from bps.unstage(self.device)
def _snap(md=None): yield from bps.open_run(md) yield from bps.create(name=stream) for obj in objects: # passive observation: DO NOT TRIGGER, only read yield from bps.read(obj) yield from bps.save() yield from bps.close_run()
def fly_row(): # go to start of row target_y = ystart + y * a_ystep_size yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, target_y) yield from bps.mv(y_centers, np.ones(num_xpixels) * target_y) # set the fly speed # ret = yield from bps.read(xy_fly_stage.z.user_readback) # (in mm) # revised by YDu, no such value before #yield from bps.sleep(0) # zpos = ( # ret[xy_fly_stage.z.user_readback.name]["value"] # if ret is not None # else 0 # ) # yield from bps.mov(z_centers, np.ones(num_xpixels) * zpos) yield from bps.mv(xy_fly_stage.x.velocity, flyspeed) yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") # arm the struck yield from bps.trigger(sclr, group=f"fly_row_{y}") # maybe start the xspress3 if xspress3 is not None: yield from bps.trigger(xspress3, group=f"fly_row_{y}") # revised by YDu, use to be 0.1 yield from bps.sleep(1.5) # fly the motor yield from bps.abs_set(xy_fly_stage.x, xstop + a_xstep_size, group=f"fly_row_{y}") yield from bps.wait(group=f"fly_row_{y}") # yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") yield from bps.mv(xy_fly_stage.x.velocity, 5.0) # revised by YDu, use to be 0.1 yield from bps.sleep(0.1) # read and save the struck yield from bps.create(name="primary") # yield from bps.read(sclr) yield from bps.read(mono) yield from bps.read(x_centers) yield from bps.read(y_centers) yield from bps.read(z_centers) yield from bps.read(xy_fly_stage.y) yield from bps.read(xy_fly_stage.z) # and maybe the xspress3 if xspress3 is not None: yield from bps.read(xspress3) yield from bps.sleep(0.2) yield from bps.save() yield from bps.sleep(0.2)
def _scan(md=None): yield from bps.open_run(md) position_list = np.linspace(start, finish, num) signal_list = list(self.signals) signal_list += [ self.axis, ] for pos in position_list: yield from bps.mv(self.axis, pos) yield from bps.trigger_and_read(signal_list) final_position = initial_position if self.peak_detected(): self.tune_ok = True if self.peak_choice == "cen": final_position = self.peaks.cen elif self.peak_choice == "com": final_position = self.peaks.com else: final_position = None self.center = final_position # add stream with results # yield from add_results_stream() stream_name = "PeakStats" results = Results(name=stream_name) results.tune_ok.put(self.tune_ok) results.center.put(self.center) results.final_position.put(final_position) results.initial_position.put(initial_position) for key in results.peakstats_attrs: v = getattr(self.peaks, key) if key in ("crossings", "min", "max"): v = np.array(v) getattr(results, key).put(v) if results.tune_ok.get(): yield from bps.create(name=stream_name) try: yield from bps.read(results) except ValueError as ex: separator = " " * 8 + "-" * 12 print(separator) print(f"Error saving stream {stream_name}:\n{ex}") print(separator) yield from bps.save() yield from bps.mv(self.axis, final_position) self.stats.append(self.peaks) yield from bps.close_run() results.report(stream_name)
def _scan(md=None): yield from bps.open_run(md) position_list = np.linspace(start, finish, num) signal_list = list(self.signals) signal_list += [ self.axis, ] for pos in position_list: yield from bps.mv(self.axis, pos) yield from bps.trigger_and_read(signal_list) final_position = initial_position if self.peak_detected(): self.tune_ok = True if self.peak_choice == "cen": final_position = self.peaks.cen elif self.peak_choice == "com": final_position = self.peaks.com else: final_position = None self.center = final_position # add stream with results # yield from add_results_stream() stream_name = "PeakStats" results = Results(name=stream_name) for key in "tune_ok center".split(): getattr(results, key).put(getattr(self, key)) results.final_position.put(final_position) results.initial_position.put(initial_position) for key in results.peakstats_attrs: v = getattr(self.peaks, key) if key in ("crossings", "min", "max"): v = np.array(v) getattr(results, key).put(v) if results.tune_ok.value: yield from bps.create(name=stream_name) yield from bps.read(results) yield from bps.save() yield from bps.mv(self.axis, final_position) self.stats.append(self.peaks) yield from bps.close_run() results.report()
def dull_scan(mot, count, sig=None, sleep_time=0): if sig: thread = threading.Thread(target=sig_sequence, args=(sig, )) thread.start() for i in range(count): yield from checkpoint() try: yield from mv(mot, i) except: pass # make every step take 1s extra yield from sleep(sleep_time) yield from checkpoint() yield from create() yield from read(mot) yield from save() yield from checkpoint()
def fly_row(): # go to start of row target_y = ystart + y * a_ystep_size yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, target_y) yield from bps.mv(y_centers, np.ones(num_xpixels) * target_y) # set the fly speed ret = yield from bps.read(xy_fly_stage.z.user_readback) # (in mm) zpos = (ret[xy_fly_stage.z.user_readback.name]["value"] if ret is not None else 0) yield from bps.mov(z_centers, np.ones(num_xpixels) * zpos) yield from bps.mv(xy_fly_stage.x.velocity, flyspeed) yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") for v in ["p1600=0", "p1600=1"]: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the struck yield from bps.trigger(sclr, group=f"fly_row_{y}") # maybe start the xspress3 # fly the motor yield from bps.abs_set(xy_fly_stage.x, xstop + a_xstep_size, group=f"fly_row_{y}") yield from bps.wait(group=f"fly_row_{y}") yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") yield from bps.mv(xy_fly_stage.x.velocity, 5.0) yield from bps.sleep(0.1) # read and save the struck yield from bps.create(name="primary") # yield from bps.read(sclr) yield from bps.read(mono) yield from bps.read(x_centers) yield from bps.read(y_centers) yield from bps.read(z_centers) yield from bps.read(xy_fly_stage.y) yield from bps.read(xy_fly_stage.z) # and maybe the xspress3 yield from bps.save()
def inner_trigger_and_read(): nonlocal group if group is None: group = short_uid('trigger') no_wait = True for obj in devices: if hasattr(obj, 'trigger'): no_wait = False yield from bps.trigger(obj, group=group) # Skip 'wait' if none of the devices implemented a trigger method. if not no_wait: yield from bps.wait(group=group) yield from bps.create(name) ret = {} # collect and return readings to give plan access to them for obj in devices: reading = (yield from bps.read(obj)) if reading is not None: ret.update(reading) yield from bps.save() return ret
def documentation_run(words, md=None, stream=None): """ Save text as a bluesky run. """ text = Signal(value=words, name="text") stream = stream or "primary" _md = dict( purpose=f"save text as bluesky run", plan_name="documentation_run", ) _md.update(md or {}) bec.disable_plots() bec.disable_table() uid = yield from bps.open_run(md=_md) yield from bps.create(stream) yield from bps.read(text) yield from bps.save() yield from bps.close_run() bec.enable_table() bec.enable_plots() return uid
def fly_once(y): # for y in range(num_scans): # go to start of row yield from bps.checkpoint() yield from bps.mv(mono.linear.velocity, 1) yield from bps.mv(mono.linear, l_start) # set the fly speed yield from bps.mv(mono.linear.velocity, flyspeed) yield from bps.trigger_and_read([mono], name="row_ends") for v in ["p1600=0", "p1600=1"]: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the Struck yield from bps.trigger(sclr, group=f"fly_energy_{y}") if xspress3 is not None: yield from bps.trigger(xspress3, group=f"fly_energy_{y}") # fly the motor yield from bps.abs_set(mono.linear, l_stop + a_l_step_size, group=f"fly_energy_{y}") yield from bps.wait(group=f"fly_energy_{y}") yield from bps.trigger_and_read([mono], name="row_ends") yield from bps.mv(mono.linear.velocity, flyspeed) # hard coded to let the sclr count its fingers and toes yield from bps.sleep(0.1) # read and save the struck yield from bps.create(name="primary") yield from bps.read(sclr) if xspress3 is not None: yield from bps.read(xspress3) yield from bps.save()
def fly_row(): # go to start of row yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, ystart + y * ystep_size) # set the fly speed yield from bps.mv(xy_fly_stage.x.velocity, flyspeed) yield from bps.trigger_and_read([xy_fly_stage], name='row_ends') for v in ['p1600=0', 'p1600=1']: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the struck yield from bps.trigger(sclr, group=f'fly_row_{y}') # maybe start the xspress3 if xspress3 is not None: yield from bps.trigger(xspress3, group=f'fly_row_{y}') yield from bps.sleep(0.1) # fly the motor yield from bps.abs_set(xy_fly_stage.x, xstop + a_xstep_size, group=f'fly_row_{y}') yield from bps.wait(group=f'fly_row_{y}') yield from bps.trigger_and_read([xy_fly_stage], name='row_ends') yield from bps.mv(xy_fly_stage.x.velocity, 5.0) yield from bps.sleep(.1) # read and save the struck yield from bps.create(name='primary') yield from bps.read(sclr) # and maybe the xspress3 if xspress3 is not None: yield from bps.read(xspress3) yield from bps.save()
def sscan_1D( sscan, poll_delay_s=0.001, phase_timeout_s = 60.0, running_stream="primary", final_array_stream=None, device_settings_stream="settings", md=None): """ simple 1-D scan using EPICS synApps sscan record assumes the sscan record has already been setup properly for a scan PARAMETERS sscan : Device one EPICS sscan record (instance of `apstools.synApps.sscanRecord`) running_stream : str or `None` (default: ``"primary"``) Name of document stream to write positioners and detectors data made available while the sscan is running. This is typically the scan data, row by row. If set to `None`, this stream will not be written. final_array_stream : str or `None` (default: ``None``) Name of document stream to write positioners and detectors data posted *after* the sscan has ended. If set to `None`, this stream will not be written. device_settings_stream : str or `None` (default: ``"settings"``) Name of document stream to write *settings* of the sscan device. This is all the information returned by ``sscan.read()``. If set to `None`, this stream will not be written. poll_delay_s : float (default: 0.001 seconds) How long to sleep during each polling loop while collecting interim data values and waiting for sscan to complete. Must be a number between zero and 0.1 seconds. phase_timeout_s : float (default: 60 seconds) How long to wait after last update of the ``sscan.FAZE``. When scanning, we expect the scan phase to update regularly as positioners move and detectors are triggered. If the scan hangs for some reason, this is a way to end the plan early. To cancel this feature, set it to ``None``. NOTE about the document stream names Make certain the names for the document streams are different from each other. If you make them all the same (such as ``primary``), you will have difficulty when reading your data later on. *Don't cross the streams!* EXAMPLE Assume that the chosen sscan record has already been setup. from apstools.devices import sscanDevice scans = sscanDevice(P, name="scans") from apstools.plans import sscan_1D RE(sscan_1D(scans.scan1), md=dict(purpose="demo")) """ global new_data, inactive_deadline if not (0 <= poll_delay_s <= 0.1): raise ValueError( "poll_delay_s must be a number between 0 and 0.1," f" received {poll_delay_s}") t0 = time.time() sscan_status = DeviceStatus(sscan.execute_scan) started = False new_data = False inactive_deadline = time.time() if phase_timeout_s is not None: inactive_deadline += phase_timeout_s def execute_cb(value, timestamp, **kwargs): """watch for sscan to complete""" if started and value in (0, "IDLE"): sscan_status._finished() sscan.execute_scan.unsubscribe_all() sscan.scan_phase.unsubscribe_all() def phase_cb(value, timestamp, **kwargs): """watch for new data""" global new_data, inactive_deadline if phase_timeout_s is not None: inactive_deadline = time.time() + phase_timeout_s if value in (15, "RECORD SCALAR DATA"): new_data = True # set flag for main plan # acquire only the channels with non-empty configuration in EPICS sscan.select_channels() # pre-identify the configured channels sscan_data_objects = _get_sscan_data_objects(sscan) # watch for sscan to complete sscan.execute_scan.subscribe(execute_cb) # watch for new data to be read out sscan.scan_phase.subscribe(phase_cb) _md = dict(plan_name="sscan_1D") _md.update(md or {}) yield from bps.open_run(_md) # start data collection yield from bps.mv(sscan.execute_scan, 1) # start sscan started = True # collect and emit data, wait for sscan to end while not sscan_status.done or new_data: if new_data and running_stream is not None: yield from bps.create(running_stream) for _k, obj in sscan_data_objects.items(): yield from bps.read(obj) yield from bps.save() new_data = False if phase_timeout_s is not None and time.time() > inactive_deadline: print(f"No change in sscan record for {phase_timeout_s} seconds.") print("ending plan early as unsuccessful") sscan_status._finished(success=False) yield from bps.sleep(poll_delay_s) # dump the complete data arrays if final_array_stream is not None: yield from bps.create(final_array_stream) # we have to search for the arrays since they have ``kind="omitted"`` # (which means they do not get reported by the ``.read()`` method) for part in (sscan.positioners, sscan.detectors): for nm in part.read_attrs: if "." not in nm: # TODO: write just the acquired data, not the FULL arrays! yield from bps.read(getattr(part, nm).array) yield from bps.save() # dump the entire sscan record into another stream if device_settings_stream is not None: yield from bps.create(device_settings_stream) yield from bps.read(sscan) yield from bps.save() yield from bps.close_run() elapsed = time.time() - t0 print(f"total time for sscan_1D: {elapsed} s") return sscan_status
def custom(detector): for i in range(3): yield from create() yield from read(detector) yield from save()
def plan(reader, expected): for i in range(10): yield from create() assert daq.state == expected yield from read(reader) yield from save()