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',]
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
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