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 dark_plan(): yield from bps.mv(shutter, 'closed') yield from bps.unstage(det) yield from bps.stage(det) yield from bps.trigger(det, group='darkframe-trigger') yield from bps.wait('darkframe-trigger') snapshot = bluesky_darkframes.SnapshotDevice(det) yield from bps.unstage(det) yield from bps.stage(det) yield from bps.mv(shutter, 'open') return snapshot
def dark_plan(detector): # 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(shutter, 'closed') # 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) yield from bps.mv(shutter, 'open') # Restage. yield from bps.unstage(detector) yield from bps.stage(detector) return snapshot
def insert_dark_frame(force_read, msg=None): # Acquire a fresh Snapshot if we need one, or retrieve a cached one. state = {} for signal in self.locked_signals: reading = yield from bluesky.plan_stubs.read(signal) # Restructure # {'data_key': {'value': <value>, 'timestamp': <timestamp>}, ...} # into (('data_key', <value>) ...). values_only = tuple( (k, v['value']) for k, v in reading.items()) state[signal.name] = values_only if self._current_state != state: self._current_state = state snapshot_changed = True else: snapshot_changed = False try: snapshot = self.get_snapshot(state) except NoMatchingSnapshot: logger.info(f"Taking a new dark frame for state=%r", state) snapshot = yield from self.dark_plan() self.add_snapshot(snapshot, state) if snapshot_changed or force_read: logger.info(f"Creating a 'dark' Event for state=%r", state) self._current_snapshot.set_snaphsot(snapshot) # Read the Snapshot into the 'dark' Event stream. yield from bps.stage(self._current_snapshot) yield from bps.trigger_and_read([self._current_snapshot], name=self.stream_name) yield from bps.unstage(self._current_snapshot) self._latch = False if msg is not None: return (yield msg)
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 insert_take_dark(msg): nonlocal need_dark qualified_dark_uid = _validate_dark(expire_time=glbl["dk_window"]) area_det = xpd_configuration["area_det"] if (not need_dark) and (not qualified_dark_uid): need_dark = True if need_dark and ( not qualified_dark_uid) and msg.command == "open_run" and ( "dark_frame" not in msg.kwargs): # We are about to start a new 'run' (e.g., a count or a scan). # Insert a dark frame run first. need_dark = False # Annoying detail: the detector was probably already staged. # Unstage it (if it wasn't staged, nothing will happen) and # then take_dark() and then re-stage it. return ( bpp.pchain( bps.unstage(area_det), take_dark(), bps.stage(area_det), bpp.single_gen(msg), open_shutter_stub(), ), None, ) elif msg.command == "open_run" and "dark_frame" not in msg.kwargs: return ( bpp.pchain(bpp.single_gen(msg), open_shutter_stub()), None, ) else: # do nothing if (not need_dark) return None, None
def dark_plan(self, detector): """The plan to take dark.""" # 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(self.shutter, self.shutter_close) # 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 = SnapshotDevice(detector) yield from bps.mv(self.shutter, self.shutter_open) # Restage. yield from bps.unstage(detector) yield from bps.stage(detector) return snapshot
def xpdacq_ramp_count(motor: typing.Any, value: typing.Any, inner_plan: typing.Callable, take_pre_data=True, timeout=None, period=None, md=None) -> typing.Generator: """ Take data while ramping one or more motors. Parameters ---------- inner_plan : The plan to repeat in loop. It returns a generator inner_plan(). motor : A positioner to ramp up. value: A value to ramp up to. timeout : float, optional If not None, the maximum time the ramp can run. In seconds take_pre_data: Bool, optional If True, add a pre data at beginning period : float, optional If not None, take data no faster than this. If None, take data as fast as possible If running the inner plan takes longer than `period` than take data with no dead time. In seconds. md : dict The metadata of this plan. """ for detector in detectors: yield from bps.stage(detector) def go_plan(): status, = yield from bps.mv(motor, value) return status yield from bp.ramp_plan(go_plan(), motor, inner_plan, take_pre_data=take_pre_data, timeout=timeout, period=period, md=md) for detector in detectors: yield from bps.unstage(detector)
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 insert_reference_to_dark_frame(msg): if msg.command == 'open_run': return ( bluesky.preprocessors.pchain( bluesky.preprocessors.single_gen(msg), bps.stage(self.dark_frame_cache), bps.trigger_and_read([self.dark_frame_cache], name='dark'), bps.unstage(self.dark_frame_cache) ), None, ) else: return None, None
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 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 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 tail(): # Acquire a fresh Snapshot if we need one, or retrieve a cached one. state = {} for signal in self.locked_signals: reading = yield bluesky.plan_stubs.read(signal) state[signal.name] = reading try: snapshot = self.get_snapshot(state) except NoMatchingSnapshot: snapshot = yield from self.dark_plan() self.add_snapshot(snapshot, state) # Read the Snapshot into the 'dark' Event stream. yield from bps.stage(snapshot) yield from bps.trigger_and_read([snapshot], name=self.stream_name) yield from bps.unstage(snapshot)
def insert_dark_frame(force_read, msg=None): # Acquire a fresh Snapshot if we need one, or retrieve a cached one. state = {} for signal in self.locked_signals: reading = yield from bluesky.plan_stubs.read(signal) # Restructure # {'data_key': {'value': <value>, 'timestamp': <timestamp>}, ...} # into (('data_key', <value>) ...). values_only = tuple( (k, v['value']) for k, v in reading.items()) state[signal.name] = values_only try: snapshot = self.get_snapshot(state) except NoMatchingSnapshot: # If we are here, we either haven't taken a reading when the # locked_signals were in this state, or the last such reading # we took has aged out of the cache. We have to trigger the # hardware and get a fresh snapshot. logger.info("Taking a new %r reading for state=%r", self.stream_name, state) snapshot = yield from self._partialed_dark_plan() self.add_snapshot(snapshot, state) # If the Snapshot is the same as the one we most recently inserted, # then we don't need to create a new Event. The previous Event # still holds. snapshot_changed = snapshot is not self._current_snapshot.get_snapshot( ) if snapshot_changed or force_read: logger.info("Creating a %r Event for state=%r", self.stream_name, state) self._current_snapshot.set_snaphsot(snapshot) # Read the Snapshot. This does not actually trigger hardware, # but it goes through all the bluesky steps to generate new # Event. # The reason we handle self._current_snapshot here instead of # snapshot itself is the bluesky RunEngine notices if you give # it a different object than you had given it earlier. Thus, # bluesky will always see the "Device" self._current_snapshot # here, and it will be satisfied. yield from bps.stage(self._current_snapshot) yield from trigger_and_read([self._current_snapshot], name=self.stream_name, group=short_uid(GROUP_PREFIX)) yield from bps.unstage(self._current_snapshot) self._latch = False if msg is not None: return (yield msg)
def tail(): # Acquire a fresh Snapshot if we need one, or retrieve a cached one. state = {} for signal in self.locked_signals: reading = yield from bluesky.plan_stubs.read(signal) # Restructure # {'data_key': {'value': <value>, 'timestamp': <timestamp>}, ...} # into (('data_key', <value>) ...). values_only = tuple( (k, v['value']) for k, v in reading.items()) state[signal.name] = values_only try: snapshot = self.get_snapshot(state) except NoMatchingSnapshot: snapshot = yield from self.dark_plan() self.add_snapshot(snapshot, state) # Read the Snapshot into the 'dark' Event stream. yield from bps.stage(snapshot) yield from bps.trigger_and_read([snapshot], name=self.stream_name) yield from bps.unstage(snapshot)
def _pe_acquisition_plan(): for det in dets: if images_per_set is not None: yield from bps.mov(det.images_per_set, images_per_set) for det in dets: yield from bps.stage(det) yield from bps.sleep(1) # close fast shutter, now take a dark # yield from bps.mov(fs, 0) yield from bpp.trigger_and_read(dets, name='dark') # open fast shutter # yield from bps.mov(fs, 1) yield from bpp.trigger_and_read(dets, name='primary') for det in dets: yield from bps.unstage(det)
def drop_daq_msg(msg): if msg.command == 'stage': return (yield from bps.stage(_Dummy())) if msg.command == 'unstage': return (yield from bps.unstage(_Dummy()))
def take_image(self): yield from bps.stage(self) yield from bps.trigger(self, wait=True) yield from bps.unstage(self)
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 _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 plan(): yield from open_run() yield from stage(m) yield from unstage(m) yield from close_run()
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()