def __single_shot(self, gasdelay=0.05, shotdelay=10.0, record=True, use_l3t=False, controls=[], end_run=True): logging.debug("Calling __single_shot with the folling parameters:") logging.debug("gasdelay: {}".format(gasdelay)) logging.debug("shotdelay: {}".format(shotdelay)) logging.debug("record: {}".format(record)) logging.debug("use_l3t: {}".format(use_l3t)) logging.debug("controls: {}".format(controls)) logging.debug("end_run: {}".format(end_run)) nshots = 1 yield from bps.configure(daq, begin_sleep=2, record=record, use_l3t=use_l3t, controls=controls) yield from bps.configure(daq, events=nshots) # Add sequencer, DAQ to detectors for shots dets = [daq, seq] for det in dets: yield from bps.stage(det) # Setup sequencer for requested rate sync_mark = int(self._sync_markers[self._rate]) seq.sync_marker.put(sync_mark) seq.play_mode.put(0) # Run sequence once # Determine the different sequences needed gdelay = int(gasdelay*120) # 120 beam delays/second sdelay = int(shotdelay*120) # 120 beam delays/second slow_cam_seq = [[167, 0, 0, 0]] gas_jet_seq = [[177, 0, 0, 0], [176, gdelay, 0, 0], [169, 0, 0, 0], [0, sdelay, 0, 0]] s = slow_cam_seq + gas_jet_seq logging.debug("Sequence: {}".format(s)) # Get exposure time in beam deltas from number of shots exposure = nshots * (int(shotdelay/120.0) + int(gasdelay/120.0)) logging.debug("Exposure time: {}".format(exposure*120.0)) # Stage and add in slow cameras *after* daq is staged and configured slowcams = SlowCameras() # The camera delay and number of 'during' shots are the same in this case (I think) config = {'slowcamdelay': exposure, 'during': exposure} dets.append(slowcams) # Add this in to auto-unstage later slowcams.stage(config) seq.sequence.put_seq(s) yield from bps.trigger_and_read(dets) # If this is the last move in the scan, check cleanup settings if end_run: daq.end_run()
def plan(): # working around 'yield from' here which breaks py2 for msg in configure(det, {'z': 3}): # no-op yield msg for msg in trigger_and_read([det]): yield msg # changing the config after a read generates a new Event Descriptor for msg in configure(det, {'z': 4}): yield msg for msg in trigger_and_read([det]): yield msg
def daq_during_plan(): yield from bps.configure(daq, events=0, record=record, use_l3t=use_l3t, controls=controls) return (yield from bpp.fly_during_wrapper(plan, flyers=[daq]))
def daq_first_cycle(msg): yield from bps.configure(daq, events=events, duration=duration, record=record, use_l3t=use_l3t, controls=list(motor_cache)) return (yield from add_daq_trigger(msg))
def __1DScan(self, motor, start, end, npoints, ndaq, record): # Setup the event sequencer for the scan logging.debug("Setting up the sequencer for %s daq points", ndaq) self.__setup_sequencer(ndaq) # Setup the pulse picker if pp.mode.get() == 3: logging.debug("The pulse picker is already in burst mode") else: logging.debug("Setting up the pulse picker for burst mode") pp.burst(wait=True) # Setup the DAQ daq.record = record daq.configure(events=ndaq) bps.configure(daq, events=ndaq) # For plan introspection # Add sequencer, DAQ to detectors for scan dets = [daq, seq] # Log stuff logging.debug("Returning __1DScan with the following parameters:") logging.debug("motor: {}".format(motor)) logging.debug("start: {}".format(start)) logging.debug("end: {}".format(end)) logging.debug("npoints: {}".format(npoints)) logging.debug("ndaq: {}".format(ndaq)) logging.debug("record: {}".format(record)) logging.debug("detectors: {}".format(dets)) # Return the plan scan_plan = scan(dets, motor, start, end, npoints) final_plan = bpp.finalize_wrapper(scan_plan, self.__cleanup_plan()) return final_plan
def daq_during_wrapper(plan, record=None, use_l3t=False, controls=None): """ Run a plan with the `Daq`. This can be used with an ordinary ``bluesky`` plan that you'd like the daq to run along with. This also stages the daq so that the run start/stop will be synchronized with the bluesky runs. This must be applied outside the ``run_wrapper``. All configuration must be done by supplying config kwargs to this wrapper. The `daq_during_decorator` is the same as the `daq_during_wrapper`, but it is meant to be used as a function decorator. Parameters ---------- plan: ``plan`` The ``plan`` to use the daq in record: ``bool``, optional If ``True``, we'll record the data. Otherwise, we'll run without recording. Defaults to ``False``, or the last set value for ``record``. use_l3t: ``bool``, optional If ``True``, an ``events`` argument to begin will be reinterpreted to only count events that pass the level 3 trigger. Defaults to ``False``. controls: ``dict{name: device}`` or ``list[device...]``, optional If provided, values from these will make it into the DAQ data stream as variables. We will check ``device.position`` and ``device.value`` for quantities to use and we will update these values each time begin is called. To provide a list, all devices must have a ``name`` attribute. """ daq = get_daq() yield from configure(daq, events=None, duration=None, record=record, use_l3t=use_l3t, controls=controls) yield from stage_wrapper(fly_during_wrapper(plan, flyers=[daq]), [daq])
def config_by_ai(cb: CalibrationData, ai: pyFAI.AzimuthalIntegrator) -> tp.Generator: """Configure the calibration data in an area detector using the AzimuthalIntegrator. Parameters ---------- cb : CalibrationData The device that hold the calibration data. ai : AzimuthalIntegrator The pyFAI AzimuthalIntegrator Yields ------ Msg : Msg The bluesky message. """ return ( yield from bps.configure(cb, {"dist": ai.dist, "poni1": ai.poni1, "poni2": ai.poni2, "rot1": ai.rot1, "rot2": ai.rot2, "rot3": ai.rot3, "detector": ai.detector.name, "wavelength": ai.wavelength, "pixel1": ai.pixel1, "pixel2": ai.pixel2}) )
def Tramp2(dets: list, exposure: float, Tstart: float, Tstop: float, Tstep: float, *, ramp_rate: float = None): """A temperature ramping plan with ramping rate configuration. The ramping rate will be configured before the ramping start. The ramping will be done continuously without holding temperature at exposure. Parameters ---------- dets : list A list of detectors. Dummy. Not used. exposure : float The exposure time in second. Tstart : float The start temperature in K (included). Tstop : float The stop temperature in K (incldued) Tstep : float The temperature step in K. ramp_rate : float The temperature ramping rate. Make sure the temperature controller has the `velocity` configuration. Yields ------ Bluesky plan. """ temp_controller: SynAxis = xpd_configuration["temp_controller"] if ramp_rate is not None: yield from bps.configure(temp_controller, {"velocity": ramp_rate}) yield from Tramp(dets, exposure, Tstart, Tstop, Tstep)
def _single_shot_plan(self, record=True, use_l3t=False, controls=[], end_run=True): """Definition of plan for taking laser shots with the MEC laser.""" # TODO: Add attenuator control logging.debug("Generating shot plan using _shot_plan.") logging.debug("_shot_plan config:") logging.debug("{}".format(self._config)) logging.debug("Record: {}".format(record)) logging.debug("use_l3t: {}".format(use_l3t)) logging.debug("controls: {}".format(controls)) # Make sure that any updates to configuration are applied self.configure(self._config) # Check number of shots for long pulse laser if self._config['laser'] == 'longpulse': lpl_shots = self._config['preo'] + self._config['during'] + \ self._config['posto'] if lpl_shots > 1: m = ("Cannot shoot the long pulse laser more than once in a " "sequence! Please reduce the number of optical shots " "requested to 1!") raise Exception(m) # Setup the daq based on config total_shots = self._config['predark'] + self._config['prex'] + \ self._config['preo'] + self._config['postdark'] + \ self._config['postx'] + self._config['posto'] + \ self._config['during'] print("Configured for {} total shots.".format(total_shots)) logging.debug("Total shots: {}".format(total_shots)) yield from bps.configure(daq, begin_sleep=2, record=record, use_l3t=use_l3t, controls=controls) # Add sequencer, DAQ to detectors for shots dets = [daq, seq] for det in dets: yield from bps.stage(det) # Check for slow cameras, stage if requested if self._config['slowcam']: from .slowcams import SlowCameras self._slowcams = SlowCameras() dets.append(self._slowcams) # Add this in to auto-unstage later yield from bps.stage(self._slowcams) # Setup the pulse picker for single shots in flip flop mode #pp.flipflop(wait=True) # Setup sequencer for requested rate sync_mark = int(self._sync_markers[self._config['rate']]) seq.sync_marker.put(sync_mark) seq.play_mode.put(0) # Run sequence once # Dark (no optical laser, no XFEL) shots if self._config['predark'] > 0: # Get number of predark shots shots = self._config['predark'] logging.debug("Configuring for {} predark shots".format(shots)) yield from bps.configure(daq, events=shots) # Preshot dark, so use preshot laser marker pre_dark_seq = self._seq.darkSequence(shots, preshot=True) seq.sequence.put_seq(pre_dark_seq) # Number of shots is determined by sequencer, so just trigger/read print("Taking {} predark shots ... ".format( self._config['predark'])) yield from bps.trigger_and_read(dets) # Pre-xray (no optical laser, XFEL only) shots if self._config['prex'] > 0: # Get number of prex shots shots = self._config['prex'] logging.debug("Configuring for {} prex shots".format(shots)) yield from bps.configure(daq, events=shots) # Preshot x-ray only shots, so use preshot laser marker prex_seq = self._seq.darkXraySequence(shots, preshot=True) seq.sequence.put_seq(prex_seq) # Number of shots is determined by sequencer, so just trigger/read print("Taking {} prex shots ... ".format(shots)) yield from bps.trigger_and_read(dets) # Pre-optical (optical laser only, no XFEL) shots if self._config['preo'] > 0: # Get number of preo shots shots = self._config['preo'] logging.debug("Configuring for {} preo shots".format(shots)) yield from bps.configure(daq, events=shots) # Optical only shot, with defined laser preo_seq = self._seq.opticalSequence(shots, self._config['laser'],\ preshot=True) seq.sequence.put_seq(preo_seq) # Number of shots is determined by sequencer, so just take 1 count print("Taking {} preo shots ... ".format(shots)) yield from bps.trigger_and_read(dets) # 'During' (optical laser + XFEL) shots if self._config['during'] > 0: # Get number of during shots shots = self._config['during'] logging.debug("Configuring for {} during shots".format(shots)) yield from bps.configure(daq, events=shots) # During shot, with defined laser during_seq = self._seq.duringSequence(shots, self._config['laser']) seq.sequence.put_seq(during_seq) # Number of shots is determined by sequencer, so just take 1 count print("Taking {} during shots ... ".format(shots)) yield from bps.trigger_and_read(dets) # Post-optical (optical laser only, no XFEL) shots if self._config['posto'] > 0: # Get number of post optical shots shots = self._config['posto'] logging.debug("Configuring for {} posto shots".format(shots)) yield from bps.configure(daq, events=shots) # Optical only shot, with defined laser posto_seq = self._seq.opticalSequence(shots, self._config['laser'],\ preshot=False) seq.sequence.put_seq(posto_seq) # Number of shots is determined by sequencer, so just take 1 count print("Taking {} posto shots ... ".format(shots)) yield from bps.trigger_and_read(dets) # Post-xray (no optical laser, XFEL only) shots if self._config['postx'] > 0: # Get number of postx shots shots = self._config['postx'] logging.debug("Configuring for {} postx shots".format(shots)) yield from bps.configure(daq, events=shots) # Postshot x-ray only shots, so use postshot laser marker postx_seq = self._seq.darkXraySequence(shots, preshot=False) seq.sequence.put_seq(postx_seq) # Number of shots is determined by sequencer, so just take 1 count print("Taking {} postx shots ... ".format(shots)) yield from bps.trigger_and_read(dets) # Dark (no optical laser, no XFEL) shots if self._config['postdark'] > 0: # Get number of postdark shots shots = self._config['postdark'] logging.debug("Configuring for {} postdark shots".format(shots)) yield from bps.configure(daq, events=shots) # Postshot dark, so use postshot laser marker post_dark_seq = self._seq.darkSequence(shots, preshot=False) seq.sequence.put_seq(post_dark_seq) # Number of shots is determined by sequencer, so just take 1 count print("Taking {} postdark shots ... ".format(shots)) yield from bps.trigger_and_read(dets) for det in dets: yield from bps.unstage(det) if end_run: daq.end_run()
def _internal_plan(dets): yield from trigger_and_read(dets) for det in dets: yield from configure(det, {}) yield from trigger_and_read(dets)
def _single_shot_plan(self, record=True, use_l3t=False, controls=[], end_run=True): """Definition of plan for taking laser shots with the MEC laser.""" # TODO: Add attenuator control logging.debug("Generating shot plan using _shot_plan.") logging.debug("_shot_plan config:") logging.debug("{}".format(self._config)) logging.debug("Record: {}".format(record)) logging.debug("use_l3t: {}".format(use_l3t)) logging.debug("controls: {}".format(controls)) # Make sure that any updates to configuration are applied self.configure(self._config) # Setup the daq based on config total_shots = 1 print("Configured for {} total shots.".format(total_shots)) logging.debug("Total shots: {}".format(total_shots)) yield from bps.configure(daq, begin_sleep=2, record=record, use_l3t=use_l3t, controls=controls) # Add sequencer, DAQ to detectors for shots dets = [daq, seq] for det in dets: yield from bps.stage(det) # Check for slow cameras, stage if requested if self._config['slowcam']: from .slowcams import SlowCameras self._slowcams = SlowCameras() dets.append(self._slowcams) # Add this in to auto-unstage later yield from bps.stage(self._slowcams) # Setup the pulse picker for single shots in flip flop mode pp.flipflop(wait=True) # Setup sequencer for requested rate sync_mark = int(self._sync_markers[self._config['rate']]) seq.sync_marker.put(sync_mark) seq.play_mode.put(0) # Run sequence once # Dual (FSL + NSL + XFEL) shots shots = total_shots logging.debug("Configuring for {} dual shots".format(shots)) yield from bps.configure(daq, events=shots) # Preshot dark, so use preshot laser marker dual_seq = self._seq.dualDuringSequence() seq.sequence.put_seq(dual_seq) # Number of shots is determined by sequencer, so just trigger/read print("Taking {} shots shots ... ".format(shots)) yield from bps.trigger_and_read(dets) for det in dets: yield from bps.unstage(det) if end_run: daq.end_run()
def __jet_scan(self, motor1, m1start, m1end, m1step, motor2, m2start, m2end, m2step, gasdelay=0.05, shotdelay=10.0, record=True, use_l3t=False, controls=[], end_run=True, carriage_return=True): """ Scan for the LU60 gas jet experiment. Parameters: ----------- motor1 : motor The first motor on which to run the scan. m1start : float The position to start the scan for motor1. The motor will travel to this position prior to beginning the scan. m1end : float The position to end the scan on for motor1. m1steps : float The number of steps for motor 1 motor2 : motor The second motor on which to run the scan. m2start : float The position to start the scan for motor2. The motor will travel to this position prior to beginning the scan. m2end : float The position to end the scan on for motor 2. m2steps : float The number of steps for motor 2. gasdelay : float (default: 0.05) The number of seconds to wait for the gas jet to be ready after the trigger. shotdelay : float (default: 10.0) The number of seconds to wait between shots. This is empirically derived, and is used to allow the chamber pressure to equillibrate following a gas jet puff. record : bool (default: True) Option to record the scan in the DAQ (or not). use_l3t : bool (default: False) Option to use a level 3 trigger (or not) in the scan. controls : list (default: []) Optional list of devices to add to the DAQ data stream. Devices added in this way will have their device.position or device.value quantities added to the scan. end_run : bool (default: True) Option to end the run after the scan. This will cause a new run to be initiated during the next scan. """ logging.debug("Calling __jet_scan with the folling parameters:") logging.debug("motor1: {}".format(motor1)) logging.debug("m1start: {}".format(m1start)) logging.debug("m1end: {}".format(m1end)) logging.debug("m1step: {}".format(m1step)) logging.debug("motor2: {}".format(motor2)) logging.debug("m2start: {}".format(m2start)) logging.debug("m2end: {}".format(m2end)) logging.debug("m2step: {}".format(m2step)) logging.debug("gasdelay: {}".format(gasdelay)) logging.debug("shotdelay: {}".format(shotdelay)) logging.debug("record: {}".format(record)) logging.debug("use_l3t: {}".format(use_l3t)) logging.debug("controls: {}".format(controls)) logging.debug("end_run: {}".format(end_run)) nshots = m1steps * m2steps logging.debug("nsteps: {}".format(nsteps)) print("Configured scan for {} steps...".format(nsteps)) if ((nsteps * 4) + 1) > 2048: raise ValueError("The number of steps cannot be greater than 2048!") yield from bps.configure(daq, begin_sleep=2, record=record, use_l3t=use_l3t, controls=controls) # Add sequencer, DAQ to detectors for shots dets = [daq, seq] for det in dets: yield from bps.stage(det) # Setup sequencer for requested rate sync_mark = int(self._sync_markers[self._config['rate']]) seq.sync_marker.put(sync_mark) seq.play_mode.put(0) # Run sequence once # TODO: determine the different sequences needed. gdelay = int(gasdelay*120) # 120 beam delays/second sdelay = int(shotdelay*120) # 120 beam delays/second slow_cam_seq = [[167, 0, 0, 0]] gas_jet_seq = [[177, 0, 0, 0], [176, gdelay, 0, 0], [169, 0, 0, 0], [0, sdelay, 0, 0]] # TODO: Configure the slow cameras # Get exposure time in beam deltas from number of shots exposure = nshots * (int(shotdelay/120.0) + int(gasdelay/120.0)) logging.debug("Exposure time: {}".format(exposure)) # Stage and add in slow cameras *after* daq is staged and configured slowcams = SlowCameras() # The camera delay and number of 'during' shots are the same in this case config = {'slowcamdelay': exposure, 'during': exposure} dets.append(slowcams) # Add this in to auto-unstage later slowcams.stage(config) m1_step_size = (m1_end-m1_start)/(m1_steps-1) logging.debug("m1 step size: {}".format(m1_step_size)) m2_step_size = (m2_end-m2_start)/(m2_steps-1) logging.debug("m2 step size: {}".format(m2_step_size)) for i in range(m2_steps): new_m2 = m2_start+m2_step_size*i logging.debug("Moving motor2 to {}".format(new_m2)) yield from bps.mv(motor2, new_m2) for j in range(m1_steps): new_m1 = m1_start+m1_step_size*j logging.debug("Moving motor1 to {}".format(new_m1)) yield from bps.mv(motor1, new_m1) # If this is the first shot, use slow cam in sequence if (i == 0) and (j == 0): s = slow_cam_seq + gas_jet_seq else: s = gas_jet_seq # TODO: set this up to run only if the sequence is different? # Do many puts to the test EVG program cause problems? seq.sequence.put_seq(s) # If this is the last move in the scan, check cleanup settings if (i == (m1_steps-1)) and (j == (m2_steps -1)): if carriage_return: # Then go back to start yield from bps.mv(motor1, m1_start) yield from bps.mv(motor2, m2_start) if end_run: daq.end_run()
def __grid_scan(self, x_motor, x_start, x_end, xsteps, y_motor, y_start, y_end, ysteps, z_motor, angle, ndaq, record=True): logging.debug("Setting up the sequencer for %s daq points", ndaq) self.__setup_sequencer(ndaq) # Setup the pulse picker if pp.mode.get() == 3: logging.debug("The pulse picker is already in burst mode") else: logging.debug("Setting up the pulse picker for burst mode") pp.burst(wait=True) # Setup the DAQ daq.record = record daq.configure(events=ndaq) bps.configure(daq, events=ndaq) # For plan introspection # Add sequencer, DAQ to detectors for scan dets = [daq, seq] # Log stuff logging.debug("Returning __grid_scan with the following parameters:") logging.debug("x_start: {}".format(x_start)) logging.debug("x_end: {}".format(x_end)) logging.debug("xsteps: {}".format(xsteps)) logging.debug("y_start: {}".format(y_start)) logging.debug("y_end: {}".format(y_end)) logging.debug("y_steps: {}".format(ysteps)) logging.debug("angle: {}".format(angle)) logging.debug("ndaq: {}".format(ndaq)) logging.debug("record: {}".format(record)) logging.debug("detectors: {}".format(dets)) z_start = z_motor.wm() x_step_size = (x_end - x_start) / (xsteps - 1) logging.debug("X step size: {}".format(x_step_size)) y_step_size = (y_end - y_start) / (ysteps - 1) logging.debug("Y step size: {}".format(y_step_size)) z_step = self.__comp_z(y_step_size, angle) logging.debug("Z step size: {}".format(z_step)) for i in range(ysteps): new_y = y_start + y_step_size * i logging.debug("Moving Y to {}".format(new_y)) yield from bps.mv(y_motor, new_y) if i != 0: # Skip first step; assume focus is fine there logging.debug("Moving Z by {}".format(z_step)) yield from bps.mvr(z_motor, z_step) yield from scan(dets, x_motor, x_start, x_end, xsteps) # Return to original positions yield from bps.mv(x_motor, x_start) yield from bps.mv(y_motor, y_start) yield from bps.mv(z_motor, z_start)