def scan_loop(self, command, repeat_command=<NUM_LIT:100>, use_delay=True, additional_delay=<NUM_LIT:0>, mask_steps=<NUM_LIT:3>, enable_mask_steps=None, enable_double_columns=None, same_mask_for_all_dc=False, fast_dc_loop=True, bol_function=None, eol_function=None, digital_injection=False, enable_shift_masks=None, disable_shift_masks=None, restore_shift_masks=True, mask=None, double_column_correction=False):
if not isinstance(command, bitarray):<EOL><INDENT>raise TypeError<EOL><DEDENT>if enable_shift_masks is None:<EOL><INDENT>enable_shift_masks = ["<STR_LIT>", "<STR_LIT>", "<STR_LIT>"]<EOL><DEDENT>if disable_shift_masks is None:<EOL><INDENT>disable_shift_masks = []<EOL><DEDENT>if isinstance(double_column_correction, basestring):  <EOL><INDENT>with open(double_column_correction) as fp:<EOL><INDENT>plsr_dac_correction = list(literal_eval(fp.readline().strip()))<EOL><DEDENT><DEDENT>elif isinstance(double_column_correction, (list, tuple)):  <EOL><INDENT>plsr_dac_correction = list(double_column_correction)<EOL><DEDENT>else:  <EOL><INDENT>if "<STR_LIT>".lower() in map(lambda x: x.lower(), enable_shift_masks) and "<STR_LIT>".lower() in map(lambda x: x.lower(), enable_shift_masks):<EOL><INDENT>plsr_dac_correction = self.register.calibration_parameters['<STR_LIT>']<EOL><DEDENT>elif "<STR_LIT>".lower() in map(lambda x: x.lower(), enable_shift_masks):<EOL><INDENT>plsr_dac_correction = self.register.calibration_parameters['<STR_LIT>']<EOL><DEDENT>elif "<STR_LIT>".lower() in map(lambda x: x.lower(), enable_shift_masks):<EOL><INDENT>plsr_dac_correction = self.register.calibration_parameters['<STR_LIT>']<EOL><DEDENT><DEDENT>initial_plsr_dac = self.register.get_global_register_value("<STR_LIT>")<EOL>restore_point_name = str(self.run_number) + '<STR_LIT:_>' + self.run_id + '<STR_LIT>'<EOL>with self.register.restored(name=restore_point_name):<EOL><INDENT>conf_mode_command = self.register.get_commands("<STR_LIT>")[<NUM_LIT:0>]<EOL>run_mode_command = self.register.get_commands("<STR_LIT>")[<NUM_LIT:0>]<EOL>if use_delay:<EOL><INDENT>delay = self.register.get_commands("<STR_LIT>", length=additional_delay + calculate_wait_cycles(mask_steps))[<NUM_LIT:0>]<EOL>scan_loop_command = command + delay<EOL><DEDENT>else:<EOL><INDENT>scan_loop_command = command<EOL><DEDENT>def enable_columns(dc):<EOL><INDENT>if digital_injection:<EOL><INDENT>return [dc * <NUM_LIT:2> + <NUM_LIT:1>, dc * <NUM_LIT:2> + <NUM_LIT:2>]<EOL><DEDENT>else:  <EOL><INDENT>if dc == <NUM_LIT:0>:<EOL><INDENT>return [<NUM_LIT:1>]<EOL><DEDENT>elif dc == <NUM_LIT>:<EOL><INDENT>return [<NUM_LIT>, <NUM_LIT>, <NUM_LIT>]<EOL><DEDENT>else:<EOL><INDENT>return [dc * <NUM_LIT:2>, dc * <NUM_LIT:2> + <NUM_LIT:1>]<EOL><DEDENT><DEDENT><DEDENT>def write_double_columns(dc):<EOL><INDENT>if digital_injection:<EOL><INDENT>return [dc]<EOL><DEDENT>else:  <EOL><INDENT>if dc == <NUM_LIT:0>:<EOL><INDENT>return [<NUM_LIT:0>]<EOL><DEDENT>elif dc == <NUM_LIT>:<EOL><INDENT>return [<NUM_LIT>, <NUM_LIT>]<EOL><DEDENT>else:<EOL><INDENT>return [dc - <NUM_LIT:1>, dc]<EOL><DEDENT><DEDENT><DEDENT>def get_dc_address_command(dc):<EOL><INDENT>commands = []<EOL>commands.append(conf_mode_command)<EOL>self.register.set_global_register_value("<STR_LIT>", dc)<EOL>commands.append(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"])[<NUM_LIT:0>])<EOL>if double_column_correction:<EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", initial_plsr_dac + int(round(plsr_dac_correction[dc])))<EOL>commands.append(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"])[<NUM_LIT:0>])<EOL><DEDENT>commands.append(run_mode_command)<EOL>return self.register_utils.concatenate_commands(commands, byte_padding=True)<EOL><DEDENT>if not enable_mask_steps:<EOL><INDENT>enable_mask_steps = range(mask_steps)<EOL><DEDENT>if not enable_double_columns:<EOL><INDENT>enable_double_columns = range(<NUM_LIT>)<EOL><DEDENT>commands = []<EOL>commands.append(conf_mode_command)<EOL>if digital_injection is True:<EOL><INDENT>if "<STR_LIT>".lower() in map(lambda x: x.lower(), enable_shift_masks) or "<STR_LIT>".lower() in map(lambda x: x.lower(), disable_shift_masks):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>if "<STR_LIT>".lower() in map(lambda x: x.lower(), enable_shift_masks) or "<STR_LIT>".lower() in map(lambda x: x.lower(), disable_shift_masks):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>self.register.set_pixel_register_value("<STR_LIT>", <NUM_LIT:0>)<EOL>self.register.set_pixel_register_value("<STR_LIT>", <NUM_LIT:0>)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=True, name=["<STR_LIT>", "<STR_LIT>"], joint_write=True))<EOL>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:0>)<EOL><DEDENT>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"]))<EOL>self.register_utils.send_commands(commands)<EOL>for mask_step in enable_mask_steps:<EOL><INDENT>if self.abort_run.is_set():<EOL><INDENT>break<EOL><DEDENT>commands = []<EOL>commands.append(conf_mode_command)<EOL>if same_mask_for_all_dc:  <EOL><INDENT>if disable_shift_masks:<EOL><INDENT>curr_dis_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, default=<NUM_LIT:1>, value=<NUM_LIT:0>, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_dis_mask), disable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False if mask is not None else True, name=disable_shift_masks, joint_write=True))<EOL><DEDENT>if enable_shift_masks:<EOL><INDENT>curr_en_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_en_mask), enable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False if mask is not None else True, name=enable_shift_masks, joint_write=True))<EOL><DEDENT>if digital_injection is True:  <EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:1>)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"]))<EOL><DEDENT><DEDENT>else:  <EOL><INDENT>if disable_shift_masks:<EOL><INDENT>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, <NUM_LIT:1>), disable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=True, name=disable_shift_masks, joint_write=True))<EOL><DEDENT>if enable_shift_masks:<EOL><INDENT>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, <NUM_LIT:0>), enable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=True, name=enable_shift_masks, joint_write=True))<EOL><DEDENT>if digital_injection is True:  <EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:1>)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"]))<EOL><DEDENT><DEDENT>self.register_utils.send_commands(commands)<EOL>logging.info('<STR_LIT>', repeat_command, mask_step, ('<STR_LIT>' % (enable_mask_steps[<NUM_LIT:0>], enable_mask_steps[-<NUM_LIT:1>])) if len(enable_mask_steps) > <NUM_LIT:1> else ('<STR_LIT>' % enable_mask_steps[<NUM_LIT:0>]))<EOL>if same_mask_for_all_dc:<EOL><INDENT>if fast_dc_loop:  <EOL><INDENT>self.dut['<STR_LIT>']['<STR_LIT>'] = repeat_command<EOL>dc_address_command = get_dc_address_command(enable_double_columns[<NUM_LIT:0>])<EOL>self.dut['<STR_LIT>']['<STR_LIT>'] = len(dc_address_command)<EOL>self.register_utils.set_command(command=self.register_utils.concatenate_commands((dc_address_command, scan_loop_command), byte_padding=False))<EOL>for index, dc in enumerate(enable_double_columns):<EOL><INDENT>if self.abort_run.is_set():<EOL><INDENT>break<EOL><DEDENT>if index != <NUM_LIT:0>:  <EOL><INDENT>dc_address_command = get_dc_address_command(dc)<EOL>self.register_utils.wait_for_command()<EOL>if eol_function:<EOL><INDENT>eol_function()  <EOL><DEDENT>self.register_utils.set_command(dc_address_command, set_length=False)  <EOL><DEDENT>if bol_function:<EOL><INDENT>bol_function()<EOL><DEDENT>self.dut['<STR_LIT>']['<STR_LIT>']<EOL><DEDENT>self.register_utils.wait_for_command()<EOL>if eol_function:<EOL><INDENT>eol_function()<EOL><DEDENT>self.dut['<STR_LIT>']['<STR_LIT>'] = <NUM_LIT:0><EOL><DEDENT>else:  <EOL><INDENT>for index, dc in enumerate(enable_double_columns):<EOL><INDENT>if self.abort_run.is_set():<EOL><INDENT>break<EOL><DEDENT>dc_address_command = get_dc_address_command(dc)<EOL>self.register_utils.send_command(dc_address_command)<EOL>if bol_function:<EOL><INDENT>bol_function()<EOL><DEDENT>self.register_utils.send_command(scan_loop_command, repeat=repeat_command)<EOL>if eol_function:<EOL><INDENT>eol_function()<EOL><DEDENT><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>if fast_dc_loop:  <EOL><INDENT>dc = enable_double_columns[<NUM_LIT:0>]<EOL>ec = enable_columns(dc)<EOL>dcs = write_double_columns(dc)<EOL>commands = []<EOL>commands.append(conf_mode_command)<EOL>if disable_shift_masks:<EOL><INDENT>curr_dis_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, default=<NUM_LIT:1>, value=<NUM_LIT:0>, enable_columns=ec, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_dis_mask), disable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, dcs=dcs, name=disable_shift_masks, joint_write=True))<EOL><DEDENT>if enable_shift_masks:<EOL><INDENT>curr_en_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, enable_columns=ec, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_en_mask), enable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, dcs=dcs, name=enable_shift_masks, joint_write=True))<EOL><DEDENT>if digital_injection is True:<EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:1>)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"]))<EOL><DEDENT>self.register_utils.send_commands(commands)<EOL>dc_address_command = get_dc_address_command(dc)<EOL>self.dut['<STR_LIT>']['<STR_LIT>'] = len(dc_address_command)<EOL>self.dut['<STR_LIT>']['<STR_LIT>'] = repeat_command<EOL>self.register_utils.set_command(command=self.register_utils.concatenate_commands((dc_address_command, scan_loop_command), byte_padding=False))<EOL>for index, dc in enumerate(enable_double_columns):<EOL><INDENT>if self.abort_run.is_set():<EOL><INDENT>break<EOL><DEDENT>if index != <NUM_LIT:0>:  <EOL><INDENT>ec = enable_columns(dc)<EOL>dcs = write_double_columns(dc)<EOL>dcs.extend(write_double_columns(enable_double_columns[index - <NUM_LIT:1>]))<EOL>commands = []<EOL>commands.append(conf_mode_command)<EOL>if disable_shift_masks:<EOL><INDENT>curr_dis_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, default=<NUM_LIT:1>, value=<NUM_LIT:0>, enable_columns=ec, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_dis_mask), disable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, dcs=dcs, name=disable_shift_masks, joint_write=True))<EOL><DEDENT>if enable_shift_masks:<EOL><INDENT>curr_en_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, enable_columns=ec, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_en_mask), enable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, dcs=dcs, name=enable_shift_masks, joint_write=True))<EOL><DEDENT>if digital_injection is True:<EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:1>)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"]))<EOL><DEDENT>dc_address_command = get_dc_address_command(dc)<EOL>self.register_utils.wait_for_command()<EOL>if eol_function:<EOL><INDENT>eol_function()  <EOL><DEDENT>self.register_utils.send_commands(commands)<EOL>self.dut['<STR_LIT>']['<STR_LIT>'] = len(dc_address_command)<EOL>self.dut['<STR_LIT>']['<STR_LIT>'] = repeat_command<EOL>self.register_utils.set_command(command=self.register_utils.concatenate_commands((dc_address_command, scan_loop_command), byte_padding=False))<EOL><DEDENT>if bol_function:<EOL><INDENT>bol_function()<EOL><DEDENT>self.dut['<STR_LIT>']['<STR_LIT>']<EOL><DEDENT>self.register_utils.wait_for_command()<EOL>if eol_function:<EOL><INDENT>eol_function()<EOL><DEDENT>self.dut['<STR_LIT>']['<STR_LIT>'] = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>for index, dc in enumerate(enable_double_columns):<EOL><INDENT>if self.abort_run.is_set():<EOL><INDENT>break<EOL><DEDENT>ec = enable_columns(dc)<EOL>dcs = write_double_columns(dc)<EOL>if index != <NUM_LIT:0>:<EOL><INDENT>dcs.extend(write_double_columns(enable_double_columns[index - <NUM_LIT:1>]))<EOL><DEDENT>commands = []<EOL>commands.append(conf_mode_command)<EOL>if disable_shift_masks:<EOL><INDENT>curr_dis_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, default=<NUM_LIT:1>, value=<NUM_LIT:0>, enable_columns=ec, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_dis_mask), disable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, dcs=dcs, name=disable_shift_masks, joint_write=True))<EOL><DEDENT>if enable_shift_masks:<EOL><INDENT>curr_en_mask = make_pixel_mask(steps=mask_steps, shift=mask_step, enable_columns=ec, mask=mask)<EOL>map(lambda mask_name: self.register.set_pixel_register_value(mask_name, curr_en_mask), enable_shift_masks)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, dcs=dcs, name=enable_shift_masks, joint_write=True))<EOL><DEDENT>if digital_injection is True:<EOL><INDENT>self.register.set_global_register_value("<STR_LIT>", <NUM_LIT:1>)<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>"]))<EOL><DEDENT>self.register_utils.send_commands(commands)<EOL>dc_address_command = get_dc_address_command(dc)<EOL>self.register_utils.send_command(dc_address_command)<EOL>if bol_function:<EOL><INDENT>bol_function()<EOL><DEDENT>self.register_utils.send_command(scan_loop_command, repeat=repeat_command)<EOL>if eol_function:<EOL><INDENT>eol_function()<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>commands = []<EOL>commands.extend(self.register.get_commands("<STR_LIT>"))<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>", "<STR_LIT>", "<STR_LIT>"]))<EOL>if restore_shift_masks:<EOL><INDENT>commands = []<EOL>commands.extend(self.register.get_commands("<STR_LIT>"))<EOL>commands.extend(self.register.get_commands("<STR_LIT>", name=["<STR_LIT>", "<STR_LIT>", "<STR_LIT>"]))<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, name=disable_shift_masks))<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, name=enable_shift_masks))<EOL>commands.extend(self.register.get_commands("<STR_LIT>", same_mask_for_all_dc=False, name="<STR_LIT>"))<EOL>
Implementation of the scan loops (mask shifting, loop over double columns, repeatedly sending any arbitrary command).

    Parameters
    ----------
    command : BitVector
        (FEI4) command that will be sent out serially.
    repeat_command : int
        The number of repetitions command will be sent out each mask step.
    use_delay : bool
        Add additional delay to the command (append zeros). This helps to avoid FE data errors because of sending to many commands to the FE chip.
    additional_delay: int
        Additional delay to increase the command-to-command delay (in number of clock cycles / 25ns).
    mask_steps : int
        Number of mask steps (from 1 to 672).
    enable_mask_steps : list, tuple
        List of mask steps which will be applied. Default is all mask steps. From 0 to (mask-1). A value equal None or empty list will select all mask steps.
    enable_double_columns : list, tuple
        List of double columns which will be enabled during scan. Default is all double columns. From 0 to 39 (double columns counted from zero). A value equal None or empty list will select all double columns.
    same_mask_for_all_dc : bool
        Use same mask for all double columns. This will only affect all shift masks (see enable_shift_masks). Enabling this is in general a good idea since all double columns will have the same configuration and the scan speed can increased by an order of magnitude.
    fast_dc_loop : bool
        If True, optimize double column (DC) loop to save time. Note that bol_function and eol_function cannot do register operations, if True.
    bol_function : function
        Begin of loop function that will be called each time before sending command. Argument is a function pointer (without braces) or functor.
    eol_function : function
        End of loop function that will be called each time after sending command. Argument is a function pointer (without braces) or functor.
    digital_injection : bool
        Enables digital injection. C_High and C_Low will be disabled.
    enable_shift_masks : list, tuple
        List of enable pixel masks which will be shifted during scan. Mask set to 1 for selected pixels else 0. None will select "Enable", "C_High", "C_Low".
    disable_shift_masks : list, tuple
        List of disable pixel masks which will be shifted during scan. Mask set to 0 for selected pixels else 1. None will disable no mask.
    restore_shift_masks : bool
        Writing the initial (restored) FE pixel configuration into FE after finishing the scan loop.
    mask : array-like
        Additional mask. Must be convertible to an array of booleans with the same shape as mask array. True indicates a masked pixel. Masked pixels will be disabled during shifting of the enable shift masks, and enabled during shifting disable shift mask.
    double_column_correction : str, bool, list, tuple
        Enables double column PlsrDAC correction. If value is a filename (string) or list/tuple, the default PlsrDAC correction will be overwritten. First line of the file must be a Python list ([0, 0, ...])