def grid_fly(flyer, y, ystart, ystop, ynum, x, xstart, xstop, xnum): generator = CompoundGenerator( generators=[ LineGenerator(y.name, "mm", ystart, ystop, ynum), LineGenerator(x.name, "mm", xstart, xstop, xnum), ], duration=0.1, ) mapping.configure(dict(generator=generator)) md = dict( hints=dict( gridding="rectilinear", dimensions=[([y.name], "primary"), ([x.name], "primary")], ), shape=(ynum, xnum), extents=([ystart, ystop], [xstart, xstop]), ) uid = yield from bps.open_run(md) yield from bps.kickoff(flyer, wait=True) yield from bps.collect(flyer, stream=True) yield from bps.checkpoint() yield from bps.complete(flyer, group="flyer") for _ in range(int(ynum * xnum * 0.1)): yield from bps.sleep(1) yield from bps.collect(flyer, stream=True) yield from bps.checkpoint() yield from bps.wait(group="flyer") yield from bps.collect(flyer, stream=True) yield from bps.close_run() return uid
def move_and_do_one(bt: Beamtime, sample_ind: tp.Union[int, str], plan_ind: tp.Union[int, str, tp.Generator], wait_time: float = 0., sample_x: str = "sample_x", sample_y: str = "sample_y", x_controller: str = "x_controller", y_controller: str = "y_controller") -> tp.Generator: """Move to the sample and conduct the plan.""" sample = translate_to_sample(bt, sample_ind) plan = translate_to_plan(bt, plan_ind, sample) xc = xpd_configuration[x_controller] yc = xpd_configuration[y_controller] x = float(get_from_sample(sample, sample_x)) y = float(get_from_sample(sample, sample_y)) yield from bps.checkpoint() print("Start moving to sample {} at ({}, {}).".format(sample_ind, x, y)) yield from bps.mv(xc, x, yc, y) print("Finish. ") yield from bps.checkpoint() print("Start sleeping for {} s.".format(wait_time)) yield from bps.sleep(wait_time) print("Wake up.") yield from bps.checkpoint() print("Start plan {} for sample {}".format(plan_ind, sample_ind)) yield from plan print("Finish.")
def cryostat_plan(bt: object, temp_motor: object, temperatures: List[float], posi_motor: object, positions: List[float], samples: List[int], exposures: List[float], temp_to_power: dict = None): """ The scanplan of cryostat measurement. Parameters ---------- bt : beamtime object The beamtime object. temp_motor : motor object The controller of temperature. temperatures : List[float] A list of temperature setpoints. posi_motor : motor object The controller of positions. positions : List[float] A list of positions. samples : List[int] A list of index of samples in bt. exposures : List[float] A list of exposure time. temp_to_power : dict A mapping from temperature range to power. The range is open at left and close at right. If None, default setting (see function 'get_heater_range') is used. Default None. Yields ------ Message of the plan """ samples = translate_to_sample(bt, samples) for temperature in temperatures: yield from set_power(temp_motor, temperature, temp_to_power) yield from checkpoint() yield from mv(temp_motor, temperature) yield from checkpoint() if not (len(positions) == len(samples) and len(samples) == len(exposures)): raise ValueError("Unmatched length of positions, samples and exposures: " f"{len(positions)}, {len(samples)}, {len(exposures)}.") for position, sample, exposure in zip(positions, samples, exposures): yield from mv(posi_motor, position) yield from checkpoint() yield from config_det_and_count([temp_motor, posi_motor], sample, exposure) yield from checkpoint()
def my_move_per_step(step: dict, pos_cache: dict): yield from bps.checkpoint() for motor, pos in step.items(): if pos == pos_cache[motor]: continue yield from bps.mv(motor, pos) pos_cache[motor] = pos
def simple_plan(): nonlocal flag try: yield from checkpoint() yield Msg('pause') except excp: flag = True
def inner_per_step(detectors, motor, step): # Set a checkpoint in case the scan is interrupted yield from checkpoint() """ # Notify the user where we are trying to move to goal_sample = inner_motor.position + inner_step_size goal_index = inner_motor.locate_1d(goal_sample) logger.info('Inner Step: Moving {0} to {1} (sample {2})'.format( inner_motor.name, goal_index, goal_sample)) """ # Move the motor to the inputted step yield from rel_set(inner_motor, inner_step_size, wait=True) if use_sequencer: # # Start and wait for the sequencer logger.info('Inner Step: Starting the sequencer') yield from abs_set(sequencer, 1, wait=True) # Wait the specified amount of time if wait: logger.info( "Inner Step: Waiting for {0} second(s)...".format(wait)) time.sleep(wait) # Fill the dataframe scan_positions.append(( outer_motor.position, #inner_motor.chip, inner_motor.position, #*inner_motor.index, #*inner_motor.coordinates ))
def close_shutter_stub(): """simple function to return a generator that yields messages to close the shutter""" yield from bps.abs_set( xpd_configuration["shutter"], XPD_SHUTTER_CONF["close"], wait=True ) yield from bps.checkpoint()
def motor_dark_step(detectors, motor, step): """ Take darks while moving motors, wait for all to be finished before taking light """ yield from bps.checkpoint() print('l120') # close the shutter #yield from _close_shutter_stub() COMMENTED OUT (dark per light) print('l123') # move motors don't wait yet. # Note for Soham: use `group=None` to ramp temp after dark collected # (Broken and replaced below) yield from bps.abs_set(motor, step, group="dark_motor") yield from bps.abs_set(motor, step, group="dark_motor") print('l127') # take dark (this has an internal wait on the readback) #yield from bps.trigger_and_read(list(detectors), name="dark") COMMENTED OUT (dark per light) print('l130') # (Broken) now wait for the motors to be done too yield from bps.wait(group="dark_motor") print('l133') # open shutter yield from open_shutter_stub() print('l136') # take data yield from bps.trigger_and_read(list(detectors) + [motor]) print('l139')
def open_shutter_stub(): """simple function to return a generator that yields messages to open the shutter""" yield from bps.abs_set( xpd_configuration["shutter"], XPD_SHUTTER_CONF["open"], wait=True ) yield from bps.sleep(glbl["shutter_sleep"]) yield from bps.checkpoint()
def xpdacq_trigger_and_read(detectors: list, name: str = "primary") -> typing.Generator: """Open shutter, wait, trigger and read detectors, close shutter.""" yield from bps.checkpoint() yield from xb.open_shutter_stub() yield from bps.sleep(xb.glbl["shutter_sleep"]) yield from bps.trigger_and_read(detectors, name=name) yield from xb.close_shutter_stub()
def dull_scan(mot, count, sig=None, sleep_time=0): if sig: thread = threading.Thread(target=sig_sequence, args=(sig, )) thread.start() for i in range(count): yield from checkpoint() try: yield from mv(mot, i) except: pass # make every step take 1s extra yield from sleep(sleep_time) yield from checkpoint() yield from create() yield from read(mot) yield from save() yield from checkpoint()
def measure(detectors, motor, step): # Perform step logger.debug("Measuring average at step %s ...", step) yield from checkpoint() yield from abs_set(motor, step, wait=True) # Measure the average return (yield from measure_average([motor, detector], num=average, filters=filters))
def move(): yield from checkpoint() grp = short_uid('set') for motor, pos in step.items(): if pos == pos_cache[motor]: # This step does not move this motor. continue yield from abs_set(motor, pos, group=grp) pos_cache[motor] = pos yield from wait(group=grp)
def move(): yield from checkpoint() grp = short_uid("set") for motor, pos in step.items(): if pos == pos_cache[motor]: # This step does not move this motor. continue yield from abs_set(motor, pos, group=grp) pos_cache[motor] = pos yield from wait(group=grp)
def one_1d_step(detectors, motor, step): """ Inner loop of a 1D step scan This is the default function for ``per_step`` param in 1D plans. """ yield from checkpoint() yield from abs_set(motor, step, wait=True) yield from trigger_and_read(list(detectors) + [motor], name="dark") return (yield from trigger_and_read(list(detectors) + [motor]))
def plan(): while True: for step in np.linspace(start, stop, num): yield from bps.abs_set(motor, step, wait=True) yield from bps.trigger_and_read(list(detectors) + [motor]) yield from bps.checkpoint() err = errorbar(lf.result, 'sigma') if err < err_thresh: break
def shutter_step(detectors, motor, step): """ customized step to ensure shutter is open before reading at each motor point and close shutter after reading """ yield from bps.checkpoint() yield from bps.abs_set(motor, step, wait=True) yield from open_shutter_stub() yield from bps.sleep(glbl["shutter_sleep"]) yield from bps.trigger_and_read(list(detectors) + [motor]) yield from close_shutter_stub()
def custom_step(detectors, motor, step): """ Inner loop of a 1D step scan This is the default function for ``per_step`` param in 1D plans. """ yield from checkpoint() print('Set attenuator to {}'.format(step)) yield from pause() yield from abs_set(motor, step, wait=True) return (yield from trigger_and_read(list(detectors) + [motor]))
def robot_wrapper(plan, sample): """Wrap a plan in load/unload messages. Parameters ---------- plan : a bluesky plan sample : dict must contain 'position'; optionally also 'geometry' Example ------- >>> plan = count([pe1c]) >>> new_plan = robot_wrapper(plan, {'position': 1}) """ yield from bps.checkpoint() yield from load_sample(sample['robot_identifier'], sample.get('robot_geometry', None)) yield from bps.checkpoint() yield from plan yield from bps.checkpoint() yield from unload_sample() yield from bps.checkpoint()
def per_step(detectors, motor, step): # Perform step yield from checkpoint() logger.debug("Measuring average at step {0} ...".format(step)) yield from abs_set(motor, step, wait=True) # Measure the average reads = (yield from measure_average(all_devices, num=average, filters=filters, *args, **kwargs)) # Fill the dataframe at this step with the centroid difference for fld in all_fields: df.loc[step, fld] = reads[fld]
def per_step(detectors, step: dict, pos_cache): """ customized step to ensure shutter is open before reading at each motor point and close shutter after reading """ yield from bps.checkpoint() for motor, pos in step.items(): yield from bps.mv(motor, pos) yield from bps.sleep(wait) yield from open_shutter_stub() yield from bps.sleep(glbl["shutter_sleep"]) yield from bps.trigger_and_read(list(detectors) + list(step.keys())) yield from close_shutter_stub()
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])
def _shutter_step(detectors, motor, step): """ customized step to ensure shutter is open before reading at each motor point and close shutter after reading """ yield from bps.checkpoint() yield from bps.abs_set(motor, step, wait=True) yield from bps.abs_set( xpd_configuration["shutter"], XPD_SHUTTER_CONF["open"], wait=True ) yield from bps.sleep(glbl['shutter_sleep']) yield from bps.trigger_and_read(list(detectors) + [motor]) yield from bps.abs_set( xpd_configuration["shutter"], XPD_SHUTTER_CONF["close"], wait=True )
def outer_per_step(detectors, motor, step): # Set a checkpoint in case the scan is interrupted yield from checkpoint() # Move the monochrometer to the inputted energy logger.info('Outer Step: Moving {0} to {1}'.format( outer_motor.name, step)) yield from abs_set(outer_motor, step, wait=True) # Define what we will do at every motor step def inner_per_step(detectors, motor, step): # Set a checkpoint in case the scan is interrupted yield from checkpoint() """ # Notify the user where we are trying to move to goal_sample = inner_motor.position + inner_step_size goal_index = inner_motor.locate_1d(goal_sample) logger.info('Inner Step: Moving {0} to {1} (sample {2})'.format( inner_motor.name, goal_index, goal_sample)) """ # Move the motor to the inputted step yield from rel_set(inner_motor, inner_step_size, wait=True) if use_sequencer: # # Start and wait for the sequencer logger.info('Inner Step: Starting the sequencer') yield from abs_set(sequencer, 1, wait=True) # Wait the specified amount of time if wait: logger.info( "Inner Step: Waiting for {0} second(s)...".format(wait)) time.sleep(wait) # Fill the dataframe scan_positions.append(( outer_motor.position, #inner_motor.chip, inner_motor.position, #*inner_motor.index, #*inner_motor.coordinates )) # Define the larger inner scan as a list_scan. We cannot use # rel_list_scan because it includes the reset_positions_decorator, # which we do not want to do yield from stub_wrapper( list_scan([], inner_motor, inner_steps, per_step=inner_per_step))
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) print(f"Start moving to beginning of the row") 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]) ## Uncomment this print(f"Finished moving to the beginning of the row") print(f"Fast axis: {xmotor.read()} Slow axis: {motor.read()}")
def solve_stub(detectors, motor, step, log=None): ''' This stub should be a bit more generic ''' bk_dev = detectors[0] yield from bps.checkpoint() yield from bps.mv(bk_dev.status, SolverState.unknown) def step_stub(detectors, motor, x): yield from bps.checkpoint() yield from bps.mv(motor, x) all_dev = list(detectors) + [motor] r = (yield from bps.trigger_and_read(all_dev)) return r def cb(val): cmd = partial(step_stub, detectors, motor, val) r = bridge.submit(cmd) val = r[motor.readback.name]['value'] return val - step bridge = setup_bridge() def run_solver(): a, b = -10, 10 r = brentq(cb, a, b) bridge.stopDelegation() return r yield from bps.mv(bk_dev.status, SolverState.searching) yield from bps.mv(bk_dev.target, step) thread = threading.Thread(target=run_solver, name='run_solver') thread.start() try: (yield from bridge_plan_stub(bridge, log=log)) except Exception: yield from bps.mv(bk_dev.status, SolverState.failed) else: yield from bps.mv(bk_dev.status, SolverState.finished) thread.join() del thread
def setup_plan(detectors, motors, *args, log=None, **kwargs): '''retrieve the actual status Reads the detectors and returns the state Args: detectors: detectors to read from Motors are passed for convenience for a user that intends to implement his own plan. ''' if log is None: log = logger yield from bps.checkpoint() log.info(f'Reading detectors {detectors}') r = (yield from bps.trigger_and_read(detectors)) log.info(f'setup returned {r}') return r
def custom_step(detectors, motor, step): """ Inner loop of a 1D step scan Modified the default function for ``per_step`` param in 1D plans. Add a pause to adjust the attenuator """ yield from checkpoint() print('Set attenuator to {}'.format(step)) # adjust DMM range if step < 12: yield from abs_set(dmm.volt_range_dc, 10) elif step < 30: yield from abs_set(dmm.volt_range_dc, 1) elif step >= 30: yield from abs_set(dmm.volt_range_dc, 0.1) yield from pause() yield from abs_set(motor, step, wait=True) return (yield from trigger_and_read(list(detectors) + [motor]))
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 step_scan(experiment, cfg_tomo): """ Collect projects with step motion """ # unpack devices det = experiment.det tomostage = experiment.tomostage 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, cfg_tomo['n_frames']) angs = np.arange( cfg_tomo['omega_start'], cfg_tomo['omega_end'] + cfg_tomo['omega_step'] / 2, cfg_tomo['omega_step'], ) for ang in angs: yield from bps.checkpoint() yield from bps.mv(tomostage.preci, ang) 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')