Beispiel #1
0
def test_live_fit_multidim(fresh_RE):
    RE = fresh_RE

    try:
        import lmfit
    except ImportError:
        raise pytest.skip('requires lmfit')

    motor1._fake_sleep = 0
    motor2._fake_sleep = 0
    det4.exposure_time = 0

    def gaussian(x, y, A, sigma, x0, y0):
        return A * np.exp(-((x - x0)**2 + (y - y0)**2) / (2 * sigma**2))

    model = lmfit.Model(gaussian, ['x', 'y'])
    init_guess = {
        'A': 2,
        'sigma': lmfit.Parameter('sigma', 3, min=0),
        'x0': -0.2,
        'y0': 0.3
    }
    cb = LiveFit(model,
                 'det4', {
                     'x': 'motor1',
                     'y': 'motor2'
                 },
                 init_guess,
                 update_every=50)
    RE(outer_product_scan([det4], motor1, -1, 1, 10, motor2, -1, 1, 10, False),
       cb)

    expected = {'A': 1, 'sigma': 1, 'x0': 0, 'y0': 0}
    for k, v in expected.items():
        assert np.allclose(cb.result.values[k], v, atol=1e-6)
Beispiel #2
0
def test_live_fit_plot(fresh_RE):
    RE = fresh_RE
    try:
        import lmfit
    except ImportError:
        raise pytest.skip('requires lmfit')

    def gaussian(x, A, sigma, x0):
        return A * np.exp(-(x - x0)**2 / (2 * sigma**2))

    model = lmfit.Model(gaussian)
    init_guess = {
        'A': 2,
        'sigma': lmfit.Parameter('sigma', 3, min=0),
        'x0': -0.2
    }
    livefit = LiveFit(model,
                      'det', {'x': 'motor'},
                      init_guess,
                      update_every=50)
    lfplot = LiveFitPlot(livefit, color='r')
    lplot = LivePlot('det', 'motor', ax=plt.gca(), marker='o', ls='none')
    RE(scan([det], motor, -1, 1, 50), [lplot, lfplot])

    expected = {'A': 1, 'sigma': 1, 'x0': 0}
    for k, v in expected.items():
        assert np.allclose(livefit.result.values[k], v, atol=1e-6)
Beispiel #3
0
def test_live_fit(RE, hw):
    try:
        import lmfit
    except ImportError:
        raise pytest.skip('requires lmfit')

    def gaussian(x, A, sigma, x0):
        return A * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2))

    model = lmfit.Model(gaussian)
    init_guess = {'A': 2,
                  'sigma': lmfit.Parameter('sigma', 3, min=0),
                  'x0': -0.2}
    cb = LiveFit(model, 'det', {'x': 'motor'}, init_guess,
                 update_every=50)
    RE(scan([hw.det], hw.motor, -1, 1, 50), cb)
    # results are in cb.result.values

    expected = {'A': 1, 'sigma': 1, 'x0': 0}
    for k, v in expected.items():
        assert np.allclose(cb.result.values[k], v, atol=1e-6)
Beispiel #4
0
import numpy as np
import lmfit
from bluesky.plans import scan
from ophyd.sim import motor, noisy_det
from bluesky.callbacks import LiveFit
from bluesky.callbacks.mpl_plotting import LivePlot, LiveFitPlot
from bluesky import RunEngine

RE = RunEngine({})


def gaussian(x, A, sigma, x0):
    return A * np.exp(-(x - x0)**2 / (2 * sigma**2))


model = lmfit.Model(gaussian)
init_guess = {'A': 2, 'sigma': lmfit.Parameter('sigma', 3, min=0), 'x0': -0.2}

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
lf = LiveFit(model, 'noisy_det', {'x': 'motor'}, init_guess)
lfp = LiveFitPlot(lf, ax=ax, color='r')
lp = LivePlot('noisy_det', 'motor', ax=ax, marker='o', linestyle='none')

RE(scan([noisy_det], motor, -1, 1, 50), [lfp, lp])
plt.draw()
Beispiel #5
0
def xScanAndCenter(iteration, detector, det_name, motor, motor_name, 
				   alignRange = [-1, 2], stepRange = [0.01, 0.10], 
				   targetDelta = def_xTargetDelta, plotter = [],
				   SimAlign = False, fudge = def_fudge, verbose = False):
	"""
	align_x:  
		-scan xMotor through range
		-monitors detector looking for transition of beam/no-beam	

	Parameters
    ----------
	iteration			: overall iteration of full alignment loop, required for 
						  plot colors/legend
	detector			: detector object
	detector_name		: detector object's name
	motor				: X motor object
	motor_name			: X motor object's name
	alignRange			: list of two floats, describing range of x-alignment 
						  Default value is [-1,2] mm,
	StepRange 			: list of two floats, minimum and maximum steps for 
						  adaptive scan. Default value is [0.015, 0.075] degrees 
						  Minimum thMotor step is 0.01 degrees
	targetDelta			: float, maximum jump in detector value before scan step 
						  decreased, default is set to def_xTargetDelta
						  value is 10 in detector units, 
	plotter  			: axis object for x alignment data, 
						  Default value is None which later creates new object
	SimAlign  			: boolean flag for simulation/testing 
						  Default value is False,
	fudge				: Fudge factor for x-scan data reduction to remove bump 
						  from post-scan fit (in mm).  Defaults to def_fudge
	verbose 			: boolean for showing alignment process using LiveTable
						  callbacks. Default value is False
	"""


	if plotter is None:
		figX, xAx = plt.subplots()
	else:
		xAx = plotter	
		
	cur_color = fit_colors[iteration % len(fit_colors)]
	cur_linestyle = linestyles[iteration // len(fit_colors)]

	scanPlot = LivePlot(det_name,x=motor_name, markeredgecolor = cur_color, 
						markerfacecolor = 'none', ax = xAx, linestyle = 'none', 
						marker = '^', label = '{} - data'.format(iteration))
		
	comp_model = lmfit.Model(erfx, prefix="erf_") + lmfit.Model(gaussian, 
							 prefix = "gau_")
	comp_guess = {'erf_low': 0,
				  'erf_high': 0.03,
				  'erf_wid': lmfit.Parameter('erf_wid', value = 0.4, min=0),
				  'erf_x0': -0.1,
				  'gau_A': 0.01,
				  'gau_sigma': lmfit.Parameter('gau_sigma', value = .1, min=0),
				  'gau_x0': 1.0}
	xLiveFit = LiveFit(comp_model, det_name, {'x': motor_name}, comp_guess, 
					   update_every=5)
	
	lt = LiveTable([detector, motor])
	
	if verbose:
		cbs = [scanPlot, xLiveFit, lt]
	else:
		cbs = [scanPlot, xLiveFit]
				
	@subs_decorator(cbs)
	def preFitScan(detectors, motor, alignRange, stepRange, targetDelta):
		yield from adaptive_scan([detectors], det_name, motor, 
								 start = alignRange[0], stop = alignRange[1], 
								 min_step = stepRange[0], 
								 max_step = stepRange[1], 
								 target_delta = targetDelta,
								 backstep = True)

	yield from preFitScan(detector, motor, alignRange, stepRange, targetDelta)

	x0_rough = xLiveFit.result.params['erf_x0'].value
	width = xLiveFit.result.params['erf_wid'].value
		
	new_x0 = fitAndPlotBumplessData(np.asarray(scanPlot.y_data), 
									np.asarray(scanPlot.x_data), 
									x0_rough, width, ax = xAx, 
									color = cur_color, 
									linestyle = cur_linestyle,
									fudge = fudge)

	other_data = []
	leg_raw	= {'label'  : 'Data',
			   'shape'  : '^',
			   'color'  : 'k',
			   'size'   : '10'}
	
	other_data = [leg_raw]

	cleanLegend(iteration, xAx, other_data)
	
	asd.x0.append(new_x0)
	
	if not SimAlign:
		if (asd.x0[-1] <= min(alignRange) or asd.x0[-1] >= max(alignRange)):
			print("Peak estimated to be outside of alignment range")
		else:
			motor.move(asd.x0[-1])
Beispiel #6
0
	@subs_decorator(coarse_cbs)
	def coarseScan(detector, motor, cRange, pts = 10):
		#Coarse scan to find region of peak
		yield from scan([detector], motor, cRange[0], cRange[1], num = pts)
		
	yield from coarseScan(detector, motor, alignRange, pts = coarsePTS)

	finePlot = LivePlot(detector_name,x=motor_name, linestyle = 'none', 
						marker = 'o', markerfacecolor = 'none', 
						markeredgecolor = cur_color, ax = thAx, 
						label = '{} - fine'.format(iteration))
	fineThetaModel = lmfit.Model(gaussian)
	fineThetaInitGuess = {'A': coarsePeak.max[1], 
						  'sigma': lmfit.Parameter('sigma', .03, min=0),
						  'x0': coarsePeak.max[0]}
	fineThetaLiveFit = LiveFit(fineThetaModel, detector_name, {'x': motor_name}, 
							   fineThetaInitGuess, update_every=1)
	fineThetaLiveFitPlot = LiveFitPlot(fineThetaLiveFit, ax = thAx, label='fit', 
									   color = fit_colors[iteration % 7],
									   linestyle = linestyles[iteration // 7])
		
	fRange = [coarsePeak.max[0]-fineRadius, coarsePeak.max[0]+fineRadius]
	   
	thTargetDelta = coarsePeak.max[1]/targetDeltaFactor
	   
	if not SimAlign:
		if coarsePeak.max[0] > alignRange[1]-1:
			motor.move(4.00)
	
	if verbose:
		fine_cbs = [finePlot, fineThetaLiveFitPlot, lt]
	else:
def Ecal_old(detectors,
             motor,
             guessed_energy,
             mode,
             *,
             guessed_amplitude=0.5,
             guessed_sigma=0.004,
             min_step=0.001,
             D='LaB6',
             max_n=3,
             margin=0.5,
             md=None):
    """
    Energy calibration scan


    Parameters
    ----------
    detectors : detectors
    motor : the motor
    guessed_energy : number
        units of keV
    mode : {'peaks', 'dips'}
    guessed_amplitude : number, optional
        detector units, defaults to 1500
    guessed_sigma : number, optional
        in units of degrees, defaults to 0.004
    min_step : number, optional
        step size in degrees, defaults to 0.001
    D : string or array, optional
        Either provide the spacings literally (as an array) or
        give the name of a known spacing ('LaB6' or 'Si')
    max_n : integer, optional
        how many peaks (on one side of 0), default is 3
    margin : number, optional
        how far to scan in two theta beyond the 
        guessed left and right peaks, default 0.5

    Example
    -------
    Execute an energy calibration scan with default steps.

    >>> RE(Ecal(68))
    """
    if mode == 'peaks':
        #motor = tth_cal
        factor = 2
        offset = 0
        sign = 1
    if mode == 'dips':
        #motor = th_cal
        factor = 1
        # theta_hardware = theta_theorhetical + offset
        offset = -35.26  # degrees
        sign = -1
    if isinstance(D, str):
        D = D_SPACINGS[D]
    # Based on the guessed energy, compute where the peaks should be centered
    # in theta. This will be used as an initial guess for peak-fitting.
    guessed_wavelength = 12.398 / guessed_energy  # angtroms

    theta = np.rad2deg(np.arcsin(guessed_wavelength / (2 * D)))
    guessed_centers = factor * theta  # 'factor' puts us in two-theta units if applicable
    _range = max(guessed_centers) + (factor * margin)
    # Scan from positive to negative because that is the direction
    # that the th_cal and tth_cal motors move without backlash.
    start, stop = _range + offset, -_range + offset
    print('guessed_wavelength={} [Angstroms]'.format(guessed_wavelength))
    print('guessed_centers={} [in {}-theta DEGREES]'.format(
        guessed_centers, factor))
    print('will scan from {} to {} in hardware units'.format(start, stop))

    if max_n > 3:
        raise NotImplementedError("I only work for n up to 3.")

    # todo : make a model and sum them
    def peaks(x, c0, wavelength, a1, a2, sigma):
        # x comes from hardware in [theta or two-theta] degrees
        x = np.deg2rad(x / factor - offset)  # radians
        assert np.all(wavelength < 2 * D), \
            "wavelength would result in illegal arg to arcsin"
        cs = np.arcsin(wavelength / (2 * D))
        c1 = cs[0]
        c2 = cs[1]
        #c3 = cs[2]
        # first peak
        result = (
            voigt(x=x, amplitude=sign * a1, center=c0 - c1, sigma=sigma) +
            voigt(x=x, amplitude=sign * a1, center=c0 + c1, sigma=sigma))

        # second peak
        result += (
            voigt(x=x, amplitude=sign * a2, center=c0 - c2, sigma=sigma) +
            voigt(x=x, amplitude=sign * a2, center=c0 + c2, sigma=sigma))

        # third peak
        #result += (voigt(x=x, amplitude=sign*a3, center=c0 - c3, sigma=sigma) +
        #voigt(x=x, amplitude=sign*a3, center=c0 + c3, sigma=sigma))
        return result

    model = Model(peaks) + LinearModel()

    # Fill out initial guess.
    init_guess = {
        'intercept':
        Parameter('intercept', value=0, min=-100, max=100),
        'slope':
        Parameter('slope', value=0, min=-100, max=100),
        'sigma':
        Parameter('sigma', value=np.deg2rad(guessed_sigma)),
        'c0':
        Parameter('c0', value=np.deg2rad(0), min=-0.2, max=0.2),
        'wavelength':
        Parameter('wavelength',
                  guessed_wavelength,
                  min=0.8 * guessed_wavelength,
                  max=1.2 * guessed_wavelength)
    }
    # min=0, max=np.min(2 * D))}
    kwargs = {'min': 0.5 * guessed_amplitude, 'max': 2 * guessed_amplitude}
    for i, center in enumerate(guessed_centers):
        init_guess.update({
            'a%d' % (1 + i):
            Parameter('a%d' % (1 + i), guessed_amplitude, **kwargs)
        })
    print(init_guess)
    lf = LiveFit(model,
                 detectors[0].name, {'x': motor.name},
                 init_guess,
                 update_every=100)

    fig, ax = plt.subplots()  # explitly create figure, axes to use below
    plot = LivePlot(detectors[0].name,
                    motor.name,
                    linestyle='none',
                    marker='o',
                    ax=ax)
    lfp = LiveFitPlot(lf, ax=ax, color='r')
    subs = [lfp, plot]

    #detectors = [det]#[sc]

    # Set up metadata -- based on the sourcecode of bluesky.plans.scan.
    _md = {
        'detectors': [det.name for det in detectors],
        'motors': [motor.name],
        'hints': {},
    }
    _md.update(md or {})
    try:
        dimensions = [(motor.hints['fields'], 'primary')]
    except (AttributeError, KeyError):
        pass
    else:
        _md['hints'].setdefault('dimensions', dimensions)

    initial_steps = np.arange(start, stop, -min_step)
    assert len(initial_steps), "bad start, stop, min_step parameters"
    size = factor * 0.05  # region around each predicted peak location

    @bpp.stage_decorator(list(detectors) + [motor])
    @bpp.run_decorator(md=_md)
    def inner_scan():
        wavelength = guessed_wavelength
        for step in initial_steps:
            yield from bps.one_1d_step(detectors, motor, step)
            x_data = lf.independent_vars_data['x']
            if x_data and lf.result is not None:
                # Have we yet scanned past the third peak?
                wavelength = lf.result.values['wavelength']
                # Convert c's to hardware units here for comparison with x_data.
                c1, c2, c3 = factor * np.rad2deg(
                    np.arcsin(wavelength / (2 * D))) + offset
                if np.min(x_data) < (c1 - 1):
                    # Stop dense scanning.
                    print('Preliminary result:\n', lf.result.values)
                    print('Becoming adaptive to save time....')
                    break
        # left of zero peaks
        c1, c2, c3 = -factor * np.rad2deg(np.arcsin(wavelength /
                                                    (2 * D))) + offset
        neighborhoods = [
            np.arange(c + size, c - size, -min_step) for c in (c1, c2, c3)
        ]
        for neighborhood in neighborhoods:
            for step in neighborhood:
                yield from bps.one_1d_step(detectors, motor, step)

    plan = inner_scan()
    plan = bpp.subs_wrapper(plan, subs)
    plan = bpp.reset_positions_wrapper(plan, [motor])
    ret = (yield from plan)
    print(lf.result.values)
    print('WAVELENGTH: {} [Angstroms]'.format(lf.result.values['wavelength']))
    return ret