def multiScan(detX, detX_name, detTh, detTh_name, motorX, mX_name, motorTh, mTh_name, motorTTh, mTTh_name, iterations = 1, alignCriteria = {}, theta_kws = None, x_kws = None, SimAlign = False, xPlot = [], thPlot = [], sumPlot = None, sumAxes = None, verbose = False): """ multiScan: -set tthMotor to 0 degrees -set thMotor to 0 degrees -scan x-direction for transition from no-beam to full-beam -scan theta direction with detector at 2theta = 10 degrees -plot summary (if flagged) of x(half-max), theta(peak) Parameters ---------- detX : X detector object (in real alignment, same as detTh) detX_name : X detector object's name (in real alignment, same as detTh_name) detTh : Theta detector object (in real alignment, same as detX) detTh_name : Theta detector object's name (in real alignment, same as detX_name) motorX : X motor object motorX_name : X motor object's name motorTh : Theta motor object mTh_name : Theta motor object's name motorTTh : 2theta motor object mTTh_name : 2theta motor object's name iterations : Number of iterations of the X, Theta alignment scans to run through alignCriteria : dict of criteria for ending alignment Default value is None, theta_kws : dict for arguments to be passed to theta-alignment Default value is None, x_kws : dict for arguments to be passed to x-alignment Default value is None xPlot : axes object for x-alignment plot thPlot : axes object for theta-alignment plot sumPlot : plot object for usmmary plot sumAxes : axes for the x-/theta-alignment summaries SimAlign : boolean flag for simulation/testing Default value is False, verbose : boolean for showing alignment process using LiveTable callbacks. Default value is False """ if not SimAlign: motorTh.move(0) try: motorTTh.move(theta_kws['det40ffset']) except: d4offset = EpicsSignalRO('29idd:userCalcOut2.VAL', name = 'd4offset') det4offset = d4offset.get() motorTTh.move(det4offset) for i in range(iterations): asd.sequence = np.arange(i+1)+1 yield from xScanAndCenter(i+1, detX, detX_name, motorX, mX_name, plotter = xPlot, SimAlign = SimAlign, verbose = verbose, **x_kws) yield from thetaScanAndCenter(i+1, detTh, detTh_name, motorTh, mTh_name, motorTTh, mTTh_name, plotter = thPlot, SimAlign = SimAlign, verbose = verbose, **theta_kws) if sumPlot is not None: if i == 0: xLine, = sumAxes[0].plot(asd.sequence, asd.x0, markeredgecolor = 'r', markerfacecolor = 'none', marker = '^', linestyle='none', label = 'x_offset') thetaLine, = sumAxes[1].plot(asd.sequence, asd.theta5, markeredgecolor = 'b', markerfacecolor = 'none', marker = 'o', linestyle='none', label = 'theta_offset') else: xLine.set_data(asd.sequence, asd.x0) thetaLine.set_data(asd.sequence, asd.theta5) cleanAxes(sumPlot, xLine, thetaLine, sumAxes[0], sumAxes[1], 'r', 'b', 'x offset (mm)', 'theta @ 2theta = 10', 'Iteration')
Default value is None which later creates new object det4offset : Detector's offset from 0 (for 2theta motor), defaults to None leading to attempt to get it from PV 29idd:userCalcOut2.VAL SimAlign : boolean flag for simulation/testing Default value is False, verbose : boolean for showing alignment process using LiveTable callbacks. Default value is False """ # detector offset angle PV: 29idd:userCalcOut2.VAL # motor2 move to offset + 10 degrees if det4offset is None: d4offset = EpicsSignalRO('29idd:userCalcOut2.VAL', name = 'd4offset') det4offset = d4offset.get() if not SimAlign: motor2.move(det4offset+10.0) motor.move(alignRange[0]) if plotter is None: figTh, thAx = plt.subplots() else: thAx = plotter cur_color = fit_colors[iteration % len(fit_colors)] coarsePlot = LivePlot(detector_name,x=motor_name, linestyle = 'none', marker = '^', markerfacecolor = 'none', markeredgecolor = cur_color, ax = thAx,