def two_wafer(det, wafer1md={'purpose':'testing'},wafer2md={'purpose':'testing'}): # don't try so hard # get the current offsets curr_offsets = [px.user_offset.get(),py.user_offset.get()] #move to the first wafer yield from wafer1() # align yield from align_wafer(xsp3,px,py,md=wafer1md) # do the 177 loc scan yield from bp.list_scan([det],px,-loc177[0],py,loc177[1],md=wafer1md) #reset the motors px.user_offset.set(curr_offsets[0]) py.user_offset.set(curr_offsets[1]) # move to wafer2 yield from wafer2() # align the sample yield from align_wafer(xsp3,px,py,md=wafer2md) # do the 177 loc scan yield from bp.list_scan([det],px,-loc177[0],py,loc177[1],md=wafer2md) # reset the motors px.user_offset.set(curr_offsets[0]) py.user_offset.set(curr_offsets[1]) # move back home yield from home()
def tomo_test(thetastart=90, thetastop=80, thetanumstep=3): theta_traj = np.linspace(thetastart, thetastop, thetanumstep) for theta_setpt in theta_traj: print('current angle') print(tomo_stage.theta.position) print('move angle to ' + str(theta_setpt)) # tomo_lab_z_initi = yield from abs_set(tomo_lab.lab_z, 0) this does not work tomo_lab_z_initi = yield from list_scan([], tomo_lab.lab_z, [0]) tomo_theta_set_gen = yield from list_scan([tomo_stage], tomo_stage.theta, [theta_setpt]) print('start running basic_scan') basic_scan_gen = yield from basic_scan() print('done running basic scan')
def listscan(self, motor, posList, nEvents, record=None, use_l3t=False, post=False): self.cleanup_RE() currPos = motor.wm() daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) try: RE(list_scan([daq], motor, posList)) except Exception: logger.debug('RE Exit', exc_info=True) finally: self.cleanup_RE() motor.mv(currPos) if post: run = get_run() message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format( name=motor.name, min1=posList[0], max1=posList[-1], num1=posList.size) self.elog.post(message, run=int(run))
def list3scan(self, m1, p1, m2, p2, m3, p3, nEvents, record=None, use_l3t=False): self.cleanup_RE() currPos1 = m1.wm() currPos2 = m2.wm() currPos3 = m3.wm() daq.configure(nEvents, record=record, controls=[m1, m2, m3], use_l3t=use_l3t) try: RE(list_scan([daq], m1, p1, m2, p2, m3, p3)) except Exception: logger.debug('RE Exit', exc_info=True) finally: self.cleanup_RE() m1.mv(currPos1) m2.mv(currPos2) m3.mv(currPos3)
def step_list_plan(detectors, motor, positions_grid, name=''): """ Example ------- >>> Ni_energy_grid, time_grid = get_xia_energy_grid(8333, -200, -50, 30, 16, 10, 0.2, 0.04) >>> Ni_positions_grid = xray.energy2encoder(Ni_energy_grid) / 360000 >>> RE(step_list_plan([xia1, pba1.adc7], hhm.theta, Ni_positions_grid), LivePlot('xia1_mca1_roi0_sum', 'hhm_theta')) """ plan = bp.list_scan(detectors, motor, list(positions_grid), md={ 'name': name, 'plan_name': 'step_list_plan' }) flyers = [] for det in detectors: if hasattr(det, 'kickoff'): flyers.append(det) if len(flyers) > 0: plan = bpp.fly_during_wrapper(plan, flyers) yield from plan
def _inner_qxscan(): yield from list_scan(detectors + extras, *args, per_step=per_step, md=_md) # put original times back. for det, preset in _ct.items(): yield from mv(det.preset_monitor, preset)
def listscan(self, motor, posList, nEvents, record=None, use_l3t=False): self.cleanup_RE() currPos = motor.wm() daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) try: RE(list_scan([daq], motor, posList)) except Exception: logger.debug('RE Exit', exc_info=True) finally: self.cleanup_RE() motor.mv(currPos)
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 scan_once(): return (yield from list_scan( [sclr, xs], mono.energy, ept, md={ "scan_title": scan_title, "operator": operator, "user_input": { "element": element, "E_sections": E_sections, "dwell_time": dwell_time, "step_size": step_size, }, "derived_input": {}, }))
def loc_cust_scan(dets, cust_locs, skip=0, md={}): """loc_cust_scan scans across a library with 177 points, measuring each detector in dets :param dets: detectors to be :type dets: list :param cust_locs: (2, N) array denoting N locations to scan. First list will direct px and the second will direct py :type cust_locs: list :param skip: number of data points to skip :yield: things from list_scan :rtype: Msg """ # format locations and stage motors if I0 not in dets: dets.append(I0) if I1 not in dets: dets.append(I1) if xsp3 in dets: yield from bps.mv(xsp3.total_points, len(cust_locs[0])) # inject logic via per_step class stateful_per_step: def __init__(self, skip): self.skip = skip self.cnt = 0 #print(self.skip, self.cnt) def __call__(self, detectors, step, pos_cache): """ has signature of bps.one_and_step, but with added logic of skipping a point if it is outside of provided radius """ if self.cnt < self.skip: # if not enough skipped self.cnt += 1 pass else: yield from bps.one_nd_step(detectors, step, pos_cache) per_stepper = stateful_per_step(skip) yield from bp.list_scan(dets, s_stage.px, list(cust_locs[0]), s_stage.py, list(cust_locs[1]), per_step=per_stepper, md=md)
def rand_exp_test(det, num, tcounts, img_key = 'pilatus1M_image'): ''' take a series of random exposures within the wafer area set the exposure time based on the maximum signal that you see :param num: number of exposures to take :type num: int ''' # set the current exposure time #det.cam.acquire_time.set(10) curr = det.cam.acquire_time.get() # get the current location wx = px.user_readback.get() wy = py.user_readback.get() # generate num many random positions within the wafer xPos = np.random.randint(wx-20,high=wx+20,size=num) yPos = np.random.randint(wy-20,high=wy+20,size=num) xPos = np.sort(xPos) yPos = np.sort(yPos) # scan through each coordinate and take an image yield from bp.list_scan([det],px,xPos,py,yPos) # grab the data results = db[-1].table(fill=True)['pilatus1M_image'] # set based on the maximum signal that you find top = 0 for img in results: arr = img[0] print('Max Pixel Value ' + str(np.max(arr))) if np.max(arr) > top: top = np.max(arr) # calculate the new exposure time new = (curr*tcounts/top) # set the new exposure time det.cam.acquire_time.set(new) print(f'New exposure time of {new} seconds')
def Tlist(dets, exposure, T_list): """defines a flexible scan with user-specified temperatures A frame is exposed for the given exposure time at each of the user-specified temperatures Parameters ---------- dets : list list of objects that represent instrument devices. In xpdAcq, it is defaulted to area detector. exposure : float total time of exposure in seconds for area detector T_list : list a list of temperature where a scan will be run Note ---- area detector and temperature controller will always be the one configured in global state. To find out which these are, please using following commands: >>> glbl.area_det >>> glbl.temp_controller To interrogate which devices are currently in use. """ pe1c, = dets # setting up area_detector and temp_controller (num_frame, acq_time, computed_exposure) = _configure_pe1c(exposure) T_controller = glbl.temp_controller xpdacq_md = {'sp_time_per_frame': acq_time, 'sp_num_frames': num_frame, 'sp_requested_exposure': exposure, 'sp_computed_exposure': computed_exposure, 'sp_T_list': T_list, 'sp_type': 'Tlist', 'sp_uid': str(uuid.uuid4()), 'sp_plan_name': 'Tlist' } # pass xpdacq_md to as additional md to bluesky plan plan = bp.list_scan([glbl.area_det], T_controller, T_list, md=xpdacq_md) plan = bp.subs_wrapper(plan, LiveTable([glbl.area_det, T_controller])) yield from plan
def line_scan(self, m1, start1, stop1, steps1, m2, start2, stop2, steps2, nEvents, record=None, use_l3t=False, post=False): # m1 is the slow motor, m2 is the fast motor self.cleanup_RE() currPos1 = m1.wm() currPos2 = m2.wm() if type(steps1)==int: m1_pos = np.linspace(start1, stop1, steps1) elif type(steps1)==float: m1_pos = np.arange(start1, stop1+steps1, steps1) else: return if type(steps2)==int: m2_pos = np.linspace(start2, stop2, steps2) elif type(steps2)==float: m2_pos = np.arange(start2, stop2+steps2, steps2) else: return for m1pos in m1_pos: # move to next row and wait until motor gets there m1.mv(m1pos, wait=True) daq.configure(nEvents, record=record, controls=[m2], use_l3t=use_l3t) try: RE(list_scan([daq],m2, m2_pos)) except Exception: logger.debug('RE Exit', exc_info=True) finally: self.cleanup_RE() if post: # get run number run = get_run() message = '{name1}={pos:.3f}, and scan {name2} from {min2:.3f} to {max2:.3f} in {num2} steps'.format(name1=m1.name,pos=m1pos,name2=m2.name, min2=np.min(m2_pos),max2=np.max(m2_pos), num2=np.size(m2_pos)) self.elog.post(message,run=int(run)) m1.mv(currPos1) m2.mv(currPos2)
def step_list_plan(detectors, motor, positions_grid, name = ''): """ Example ------- >>> Ni_energy_grid, time_grid = get_xia_energy_grid(8333, -200, -50, 30, 16, 10, 0.2, 0.04) >>> Ni_positions_grid = xray.energy2encoder(Ni_energy_grid) / 360000 >>> RE(step_list_plan([xia1, pba1.adc7], hhm.theta, Ni_positions_grid), LivePlot('xia1_mca1_roi0_sum', 'hhm_theta')) """ plan = bp.list_scan(detectors, motor, list(positions_grid), md={'name': name, 'plan_name': 'step_list_plan'}) flyers = [] for det in detectors: if hasattr(det, 'kickoff'): flyers.append(det) if len(flyers) > 0: plan = bpp.fly_during_wrapper(plan, flyers) yield from plan
def inner_scan(): try: for i in range(len(ss)): yield from bps.mv(scan_motor, ss[i]) for j in range(n_shots): x = (next(item['pos'] for item in cycle_xx if item["status"] is False)) y = (next(item['pos'] for item in cycle_yy if item["status"] is False)) yield from bpp.stub_wrapper( bp.list_scan(detectors, x_motor, [x], y_motor, [y])) update_sample(sample, path, (n_shots * len(ss))) except Exception: current_position = x_motor.position try: last_index = next((index for (index, d) in enumerate(xx) if np.isclose(d["pos"], current_position))) update_sample(sample, path, (last_index - next_index + 1)) except Exception: logger.warning( 'Could not find the index in the targets list ' 'for the current motor value: %d', current_position)
def tuning_scan(motor, detector, scan_range, scan_step, n_tries = 3, **kwargs): sys.stdout = kwargs.pop('stdout', sys.stdout) channel = detector.hints['fields'][0] for jj in range(n_tries): motor_init_position = motor.read()[motor.name]['value'] min_limit = motor_init_position - scan_range / 2 max_limit = motor_init_position + scan_range / 2 + scan_step / 2 scan_positions = np.arange(min_limit,max_limit,scan_step) scan_range = (scan_positions[-1] - scan_positions[0]) min_threshold = scan_positions[0] + scan_range / 10 max_threshold = scan_positions[-1] - scan_range / 10 plan = bp.list_scan([detector], motor,scan_positions) if hasattr(detector, 'kickoff'): plan = bpp.fly_during_wrapper(plan, [detector]) uid = (yield from plan) if uid: hdr = db[uid] if detector.polarity == 'pos': idx = getattr(hdr.table()[channel], 'idxmax')() elif detector.polarity == 'neg': idx = getattr(hdr.table()[channel], 'idxmin')() motor_pos = hdr.table()[motor.name][idx] print(f'New motor position {motor_pos}') if motor_pos < min_threshold: yield from bps.mv(motor,min_limit) if jj+1 < n_tries: print(f' Starting {jj+2} try') elif max_threshold < motor_pos: print('max') if jj+1 < n_tries: print(f' Starting {jj+2} try') yield from bps.mv(motor, max_limit) else: yield from bps.mv(motor, motor_pos) break
def test_multi_motor_list_scan(RE, hw): expected_data = [{ 'motor2': 18, 'motor2_setpoint': 18, 'det': 1, 'motor1': 6, 'motor1_setpoint': 6 }, { 'motor2': 28, 'motor2_setpoint': 28, 'det': 1, 'motor1': 7, 'motor1_setpoint': 7 }, { 'motor2': 38, 'motor2_setpoint': 38, 'det': 1, 'motor1': 8, 'motor1_setpoint': 8 }] scan = bp.list_scan([hw.det], hw.motor1, [6, 7, 8], hw.motor2, [18, 28, 38]) multi_traj_checker(RE, scan, expected_data)
def xanes_plan(erange=[], estep=[], acqtime=1., samplename='', filename='', det_xs=xs, harmonic=1, detune=0, align=False, align_at=None, roinum=1, shutter=True, per_step=None): ''' erange (list of floats): energy ranges for XANES in eV, e.g. erange = [7112-50, 7112-20, 7112+50, 7112+120] estep (list of floats): energy step size for each energy range in eV, e.g. estep = [2, 1, 5] acqtime (float): acqusition time to be set for both xspress3 and preamplifier samplename (string): sample name to be saved in the scan metadata filename (string): filename to be added to the scan id as the text output filename det_xs (xs3 detector): the xs3 detector used for the measurement harmonic (odd integer): when set to 1, use the highest harmonic achievable automatically. when set to an odd integer, force the XANES scan to use that harmonic detune: add this value to the gap of the undulator to reduce flux [keV] align: perform peakup_fine before scan [bool] align_at: energy at which to align, default is average of the first and last energy points roinum: select the roi to be used to calculate the XANES spectrum shutter: instruct the scan to control the B shutter [bool] per_step: use a custom function for each energy point ''' # Make sure user provided correct input if (erange is []): raise AttributeError( "An energy range must be provided in a list by means of the 'erange' keyword." ) if (estep is []): raise AttributeError( "A list of energy steps must be provided by means of the 'esteps' keyword." ) if (not isinstance(erange, list)) or (not isinstance(estep, list)): raise TypeError("The keywords 'estep' and 'erange' must be lists.") if (len(erange) - len(estep) is not 1): raise ValueError("The 'erange' and 'estep' lists are inconsistent; " \ + 'c.f., erange = [7000, 7100, 7150, 7500], estep = [2, 0.5, 5] ') if (type(roinum) is not list): roinum = [roinum] if (detune is not 0): yield from abs_set(energy.detune, detune) # Record relevant meta data in the Start document, defined in 90-usersetup.py # Add user meta data scan_md = {} get_stock_md(scan_md) scan_md['sample'] = {'name': samplename} scan_md['scaninfo'] = { 'type': 'XANES', 'ROI': roinum, 'raster': False, 'dwell': acqtime } scan_md['scan_input'] = str(np.around(erange, 2)) + ', ' + str( np.around(estep, 2)) # Convert erange and estep to numpy array ept = np.array([]) erange = np.array(erange) estep = np.array(estep) # Calculation for the energy points for i in range(len(estep)): ept = np.append(ept, np.arange(erange[i], erange[i + 1], estep[i])) ept = np.append(ept, np.array(erange[-1])) # Debugging, is this needed? is this recorded in scanoutput? # Convert energy to bragg angle egap = np.array(()) ebragg = np.array(()) exgap = np.array(()) for i in ept: eg, eb, ex = energy.forward(i) egap = np.append(egap, eg) ebragg = np.append(ebragg, eb) exgap = np.append(exgap, ex) # Register the detectors det = [ring_current, sclr1, det_xs] # Setup xspress3 yield from abs_set(det_xs.external_trig, False) yield from abs_set(det_xs.settings.acquire_time, acqtime) yield from abs_set(det_xs.total_points, len(ept)) # Setup the scaler yield from abs_set(sclr1.preset_time, acqtime) # Setup DCM/energy options if (harmonic != 1): yield from abs_set(energy.harmonic, harmonic) # Prepare to peak up DCM at middle scan point if (align_at is not None): align = True if (align is True): if (align_at is None): align_at = 0.5 * (ept[0] + ept[-1]) print("Aligning at ", align_at) yield from abs_set(energy, align_at, wait=True) else: print("Aligning at ", align_at) yield from abs_set(energy, float(align_at), wait=True) # Peak up DCM at first scan point if (align is True): yield from peakup_fine(shutter=shutter) # Setup the live callbacks livecallbacks = [] # Setup Raw data livetableitem = ['energy_energy', 'sclr_i0', 'sclr_it'] roi_name = 'roi{:02}'.format(roinum[0]) roi_key = [] roi_key.append(getattr(det_xs.channel1.rois, roi_name).value.name) try: roi_key.append(getattr(xs.channel2.rois, roi_name).value.name) roi_key.append(getattr(xs.channel3.rois, roi_name).value.name) except NameError: pass livetableitem.append(roi_key[0]) livecallbacks.append(LiveTable(livetableitem)) liveploty = roi_key[0] liveplotx = energy.energy.name def my_factory(name): fig = plt.figure(num=name) ax = fig.gca() return fig, ax # liveplotfig = plt.figure('Raw XANES') # livecallbacks.append(LivePlot(liveploty, x=liveplotx, fig=liveplotfig)) livecallbacks.append( HackLivePlot(liveploty, x=liveplotx, fig_factory=partial(my_factory, name='Raw XANES'))) # Setup normalization liveploty = 'sclr_i0' i0 = 'sclr_i0' # liveplotfig2 = plt.figure('I0') # livecallbacks.append(LivePlot(liveploty, x=liveplotx, fig=liveplotfig2)) livecallbacks.append( HackLivePlot(liveploty, x=liveplotx, fig_factory=partial(my_factory, name='I0'))) # Setup normalized XANES # livenormfig = plt.figure('Normalized XANES') # livecallbacks.append(NormalizeLivePlot(roi_key[0], x=liveplotx, norm_key = i0, fig=livenormfig)) livecallbacks.append( NormalizeLivePlot(roi_key[0], x=liveplotx, norm_key=i0, fig_factory=partial(my_factory, name='Normalized XANES'))) def after_scan(name, doc): if (name != 'stop'): print( "You must export this scan data manually: xanes_afterscan_plan(doc[-1], <filename>, <roinum>)" ) return xanes_afterscan_plan(doc['run_start'], filename, roinum) logscan_detailed('xanes') def at_scan(name, doc): scanrecord.current_scan.put(doc['uid'][:6]) scanrecord.current_scan_id.put(str(doc['scan_id'])) # Not sure if RE should be here, but not sure what to make it # scanrecord.current_type.put(RE.md['scaninfo']['type']) scanrecord.current_type.put(scan_md['scaninfo']['type']) scanrecord.scanning.put(True) def finalize_scan(): yield from abs_set(energy.move_c2_x, True) yield from abs_set(energy.harmonic, 1) if (shutter is True): yield from mv(shut_b, 'Close') if (detune is not None): yield from abs_set(energy.detune, 0) scanrecord.scanning.put(False) energy.move(ept[0]) myscan = list_scan(det, energy, list(ept), per_step=per_step, md=scan_md) myscan = finalize_wrapper(myscan, finalize_scan) # Open b shutter if (shutter is True): yield from mv(shut_b, 'Open') return (yield from subs_wrapper(myscan, { 'all': livecallbacks, 'stop': after_scan, 'start': at_scan }))
def xanes_plan(erange=[], estep=[], harmonic=1, correct_c2_x=True, correct_c1_r=False, detune=None, acqtime=1., roinum=1, delaytime=0.00, struck=True, fluor=True, samplename='', filename='', shutter=True, align=False, align_at=None, per_step=None): ''' erange (list of floats): energy ranges for XANES in eV, e.g. erange = [7112-50, 7112-20, 7112+50, 7112+120] estep (list of floats): energy step size for each energy range in eV, e.g. estep = [2, 1, 5] harmonic (odd integer): when set to 1, use the highest harmonic achievable automatically. when set to an odd integer, force the XANES scan to use that harmonic correct_c2_x (boolean or float): when True, automatically correct the c2x when False, c2x will not be moved during the XANES scan correct_c1_r (False or float): when False, c1r will not be moved during a XANES scan when set to a float, c1r will be set to that value before a XANES scan but will remain the same during the whole scan detune: add this value to the gap of the undulator to reduce flux [mm] acqtime (float): acqusition time to be set for both xspress3 and preamplifier roinum: select the roi to be used to calculate the XANES spectrum delaytime: reduce acquisition time of F460 by this value [sec] struck: Use the SRS and Struck scaler for the ion chamber and diode. Set to False to use the F460. fluorescence: indicate the presence of fluorescence data [bool] samplename (string): sample name to be saved in the scan metadata filename (string): filename to be added to the scan id as the text output filename shutter: instruct the scan to control the B shutter [bool] align: control the tuning of the DCM pointing before each XANES scan [bool] align_at: energy at which to align, default is the first energy point ''' ept = numpy.array([]) det = [] filename = filename last_time_pt = time.time() ringbuf = collections.deque(maxlen=10) c2pitch_kill = EpicsSignal("XF:05IDA-OP:1{Mono:HDCM-Ax:P2}Cmd:Kill-Cmd") xs.external_trig.put(False) #make sure user provided correct input if erange is []: raise AttributeError( "An energy range must be provided in a list by means of the 'erange' keyword." ) if estep is []: raise AttributeError( "A list of energy steps must be provided by means of the 'esteps' keyword." ) if (not isinstance(erange, list)) or (not isinstance(estep, list)): raise TypeError("The keywords 'estep' and 'erange' must be lists.") if len(erange) - len(estep) is not 1: raise ValueError("The 'erange' and 'estep' lists are inconsistent;"\ +'c.f., erange = [7000, 7100, 7150, 7500], estep = [2, 0.5, 5] ') if type(roinum) is not list: roinum = [roinum] if detune is not None: yield from abs_set(energy.detune, detune) #record relevant meta data in the Start document, defined in 90-usersetup.py metadata_record() #add user meta data RE.md['sample'] = {'name': samplename} RE.md['scaninfo'] = { 'type': 'XANES', 'ROI': roinum, 'raster': False, 'dwell': acqtime } RE.md['scan_input'] = str(np.around(erange, 2)) + ', ' + str( np.around(estep, 2)) #convert erange and estep to numpy array erange = numpy.array(erange) estep = numpy.array(estep) #calculation for the energy points for i in range(len(estep)): ept = numpy.append(ept, numpy.arange(erange[i], erange[i + 1], estep[i])) ept = numpy.append(ept, numpy.array(erange[-1])) # Debugging # Convert energy to bragg angle egap = np.array(()) ebragg = np.array(()) exgap = np.array(()) for i in ept: # Convert from eV to keV # if (i > 4500): # i = i / 1000 # Convert keV to bragg angle #b, _, _ = energy.energy_to_positions(i, 5, 0) eg, eb, ex = energy.forward(i) egap = np.append(egap, eg) ebragg = np.append(ebragg, eb) exgap = np.append(exgap, ex) # print(ebragg) #register the detectors det = [ring_current] if struck == True: det.append(sclr1) else: det.append(current_preamp) if fluor == True: det.append(xs) #setup xspress3 yield from abs_set(xs.settings.acquire_time, acqtime) yield from abs_set(xs.total_points, len(ept)) #setup the preamp if struck == True: yield from abs_set(sclr1.preset_time, acqtime) else: yield from abs_set(current_preamp.exp_time, acqtime - delaytime) #setup dcm/energy options if correct_c2_x is False: yield from abs_set(energy.move_c2_x, False) if correct_c1_r is not False: yield from abs_set(dcm.c1_roll, correct_c1_r) if harmonic != 1: yield from abs_set(energy.harmonic, harmonic) #prepare to peak up DCM at first scan point if align_at is not None: align = True if align is True: if align_at == None: yield from abs_set(energy, ept[0], wait=True) else: print("aligning at ", align_at) yield from abs_set(energy, float(align_at), wait=True) # energy.u_gap.corrfunc_dis.put(1) #open b shutter if shutter is True: #shut_b.open() yield from mv(shut_b, 'Open') #yield from abs_set(shut_b,1,wait=True) #peak up DCM at first scan point if align is True: ps = PeakStats(dcm.c2_pitch.name, 'sclr_i0') e_value = energy.energy.get()[1] # if e_value < 10.: # yield from abs_set(sclr1.preset_time,0.1, wait = True) # peakup = scan([sclr1], dcm.c2_pitch, -19.335, -19.305, 31) # else: # yield from abs_set(sclr1.preset_time,1., wait = True) # peakup = scan([sclr1], dcm.c2_pitch, -19.355, -19.320, 36) if e_value < 14.: sclr1.preset_time.put(0.1) else: sclr1.preset_time.put(1.) peakup = scan([sclr1], dcm.c2_pitch, -19.320, -19.360, 41) peakup = subs_wrapper(peakup, ps) yield from peakup yield from abs_set(dcm.c2_pitch, ps.cen, wait=True) #ttime.sleep(10) #yield from abs_set(c2pitch_kill, 1) #setup the live callbacks myscan = list_scan(det, energy, list(ept), per_step=per_step) livecallbacks = [] livetableitem = ['energy_energy'] if struck == True: livetableitem = livetableitem + ['sclr_i0', 'sclr_it'] else: livetableitem = livetableitem + [ 'current_preamp_ch0', 'current_preamp_ch2' ] if fluor == True: roi_name = 'roi{:02}'.format(roinum[0]) roi_key = [] roi_key.append(getattr(xs.channel1.rois, roi_name).value.name) roi_key.append(getattr(xs.channel2.rois, roi_name).value.name) roi_key.append(getattr(xs.channel3.rois, roi_name).value.name) livetableitem.append(roi_key[0]) livecallbacks.append(LiveTable(livetableitem)) liveploty = roi_key[0] liveplotx = energy.energy.name liveplotfig = plt.figure('raw xanes') elif struck == True: liveploty = 'sclr_it' liveplotx = energy.energy.name liveplotfig = plt.figure('raw xanes') # livecallbacks.append(LiveTable([sclr1, xs, energy])) livecallbacks.append(LivePlot(liveploty, x=liveplotx, fig=liveplotfig)) #livecallbacks.append(LivePlot(liveploty, x=liveplotx, ax=plt.gca(title='raw xanes'))) if struck == True: liveploty = 'sclr_i0' i0 = 'sclr_i0' else: liveploty = 'current_preamp_ch2' i0 = 'current_preamp_ch2' liveplotfig2 = plt.figure('i0') livecallbacks.append(LivePlot(liveploty, x=liveplotx, fig=liveplotfig2)) #livecallbacks.append(LivePlot(liveploty, x=liveplotx, ax=plt.gca(title='incident intensity'))) livenormfig = plt.figure('normalized xanes') if fluor == True: livecallbacks.append( NormalizeLivePlot(roi_key[0], x=liveplotx, norm_key=i0, fig=livenormfig)) #livecallbacks.append(NormalizeLivePlot(roi_key[0], x=liveplotx, norm_key = i0, ax=plt.gca(title='normalized xanes'))) else: livecallbacks.append( NormalizeLivePlot('sclr_it', x=liveplotx, norm_key=i0, fig=livenormfig)) #livecallbacks.append(NormalizeLivePlot(roi_key[0], x=liveplotx, norm_key = i0, ax=plt.gca(title='normalized xanes'))) def after_scan(name, doc): if name != 'stop': print( "You must export this scan data manually: xanes_afterscan_plan(doc[-1], <filename>, <roinum>)" ) return xanes_afterscan_plan(doc['run_start'], filename, roinum) logscan_detailed('xanes') def at_scan(name, doc): scanrecord.current_scan.put(doc['uid'][:6]) scanrecord.current_scan_id.put(str(doc['scan_id'])) scanrecord.current_type.put(RE.md['scaninfo']['type']) scanrecord.scanning.put(True) def finalize_scan(): # yield from abs_set(energy.u_gap.corrfunc_en,1) # disabled to test if # undulator gets stuck -AMK yield from abs_set(energy.move_c2_x, True) yield from abs_set(energy.harmonic, 1) scanrecord.scanning.put(False) if shutter == True: yield from mv(shut_b, 'Close') if detune is not None: energy.detune.put(0) del RE.md['sample']['name'] del RE.md['scaninfo'] myscan = list_scan(det, energy, list(ept), per_step=per_step) # myscan = list_scan(det, energy, list(ept), per_step=per_step(detectors, motor, step)) # myscan = list_scan(det, energy.bragg, list(ebragg), energy.u_gap, list(egap), energy.c2_x, list(exgap)) # myscan = scan_nd(det, energy.bragg, list(ebragg), energy.u_gap, list(egap), energy.c2_x, list(exgap)) myscan = finalize_wrapper(myscan, finalize_scan) return (yield from subs_wrapper(myscan, { 'all': livecallbacks, 'stop': after_scan, 'start': at_scan }))
def listscan(self, motor, posList, nEvents, record=True): currPos = motor.wm() daq.configure(nEvents, record=record, controls=[motor]) RE(list_scan([daq], motor, posList)) motor.mv(currPos)
def Tramp(sample, exposure, start, stop, step): Tpoints = np.arange(start, stop, step) plan = subs_wrapper(list_scan([pec1], cs700, points), LiveTable([cs700])) # plan = robot_wrapper(plan, sample) yield from plan
def test_ascan(RE, hw): traj = [1, 2, 3] scan = bp.list_scan([hw.det], hw.motor, traj) traj_checker(RE, scan, traj)
def daq_list_scan(*args, per_step=None, md=None): """ Scan through a multi-motor list trajectory with DAQ support. This is an LCLS-I DAQ version of ``bluesky``'s built-in `bluesky.plans.list_scan` plan. It also returns the motors to their starting points after the scan is complete. Parameters ---------- detectors : list, optional List of 'readable' objects to read at every step. *args : For one dimension, ``motor, [point1, point2, ....]``. In general: .. code-block:: python motor1, [point1, point2, ...], motor2, [point1, point2, ...], ..., motorN, [point1, point2, ...] Motors can be any 'settable' object (motor, temp controller, etc.) events : int, optional Number of events to take at each step. If omitted, uses the duration argument or the last configured value. duration : int or float, optional Duration of time to spend at each step. If omitted, uses the events argument or the last configured value. record : bool, optional Whether or not to record the run in the DAQ. Defaults to True because we don't want to accidentally skip recording good runs. use_l3t : bool, optional Whether or not the use the l3t filter for the events argument. Defaults to False to avoid confusion from unconfigured filters. per_step : callable, optional Hook for customizing action of inner loop (messages per step). See docstring of `bluesky.plan_stubs.one_nd_step` (the default) for details. md : dict, optional Additional metadata to include in the start document. Note ---- The events, duration, record, and use_l3t arguments come from the :py:func:`nabs.preprocessors.daq_step_scan_decorator`. """ if isinstance(args[0], list): detectors = args[0] scan_args = args[1:] else: detectors = [] scan_args = args return (yield from bp.list_scan(detectors, *scan_args, per_step=per_step, md=md))
def tomo_fullfield(thetastart = -90, thetastop = 90, numproj = 361, ffwait = 2, acqtime = 0.002, record_preamp = True, preamp_acqtime = None, num_darkfield = 10, dfwait = 2, num_whitefield = 10, wf_sam_movrx = 0, wf_sam_movry = -1, wfwait = 2, eventlog_list = ['pcoedge_tiff_file_name'] ): ''' argurments: thetastart (float): angle for the start of the fullfied scan, in degree thetastop (float): angle for the stop of the fullfied scan, includsive, in degree numproj (int): number of projections to collected within the angular range from thetastart to thetastop acqtime (float): acqusition time for pco.edge camera, in second record_preamp (boolean, default = True): when True, the current_preamp will be included in detecotr list in all data collection preamp_acqtime (float): record_preamp is True, this value will be used to set the acqsition time for the current_preamp, if not defined, the same acqusition time as the pco.edge will be used, as set in acqtime num_darkfield (int): number of dark field images collected before the scan; shutter will be atuomatically closed/opened before/after this collection num_whitefield (int): number of white field images collected before and after the scan, sample will be moved out of field of view prior to this collection, as defined in wf_sam_movrx and wf_sam_movry wf_sam_movrx (float): distance to move x before/after the tomography collection to collect white field wf_sam_movry (float): distance to move y before/after the tomography collection to collect white field eventlog_list (list of strings): fileds to record in the datalog file from evnets[0]['data'] ffwait (float): time to wait before collecting full field tomography, in second wfwait (float): time to wait before collecting white field, in second d ''' print('start of full field tomography') print('acqusition time', acqtime) theta_traj = np.linspace(thetastart, thetastop, numproj) tomo_scan_output = [] #setup detectors det = [pcoedge, tomo_stage.theta] pcoedge.cam.acquire_time.set(acqtime) if record_preamp is True: det.append(current_preamp) print('recording preamp') if preamp_acqtime is None: current_preamp.exp_time.set(acqtime) print('preamp acqtime', acqtime) else: current_preamp.exp_time.set(preamp_acqtime) print('preamp acqtime = ', preamp_acqtime) else: print('NOT recording preamp') livecallbacks = [] livetableitem = ['tomo_stage_theta'] if record_preamp is True: livetableitem.append('current_preamp_ch2') livecallbacks.append(LiveTable(livetableitem)) #close the shutter print('closing shutter to collect darkfield') shut_b.close() #collecting darkfield time.sleep(dfwait) print('shutter closed, start collecting darkfield images, num = ', num_darkfield) fftomo_df_plan = count(det, num = num_darkfield) fftomo_df_plan = bp.subs_wrapper(fftomo_df_plan, livecallbacks) fftomo_df_gen = yield from fftomo_df_plan logscan_event0info('full_field_tomo_dark_field', event0info = eventlog_list) #logscan('full_field_tomo_dark_field') print('darkfield collection done') #move sample out prior to white field collection print('moving sample out of field of view') print('moving sample x relative by', wf_sam_movrx) print('moving sample y relative by', wf_sam_movry) movesamplex_out = yield from list_scan([], tomo_stage.x, [tomo_stage.x.position+wf_sam_movrx]) movesampley_out = yield from list_scan([], tomo_stage.y, [tomo_stage.y.position+wf_sam_movry]) time.sleep(wfwait) print('sample out') #open the shutter print('opening shutter to collect whitefield') shut_b.open() #collecting whitefield print('shutter opened, start collecting whitefield images, num = ', num_whitefield) fftomo_wf_plan = count(det, num = num_whitefield) fftomo_wf_plan = bp.subs_wrapper(fftomo_wf_plan, livecallbacks) fftomo_wf_gen = yield from fftomo_wf_plan logscan_event0info('full_field_tomo_white_field_prescan', event0info = eventlog_list) #logscan('full_field_tomo_white_field_prescan') #move sample back after white field collection print('moving sample back to the field of view') print('moving sample x relative by', (-1)*wf_sam_movrx) print('moving sample y relative by', (-1)*wf_sam_movry) movesamplex_in = yield from list_scan([], tomo_stage.x, [tomo_stage.x.position-wf_sam_movrx]) movesampley_in = yield from list_scan([], tomo_stage.y, [tomo_stage.y.position-wf_sam_movry]) #collecting tomography data print('start collecting tomographyd data') print('start anggle', thetastart) print('stop anggle', thetastop) print('number of projections', numproj) fftomo_plan = scan(det, tomo_stage.theta, thetastart, thetastop, numproj) fftomo_plan = bp.subs_wrapper(fftomo_plan, livecallbacks) fftomo_gen = yield from fftomo_plan logscan_event0info('full_field_tomo_projections', event0info = eventlog_list) #logscan('full_field_tomo_projections') #move sample out prior to white field collection print('moving sample out of field of view') print('moving sample x relative by', wf_sam_movrx) print('moving sample y relative by', wf_sam_movry) movesamplex_out = yield from list_scan([], tomo_stage.x, [tomo_stage.x.position+wf_sam_movrx]) movesampley_out = yield from list_scan([], tomo_stage.y, [tomo_stage.y.position+wf_sam_movry]) time.sleep(wfwait) #collecting whitefield fftomo_wf_plan = count(det, num = num_whitefield) fftomo_wf_plan = bp.subs_wrapper(fftomo_wf_plan, livecallbacks) fftomo_wf_gen = yield from fftomo_wf_plan logscan_event0info('full_field_tomo_white_field_postscan', event0info = eventlog_list) #logscan('full_field_tomo_white_field_postscan') #move sample back after white field collection print('moving sample back to the field of view') print('moving sample x relative by', (-1)*wf_sam_movrx) print('moving sample y relative by', (-1)*wf_sam_movry) movesamplex_in = yield from list_scan([], tomo_stage.x, [tomo_stage.x.position-wf_sam_movrx]) movesampley_in = yield from list_scan([], tomo_stage.y, [tomo_stage.y.position-wf_sam_movry]) print('done')
def test_simple_list_scan(): RE = RunEngine() hardware = yaqc_bluesky.Device(39424) sensor = yaqc_bluesky.Device(39425) lis = [-10, -8, 4, 2, 10] RE(list_scan([sensor], hardware, lis))
interval = sorted(set(ll))[1] / 2 for lll in ll: j = lll + interval j = round(j, 0) if j not in l and j < 180: l.append(j) # Run Full Field Scans, each scan has more slices, showing how we can minimize # the number of slices by interleaving them by half for i in [180]: RE( bp.list_scan( [det], m, l[:i], md={ "tomo": { "type": "full_field", "rotation": "motor1", "center": rot_center, } }, ) ) print(i) time.sleep(3) ''' # Run in pencil beam geometry (this takes a long time!) RE( bp.grid_scan( [det2], m, 0,
ada2200.serial_interface.set(0x18) # enables SDO (bit 4,3 = 1) ada2200.demod_control.set(0x10) # SDO to RCLK ada_config = ada2200.read_configuration() ada2200.serial_interface.set(0x10) # enables SDO (bit 4,3 = 1) ada2200.demod_control.set(0x18) # bit 3: 0 = SDO to RCLK dmm_config = dmm.read_configuration() dmm.burst_volt_timer.stage() time.sleep(0.1) print('starting plan!') uid = RE( list_scan([dmm.burst_volt_timer, dmm_burst_stats.mean, dmm_filter_stats.filter_6dB_mean, dmm_filter_stats.filter_24dB_mean, dmm_filter_stats.filter_6dB_std, dmm_filter_stats.filter_24dB_std], att.val, [0, 6, 10, 20, 30, 40, 50, 60, 70, 90, 1000], per_step=custom_step), LiveTable([att.val, dmm.burst_volt_timer]), # the parameters below will be metadata attenuator='attenuator sweep', purpose='snr_ADA2200', operator='Lucas', dut='ADA2200', preamp='yes_AD8655', notes='SNR with RCLK as input; trigger DMM with RCLK; 1000 dB = terminated (50 Ohm) input; filter tau = 10e-3', pwr_config=pwr.read_configuration(), ada2200_config=ada_config, dmm_config=dmm_config ) # the script does not continue along
interval = sorted(set(ll))[1] / 2 for lll in ll: j = lll + interval j = round(j, 0) if j not in l and j < 180: l.append(j) # Run Full Field Scans, each scan has more slices, showing how we can minimize # the number of slices by interleaving them by half for i in [180]: RE( bp.list_scan( [det], m, l[:i], md={ "tomo": { "type": "full_field", "rotation": "motor1", "center": rot_center, } }, )) print(i) time.sleep(3) ''' # Run in pencil beam geometry (this takes a long time!) RE( bp.grid_scan( [det2], m, 0, 180,
def maximize_lorentz(detector, motor, read_field, step_size=1, bounds=None, average=None, filters=None, position_field='user_readback', initial_guess=None): """ Maximize a signal with a Lorentzian relationship to a motor The following plan does a linear step scan through the parameter space while collecting information to create a Lorentzian model. After the scan has completed, the created model will be queried to find the estimated motor position that will yield the absolute maximum of the Lorentz equation Parameters ---------- detector : obj The object to be read during the plan motor : obj The object to be moved via the plan. read_field : str Field of detector to maximize nsteps : int, optional The step size used by the initial linear scan to create the Lorentzian model. A smaller step size will create a more accurate model, while a larger step size will increase the speed of the entire operation. bounds : tuple, optional The lower and higher limit of the search space. If no value is given the :attr:`.limits` property of the motor will be queried next. If this does not yield anything useful an exception will be raised average : int, optional The number of shots to average at every step of the scan. If left as None, no average will be used filters : dict, optional Filters used to drop shots from the analysis position_field : str, optional Motor field that will have the Lorentzian relationship with the given signal initial_guess : dict, optional Initial guess to the Lorentz model parameters of `sigma` `center` `amplitude` """ average = average or 1 # Define bounds if not bounds: try: bounds = motor.limits logger.debug( "Bounds were not specified, the area " "between %s and %s will searched", bounds[0], bounds[1]) except AttributeError as exc: raise UndefinedBounds("Bounds are not defined by motor {} or " "plan".format(motor.name)) from exc # Calculate steps steps = np.arange(bounds[0], bounds[1], step_size) # Include the last step even if this is smaller than the step_size steps = np.append(steps, bounds[1]) # Create Lorentz fit and live model build fit = LorentzianModel(missing='drop') i_vars = {'x': position_field} model = LiveBuild(fit, read_field, i_vars, filters=filters, average=average, init_guess=initial_guess) #, # update_every=len(steps)) # Set to fit only on last step # Create per_step plan 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)) # Create linear scan plan = list_scan([detector], motor, steps, per_step=measure) @subs_decorator(model) def inner(): # Run plan (stripping open/close run messages) yield from msg_mutator(plan, block_run_control) # Yield result of Lorentz model logger.debug(model.result.fit_report()) max_position = model.result.values['center'] # Check that the estimated position is reasonable if not bounds[0] < max_position < bounds[1]: raise ValueError("Predicted maximum position of {} is outside the " "bounds {}".format(max_position, bounds)) # Order move to maximum position logger.debug("Travelling to maximum of Lorentz at %s", max_position) yield from abs_set(motor, model.result.values['center'], wait=True) # Run the assembled plan yield from inner() # Return the fit return model
def yale_fourin(det,locs,md='None'): print('Plan start') yield from bp.list_scan([det],px,locs[0],py,locs[1],md=md) print('Plan finish')
def _gen(self): return list_scan(self.detectors, self.motor, self.steps, md=self.md)
def Tlist(dets, exposure, T_list, *, per_step=shutter_step): """ Collect data over a list of user-specific temperatures This plan sets the sample temperature using a temp_controller device and exposes a detector for a set time at each temperature. It also has logic for equilibrating the temperature before each acquisition. By default it closes the fast shutter at XPD in between exposures. This behavior may be overridden, leaving the fast shutter open for the entire scan. Please see below. Parameters ---------- dets : list list of 'readable' objects. default to the temperature controller and area detector linked to xpdAcq. exposure : float total time of exposure in seconds T_list : list a list of temperatures where a scan will be run per_step : callable, optional hook for customizing action at each temperature point. Tramp uses this for opening and closing the shutter at each temperature acquisition. Default behavior: `` open shutter - collect data - close shutter `` To make shutter always open during the temperature ramp, pass ``None`` to this argument. See ``Notes`` below for more detailed information. Notes ----- 1. To see which area detector and temperature controller will be used, type the following commands: >>> xpd_configuration['area_det'] >>> xpd_configuration['temp_controller'] 2. To change the default behavior to shutter-always-open, please pass the argument for ``per_step`` in the ``ScanPlan`` definition, as follows: >>> ScanPlan(bt, Tlist, 5, [300, 250, 198], per_step=None) This will create a ``Tlist`` ScanPlan, with shutter always open during the ramping. """ pe1c, = dets # setting up area_detector and temp_controller (num_frame, acq_time, computed_exposure) = yield from _configure_area_det( exposure ) area_det = xpd_configuration["area_det"] T_controller = xpd_configuration["temp_controller"] xpdacq_md = { "sp_time_per_frame": acq_time, "sp_num_frames": num_frame, "sp_requested_exposure": exposure, "sp_computed_exposure": computed_exposure, "sp_T_list": T_list, "sp_type": "Tlist", "sp_uid": str(uuid.uuid4()), "sp_plan_name": "Tlist", } # pass xpdacq_md to as additional md to bluesky plan plan = bp.list_scan( [area_det], T_controller, T_list, per_step=per_step, md=xpdacq_md ) plan = bpp.subs_wrapper(plan, LiveTable([T_controller])) yield from plan
from bluesky.plans import list_scan positions = [1, 1, 2, 3, 5, 8] RE(list_scan([det], motor, positions)) # or, equivalently, without a separate variable: RE(list_scan([det], motor, [1, 1, 2, 3, 5, 8]))
def _per_step(detectors, step, pos_cache, take_reading=my_take_reading): yield from bps.sleep(delay) sts = yield from bps.one_nd_step(detectors, step, pos_cache, take_reading=take_reading) return sts return _per_step # Mandy's samples per_step7 = gen_per_step(60 * 5) plan42 = pchain( configure_area_det(pe1c, 60 * 5, 0.2), bp.list_scan([pe1c], cs700, [300, 433, 465], per_step=per_step7), configure_area_det(pe1c, 60, 0.2), bp.grid_scan([pe1c], cs700, 465, 300, 34, per_step=my_per_step)) plan43 = pchain(configure_area_det(pe1c, 60 * 5, 0.2), bp.list_scan([pe1c], cs700, [300, 433], per_step=per_step7), bps.mv(cs700, 300)) plan44 = pchain( configure_area_det(pe1c, 60 * 5, 0.2), bp.list_scan([pe1c], cs700, [300], per_step=my_per_step), configure_area_det(pe1c, 60, 0.2), bp.grid_scan([pe1c], cs700, 300, 455, 32, per_step=my_per_step), configure_area_det(pe1c, 60 * 5, 0.2), bp.list_scan([pe1c], cs700, [455], per_step=per_step7), configure_area_det(pe1c, 60, 0.2), bp.grid_scan([pe1c], cs700, 455, 300, 32, per_step=my_per_step), )