예제 #1
0
    def test_data_and_position_references(self):
        n_images = 10
        positioner = StaticPositioner(n_images)
        readables = [
            epics_pv("PYSCAN:TEST:OBS1"),
            epics_pv("PYSCAN:TEST:OBS2"),
            epics_pv("PYSCAN:TEST:OBS3")
        ]

        # Shift each OBS by 1, so we can resolve them when comparing results.
        fixed_values["PYSCAN:TEST:OBS1"] = iter(range(0, n_images))
        fixed_values["PYSCAN:TEST:OBS2"] = iter(range(1, n_images + 1))
        fixed_values["PYSCAN:TEST:OBS3"] = iter(range(2, n_images + 2))

        positions = []
        data = []
        data_processor = SimpleDataProcessor(positions, data)

        def after_read():
            nonlocal current_number_of_items
            self.assertEqual(
                len(positions), len(data),
                "The number of positions and data is out of sync.")
            self.assertEqual(len(data), current_number_of_items + 1,
                             "More than 1 data point was taken.")
            current_number_of_items += 1

        current_number_of_items = 0

        scan(positioner=positioner,
             readables=readables,
             data_processor=data_processor,
             after_read=after_read)
예제 #2
0
def lscan(writables,
          readables,
          start,
          end,
          steps,
          latency=0.0,
          relative=False,
          passes=1,
          zigzag=False,
          before_read=None,
          after_read=None,
          title=None):
    """Line Scan: positioners change together, linearly from start to end positions.

    Args:
        writables(list of Writable): Positioners set on each step.
        readables(list of Readable): Sensors to be sampled on each step.
        start(list of float): start positions of writables.
        end(list of float): final positions of writables.
        steps(int or float or list of float): number of scan steps (int) or step size (float).
        relative (bool, optional): if true, start and end positions are relative to 
            current at start of the scan
        latency(float, optional): settling time for each step before readout, defaults to 0.0.
        passes(int, optional): number of passes
        zigzag(bool, optional): if true writables invert direction on each pass.
        before_read (function, optional): callback on each step, before each readout. Callback may have as 
            optional parameters list of positions.
        after_read (function, optional): callback on each step, after each readout. Callback may have as 
            optional parameters a ScanRecord object. 
        title(str, optional): plotting window name.

    Returns:
        ScanResult object.

    """
    offsets, finalization_actions, settings = _generate_scan_parameters(
        relative, writables, latency)
    n_steps, step_size = _convert_steps_parameter(steps)

    if zigzag:
        positioner_class = ZigZagLinePositioner
    else:
        positioner_class = LinePositioner

    positioner = positioner_class(start=start,
                                  end=end,
                                  step_size=step_size,
                                  n_steps=n_steps,
                                  offsets=offsets,
                                  passes=passes)

    result = scan(positioner,
                  readables,
                  writables,
                  before_read=before_read,
                  after_read=after_read,
                  settings=settings,
                  finalization=finalization_actions)

    return result
예제 #3
0
def tscan(readables,
          points,
          interval,
          before_read=None,
          after_read=None,
          title=None):
    """Time Scan: sensors are sampled in fixed time intervals.

    Args:
        readables(list of Readable): Sensors to be sampled on each step.
        points(int): number of samples.
        interval(float): time interval between readouts. Minimum temporization is 0.001s
        before_read (function, optional): callback on each step, before each readout.
        after_read (function, optional): callback on each step, after each readout.
        title(str, optional): plotting window name.

    Returns:
        ScanResult object.

    """
    positioner = TimePositioner(interval, points)
    result = scan(positioner,
                  readables,
                  before_read=before_read,
                  after_read=after_read)
    return result
예제 #4
0
    def test_DictionaryDataProcessor(self):
        n_images = 10
        positioner = StaticPositioner(n_images)
        readables = [
            epics_pv("PYSCAN:TEST:OBS1"),
            epics_pv("PYSCAN:TEST:OBS2"),
            epics_pv("PYSCAN:TEST:OBS3")
        ]

        # Shift each OBS by 1, so we can resolve them when comparing results.
        fixed_values["PYSCAN:TEST:OBS1"] = iter(range(0, n_images))
        fixed_values["PYSCAN:TEST:OBS2"] = iter(range(1, n_images + 1))
        fixed_values["PYSCAN:TEST:OBS3"] = iter(range(2, n_images + 2))

        data_processor = DictionaryDataProcessor(readables)

        result = scan(positioner=positioner,
                      readables=readables,
                      data_processor=data_processor)

        for index in range(n_images):
            self.assertEqual(result[index]["PYSCAN:TEST:OBS1"], index,
                             "Unexpected result for OBS1.")
            self.assertEqual(result[index]["PYSCAN:TEST:OBS2"], index + 1,
                             "Unexpected result for OBS2.")
            self.assertEqual(result[index]["PYSCAN:TEST:OBS3"], index + 2,
                             "Unexpected result for OBS3.")
예제 #5
0
def ascan(writables,
          readables,
          start,
          end,
          steps,
          latency=0.0,
          relative=False,
          passes=1,
          zigzag=False,
          before_read=None,
          after_read=None,
          title=None):
    """
    Area Scan: multi-dimentional scan, each positioner is a dimention.
    :param writables: List of identifiers to write to at each step.
    :param readables: List of identifiers to read from at each step.
    :param start: Start position for writables.
    :param end: Stop position for writables.
    :param steps: Number of scan steps(integer) or step size (float).
    :param latency: Settling time before each readout. Default = 0.
    :param relative: Start and stop positions are relative to the current position.
    :param passes: Number of passes for each scan.
    :param zigzag: If True and passes > 1, invert moving direction on each pass.
    :param before_read: List of callback functions on each step before readback.
    :param after_read: List of callback functions on each step after readback.
    :param title: Not used in this implementation - legacy.
    :return: Data from the scan.
    """

    offsets, finalization_actions, settings = _generate_scan_parameters(
        relative, writables, latency)
    n_steps, step_size = _convert_steps_parameter(steps)

    if zigzag:
        positioner_class = ZigZagAreaPositioner
    else:
        positioner_class = AreaPositioner

    positioner = positioner_class(start=start,
                                  end=end,
                                  step_size=step_size,
                                  n_steps=n_steps,
                                  offsets=offsets,
                                  passes=passes)

    result = scan(positioner,
                  readables,
                  writables,
                  before_read=before_read,
                  after_read=after_read,
                  settings=settings,
                  finalization=finalization_actions)

    return result
예제 #6
0
def get_images(screen, n_images, beamline='Aramis', dry_run=None):

    print('Start get_images for screen %s, %i images, beamline %s' %
          (screen, n_images, beamline))

    meta_dict_1 = get_meta_data(screen)

    positioner = pyscan.BsreadPositioner(n_messages=n_images)
    settings = pyscan.scan_settings(settling_time=0.01,
                                    measurement_interval=0.2,
                                    n_measurements=1)

    pipeline_client = PipelineClient("http://sf-daqsync-01:8889/")
    cam_instance_name = str(screen) + "_sp1"
    stream_address = pipeline_client.get_instance_stream(cam_instance_name)
    stream_host, stream_port = get_host_port_from_stream_address(
        stream_address)

    # Configure bsread
    pyscan.config.bs_default_host = stream_host
    pyscan.config.bs_default_port = stream_port

    logging.getLogger("mflow.mflow").setLevel(logging.ERROR)

    readables = get_readables(beamline)

    raw_output = pyscan.scan(positioner=positioner,
                             readables=readables,
                             settings=settings)
    output = [[x] for x in raw_output]

    result_dict = pyscan_result_to_dict(readables, output, scrap_bs=True)

    for ax in ['x_axis', 'y_axis']:
        arr = result_dict[ax] * 1e-6  # convert to m
        if len(arr.shape) == 3:
            result_dict[ax + '_m'] = arr[0, 0, :]
        elif len(arr.shape) == 2:
            result_dict[ax + '_m'] = arr[0, :]
        else:
            raise ValueError('Unexpected', len(arr.shape))

    meta_dict_2 = get_meta_data(screen)

    output_dict = {
        'pyscan_result': result_dict,
        'meta_data_begin': meta_dict_1,
        'meta_data_end': meta_dict_2,
    }

    print('End get_images')

    return output_dict
    def test_pshell_function_in_scan(self):

        n_steps = 3

        pshell_test = MockPShellFunction(script_name="", parameters={})

        n_positions = 5

        positioner = StaticPositioner(n_positions)
        readables = function_value(pshell_test.read)

        result = scan(positioner=positioner, readables=readables)

        self.assertEqual(n_positions, len(result))

        for position_index in range(n_positions):
            for step_index in range(n_steps):
                result[position_index][0][step_index][0] == float(10)
예제 #8
0
def vscan(writables,
          readables,
          vector,
          line=False,
          latency=0.0,
          relative=False,
          passes=1,
          zigzag=False,
          before_read=None,
          after_read=None,
          title=None):
    """Vector Scan: positioners change following values provided in a vector.

    Args:
        writables(list of Writable): Positioners set on each step.
        readables(list of Readable): Sensors to be sampled on each step.
        vector(list of list of float): table of positioner values.
        line (bool, optional): if true, processs as line scan (1d)
        relative (bool, optional): if true, start and end positions are relative to current at 
            start of the scan
        latency(float, optional): settling time for each step before readout, defaults to 0.0.        
        passes(int, optional): number of passes
        zigzag(bool, optional): if true writables invert direction on each pass.
        before_read (function, optional): callback on each step, before each readout.
        after_read (function, optional): callback on each step, after each readout.
        title(str, optional): plotting window name.

    Returns:
        ScanResult object.

    """
    offsets, finalization_actions, settings = _generate_scan_parameters(
        relative, writables, latency)

    # The compound positioner does not allow you to do zigzag positioning.
    if not line and zigzag:
        raise ValueError("Area vector scan cannot use zigzag positioning.")

    if zigzag:
        positioner_class = ZigZagVectorPositioner
    else:
        positioner_class = VectorPositioner

    # If the vector is treated as a line scan, move all motors to the next position at the same time.
    if line:
        positioner = positioner_class(positions=vector,
                                      passes=passes,
                                      offsets=offsets)
    # The vector is treated as an area scan. Move motors one by one, covering all positions.
    else:
        vector = convert_to_list(vector)
        if not all(isinstance(x, list) for x in vector):
            raise ValueError(
                "In case of area scan, a list of lists is required for a vector."
            )

        positioner = CompoundPositioner([
            VectorPositioner(positions=x, passes=passes, offsets=offsets)
            for x in vector
        ])

    result = scan(positioner,
                  readables,
                  writables,
                  before_read=before_read,
                  after_read=after_read,
                  settings=settings,
                  finalization=finalization_actions)

    return result
예제 #9
0
def data_streaker_offset(streaker,
                         offset_range,
                         screen,
                         n_images,
                         dry_run,
                         beamline='Aramis'):

    print(
        'Start data_streaker_offset for streaker %s, screen %s, beamline %s, dry_run %s'
        % (streaker, screen, beamline, dry_run))
    meta_dict_1 = get_meta_data(screen)

    pipeline_client = PipelineClient('http://sf-daqsync-01:8889/')
    offset_pv = streaker + ':CENTER'

    current_val = caget(offset_pv + '.RBV')

    # Start from closer edge of scan
    if abs(current_val - offset_range[0]) > abs(current_val -
                                                offset_range[-1]):
        offset_range = offset_range[::-1]

    if dry_run:
        screen = 'simulation'
        writables = None
        positioner = pyscan.TimePositioner(time_interval=(1.1 * n_images),
                                           n_intervals=len(offset_range))

    else:
        positions = offset_range * 1e3  # convert to mm
        positioner = pyscan.VectorPositioner(positions=positions.tolist())
        writables = [
            pyscan.epics_pv(pv_name=offset_pv,
                            readback_pv_name=offset_pv + '.RBV',
                            tolerance=0.005)
        ]

    cam_instance_name = screen + '_sp1'
    stream_address = pipeline_client.get_instance_stream(cam_instance_name)
    stream_host, stream_port = get_host_port_from_stream_address(
        stream_address)

    # Configure bsread
    pyscan.config.bs_default_host = stream_host
    pyscan.config.bs_default_port = stream_port

    logging.getLogger('mflow.mflow').setLevel(logging.ERROR)

    settings = pyscan.scan_settings(settling_time=1,
                                    n_measurements=n_images,
                                    write_timeout=60)

    readables = get_readables(beamline)

    raw_output = pyscan.scan(positioner=positioner,
                             readables=readables,
                             settings=settings,
                             writables=writables)
    result_dict = pyscan_result_to_dict(readables, raw_output, scrap_bs=True)
    #import pdb; pdb.set_trace()
    for ax in ['x_axis', 'y_axis']:
        arr = result_dict[ax] * 1e-6
        if len(arr.shape) == 3:
            result_dict[ax + '_m'] = arr[0][0]
        elif len(arr.shape) == 2:
            result_dict[ax + '_m'] = arr[0]
        else:
            raise ValueError('Unexpected', len(arr.shape))

    meta_dict_2 = get_meta_data(screen)

    output = {
        'pyscan_result': result_dict,
        'streaker_offsets': offset_range,
        'screen': screen,
        'n_images': n_images,
        'dry_run': dry_run,
        'streaker': streaker,
        'meta_data_begin': meta_dict_1,
        'meta_data_end': meta_dict_2,
    }
    print('End data_streaker_offset')
    return output