Exemplo n.º 1
0
def filter_opt_count(det, target_count=100000, md={}):
    """ filter_opt_count
    OPtimize counts using filters 
    Assumes mu=0.2, x = [0.89, 2.52, 3.83, 10.87]
    I = I_o \exp(-mu*x) 

    Only takes one detector, since we are optimizing based on it alone
    target is mean+2std
    """
    dc = DocumentCache()
    token = yield from bps.subscribe('all', dc)
    yield from bps.stage(det)

    md = {}

    yield from bps.open_run(md=md)
    # BlueskyRun object allows interaction with documents similar to db.v2,
    # but documents are in memory
    run = BlueskyRun(dc)
    yield from bps.trigger_and_read([det, filter1, filter2, filter3, filter4])

    data = run.primary.read()['pilatus300k_image']
    mean = data[-1].mean().values.item()  # xarray.DataArray methods
    std = data[-1].std().values.item()  # xarray.DataArray methods
    curr_counts = mean + 2 * std

    # gather filter information and solve
    filter_status = [
        round(filter1.get() / 5),
        round(filter2.get() / 5),
        round(filter3.get() / 5),
        round(filter4.get() / 5)
    ]
    print(filter_status)
    filter_status = [not e for e in filter_status]
    new_filters = solve_filter_setup(filter_status, curr_counts, target_count)
    # invert again to reflect filter status
    new_filters = [not e for e in new_filters]
    print(new_filters)
    # set new filters and read.  For some reason hangs on bps.mv when going high
    filter1.put(new_filters[0] * 4.9)
    filter2.put(new_filters[1] * 4.9)
    filter3.put(new_filters[2] * 4.9)
    filter4.put(new_filters[3] * 4.9)

    yield from bps.trigger_and_read([det, filter1, filter2, filter3, filter4])

    # close out run
    yield from bps.close_run()
    yield from bps.unsubscribe(token)
    yield from bps.unstage(det)
Exemplo n.º 2
0
def measure_average(detectors, num, delay=None, stream=None):
    """
    Measure an average over a number of shots from a set of detectors

    Parameters
    ----------
    detectors : list
        List of detectors to read

    num : int
        Number of shots to average together

    delay: iterable or scalar, optional
        Time delay between successive readings. See ``bluesky.count`` for more
        details

    stream : AverageStream, optional
        If a plan will call :func:`.measure_average` multiple times, a single
        ``AverageStream`` instance can be created and then passed in on each
        call. This allows other callbacks to subscribe to the averaged data
        stream. If no ``AverageStream`` is provided then one is created for the
        purpose of this function.

    Returns
    -------
    averaged_event : dict
        A dictionary of all the measurements taken from the list of detectors
        averaged for ``num`` shots. The keys follow the same naming convention
        as that will appear in the event documents i.e "{name}_{field}"

    Notes
    -----
    The returned average dictionary will only contain keys for 'number' or
    'array' fields. Field types that can not be averaged such as 'string' will
    be ignored, do not expect them in the output.
    """
    # Create a stream and subscribe if not given one
    if not stream:
        stream = AverageStream(num=num)
        yield from subscribe('all', stream)
        # Manually kick the LiveDispatcher to emit a start document because we
        # will not see the original one since this is subscribed after open_run
        stream.start({'uid': None})
    # Ensure we sync our stream with request if using a prior one
    else:
        stream.num = num
    # Measure our detectors
    yield from stub_wrapper(count(detectors, num=num, delay=delay))
    # Return the measured average as a dictionary for use in adaptive plans
    return stream.last_event
Exemplo n.º 3
0
def golden_section_search(signal, motor, tolerance, limits, average=None):
    """
    Use golden-section search to find the extrema of a signal

    The algorithm is fed the starting range in which the extrema is contained
    within and a tolerance in which we would like to know the position of the
    extrema. For the algorithm to succeed it is a requirement that the
    underlying distribution is unimodal. After beginning the scan, "probe"
    points will be chosen to help determine how to narrow the range which
    contains the extrema. These probes are chosen using the golden ratio so the
    scan will complete in a deterministic number of iterations based on the
    starting range and desired resolution.

    Parameters
    ----------
    signal: ophyd.Signal
        Signal whose distribution we are investigating

    motor: ophyd.OphydObject
        Object that is ``set`` to probe different points of the distribution.

    tolerance: float
        The size of the range we would like to narrow the position of our
        extrema. Note that this is not the tolerance that we will know the
        "value" of the extrema, but instead the resolution we will be sure that
        it lies within on the "x" axis

    limits: tuple
        Starting bounds that we know the extrema lie within

    average : int, optional
        Option to average the signal we are reading to limit the affect of
        noise on our measurements

    Returns
    -------
    bounds: tuple
        The range in which we have determined the extrema to lie within.
    """
    # This is boiler plate code and should be packaged into a
    # pre-processor, for now we repeat it as to not subscribe numerous
    # streams
    average = average or 1
    stream = AverageStream(num=average)
    yield from bps.subscribe('all', stream)
    stream.start({'uid': None})

    # Measurement plan
    def measure_probe(position):
        # Move motor
        yield from bps.mv(motor, position)
        # Return measurement
        ret = yield from measure_average([signal, motor], average,
                                         stream=stream)
        logger.debug("Found a values of %r at %r",
                     ret[signal.name], position)
        return ret[signal.name]

    # If we have already found what we are looking for stop the scan
    (a, b) = limits
    region_size = b - a
    if region_size <= tolerance:
        return (a, b)
    # Determine the number of steps to converge
    n = math.ceil(math.log(tolerance/region_size)
                  / math.log(1/golden_ratio))
    logger.debug("Beginning golden-section search, "
                 "narrowing extrema location to %r "
                 "will require %r steps",
                 tolerance, n)
    # Place holders for probe values
    c = b - region_size/golden_ratio
    d = a + region_size/golden_ratio
    # Examine our new probe locations
    low_probe = yield from measure_probe(c)
    high_probe = yield from measure_probe(d)
    # Begin iteratively narrowing range
    for step in range(n - 1):
        logger.debug("Iteration %s: Extrema is between %s and %s",
                     step + 1, a, b)
        if low_probe < high_probe:
            # Readjust region of interest
            b = d
            d = c
            high_probe = low_probe
            region_size /= golden_ratio
            # Calculate next probe
            c = b - region_size/golden_ratio
            # Measure next probe
            low_probe = yield from measure_probe(c)
        else:
            # Readjust region of interest
            a = c
            c = d
            low_probe = high_probe
            region_size /= golden_ratio
            # Calculate next probe
            d = a + region_size/golden_ratio
            # Measure next probe
            high_probe = yield from measure_probe(d)
    # Return the final banding region
    if low_probe < high_probe:
        final_region = (a, d)
    else:
        final_region = (c, b)
    logger.debug("Extrema determined to be within %r",
                 final_region)
    return final_region
Exemplo n.º 4
0
def plan_simultaneously(x_centroid,
                        y_centroid,
                        x,
                        y,
                        atol,
                        x_target=None,
                        y_target=None):
    """
     
    This BlueSky plan aligns the laser's centroid with the x-ray's centroid.
     
    This plan implements 'walk_to_pixel' from the pswalker (a beam alignment module). The plan uses an iterative procedure to  align any beam to a position on a screen, when two motors move the beam along the two axes. Liveplots are updated and show the paths taken to achieve alignment.

    
    Parameters
    ----------
    x_centroid, y_centroid : 
        These represent the x_centroid and y_centroid 
    x, y: 
        These respresnt the x_motor and y_motor
    x_target, y_target : int
        Target value on the x-axis and y-axis
        
    """

    #Create a figure
    fig = plt.figure(figsize=(15, 10))
    fig.subplots_adjust(hspace=0.3, wspace=0.4)

    #The first subplot, which plots the y_centroid vs x_centroid
    ax1 = fig.add_subplot(2, 2, 1)
    ax1.invert_yaxis()
    x_centroid_y_centroid = LivePlot(y_centroid.name,
                                     x_centroid.name,
                                     ax=ax1,
                                     marker='x',
                                     markersize=7,
                                     color='orange')

    #The second subplot, which plots the y_centroid and x_centroid with same x-axis (y_motor)
    ax2 = fig.add_subplot(2, 2, 3)
    ax2.set_ylabel(y_centroid.name, color='red')
    ax3 = ax2.twinx()
    #     ax2.invert_yaxis()
    #     ax3.invert_yaxis()
    ax3.set_ylabel(x_centroid.name, color='blue')
    y_plot_y_centroid = LivePlot(y_centroid.name,
                                 y.name,
                                 ax=ax2,
                                 marker='x',
                                 markersize=6,
                                 color='red')
    y_plot_x_centroid = LivePlot(x_centroid.name,
                                 y.name,
                                 ax=ax3,
                                 marker='o',
                                 markersize=6,
                                 color='blue')

    #The third subplot, which plots the y_centroid and x_centroid with same x-axis (x_motor)
    ax4 = fig.add_subplot(2, 2, 4)
    ax4.set_ylabel(y_centroid.name, color='green')
    ax5 = ax4.twinx()
    ax5.set_ylabel(x_centroid.name, color='purple')
    x_plot_y_centroid = LivePlot(y_centroid.name,
                                 x.name,
                                 ax=ax4,
                                 marker='x',
                                 markersize=6,
                                 color='green')
    x_plot_x_centroid = LivePlot(x_centroid.name,
                                 x.name,
                                 ax=ax5,
                                 marker='o',
                                 markersize=6,
                                 color='purple')

    #Subscribe the plots
    token_x_centroid_y_centroid = yield from subscribe('all',
                                                       x_centroid_y_centroid)
    token_y_plot_x_centroid = yield from subscribe('all', y_plot_x_centroid)
    token_y_plot_y_centroid = yield from subscribe('all', y_plot_y_centroid)
    token_x_plot_x_centroid = yield from subscribe('all', x_plot_x_centroid)
    token_x_plot_y_centroid = yield from subscribe('all', x_plot_y_centroid)

    #Start a new run
    yield from open_run(
        md={
            'detectors': [(x_centroid.name), (y_centroid.name)],
            'motors': [(x.name), (y.name)],
            'hints': {
                'dimensions': [(x.hints['fields'],
                                'primary'), (y.hints['fields'], 'primary')]
            }
        })

    #Ask for the target values
    if x_target is None:
        x_target = int(input('Enter the x value: '))
    if y_target is None:
        y_target = int(input('Enter the y value: '))

    #Iteratively move until x_target and x-centroid are within a certain threshold of each other
    while True:
        if not np.isclose(x_target, x_centroid.get(), atol):
            yield from walk_to_pixel(x_centroid,
                                     x,
                                     x_target,
                                     first_step=0.1,
                                     target_fields=[x_centroid.name, x.name],
                                     tolerance=atol,
                                     average=5,
                                     system=[y, y_centroid])
        elif not np.isclose(y_target, y_centroid.get(), atol):
            yield from walk_to_pixel(y_centroid,
                                     y,
                                     y_target,
                                     first_step=0.1,
                                     tolerance=atol,
                                     average=5,
                                     target_fields=[y_centroid.name, y.name],
                                     system=[x, x_centroid])
        else:
            break


#     plt.show(block=True)

#Close the run
    yield from close_run()
    #Unsubscribe the plots
    yield from unsubscribe(token_x_centroid_y_centroid)
    yield from unsubscribe(token_y_plot_x_centroid)
    yield from unsubscribe(token_y_plot_y_centroid)
    yield from unsubscribe(token_x_plot_x_centroid)
    yield from unsubscribe(token_x_plot_y_centroid)