Example #1
0
 def __init__(self, prefix, name=None, *args, **kwargs):
     super().__init__(prefix, name=name, *args, **kwargs)
     if self.parent:
         self.motor_fields=['readback']
         self.calib_motors=[self.parent.t1.chi1, self.parent.t1.y1]
         self.calib_fields=[field_prepend('user_readback', calib_motor)
                            for calib_motor in self.calib_motors]
         self.detector_fields=['stats2_centroid_x', 'stats2_centroid_y',]
Example #2
0
def euclidean_distance(device,
                       device_fields,
                       targets,
                       average=None,
                       filters=None):
    """
    Calculates the euclidean distance between the device_fields and targets.

    Parameters
    ----------
    device : :class:`.Device`
        Device from which to take the value measurements

    device_fields : iterable
        Fields of the device to measure

    targets : iterable
        Target value to calculate the distance from

    average : int, optional
        Number of averages to take for each measurement
    
    Returns
    -------
    distance : float
        The euclidean distance between the device fields and the targets.
    """
    average = average or 1
    # Turn things into lists
    device_fields = as_list(device_fields)
    targets = as_list(targets, len(device_fields))

    # Get the full detector fields
    prep_dev_fields = [field_prepend(fld, device) for fld in device_fields]

    # Make sure the number of device fields and targets is the same
    if len(device_fields) != len(targets):
        raise ValueError(
            "Number of device fields and targets must be the same."
            "Got {0} and {1}".format(len(device_fields, len(targets))))
    # Measure the average
    read = (yield from measure_average([device], num=average, filters=filters))
    # Get the squared differences between the centroids
    squared_differences = [(read[fld] - target)**2
                           for fld, target in zip(prep_dev_fields, targets)]
    # Combine into euclidean distance
    distance = math.sqrt(sum(squared_differences))
    return distance
Example #3
0
def centroid_scan(detector, motor, start, stop, steps, average=None, 
                  detector_fields=['stats2_centroid_x', 'stats2_centroid_y'], 
                  motor_fields=None, system=None, system_fields=None,
                  filters=None, return_to_start=True, *args, **kwargs):
    """
    Performs a scan and returns the centroids of the inputted detector.

    The returned centroids can be absolute or relative to the initial value. The
    values are returned in a pandas DataFrame where the indices are the target
    motor positions.

    Parameters
    ----------
    detector : :class:`.BeamDetector`
        Detector from which to take the value measurements
    
    motor : :class:`.Motor`
        Main motor to perform the scan

    start : float
        Starting position of motor

    stop : float
        Ending position of motor

    steps : int
        Number of steps to take
    
    average : int, optional
        Number of averages to take for each measurement

    detector_fields : iterable, optional
        Fields of the detector to add to the returned dataframe

    motor_fields : iterable, optional
        Fields of the motor to add to the returned dataframe

    system : list, optional
        Extra devices to include in the datastream as we measure the average
        
    system_fields : list, optional
        Fields of the extra devices to add to the returned dataframe

    filters : dict, optional
        Key, callable pairs of event keys and single input functions that
        evaluate to True or False. For more infromation see
        :meth:`.apply_filters`

    return_to_start : bool, optional
        Move the scan motor back to its initial position after the scan     
    
    Returns
    -------
    df : pd.DataFrame
        DataFrame containing the detector, motor, and system fields at every
        step of the scan.
    """
    average = average or 1
    system = as_list(system or [])
    all_devices = [motor] + system + [detector]

    # Ensure all fields are lists
    detector_fields = as_list(detector_fields)
    motor_fields = as_list(motor_fields or motor.name)
    system_fields = as_list(system_fields or [])

    # Get the full detector fields
    prep_det_fields = [field_prepend(fld, detector) for fld in detector_fields]
    # Put all the fields together into one list
    all_fields = motor_fields + system_fields + prep_det_fields

    # Build the dataframe with the centroids
    df = pd.DataFrame(columns=all_fields, index=np.linspace(start, stop, steps))

    # Create a basic measuring plan
    def per_step(detectors, motor, step):
        # Perform step
        yield from checkpoint()
        logger.debug("Measuring average at step {0} ...".format(step))
        yield from abs_set(motor, step, wait=True)
        # Measure the average
        reads = (yield from measure_average(all_devices, num=average,
                                            filters=filters, *args, **kwargs))
        # Fill the dataframe at this step with the centroid difference
        for fld in all_fields:
            df.loc[step, fld] = reads[fld]

    # Run the inner plan
    @_return_to_start(motor, perform=return_to_start)
    def inner():
        plan = scan([detector], motor, start, stop, steps, per_step=per_step)
        yield from stub_wrapper(plan)
    yield from inner()

    # Return the filled dataframe
    return df