Beispiel #1
0
def analyse():
    global global_vars
    
    if threshold_vars["integration_time"] < 0.05:
        threshold_vars["integration_time"] = 0.05


 
    rep = Replay() 
    for i, ro in enumerate(tqdm(rep.get_data(r"/home/rasmus/Documents/Rasmus/110_mimosa_telescope_testbeam_14122016_fei4_self_trigger_scan.h5", real_time=True))):
    
        raw_data = ro[0]
        
        data_record = ru.convert_data_array(raw_data, filter_func=is_record)
#         if np.any(is_trigger_word(data_record)):
#             raise
        
        #dr = is_data_record(raw_data)
 
        global_vars["timestamp_start"].append(ro[1])
        timestamp_stop = ro[2]
        global_vars["hits"].append(len(data_record))
         
#        print "{0:b}".format(ro[0][0]), FEI4Record(ro[0][0], chip_flavor="fei4b"), is_data_record(ro[0][0])
        
        if np.any(data_record):
            col, row = get_col_row_array_from_data_record_array(data_record)
            global_vars["coloumn"].append(np.median(col))
            global_vars["row"].append(np.median(row))               
            if not np.any(global_vars["hist_occ"]):
                global_vars["hist_occ"] = fast_analysis_utils.hist_2d_index(col, row, shape=(81, 337))
            #    global_vars["hist_occ"] = fast_analysis_utils.hist_2d_index(np.mean(col), np.mean(row), shape=(81, 337))
            else:
                global_vars["hist_occ"] += fast_analysis_utils.hist_2d_index(col, row, shape=(81, 337))
            #   global_vars["hist_occ"] += fast_analysis_utils.hist_2d_index(np.mean(col), np.mean(row), shape=(81, 337))
             
            if len(global_vars["time"]) == 0:
                global_vars["time"].append(0)

            if timestamp_stop - global_vars["timestamp_start"][0] > threshold_vars["integration_time"]:
                global_vars["time"].append(global_vars["time"][-1] + timestamp_stop - global_vars["timestamp_start"][0])
                global_vars["c"].append(np.var(global_vars["coloumn"]))
                global_vars["r"].append(np.var(global_vars["row"]))
                global_vars["hitrate"].append(np.sum(global_vars["hits"]) / (timestamp_stop - global_vars["timestamp_start"][0]))
                if global_vars["analyse"]:
                    global_vars["beam"] = analyse_beam(global_vars["beam"])
                 
                p_hist = pickle.dumps(global_vars["hist_occ"], -1)
                zlib_hist = zlib.compress(p_hist)
                socket2.send(zlib_hist)
    #             # free memory of global variables
                del global_vars["hits"][:]
                del global_vars["timestamp_start"][:]
                global_vars["hist_occ"] = None
                if len(global_vars["coloumn"])>threshold_vars["reset_coloumn_row_arrays"]:
                    del global_vars["coloumn"][:]
                    del global_vars["row"][:]
Beispiel #2
0
def draw_hit_map_from_raw_data(raw_data_file, front_ends):
    with PdfPages(os.path.splitext(raw_data_file)[0] + '.pdf') as output_pdf:
        with tb.open_file(raw_data_file, 'r') as in_file_h5:
            raw_data = in_file_h5.root.raw_data[:]
            for front_end in range(front_ends):
                print 'Create occupancy hist of front end %d' % front_end
                occupancy_array, _, _ = np.histogram2d(*readout_utils.convert_data_array(raw_data,
                                                                                         filter_func=readout_utils.logical_and(readout_utils.is_data_record, readout_utils.is_data_from_channel(4 - front_end)),
                                                                                         converter_func=readout_utils.get_col_row_array_from_data_record_array), bins=(80, 336), range=[[1, 80], [1, 336]])
                plotting.plot_three_way(hist=occupancy_array.T, title="Occupancy of chip %d" % front_end, x_axis_title="Occupancy", filename=output_pdf)
Beispiel #3
0
def draw_hit_map_from_raw_data(raw_data_file, front_ends):
    with PdfPages(raw_data_file[:-3] + '.pdf') as output_pdf:
        with tb.open_file(raw_data_file, 'r') as in_file_h5:
            raw_data = in_file_h5.root.raw_data[:]
            for front_end in range(front_ends):
                print 'Create occupancy hist of front end %d' % front_end
                occupancy_array, _, _ = np.histogram2d(*readout_utils.convert_data_array(raw_data,
                                                                                         filter_func=readout_utils.logical_and(readout_utils.is_data_record, readout_utils.is_data_from_channel(4 - front_end)),
                                                                                         converter_func=readout_utils.get_col_row_array_from_data_record_array), bins=(80, 336), range=[[1, 80], [1, 336]])
                plotting.plotThreeWay(hist=occupancy_array.T, title="Occupancy of chip %d" % front_end, x_axis_title="Occupancy", filename=output_pdf)
Beispiel #4
0
    def read_raw_data_from_fifo(self,
                                fifo,
                                filter_func=None,
                                converter_func=None):
        '''Reads FIFO data and returns raw data array.

        Returns
        -------
        data : np.array
            An array containing FIFO data words.
        '''
        return convert_data_array(self.dut[fifo].get_data(),
                                  filter_func=filter_func,
                                  converter_func=converter_func)
Beispiel #5
0
def analyse(data_array):
    global global_vars

    if threshold_vars["integration_time"] < 0.05:
        threshold_vars["integration_time"] = 0.05
    for ro in data_array[0]:
        raw_data = ro[0]
        data_record = ru.convert_data_array(raw_data, filter_func=is_record)
        global_vars["timestamp_start"].append(ro[1])
        timestamp_stop = ro[2]
        global_vars["hits"].append(len(data_record))

        if np.any(data_record):
            col, row = get_col_row_array_from_data_record_array(data_record)

            global_vars["coloumn"].append(np.median(col))
            global_vars["row"].append(np.median(row))

            if not np.any(global_vars["hist_occ"]):
                global_vars["hist_occ"] = fast_analysis_utils.hist_2d_index(
                    col, row, shape=(81, 337))
            else:
                global_vars["hist_occ"] += fast_analysis_utils.hist_2d_index(
                    col, row, shape=(81, 337))

        if timestamp_stop - global_vars["timestamp_start"][0] > threshold_vars[
                "integration_time"]:
            global_vars["hitrate"].append(
                np.sum(global_vars["hits"]) /
                (timestamp_stop - global_vars["timestamp_start"][0]))

            if (runmngr.current_run.run_id == "fei4_self_trigger_scan"
                    or runmngr.current_run.run_id
                    == "ext_trigger_scan") and global_vars["analyse"]:
                global_vars["beam"] = analyse_beam(global_vars["beam"])

            p_hist = pickle.dumps(global_vars["hist_occ"], -1)
            zlib_hist = zlib.compress(p_hist)
            socket2.send(zlib_hist)
            # free memory of global variables
            del global_vars["hits"][:]
            del global_vars["timestamp_start"][:]
            global_vars["hist_occ"] = None
            #single variance gets diminished for long mesurements, this resets the variables after some time
            #diminishing the number leads to more sensitivity
            if len(global_vars["coloumn"]
                   ) > threshold_vars["reset_coloumn_row_arrays"]:
                del global_vars["coloumn"][:]
                del global_vars["row"][:]
Beispiel #6
0
 def test_hit_histograming(self):
     raw_data = np.array([67307647, 67645759, 67660079, 67541711, 67718111, 67913663, 67914223, 67847647, 67978655, 68081199, 68219119, 68219487, 68425615, 68311343, 68490719, 68373295, 68553519, 68693039, 68573503, 68709951, 68717058, 68734735, 68604719, 68753999, 68761151, 68847327, 69014799, 69079791, 69211359, 69221055, 69279567, 69499247, 69773183, 69788527, 69998559, 69868559, 69872655, 70003599, 69902527, 70274575, 70321471, 70429983, 70563295, 70574959, 70447631, 70584591, 70783023, 71091999, 70972687, 70985087, 71214815, 71382623, 71609135, 71643519, 71720527, 71897695, 72167199, 72040047, 72264927, 72423983, 77471983, 77602863, 77604383, 77485295, 77616415, 77618927, 77619231, 77639983, 77655871, 77544159, 77548303, 77338399, 77345567, 77346287, 77360399, 77255407, 77386211, 77268287, 77279215, 77409599, 77075983, 76951903, 76980527, 77117023, 76991055, 77011007, 77148127, 77148815, 76827167, 76700031, 76868895, 76758575, 76889567, 76558303, 76429599, 76584783, 76468191, 76610943, 76613743, 76620879, 76629375, 76285999, 76321908, 76194319, 76205599, 76233759, 76065391, 76075839, 76093759, 75801311, 75826319, 75829215, 75699231, 75403887, 75565039, 75439135, 75111711, 75115151, 75251487, 75258399, 75138015, 75303471, 74974111, 74868559, 75030047, 75050079, 74714591, 74722847, 74595103, 74649935, 74656815, 74796511, 74455519, 74391519, 74402607, 74534383, 74189695, 74064911, 74246271, 74116063, 74248719, 74133119, 73935183, 73941087, 73811295, 73663583, 73743423, 73449647, 73453391, 73323743, 73343471, 73474159, 73345087, 73206751, 72899295, 72958559, 72828447, 72542623, 82383232, 67374687, 67503967, 67766575, 68179999, 68052847, 68198239, 68104495, 68235759, 68238223, 68472415, 68490463, 68501279, 68621071, 68623903, 68821791, 68988639, 68864047, 69003183, 68876015, 69007423, 68891407, 69267743, 69272367, 69159567, 69666911, 69684447, 70003247, 70018895, 69898927, 69938543, 69942031, 70198863, 70339919, 70587455, 70462783, 70597679, 70796399, 70800015, 70703887, 71121183, 71323151, 71243535, 71578703, 71467695, 71622879, 71629359, 71831264, 71836511, 71710319, 71992943, 72353855, 72355039, 77606628, 77608287, 77622047, 77510223, 77653263, 77664319, 77546223, 77677471, 77549375, 77213519, 77219551, 77232207, 77234991, 77366511, 77373791, 77389647, 77404383, 77070655, 77087199, 76956975, 76996431, 77009183, 77015327, 76683567, 76840351, 76862255, 76888804, 76548975, 76554767, 76427087, 76560159, 76451967, 76456847, 76468015, 76627295, 76352831, 76354863, 76365887, 75923999, 76074175, 75955439, 76086063, 75774239, 75781535, 75792671, 75662111, 75793647, 75797167, 75827023, 75696543, 75390527, 75522031, 75533663, 75541775, 75432255, 75571535, 75115535, 75247999, 75145197, 75151391, 75160799, 74974991, 74852831, 74871839, 74882783, 75023199, 74896943, 75028767, 75046431, 74922463, 74725711, 74621199, 74658623, 74663183, 74336383, 74484559, 74364526, 74370287, 74370639, 74517983, 74393615, 74205471, 74217359, 74227263, 74231727, 74102559, 74237999, 74248735, 73953599, 73868591, 74000703, 74002975, 73877295, 73664910, 73695967, 73704751, 73579583, 73582639, 73719055, 73405998, 73448207, 73481951, 73008831, 73175087, 73044495, 73058863, 73194895, 73197919, 73093151, 72895567, 72918543, 72947039, 72957919, 82383481, 67392015, 67303135, 67312799, 67318303, 67453727, 67454767, 67634719, 67645887, 67717391, 67914111, 67947919, 67818463, 68052959, 68097215, 68500543, 68711909, 68584735, 68726975, 68741679, 68615471, 68750559, 68755487, 68629311, 68764687, 68765648, 68990175, 69022959, 69023727, 69217327, 69547327, 69665839, 69809983, 69814815, 70006831, 70037807, 70055951, 70068511, 70184031, 70323999, 70334687, 70566095, 70588751, 70723935, 71049695, 70952031, 71084831, 71376863, 71256287, 71611039, 71487727, 71618591, 71623999, 71514239, 71891231, 71897327, 71897663, 72036783, 72391487, 77604975, 77608163, 77621327, 77501983, 77635039, 77646559, 77654671, 77655695, 77546543, 77678383, 77345471, 77224735, 77375519, 77385519, 77393967, 76944399, 76975663, 77114628, 77115231, 77127525, 77142959, 76677423, 76699967, 76722287, 76857647, 76739039, 76883567, 76891615, 76453343, 76584335, 76590623, 76594607, 76600031, 76611167, 76617743, 76622303, 76285999, 76329231, 76335839, 76348175, 76350351, 76356783, 75910383, 75639343, 75787615, 75660079, 75796895, 75797615, 75692559, 75827999, 75833487, 75836479, 75518943, 75568143, 75278943, 75290271, 75297903, 75309391, 75312479, 75315119, 74852223, 74987055, 74858047, 74992943, 74875439, 75008031, 74885407, 75027743, 75055583, 74927839, 74738719, 74629087, 74767391, 74779295, 74789343, 74791247, 74323183, 74454239, 74349455, 74364751, 74516047, 74528559, 74192207, 74201535, 74084367, 74220511, 74109039, 74263263, 74133215, 73807119, 73945313, 73868148, 74001631, 73536815, 73684815, 73711439, 73275407, 73408799, 73052767, 73190975, 73209823, 72788271, 72960607, 72487647, 82383730, 67407151, 67415583, 67322127, 67523871, 67700959, 67583039, 67905375, 67793199, 68159583, 68237791, 68306479, 68492399], np.uint32)
     interpreter = PyDataInterpreter()
     histograming = PyDataHistograming()
     interpreter.set_trig_count(1)
     interpreter.set_warning_output(False)
     histograming.set_no_scan_parameter()
     histograming.create_occupancy_hist(True)
     interpreter.interpret_raw_data(raw_data)
     interpreter.store_event()
     histograming.add_hits(interpreter.get_hits())
     occ_hist_cpp = histograming.get_occupancy()[:, :, 0]
     col_arr, row_arr = convert_data_array(raw_data, filter_func=is_data_record, converter_func=get_col_row_array_from_data_record_array)
     occ_hist_python, _, _ = np.histogram2d(col_arr, row_arr, bins=(80, 336), range=[[1, 80], [1, 336]])
     self.assertTrue(np.all(occ_hist_cpp == occ_hist_python))
Beispiel #7
0
    def get_raw_data_from_buffer(self, filter_func=None, converter_func=None):
        '''Reads local data buffer and returns raw data array.

        Returns
        -------
        data : np.array
            An array containing data words from the local data buffer.
        '''
        if self._is_running:
            raise RuntimeError('Readout thread running')
        if not self.fill_buffer:
            logging.warning('Data buffer is not activated')
        return [
            convert_data_array(data_array_from_data_iterable(data_iterable),
                               filter_func=filter_func,
                               converter_func=converter_func)
            for data_iterable in self._data_buffer
        ]
Beispiel #8
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False
        mask_steps = 3
        enable_mask_steps = [
            0
        ]  # one mask step to increase speed, no effect on precision
        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands(
                    "LV1")[0] + self.register.get_commands(
                        "zeros", mask_steps=mask_steps)[0]

        self.write_target_charge()

        for feedback_bit in self.feedback_tune_bits:  # reset all GDAC bits
            self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)

        additional_scan = True
        last_bit_result = self.n_injections_feedback

        tot_mean_best = 0
        feedback_best = self.register.get_global_register_value("PrmpVbpf")
        for feedback_bit in self.feedback_tune_bits:
            if additional_scan:
                self.set_prmp_vbpf_bit(feedback_bit)
                logging.info(
                    'PrmpVbpf setting: %d, bit %d = 1' %
                    (self.register.get_global_register_value("PrmpVbpf"),
                     feedback_bit))
            else:
                self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)
                logging.info(
                    'PrmpVbpf setting: %d, bit %d = 0' %
                    (self.register.get_global_register_value("PrmpVbpf"),
                     feedback_bit))

            scan_parameter_value = self.register.get_global_register_value(
                "PrmpVbpf")

            with self.readout(PrmpVbpf=scan_parameter_value):
                scan_loop(self,
                          cal_lvl1_command,
                          repeat_command=self.n_injections_feedback,
                          mask_steps=mask_steps,
                          enable_mask_steps=enable_mask_steps,
                          enable_double_columns=None,
                          same_mask_for_all_dc=True,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            self.raw_data_file.append(
                self.fifo_readout.data,
                scan_parameters=self.scan_parameters._asdict())

            tots = convert_data_array(
                data_array_from_data_iterable(self.fifo_readout.data),
                filter_func=is_data_record,
                converter_func=get_tot_array_from_data_record_array)
            mean_tot = np.mean(tots)
            if np.isnan(mean_tot):
                logging.error(
                    "No hits, ToT calculation not possible, tuning will fail")

            if abs(mean_tot - self.target_tot) < abs(tot_mean_best -
                                                     self.target_tot):
                tot_mean_best = mean_tot
                feedback_best = self.register.get_global_register_value(
                    "PrmpVbpf")

            logging.info('Mean ToT = %f' % mean_tot)
            self.tot_array, _ = np.histogram(a=tots, range=(0, 16), bins=16)
            if self.plot_intermediate_steps:
                plot_tot(hist=self.tot_array,
                         title='ToT distribution (PrmpVbpf ' +
                         str(scan_parameter_value) + ')',
                         filename=self.plots_filename)

            if abs(
                    mean_tot - self.target_tot
            ) < self.max_delta_tot and feedback_bit > 0:  # abort if good value already found to save time
                logging.info(
                    'Good result already achieved, skipping missing bits')
                break

            if feedback_bit > 0 and mean_tot < self.target_tot:
                self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)
                logging.info('Mean ToT = %f < %d ToT, set bit %d = 0' %
                             (mean_tot, self.target_tot, feedback_bit))

            if feedback_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    last_bit_result = mean_tot
                    self.feedback_tune_bits.append(
                        0)  # bit 0 has to be scanned twice
                else:
                    logging.info(
                        'Scanned bit 0 = 0 with %f instead of %f for scanned bit 0 = 1'
                        % (mean_tot, last_bit_result))
                    if (abs(mean_tot - self.target_tot) >
                            abs(last_bit_result - self.target_tot)
                        ):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        self.set_prmp_vbpf_bit(feedback_bit, bit_value=1)
                        mean_tot = last_bit_result
                        logging.info('Set bit 0 = 1')
                    else:
                        logging.info('Set bit 0 = 0')
                if abs(mean_tot - self.target_tot) > abs(tot_mean_best -
                                                         self.target_tot):
                    logging.info(
                        "Binary search converged to non optimal value, take best measured value instead"
                    )
                    mean_tot = tot_mean_best
                    self.register.set_global_register_value(
                        "PrmpVbpf", feedback_best)

        if self.register.get_global_register_value(
                "PrmpVbpf") == 0 or self.register.get_global_register_value(
                    "PrmpVbpf") == 254:
            logging.warning('PrmpVbpf reached minimum/maximum value')

        if abs(mean_tot - self.target_tot) > 2 * self.max_delta_tot:
            logging.warning(
                'Global feedback tuning failed. Delta ToT = %f > %f. PrmpVbpf = %d'
                % (abs(mean_tot - self.target_tot), self.max_delta_tot,
                   self.register.get_global_register_value("PrmpVbpf")))
        else:
            logging.info('Tuned PrmpVbpf to %d' %
                         self.register.get_global_register_value("PrmpVbpf"))

        self.feedback_best = self.register.get_global_register_value(
            "PrmpVbpf")
Beispiel #9
0
    def scan(self):
        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while(int_type):
                if(int_type & 1):
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        if not self.enable_mask_steps_feedback:
            self.enable_mask_steps_feedback = range(self.mask_steps)
        for mask_step in self.enable_mask_steps_feedback:
            select_mask_array += make_pixel_mask(steps=self.mask_steps, shift=mask_step)
        for column in bits_set(self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info('Deselect double column %d' % column)
            select_mask_array[column, :] = 0

        cal_lvl1_command = self.register.get_commands("CAL")[0] + self.register.get_commands("zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_charge()

        for feedback_bit in self.feedback_tune_bits:  # reset all feedback bits
            self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)

        additional_scan = True
        tot_mean_best = 0.0
        feedback_best = self.register.get_global_register_value("PrmpVbpf")
        feedback_tune_bits = self.feedback_tune_bits[:]
        for feedback_bit in feedback_tune_bits:
            if self.stop_run.is_set():
                break
            if additional_scan:
                self.set_prmp_vbpf_bit(feedback_bit, bit_value=1)
                logging.info('PrmpVbpf setting: %d, set bit %d = 1', self.register.get_global_register_value("PrmpVbpf"), feedback_bit)
            else:
                self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)
                logging.info('PrmpVbpf setting: %d, set bit %d = 0', self.register.get_global_register_value("PrmpVbpf"), feedback_bit)

            scan_parameter_value = self.register.get_global_register_value("PrmpVbpf")

            with self.readout(PrmpVbpf=scan_parameter_value, fill_buffer=True):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_feedback,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=self.enable_mask_steps_feedback,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            data = convert_data_array(array=self.read_data(), filter_func=is_data_record, converter_func=get_col_row_tot_array_from_data_record_array)
            col_row_tot_array = np.column_stack(data)
            occupancy_array, _, _ = np.histogram2d(col_row_tot_array[:, 0], col_row_tot_array[:, 1], bins=(80, 336), range=[[1, 80], [1, 336]])
            occupancy_array = np.ma.array(occupancy_array, mask=np.logical_not(np.ma.make_mask(select_mask_array)))  # take only selected pixel into account by creating a mask
            occupancy_array = np.ma.masked_where(occupancy_array > self.n_injections_feedback, occupancy_array)
            col_row_tot_hist = np.histogramdd(col_row_tot_array, bins=(80, 336, 16), range=[[1, 80], [1, 336], [0, 15]])[0]
            tot_mean_array = np.average(col_row_tot_hist, axis=2, weights=range(0, 16)) * sum(range(0, 16)) / self.n_injections_feedback
            tot_mean_array = np.ma.array(tot_mean_array, mask=occupancy_array.mask)
            # keep noisy pixels out
            mean_tot = np.ma.mean(tot_mean_array)

            if abs(mean_tot - self.target_tot) < abs(tot_mean_best - self.target_tot):
                tot_mean_best = mean_tot
                feedback_best = self.register.get_global_register_value("PrmpVbpf")

            logging.info('Mean ToT = %.2f', mean_tot)
            tot_array = col_row_tot_array[:, 2]
            self.tot_hist, _ = np.histogram(a=tot_array, range=(0, 16), bins=16)
            if self.plot_intermediate_steps:
                plot_tot(hist=self.tot_hist, title='ToT distribution (PrmpVbpf ' + str(scan_parameter_value) + ')', filename=self.plots_filename)

#             if abs(mean_tot - self.target_tot) < self.max_delta_tot and feedback_bit > 0:  # abort if good value already found to save time
#                 logging.info('Good result already achieved, skipping missing bits')
#                 break

            if feedback_bit > 0:
                # TODO: if feedback is to high, no hits
                if mean_tot < self.target_tot:
                    self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)
                    logging.info('Mean ToT = %.2f < %.2f ToT, set bit %d = 0', mean_tot, self.target_tot, feedback_bit)
                else:
                    logging.info('Mean ToT = %.2f > %.2f ToT, keep bit %d = 1', mean_tot, self.target_tot, feedback_bit)
            elif feedback_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    last_mean_tot = mean_tot
                    last_tot_hist = self.tot_hist.copy()
                    feedback_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    logging.info('Measured %.2f with bit 0 = 0 and %.2f with bit 0 = 1', mean_tot, last_mean_tot)
                    if(abs(mean_tot - self.target_tot) > abs(last_mean_tot - self.target_tot)):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        logging.info('Set bit 0 = 1')
                        self.set_prmp_vbpf_bit(0, bit_value=1)
                        self.tot_hist = last_tot_hist.copy()
                        mean_tot = last_mean_tot
                    else:
                        logging.info('Keep bit 0 = 0')

        # select best Feedback value
        if abs(mean_tot - self.target_tot) > abs(tot_mean_best - self.target_tot):
            logging.info("Binary search converged to non-optimal value, apply best Feedback value, change PrmpVbpf from %d to %d", self.register.get_global_register_value("PrmpVbpf"), feedback_best)
            mean_tot = tot_mean_best
            self.register.set_global_register_value("PrmpVbpf", feedback_best)

        self.feedback_best = self.register.get_global_register_value("PrmpVbpf")

        if abs(mean_tot - self.target_tot) > 2 * self.max_delta_tot and not self.stop_run.is_set():
            if np.all((((self.feedback_best & (1 << np.arange(self.register.global_registers['PrmpVbpf']['bitlength'])))) > 0).astype(int)[self.feedback_tune_bits] == 1):
                if self.fail_on_warning:
                    raise RuntimeWarning('Selected Feedback bits reached maximum value')
                else:
                    logging.warning('Selected Feedback bits reached maximum value')
            elif np.all((((self.feedback_best & (1 << np.arange(self.register.global_registers['PrmpVbpf']['bitlength'])))) > 0).astype(int)[self.feedback_tune_bits] == 0):
                if self.fail_on_warning:
                    raise RuntimeWarning('Selected Feedback bits reached minimum value')
                else:
                    logging.warning('Selected Feedback bits reached minimum value')
            else:
                if self.fail_on_warning:
                    raise RuntimeWarning('Global feedback tuning failed. Delta ToT = %.2f > %.2f. PrmpVbpf = %d' % (abs(mean_tot - self.target_tot), self.max_delta_tot, self.register.get_global_register_value("PrmpVbpf")))
                else:
                    logging.warning('Global feedback tuning failed. Delta ToT = %.2f > %.2f. PrmpVbpf = %d', abs(mean_tot - self.target_tot), self.max_delta_tot, self.register.get_global_register_value("PrmpVbpf"))
        else:
            logging.info('Tuned PrmpVbpf to %d', self.register.get_global_register_value("PrmpVbpf"))
Beispiel #10
0
    def scan(self):
        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_threshold()

        scan_parameter_range = [
            (2**self.register.global_registers['Vthin_AltFine']['bitlength']),
            0
        ]  # high to low
        if self.start_gdac:
            scan_parameter_range[0] = self.start_gdac
        if self.gdac_lower_limit:
            scan_parameter_range[1] = self.gdac_lower_limit

        scan_parameter_range = np.arange(scan_parameter_range[0],
                                         scan_parameter_range[1] - 1,
                                         self.step_size)

        logging.info("Scanning %s from %d to %d", 'GDAC',
                     scan_parameter_range[0], scan_parameter_range[-1])

        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while (int_type):
                if (int_type & 1):
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        self.occ_array_sel_pixels_best = select_mask_array.copy()
        self.occ_array_desel_pixels_best = select_mask_array.copy()
        if not self.enable_mask_steps_gdac:
            self.enable_mask_steps_gdac = range(self.mask_steps)
        for mask_step in self.enable_mask_steps_gdac:
            select_mask_array += make_pixel_mask(steps=self.mask_steps,
                                                 shift=mask_step)
        for column in bits_set(
                self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info('Deselect double column %d' % column)
            select_mask_array[column, :] = 0

        gdac_values = []
        gdac_occupancies = []
        gdac_occ_array_sel_pixels = []
        gdac_occ_array_desel_pixels = []
        median_occupancy_last_step = None
        for scan_parameter_value in scan_parameter_range:
            if self.stop_run.is_set():
                break
            self.register_utils.set_gdac(scan_parameter_value)
            with self.readout(GDAC=scan_parameter_value, fill_buffer=True):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_gdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=self.enable_mask_steps_gdac,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            data = convert_data_array(
                array=self.read_data(),
                filter_func=is_data_record,
                converter_func=get_col_row_array_from_data_record_array)
            occupancy_array, _, _ = np.histogram2d(*data,
                                                   bins=(80, 336),
                                                   range=[[1, 80], [1, 336]])
            occ_array_sel_pixels = np.ma.array(
                occupancy_array,
                mask=np.logical_not(np.ma.make_mask(select_mask_array))
            )  # take only selected pixel into account by using the mask
            occ_array_desel_pixels = np.ma.array(
                occupancy_array, mask=np.ma.make_mask(select_mask_array)
            )  # take only de-selected pixel into account by using the inverted mask
            median_occupancy = np.ma.median(occ_array_sel_pixels)
            percentile_noise_occupancy = np.percentile(
                occ_array_desel_pixels.compressed(), 99.0)
            occupancy_almost_zero = np.allclose(median_occupancy, 0)
            no_noise = np.allclose(percentile_noise_occupancy, 0)
            gdac_values.append(self.register_utils.get_gdac())
            gdac_occupancies.append(median_occupancy)
            gdac_occ_array_sel_pixels.append(occ_array_sel_pixels.copy())
            gdac_occ_array_desel_pixels.append(occ_array_desel_pixels.copy())
            self.occ_array_sel_pixels_best = occ_array_sel_pixels.copy()
            self.occ_array_desel_pixels_best = occ_array_desel_pixels.copy()

            # abort early if threshold is found
            if no_noise and not occupancy_almost_zero and (
                    median_occupancy_last_step is not None
                    and median_occupancy >= median_occupancy_last_step
            ) and median_occupancy >= self.n_injections_gdac / 2.0:
                break

            if no_noise and not occupancy_almost_zero:
                median_occupancy_last_step = median_occupancy
            else:
                median_occupancy_last_step = 0.0

        if not self.stop_run.is_set():
            # select best GDAC value
            sorted_indices = np.argsort(np.array(gdac_values))
            occupancy_sorted = np.array(gdac_occupancies)[sorted_indices]
            gdac_sorted = np.sort(gdac_values)
            gdac_min_idx = np.where(
                occupancy_sorted >= self.n_injections_gdac / 2.0)[0][-1]
            occupancy_sorted_sel = occupancy_sorted[gdac_min_idx:]
            gdac_sorted_sel = gdac_sorted[gdac_min_idx:]
            best_index_sel = np.abs(
                np.array(occupancy_sorted_sel) -
                self.n_injections_gdac / 2.0).argmin()
            best_index = sorted_indices[gdac_min_idx:][::-1][best_index_sel]
            gdac_best = gdac_values[best_index]
            median_occupancy = gdac_occupancies[best_index]
            self.register_utils.set_gdac(gdac_best, send_command=False)
            # for plotting
            self.occ_array_sel_pixels_best = gdac_occ_array_sel_pixels[
                best_index]
            self.occ_array_desel_pixels_best = gdac_occ_array_desel_pixels[
                best_index]
            self.gdac_best = self.register_utils.get_gdac()

            if abs(median_occupancy - self.n_injections_gdac / 2.0
                   ) > self.max_delta_threshold and not self.stop_run.is_set():
                if np.all((((self.gdac_best & (1 << np.arange(
                        self.register.global_registers['Vthin_AltFine']
                    ['bitlength'] + self.register.
                        global_registers['Vthin_AltFine']['bitlength'])))) > 0
                           ).astype(int) == 0):
                    if self.fail_on_warning:
                        raise RuntimeWarning(
                            'Selected GDAC bits reached minimum value')
                    else:
                        logging.warning(
                            'Selected GDAC bits reached minimum value')
                else:
                    if self.fail_on_warning:
                        raise RuntimeWarning(
                            'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d'
                            % (abs(median_occupancy - self.n_injections_gdac /
                                   2.0), self.max_delta_threshold,
                               self.register.get_global_register_value(
                                   "Vthin_AltCoarse"),
                               self.register.get_global_register_value(
                                   "Vthin_AltFine")))
                    else:
                        logging.warning(
                            'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                            abs(median_occupancy -
                                self.n_injections_gdac / 2.0),
                            self.max_delta_threshold,
                            self.register.get_global_register_value(
                                "Vthin_AltCoarse"),
                            self.register.get_global_register_value(
                                "Vthin_AltFine"))
            else:
                logging.info(
                    'Tuned GDAC to Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                    self.register.get_global_register_value("Vthin_AltCoarse"),
                    self.register.get_global_register_value("Vthin_AltFine"))
Beispiel #11
0
    def scan(self):
        enable_mask_steps = []

        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_charge()
        additional_scan = True
        last_tot_mean_array = np.zeros(
            shape=self.register.get_pixel_register_value("FDAC").shape,
            dtype=self.register.get_pixel_register_value("FDAC").dtype)

        self.set_start_fdac()

        self.tot_mean_best = np.full(
            shape=(80, 336), fill_value=0
        )  # array to store the best occupancy (closest to Ninjections/2) of the pixel
        self.fdac_mask_best = self.register.get_pixel_register_value("FDAC")
        fdac_tune_bits = self.fdac_tune_bits[:]
        for scan_parameter_value, fdac_bit in enumerate(fdac_tune_bits):
            if self.stop_run.is_set():
                break
            if additional_scan:
                self.set_fdac_bit(fdac_bit, bit_value=1)
                logging.info('FDAC setting: bit %d = 1', fdac_bit)
            else:
                self.set_fdac_bit(fdac_bit, bit_value=0)
                logging.info('FDAC setting: bit %d = 0', fdac_bit)

            self.write_fdac_config()

            with self.readout(FDAC=scan_parameter_value, fill_buffer=True):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_fdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=enable_mask_steps,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            data = convert_data_array(
                array=self.read_data(),
                filter_func=is_data_record,
                converter_func=get_col_row_tot_array_from_data_record_array)
            col_row_tot = np.column_stack(data)
            tot_array = np.histogramdd(col_row_tot,
                                       bins=(80, 336, 16),
                                       range=[[1, 80], [1, 336], [0, 15]])[0]
            tot_mean_array = np.average(
                tot_array, axis=2, weights=range(0, 16)) * sum(range(
                    0, 16)) / self.n_injections_fdac
            select_better_pixel_mask = abs(
                tot_mean_array - self.target_tot) <= abs(self.tot_mean_best -
                                                         self.target_tot)
            self.tot_mean_best[select_better_pixel_mask] = tot_mean_array[
                select_better_pixel_mask]
            fdac_mask = self.register.get_pixel_register_value("FDAC")
            self.fdac_mask_best[select_better_pixel_mask] = fdac_mask[
                select_better_pixel_mask]

            if fdac_bit > 0:
                pixel_with_too_small_mean_tot_mask = tot_mean_array < self.target_tot
                fdac_mask[pixel_with_too_small_mean_tot_mask] = fdac_mask[
                    pixel_with_too_small_mean_tot_mask] & ~(
                        1 << fdac_bit)  # unset FDAC bit, increase ToT
                self.register.set_pixel_register_value("FDAC", fdac_mask)
            elif fdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    fdac_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    pass

        if not self.stop_run.is_set():
            self.register.set_pixel_register_value(
                "FDAC", self.fdac_mask_best)  # set value for meta scan
            self.write_fdac_config()
    def scan(self):
        scan_parameter_range = [
            self.register.get_global_register_value("Vthin_AltFine"), 0
        ]
        if self.scan_parameters.Vthin_AltFine[0]:
            scan_parameter_range[0] = self.scan_parameters.Vthin_AltFine[0]
        if self.scan_parameters.Vthin_AltFine[1]:
            scan_parameter_range[1] = self.scan_parameters.Vthin_AltFine[1]
        steps = 1
        if self.scan_parameters.Step:
            steps = self.scan_parameters.Step

        lvl1_command = self.register.get_commands(
            "LV1")[0] + self.register.get_commands(
                "zeros", length=self.trigger_rate_limit)[0]
        self.total_scan_time = int(lvl1_command.length() * 25 * (10**-9) *
                                   self.n_triggers)

        disabled_pixels_limit_cnt = int(self.disabled_pixels_limit * 336 * 80)
        preselected_pixels = invert_pixel_mask(
            self.register.get_pixel_register_value('Enable')).sum()
        disabled_pixels = 0

        for reg_val in range(scan_parameter_range[0],
                             scan_parameter_range[1] - 1, -1):
            if self.stop_run.is_set():
                break
            self.register.create_restore_point(name=str(reg_val))
            logging.info('Scanning Vthin_AltFine %d' % reg_val)
            commands = []
            commands.extend(self.register.get_commands("ConfMode"))
            self.register.set_global_register_value(
                "Vthin_AltFine", reg_val)  # set number of consecutive triggers
            commands.extend(
                self.register.get_commands("WrRegister",
                                           name=["Vthin_AltFine"]))
            # setting FE into RunMode
            commands.extend(self.register.get_commands("RunMode"))
            self.register_utils.send_commands(commands)
            step = 0
            while True:
                if self.stop_run.is_set():
                    break
                step += 1
                logging.info('Step %d / %d at Vthin_AltFine %d' %
                             (step, steps, reg_val))
                logging.info('Estimated scan time: %ds' % self.total_scan_time)

                with self.readout(Vthin_AltFine=reg_val, Step=step):
                    got_data = False
                    start = time()
                    self.register_utils.send_command(lvl1_command,
                                                     repeat=self.n_triggers,
                                                     wait_for_finish=False,
                                                     set_length=True,
                                                     clear_memory=False)
                    while not self.stop_run.wait(0.1):
                        if self.register_utils.is_ready:
                            if got_data:
                                self.progressbar.finish()
                            logging.info('Finished sending %d triggers' %
                                         self.n_triggers)
                            break
                        if not got_data:
                            if self.fifo_readout.data_words_per_second() > 0:
                                got_data = True
                                logging.info('Taking data...')
                                self.progressbar = progressbar.ProgressBar(
                                    widgets=[
                                        '',
                                        progressbar.Percentage(), ' ',
                                        progressbar.Bar(marker='*',
                                                        left='|',
                                                        right='|'), ' ',
                                        progressbar.Timer()
                                    ],
                                    maxval=self.total_scan_time,
                                    poll=10,
                                    term_width=80).start()
                        else:
                            try:
                                self.progressbar.update(time() - start)
                            except ValueError:
                                pass

                self.raw_data_file.append(
                    self.fifo_readout.data,
                    scan_parameters=self.scan_parameters._asdict())
                col_arr, row_arr = convert_data_array(
                    data_array_from_data_iterable(self.fifo_readout.data),
                    filter_func=is_data_record,
                    converter_func=get_col_row_array_from_data_record_array)
                occ_hist, _, _ = np.histogram2d(col_arr,
                                                row_arr,
                                                bins=(80, 336),
                                                range=[[1, 80], [1, 336]])
                occ_mask = np.zeros(shape=occ_hist.shape,
                                    dtype=np.dtype('>u1'))
                # noisy pixels are set to 1
                occ_mask[occ_hist > self.occupancy_limit * self.n_triggers *
                         self.consecutive_lvl1] = 1
                #                     plot_occupancy(occ_hist.T, title='Occupancy', filename=self.scan_data_filename + '_noise_occ_' + str(reg_val) + '_' + str(step) + '.pdf')

                tdac_reg = self.register.get_pixel_register_value('TDAC')
                decrease_pixel_mask = np.logical_and(occ_mask > 0,
                                                     tdac_reg > 0)
                disable_pixel_mask = np.logical_and(occ_mask > 0,
                                                    tdac_reg == 0)
                enable_reg = self.register.get_pixel_register_value('Enable')
                enable_mask = np.logical_and(
                    enable_reg, invert_pixel_mask(disable_pixel_mask))
                if np.logical_and(occ_mask > 0, enable_reg == 0).sum():
                    logging.warning('Received data from disabled pixels')


#                     disabled_pixels += disable_pixel_mask.sum()  # can lead to wrong values if the enable reg is corrupted
                disabled_pixels = invert_pixel_mask(
                    enable_mask).sum() - preselected_pixels
                if disabled_pixels > disabled_pixels_limit_cnt:
                    logging.info(
                        'Limit of disabled pixels reached: %d (limit %d)... stopping scan'
                        % (disabled_pixels, disabled_pixels_limit_cnt))
                    self.register.restore(name=str(reg_val))
                    break
                else:
                    logging.info('Increasing threshold of %d pixel(s)' %
                                 (decrease_pixel_mask.sum(), ))
                    logging.info(
                        'Disabling %d pixel(s), total number of disabled pixel(s): %d'
                        % (disable_pixel_mask.sum(), disabled_pixels))
                    tdac_reg[decrease_pixel_mask] -= 1  # TODO
                    self.register.set_pixel_register_value('TDAC', tdac_reg)
                    self.register.set_pixel_register_value(
                        'Enable', enable_mask)
                    commands = []
                    commands.extend(self.register.get_commands("ConfMode"))
                    commands.extend(
                        self.register.get_commands("WrFrontEnd",
                                                   same_mask_for_all_dc=False,
                                                   name='TDAC'))
                    commands.extend(
                        self.register.get_commands("WrFrontEnd",
                                                   same_mask_for_all_dc=False,
                                                   name='Enable'))
                    commands.extend(self.register.get_commands("RunMode"))
                    self.register_utils.send_commands(commands)
                    if occ_mask.sum(
                    ) == 0 or step == steps or decrease_pixel_mask.sum(
                    ) < disabled_pixels_limit_cnt:
                        self.register.clear_restore_points(name=str(reg_val))
                        self.last_tdac_distribution = self.register.get_pixel_register_value(
                            'TDAC')
                        self.last_occupancy_hist = occ_hist.copy()
                        self.last_occupancy_mask = occ_mask.copy()
                        self.last_reg_val = reg_val
                        self.last_step = step
                        break
                    else:
                        logging.info(
                            'Found noisy pixels... repeat tuning step for Vthin_AltFine %d'
                            % (reg_val, ))

            if disabled_pixels > disabled_pixels_limit_cnt:
                self.last_good_threshold = self.register.get_global_register_value(
                    "Vthin_AltFine")
                self.last_good_tdac = self.register.get_pixel_register_value(
                    'TDAC')
                self.last_good_enable_mask = self.register.get_pixel_register_value(
                    'Enable')
                break
Beispiel #13
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False

        enable_mask_steps = []

        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_charge()
        additional_scan = True
        lastBitResult = np.zeros(
            shape=self.register.get_pixel_register_value("FDAC").shape,
            dtype=self.register.get_pixel_register_value("FDAC").dtype)

        self.set_start_fdac()

        self.tot_mean_best = np.full(
            shape=(80, 336), fill_value=0
        )  # array to store the best occupancy (closest to Ninjections/2) of the pixel
        self.fdac_mask_best = self.register.get_pixel_register_value("FDAC")
        fdac_tune_bits = self.fdac_tune_bits[:]
        for scan_parameter_value, fdac_bit in enumerate(fdac_tune_bits):
            if additional_scan:
                self.set_fdac_bit(fdac_bit)
                logging.info('FDAC setting: bit %d = 1', fdac_bit)
            else:
                self.set_fdac_bit(fdac_bit, bit_value=0)
                logging.info('FDAC setting: bit %d = 0', fdac_bit)

            self.write_fdac_config()

            with self.readout(FDAC=scan_parameter_value,
                              reset_sram_fifo=True,
                              fill_buffer=True,
                              clear_buffer=True,
                              callback=self.handle_data):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_fdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=enable_mask_steps,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            col_row_tot = np.column_stack(
                convert_data_array(
                    data_array_from_data_iterable(self.fifo_readout.data),
                    filter_func=logical_and(is_fe_word, is_data_record),
                    converter_func=get_col_row_tot_array_from_data_record_array
                ))
            tot_array = np.histogramdd(col_row_tot,
                                       bins=(80, 336, 16),
                                       range=[[1, 80], [1, 336], [0, 15]])[0]
            tot_mean_array = np.average(
                tot_array, axis=2, weights=range(0, 16)) * sum(range(
                    0, 16)) / self.n_injections_fdac
            select_better_pixel_mask = abs(
                tot_mean_array - self.target_tot) <= abs(self.tot_mean_best -
                                                         self.target_tot)
            pixel_with_too_small_mean_tot_mask = tot_mean_array < self.target_tot
            self.tot_mean_best[select_better_pixel_mask] = tot_mean_array[
                select_better_pixel_mask]

            if self.plot_intermediate_steps:
                plot_three_way(hist=tot_mean_array.transpose().transpose(),
                               title="Mean ToT (FDAC tuning bit " +
                               str(fdac_bit) + ")",
                               x_axis_title='mean ToT',
                               filename=self.plots_filename,
                               minimum=0,
                               maximum=15)

            fdac_mask = self.register.get_pixel_register_value("FDAC")
            self.fdac_mask_best[select_better_pixel_mask] = fdac_mask[
                select_better_pixel_mask]
            if fdac_bit > 0:
                fdac_mask[pixel_with_too_small_mean_tot_mask] = fdac_mask[
                    pixel_with_too_small_mean_tot_mask] & ~(1 << fdac_bit)
                self.register.set_pixel_register_value("FDAC", fdac_mask)

            if fdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    lastBitResult = tot_mean_array.copy()
                    fdac_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    fdac_mask[abs(tot_mean_array - self.target_tot) > abs(
                        lastBitResult - self.target_tot
                    )] = fdac_mask[abs(tot_mean_array - self.target_tot) > abs(
                        lastBitResult - self.target_tot)] | (1 << fdac_bit)
                    tot_mean_array[abs(tot_mean_array - self.target_tot) > abs(
                        lastBitResult - self.target_tot)] = lastBitResult[
                            abs(tot_mean_array -
                                self.target_tot) > abs(lastBitResult -
                                                       self.target_tot)]
                    self.tot_mean_best[
                        abs(tot_mean_array - self.target_tot) <= abs(
                            self.tot_mean_best -
                            self.n_injections_fdac / 2)] = tot_mean_array[
                                abs(tot_mean_array - self.target_tot) <= abs(
                                    self.tot_mean_best -
                                    self.n_injections_fdac / 2)]
                    self.fdac_mask_best[
                        abs(tot_mean_array - self.target_tot) <= abs(
                            self.tot_mean_best -
                            self.n_injections_fdac / 2)] = fdac_mask[
                                abs(tot_mean_array - self.target_tot) <= abs(
                                    self.tot_mean_best -
                                    self.n_injections_fdac / 2)]

        self.register.set_pixel_register_value(
            "FDAC", self.fdac_mask_best)  # set value for meta scan
        self.write_fdac_config()
Beispiel #14
0
    def scan(self):
        enable_mask_steps = []
        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_threshold()
        additional_scan = True
        lastBitResult = np.zeros(
            shape=self.register.get_pixel_register_value("TDAC").shape,
            dtype=self.register.get_pixel_register_value("TDAC").dtype)

        self.set_start_tdac()

        self.occupancy_best = np.full(
            shape=(80, 336), fill_value=self.n_injections_tdac
        )  # array to store the best occupancy (closest to Ninjections/2) of the pixel
        self.tdac_mask_best = self.register.get_pixel_register_value("TDAC")
        tdac_tune_bits = self.tdac_tune_bits[:]
        for scan_parameter_value, tdac_bit in enumerate(tdac_tune_bits):
            if self.stop_run.is_set():
                break
            if additional_scan:
                self.set_tdac_bit(tdac_bit)
                logging.info('TDAC setting: bit %d = 1', tdac_bit)
            else:
                self.set_tdac_bit(tdac_bit, bit_value=0)
                logging.info('TDAC setting: bit %d = 0', tdac_bit)

            self.write_tdac_config()

            with self.readout(TDAC=scan_parameter_value, fill_buffer=True):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_tdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=enable_mask_steps,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            data = convert_data_array(
                array=self.read_data(),
                filter_func=is_data_record,
                converter_func=get_col_row_array_from_data_record_array)
            occupancy_array, _, _ = np.histogram2d(*data,
                                                   bins=(80, 336),
                                                   range=[[1, 80], [1, 336]])
            select_better_pixel_mask = abs(occupancy_array -
                                           self.n_injections_tdac / 2) <= abs(
                                               self.occupancy_best -
                                               self.n_injections_tdac / 2)
            pixel_with_too_high_occupancy_mask = occupancy_array > self.n_injections_tdac / 2
            self.occupancy_best[select_better_pixel_mask] = occupancy_array[
                select_better_pixel_mask]

            if self.plot_intermediate_steps:
                plot_three_way(occupancy_array.transpose(),
                               title="Occupancy (TDAC tuning bit " +
                               str(tdac_bit) + ")",
                               x_axis_title='Occupancy',
                               filename=self.plots_filename,
                               maximum=self.n_injections_tdac)

            tdac_mask = self.register.get_pixel_register_value("TDAC")
            self.tdac_mask_best[select_better_pixel_mask] = tdac_mask[
                select_better_pixel_mask]

            if tdac_bit > 0:
                tdac_mask[pixel_with_too_high_occupancy_mask] = tdac_mask[
                    pixel_with_too_high_occupancy_mask] & ~(1 << tdac_bit)
                self.register.set_pixel_register_value("TDAC", tdac_mask)

            if tdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    lastBitResult = occupancy_array.copy()
                    tdac_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    tdac_mask[
                        abs(occupancy_array - self.n_injections_tdac / 2) >
                        abs(lastBitResult -
                            self.n_injections_tdac / 2)] = tdac_mask[
                                abs(occupancy_array - self.n_injections_tdac /
                                    2) > abs(lastBitResult -
                                             self.n_injections_tdac / 2)] | (
                                                 1 << tdac_bit)
                    occupancy_array[
                        abs(occupancy_array - self.n_injections_tdac / 2) >
                        abs(lastBitResult -
                            self.n_injections_tdac / 2)] = lastBitResult[
                                abs(occupancy_array - self.n_injections_tdac /
                                    2) > abs(lastBitResult -
                                             self.n_injections_tdac / 2)]
                    self.occupancy_best[
                        abs(occupancy_array - self.n_injections_tdac / 2) <=
                        abs(self.occupancy_best -
                            self.n_injections_tdac / 2)] = occupancy_array[
                                abs(occupancy_array - self.n_injections_tdac /
                                    2) <= abs(self.occupancy_best -
                                              self.n_injections_tdac / 2)]
                    self.tdac_mask_best[
                        abs(occupancy_array - self.n_injections_tdac / 2) <=
                        abs(self.occupancy_best -
                            self.n_injections_tdac / 2)] = tdac_mask[
                                abs(occupancy_array - self.n_injections_tdac /
                                    2) <= abs(self.occupancy_best -
                                              self.n_injections_tdac / 2)]

        self.register.set_pixel_register_value(
            "TDAC", self.tdac_mask_best)  # set value for meta scan
        self.write_tdac_config()
Beispiel #15
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False

        enable_mask_steps = []

        cal_lvl1_command = self.register.get_commands("CAL")[0] + self.register.get_commands("zeros", length=40)[0] + self.register.get_commands("LV1")[0] + self.register.get_commands("zeros", mask_steps=self.mask_steps)[0]

        self.write_target_charge()
        additional_scan = True
        lastBitResult = np.zeros(shape=self.register.get_pixel_register_value("FDAC").shape, dtype=self.register.get_pixel_register_value("FDAC").dtype)

        self.set_start_fdac()

        self.tot_mean_best = np.empty(shape=(80, 336))  # array to store the best occupancy (closest to Ninjections/2) of the pixel
        self.tot_mean_best.fill(0)
        self.fdac_mask_best = self.register.get_pixel_register_value("FDAC")

        for scan_parameter_value, fdac_bit in enumerate(self.fdac_tune_bits):
            if additional_scan:
                self.set_fdac_bit(fdac_bit)
                logging.info('FDAC setting: bit %d = 1', fdac_bit)
            else:
                self.set_fdac_bit(fdac_bit, bit_value=0)
                logging.info('FDAC setting: bit %d = 0', fdac_bit)

            self.write_fdac_config()

            with self.readout(FDAC=scan_parameter_value, reset_sram_fifo=True, fill_buffer=True, clear_buffer=True, callback=self.handle_data):
                scan_loop(self, cal_lvl1_command, repeat_command=self.n_injections_fdac, mask_steps=self.mask_steps, enable_mask_steps=enable_mask_steps, enable_double_columns=None, same_mask_for_all_dc=True, eol_function=None, digital_injection=False, enable_shift_masks=self.enable_shift_masks, disable_shift_masks=self.disable_shift_masks, restore_shift_masks=True, mask=None, double_column_correction=self.pulser_dac_correction)

            col_row_tot = np.column_stack(convert_data_array(data_array_from_data_iterable(self.fifo_readout.data), filter_func=is_data_record, converter_func=get_col_row_tot_array_from_data_record_array))
            tot_array = np.histogramdd(col_row_tot, bins=(80, 336, 16), range=[[1, 80], [1, 336], [0, 15]])[0]
            tot_mean_array = np.average(tot_array, axis=2, weights=range(0, 16)) * sum(range(0, 16)) / self.n_injections_fdac
            select_better_pixel_mask = abs(tot_mean_array - self.target_tot) <= abs(self.tot_mean_best - self.target_tot)
            pixel_with_too_small_mean_tot_mask = tot_mean_array < self.target_tot
            self.tot_mean_best[select_better_pixel_mask] = tot_mean_array[select_better_pixel_mask]

            if self.plot_intermediate_steps:
                plot_three_way(hist=tot_mean_array.transpose().transpose(), title="Mean ToT (FDAC tuning bit " + str(fdac_bit) + ")", x_axis_title='mean ToT', filename=self.plots_filename, minimum=0, maximum=15)

            fdac_mask = self.register.get_pixel_register_value("FDAC")
            self.fdac_mask_best[select_better_pixel_mask] = fdac_mask[select_better_pixel_mask]
            if fdac_bit > 0:
                fdac_mask[pixel_with_too_small_mean_tot_mask] = fdac_mask[pixel_with_too_small_mean_tot_mask] & ~(1 << fdac_bit)
                self.register.set_pixel_register_value("FDAC", fdac_mask)

            if fdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    lastBitResult = tot_mean_array.copy()
                    self.fdac_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    fdac_mask[abs(tot_mean_array - self.target_tot) > abs(lastBitResult - self.target_tot)] = fdac_mask[abs(tot_mean_array - self.target_tot) > abs(lastBitResult - self.target_tot)] | (1 << fdac_bit)
                    tot_mean_array[abs(tot_mean_array - self.target_tot) > abs(lastBitResult - self.target_tot)] = lastBitResult[abs(tot_mean_array - self.target_tot) > abs(lastBitResult - self.target_tot)]
                    self.tot_mean_best[abs(tot_mean_array - self.target_tot) <= abs(self.tot_mean_best - self.n_injections_fdac / 2)] = tot_mean_array[abs(tot_mean_array - self.target_tot) <= abs(self.tot_mean_best - self.n_injections_fdac / 2)]
                    self.fdac_mask_best[abs(tot_mean_array - self.target_tot) <= abs(self.tot_mean_best - self.n_injections_fdac / 2)] = fdac_mask[abs(tot_mean_array - self.target_tot) <= abs(self.tot_mean_best - self.n_injections_fdac / 2)]

        self.register.set_pixel_register_value("FDAC", self.fdac_mask_best)  # set value for meta scan
        self.write_fdac_config()
Beispiel #16
0
    def scan(self):
        if self.trig_count == 0:
            self.consecutive_lvl1 = 2 ** self.register.global_registers['Trig_Count']['bitlength']
        else:
            self.consecutive_lvl1 = self.trig_count
        enabled_pixels = self.register.get_pixel_register_value('Enable').sum()
        preselected_pixels = invert_pixel_mask(self.register.get_pixel_register_value('Enable')).sum()
        disabled_pixels_limit_cnt = int(self.disabled_pixels_limit * self.register.get_pixel_register_value('Enable').sum())
        abs_occ_limit = stats.poisson.ppf(0.5, mu=self.occupancy_limit * self.n_triggers * self.consecutive_lvl1)
        logging.info('The pixel threshold will be increased when occpancy >%d' % abs_occ_limit)
        total_occ_limit = int(self.occupancy_limit * self.n_triggers * self.consecutive_lvl1 * enabled_pixels)
        # Sum of PMF of Poisson distribution (k>0)
        n_expected_pixel_hits = int((1.0 - stats.poisson.pmf(k=0, mu=self.occupancy_limit * self.n_triggers * self.consecutive_lvl1)) * enabled_pixels)
        logging.info('The global threshold will be decreased when total occupancy is <=%d and pixel with hits <=%d' % (total_occ_limit, n_expected_pixel_hits))
        max_tdac_steps = max(1, int(np.ceil((1 / self.occupancy_limit) / (self.n_triggers * self.consecutive_lvl1) * (1 / (1 - 0.5)))))
        tdac_center = 2 ** self.register.pixel_registers['TDAC']['bitlength'] / 2
        lvl1_command = self.register.get_commands("LV1")[0] + self.register.get_commands("zeros", length=self.trigger_rate_limit)[0]
        total_scan_time = int(lvl1_command.length() * 25 * (10 ** -9) * self.n_triggers)

        self.threshold = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.tdac_step = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.tdac = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.new_tdac = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.enable_mask = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.new_enable_mask = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.occupancy_hist = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)
        self.occupancy_mask = deque([None] * (self.plot_n_steps + 2), maxlen=self.plot_n_steps + 2)

#         interpreter = PyDataInterpreter()
#         histogram = PyDataHistograming()
#         interpreter.set_trig_count(self.trig_count)
#         interpreter.set_warning_output(False)
#         histogram.set_no_scan_parameter()
#         histogram.create_occupancy_hist(True)
        coarse_threshold = [self.gdac_range[0]]
        reached_pixels_limit_cnt = False
        reached_tdac_center = False
        reached_gdac_lower_limit = False
        do_refine_tuning = False
        for reg_val in coarse_threshold:  # outer loop, coarse tuning threshold
            if self.stop_run.is_set():
                break
            logging.info('Scanning Vthin_AltFine %d', reg_val)
            commands = []
            commands.extend(self.register.get_commands("ConfMode"))
            self.register.set_global_register_value("Vthin_AltFine", reg_val)
            commands.extend(self.register.get_commands("WrRegister", name=["Vthin_AltFine"]))
            # setting FE into RunMode
            commands.extend(self.register.get_commands("RunMode"))
            self.register_utils.send_commands(commands)
            tdac_step = 1
            while True:  # inner loop
                if self.stop_run.is_set():
                    break
#                 histogram.reset()

                logging.info('TDAC step %d at Vthin_AltFine %d', tdac_step, reg_val)
#                 logging.info('Estimated scan time: %ds', total_scan_time)

                with self.readout(Vthin_AltFine=reg_val, TDAC_step=tdac_step, fill_buffer=True):
                    got_data = False
                    start = time()
                    self.register_utils.send_command(lvl1_command, repeat=self.n_triggers, wait_for_finish=False, set_length=True, clear_memory=False)
                    while not self.stop_run.wait(0.1):
                        if self.register_utils.is_ready:
                            if got_data:
                                self.progressbar.finish()
                            logging.info('Finished sending %d triggers', self.n_triggers)
                            break
                        if not got_data:
                            if self.data_words_per_second() > 0:
                                got_data = True
                                logging.info('Taking data...')
                                self.progressbar = progressbar.ProgressBar(widgets=['', progressbar.Percentage(), ' ', progressbar.Bar(marker='*', left='|', right='|'), ' ', progressbar.Timer()], maxval=total_scan_time, poll=10, term_width=80).start()
                        else:
                            try:
                                self.progressbar.update(time() - start)
                            except ValueError:
                                pass
                # use Numpy for analysis and histogramming
                col_arr, row_arr = convert_data_array(array=self.read_data(), filter_func=is_data_record, converter_func=get_col_row_array_from_data_record_array)
                occ_hist, _, _ = np.histogram2d(col_arr, row_arr, bins=(80, 336), range=[[1, 80], [1, 336]])
                occ_mask = np.zeros(shape=occ_hist.shape, dtype=np.dtype('>u1'))

                # use FEI4 interpreter for analysis and histogramming
#                 from pybar.daq.readout_utils import data_array_from_data_iterable
#                 raw_data = np.ascontiguousarray(data_array_from_data_iterable(self.read_data()), dtype=np.uint32)
#                 interpreter.interpret_raw_data(raw_data)
#                 interpreter.store_event()  # force to create latest event
#                 histogram.add_hits(interpreter.get_hits())
#                 occ_hist = histogram.get_occupancy()[:, :, 0]
#                 # noisy pixels are set to 1
#                 occ_mask = np.zeros(shape=occ_hist.shape, dtype=np.dtype('>u1'))

                occ_mask[occ_hist > abs_occ_limit] = 1

                tdac_reg = self.register.get_pixel_register_value('TDAC')
                decrease_pixel_mask = np.logical_and(occ_mask > 0, tdac_reg > 0)
                disable_pixel_mask = np.logical_and(occ_mask > 0, tdac_reg == 0)
                enable_mask = self.register.get_pixel_register_value('Enable')
                new_enable_mask = np.logical_and(enable_mask, invert_pixel_mask(disable_pixel_mask))
                if np.logical_and(occ_mask > 0, enable_mask == 0).sum():
                    logging.warning('Received data from disabled pixels')
#                     disabled_pixels += disable_pixel_mask.sum()  # can lead to wrong values if the enable reg is corrupted
                disabled_pixels = invert_pixel_mask(new_enable_mask).sum() - preselected_pixels
                logging.info('Found %d noisy pixels', occ_mask.sum())
                logging.info('Increasing threshold of %d pixel(s)', decrease_pixel_mask.sum())
                logging.info('Disabling %d pixel(s), total number of disabled pixel(s): %d', disable_pixel_mask.sum(), disabled_pixels)

                # increasing threshold before writing TDACs to avoid FE becoming noisy
                self.register.set_global_register_value("Vthin_AltFine", self.gdac_range[0])
                commands = []
                commands.extend(self.register.get_commands("ConfMode"))
                commands.extend(self.register.get_commands("WrRegister", name=["Vthin_AltFine"]))
                self.register_utils.send_commands(commands)
                # writing TDAC
                new_tdac_reg = tdac_reg.copy()
                new_tdac_reg[decrease_pixel_mask] -= 1  # smaller TDAC translates to higher threshold
                self.register.set_pixel_register_value('TDAC', new_tdac_reg)
                self.register.set_pixel_register_value('Enable', new_enable_mask)
                commands = []
                commands.extend(self.register.get_commands("WrFrontEnd", same_mask_for_all_dc=False, name='TDAC'))
                commands.extend(self.register.get_commands("WrFrontEnd", same_mask_for_all_dc=False, name='Enable'))
                self.register_utils.send_commands(commands)
                # writing threshold value after writing TDACs
                self.register.set_global_register_value("Vthin_AltFine", reg_val)
                commands = []
                commands.extend(self.register.get_commands("WrRegister", name=["Vthin_AltFine"]))
                commands.extend(self.register.get_commands("RunMode"))
                self.register_utils.send_commands(commands)

                if (not do_refine_tuning and occ_hist.sum() <= total_occ_limit and occ_mask.sum() <= n_expected_pixel_hits) or (tdac_step >= max_tdac_steps):
                    logging.info('Stop tuning TDACs at Vthin_AltFine %d', reg_val)
                    self.threshold.appendleft(self.register.get_global_register_value("Vthin_AltFine"))
                    self.tdac_step.appendleft(tdac_step)
                    self.tdac.appendleft(tdac_reg)
                    self.new_tdac.appendleft(new_tdac_reg)
                    self.enable_mask.appendleft(enable_mask)
                    self.new_enable_mask.appendleft(new_enable_mask)
                    self.occupancy_hist.appendleft(occ_hist.copy())
                    self.occupancy_mask.appendleft(occ_mask.copy())
                    if not do_refine_tuning and np.mean(new_tdac_reg[new_enable_mask]) <= tdac_center + (1 if self.refine_tuning else 0):
                        reached_tdac_center = True
                    if not do_refine_tuning and disabled_pixels > disabled_pixels_limit_cnt:
                        reached_pixels_limit_cnt = True
                        logging.info('Limit of disabled pixels reached: %d (limit %d).' % (disabled_pixels, disabled_pixels_limit_cnt))
                    if not do_refine_tuning and reg_val <= self.gdac_range[1]:
                        reached_gdac_lower_limit = True
                    break
                else:
                    logging.info('Continue tuning TDACs at Vthin_AltFine %d', reg_val)
                # increase scan parameter counter
                tdac_step += 1

            if not self.refine_tuning and (reached_pixels_limit_cnt or reached_tdac_center or reached_gdac_lower_limit):
                pass  # will exit loop
            elif do_refine_tuning:
                logging.info("Finished TDAC refine tuning.")
            elif reached_pixels_limit_cnt or reached_tdac_center or reached_gdac_lower_limit:
                do_refine_tuning = True
                logging.info("Starting TDAC refine tuning...")
                coarse_threshold.append(reg_val - 1)
                abs_occ_limit = stats.poisson.ppf(0.99, mu=self.occupancy_limit * self.n_triggers * self.consecutive_lvl1)
                logging.info('The pixel threshold will be increased when occpancy >%d' % abs_occ_limit)
                max_tdac_steps = max(1, int(np.ceil((1 / self.occupancy_limit) / (self.n_triggers * self.consecutive_lvl1) * (1 / (1 - 0.99)))))
            else:
                coarse_threshold.append(reg_val - 1)
Beispiel #17
0
    def scan(self):
        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_threshold()

        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while (int_type):
                if (int_type & 1):
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        if not self.enable_mask_steps_gdac:
            self.enable_mask_steps_gdac = range(self.mask_steps)
        for mask_step in self.enable_mask_steps_gdac:
            select_mask_array += make_pixel_mask(steps=self.mask_steps,
                                                 shift=mask_step)
        for column in bits_set(
                self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info('Deselect double column %d' % column)
            select_mask_array[column, :] = 0

        gdacs_above_threshold = []
        additional_scan_ongoing = False
        last_good_gdac_bit = self.gdac_tune_bits[0]
        last_good_gdac_scan_step = 0
        gdac_tune_bits_permutation = 0
        gdac_values = []
        gdac_occupancies = []
        gdac_occ_array_sel_pixels = []
        gdac_occ_array_desel_pixels = []
        gdac_tune_bits = self.gdac_tune_bits[:]
        min_gdac_with_occupancy = None
        for gdac_scan_step, gdac_bit in enumerate(gdac_tune_bits):
            if self.stop_run.is_set():
                break
            # set all higher GDAC bits
            gdac_tune_bits_permutation_header = map(
                int,
                bin(2**last_good_gdac_scan_step - 1 -
                    gdac_tune_bits_permutation)[2:].zfill(
                        last_good_gdac_scan_step))[-last_good_gdac_scan_step:]
            for gdac_permutation_bit, gdac_permutation_bit_value in enumerate(
                    gdac_tune_bits_permutation_header):
                self.set_gdac_bit(self.gdac_tune_bits[gdac_permutation_bit],
                                  bit_value=gdac_permutation_bit_value,
                                  send_command=False)
            # clear all lower GDAC bits
            for clear_gdac_bit in self.gdac_tune_bits:
                if clear_gdac_bit < gdac_bit:
                    self.set_gdac_bit(clear_gdac_bit,
                                      bit_value=0,
                                      send_command=False)
            if additional_scan_ongoing:
                self.set_gdac_bit(gdac_bit, bit_value=0, send_command=True)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse")
                    << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info('GDAC setting: %d, set bit %d = 0',
                             scan_parameter_value, gdac_bit)
            else:  # default
                self.set_gdac_bit(gdac_bit, bit_value=1, send_command=False)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse")
                    << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info('GDAC setting: %d, set bit %d = 1',
                             scan_parameter_value, gdac_bit)
            # check if GDAC values are too low or were already scanned
            if not additional_scan_ongoing and (
                (self.register_utils.get_gdac() in gdac_values) or
                (self.gdac_lower_limit
                 and self.register_utils.get_gdac() < self.gdac_lower_limit) or
                (min_gdac_with_occupancy and
                 self.register_utils.get_gdac() <= min_gdac_with_occupancy)):
                if gdac_tune_bits_permutation + 1 == 2**last_good_gdac_scan_step:  # next permutation step
                    gdac_tune_bits_permutation = 0
                    last_good_gdac_scan_step += 1
                else:
                    gdac_tune_bits_permutation += 1
                for i in range(len(gdac_tune_bits) - (gdac_scan_step + 1)):
                    gdac_tune_bits.pop()
                gdac_tune_bits.extend(
                    self.gdac_tune_bits[last_good_gdac_scan_step:]
                )  # repeat all scan steps from last bit
                continue
            # write GDAC
            self.register_utils.set_gdac(self.register_utils.get_gdac(),
                                         send_command=True)
            # start scan loop
            with self.readout(GDAC=scan_parameter_value, fill_buffer=True):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_gdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=self.enable_mask_steps_gdac,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)
            # calculate arrays from data
            data = convert_data_array(
                array=self.read_data(),
                filter_func=is_data_record,
                converter_func=get_col_row_array_from_data_record_array)
            occupancy_array, _, _ = np.histogram2d(*data,
                                                   bins=(80, 336),
                                                   range=[[1, 80], [1, 336]])
            occ_array_sel_pixels = np.ma.array(
                occupancy_array,
                mask=np.logical_not(np.ma.make_mask(select_mask_array))
            )  # take only selected pixel into account by using the mask
            occ_array_desel_pixels = np.ma.array(
                occupancy_array, mask=np.ma.make_mask(select_mask_array)
            )  # take only de-selected pixel into account by using the inverted mask
            median_occupancy = np.ma.median(occ_array_sel_pixels)
            percentile_noise_occupancy = np.percentile(
                occ_array_desel_pixels.compressed(), 99.0)
            occupancy_almost_zero = np.allclose(median_occupancy, 0)
            no_noise = np.allclose(percentile_noise_occupancy, 0)
            gdac_values.append(self.register_utils.get_gdac())
            gdac_occupancies.append(median_occupancy)
            gdac_occ_array_sel_pixels.append(occ_array_sel_pixels.copy())
            gdac_occ_array_desel_pixels.append(occ_array_desel_pixels.copy())
            self.occ_array_sel_pixels_best = occ_array_sel_pixels.copy()
            self.occ_array_desel_pixels_best = occ_array_desel_pixels.copy()

            if len(gdac_values) >= 2:
                for index, scanned_gdac in enumerate(gdac_values[:-1]):
                    if (self.register_utils.get_gdac() < scanned_gdac
                            and median_occupancy <= gdac_occupancies[index]
                            and gdac_occupancies[index] != 0):
                        if min_gdac_with_occupancy is None:
                            min_gdac_with_occupancy = self.register_utils.get_gdac(
                            )
                        else:
                            min_gdac_with_occupancy = max(
                                min_gdac_with_occupancy,
                                self.register_utils.get_gdac())
                    if (scanned_gdac < self.register_utils.get_gdac()
                            and gdac_occupancies[index] <= median_occupancy
                            and median_occupancy != 0):
                        if min_gdac_with_occupancy is None:
                            min_gdac_with_occupancy = scanned_gdac
                        else:
                            min_gdac_with_occupancy = max(
                                min_gdac_with_occupancy, scanned_gdac)
                    for gdac_above_threshold in gdacs_above_threshold:
                        if gdac_above_threshold <= min_gdac_with_occupancy:  # check for valid values
                            gdacs_above_threshold.remove(gdac_above_threshold)

            if gdac_scan_step + 1 == len(
                    gdac_tune_bits):  # last GDAC scan step
                if not additional_scan_ongoing and (
                    (occupancy_almost_zero and no_noise)
                        or not gdacs_above_threshold or
                    (self.gdac_lower_limit and
                     self.register_utils.get_gdac() < self.gdac_lower_limit) or
                    (min_gdac_with_occupancy and
                     self.register_utils.get_gdac() <= min_gdac_with_occupancy)
                        or not no_noise
                ) and len(
                        self.gdac_tune_bits
                ) >= last_good_gdac_scan_step + 2:  # min. 2 bits for bin search
                    self.set_gdac_bit(
                        gdac_bit, bit_value=0,
                        send_command=False)  # clear current tuning bit
                    if gdac_tune_bits_permutation + 1 == 2**last_good_gdac_scan_step:  # next permutation step
                        gdac_tune_bits_permutation = 0
                        last_good_gdac_scan_step += 1
                    else:
                        gdac_tune_bits_permutation += 1
                    gdac_tune_bits.extend(
                        self.gdac_tune_bits[last_good_gdac_scan_step:]
                    )  # repeat all scan steps from last bit
                elif gdac_bit == 0 and not additional_scan_ongoing:  # scan bit 0 = 1
                    additional_scan_ongoing = True
                    last_occ_array_sel_pixels = occ_array_sel_pixels.copy()
                    last_occ_array_desel_pixels = occ_array_desel_pixels.copy()
                    last_median_occupancy = median_occupancy
                    gdac_tune_bits.append(
                        0)  # the last tune bit has to be scanned twice
                elif gdac_bit == 0 and additional_scan_ongoing:  # scan bit 0 = 0
                    additional_scan_ongoing = False
                    logging.info(
                        'Measured %.2f with bit 0 = 0 with and %.2f with bit 0 = 1',
                        median_occupancy, last_median_occupancy)
                    if (abs(median_occupancy - self.n_injections_gdac / 2.0) >=
                            abs(last_median_occupancy -
                                self.n_injections_gdac / 2.0)
                        ) or (
                            last_median_occupancy >=
                            self.n_injections_gdac / 2.0
                        ):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        logging.info('Set bit 0 = 1')
                        self.set_gdac_bit(
                            0, bit_value=1,
                            send_command=True)  # write GDAC value
                        occ_array_sel_pixels = last_occ_array_sel_pixels.copy()
                        occ_array_desel_pixels = last_occ_array_desel_pixels.copy(
                        )
                        median_occupancy = last_median_occupancy
                    else:
                        logging.info('Keep bit 0 = 0')
            else:  # regular GDAC scan step
                # GDAC too low, no hits
                if (self.gdac_lower_limit and
                        self.register_utils.get_gdac() < self.gdac_lower_limit
                    ) or (min_gdac_with_occupancy
                          and self.register_utils.get_gdac() <=
                          min_gdac_with_occupancy) or not no_noise:
                    logging.info(
                        'Median = %.2f > %.2f, GDAC possibly too low, keep bit %d = 1',
                        median_occupancy, self.n_injections_gdac / 2.0,
                        gdac_bit)
                # GDAC too high, less hits, decrease GDAC
                elif median_occupancy < self.n_injections_gdac / 2.0:  # set GDAC bit to 0 if the occupancy is too low, thus decrease threshold
                    logging.info('Median = %.2f < %.2f, set bit %d = 0',
                                 median_occupancy,
                                 self.n_injections_gdac / 2.0, gdac_bit)
                    self.set_gdac_bit(
                        gdac_bit, bit_value=0, send_command=False
                    )  # do not write, might be too low, do this in next iteration
                # GDAC too low, more hits, increase GDAC
                else:
                    gdacs_above_threshold.append(
                        self.register_utils.get_gdac())
                    logging.info('Median = %.2f > %.2f, keep bit %d = 1',
                                 median_occupancy,
                                 self.n_injections_gdac / 2.0, gdac_bit)

        if not self.stop_run.is_set():
            # select best GDAC value
            sorted_indices = np.argsort(np.array(gdac_values))
            occupancy_sorted = np.array(gdac_occupancies)[sorted_indices]
            gdac_sorted = np.sort(gdac_values)
            try:
                diff_occupancy = occupancy_sorted[1:] - occupancy_sorted[:-1]
                gdac_min_idx = np.where(diff_occupancy > 0)[0][-1] + 1
            except IndexError:
                gdac_min_idx = None
            occupancy_sorted_sel = occupancy_sorted[gdac_min_idx:]
            best_index_sel = np.abs(
                np.array(occupancy_sorted_sel[::-1]) -
                self.n_injections_gdac / 2.0).argmin()
            best_index = sorted_indices[gdac_min_idx:][::-1][best_index_sel]
            gdac_best = gdac_values[best_index]
            median_occupancy = gdac_occupancies[best_index]
            # for plotting
            self.occ_array_sel_pixels_best = gdac_occ_array_sel_pixels[
                best_index]
            self.occ_array_desel_pixels_best = gdac_occ_array_desel_pixels[
                best_index]
            if gdac_best != self.register_utils.get_gdac():
                logging.info(
                    "Binary search converged to non-optimal value, apply best GDAC value, change GDAC from %d to %d",
                    self.register_utils.get_gdac(), gdac_best)
                self.register_utils.set_gdac(gdac_best, send_command=False)
            self.gdac_best = self.register_utils.get_gdac()

            if abs(median_occupancy - self.n_injections_gdac / 2.0) > abs(
                    self.n_injections_gdac * 0.01 *
                    self.max_delta_threshold) and not self.stop_run.is_set():
                if np.all((((self.gdac_best & (1 << np.arange(
                        self.register.global_registers['Vthin_AltFine']
                    ['bitlength'] + self.register.
                        global_registers['Vthin_AltFine']['bitlength'])))) > 0
                           ).astype(int)[self.gdac_tune_bits] == 1):
                    if self.fail_on_warning:
                        raise RuntimeWarning(
                            'Selected GDAC bits reached maximum value')
                    else:
                        logging.warning(
                            'Selected GDAC bits reached maximum value')
                elif np.all((((self.gdac_best & (1 << np.arange(
                        self.register.global_registers['Vthin_AltFine']
                    ['bitlength'] + self.register.
                        global_registers['Vthin_AltFine']['bitlength'])))) > 0
                             ).astype(int)[self.gdac_tune_bits] == 0):
                    if self.fail_on_warning:
                        raise RuntimeWarning(
                            'Selected GDAC bits reached minimum value')
                    else:
                        logging.warning(
                            'Selected GDAC bits reached minimum value')
                else:
                    if self.fail_on_warning:
                        raise RuntimeWarning(
                            'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d'
                            % (abs(median_occupancy -
                                   self.n_injections_gdac / 2.0),
                               abs(self.n_injections_gdac * 0.01 *
                                   self.max_delta_threshold),
                               self.register.get_global_register_value(
                                   "Vthin_AltCoarse"),
                               self.register.get_global_register_value(
                                   "Vthin_AltFine")))
                    else:
                        logging.warning(
                            'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                            abs(median_occupancy -
                                self.n_injections_gdac / 2.0),
                            abs(self.n_injections_gdac * 0.01 *
                                self.max_delta_threshold),
                            self.register.get_global_register_value(
                                "Vthin_AltCoarse"),
                            self.register.get_global_register_value(
                                "Vthin_AltFine"))
            else:
                logging.info(
                    'Tuned GDAC to Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                    self.register.get_global_register_value("Vthin_AltCoarse"),
                    self.register.get_global_register_value("Vthin_AltFine"))
Beispiel #18
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False

        enable_mask_steps = [0]  # one mask step to increase speed, no effect on precision
        cal_lvl1_command = self.register.get_commands("CAL")[0] + self.register.get_commands("zeros", length=40)[0] + self.register.get_commands("LV1")[0] + self.register.get_commands("zeros", mask_steps=self.mask_steps)[0]

        self.write_target_charge()

        for feedback_bit in self.feedback_tune_bits:  # reset all GDAC bits
            self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)

        additional_scan = True
        last_bit_result = self.n_injections_feedback

        tot_mean_best = 0
        feedback_best = self.register.get_global_register_value("PrmpVbpf")
        for feedback_bit in self.feedback_tune_bits:
            if additional_scan:
                self.set_prmp_vbpf_bit(feedback_bit)
                logging.info('PrmpVbpf setting: %d, bit %d = 1', self.register.get_global_register_value("PrmpVbpf"), feedback_bit)
            else:
                self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)
                logging.info('PrmpVbpf setting: %d, bit %d = 0', self.register.get_global_register_value("PrmpVbpf"), feedback_bit)

            scan_parameter_value = self.register.get_global_register_value("PrmpVbpf")

            with self.readout(PrmpVbpf=scan_parameter_value, reset_sram_fifo=True, fill_buffer=True, clear_buffer=True, callback=self.handle_data):
                scan_loop(self, cal_lvl1_command, repeat_command=self.n_injections_feedback, mask_steps=self.mask_steps, enable_mask_steps=enable_mask_steps, enable_double_columns=None, same_mask_for_all_dc=True, eol_function=None, digital_injection=False, enable_shift_masks=self.enable_shift_masks, disable_shift_masks=self.disable_shift_masks, restore_shift_masks=True, mask=None, double_column_correction=self.pulser_dac_correction)

            tots = convert_data_array(data_array_from_data_iterable(self.fifo_readout.data), filter_func=is_data_record, converter_func=get_tot_array_from_data_record_array)
            mean_tot = np.mean(tots)
            if np.isnan(mean_tot):
                logging.error("No hits, ToT calculation not possible, tuning will fail")

            if abs(mean_tot - self.target_tot) < abs(tot_mean_best - self.target_tot):
                tot_mean_best = mean_tot
                feedback_best = self.register.get_global_register_value("PrmpVbpf")

            logging.info('Mean ToT = %f', mean_tot)
            self.tot_array, _ = np.histogram(a=tots, range=(0, 16), bins=16)
            if self.plot_intermediate_steps:
                plot_tot(hist=self.tot_array, title='ToT distribution (PrmpVbpf ' + str(scan_parameter_value) + ')', filename=self.plots_filename)

            if abs(mean_tot - self.target_tot) < self.max_delta_tot and feedback_bit > 0:  # abort if good value already found to save time
                logging.info('Good result already achieved, skipping missing bits')
                break

            if feedback_bit > 0 and mean_tot < self.target_tot:
                self.set_prmp_vbpf_bit(feedback_bit, bit_value=0)
                logging.info('Mean ToT = %f < %d ToT, set bit %d = 0', mean_tot, self.target_tot, feedback_bit)

            if feedback_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    last_bit_result = mean_tot
                    self.feedback_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    logging.info('Scanned bit 0 = 0 with %f instead of %f for scanned bit 0 = 1', mean_tot, last_bit_result)
                    if(abs(mean_tot - self.target_tot) > abs(last_bit_result - self.target_tot)):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        self.set_prmp_vbpf_bit(feedback_bit, bit_value=1)
                        mean_tot = last_bit_result
                        logging.info('Set bit 0 = 1')
                    else:
                        logging.info('Set bit 0 = 0')
                if abs(mean_tot - self.target_tot) > abs(tot_mean_best - self.target_tot):
                    logging.info("Binary search converged to non optimal value, take best measured value instead")
                    mean_tot = tot_mean_best
                    self.register.set_global_register_value("PrmpVbpf", feedback_best)

        if self.register.get_global_register_value("PrmpVbpf") == 0 or self.register.get_global_register_value("PrmpVbpf") == 254:
            logging.warning('PrmpVbpf reached minimum/maximum value')
            if self.fail_on_warning:
                raise RuntimeWarning('PrmpVbpf reached minimum/maximum value')
        if abs(mean_tot - self.target_tot) > 2 * self.max_delta_tot:
            logging.warning('Global feedback tuning failed. Delta ToT = %f > %f. PrmpVbpf = %d', abs(mean_tot - self.target_tot), self.max_delta_tot, self.register.get_global_register_value("PrmpVbpf"))
            if self.fail_on_warning:
                raise RuntimeWarning('Global feedback tuning failed.')
        else:
            logging.info('Tuned PrmpVbpf to %d', self.register.get_global_register_value("PrmpVbpf"))

        self.feedback_best = self.register.get_global_register_value("PrmpVbpf")
Beispiel #19
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False
        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_threshold()

        for gdac_bit in self.gdac_tune_bits:  # reset all GDAC bits
            self.set_gdac_bit(gdac_bit, bit_value=0, send_command=False)

        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while (int_type):
                if (int_type & 1):
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        self.occ_array_sel_pixels_best = select_mask_array.copy()
        self.occ_array_desel_pixels_best = select_mask_array.copy()
        if not self.enable_mask_steps_gdac:
            self.enable_mask_steps_gdac = range(self.mask_steps)
        for mask_step in self.enable_mask_steps_gdac:
            select_mask_array += make_pixel_mask(steps=self.mask_steps,
                                                 shift=mask_step)
        for column in bits_set(
                self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info('Deselect double column %d' % column)
            select_mask_array[column, :] = 0

        additional_scan = True
        additional_scan_ongoing = False
        occupancy_best = 0.0
        last_good_gdac_bit = self.gdac_tune_bits[0]
        last_good_gdac_scan_step = 0
        gdac_tune_bits_permutation = 0
        gdac_best = self.register_utils.get_gdac()
        gdac_tune_bits = self.gdac_tune_bits[:]
        min_gdac_with_occupancy = None
        for gdac_scan_step, gdac_bit in enumerate(gdac_tune_bits):
            if additional_scan:
                self.set_gdac_bit(gdac_bit, bit_value=1, send_command=True)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse")
                    << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info('GDAC setting: %d, set bit %d = 1',
                             scan_parameter_value, gdac_bit)
            else:
                self.set_gdac_bit(gdac_bit, bit_value=0, send_command=True)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse")
                    << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info('GDAC setting: %d, set bit %d = 0',
                             scan_parameter_value, gdac_bit)

            with self.readout(GDAC=scan_parameter_value,
                              reset_sram_fifo=True,
                              fill_buffer=True,
                              clear_buffer=True,
                              callback=self.handle_data):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_gdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=self.enable_mask_steps_gdac,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            occupancy_array, _, _ = np.histogram2d(*convert_data_array(
                data_array_from_data_iterable(self.fifo_readout.data),
                filter_func=logical_and(is_fe_word, is_data_record),
                converter_func=get_col_row_array_from_data_record_array),
                                                   bins=(80, 336),
                                                   range=[[1, 80], [1, 336]])
            occ_array_sel_pixels = np.ma.array(
                occupancy_array,
                mask=np.logical_not(np.ma.make_mask(select_mask_array))
            )  # take only selected pixel into account by using the mask
            occ_array_desel_pixels = np.ma.array(
                occupancy_array, mask=np.ma.make_mask(select_mask_array)
            )  # take only de-selected pixel into account by using the inverted mask
            median_occupancy = np.ma.median(occ_array_sel_pixels)
            noise_occupancy = np.ma.median(occ_array_desel_pixels)
            occupancy_almost_zero = np.allclose(median_occupancy, 0)
            no_noise = np.allclose(noise_occupancy, 0)
            if abs(median_occupancy - self.n_injections_gdac /
                   2) < abs(occupancy_best - self.n_injections_gdac / 2):
                occupancy_best = median_occupancy
                gdac_best = self.register_utils.get_gdac()
                self.occ_array_sel_pixels_best = occ_array_sel_pixels.copy()
                self.occ_array_desel_pixels_best = occ_array_desel_pixels.copy(
                )

            if self.plot_intermediate_steps:
                plot_three_way(self.occ_array_sel_pixel.transpose(),
                               title="Occupancy (GDAC " +
                               str(scan_parameter_value) +
                               " with tuning bit " + str(gdac_bit) + ")",
                               x_axis_title='Occupancy',
                               filename=self.plots_filename,
                               maximum=self.n_injections_gdac)

            if not occupancy_almost_zero and no_noise:
                if min_gdac_with_occupancy is None:
                    min_gdac_with_occupancy = self.register_utils.get_gdac()
                else:
                    min_gdac_with_occupancy = min(
                        min_gdac_with_occupancy,
                        self.register_utils.get_gdac())

            if gdac_bit > 0:
                # GDAC too low, no hits
                if occupancy_almost_zero and no_noise and self.register_utils.get_gdac(
                ) < min_gdac_with_occupancy:
                    logging.info(
                        'Median = %.2f > %.2f, GDAC possibly too low, keep bit %d = 1',
                        median_occupancy, self.n_injections_gdac / 2, gdac_bit)
                # GDAC too high, less hits, decrease GDAC
                elif no_noise and median_occupancy < (
                        self.n_injections_gdac / 2
                ):  # set GDAC bit to 0 if the occupancy is too low, thus decrease threshold
                    try:
                        next_gdac_bit = gdac_tune_bits[gdac_scan_step + 1]
                    except IndexError:
                        next_gdac_bit = None
                    # check if new value is below lower limit
                    if self.gdac_lower_limit and (
                            next_gdac_bit is not None
                            and self.register_utils.get_gdac() - 2**gdac_bit +
                            2**next_gdac_bit < self.gdac_lower_limit) or (
                                next_gdac_bit is None
                                and self.register_utils.get_gdac() -
                                2**gdac_bit < self.gdac_lower_limit):
                        logging.info(
                            'Median = %.2f < %.2f, reaching lower GDAC limit, keep bit %d = 1',
                            median_occupancy, self.n_injections_gdac / 2,
                            gdac_bit)
                    else:
                        logging.info('Median = %.2f < %.2f, set bit %d = 0',
                                     median_occupancy,
                                     self.n_injections_gdac / 2, gdac_bit)
                        self.set_gdac_bit(
                            gdac_bit, bit_value=0, send_command=False
                        )  # do not write, might be too low, do this in next iteration
                # GDAC too low, more hits
                else:
                    logging.info('Median = %.2f > %.2f, keep bit %d = 1',
                                 median_occupancy, self.n_injections_gdac / 2,
                                 gdac_bit)
            elif gdac_bit == 0:
                if not additional_scan_ongoing and (
                    (occupancy_almost_zero and no_noise) or not no_noise
                ) and len(self.gdac_tune_bits) > last_good_gdac_scan_step + 2:
                    self.set_gdac_bit(0, bit_value=0,
                                      send_command=False)  # turn off LSB
                    if len(
                            gdac_tune_bits
                    ) == gdac_scan_step + 1 and gdac_tune_bits_permutation == 0:  # min. 2 bits for bin search
                        self.set_gdac_bit(
                            last_good_gdac_bit,
                            bit_value=1,
                            send_command=False)  # always enable highest bit
                        gdac_tune_bits.extend(
                            self.gdac_tune_bits[last_good_gdac_scan_step + 1:]
                        )  # repeat all scan stept from last bit
                        for gdac_clear_bit in self.gdac_tune_bits[:
                                                                  last_good_gdac_scan_step]:
                            self.set_gdac_bit(gdac_clear_bit,
                                              bit_value=0,
                                              send_command=False)
                        if 2**last_good_gdac_scan_step == 1:  # last step, cleanup
                            last_good_gdac_bit = self.gdac_tune_bits[
                                last_good_gdac_scan_step + 1]
                            last_good_gdac_scan_step += 1
                        else:
                            gdac_tune_bits_permutation += 1
                    else:
                        gdac_tune_bits_permutation_header = map(
                            int,
                            bin(gdac_tune_bits_permutation)[2:].zfill(
                                last_good_gdac_scan_step))
                        for gdac_permutation_bit, gdac_permutation_bit_value in enumerate(
                                gdac_tune_bits_permutation_header):
                            self.set_gdac_bit(
                                self.gdac_tune_bits[gdac_permutation_bit],
                                bit_value=gdac_permutation_bit_value,
                                send_command=False)
                        gdac_tune_bits.extend(
                            self.gdac_tune_bits[last_good_gdac_scan_step + 1:])
                        if 2**last_good_gdac_scan_step > gdac_tune_bits_permutation + 1:
                            gdac_tune_bits_permutation += 1
                        else:  # last step, cleanup
                            gdac_tune_bits_permutation = 0
                            last_good_gdac_bit = self.gdac_tune_bits[
                                last_good_gdac_scan_step + 1]
                            last_good_gdac_scan_step += 1
                elif additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    additional_scan_ongoing = True
                    last_occ_array_sel_pixels = occ_array_sel_pixels.copy()
                    last_occ_array_desel_pixels = occ_array_desel_pixels.copy()
                    gdac_tune_bits.append(
                        0)  # the last tune bit has to be scanned twice
                else:
                    additional_scan_ongoing = False
                    last_median_occupancy = np.ma.median(
                        last_occ_array_sel_pixels)
                    logging.info(
                        'Measured %.2f with bit 0 = 0 with and %.2f with bit 0 = 1',
                        median_occupancy, last_median_occupancy)
                    if abs(median_occupancy - self.n_injections_gdac / 2) > abs(
                            last_median_occupancy - self.n_injections_gdac / 2
                    ):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        logging.info('Set bit 0 = 1')
                        self.set_gdac_bit(0, bit_value=1, send_command=True)
                        occ_array_sel_pixels = last_occ_array_sel_pixels.copy()
                        occ_array_desel_pixels = last_occ_array_desel_pixels.copy(
                        )
                        median_occupancy = last_median_occupancy
                    else:
                        logging.info('Keep bit 0 = 0')

        # select best GDAC value
        if abs(occupancy_best -
               self.n_injections_gdac / 2) < abs(median_occupancy -
                                                 self.n_injections_gdac / 2):
            logging.info(
                "Binary search converged to non-optimal value, apply best GDAC value, change GDAC from %d to %d",
                self.register_utils.get_gdac(), gdac_best)
            median_occupancy = occupancy_best
            self.register_utils.set_gdac(gdac_best, send_command=False)

        self.gdac_best = self.register_utils.get_gdac()

        if abs(median_occupancy -
               self.n_injections_gdac / 2) > self.max_delta_threshold:
            if np.all((((self.gdac_best & (1 << np.arange(
                    self.register.global_registers['Vthin_AltFine']
                ['bitlength'] + self.register.global_registers['Vthin_AltFine']
                ['bitlength'])))) > 0).astype(int)[self.gdac_tune_bits] == 1):
                if self.fail_on_warning:
                    raise RuntimeWarning(
                        'Selected GDAC bits reached maximum value')
                else:
                    logging.warning('Selected GDAC bits reached maximum value')
            elif np.all((((self.gdac_best & (1 << np.arange(
                    self.register.global_registers['Vthin_AltFine']
                ['bitlength'] + self.register.global_registers['Vthin_AltFine']
                ['bitlength'])))) > 0).astype(int)[self.gdac_tune_bits] == 0):
                if self.fail_on_warning:
                    raise RuntimeWarning(
                        'Selected GDAC bits reached minimum value')
                else:
                    logging.warning('Selected GDAC bits reached minimum value')
            else:
                if self.fail_on_warning:
                    raise RuntimeWarning(
                        'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d'
                        % (abs(median_occupancy - self.n_injections_gdac / 2),
                           self.max_delta_threshold,
                           self.register.get_global_register_value(
                               "Vthin_AltCoarse"),
                           self.register.get_global_register_value(
                               "Vthin_AltFine")))
                else:
                    logging.warning(
                        'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                        abs(median_occupancy - self.n_injections_gdac / 2),
                        self.max_delta_threshold,
                        self.register.get_global_register_value(
                            "Vthin_AltCoarse"),
                        self.register.get_global_register_value(
                            "Vthin_AltFine"))
        else:
            logging.info(
                'Tuned GDAC to Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                self.register.get_global_register_value("Vthin_AltCoarse"),
                self.register.get_global_register_value("Vthin_AltFine"))
Beispiel #20
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + ".pdf")
            self.close_plots = True
        else:
            self.close_plots = False
        cal_lvl1_command = (
            self.register.get_commands("CAL")[0]
            + self.register.get_commands("zeros", length=40)[0]
            + self.register.get_commands("LV1")[0]
            + self.register.get_commands("zeros", mask_steps=self.mask_steps_gdac)[0]
        )

        self.write_target_threshold()
        for gdac_bit in self.gdac_tune_bits:  # reset all GDAC bits
            self.set_gdac_bit(gdac_bit, bit_value=0, send_command=False)

        last_bit_result = self.n_injections_gdac
        decreased_threshold = False  # needed to determine if the FE is noisy
        all_bits_zero = True

        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while int_type:
                if int_type & 1:
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        if not self.enable_mask_steps_gdac:
            self.enable_mask_steps_gdac = range(self.mask_steps_gdac)
        for mask_step in self.enable_mask_steps_gdac:
            select_mask_array += make_pixel_mask(steps=self.mask_steps_gdac, shift=mask_step)
        for column in bits_set(self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info("Deselect double column %d" % column)
            select_mask_array[column, :] = 0

        additional_scan = True
        occupancy_best = 0
        gdac_best = self.register_utils.get_gdac()
        for gdac_bit in self.gdac_tune_bits:
            if additional_scan:
                self.set_gdac_bit(gdac_bit)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse") << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info("GDAC setting: %d, bit %d = 1", scan_parameter_value, gdac_bit)
            else:
                self.set_gdac_bit(gdac_bit, bit_value=0)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse") << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info("GDAC setting: %d, bit %d = 0", scan_parameter_value, gdac_bit)

            with self.readout(
                GDAC=scan_parameter_value,
                reset_sram_fifo=True,
                fill_buffer=True,
                clear_buffer=True,
                callback=self.handle_data,
            ):
                scan_loop(
                    self,
                    cal_lvl1_command,
                    repeat_command=self.n_injections_gdac,
                    mask_steps=self.mask_steps_gdac,
                    enable_mask_steps=self.enable_mask_steps_gdac,
                    enable_double_columns=None,
                    same_mask_for_all_dc=True,
                    eol_function=None,
                    digital_injection=False,
                    enable_shift_masks=self.enable_shift_masks,
                    disable_shift_masks=self.disable_shift_masks,
                    restore_shift_masks=True,
                    mask=None,
                    double_column_correction=self.pulser_dac_correction,
                )

            occupancy_array, _, _ = np.histogram2d(
                *convert_data_array(
                    data_array_from_data_iterable(self.fifo_readout.data),
                    filter_func=is_data_record,
                    converter_func=get_col_row_array_from_data_record_array,
                ),
                bins=(80, 336),
                range=[[1, 80], [1, 336]]
            )
            self.occ_array_sel_pixel = np.ma.array(
                occupancy_array, mask=np.logical_not(np.ma.make_mask(select_mask_array))
            )  # take only selected pixel into account by creating a mask
            median_occupancy = np.ma.median(self.occ_array_sel_pixel)
            if abs(median_occupancy - self.n_injections_gdac / 2) < abs(occupancy_best - self.n_injections_gdac / 2):
                occupancy_best = median_occupancy
                gdac_best = self.register_utils.get_gdac()

            if self.plot_intermediate_steps:
                plot_three_way(
                    self.occ_array_sel_pixel.transpose(),
                    title="Occupancy (GDAC " + str(scan_parameter_value) + " with tuning bit " + str(gdac_bit) + ")",
                    x_axis_title="Occupancy",
                    filename=self.plots_filename,
                    maximum=self.n_injections_gdac,
                )

            if (
                abs(median_occupancy - self.n_injections_gdac / 2) < self.max_delta_threshold and gdac_bit > 0
            ):  # abort if good value already found to save time
                logging.info(
                    "Median = %f, good result already achieved (median - Ninj/2 < %f), skipping not varied bits",
                    median_occupancy,
                    self.max_delta_threshold,
                )
                break

            if median_occupancy == 0 and decreased_threshold and all_bits_zero:
                logging.info("Chip may be noisy")

            if gdac_bit > 0:
                if (
                    median_occupancy < self.n_injections_gdac / 2
                ):  # set GDAC bit to 0 if the occupancy is too lowm, thus decrease threshold
                    logging.info(
                        "Median = %f < %f, set bit %d = 0", median_occupancy, self.n_injections_gdac / 2, gdac_bit
                    )
                    self.set_gdac_bit(gdac_bit, bit_value=0)
                    decreased_threshold = True
                else:  # set GDAC bit to 1 if the occupancy is too high, thus increase threshold
                    logging.info(
                        "Median = %f > %f, leave bit %d = 1", median_occupancy, self.n_injections_gdac / 2, gdac_bit
                    )
                    decreased_threshold = False
                    all_bits_zero = False
            elif gdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    last_bit_result = self.occ_array_sel_pixel.copy()
                    self.gdac_tune_bits.append(self.gdac_tune_bits[-1])  # the last tune bit has to be scanned twice
                else:
                    last_bit_result_median = np.median(last_bit_result[select_mask_array > 0])
                    logging.info("Scanned bit 0 = 0 with %f instead of %f", median_occupancy, last_bit_result_median)
                    if abs(median_occupancy - self.n_injections_gdac / 2) > abs(
                        last_bit_result_median - self.n_injections_gdac / 2
                    ):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        self.set_gdac_bit(gdac_bit, bit_value=1)
                        logging.info("Set bit 0 = 1")
                        self.occ_array_sel_pixel = last_bit_result
                        median_occupancy = np.ma.median(self.occ_array_sel_pixel)
                    else:
                        logging.info("Set bit 0 = 0")
                    if abs(occupancy_best - self.n_injections_gdac / 2) < abs(
                        median_occupancy - self.n_injections_gdac / 2
                    ):
                        logging.info("Binary search converged to non optimal value, take best measured value instead")
                        median_occupancy = occupancy_best
                        self.register_utils.set_gdac(gdac_best, send_command=False)

        self.gdac_best = self.register_utils.get_gdac()

        if np.all((((self.gdac_best & (1 << np.arange(16)))) > 0).astype(int)[self.gdac_tune_bits[:-2]] == 1):
            logging.warning("Selected GDAC bits reached maximum value")
        elif np.all((((self.gdac_best & (1 << np.arange(16)))) > 0).astype(int)[self.gdac_tune_bits] == 0):
            logging.warning("Selected GDAC bits reached minimum value")

        if abs(median_occupancy - self.n_injections_gdac / 2) > 2 * self.max_delta_threshold:
            logging.warning(
                "Global threshold tuning failed. Delta threshold = %f > %f. Vthin_AltCoarse / Vthin_AltFine = %d / %d",
                abs(median_occupancy - self.n_injections_gdac / 2),
                self.max_delta_threshold,
                self.register.get_global_register_value("Vthin_AltCoarse"),
                self.register.get_global_register_value("Vthin_AltFine"),
            )
        else:
            logging.info(
                "Tuned GDAC to Vthin_AltCoarse / Vthin_AltFine = %d / %d",
                self.register.get_global_register_value("Vthin_AltCoarse"),
                self.register.get_global_register_value("Vthin_AltFine"),
            )

        self.gdac_best = self.register_utils.get_gdac()
Beispiel #21
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False
        mask_steps = 3
        enable_mask_steps = []
        cal_lvl1_command = self.register.get_commands("CAL")[0] + self.register.get_commands("zeros", length=40)[0] + self.register.get_commands("LV1")[0] + self.register.get_commands("zeros", mask_steps=mask_steps)[0]

        self.write_target_threshold()
        additional_scan = True
        lastBitResult = np.zeros(shape=self.register.get_pixel_register_value("TDAC").shape, dtype=self.register.get_pixel_register_value("TDAC").dtype)

        self.set_start_tdac()

        self.occupancy_best = np.empty(shape=(80, 336))  # array to store the best occupancy (closest to Ninjections/2) of the pixel
        self.occupancy_best.fill(self.n_injections_tdac)
        self.tdac_mask_best = self.register.get_pixel_register_value("TDAC")

        for scan_parameter_value, tdac_bit in enumerate(self.tdac_tune_bits):
            if additional_scan:
                self.set_tdac_bit(tdac_bit)
                logging.info('TDAC setting: bit %d = 1', tdac_bit)
            else:
                self.set_tdac_bit(tdac_bit, bit_value=0)
                logging.info('TDAC setting: bit %d = 0', tdac_bit)

            self.write_tdac_config()

            with self.readout(TDAC=scan_parameter_value, reset_sram_fifo=True, fill_buffer=True, clear_buffer=True, callback=self.handle_data):
                scan_loop(self, cal_lvl1_command, repeat_command=self.n_injections_tdac, mask_steps=mask_steps, enable_mask_steps=enable_mask_steps, enable_double_columns=None, same_mask_for_all_dc=True, eol_function=None, digital_injection=False, enable_shift_masks=self.enable_shift_masks, disable_shift_masks=self.disable_shift_masks, restore_shift_masks=True, mask=None, double_column_correction=self.pulser_dac_correction)

            occupancy_array, _, _ = np.histogram2d(*convert_data_array(data_array_from_data_iterable(self.fifo_readout.data), filter_func=is_data_record, converter_func=get_col_row_array_from_data_record_array), bins=(80, 336), range=[[1, 80], [1, 336]])
            select_better_pixel_mask = abs(occupancy_array - self.n_injections_tdac / 2) <= abs(self.occupancy_best - self.n_injections_tdac / 2)
            pixel_with_too_high_occupancy_mask = occupancy_array > self.n_injections_tdac / 2
            self.occupancy_best[select_better_pixel_mask] = occupancy_array[select_better_pixel_mask]

            if self.plot_intermediate_steps:
                plotThreeWay(occupancy_array.transpose(), title="Occupancy (TDAC tuning bit " + str(tdac_bit) + ")", x_axis_title='Occupancy', filename=self.plots_filename, maximum=self.n_injections_tdac)

            tdac_mask = self.register.get_pixel_register_value("TDAC")
            self.tdac_mask_best[select_better_pixel_mask] = tdac_mask[select_better_pixel_mask]

            if tdac_bit > 0:
                tdac_mask[pixel_with_too_high_occupancy_mask] = tdac_mask[pixel_with_too_high_occupancy_mask] & ~(1 << tdac_bit)
                self.register.set_pixel_register_value("TDAC", tdac_mask)

            if tdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    lastBitResult = occupancy_array.copy()
                    self.tdac_tune_bits.append(0)  # bit 0 has to be scanned twice
                else:
                    tdac_mask[abs(occupancy_array - self.n_injections_tdac / 2) > abs(lastBitResult - self.n_injections_tdac / 2)] = tdac_mask[abs(occupancy_array - self.n_injections_tdac / 2) > abs(lastBitResult - self.n_injections_tdac / 2)] | (1 << tdac_bit)
                    occupancy_array[abs(occupancy_array - self.n_injections_tdac / 2) > abs(lastBitResult - self.n_injections_tdac / 2)] = lastBitResult[abs(occupancy_array - self.n_injections_tdac / 2) > abs(lastBitResult - self.n_injections_tdac / 2)]
                    self.occupancy_best[abs(occupancy_array - self.n_injections_tdac / 2) <= abs(self.occupancy_best - self.n_injections_tdac / 2)] = occupancy_array[abs(occupancy_array - self.n_injections_tdac / 2) <= abs(self.occupancy_best - self.n_injections_tdac / 2)]
                    self.tdac_mask_best[abs(occupancy_array - self.n_injections_tdac / 2) <= abs(self.occupancy_best - self.n_injections_tdac / 2)] = tdac_mask[abs(occupancy_array - self.n_injections_tdac / 2) <= abs(self.occupancy_best - self.n_injections_tdac / 2)]

        self.register.set_pixel_register_value("TDAC", self.tdac_mask_best)  # set value for meta scan
        self.write_tdac_config()
Beispiel #22
0
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False
        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands(
                    "LV1")[0] + self.register.get_commands(
                        "zeros", mask_steps=self.mask_steps_gdac)[0]

        self.write_target_threshold()
        for gdac_bit in self.gdac_tune_bits:  # reset all GDAC bits
            self.set_gdac_bit(gdac_bit, bit_value=0, send_command=False)

        last_bit_result = self.n_injections_gdac
        decreased_threshold = False  # needed to determine if the FE is noisy
        all_bits_zero = True

        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while (int_type):
                if (int_type & 1):
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        if not self.enable_mask_steps_gdac:
            self.enable_mask_steps_gdac = range(self.mask_steps_gdac)
        for mask_step in self.enable_mask_steps_gdac:
            select_mask_array += make_pixel_mask(steps=self.mask_steps_gdac,
                                                 shift=mask_step)
        for column in bits_set(
                self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info('Deselect double column %d' % column)
            select_mask_array[column, :] = 0

        additional_scan = True
        occupancy_best = 0
        gdac_best = self.register_utils.get_gdac()
        for gdac_bit in self.gdac_tune_bits:
            if additional_scan:
                self.set_gdac_bit(gdac_bit)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse")
                    << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info('GDAC setting: %d, bit %d = 1',
                             scan_parameter_value, gdac_bit)
            else:
                self.set_gdac_bit(gdac_bit, bit_value=0)
                scan_parameter_value = (
                    self.register.get_global_register_value("Vthin_AltCoarse")
                    << 8
                ) + self.register.get_global_register_value("Vthin_AltFine")
                logging.info('GDAC setting: %d, bit %d = 0',
                             scan_parameter_value, gdac_bit)

            with self.readout(GDAC=scan_parameter_value,
                              reset_sram_fifo=True,
                              fill_buffer=True,
                              clear_buffer=True,
                              callback=self.handle_data):
                scan_loop(self,
                          cal_lvl1_command,
                          repeat_command=self.n_injections_gdac,
                          mask_steps=self.mask_steps_gdac,
                          enable_mask_steps=self.enable_mask_steps_gdac,
                          enable_double_columns=None,
                          same_mask_for_all_dc=True,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            occupancy_array, _, _ = np.histogram2d(*convert_data_array(
                data_array_from_data_iterable(self.fifo_readout.data),
                filter_func=is_data_record,
                converter_func=get_col_row_array_from_data_record_array),
                                                   bins=(80, 336),
                                                   range=[[1, 80], [1, 336]])
            self.occ_array_sel_pixel = np.ma.array(
                occupancy_array,
                mask=np.logical_not(np.ma.make_mask(select_mask_array))
            )  # take only selected pixel into account by creating a mask
            median_occupancy = np.ma.median(self.occ_array_sel_pixel)
            if abs(median_occupancy - self.n_injections_gdac /
                   2) < abs(occupancy_best - self.n_injections_gdac / 2):
                occupancy_best = median_occupancy
                gdac_best = self.register_utils.get_gdac()

            if self.plot_intermediate_steps:
                plot_three_way(self.occ_array_sel_pixel.transpose(),
                               title="Occupancy (GDAC " +
                               str(scan_parameter_value) +
                               " with tuning bit " + str(gdac_bit) + ")",
                               x_axis_title='Occupancy',
                               filename=self.plots_filename,
                               maximum=self.n_injections_gdac)

            if abs(
                    median_occupancy - self.n_injections_gdac / 2
            ) < self.max_delta_threshold and gdac_bit > 0:  # abort if good value already found to save time
                logging.info(
                    'Median = %f, good result already achieved (median - Ninj/2 < %f), skipping not varied bits',
                    median_occupancy, self.max_delta_threshold)
                break

            if median_occupancy == 0 and decreased_threshold and all_bits_zero:
                logging.info('Chip may be noisy')

            if gdac_bit > 0:
                if (
                        median_occupancy < self.n_injections_gdac / 2
                ):  # set GDAC bit to 0 if the occupancy is too lowm, thus decrease threshold
                    logging.info('Median = %f < %f, set bit %d = 0',
                                 median_occupancy, self.n_injections_gdac / 2,
                                 gdac_bit)
                    self.set_gdac_bit(gdac_bit, bit_value=0)
                    decreased_threshold = True
                else:  # set GDAC bit to 1 if the occupancy is too high, thus increase threshold
                    logging.info('Median = %f > %f, leave bit %d = 1',
                                 median_occupancy, self.n_injections_gdac / 2,
                                 gdac_bit)
                    decreased_threshold = False
                    all_bits_zero = False
            elif gdac_bit == 0:
                if additional_scan:  # scan bit = 0 with the correct value again
                    additional_scan = False
                    last_bit_result = self.occ_array_sel_pixel.copy()
                    self.gdac_tune_bits.append(
                        self.gdac_tune_bits[-1]
                    )  # the last tune bit has to be scanned twice
                else:
                    last_bit_result_median = np.median(
                        last_bit_result[select_mask_array > 0])
                    logging.info('Scanned bit 0 = 0 with %f instead of %f',
                                 median_occupancy, last_bit_result_median)
                    if abs(median_occupancy - self.n_injections_gdac / 2) > abs(
                            last_bit_result_median - self.n_injections_gdac / 2
                    ):  # if bit 0 = 0 is worse than bit 0 = 1, so go back
                        self.set_gdac_bit(gdac_bit, bit_value=1)
                        logging.info('Set bit 0 = 1')
                        self.occ_array_sel_pixel = last_bit_result
                        median_occupancy = np.ma.median(
                            self.occ_array_sel_pixel)
                    else:
                        logging.info('Set bit 0 = 0')
                    if abs(occupancy_best - self.n_injections_gdac / 2) < abs(
                            median_occupancy - self.n_injections_gdac / 2):
                        logging.info(
                            "Binary search converged to non optimal value, take best measured value instead"
                        )
                        median_occupancy = occupancy_best
                        self.register_utils.set_gdac(gdac_best,
                                                     send_command=False)

        self.gdac_best = self.register_utils.get_gdac()

        if np.all((((self.gdac_best & (1 << np.arange(16)))) > 0
                   ).astype(int)[self.gdac_tune_bits[:-2]] == 1):
            logging.warning('Selected GDAC bits reached maximum value')
        elif np.all((((self.gdac_best & (1 << np.arange(16)))) > 0
                     ).astype(int)[self.gdac_tune_bits] == 0):
            logging.warning('Selected GDAC bits reached minimum value')

        if abs(median_occupancy -
               self.n_injections_gdac / 2) > 2 * self.max_delta_threshold:
            logging.warning(
                'Global threshold tuning failed. Delta threshold = %f > %f. Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                abs(median_occupancy - self.n_injections_gdac / 2),
                self.max_delta_threshold,
                self.register.get_global_register_value("Vthin_AltCoarse"),
                self.register.get_global_register_value("Vthin_AltFine"))
        else:
            logging.info(
                'Tuned GDAC to Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                self.register.get_global_register_value("Vthin_AltCoarse"),
                self.register.get_global_register_value("Vthin_AltFine"))

        self.gdac_best = self.register_utils.get_gdac()
Beispiel #23
0
    def scan(self):
        self.start_condition_triggered = False  # set to true if the start condition is true once
        self.stop_condition_triggered = False  # set to true if the stop condition is true once

        self.start_at = 0.01  # if more than start_at*activated_pixel see at least one hit the precise scanning is started
        self.stop_at = 0.95  # if more than stop_at*activated_pixel see the maximum numbers of injection, the scan is stopped

        self.record_data = False  # set to true to activate data storage, so far not everything is recorded to ease data analysis

        scan_parameter_range = [0, (2 ** self.register.global_registers['PlsrDAC']['bitlength'] - 1)]
        if self.scan_parameters.PlsrDAC[0]:
            scan_parameter_range[0] = self.scan_parameters.PlsrDAC[0]
        if self.scan_parameters.PlsrDAC[1]:
            scan_parameter_range[1] = self.scan_parameters.PlsrDAC[1]
        logging.info("Scanning %s from %d to %d", 'PlsrDAC', scan_parameter_range[0], scan_parameter_range[1])
        self.scan_parameter_value = scan_parameter_range[0]  # set to start value
        self.search_distance = self.search_distance
        self.data_points = 0  # counter variable to count the data points already recorded, have to be at least minimum_data_ponts

        # calculate DCs to scan from the columns to ignore
        enable_double_columns = range(0, 40)
        if 1 in self.ignore_columns:
            enable_double_columns.remove(0)
        if set((78, 79, 80)).issubset(self.ignore_columns):
            enable_double_columns.remove(39)
        for double_column in range(1, 39):
            if set((double_column * 2, (double_column * 2) + 1)).issubset(self.ignore_columns):
                enable_double_columns.remove(double_column)
        logging.info("Use DCs: %s", str(enable_double_columns))

        self.select_arr_columns = range(0, 80)
        for column in self.ignore_columns:
            self.select_arr_columns.remove(column - 1)

        while self.scan_parameter_value <= scan_parameter_range[1]:  # scan as long as scan parameter is smaller than defined maximum
            if self.stop_run.is_set():
                break

            commands = []
            commands.extend(self.register.get_commands("ConfMode"))
            self.register.set_global_register_value('PlsrDAC', self.scan_parameter_value)
            commands.extend(self.register.get_commands("WrRegister", name=['PlsrDAC']))
            self.register_utils.send_commands(commands)

            with self.readout(PlsrDAC=self.scan_parameter_value, reset_sram_fifo=True, fill_buffer=True, clear_buffer=True, callback=self.handle_data if self.record_data else None):
                cal_lvl1_command = self.register.get_commands("CAL")[0] + self.register.get_commands("zeros", length=40)[0] + self.register.get_commands("LV1")[0]
                scan_loop(self, cal_lvl1_command, repeat_command=self.n_injections, use_delay=True, mask_steps=self.mask_steps, enable_mask_steps=self.enable_mask_steps, enable_double_columns=enable_double_columns, same_mask_for_all_dc=True, eol_function=None, digital_injection=False, enable_shift_masks=self.enable_shift_masks, disable_shift_masks=self.disable_shift_masks, restore_shift_masks=False, mask=invert_pixel_mask(self.register.get_pixel_register_value('Enable')) if self.use_enable_mask else None, double_column_correction=self.pulser_dac_correction)

            if not self.start_condition_triggered or self.data_points > self.minimum_data_points:  # speed up, only create histograms when needed. Python is much too slow here.
                if not self.start_condition_triggered and not self.record_data:
                    logging.info('Testing for start condition: %s %d', 'PlsrDAC', self.scan_parameter_value)
                if not self.stop_condition_triggered and self.record_data:
                    logging.info('Testing for stop condition: %s %d', 'PlsrDAC', self.scan_parameter_value)

                col, row = convert_data_array(data_array_from_data_iterable(self.fifo_readout.data), filter_func=is_data_record, converter_func=get_col_row_array_from_data_record_array)
                if np.any(np.logical_and(col < 1, col > 80)) or np.any(np.logical_and(row < 1, row > 336)):  # filter bad data records that can happen 
                    logging.warning('There are undefined %d data records (e.g. random data)', np.count_nonzero(np.logical_and(col < 1, col > 80)) + np.count_nonzero(np.logical_and(row < 1, row > 336)))
                    col, row = col[np.logical_and(col > 0, col <= 80)], row[np.logical_and(row > 0, row < 336)]
                occupancy_array = hist_2d_index(col - 1, row - 1, shape=(80, 336))
                self.scan_condition(occupancy_array)

            # start condition is met for the first time
            if self.start_condition_triggered and not self.record_data:
                self.scan_parameter_value = self.scan_parameter_value - self.search_distance + self.step_size
                if self.scan_parameter_value < 0:
                    self.scan_parameter_value = 0
                logging.info('Starting threshold scan at %s %d', 'PlsrDAC', self.scan_parameter_value)
                self.scan_parameter_start = self.scan_parameter_value
                self.record_data = True
                continue

            # saving data
            if self.record_data:
                self.data_points = self.data_points + 1

            # stop condition is met for the first time
            if self.stop_condition_triggered and self.record_data:
                logging.info('Stopping threshold scan at %s %d', 'PlsrDAC', self.scan_parameter_value)
                break

            # increase scan parameter value
            if not self.start_condition_triggered:
                self.scan_parameter_value = self.scan_parameter_value + self.search_distance
            else:
                self.scan_parameter_value = self.scan_parameter_value + self.step_size

        if self.scan_parameter_value >= scan_parameter_range[1]:
            logging.warning("Reached maximum of PlsrDAC range... stopping scan")
Beispiel #24
0
    def scan(self):
        self.start_condition_triggered = False  # set to true if the start condition is true once
        self.stop_condition_triggered = False  # set to true if the stop condition is true once

        self.start_at = 0.01  # if more than start_at*activated_pixel see at least one hit the precise scanning is started
        self.stop_at = 0.95  # if more than stop_at*activated_pixel see the maximum numbers of injection, the scan is stopped

        self.record_data = False  # set to true to activate data storage, so far not everything is recorded to ease data analysis

        scan_parameter_range = [
            0, (2**self.register.global_registers['PlsrDAC']['bitlength'])
        ]
        if self.scan_parameters.PlsrDAC[0]:
            scan_parameter_range[0] = self.scan_parameters.PlsrDAC[0]
        if self.scan_parameters.PlsrDAC[1]:
            scan_parameter_range[1] = self.scan_parameters.PlsrDAC[1]
        logging.info(
            "Scanning %s from %d to %d" %
            ('PlsrDAC', scan_parameter_range[0], scan_parameter_range[1]))
        self.scan_parameter_value = scan_parameter_range[
            0]  # set to start value
        self.search_distance = self.search_distance
        self.data_points = 0  # counter variable to count the data points already recorded, have to be at least minimum_data_ponts

        # calculate DCs to scan from the columns to ignore
        enable_double_columns = range(0, 40)
        if 1 in self.ignore_columns:
            enable_double_columns.remove(0)
        if set((78, 79, 80)).issubset(self.ignore_columns):
            enable_double_columns.remove(39)
        for double_column in range(1, 39):
            if set((double_column * 2,
                    (double_column * 2) + 1)).issubset(self.ignore_columns):
                enable_double_columns.remove(double_column)
        logging.info("Use DCs: %s" % str(enable_double_columns))

        self.select_arr_columns = range(0, 80)
        for column in self.ignore_columns:
            self.select_arr_columns.remove(column - 1)

        while self.scan_parameter_value <= scan_parameter_range[
                1]:  # scan as long as scan parameter is smaller than defined maximum
            if self.stop_run.is_set():
                break
            if self.record_data:
                logging.info(
                    "Scan step %d (%s %d)" %
                    (self.data_points, 'PlsrDAC', self.scan_parameter_value))

            commands = []
            commands.extend(self.register.get_commands("ConfMode"))
            self.register.set_global_register_value('PlsrDAC',
                                                    self.scan_parameter_value)
            commands.extend(
                self.register.get_commands("WrRegister", name=['PlsrDAC']))
            self.register_utils.send_commands(commands)

            with self.readout(PlsrDAC=self.scan_parameter_value):
                cal_lvl1_command = self.register.get_commands(
                    "CAL")[0] + self.register.get_commands(
                        "zeros",
                        length=40)[0] + self.register.get_commands("LV1")[0]
                scan_loop(self,
                          cal_lvl1_command,
                          repeat_command=self.n_injections,
                          use_delay=True,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=self.enable_mask_steps,
                          enable_double_columns=enable_double_columns,
                          same_mask_for_all_dc=True,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=False,
                          mask=invert_pixel_mask(
                              self.register.get_pixel_register_value('Enable'))
                          if self.use_enable_mask else None,
                          double_column_correction=self.pulser_dac_correction)

            if not self.start_condition_triggered or self.data_points > self.minimum_data_points:  # speed up, only create histograms when needed. Python is much too slow here.
                if not self.start_condition_triggered and not self.record_data:
                    logging.info('Testing for start condition: %s %d' %
                                 ('PlsrDAC', self.scan_parameter_value))
                if not self.stop_condition_triggered and self.record_data:
                    logging.info('Testing for stop condition: %s %d' %
                                 ('PlsrDAC', self.scan_parameter_value))

                col, row = convert_data_array(
                    data_array_from_data_iterable(self.fifo_readout.data),
                    filter_func=is_data_record,
                    converter_func=get_col_row_array_from_data_record_array)
                # using self written histogrammer in C++
                occupancy_array = hist_2d_index(col - 1,
                                                row - 1,
                                                shape=(80, 336))
                # using numpy
                #                 occupancy_array = np.histogram2d(col, row, bins=(80, 336), range=[[1, 80], [1, 336]])[0]

                self.scan_condition(occupancy_array)

            # start condition is met for the first time
            if self.start_condition_triggered and not self.record_data:
                self.scan_parameter_value = self.scan_parameter_value - self.search_distance + self.step_size
                if self.scan_parameter_value < 0:
                    self.scan_parameter_value = 0
                logging.info('Starting threshold scan at %s %d' %
                             ('PlsrDAC', self.scan_parameter_value))
                self.scan_parameter_start = self.scan_parameter_value
                self.record_data = True
                continue

            # saving data
            if self.record_data:
                self.data_points = self.data_points + 1
                self.raw_data_file.append(
                    self.fifo_readout.data,
                    scan_parameters=self.scan_parameters._asdict())

            # stop condition is met for the first time
            if self.stop_condition_triggered and self.record_data:
                logging.info('Stopping threshold scan at %s %d' %
                             ('PlsrDAC', self.scan_parameter_value))
                break

            # increase scan parameter value
            if not self.start_condition_triggered:
                self.scan_parameter_value = self.scan_parameter_value + self.search_distance
            else:
                self.scan_parameter_value = self.scan_parameter_value + self.step_size

        if self.scan_parameter_value >= scan_parameter_range[1]:
            logging.warning(
                "Reached maximum of PlsrDAC range... stopping scan")
    def scan(self):
        if not self.plots_filename:
            self.plots_filename = PdfPages(self.output_filename + '.pdf')
            self.close_plots = True
        else:
            self.close_plots = False

        cal_lvl1_command = self.register.get_commands(
            "CAL")[0] + self.register.get_commands(
                "zeros", length=40)[0] + self.register.get_commands("LV1")[0]

        self.write_target_threshold()

        scan_parameter_range = [
            (2**self.register.global_registers['Vthin_AltFine']['bitlength']),
            0
        ]  # high to low
        if self.scan_parameters.GDAC[0]:
            scan_parameter_range[0] = self.scan_parameters.GDAC[0]
        if self.scan_parameters.GDAC[1]:
            scan_parameter_range[1] = self.scan_parameters.GDAC[1]
        scan_parameter_range = range(scan_parameter_range[0],
                                     scan_parameter_range[1] - 1,
                                     self.step_size)
        logging.info("Scanning %s from %d to %d", 'GDAC',
                     scan_parameter_range[0], scan_parameter_range[-1])

        def bits_set(int_type):
            int_type = int(int_type)
            position = 0
            bits_set = []
            while (int_type):
                if (int_type & 1):
                    bits_set.append(position)
                position += 1
                int_type = int_type >> 1
            return bits_set

        # calculate selected pixels from the mask and the disabled columns
        select_mask_array = np.zeros(shape=(80, 336), dtype=np.uint8)
        self.occ_array_sel_pixels_best = select_mask_array.copy()
        self.occ_array_desel_pixels_best = select_mask_array.copy()
        if not self.enable_mask_steps_gdac:
            self.enable_mask_steps_gdac = range(self.mask_steps)
        for mask_step in self.enable_mask_steps_gdac:
            select_mask_array += make_pixel_mask(steps=self.mask_steps,
                                                 shift=mask_step)
        for column in bits_set(
                self.register.get_global_register_value("DisableColumnCnfg")):
            logging.info('Deselect double column %d' % column)
            select_mask_array[column, :] = 0

        occupancy_best = 0.0
        median_occupancy_last_step = 0.0
        gdac_best = self.register_utils.get_gdac()
        for gdac_scan_step, scan_parameter_value in enumerate(
                scan_parameter_range):
            self.register_utils.set_gdac(scan_parameter_value)
            with self.readout(GDAC=scan_parameter_value,
                              reset_sram_fifo=True,
                              fill_buffer=True,
                              clear_buffer=True,
                              callback=self.handle_data):
                scan_loop(self,
                          command=cal_lvl1_command,
                          repeat_command=self.n_injections_gdac,
                          mask_steps=self.mask_steps,
                          enable_mask_steps=self.enable_mask_steps_gdac,
                          enable_double_columns=None,
                          same_mask_for_all_dc=self.same_mask_for_all_dc,
                          eol_function=None,
                          digital_injection=False,
                          enable_shift_masks=self.enable_shift_masks,
                          disable_shift_masks=self.disable_shift_masks,
                          restore_shift_masks=True,
                          mask=None,
                          double_column_correction=self.pulser_dac_correction)

            occupancy_array, _, _ = np.histogram2d(*convert_data_array(
                data_array_from_data_iterable(self.fifo_readout.data),
                filter_func=logical_and(is_fe_word, is_data_record),
                converter_func=get_col_row_array_from_data_record_array),
                                                   bins=(80, 336),
                                                   range=[[1, 80], [1, 336]])
            occ_array_sel_pixels = np.ma.array(
                occupancy_array,
                mask=np.logical_not(np.ma.make_mask(select_mask_array))
            )  # take only selected pixel into account by using the mask
            occ_array_desel_pixels = np.ma.array(
                occupancy_array, mask=np.ma.make_mask(select_mask_array)
            )  # take only de-selected pixel into account by using the inverted mask
            median_occupancy = np.ma.median(occ_array_sel_pixels)
            noise_occupancy = np.ma.median(occ_array_desel_pixels)
            occupancy_almost_zero = np.allclose(median_occupancy, 0)
            no_noise = np.allclose(noise_occupancy, 0)
            if no_noise and not occupancy_almost_zero and abs(
                    median_occupancy - self.n_injections_gdac /
                    2) < abs(occupancy_best - self.n_injections_gdac / 2):
                occupancy_best = median_occupancy
                gdac_best = self.register_utils.get_gdac()
                self.occ_array_sel_pixels_best = occ_array_sel_pixels.copy()
                self.occ_array_desel_pixels_best = occ_array_desel_pixels.copy(
                )

            if self.plot_intermediate_steps:
                plot_three_way(self.occ_array_sel_pixel.transpose(),
                               title="Occupancy (GDAC " +
                               str(scan_parameter_value) + ")",
                               x_axis_title='Occupancy',
                               filename=self.plots_filename,
                               maximum=self.n_injections_gdac)

            if no_noise and not occupancy_almost_zero and median_occupancy >= median_occupancy_last_step and median_occupancy >= self.n_injections_gdac / 2:
                break
            if no_noise and not occupancy_almost_zero:
                median_occupancy_last_step = median_occupancy
            else:
                median_occupancy_last_step = 0.0

        self.register_utils.set_gdac(gdac_best, send_command=False)
        median_occupancy = occupancy_best
        self.gdac_best = self.register_utils.get_gdac()

        if abs(median_occupancy -
               self.n_injections_gdac / 2) > self.max_delta_threshold:
            if np.all((((self.gdac_best & (1 << np.arange(
                    self.register.global_registers['Vthin_AltFine']
                ['bitlength'] + self.register.global_registers['Vthin_AltFine']
                ['bitlength'])))) > 0).astype(int) == 0):
                if self.fail_on_warning:
                    raise RuntimeWarning(
                        'Selected GDAC bits reached minimum value')
                else:
                    logging.warning('Selected GDAC bits reached minimum value')
            else:
                if self.fail_on_warning:
                    raise RuntimeWarning(
                        'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d'
                        % (abs(median_occupancy - self.n_injections_gdac / 2),
                           self.max_delta_threshold,
                           self.register.get_global_register_value(
                               "Vthin_AltCoarse"),
                           self.register.get_global_register_value(
                               "Vthin_AltFine")))
                else:
                    logging.warning(
                        'Global threshold tuning failed. Delta threshold = %.2f > %.2f. Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                        abs(median_occupancy - self.n_injections_gdac / 2),
                        self.max_delta_threshold,
                        self.register.get_global_register_value(
                            "Vthin_AltCoarse"),
                        self.register.get_global_register_value(
                            "Vthin_AltFine"))
        else:
            logging.info(
                'Tuned GDAC to Vthin_AltCoarse / Vthin_AltFine = %d / %d',
                self.register.get_global_register_value("Vthin_AltCoarse"),
                self.register.get_global_register_value("Vthin_AltFine"))