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)
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
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
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.")
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
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)
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
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