def interpret_word_table(self, analyzed_data_file=None, use_settings_from_file=True, fei4b=None):
        '''Interprets the raw data word table of all given raw data files with the c++ library.
        Creates the h5 output file and PDF plots.

        Parameters
        ----------
        analyzed_data_file : string
            The file name of the output analyzed data file. If None, the output analyzed data file
            specified during initialization is taken.
        use_settings_from_file : boolean
            True if the needed parameters should be extracted from the raw data file
        fei4b : boolean
            True if the raw data is from FE-I4B.
        '''

        logging.info('Interpreting raw data file(s): ' + (', ').join(self.files_dict.keys()))

        if self._create_meta_word_index:
            meta_word = np.empty((self._chunk_size,), dtype=dtype_from_descr(data_struct.MetaInfoWordTable))
            self.interpreter.set_meta_data_word_index(meta_word)
        self.interpreter.reset_event_variables()
        self.interpreter.reset_counters()

        self.meta_data = analysis_utils.combine_meta_data(self.files_dict, meta_data_v2=self.interpreter.meta_table_v2)

        if self.meta_data is None or self.meta_data.shape[0] == 0:
            raise analysis_utils.IncompleteInputError('Meta data is empty. Stopping interpretation.')

        self.interpreter.set_meta_data(self.meta_data)  # tell interpreter the word index per readout to be able to calculate the event number per read out
        meta_data_size = self.meta_data.shape[0]
        self.meta_event_index = np.zeros((meta_data_size,), dtype=[('metaEventIndex', np.uint64)])  # this array is filled by the interpreter and holds the event number per read out
        self.interpreter.set_meta_event_data(self.meta_event_index)  # tell the interpreter the data container to write the meta event index to

        if self.scan_parameters is None:
            self.histogram.set_no_scan_parameter()
        else:
            self.scan_parameter_index = analysis_utils.get_scan_parameters_index(self.scan_parameters)  # a array that labels unique scan parameter combinations
            self.histogram.add_scan_parameter(self.scan_parameter_index)  # just add an index for the different scan parameter combinations

        if self._create_cluster_size_hist:  # Cluster size result histogram
            self._cluster_size_hist = np.zeros(shape=(6, ), dtype=np.uint32)

        if self._create_cluster_tot_hist:  # Cluster tot/size result histogram
            self._cluster_tot_hist = np.zeros(shape=(16, 6), dtype=np.uint32)

        close_analyzed_data_file = False
        if analyzed_data_file is not None:  # if an output file name is specified create new file for analyzed data
            if self.is_open(self.out_file_h5) and os.path.abspath(analyzed_data_file) == os.path.abspath(self.out_file_h5.filename):
                out_file_h5 = self.out_file_h5
            else:
                # normalize path
                analyzed_data_file = os.path.abspath(analyzed_data_file)
                if os.path.splitext(analyzed_data_file)[1].lower() != ".h5":
                    analyzed_data_file = os.path.splitext(analyzed_data_file)[0] + ".h5"
                out_file_h5 = tb.open_file(analyzed_data_file, mode="w", title="Interpreted FE-I4 raw data")
                close_analyzed_data_file = True
        elif self.is_open(self.out_file_h5):
                out_file_h5 = self.out_file_h5
        else:
            out_file_h5 = None

        tmp_out_file_h5 = self.out_file_h5
        if not self.is_open(self.out_file_h5) and self.is_open(out_file_h5):
            close_analyzed_data_file = False
            tmp_out_file_h5 = out_file_h5
        self.out_file_h5 = out_file_h5
        if self.is_open(self.out_file_h5):
            self._analyzed_data_file = self.out_file_h5.filename
        else:
            self._analyzed_data_file is None

        if self._analyzed_data_file is not None:
            if self._create_hit_table is True:
                description = data_struct.HitInfoTable().columns.copy()
                hit_table = self.out_file_h5.create_table(self.out_file_h5.root, name='Hits', description=description, title='hit_data', filters=self._filter_table, chunkshape=(self._chunk_size / 100,))
            if self._create_meta_word_index is True:
                meta_word_index_table = self.out_file_h5.create_table(self.out_file_h5.root, name='EventMetaData', description=data_struct.MetaInfoWordTable, title='event_meta_data', filters=self._filter_table, chunkshape=(self._chunk_size / 10,))
            if self._create_cluster_table:
                cluster_table = self.out_file_h5.create_table(self.out_file_h5.root, name='Cluster', description=data_struct.ClusterInfoTable, title='Cluster data', filters=self._filter_table, expectedrows=self._chunk_size)
            if self._create_cluster_hit_table:
                description = data_struct.ClusterHitInfoTable().columns.copy()
                cluster_hit_table = self.out_file_h5.create_table(self.out_file_h5.root, name='ClusterHits', description=description, title='cluster_hit_data', filters=self._filter_table, expectedrows=self._chunk_size)

        logging.info("Interpreting raw data...")
        progress_bar = progressbar.ProgressBar(widgets=['', progressbar.Percentage(), ' ', progressbar.Bar(marker='*', left='|', right='|'), ' ', progressbar.AdaptiveETA()], maxval=analysis_utils.get_total_n_data_words(self.files_dict), term_width=80)
        progress_bar.start()
        total_words = 0

        for file_index, raw_data_file in enumerate(self.files_dict.keys()):  # loop over all raw data files
            self.interpreter.reset_meta_data_counter()
            with tb.open_file(raw_data_file, mode="r") as in_file_h5:
                if use_settings_from_file:
                    self._deduce_settings_from_file(in_file_h5)
                else:
                    self.fei4b = fei4b
                if self.interpreter.meta_table_v2:
                    index_start = in_file_h5.root.meta_data.read(field='index_start')
                    index_stop = in_file_h5.root.meta_data.read(field='index_stop')
                else:
                    index_start = in_file_h5.root.meta_data.read(field='start_index')
                    index_stop = in_file_h5.root.meta_data.read(field='stop_index')
                bad_word_index = set()

                # Check for bad data
                if self._correct_corrupted_data:
                    tw = 2147483648  # trigger word
                    dh = 15269888  # data header
                    is_fe_data_header = logical_and(is_fe_word, is_data_header)
                    found_first_trigger = False
                    readout_slices = np.column_stack((index_start, index_stop))
                    previous_prepend_data_headers = None
                    prepend_data_headers = None
                    last_good_readout_index = None
                    last_index_with_event_data = None
                    for read_out_index, (index_start, index_stop) in enumerate(readout_slices):
                        try:
                            raw_data = in_file_h5.root.raw_data.read(index_start, index_stop)
                        except OverflowError, e:
                            pass
                        except tb.exceptions.HDF5ExtError:
                            break
                        # previous data chunk had bad data, check for good data
                        if (index_start - 1) in bad_word_index:
                            bad_data, current_prepend_data_headers, _ , _ = check_bad_data(raw_data, prepend_data_headers=1, trig_count=None)
                            if bad_data:
                                bad_word_index = bad_word_index.union(range(index_start, index_stop))
                            else:
#                                 logging.info("found good data in %s from index %d to %d (chunk %d, length %d)" % (in_file_h5.filename, index_start, index_stop, read_out_index, (index_stop - index_start)))
                                if last_good_readout_index + 1 == read_out_index - 1:
                                    logging.warning("found bad data in %s from index %d to %d (chunk %d, length %d)" % (in_file_h5.filename, readout_slices[last_good_readout_index][1], readout_slices[read_out_index - 1][1], last_good_readout_index + 1, (readout_slices[read_out_index - 1][1] - readout_slices[last_good_readout_index][1])))
                                else:
                                    logging.warning("found bad data in %s from index %d to %d (chunk %d to %d, length %d)" % (in_file_h5.filename, readout_slices[last_good_readout_index][1], readout_slices[read_out_index - 1][1], last_good_readout_index + 1, read_out_index - 1, (readout_slices[read_out_index - 1][1] - readout_slices[last_good_readout_index][1])))
                                previous_good_raw_data = in_file_h5.root.raw_data.read(readout_slices[last_good_readout_index][0], readout_slices[last_good_readout_index][1] - 1)
                                previous_bad_raw_data = in_file_h5.root.raw_data.read(readout_slices[last_good_readout_index][1] - 1, readout_slices[read_out_index - 1][1])
                                fixed_raw_data, _ = fix_raw_data(previous_bad_raw_data, lsb_byte=None)
                                fixed_raw_data = np.r_[previous_good_raw_data, fixed_raw_data, raw_data]
                                _, prepend_data_headers, n_triggers, n_dh = check_bad_data(fixed_raw_data, prepend_data_headers=previous_prepend_data_headers, trig_count=self.trig_count)
                                last_good_readout_index = read_out_index
                                if n_triggers != 0 or n_dh != 0:
                                    last_index_with_event_data = read_out_index
                                    last_event_data_prepend_data_headers = prepend_data_headers
                                fixed_previous_raw_data = np.r_[previous_good_raw_data, fixed_raw_data]
                                _, previous_prepend_data_headers, _ , _ = check_bad_data(fixed_previous_raw_data, prepend_data_headers=previous_prepend_data_headers, trig_count=self.trig_count)
                        # check for bad data
                        else:
                            # workaround for first data chunk, might have missing trigger in some rare cases (already fixed in firmware)
                            if read_out_index == 0 and (np.any(is_trigger_word(raw_data) >= 1) or np.any(is_fe_data_header(raw_data) >= 1)):
                                bad_data, current_prepend_data_headers, n_triggers , n_dh = check_bad_data(raw_data, prepend_data_headers=1, trig_count=None)
                                # check for full last event in data
                                if current_prepend_data_headers == self.trig_count:
                                    current_prepend_data_headers = None
                            # usually check for bad data happens here
                            else:
                                bad_data, current_prepend_data_headers, n_triggers , n_dh = check_bad_data(raw_data, prepend_data_headers=prepend_data_headers, trig_count=self.trig_count)

                            # do additional check with follow up data chunk and decide whether current chunk is defect or not
                            if bad_data:
                                if read_out_index == 0:
                                    fixed_raw_data_chunk, _ = fix_raw_data(raw_data, lsb_byte=None)
                                    fixed_raw_data_list = [fixed_raw_data_chunk]
                                else:
                                    previous_raw_data = in_file_h5.root.raw_data.read(*readout_slices[read_out_index - 1])
                                    raw_data_with_previous_data_word = np.r_[previous_raw_data[-1], raw_data]
                                    fixed_raw_data_chunk, _ = fix_raw_data(raw_data_with_previous_data_word, lsb_byte=None)
                                    fixed_raw_data = np.r_[previous_raw_data[:-1], fixed_raw_data_chunk]
                                    # last data word of chunk before broken chunk migh be a trigger word or data header which cannot be recovered
                                    fixed_raw_data_with_tw = np.r_[previous_raw_data[:-1], tw, fixed_raw_data_chunk]
                                    fixed_raw_data_with_dh = np.r_[previous_raw_data[:-1], dh, fixed_raw_data_chunk]
                                    fixed_raw_data_list = [fixed_raw_data, fixed_raw_data_with_tw, fixed_raw_data_with_dh]
                                bad_fixed_data, _, _ , _ = check_bad_data(fixed_raw_data_with_dh, prepend_data_headers=previous_prepend_data_headers, trig_count=self.trig_count)
                                bad_fixed_data = map(lambda data: check_bad_data(data, prepend_data_headers=previous_prepend_data_headers, trig_count=self.trig_count)[0], fixed_raw_data_list)
                                if not all(bad_fixed_data): # good fixed data
                                    # last word in chunk before currrent chunk is also bad
                                    if index_start != 0:
                                        bad_word_index.add(index_start - 1)
                                    # adding all word from current chunk
                                    bad_word_index = bad_word_index.union(range(index_start, index_stop))
                                    last_good_readout_index = read_out_index - 1
                                else:
                                    # a previous chunk might be broken and the last data word becomes a trigger word, so do additional checks
                                    if last_index_with_event_data and last_event_data_prepend_data_headers != read_out_index:
                                        before_bad_raw_data = in_file_h5.root.raw_data.read(readout_slices[last_index_with_event_data - 1][0], readout_slices[last_index_with_event_data - 1][1] - 1)
                                        previous_bad_raw_data = in_file_h5.root.raw_data.read(readout_slices[last_index_with_event_data][0] - 1, readout_slices[last_index_with_event_data][1])
                                        fixed_raw_data, _ = fix_raw_data(previous_bad_raw_data, lsb_byte=None)
                                        previous_good_raw_data = in_file_h5.root.raw_data.read(readout_slices[last_index_with_event_data][1], readout_slices[read_out_index - 1][1])
                                        fixed_raw_data = np.r_[before_bad_raw_data, fixed_raw_data, previous_good_raw_data, raw_data]
                                        bad_fixed_previous_data, current_prepend_data_headers, _, _ = check_bad_data(fixed_raw_data, prepend_data_headers=last_event_data_prepend_data_headers, trig_count=self.trig_count)
                                        if not bad_fixed_previous_data:
                                            logging.warning("found bad data in %s from index %d to %d (chunk %d, length %d)" % (in_file_h5.filename, readout_slices[last_index_with_event_data][0], readout_slices[last_index_with_event_data][1], last_index_with_event_data, (readout_slices[last_index_with_event_data][1] - readout_slices[last_index_with_event_data][0])))
                                            bad_word_index = bad_word_index.union(range(readout_slices[last_index_with_event_data][0] - 1, readout_slices[last_index_with_event_data][1]))
                                        else:
                                            logging.warning("found bad data which cannot be corrected in %s from index %d to %d (chunk %d, length %d)" % (in_file_h5.filename, index_start, index_stop, read_out_index, (index_stop - index_start)))
                                    else:
                                        logging.warning("found bad data which cannot be corrected in %s from index %d to %d (chunk %d, length %d)" % (in_file_h5.filename, index_start, index_stop, read_out_index, (index_stop - index_start)))
                            if n_triggers != 0 or n_dh != 0:
                                last_index_with_event_data = read_out_index
                                last_event_data_prepend_data_headers = prepend_data_headers
                            if not bad_data or (bad_data and bad_fixed_data):
                                previous_prepend_data_headers = prepend_data_headers
                                prepend_data_headers = current_prepend_data_headers

                    consecutive_bad_words_list = consecutive(sorted(bad_word_index))

                lsb_byte = None
                # Loop over raw data in chunks
                for word_index in range(0, in_file_h5.root.raw_data.shape[0], self._chunk_size):  # loop over all words in the actual raw data file
                    try:
                        raw_data = in_file_h5.root.raw_data.read(word_index, word_index + self._chunk_size)
                    except OverflowError, e:
                        logging.error('%s: 2^31 xrange() limitation in 32-bit Python', e)
                    except tb.exceptions.HDF5ExtError:
                        logging.warning('Raw data file %s has missing raw data. Continue raw data analysis.', in_file_h5.filename)
                        break
                    total_words += raw_data.shape[0]
                    # fix bad data
                    if self._correct_corrupted_data:
                        # increase word shift for every bad data chunk in raw data chunk
                        word_shift = 0
                        chunk_indices = np.arange(word_index, word_index + self._chunk_size)
                        for consecutive_bad_word_indices in consecutive_bad_words_list:
                            selected_words = np.intersect1d(consecutive_bad_word_indices, chunk_indices, assume_unique=True)
                            if selected_words.shape[0]:
                                fixed_raw_data, lsb_byte = fix_raw_data(raw_data[selected_words - word_index - word_shift], lsb_byte=lsb_byte)
                                raw_data = np.r_[raw_data[:selected_words[0] - word_index - word_shift], fixed_raw_data, raw_data[selected_words[-1] - word_index + 1 - word_shift:]]
                                # check if last word of bad data chunk in current raw data chunk
                                if consecutive_bad_word_indices[-1] in selected_words:
                                    lsb_byte = None
                                    # word shift by removing data word at the beginning of each defect chunk
                                    word_shift += 1
                                # bad data chunk is at the end of current raw data chunk
                                else:
                                    break

                    self.interpreter.interpret_raw_data(raw_data)  # interpret the raw data
                    # store remaining buffered event in the interpreter at the end of the last file
                    if file_index == len(self.files_dict.keys()) - 1 and word_index == range(0, in_file_h5.root.raw_data.shape[0], self._chunk_size)[-1]:  # store hits of the latest event of the last file
                        self.interpreter.store_event()
                    hits = self.interpreter.get_hits()
                    if self.scan_parameters is not None:
                        nEventIndex = self.interpreter.get_n_meta_data_event()
                        self.histogram.add_meta_event_index(self.meta_event_index, nEventIndex)
                    if self.is_histogram_hits():
                        self.histogram_hits(hits)
                    if self.is_cluster_hits():
                        cluster_hits, clusters = self.cluster_hits(hits)
                        if self._create_cluster_hit_table:
                            cluster_hit_table.append(cluster_hits)
                        if self._create_cluster_table:
                            cluster_table.append(clusters)
                        if self._create_cluster_size_hist:
                            if clusters['size'].shape[0] > 0 and np.max(clusters['size']) + 1 > self._cluster_size_hist.shape[0]:
                                self._cluster_size_hist.resize(np.max(clusters['size']) + 1)
                            self._cluster_size_hist += fast_analysis_utils.hist_1d_index(clusters['size'], shape=self._cluster_size_hist.shape)
                        if self._create_cluster_tot_hist:
                            if clusters['tot'].shape[0] > 0 and np.max(clusters['tot']) + 1 > self._cluster_tot_hist.shape[0]:
                                self._cluster_tot_hist.resize((np.max(clusters['tot']) + 1, self._cluster_tot_hist.shape[1]))
                            if clusters['size'].shape[0] > 0 and np.max(clusters['size']) + 1 > self._cluster_tot_hist.shape[1]:
                                self._cluster_tot_hist.resize((self._cluster_tot_hist.shape[0], np.max(clusters['size']) + 1))
                            self._cluster_tot_hist += fast_analysis_utils.hist_2d_index(clusters['tot'], clusters['size'], shape=self._cluster_tot_hist.shape)
                    if self._analyzed_data_file is not None and self._create_hit_table:
                        hit_table.append(hits)
                    if self._analyzed_data_file is not None and self._create_meta_word_index:
                        size = self.interpreter.get_n_meta_data_word()
                        meta_word_index_table.append(meta_word[:size])

                    if total_words <= progress_bar.maxval:  # Otherwise exception is thrown
                        progress_bar.update(total_words)
                    self.out_file_h5.flush()
        progress_bar.finish()
        self._create_additional_data()

        if close_analyzed_data_file:
            self.out_file_h5.close()
            self.out_file_h5 = None
        self.out_file_h5 = out_file_h5
        if self.is_open(self.out_file_h5):
            self._analyzed_data_file = self.out_file_h5.filename
        else:
            self._analyzed_data_file = None