def _stage(): _heater_status = yield from rd(mag6t.field.switch_heater) if _heater_status != 'On': # Click current ramp button yield from mv(mag6t.field.ramp_button, 1) # Wait for the supply current to match the magnet. target = yield from rd(mag6t.field.current) function = _difference_check(target, tolerance=0.01) yield from abs_set(signal, mag6t.field.supply_current, function, wait=True) # Turn on persistance switch heater. yield from mv(mag6t.field.switch_heater, 'On') yield from sleep(2) # Wait for the heater to be on. function = _status_check(target=[3]) yield from abs_set(signal, mag6t.field.magnet_status, function, wait=True) # Click current ramp button yield from mv(mag6t.field.ramp_button, 1)
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 test_rd_fails(hw): require_ophyd_1_4_0() obj = hw.det obj.noise.kind = "hinted" hints = obj.hints.get("fields", []) msg = re.escape( f"Your object {obj} ({obj.name}.{obj.dotted_name}) " + f"has {len(hints)} items hinted ({hints}). We " ) with pytest.raises(ValueError, match=msg): list(bps.rd(obj)) obj.noise.kind = "normal" obj.val.kind = "normal" msg = re.escape( f"Your object {obj} ({obj.name}.{obj.dotted_name}) " + f"and has {len(obj.read_attrs)} read attrs. We " ) with pytest.raises(ValueError, match=msg): list(bps.rd(obj)) obj.read_attrs = [] msg = re.escape( f"Your object {obj} ({obj.name}.{obj.dotted_name}) " + f"and has {len(obj.read_attrs)} read attrs. We " ) with pytest.raises(ValueError, match=msg): list(bps.rd(obj))
def qxscan(edge_energy, time=None, *, detectors=None, md=None, dichro=False, lockin=False): """ Scan the beamline energy using variable step size. It reads the `qxscan_params` device. Prior to this scan, please run `qxscan_params.setup` or load setttings using `qxscan_params.load_params_json`. Parameters ---------- detectors : list list of 'readable' objects edge_energy : float Energy of the absorption edge. md : dict, optional metadata dichro : boolean, optional Flag to run a dichro energy scan. Please run pr_setup.config() prior to a dichro scan. Note that this will switch the x-ray polarization at every point using the +, -, -, + sequence, thus increasing the number of points, and time per energy, by a factor of 4 lockin : boolean, optional Flag to run a lockin energy scan. Please run pr_setup.config() prior to a lockin scan. See Also -------- :func:`moveE` :func:`Escan_list` :func:`Escan` """ if not detectors: detectors = counters.detectors # Scalerd is always selected. if scalerd not in detectors: scalerd.select_plot_channels([]) detectors += [scalerd] _md = {'plan_args': {'detectors': list(map(repr, detectors)), 'edge_energy': repr(edge_energy), 'dichro': dichro, 'lockin': lockin}, 'plan_name': 'qxscan' } _md.update(md or {}) energy_list = yield from rd(qxscan_params.energy_list) energy_list = array(energy_list) + edge_energy _factor_list = yield from rd(qxscan_params.factor_list) return (yield from Escan_list(detectors, energy_list, time, factor_list=_factor_list, md=_md, dichro=dichro, lockin=lockin))
def tester(obj): nonlocal called direct_read = yield from bps.read(obj) rd_read = yield from bps.rd(obj) sig_read = yield from bps.rd(obj.val) assert rd_read == direct_read["det"]["value"] assert sig_read == rd_read called = True
def dichro_steps(devices_to_read, take_reading): pr_pos = yield from rd(pr_setup.positioner) offset = yield from rd(pr_setup.offset) devices_to_read += [pr_setup.positioner] for sign in pr_setup.dichro_steps: yield from mv(pr_setup.positioner, pr_pos + sign * offset) yield from take_reading(devices_to_read) yield from mv(pr_setup.positioner, pr_pos)
def _collect_extras(escan_flag, fourc_flag): extras = counters.extra_devices.copy() if escan_flag: und_track = yield from rd(undulator.downstream.tracking) if und_track: extras.append(undulator.downstream.energy) for pr in [pr1, pr2, pr3]: pr_track = yield from rd(pr.tracking) if pr_track: extras.append(pr.th) if fourc_flag: extras.append(fourc) return extras
def setup(): if count_time < 0: if detectors != [scalerd]: raise ValueError('count_time can be < 0 only if the scalerd ' 'is only detector used.') else: if scalerd.monitor == 'Time': raise ValueError('count_time can be < 0 only if ' 'scalerd.monitor is not "Time".') original_times[scalerd] = yield from rd(scalerd.preset_monitor) yield from mv(scalerd.preset_monitor, abs(count_time)) elif count_time > 0: for det in detectors: if det == scalerd: original_monitor.append(scalerd.monitor) det.monitor = 'Time' original_times[det] = yield from rd(det.preset_monitor) yield from mv(det.preset_monitor, count_time) else: raise ValueError('count_time cannot be zero.')
def dark_plan(detector): # stash numcapture and shutter_enabled num_capture = yield from bps.rd(detector.hdf5.num_capture) shutter_enabled = yield from bps.rd(detector.dg1.shutter_enabled) # set to 1 temporarily detector.hdf5.num_capture.put(1) # Restage to ensure that dark frames goes into a separate file. yield from bps.unstage(detector) yield from bps.stage(detector) yield from bps.mv(detector.dg1.shutter_enabled, 2) # The `group` parameter passed to trigger MUST start with # bluesky-darkframes-trigger. yield from bps.trigger(detector, group='bluesky-darkframes-trigger') yield from bps.wait('bluesky-darkframes-trigger') snapshot = bluesky_darkframes.SnapshotDevice(detector) # Restage. yield from bps.unstage(detector) # restore numcapture and shutter_enabled yield from bps.mv(detector.hdf5.num_capture, num_capture) yield from bps.mv(detector.dg1.shutter_enabled, shutter_enabled) return snapshot
def qxscan(edge_energy, time=None, detectors=None, lockin=False, dichro=False, fixq=False, md=None): """ Energy scan with fixed delta_K steps. WARNING: please run qxscan_params.setup() before using this plan! It will use the parameters set in qxscan_params to determine the energy points. Parameters ---------- edge_energy : float Absorption edge energy. The parameters in qxscan_params offset by this energy. time : float, optional If a number is passed, it will modify the counts over time. All detectors need to have a .preset_monitor signal. detectors : list, optional List of detectors to be used in the scan. If None, will use the detectors defined in `counters.detectors`. lockin : boolean, optional Flag to do a lock-in scan. Please run pr_setup.config() prior do a lock-in scan dichro : boolean, optional Flag to do a dichro scan. Please run pr_setup.config() prior do a dichro scan. Note that this will switch the x-ray polarization at every point using the +, -, -, + sequence, thus increasing the number of points by a factor of 4 fixq : boolean, optional Flag for fixQ scans. If True, it will fix the diffractometer hkl position during the scan. Note that hkl is moved ~after~ the other motors! md : dictionary, optional Metadata to be added to the run start. See Also -------- :func:`bluesky.plans.scan` :func:`lup` """ if detectors is None: detectors = counters.detectors flag.dichro = dichro flag.fixq = fixq per_step = one_local_step if fixq or dichro else None # Get energy argument and extras energy_list = yield from rd(qxscan_params.energy_list) args = (energy, array(energy_list) + edge_energy) extras = yield from _collect_extras(energy in args, "fourc" in str(args)) # Setup count time factor_list = yield from rd(qxscan_params.factor_list) # TODO: The md handling might go well in a decorator. # TODO: May need to add reference to stream. _md = {'hints': {'monitor': counters.monitor, 'detectors': []}} for item in detectors: _md['hints']['detectors'].extend(item.hints['fields']) if dichro: _md['hints']['scan_type'] = 'dichro' _md.update(md or {}) _ct = {} if time: if time < 0 and detectors != [scalerd]: raise TypeError('time < 0 can only be used with scaler.') else: for det in detectors: _ct[det] = abs(time) args += (det.preset_monitor, abs(time) * array(factor_list)) else: for det in detectors: _ct[det] = yield from rd(det.preset_monitor) args += (det.preset_monitor, _ct[det] * array(factor_list)) @configure_counts_decorator(detectors, time) @stage_dichro_decorator(dichro, lockin) @extra_devices_decorator(extras) def _inner_qxscan(): yield from list_scan(detectors + extras, *args, per_step=per_step, md=_md) # put original times back. for det, preset in _ct.items(): yield from mv(det.preset_monitor, preset) return (yield from _inner_qxscan())
def tester(obj, val): yield from bps.mv(sig, val) ret = yield from bps.rd(obj, default_value=object()) assert ret == val
def tester(obj, dflt): ret = yield from bps.rd(obj, default_value=dflt) assert ret is dflt
def Escan_list(detectors, energy_list, count_time=None, *, factor_list=None, md=None, dichro=False, lockin=False): """ Scan the beamline energy using a list of energies. Due to the undulator backlash, it is recommended for energy_list to be in descending order. Parameters ---------- detectors : list list of 'readable' objects energy_list : iterable List of energies to be used factor_list: iterable, optional Controls the time per point by multiplying the initial count time by this factor. Needs to have the same length as energy_list. md : dict, optional metadata dichro : boolean, optional Flag to run a dichro energy scan. Please run pr_setup.config() prior to a dichro scan. Note that this will switch the x-ray polarization at every point using the +, -, -, + sequence, thus increasing the number of points, and time per energy, by a factor of 4 lockin : boolean, optional Flag to run a lockin energy scan. Please run pr_setup.config() prior to a lockin scan. See Also -------- :func:`moveE` :func:`Escan` :func:`qxscan` """ # Create positioners list _positioners = [mono.energy] if (yield from rd(undulator.downstream.tracking)): _positioners.append(undulator.downstream.energy) for pr in [pr1, pr2, pr3]: if pr.tracking.get(): _positioners.append(pr.th) for pr in [pr1, pr2, pr3]: if (yield from rd(pr.tracking)): _positioners.append(pr.th) _positioners.append(pr.energy) # Controls the time per point. if factor_list is None: factor_list = [1 for i in range(len(energy_list))] else: if len(factor_list) != len(energy_list): raise ValueError("The size of factor_list cannot be different " "from the size of the energy_list") # Metadata _md = {'detectors': [det.name for det in detectors], 'positioners': [pos.name for pos in _positioners], 'num_points': len(energy_list), 'num_intervals': len(energy_list) - 1, 'plan_args': {'detectors': list(map(repr, detectors)), 'energy_list': list(map(repr, energy_list))}, 'plan_name': 'Escan_list', 'hints': {'dimensions': [(['monochromator_energy'], 'primary')]}, } _md.update(md or {}) # Collects current monitor count for each detector dets_preset = [] for detector in detectors: if count_time: value = abs(count_time) else: value = yield from rd(detector.preset_monitor) dets_preset.append(value) @stage_dichro_decorator(dichro, lockin) @configure_counts_decorator(detectors, count_time) @run_decorator(md=_md) def _inner_Escan_list(): yield from moveE(energy_list[0]+0.001) for energy, factor in zip(energy_list, factor_list): # Change counting time for detector, original_preset in zip(detectors, dets_preset): yield from mv(detector.preset_monitor, factor*original_preset) # Move and scan grp = short_uid('set') yield Msg('checkpoint') yield from moveE(energy, group=grp) if dichro: yield from dichro_steps(detectors, _positioners, trigger_and_read) else: yield from trigger_and_read(list(detectors)+_positioners) return (yield from _inner_Escan_list())