def fly_row(): # go to start of row target_y = ystart + y * a_ystep_size yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, target_y) yield from bps.mv(y_centers, np.ones(num_xpixels) * target_y) # set the fly speed # ret = yield from bps.read(xy_fly_stage.z.user_readback) # (in mm) # revised by YDu, no such value before #yield from bps.sleep(0) # zpos = ( # ret[xy_fly_stage.z.user_readback.name]["value"] # if ret is not None # else 0 # ) # yield from bps.mov(z_centers, np.ones(num_xpixels) * zpos) yield from bps.mv(xy_fly_stage.x.velocity, flyspeed) yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") # arm the struck yield from bps.trigger(sclr, group=f"fly_row_{y}") # maybe start the xspress3 if xspress3 is not None: yield from bps.trigger(xspress3, group=f"fly_row_{y}") # revised by YDu, use to be 0.1 yield from bps.sleep(1.5) # fly the motor yield from bps.abs_set(xy_fly_stage.x, xstop + a_xstep_size, group=f"fly_row_{y}") yield from bps.wait(group=f"fly_row_{y}") # yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") yield from bps.mv(xy_fly_stage.x.velocity, 5.0) # revised by YDu, use to be 0.1 yield from bps.sleep(0.1) # read and save the struck yield from bps.create(name="primary") # yield from bps.read(sclr) yield from bps.read(mono) yield from bps.read(x_centers) yield from bps.read(y_centers) yield from bps.read(z_centers) yield from bps.read(xy_fly_stage.y) yield from bps.read(xy_fly_stage.z) # and maybe the xspress3 if xspress3 is not None: yield from bps.read(xspress3) yield from bps.sleep(0.2) yield from bps.save() yield from bps.sleep(0.2)
def fly_scan(experiment, cfg_tomo): """ Collect projections with fly motion """ det = experiment.det psofly = experiment.psofly yield from bps.mv(det.hdf1.nd_array_port, 'PG1') yield from bps.mv(det.tiff1.nd_array_port, 'PG1') # we are assuming that the global psofly is available yield from bps.mv( psofly.start, cfg_tomo['omega_start'], psofly.end, cfg_tomo['omega_end'], psofly.scan_delta, abs(cfg_tomo['omega_step']), psofly.slew_speed, cfg_tomo['slew_speed'], ) # taxi yield from bps.mv(psofly.taxi, "Taxi") yield from bps.mv( det.cam.num_images, cfg_tomo['n_projections'], det.cam.trigger_mode, "Overlapped", ) # start the fly scan yield from bps.trigger(det, group='fly') yield from bps.abs_set(psofly.fly, "Fly", group='fly') yield from bps.wait(group='fly')
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 fly_body(): yield from bps.trigger_and_read([E_centers], name='energy_bins') for y in range(num_scans): # go to start of row yield from bps.mv(mono.linear, l_start) # set the fly speed yield from bps.mv(mono.linear.velocity, flyspeed) yield from bps.trigger_and_read([mono], name='row_ends') for v in ['p1600=0', 'p1600=1']: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the struck yield from bps.trigger(sclr, group=f'fly_energy_{y}') # fly the motor yield from bps.abs_set(mono.linear, l_stop + a_l_step_size, group=f'fly_energy_{y}') yield from bps.wait(group=f'fly_energy_{y}') yield from bps.trigger_and_read([mono], name='row_ends') yield from bps.mv(mono.linear.velocity, 0.5) # hard coded to let the sclr count its fingers and toes yield from bps.sleep(.1) # read and save the struck yield from bps.create(name='primary') yield from bps.read(sclr) yield from bps.save()
def 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 fly_once(y): # for y in range(num_scans): # go to start of row yield from bps.checkpoint() yield from bps.mv(mono.linear.velocity, 1) yield from bps.mv(mono.linear, l_start) # set the fly speed yield from bps.mv(mono.linear.velocity, flyspeed) yield from bps.trigger_and_read([mono], name="row_ends") for v in ["p1600=0", "p1600=1"]: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the Struck yield from bps.trigger(sclr, group=f"fly_energy_{y}") if xspress3 is not None: yield from bps.trigger(xspress3, group=f"fly_energy_{y}") # fly the motor yield from bps.abs_set(mono.linear, l_stop + a_l_step_size, group=f"fly_energy_{y}") yield from bps.wait(group=f"fly_energy_{y}") yield from bps.trigger_and_read([mono], name="row_ends") yield from bps.mv(mono.linear.velocity, flyspeed) # hard coded to let the sclr count its fingers and toes yield from bps.sleep(0.1) # read and save the struck yield from bps.create(name="primary") yield from bps.read(sclr) if xspress3 is not None: yield from bps.read(xspress3) yield from bps.save()
def per_step(detectors, step, pos_cache): """ Override default per_step to start the sequencer on each row. The first move is not a fly scan move: it moves us into the start position. The second move is, as is the fourth, sixth... """ nonlocal is_seq_step if is_seq_step: yield from trigger(seq) is_seq_step = False else: is_seq_step = True yield from one_nd_step(detectors, step, pos_cache)
def fly_row(): # go to start of row yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, ystart + y * ystep_size) # set the fly speed yield from bps.mv(xy_fly_stage.x.velocity, flyspeed) yield from bps.trigger_and_read([xy_fly_stage], name='row_ends') for v in ['p1600=0', 'p1600=1']: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the struck yield from bps.trigger(sclr, group=f'fly_row_{y}') # maybe start the xspress3 if xspress3 is not None: yield from bps.trigger(xspress3, group=f'fly_row_{y}') yield from bps.sleep(0.1) # fly the motor yield from bps.abs_set(xy_fly_stage.x, xstop + a_xstep_size, group=f'fly_row_{y}') yield from bps.wait(group=f'fly_row_{y}') yield from bps.trigger_and_read([xy_fly_stage], name='row_ends') yield from bps.mv(xy_fly_stage.x.velocity, 5.0) yield from bps.sleep(.1) # read and save the struck yield from bps.create(name='primary') yield from bps.read(sclr) # and maybe the xspress3 if xspress3 is not None: yield from bps.read(xspress3) yield from bps.save()
def 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 dark_plan(cam, dark_frame_cache, obsolete_secs, shutter): if (dark_frame_cache.just_started or # first run after instantiation (dark_frame_cache.last_collected is not None and time.monotonic() - dark_frame_cache.last_collected > obsolete_secs)): tmp = yield from bps.read(shutter.status) init_shutter_state = tmp[shutter.status.name]['value'] if tmp is not None else None yield from bps.mv(shutter, 'Close') yield from bps.trigger(cam, group='cam') yield from bps.wait('cam') yield from bps.mv(shutter, init_shutter_state) teleport(cam, dark_frame_cache) dark_frame_cache.just_started = False dark_frame_cache.update_done = True else: dark_frame_cache.update_done = False
def dark_plan(detector, dark_frame_cache, max_age, shutter): if (dark_frame_cache.just_started or # first run after instantiation (dark_frame_cache.last_collected is not None and time.monotonic() - dark_frame_cache.last_collected > max_age)): init_shutter_state = shutter.get() yield from bps.mv(shutter, 0) yield from bps.trigger(detector, group='cam') yield from bps.wait('cam') yield from bps.mv(shutter, init_shutter_state) teleport(detector, dark_frame_cache) dark_frame_cache.just_started = False dark_frame_cache.update_done = True else: dark_frame_cache.update_done = False
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 no_run_trigger_and_wait(objects): """ count objects (presume detectors) but do not create a bluesky run Does most of bps.trigger_and_read() but does not create&save a run. Caller must call `.read()` on each object once this returns. The primary use case is to count detectors (on a scaler card) when measuring sample transmission. """ if not isinstance(objects, (tuple, set, list)): objects = [objects] group = bps._short_uid("trigger_and_wait_no_run") for obj in objects: yield from bps.trigger(obj, group=group) yield from bps.wait(group=group)
def fly_row(): # go to start of row target_y = ystart + y * a_ystep_size yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, target_y) yield from bps.mv(y_centers, np.ones(num_xpixels) * target_y) # set the fly speed ret = yield from bps.read(xy_fly_stage.z.user_readback) # (in mm) zpos = (ret[xy_fly_stage.z.user_readback.name]["value"] if ret is not None else 0) yield from bps.mov(z_centers, np.ones(num_xpixels) * zpos) yield from bps.mv(xy_fly_stage.x.velocity, flyspeed) yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") for v in ["p1600=0", "p1600=1"]: yield from bps.mv(dtt, v) yield from bps.sleep(0.1) # arm the struck yield from bps.trigger(sclr, group=f"fly_row_{y}") # maybe start the xspress3 # fly the motor yield from bps.abs_set(xy_fly_stage.x, xstop + a_xstep_size, group=f"fly_row_{y}") yield from bps.wait(group=f"fly_row_{y}") yield from bps.trigger_and_read([xy_fly_stage], name="row_ends") yield from bps.mv(xy_fly_stage.x.velocity, 5.0) yield from bps.sleep(0.1) # read and save the struck yield from bps.create(name="primary") # yield from bps.read(sclr) yield from bps.read(mono) yield from bps.read(x_centers) yield from bps.read(y_centers) yield from bps.read(z_centers) yield from bps.read(xy_fly_stage.y) yield from bps.read(xy_fly_stage.z) # and maybe the xspress3 yield from bps.save()
def inner_trigger_and_read(): nonlocal group if group is None: group = short_uid('trigger') no_wait = True for obj in devices: if hasattr(obj, 'trigger'): no_wait = False yield from bps.trigger(obj, group=group) # Skip 'wait' if none of the devices implemented a trigger method. if not no_wait: yield from bps.wait(group=group) yield from bps.create(name) ret = {} # collect and return readings to give plan access to them for obj in devices: reading = (yield from bps.read(obj)) if reading is not None: ret.update(reading) yield from bps.save() return ret
def fly_each_step(detectors, motor, step, firststep): "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook" # First, let 'scan' handle the normal y step, including a checkpoint. yield from one_1d_step(detectors, motor, step) # Now do the x steps. v = (xstop - xstart) / (xnum-1) / dwell # compute "stage speed" yield from abs_set(xmotor, xstart - delta, wait=True) # ready to move yield from abs_set(xmotor.velocity, v, wait=True) # set the "stage speed" yield from abs_set(xs.hdf5.num_capture, xnum, wait=True) yield from abs_set(xs.settings.num_images, xnum, wait=True) yield from abs_set(ion.nuse_all,xnum) # arm the Zebra (start caching x positions) yield from kickoff(flying_zebra, xstart=xstart, xstop=xstop, xnum=xnum, dwell=dwell, wait=True) yield from abs_set(ion.erase_start, 1) # arm SIS3820, note that there is a 1 sec delay in setting X into motion # so the first point *in each row* won't normalize... yield from bps.trigger(xs, group='row') #if firststep == True: # ttime.sleep(0.) yield from bps.sleep(1.5) yield from abs_set(xmotor, xstop+1*delta, group='row') # move in x yield from bps.wait(group='row') # yield from abs_set(xs.settings.acquire, 0) # stop acquiring images yield from abs_set(ion.stop_all, 1) # stop acquiring scaler yield from complete(flying_zebra) # tell the Zebra we are done yield from collect(flying_zebra) # extract data from Zebra if ('e_tomo' in xmotor.name): v_return = 4 v_max = xmotor.velocity.high_limit if (v_return > v_max): xmotor.velocity.set(v_max) else: xmotor.velocity.set(v_return) else: yield from abs_set(xmotor.velocity, 1.0, wait=True) # set the "stage speed"
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 fly_each_step(motor, step, row_start, row_stop): def move_to_start_fly(): "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook" # row_str = short_uid('row') # yield from abs_set(xmotor, row_start, group=row_str) # yield from one_1d_step([temp_nanoKB], motor, step) # yield from bps.wait(group=row_str) row_str = short_uid('row') yield from bps.checkpoint() yield from bps.abs_set(xmotor, row_start, group=row_str) yield from bps.abs_set(motor, step, group=row_str) yield from bps.wait(group=row_str) yield from bps.trigger_and_read([temp_nanoKB, motor]) if verbose: t_mvstartfly = tic() yield from move_to_start_fly() # TODO Why are we re-trying the move? This should be fixed at # a lower level # yield from bps.sleep(1.0) # wait for the "x motor" to move x_set = row_start x_dial = xmotor.user_readback.get() # Get retry deadband value and check against that i = 0 DEADBAND = 0.050 # retry deadband of nPoint scanner while (np.abs(x_set - x_dial) > DEADBAND): if (i == 0): print('Waiting for motor to reach starting position...', end='', flush=True) i = i + 1 yield from mv(xmotor, row_start) yield from bps.sleep(0.1) x_dial = xmotor.user_readback.get() if (i != 0): print('done') if verbose: toc(t_mvstartfly, str='Move to start fly each') # Set the scan speed # Is abs_set(wait=True) or mv() faster? v = ((xstop - xstart) / (xnum - 1)) / dwell # compute "stage speed" # yield from abs_set(xmotor.velocity, v, wait=True) # set the "stage speed" if (v > xmotor.velocity.high_limit): raise ValueError( f'Desired motor velocity too high\nMax velocity: {xmotor.velocity.high_limit}' ) elif (v < xmotor.velocity.low_limit): raise ValueError( f'Desired motor velocity too low\nMin velocity: {xmotor.velocity.low_limit}' ) else: yield from mv(xmotor.velocity, v) # set up all of the detectors # TODO we should be able to move this out of the per-line call?! if ('xs' in dets_by_name): xs = dets_by_name['xs'] yield from abs_set(xs.hdf5.num_capture, xnum, group='set') yield from abs_set(xs.settings.num_images, xnum, group='set') yield from bps.wait(group='set') # yield from mv(xs.hdf5.num_capture, xnum, # xs.settings.num_images, xnum) # xs.hdf5.num_capture.put(xnum) # xs.settings.num_images.put(xnum) if ('xs2' in dets_by_name): xs2 = dets_by_name['xs2'] # yield from abs_set(xs2.hdf5.num_capture, xnum, wait=True) # yield from abs_set(xs2.settings.num_images, xnum, wait=True) yield from mv(xs2.hdf5.num_capture, xnum, xs2.settings.num_images, xnum) if ('merlin' in dets_by_name): merlin = dets_by_name['merlin'] yield from abs_set(merlin.hdf5.num_capture, xnum, wait=True) yield from abs_set(merlin.cam.num_images, xnum, wait=True) if ('dexela' in dets_by_name): dexela = dets_by_name['dexela'] yield from abs_set(dexela.hdf5.num_capture, xnum, wait=True) # yield from abs_set(dexela.hdf5.num_frames_chunks, xnum, wait=True) yield from abs_set(dexela.cam.num_images, xnum, wait=True) ion = flying_zebra.sclr yield from abs_set(ion.nuse_all, 2 * xnum) # arm the Zebra (start caching x positions) # @timer_wrapper def zebra_kickoff(): if row_start < row_stop: yield from kickoff(flying_zebra, xstart=xstart, xstop=xstop, xnum=xnum, dwell=dwell, wait=True) else: yield from kickoff(flying_zebra, xstart=xstop, xstop=xstart, xnum=xnum, dwell=dwell, wait=True) if verbose: t_zebkickoff = tic() yield from zebra_kickoff() if verbose: toc(t_zebkickoff, str='Zebra kickoff') if verbose: t_datacollect = tic() # arm SIS3820, note that there is a 1 sec delay in setting X # into motion so the first point *in each row* won't # normalize... yield from abs_set(ion.erase_start, 1) if verbose: toc(t_datacollect, str=' reset scaler') # trigger all of the detectors row_str = short_uid('row') if verbose: print('Data collection:') for d in flying_zebra.detectors: if verbose: print(f' triggering {d.name}') st = yield from bps.trigger(d, group=row_str) st.add_callback(lambda x: toc( t_datacollect, str= f" status object {datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S.%f')}" )) if (d.name == 'dexela'): yield from bps.sleep(1) if verbose: toc(t_datacollect, str=' trigger detectors') # yield from bps.sleep(1.5) if verbose: toc(t_datacollect, str=' sleep') # start the 'fly' def print_watch(*args, **kwargs): with open('/home/xf05id1/bluesky_output.txt', 'a') as f: f.write( datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S.%f\n')) # print(args) f.write(json.dumps(kwargs)) f.write('\n') st = yield from abs_set(xmotor, row_stop, group=row_str) # st.watch(print_watch) if verbose: toc(t_datacollect, str=' move start') if verbose and False: ttime.sleep(1) while (xmotor.motor_is_moving.get()): ttime.sleep(0.001) toc(t_datacollect, str=' move end') while (xs.settings.detector_state.get()): ttime.sleep(0.001) toc(t_datacollect, str=' xs done') while (sclr1.acquiring.get()): ttime.sleep(0.001) toc(t_datacollect, str=' sclr1 done') # wait for the motor and detectors to all agree they are done yield from bps.wait(group=row_str) st.wait() if verbose: toc(t_datacollect, str='Total time') # we still know about ion from above yield from abs_set(ion.stop_all, 1) # stop acquiring scaler # set speed back reset_scanner_velocity() # @timer_wrapper def zebra_complete(): yield from complete(flying_zebra) # tell the Zebra we are done if verbose: t_zebcomplete = tic() yield from zebra_complete() if verbose: toc(t_zebcomplete, str='Zebra complete') # @timer_wrapper def zebra_collect(): yield from collect(flying_zebra) # extract data from Zebra if verbose: t_zebcollect = tic() yield from zebra_collect() if verbose: toc(t_zebcollect, str='Zebra collect')
def fly_each_step(motor, step): def move_to_start_fly(): "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook" yield from abs_set(xmotor, xstart-delta, group='row') yield from one_1d_step([temp_nanoKB], motor, step) yield from bps.wait(group='row') # t_mvstartfly = tic() yield from move_to_start_fly() # toc(t_mvstartfly, str='Move to start fly each') # TODO Why are we re-trying the move? This should be fixed at # a lower level # yield from bps.sleep(1.0) # wait for the "x motor" to move x_set = xstart - delta x_dial = xmotor.user_readback.get() # Get retry deadband value and check against that i = 0 if (xmotor.egu == 'mm'): DEADBAND = 0.0005 else: DEADBAND = 0.02 while (np.abs(x_set - x_dial) > DEADBAND): if (i == 0): print('Waiting for motor to reach starting position...', end='', flush=True) i = i + 1 yield from mv(xmotor, xstart - delta) yield from bps.sleep(0.1) x_dial = xmotor.user_readback.get() if (i != 0): print('done') # Set the scan speed # Is abs_set(wait=True) or mv() faster? v = ((xstop - xstart) / (xnum-1)) / dwell # compute "stage speed" # yield from abs_set(xmotor.velocity, v, wait=True) # set the "stage speed" yield from mv(xmotor.velocity, v) # Change backlash speed for hf_stage.x and hf_stage.y if (hf_stage.x is xmotor): yield from mv(hf_stage.BACKLASH_SPEED_X, v) if (hf_stage.y is xmotor): yield from mv(hf_stage.BACKLASH_SPEED_Y, v) # set up all of the detectors # TODO we should be able to move this out of the per-line call?! if ('xs' in dets_by_name): xs = dets_by_name['xs'] # yield from abs_set(xs.hdf5.num_capture, xnum, wait=True) # yield from abs_set(xs.settings.num_images, xnum, wait=True) yield from mv(xs.hdf5.num_capture, xnum, xs.settings.num_images, xnum) if ('xs2' in dets_by_name): xs2 = dets_by_name['xs2'] # yield from abs_set(xs2.hdf5.num_capture, xnum, wait=True) # yield from abs_set(xs2.settings.num_images, xnum, wait=True) yield from mv(xs2.hdf5.num_capture, xnum, xs2.settings.num_images, xnum) if ('merlin' in dets_by_name): merlin = dets_by_name['merlin'] yield from abs_set(merlin.hdf5.num_capture, xnum, wait=True) yield from abs_set(merlin.cam.num_images, xnum, wait=True) if ('dexela' in dets_by_name): dexela = dets_by_name['dexela'] yield from abs_set(dexela.hdf5.num_capture, xnum, wait=True) yield from abs_set(dexela.cam.num_images, xnum, wait=True) ion = flying_zebra.sclr yield from abs_set(ion.nuse_all,xnum) # arm the Zebra (start caching x positions) # @timer_wrapper def zebra_kickoff(): yield from kickoff(flying_zebra, xstart=xstart, xstop=xstop, xnum=xnum, dwell=dwell, wait=True) # t_zebkickoff = tic() yield from zebra_kickoff() # toc(t_zebkickoff, str='Zebra kickoff') # arm SIS3820, note that there is a 1 sec delay in setting X # into motion so the first point *in each row* won't # normalize... yield from abs_set(ion.erase_start, 1) # trigger all of the detectors for d in flying_zebra.detectors: yield from bps.trigger(d, group='row') if (d.name == 'dexela'): yield from bps.sleep(1) yield from bps.sleep(1.5) # start the 'fly' yield from abs_set(xmotor, xstop + 1*delta, group='row') # move in x # wait for the motor and detectors to all agree they are done yield from bps.wait(group='row') # we still know about ion from above yield from abs_set(ion.stop_all, 1) # stop acquiring scaler # @timer_wrapper def zebra_complete(): yield from complete(flying_zebra) # tell the Zebra we are done # t_zebcomplete = tic() yield from zebra_complete() # toc(t_zebcomplete, str='Zebra complete') # @timer_wrapper def zebra_collect(): yield from collect(flying_zebra) # extract data from Zebra # t_zebcollect = tic() yield from zebra_collect() # toc(t_zebcollect, str='Zebra collect') # TODO what? if ('e_tomo' in xmotor.name): v_return = min(4, xmotor.velocity.high_limit) yield from mv(xmotor.velocity, v_return) if ('nano_stage' in xmotor.name): yield from mv(xmotor.velocity, 30) else: # set the "stage speed" yield from mv(xmotor.velocity, 1.0)
def fly_each_step(motor, step): "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook" # First, let 'scan' handle the normal y step, including a checkpoint. yield from one_1d_step([], motor, step) # yield from bps.sleep(1.0) # wait for the "x motor" to move # Now do the x steps. v = ((xstop - xstart) / (xnum - 1)) / dwell # compute "stage speed" yield from abs_set(xmotor, xstart - delta, wait=True) # ready to move # TODO Why are we re-trying the move? This should be fixed at # a lower level # yield from bps.sleep(1.0) # wait for the "x motor" to move x_set = xstart - delta x_dial = xmotor.user_readback.get() i = 0 while (np.abs(x_set - x_dial) > 0.0001): if (i == 0): print('Waiting for motor to reach starting position...', end='') i = i + 1 yield from abs_set(xmotor, xstart - delta, wait=True) yield from bps.sleep(1.0) x_dial = xmotor.user_readback.get() if (i != 0): print('done') yield from abs_set(xmotor.velocity, v, wait=True) # set the "stage speed" # set up all of the detectors # TODO we should be able to move this out of the per-line call?! if 'xs' in dets_by_name: xs = dets_by_name['xs'] yield from abs_set(xs.hdf5.num_capture, xnum, wait=True) yield from abs_set(xs.settings.num_images, xnum, wait=True) if 'xs2' in dets_by_name: xs2 = dets_by_name['xs2'] yield from abs_set(xs2.hdf5.num_capture, xnum, wait=True) yield from abs_set(xs2.settings.num_images, xnum, wait=True) if 'merlin' in dets_by_name: merlin = dets_by_name['merlin'] yield from abs_set(merlin.hdf5.num_capture, xnum, wait=True) yield from abs_set(merlin.cam.num_images, xnum, wait=True) if 'dexela' in dets_by_name: dexela = dets_by_name['dexela'] yield from abs_set(dexela.hdf5.num_capture, xnum, wait=True) yield from abs_set(dexela.cam.num_images, xnum, wait=True) ion = flying_zebra.sclr yield from abs_set(ion.nuse_all, xnum) # arm the Zebra (start caching x positions) yield from kickoff(flying_zebra, xstart=xstart, xstop=xstop, xnum=xnum, dwell=dwell, wait=True) # arm SIS3820, note that there is a 1 sec delay in setting X # into motion so the first point *in each row* won't # normalize... yield from abs_set(ion.erase_start, 1) # trigger all of the detectors for d in flying_zebra.detectors: yield from bps.trigger(d, group='row') yield from bps.sleep(1.5) # start the 'fly' yield from abs_set(xmotor, xstop + 1 * delta, group='row') # move in x # wait for the motor and detectors to all agree they are done yield from bps.wait(group='row') # yield from abs_set(xs.settings.acquire, 0) # stop acquiring images # we still know about ion from above yield from abs_set(ion.stop_all, 1) # stop acquiring scaler yield from complete(flying_zebra) # tell the Zebra we are done yield from collect(flying_zebra) # extract data from Zebra # TODO what? if ('e_tomo' in xmotor.name): v_return = min(4, xmotor.velocity.high_limit) yield from bps.mov(xmotor.velocity, v_return) else: # set the "stage speed" yield from bps.mov(xmotor.velocity, 1.0) # TODO wat # set the "stage speed" twice just in case yield from abs_set(xmotor.velocity, 1.0, wait=True)
def mona_core(detector_list, acquire, num=1): yield from bps.trigger(area_det, wait=False) yield from bp.scan(detector_list, motor, start, finish, num=num)
def mona_core(detectors, acquire, num=1): yield from bps.trigger(adsimdet, wait=False) yield from bp.count(detectors, num=num)
def add_daq_trigger(msg): if msg.obj is not daq: yield from bps.trigger(daq, group=msg.kwargs['group']) return (yield msg)
def take_image(self): yield from bps.stage(self) yield from bps.trigger(self, wait=True) yield from bps.unstage(self)
def _scan_(): count_time = count_time_base ar0 = terms.USAXS.center.AR.get() sy0 = s_stage.y.position for i, target_ar in enumerate(ar_series.stepper()): if useDynamicTime: if i / intervals < 0.33: count_time = count_time_base / 3 elif i / intervals < 0.66: count_time = count_time_base else: count_time = count_time_base * 2 # track ay & dy on scattered beam position target_ay = ay0 + _triangulate_(target_ar - ar0, SAD_mm) target_dy = dy0 + _triangulate_(target_ar - ar0, SDD_mm) # re-position the sample before each step target_sy = sy0 + i * terms.USAXS.sample_y_step.get() moves = [ a_stage.r, target_ar, a_stage.y, target_ay, d_stage.y, target_dy, s_stage.y, target_sy, scaler0.preset_time, count_time ] if terms.USAXS.useSBUSAXS.get(): # adjust the ASRP piezo on the AS side-bounce stage tanBragg = math.tan(reference * math.pi / 180) cosScatAngle = math.cos( (reference - target_ar) * math.pi / 180) diff = math.atan( tanBragg / cosScatAngle) * 180 / math.pi - reference # Note on asrp adjustment: NOTE: seems wrong, but may need to be revisited??? # use "-" when reflecting inboard towards storage ring (single bounce setup) # use "+" when reflecting outboard towards experimenters (channel-cut setup) ### on 2/06/2002 Andrew realized, that we are moving in wrong direction ## the sign change to - moves ASRP towards larger Bragg angles... ## verified experimentally - higher voltage on piezo = lower Bragg angle... ## and we need to INCREASE the Bragg Angle with increasing Q, to correct for tilt down... asrp_vdc = asrp0 - diff / terms.usaxs.asrp_degrees_per_VDC.get( ) moves += [as_stage.rp, asrp_vdc] # added for fuel spray users as indication that we are counting... moves += [fuel_spray_bit, 1] yield from user_data.set_state_plan( f"moving motors {i+1}/{intervals}") yield from bps.mv(*moves) # count yield from user_data.set_state_plan(f"counting {i+1}/{intervals}") yield from bps.trigger(scaler0, group="uascan_count") # start the scaler yield from bps.wait(group="uascan_count") # wait for the scaler # collect data for the primary stream yield from addDeviceDataAsStream(read_devices, "primary") if useDynamicTime: if i < intervals / 3: count_time = count_time_base / 2 elif intervals / 3 <= i < intervals * 2 / 3: count_time = count_time_base else: count_time = 2 * count_time_base
def _scaler_autoscale_(controls, count_time=0.05, max_iterations=9): """plan: internal: autoscale amplifiers for signals sharing a common scaler""" global _last_autorange_gain_ scaler = controls[0].scaler originals = {} originals["preset_time"] = scaler.preset_time.get() originals["delay"] = scaler.delay.get() originals["count_mode"] = scaler.count_mode.get() yield from bps.mv( scaler.preset_time, count_time, scaler.delay, 0.2, scaler.count_mode, "OneShot", ) last_gain_dict = _last_autorange_gain_[scaler.name] settling_time = AMPLIFIER_MINIMUM_SETTLING_TIME for control in controls: yield from bps.mv(control.auto.mode, AutorangeSettings.automatic) # faster if we start from last known autoscale gain gain = last_gain_dict.get(control.auto.gain.name) if gain is not None: # be cautious, might be unknown yield from control.auto.setGain(gain) last_gain_dict[control.auto.gain.name] = control.auto.gain.get() settling_time = max(settling_time, control.femto.settling_time.get()) yield from bps.sleep(settling_time) # Autoscale has converged if no gains change # Also, make sure no detector count rates are stuck at max complete = False for iteration in range(max_iterations): converged = [] # append True is convergence criteria is satisfied yield from bps.trigger(scaler, wait=True) #timeout=count_time+1.0) # amplifier sequence program (in IOC) will adjust the gain now for control in controls: # any gains changed? gain_now = control.auto.gain.get() gain_previous = last_gain_dict[control.auto.gain.name] converged.append(gain_now == gain_previous) last_gain_dict[control.auto.gain.name] = gain_now # are we topped up on any detector? max_rate = control.auto.max_count_rate.get() if isinstance(control.signal, ScalerChannel): # ophyd.ScalerCH actual_rate = control.signal.s.get() / control.scaler.time.get( ) elif isinstance(control.signal, EpicsSignalRO): # ophyd.EpicsScaler # actual_rate = control.signal.get() # FIXME raise RuntimeError("This scaler needs to divide by time") else: raise ValueError( f"unexpected control.signal: {control.signal}") converged.append(actual_rate <= max_rate) logger.debug( f"gain={gain_now} rate: {actual_rate} max: {max_rate} converged={converged}" ) if False not in converged: # all True? complete = True for control in controls: yield from bps.mv(control.auto.mode, "manual") logger.debug(f"converged: {converged}") break # no changes # scaler.stage_sigs = stage_sigs["scaler"] # restore starting conditions yield from bps.mv( scaler.preset_time, originals["preset_time"], scaler.delay, originals["delay"], scaler.count_mode, originals["count_mode"], ) if not complete and aps.inUserOperations: # bailed out early from loop logger.warning(f"converged={converged}") msg = f"FAILED TO FIND CORRECT GAIN IN {max_iterations} AUTOSCALE ITERATIONS" if RE.state != "idle": # don't raise if in summarize_plan() raise AutoscaleError(msg)
def scan_closure(): yield from bps.mv(det.cam.acquire_time, acquire_time) yield from bps.mv(det.cam.acquire_period, acquire_period) # ------------------- # collect white field # ------------------- # 1-1 monitor shutter status, auto-puase scan if beam is lost yield from bps.mv(A_shutter, 'open') yield from bps.install_suspender(suspend_A_shutter) # 1-2 move sample out of the way current_samx = samx.position current_samy = samy.position current_preci = preci.position dx = config['tomo']['sample_out_position']['samx'] dy = config['tomo']['sample_out_position']['samy'] dr = config['tomo']['sample_out_position']['preci'] yield from bps.mv(samx, current_samx + dx) yield from bps.mv(samy, current_samy + dy) yield from bps.mv(preci, current_preci + dr) # 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.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.trigger_and_read([det]) # 1-4 move sample back yield from bps.mv(samx, current_samx) yield from bps.mv(samy, current_samy) yield from bps.mv(preci, current_preci) # ------------------- # collect projections # ------------------- # 1-4.5 set frame type for an organized HDF5 archive yield from bps.mv(det.cam.frame_type, 1) # 1-5 quicly reset proc1 yield from bps.mv(det.proc1.reset_filter, 1) # 1-6 collect projections yield from motor_set_modulo(preci, 360.0) # configure the psofly interface yield from bps.mv( psofly.start, config['tomo']['omega_start'], psofly.end, config['tomo']['omega_end'], psofly.scan_control, "Standard", psofly.scan_delta, config['tomo']['omega_step'], psofly.slew_speed, slew_speed, preci.velocity, ROT_STAGE_FAST_SPEED, preci.acceleration, slew_speed / accl, ) # taxi yield from bps.mv(psofly.taxi, "Taxi") yield from bps.mv(preci.velocity, slew_speed) # ??? yield from bps.mv( det.cam.num_images, n_projections, det.cam.trigger_mode, "Overlapped", ) # start the fly scan yield from bps.trigger(det, group='fly') yield from bps.abs_set(psofly.fly, "Fly", group='fly') yield from bps.wait(group='fly') # ------------------ # 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, current_preci + dr) yield from bps.mv(samx, current_samx + dx) yield from bps.mv(samy, current_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.cam.num_images, n_frames * n_white) yield from bps.trigger_and_read([det]) # 1-9 move sample back yield from bps.mv(samx, current_samx) yield from bps.mv(samy, current_samy) yield from bps.mv(preci, current_preci) # ----------------- # 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])
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 _scaler_background_measurement_(control_list, count_time=0.2, num_readings=8): """plan: internal: measure amplifier backgrounds for signals sharing a common scaler""" scaler = control_list[0].scaler signals = [c.signal for c in control_list] stage_sigs = {} stage_sigs["scaler"] = scaler.stage_sigs # benign original = {} original["scaler.preset_time"] = scaler.preset_time.get() original["scaler.auto_count_delay"] = scaler.auto_count_delay.get() yield from bps.mv(scaler.preset_time, count_time, scaler.auto_count_delay, 0) for control in control_list: yield from bps.mv(control.auto.mode, AutorangeSettings.manual) for n in range(NUM_AUTORANGE_GAINS - 1, -1, -1): # reverse order # set gains settling_time = AMPLIFIER_MINIMUM_SETTLING_TIME for control in control_list: yield from control.auto.setGain(n) settling_time = max(settling_time, control.femto.settling_time.get()) yield from bps.sleep(settling_time) def getScalerChannelPvname(scaler_channel): try: return scaler_channel.pvname # EpicsScaler channel except AttributeError: return scaler_channel.chname.get() # ScalerCH channel # readings is a PV-keyed dictionary readings = {getScalerChannelPvname(s): [] for s in signals} for m in range(num_readings): yield from bps.sleep(0.05) # allow amplifier to stabilize on gain # count and wait to complete yield from bps.trigger(scaler, wait=True) #timeout=count_time+1.0) for s in signals: pvname = getScalerChannelPvname(s) value = s.get( ) # EpicsScaler channel value or ScalerCH ScalerChannelTuple if not isinstance(value, float): value = s.s.get() # ScalerCH channel value # logger.debug(f"scaler reading {m+1}: value: {value}") readings[pvname].append(value) s_range_name = f"gain{n}" for control in control_list: g = getattr(control.auto.ranges, s_range_name) pvname = getScalerChannelPvname(control.signal) # logger.debug(f"gain: {s_range_name} readings:{readings[pvname]}") yield from bps.mv( g.background, np.mean(readings[pvname]), g.background_error, np.std(readings[pvname]), ) msg = f"{control.nickname}" msg += f" range={n}" msg += f" gain={ _gain_to_str_(control.auto.gain.get())}" msg += f" bkg={g.background.get()}" msg += f" +/- {g.background_error.get()}" logger.info(msg) scaler.stage_sigs = stage_sigs["scaler"] yield from bps.mv( scaler.preset_time, original["scaler.preset_time"], scaler.auto_count_delay, original["scaler.auto_count_delay"], )