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 grid_fly(flyer, y, ystart, ystop, ynum, x, xstart, xstop, xnum): generator = CompoundGenerator( generators=[ LineGenerator(y.name, "mm", ystart, ystop, ynum), LineGenerator(x.name, "mm", xstart, xstop, xnum), ], duration=0.1, ) mapping.configure(dict(generator=generator)) md = dict( hints=dict( gridding="rectilinear", dimensions=[([y.name], "primary"), ([x.name], "primary")], ), shape=(ynum, xnum), extents=([ystart, ystop], [xstart, xstop]), ) uid = yield from bps.open_run(md) yield from bps.kickoff(flyer, wait=True) yield from bps.collect(flyer, stream=True) yield from bps.checkpoint() yield from bps.complete(flyer, group="flyer") for _ in range(int(ynum * xnum * 0.1)): yield from bps.sleep(1) yield from bps.collect(flyer, stream=True) yield from bps.checkpoint() yield from bps.wait(group="flyer") yield from bps.collect(flyer, stream=True) yield from bps.close_run() return uid
def measure_plan(detectors): yield from open_run() ret = yield from measure_average(detectors, num=250) assert ret['motor'] == 0.0 assert ret['motor_setpoint'] == 0.0 assert np.isclose(ret['noisy_det'], 1.0, atol=0.01) yield from close_run()
def set_and_fly(filepaths, flyers, sleeptime=10): ''' Fly on flyers with file prefix for a certain sleep time. fileprefix: file prefix sleeptime : sleep time to let flyer run for I've written this manually for now. ''' # set the file paths for filepath, flyer in zip(filepaths, flyers): yield from bps.abs_set(flyer.filepath, filepath) yield from bps.open_run() for flyer in flyers: yield from bps.stage(flyer) grp = str(uuid4()) for flyer in flyers: yield from bps.kickoff(flyer, group=grp, wait=False) yield from bps.wait(group=grp) yield from bps.sleep(sleeptime) for flyer in flyers: yield from bps.complete(flyer, group=grp, wait=False) for flyer in flyers: yield from bps.collect(flyer) for flyer in flyers: yield from bps.unstage(flyer) yield from bps.close_run()
def gss(): global region_limits yield from open_run() region_limits = yield from golden_section_search(sig, motor, 0.01, limits=(-10, 5)) yield from close_run()
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 measure_plan(detectors): yield from open_run() ret = yield from measure_average(detectors, num=250) logger.debug('Test received %s from measure_average', str(ret)) assert ret['motor'] == 0.0 assert ret['motor_setpoint'] == 0.0 assert np.isclose(ret['noisy_det'], 1.0, atol=0.1) yield from close_run()
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 manual_count(det=eiger1m_single): detectors = [det] for det in detectors: yield from stage(det) yield from open_run() print("All slow setup code has been run. " "Type RE.resume() when ready to acquire.") yield from pause() yield from trigger_and_read(detectors) yield from close_run() for det in detectors: yield from unstage(det)
def interlaced_plan(dets, motor): to_read = (motor, *dets) run_ids = list("abc") for rid in run_ids: yield from drw(bps.open_run(md={rid: rid}), run=rid) for j in range(5): for i, rid in enumerate(run_ids): yield from bps.mov(motor, j + 0.1 * i) yield from drw(bps.trigger_and_read(to_read), run=rid) for rid in run_ids: yield from drw(bps.close_run(), run=rid)
def interlaced_plan(dets, motor): to_read = (motor, *dets) run_names = ["run_one", "run_two", "run_three"] for rid in run_names: yield from srkw(bps.open_run(md={rid: rid}), run=rid) for j in range(5): for i, rid in enumerate(run_names): yield from bps.mov(motor, j + 0.1 * i) yield from srkw(bps.trigger_and_read(to_read), run=rid) for rid in run_names: yield from srkw(bps.close_run(), run=rid)
def filter_opt_count(det, target_count=100000, md={}): """ filter_opt_count OPtimize counts using filters Assumes mu=0.2, x = [0.89, 2.52, 3.83, 10.87] I = I_o \exp(-mu*x) Only takes one detector, since we are optimizing based on it alone target is mean+2std """ dc = DocumentCache() token = yield from bps.subscribe('all', dc) yield from bps.stage(det) md = {} yield from bps.open_run(md=md) # BlueskyRun object allows interaction with documents similar to db.v2, # but documents are in memory run = BlueskyRun(dc) yield from bps.trigger_and_read([det, filter1, filter2, filter3, filter4]) data = run.primary.read()['pilatus300k_image'] mean = data[-1].mean().values.item() # xarray.DataArray methods std = data[-1].std().values.item() # xarray.DataArray methods curr_counts = mean + 2 * std # gather filter information and solve filter_status = [ round(filter1.get() / 5), round(filter2.get() / 5), round(filter3.get() / 5), round(filter4.get() / 5) ] print(filter_status) filter_status = [not e for e in filter_status] new_filters = solve_filter_setup(filter_status, curr_counts, target_count) # invert again to reflect filter status new_filters = [not e for e in new_filters] print(new_filters) # set new filters and read. For some reason hangs on bps.mv when going high filter1.put(new_filters[0] * 4.9) filter2.put(new_filters[1] * 4.9) filter3.put(new_filters[2] * 4.9) filter4.put(new_filters[3] * 4.9) yield from bps.trigger_and_read([det, filter1, filter2, filter3, filter4]) # close out run yield from bps.close_run() yield from bps.unsubscribe(token) yield from bps.unstage(det)
def plan(): yield from bps.open_run() yield from bps.stage(det) yield from bps.mv(det.exposure_time, 0.01) yield from bps.trigger_and_read([det]) # should prompt new dark Event yield from bps.trigger_and_read([det]) yield from bps.mv(det.exposure_time, 0.02) yield from bps.trigger_and_read([det]) # should prompt new dark Event yield from bps.trigger_and_read([det]) yield from bps.mv(det.exposure_time, 0.01) yield from bps.trigger_and_read([det]) # should prompt new dark Event yield from bps.trigger_and_read([det]) yield from bps.trigger_and_read([det]) yield from bps.unstage(det) yield from bps.close_run()
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 plan(threshold): yield from bps.open_run() yield from bps.kickoff(det, wait=True) target_pos = -3.0 while True: yield from bps.mv(pos, target_pos) yield from bps.sleep(0.1) # fake motor delay payload = yield from bps.collect(det, stream=True) for reading in payload: x = reading['data']['x'] historical_pos = reading['data']['pos'] print( f"current={target_pos:.3} historical={historical_pos:.3} x={x:.3}" ) if x > threshold: yield from bps.close_run() print("DONE!") return target_pos += 0.1
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 plan(): yield from open_run(md={'a': 1})
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 plan(self, md={}): """ run the USAXS fly scan """ bluesky_runengine_running = RE.state != "idle" def _report_(t): elapsed = struck.elapsed_real_time.get() channel = None if elapsed is not None: channel = struck.current_channel.get() if elapsed > t: # looking at previous fly scan elapsed = 0 channel = 0 terms.FlyScan.elapsed_time.put(elapsed) # for our GUI display values = [ f"{t:.2f}", ] values.append(f"{a_stage.r.position:.7f}") values.append(f"{a_stage.y.position:.5f}") values.append(f"{d_stage.y.position:.5f}") missing = "-missing-" if channel is None: values.append(missing) else: values.append(f"{channel}") if elapsed is None: values.append(missing) else: values.append(f"{elapsed:.2f}") # values.append(resource_usage()) return " ".join([f"{s:11}" for s in values]) @run_in_thread def progress_reporting(): logger.debug("progress_reporting has arrived") t = time.time() timeout = t + self.scan_time.get( ) + self.timeout_s # extra padded time startup = t + self.update_interval_s / 2 while t < startup and not self.flying.get( ): # wait for flyscan to start time.sleep(0.01) labels = ("flying, s", "ar, deg", "ay, mm", "dy, mm", "channel", "elapsed, s") logger.info(" ".join([f"{s:11}" for s in labels])) while t < timeout and self.flying.get(): if t > self.update_time: self.update_time = t + self.update_interval_s msg = _report_(t - self.t0) logger.debug(msg) time.sleep(0.01) t = time.time() msg = _report_(time.time() - self.t0) logger.info(msg) # user_data.set_state_blocking(msg.split()[0]) if t > timeout: logger.error( f"{time.time()-self.t0}s - progress_reporting timeout!!") else: logger.debug( f"{time.time()-self.t0}s - progress_reporting is done") @run_in_thread def prepare_HDF5_file(): fname = os.path.abspath(self.saveFlyData_HDF5_dir) if not os.path.exists(fname): msg = f"Must save fly scan data to an existing directory. Gave {fname}" fname = os.path.abspath(self.fallback_dir) msg += f" Using fallback directory {self.fallback_dir}" logger.error(msg) s = self.saveFlyData_HDF5_file _s_ = os.path.join(fname, s) # for testing here if os.path.exists(_s_): msg = f"File {_s_} exists. Will not overwrite." s = datetime.datetime.isoformat(datetime.datetime.now(), sep="_").split(".")[0] s = s.replace(":", "").replace("-", "") # s = "flyscan_" + s + ".h5" _s_ = os.path.join(fname, s) msg += f" Using fallback file name {_s_}" logger.error(msg) fname = os.path.join(fname, s) logger.info(f"HDF5 config: {self.saveFlyData_config}") logger.info(f"HDF5 output: {fname}") self._output_HDF5_file_ = fname user_data.set_state_blocking("FlyScanning: " + os.path.split(fname)[-1]) # logger.debug(resource_usage("before SaveFlyScan()")) self.saveFlyData = SaveFlyScan(fname, config_file=self.saveFlyData_config) # logger.debug(resource_usage("before saveFlyData.preliminaryWriteFile()")) self.saveFlyData.preliminaryWriteFile() # logger.debug(resource_usage("after saveFlyData.preliminaryWriteFile()")) @run_in_thread def finish_HDF5_file(): if self.saveFlyData is None: raise RuntimeError("Must first call prepare_HDF5_file()") self.saveFlyData.saveFile() logger.info(f"HDF5 output complete: {self._output_HDF5_file_}") self.saveFlyData = None ###################################################################### # plan starts here global specwriter # remember our starting conditions self.ar0 = a_stage.r.position self.ay0 = a_stage.y.position self.dy0 = d_stage.y.position _md = OrderedDict() _md.update(md or {}) _md["hdf5_file"] = self.saveFlyData_HDF5_file _md["hdf5_path"] = self.saveFlyData_HDF5_dir yield from bps.open_run(md=_md) specwriter._cmt("start", "start USAXS Fly scan") yield from bps.mv( upd_controls.auto.mode, AutorangeSettings.auto_background, ) self.t0 = time.time() self.update_time = self.t0 + self.update_interval_s if self.flying.get(): yield from bps.abs_set(self.flying, False) else: logger.warning("Was not flying but should be.") if bluesky_runengine_running: prepare_HDF5_file( ) # prepare HDF5 file to save fly scan data (background thread) # path = os.path.abspath(self.saveFlyData_HDF5_dir) specwriter._cmt("start", f"HDF5 configuration file: {self.saveFlyData_config}") g = uuid.uuid4() yield from bps.abs_set( self.busy, BusyStatus.busy, group=g, # waits until done timeout=self.scan_time.get() + self.timeout_s) if bluesky_runengine_running: progress_reporting() if self.flying._status is not None and not self.flying._status.done: # per https://github.com/APS-USAXS/ipython-usaxs/issues/499 logger.warning( "Clearing unfinished status object on 'usaxs_flyscan/flying'") self.flying._status.set_finished() if not self.flying.get(): yield from bps.abs_set(self.flying, True) else: logger.warning("Already flying, should not be flying now.") yield from bps.wait(group=g) if not self.flying.get(): yield from bps.abs_set(self.flying, False) else: logger.warning( "Already flying (after wait), should not be flying now.") elapsed = time.time() - self.t0 specwriter._cmt("stop", f"fly scan completed in {elapsed} s") if bluesky_runengine_running: msg = f"writing fly scan HDF5 file: {self._output_HDF5_file_}" logger.debug(msg) try: yield from user_data.set_state_plan( "writing fly scan HDF5 file") except Exception as exc: # do not fail the scan just because of updating program state logger.warning("Non-fatal error while %s\n%s\nPlan continues", msg, exc) # FIXME: hack to avoid `Another set() call is still in progress` # see: https://github.com/APS-USAXS/ipython-usaxs/issues/417 user_data.state._set_thread = None # logger.debug(resource_usage("before saveFlyData.finish_HDF5_file()")) finish_HDF5_file( ) # finish saving data to HDF5 file (background thread) # logger.debug(resource_usage("after saveFlyData.finish_HDF5_file()")) specwriter._cmt("stop", f"finished {msg}") logger.info(f"finished {msg}") yield from bps.mv( a_stage.r.user_setpoint, self.ar0, a_stage.y.user_setpoint, self.ay0, d_stage.y.user_setpoint, self.dy0, upd_controls.auto.mode, AutorangeSettings.auto_background, ti_filter_shutter, "close", ) yield from addDeviceDataAsStream( [struck.mca1, struck.mca2, struck.mca3], "mca") logger.debug(f"after return: {time.time() - self.t0}s") yield from user_data.set_state_plan("fly scan finished") yield from bps.close_run()
def interlaced_plan(dets, motor): run_ids = list("abc") for rid in run_ids: yield from drw(bps.open_run(md={rid: rid}), run=rid) raise Exception("womp womp")
def plan_simultaneously(x_centroid, y_centroid, x, y, atol, x_target=None, y_target=None): """ This BlueSky plan aligns the laser's centroid with the x-ray's centroid. This plan implements 'walk_to_pixel' from the pswalker (a beam alignment module). The plan uses an iterative procedure to align any beam to a position on a screen, when two motors move the beam along the two axes. Liveplots are updated and show the paths taken to achieve alignment. Parameters ---------- x_centroid, y_centroid : These represent the x_centroid and y_centroid x, y: These respresnt the x_motor and y_motor x_target, y_target : int Target value on the x-axis and y-axis """ #Create a figure fig = plt.figure(figsize=(15, 10)) fig.subplots_adjust(hspace=0.3, wspace=0.4) #The first subplot, which plots the y_centroid vs x_centroid ax1 = fig.add_subplot(2, 2, 1) ax1.invert_yaxis() x_centroid_y_centroid = LivePlot(y_centroid.name, x_centroid.name, ax=ax1, marker='x', markersize=7, color='orange') #The second subplot, which plots the y_centroid and x_centroid with same x-axis (y_motor) ax2 = fig.add_subplot(2, 2, 3) ax2.set_ylabel(y_centroid.name, color='red') ax3 = ax2.twinx() # ax2.invert_yaxis() # ax3.invert_yaxis() ax3.set_ylabel(x_centroid.name, color='blue') y_plot_y_centroid = LivePlot(y_centroid.name, y.name, ax=ax2, marker='x', markersize=6, color='red') y_plot_x_centroid = LivePlot(x_centroid.name, y.name, ax=ax3, marker='o', markersize=6, color='blue') #The third subplot, which plots the y_centroid and x_centroid with same x-axis (x_motor) ax4 = fig.add_subplot(2, 2, 4) ax4.set_ylabel(y_centroid.name, color='green') ax5 = ax4.twinx() ax5.set_ylabel(x_centroid.name, color='purple') x_plot_y_centroid = LivePlot(y_centroid.name, x.name, ax=ax4, marker='x', markersize=6, color='green') x_plot_x_centroid = LivePlot(x_centroid.name, x.name, ax=ax5, marker='o', markersize=6, color='purple') #Subscribe the plots token_x_centroid_y_centroid = yield from subscribe('all', x_centroid_y_centroid) token_y_plot_x_centroid = yield from subscribe('all', y_plot_x_centroid) token_y_plot_y_centroid = yield from subscribe('all', y_plot_y_centroid) token_x_plot_x_centroid = yield from subscribe('all', x_plot_x_centroid) token_x_plot_y_centroid = yield from subscribe('all', x_plot_y_centroid) #Start a new run yield from open_run( md={ 'detectors': [(x_centroid.name), (y_centroid.name)], 'motors': [(x.name), (y.name)], 'hints': { 'dimensions': [(x.hints['fields'], 'primary'), (y.hints['fields'], 'primary')] } }) #Ask for the target values if x_target is None: x_target = int(input('Enter the x value: ')) if y_target is None: y_target = int(input('Enter the y value: ')) #Iteratively move until x_target and x-centroid are within a certain threshold of each other while True: if not np.isclose(x_target, x_centroid.get(), atol): yield from walk_to_pixel(x_centroid, x, x_target, first_step=0.1, target_fields=[x_centroid.name, x.name], tolerance=atol, average=5, system=[y, y_centroid]) elif not np.isclose(y_target, y_centroid.get(), atol): yield from walk_to_pixel(y_centroid, y, y_target, first_step=0.1, tolerance=atol, average=5, target_fields=[y_centroid.name, y.name], system=[x, x_centroid]) else: break # plt.show(block=True) #Close the run yield from close_run() #Unsubscribe the plots yield from unsubscribe(token_x_centroid_y_centroid) yield from unsubscribe(token_y_plot_x_centroid) yield from unsubscribe(token_y_plot_y_centroid) yield from unsubscribe(token_x_plot_x_centroid) yield from unsubscribe(token_x_plot_y_centroid)
def tfs_scan(start, stop): yield from open_run() yield from mv(tfs_trans, start) yield from mv(tfs_trans, stop) yield from close_run()
def move_and_count(motor, target): yield from bps.open_run(None) yield from bps.mv(motor, target) yield from bps.close_run()
def interlaced_plan(dets, motor): run_names = ["run_one", "run_two", "run_three"] for rid in run_names: yield from srkw(bps.open_run(md={rid: rid}), run=rid) raise Exception("womp womp")
def pe_count( filename="", exposure=1, num_images: int = 1, num_dark_images: int = 1, num_repetitions: int = 5, delay=60, ): year = "2020" # RE.md["year"] cycle = "C2" # RE.md["cycle"] proposal = "67890" # RE.md["PROPOSAL"] # write_path_template = 'Z:\\data\\pe1_data\\%Y\\%m\\%d\\' # write_path_template = f"Z:\\users\\{year}\\{cycle}\\{proposal}XRD\\" # file_path = datetime.now().strftime(write_path_template) # filename = filename + str(uuid.uuid4())[:6] # this is an example of what would be used at the beamline pe_detector.tiff_writer.resource_root_path = PureWindowsPath( f"Z:\\users\\") pe_detector.tiff_writer.relative_write_path = PureWindowsPath( f"{year}\\{cycle}\\{proposal}XRD\\") # for testing pe_detector.tiff_writer.resource_root_path = Path("/tmp/") pe_detector.tiff_writer.relative_write_path = Path( f"perkin_elmer/detector/{year}/{cycle}/XRD{proposal}" # remove "XRD" from the end? ) # start the run yield from bps.open_run() # stage the detector yield from bps.stage(pe_detector) yield from bps.mv(pe_detector.tiff_writer.file_number, 1) tiff_full_file_path = (pe_detector.tiff_writer.resource_root_path / pe_detector.tiff_writer.relative_write_path) print(f"tiff_full_file_path: {str(tiff_full_file_path)}") yield from bps.mv(pe_detector.tiff_writer.file_path, str(tiff_full_file_path)) for repetition_index in range(int(num_repetitions)): print("\n") print( "<<<<<<<<<<<<<<<<< Doing repetition {} out of {} >>>>>>>>>>>>>>>>>" .format(repetition_index + 1, num_repetitions)) # TiffWriter or similar plugin should do this yield from bps.mv(pe_detector.tiff_writer.file_name, filename + str(uuid.uuid4())) if num_dark_images > 0: # originally used pe_detector.num_dark_images # but this is really pe_num_offset_frames yield from bps.mv(pe_detector.cam.pe_num_offset_frames, num_dark_images) yield from bps.mv( pe_detector.cam.image_mode, PerkinElmerCamera.PerkinElmerImageMode.AVERAGE, ) # yield from bps.mv(fast_shutter, "Close") yield from bps.sleep(0.5) yield from bps.mv(pe_detector.tiff_writer.file_write_mode, NDFile.FileWriteMode.SINGLE) # acquire a "dark frame" pe_acquire_offset_status = SubscriptionStatus( pe_detector.cam.pe_acquire_offset, high_to_low_pe_acquire_offset) yield from bps.abs_set( pe_detector.cam.pe_acquire_offset, PerkinElmerCamera.AcquireOffset.ACQUIRE, wait=False, ) yield Msg("wait_for_status", None, pe_acquire_offset_status) yield from bps.mv(pe_detector.tiff_writer.write_file, NDFile.WriteFile.WRITE) # yield from bps.mv( # pe1.cam.image_mode, # NewPerkinElmerDetector.ImageMode.MULTIPLE # ) yield from bps.mv( pe_detector.cam.image_mode, PerkinElmerCamera.PerkinElmerImageMode.AVERAGE, ) yield from bps.mv(pe_detector.cam.acquire_time, exposure) yield from bps.mv(pe_detector.cam.num_images, num_images) # yield from bps.mv(fast_shutter, "Open") yield from bps.sleep(0.5) ## Below 'Capture' mode is used with 'Multiple' image_mode # yield from bps.mv(pe1.tiff_writer.file_write_mode, 'Capture') ## Below 'Single' mode is used with 'Average' image_mode yield from bps.mv( pe_detector.tiff_writer.file_write_mode, NDFile.FileWriteMode.SINGLE, # "Single" ) ## Uncomment 'capture' bit settings when used in 'Capture' mode # yield from bps.mv(pe1.tiff_writer.capture, 1) # this was the old way to initiate the acquisition # yield from bps.mv(pe_detector, "acquire_light") yield from bps.trigger_and_read([pe_detector], name="primary") # can TiffWriter or similar plugin do this? ##Below write_file is needed when used in 'Average' mode yield from bps.mv( pe_detector.tiff_writer.write_file, NDFile.WriteFile.WRITE # 1 ) yield from bps.sleep(delay) # unstage the detector yield from bps.unstage(pe_detector) # end the run yield from bps.close_run()
def plan(): yield from open_run() yield from stage(m) yield from unstage(m) yield from close_run()
def ud_crab_plan(pu, us_u, us_l, ds_u, ds_l, other_dets=None): '''A generator plan for crabbing the undulator to new position This is a single-use plan for moving the undulator to a new position :: plan = ud_crab_plan(pu, a, 6.46, 6.46, 6.46, [ut]) gs.RE(plan) This plan round-robin moves the motors to the desired positions taking readings of all the motor positions and any additional detectors and ~1Hz Parameters ---------- pu : PowerUndulator Bucket of undulator motors us_u : float The target upstream upper motor position us_l : float The target upstream lower motor position ds_u : float The target downstream upper motor position ds_l : float The target downstream lower motor position other_dets : list, optional List of other detectors to read ''' pu.stop() if other_dets is None: other_dets = [] # magic goes here #if abs(us_u - ds_u) > CRAB_LIMIT: if abs(us_u - ds_u) > TILT_LIMIT: raise ValueError("exceded tilt limit on upper |{} - {}| > {}".format( us_u, ds_u, TILT_LIMIT)) #if abs(us_l - ds_l) > CRAB_LIMIT: if abs(us_l - ds_l) > TILT_LIMIT: raise ValueError("exceded tilt limit on lower |{} - {}| > {}".format( us_l, ds_l, TILT_LIMIT)) def limit_position(pos, pair_pos, target, pair_target): if abs(pair_pos - pair_target) < TARGET_THRESH: # on final step limit = TILT_LIMIT else: limit = CRAB_LIMIT # moving out if target > pos: return min(target, pair_pos + limit) else: return max(target, pair_pos - limit) def traj(pu): while True: done_count = 0 # MOVE THE UPSTREAM UPPER cur_usu = pu.us_upper.position cur_dsu = pu.ds_upper.position if abs(cur_usu - us_u) > TARGET_THRESH: target = limit_position(cur_usu, cur_dsu, us_u, ds_u) yield pu.us_upper, target else: done_count += 1 # MOVE THE DOWNSTREAM UPPER cur_usu = pu.us_upper.position cur_dsu = pu.ds_upper.position if abs(cur_dsu - ds_u) > TARGET_THRESH: target = limit_position(cur_dsu, cur_usu, ds_u, us_u) yield pu.ds_upper, target else: done_count += 1 # MOVE THE UPSTREAM lower cur_usl = pu.us_lower.position cur_dsl = pu.ds_lower.position if abs(cur_usl - us_l) > TARGET_THRESH: target = limit_position(cur_usl, cur_dsl, us_l, ds_l) yield pu.us_lower, target else: done_count += 1 # MOVE THE DOWNSTREAM lower cur_usl = pu.us_lower.position cur_dsl = pu.ds_lower.position if abs(cur_dsl - ds_l) > TARGET_THRESH: target = limit_position(cur_dsl, cur_usl, ds_l, us_l) yield pu.ds_lower, target else: done_count += 1 if done_count == 4: return yield from open_run() yield from trigger_and_read([pu] + other_dets) for mot, target in traj(pu): print("About to move {} to {}".format(mot.name, target)) # yield Msg('checkpoint', None) # yield Msg('pause', None) # yield Msg('clear_checkpoint', None) st = yield Msg('set', mot, target, timeout=None) # move the motor # speed is mm / s measured on us lower 2016-06-02 # timeout is 3 * max_crab / speed fail_time = ttime.time() + (TILT_LIMIT / .0003) * 4 while not st.done: yield from trigger_and_read([pu] + other_dets) if ttime.time() > fail_time: mot.stop() raise RuntimeError("Undulator move timed out") yield Msg('checkpoint') yield Msg('sleep', None, 1) if st.error > .002: raise RuntimeError("only got with in {} of target {}". format(st.error, st.target)) yield Msg('checkpoint') for j in range(2): yield Msg('sleep', None, 1) yield from trigger_and_read([pu] + other_dets) yield Msg('checkpoint') yield from close_run()
def scan_closure(): # ------------------- # collect white field # ------------------- # 1-1 monitor shutter status, auto-puase scan if beam is lost yield from bps.open_run() yield from bps.mv(A_shutter, 'open') yield from bps.install_suspender(suspend_A_shutter) #1-1.5 configure output plugins edited by Jason 07/19/2019 for me in [det.tiff1, det.hdf1]: yield from bps.mv(me.file_path, fp) yield from bps.mv(me.file_name, fn) yield from bps.mv(me.file_write_mode, 2) yield from bps.mv(me.num_capture, total_images) yield from bps.mv( me.file_template, ".".join([r"%s%s_%06d", config['output']['type'].lower()])) if config['output']['type'] in ['tif', 'tiff']: yield from bps.mv(det.tiff1.enable, 1) yield from bps.mv(det.tiff1.capture, 1) yield from bps.mv(det.hdf1.enable, 0) elif config['output']['type'] in ['hdf', 'hdf1', 'hdf5']: yield from bps.mv(det.tiff1.enable, 0) yield from bps.mv(det.hdf1.enable, 1) yield from bps.mv(det.hdf1.capture, 1) else: raise ValueError(f"Unsupported output type {output_dict['type']}") # 1-2 move sample out of the way initial_samx = samX.position initial_samy = samY.position initial_preci = preci.position dx = config['tomo']['sample_out_position']['samX'] dy = config['tomo']['sample_out_position']['samY'] r = config['tomo']['sample_out_position']['preci'] yield from bps.mv(samX, initial_samx + dx) yield from bps.mv(samY, initial_samy + dy) yield from bps.mv(preci, r) # 1-2.5 set frame type for an organized HDF5 archive yield from bps.mv(det.cam.frame_type, 0) # 1-3 collect front white field images yield from bps.mv(det.hdf1.nd_array_port, 'PROC1') yield from bps.mv(det.tiff1.nd_array_port, 'PROC1') yield from bps.mv(det.proc1.enable, 1) yield from bps.mv(det.proc1.reset_filter, 1) yield from bps.mv(det.proc1.num_filter, n_frames) yield from bps.mv(det.cam.trigger_mode, "Internal") yield from bps.mv(det.cam.image_mode, "Multiple") yield from bps.mv(det.cam.num_images, n_frames * n_white) yield from bps.mv(det.cam.acquire_time, acquire_time) yield from bps.mv(det.cam.acquire_period, acquire_period) yield from bps.trigger_and_read([det]) # 1-4 move sample back yield from bps.mv(samX, initial_samx) yield from bps.mv(samY, initial_samy) #yield from bps.mv(preci, initial_preci) # ------------------- # collect projections # ------------------- # 1-5 set frame type for an organized HDF5 archive yield from bps.mv(det.cam.frame_type, 1) # 1-6 step and fly scan are differnt if config['tomo']['type'].lower() == 'step': yield from bps.mv(det.proc1.reset_filter, 1) yield from bps.mv(det.cam.num_images, n_frames) # 1-6 collect projections for ang in angs: yield from bps.checkpoint() yield from bps.mv(preci, ang) yield from bps.trigger_and_read([det]) elif config['tomo']['type'].lower() == 'fly': yield from bps.mv(det.proc1.num_filter, 1) yield from bps.mv(det.hdf1.nd_array_port, 'PG1') yield from bps.mv(det.tiff1.nd_array_port, 'PG1') yield from bps.mv( psofly.start, config['tomo']['omega_start'], psofly.end, config['tomo']['omega_end'], psofly.scan_delta, abs(config['tomo']['omega_step']), psofly.slew_speed, slew_speed, ) # taxi yield from bps.mv(psofly.taxi, "Taxi") # setup detector to overlap for fly scan yield from bps.mv( det.cam.num_images, n_projections, det.cam.trigger_mode, "Overlapped", ) # start the fly scan print("before trigger") yield from bps.trigger(det, group='trigger') print("waiting for trigger") # yield from bps.wait(group='trigger') print("before plan()") try: yield from psofly.plan() except NotEnoughTriggers as err: reason = ( f"{err.expected:.0f} were expected but {err.actual:.0f} were received." ) yield from bps.close_run('fail', reason=reason) return # short-circuit # fly scan finished. switch image port and trigger_mode back yield from bps.mv(det.cam.trigger_mode, "Internal") yield from bps.mv(det.hdf1.nd_array_port, 'PROC1') yield from bps.mv(det.tiff1.nd_array_port, 'PROC1') else: raise ValueError(f"Unknown scan type: {config['tomo']['type']}") # ------------------ # collect back white # ------------------ # 1-7 move the sample out of the way # NOTE: # this will return ALL motors to starting positions, we need a # smart way to calculate a shorter trajectory to move sample # out of way yield from bps.mv(preci, r) yield from bps.mv(samX, initial_samx + dx) yield from bps.mv(samY, initial_samy + dy) # 1-7.5 set frame type for an organized HDF5 archive yield from bps.mv(det.cam.frame_type, 2) # 1-8 take the back white yield from bps.mv(det.proc1.num_filter, n_frames) yield from bps.mv(det.cam.num_images, n_frames * n_white) yield from bps.trigger_and_read([det]) # 1-9 move sample back yield from bps.mv(samX, initial_samx) yield from bps.mv(samY, initial_samy) # ----------------- # collect back dark # ----------------- # 1-10 close the shutter yield from bps.remove_suspender(suspend_A_shutter) yield from bps.mv(A_shutter, "close") # 1-10.5 set frame type for an organized HDF5 archive yield from bps.mv(det.cam.frame_type, 3) # 1-11 collect the back dark yield from bps.mv(det.cam.num_images, n_frames * n_dark) yield from bps.trigger_and_read([det]) yield from bps.close_run('success')
def plan(): yield from open_run() yield from sleep(1) yield from pause() yield from close_run()