Data Collection

Here we will go through the typical steps needed to collect data on a combinatorial library with the high throughput (HiTp) XRD setup. There are many different types of samples that can be run, and we have tried to provide plans that cover the most common use cases.

Here we will cover what typically happens once a sample has been loaded and the stage aligned. This includes:

  • basic use of plans

  • Standard adding of metadata

  • scripting higher level macros

Basic plan choice

There are a variety of plans available at your disposal to take data on wafer libraries. They are described in detail in High Throughput (HiTp) specific plans. Some suggestions:

Take a single exposure. If you want to measure a single spot for diagnostic purposes, or for a single sample. Note: exposure time is set per detector, as you can count from multiple detectors in a single call.

In [1]: RE(bp.count([pilDet]), purpose='testing')

Scan a detector with a motor. See scanning-detectors

The Xspress3 needs to know how many points are being measured before acquisition, so the command is a bit longer

In [1]: num=50; xsp3.total_points.put(num); RE(bp.rel_scan([xsp3], py,-45,45,
   ...: num=num, md={'purpose':'align'}))

Run a “wafer-library”. Combinatorial samples are often deposited on a silicon wafer, requiring a slightly modified grid scan.

The classic 177 point case. Has the option to specify some number of points to skip, if a run was interrupted.

In [1]: RE(loc_177_scan([pilDet], skip=0), sample_id='XX001',
            purpose='measurement')

You can also supply your own locations. The same skip functionality exists. A few location lists are provided, but you can always generate your own.

In [1]: RE(loc_cust_scan([pilDet], locYale41, skip=10),
         sample_id='XX001', purpose='measurement')

If you would like to confirm the order of acquisition, you can pass the laser range finder in as the detector and watch the acquisition

In [1]: RE(loc_cust_scan([lrf], locYale41, skip=10), purpose='testing')

Managing metadata

Labeling your runs is of critical importance. The syntax of this has been covered in Managing Metadata, but some guiding principles will be provided here.

Metadata is stored in “key-value pairs”. If you execute:

In [1]: RE(plan(), sample_id='A', purpose='calibration')

sample_id and purpose are keys, while A and caibration are their respective values.

Your metadata keys should be consistent across your dataset, otherwise you will have difficulty finding your data. For example, if you end up using both sample_name and name to label your runs, you may end up missing data when you search the databroker later.

As a fall back option, you can remember the scan number of any run that you believe will be important. The scan number is automatically incremented for each plan/scan that is run, and is an easy way to record runs. Writing these down in your own notes is recommended.

Useful keys to add:

  • sample_name : ‘A’, ‘B’, ‘test_wafer’ …

  • purpose: ‘calibration’, ‘data’, ‘testing’ …

Keys that are recorded automatically (as in you don’t need to add them yourself):

  • time - In this context, the start time. (Other times are also recorded.)

  • uid - a globally unique ID for this run

  • plan_name - the function or class name of plan (e.g., ‘count’)

  • plan_type - e.g., the Python type of plan (e.g., ‘generator’)

Extending to the two wafer setup

Collecting data on two wafers is a simple extension of the plans we have discussed earlier. This plan is a bit verbose for the sake of demonstration.

@inject_md_decorator({'macro_name':'two_wafer'})
def two_wafer(wafer1md={'purpose':'testing'},wafer2md={'purpose':'testing'}):
    # get the current offsets
    curr_offsets = [px.user_offset.get(),py.user_offset.get()]

    #move to the first wafer, assuming we know the center
    yield from bps.mv(px, w1_centerx, py, w1_centery)

    # do the 177 loc scan
    yield from bp.list_scan([det],px,-loc177[0],py,loc177[1],md=wafer1md)

    #reset the motors
    yield from bp.mv(px.user_offset, curr_offsets[0],
                     py.user_offset, curr_offsets[1])

    #move to the second wafer, assuming we know the center
    yield from bps.mv(px, w2_centerx, py, w2_centery)

    # do the 177 loc scan
    yield from bp.list_scan([det],px,-loc177[0],py,loc177[1],md=wafer2md)

    #reset the motors
    yield from bp.mv(px.user_offset, curr_offsets[0],
                     py.user_offset, curr_offsets[1])