def plot_histograms(self, pdf_filename=None, analyzed_data_file=None, maximum=None, create_hit_hists_only=False):  # plots the histogram from output file if available otherwise from ram
        logging.info('Creating histograms%s', (' (source: %s)' % analyzed_data_file) if analyzed_data_file is not None else (' (source: %s)' % self._analyzed_data_file) if self._analyzed_data_file is not None else '')
        close_analyzed_data_file = False
        if analyzed_data_file is not None:
            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="r")
                close_analyzed_data_file = True
        elif self.is_open(self.out_file_h5):
            out_file_h5 = self.out_file_h5
        else:
            logging.info('Parameter "analyzed_data_file" not set. Use histograms from memory.')
        if pdf_filename is not None:
            # normalize path
            pdf_filename = os.path.abspath(pdf_filename)
            if os.path.splitext(pdf_filename)[1].lower() != ".pdf":
                output_pdf_filename = os.path.splitext(pdf_filename)[0] + ".pdf"
            else:
                output_pdf_filename = pdf_filename
        # reuse existing PDF file
        if pdf_filename is not None and os.path.abspath(output_pdf_filename) != self.output_pdf._file.fh.name:
            logging.info('Opening output PDF file: %s', output_pdf_filename)
            output_pdf = PdfPages(output_pdf_filename)
            close_pdf = True
        else:
            output_pdf = self.output_pdf
            close_pdf = False
        if output_pdf is None:
            raise ValueError('Parameter "pdf_filename" not specified.')
        logging.info('Saving histograms to PDF file: %s', str(output_pdf._file.fh.name))
        if self._create_threshold_hists:
            if self._create_threshold_mask:  # mask pixel with bad data for plotting
                if out_file_h5 is not None:
                    self.threshold_mask = analysis_utils.generate_threshold_mask(out_file_h5.root.HistNoise[:])
                else:
                    self.threshold_mask = analysis_utils.generate_threshold_mask(self.noise_hist)
            else:
                self.threshold_mask = np.zeros_like(out_file_h5.root.HistThreshold[:] if out_file_h5 is not None else self.threshold_hist, dtype=np.bool)
            threshold_hist = np.ma.array(out_file_h5.root.HistThreshold[:] if out_file_h5 is not None else self.threshold_hist, mask=self.threshold_mask)
            noise_hist = np.ma.array(out_file_h5.root.HistNoise[:] if out_file_h5 is not None else self.noise_hist, mask=self.threshold_mask)
            mask_cnt = np.ma.count_masked(noise_hist)
            logging.info('Fast algorithm: masking %d pixel(s)', mask_cnt)
            plotting.plot_three_way(hist=threshold_hist, title='Threshold%s' % ((' (masked %i pixel(s))' % mask_cnt) if self._create_threshold_mask else ''), x_axis_title="threshold [PlsrDAC]", filename=output_pdf, bins=100, minimum=0, maximum=maximum)
            plotting.plot_three_way(hist=noise_hist, title='Noise%s' % ((' (masked %i pixel(s))' % mask_cnt) if self._create_threshold_mask else ''), x_axis_title="noise [PlsrDAC]", filename=output_pdf, bins=100, minimum=0, maximum=maximum)
        if self._create_fitted_threshold_hists:
            if self._create_fitted_threshold_mask:
                if out_file_h5 is not None:
                    self.fitted_threshold_mask = analysis_utils.generate_threshold_mask(out_file_h5.root.HistNoiseFitted[:])
                else:
                    self.fitted_threshold_mask = analysis_utils.generate_threshold_mask(self.scurve_fit_results[:, :, 1])
            else:
                self.threshold_mask = np.zeros_like(out_file_h5.root.HistThresholdFitted[:] if out_file_h5 is not None else self.scurve_fit_results, dtype=np.bool8)
            threshold_hist = np.ma.array(out_file_h5.root.HistThresholdFitted[:] if out_file_h5 is not None else self.scurve_fit_results[:, :, 0], mask=self.fitted_threshold_mask)
            noise_hist = np.ma.array(out_file_h5.root.HistNoiseFitted[:] if out_file_h5 is not None else self.scurve_fit_results[:, :, 1], mask=self.fitted_threshold_mask)
            threshold_hist_calib = np.ma.array(out_file_h5.root.HistThresholdFittedCalib[:] if out_file_h5 is not None else self.threshold_hist_calib[:], mask=self.fitted_threshold_mask)
            noise_hist_calib = np.ma.array(out_file_h5.root.HistNoiseFittedCalib[:] if out_file_h5 is not None else self.noise_hist_calib[:], mask=self.fitted_threshold_mask)
            mask_cnt = np.ma.count_masked(noise_hist)
            logging.info('S-curve fit: masking %d pixel(s)', mask_cnt)
            plotting.plot_three_way(hist=threshold_hist, title='Threshold (S-curve fit, masked %i pixel(s))' % mask_cnt, x_axis_title="Threshold [PlsrDAC]", filename=output_pdf, bins=100, minimum=0, maximum=maximum)
            plotting.plot_three_way(hist=noise_hist, title='Noise (S-curve fit, masked %i pixel(s))' % mask_cnt, x_axis_title="Noise [PlsrDAC]", filename=output_pdf, bins=100, minimum=0, maximum=maximum)
            plotting.plot_three_way(hist=threshold_hist_calib, title='Threshold (S-curve fit, masked %i pixel(s))' % mask_cnt, x_axis_title="Threshold [e]", filename=output_pdf, bins=100, minimum=0)
            plotting.plot_three_way(hist=noise_hist_calib, title='Noise (S-curve fit, masked %i pixel(s))' % mask_cnt, x_axis_title="Noise [e]", filename=output_pdf, bins=100, minimum=0)
        if self._create_occupancy_hist:
            if self._create_fitted_threshold_hists:
                _, scan_parameters_idx = np.unique(self.scan_parameters['PlsrDAC'], return_index=True)
                scan_parameters = self.scan_parameters['PlsrDAC'][np.sort(scan_parameters_idx)]
                plotting.plot_scurves(occupancy_hist=out_file_h5.root.HistOcc[:] if out_file_h5 is not None else self.occupancy_array[:], filename=output_pdf, scan_parameters=scan_parameters, scan_parameter_name="PlsrDAC")
            else:
                hist = np.sum(out_file_h5.root.HistOcc[:], axis=2) if out_file_h5 is not None else np.sum(self.occupancy_array[:], axis=2)
                occupancy_array_masked = np.ma.masked_equal(hist, 0)
                if self._create_source_scan_hist:
                    plotting.plot_fancy_occupancy(hist=occupancy_array_masked, filename=output_pdf, z_max='median')
                    plotting.plot_occupancy(hist=occupancy_array_masked, filename=output_pdf, z_max='maximum')
                else:
                    plotting.plot_three_way(hist=occupancy_array_masked, title="Occupancy", x_axis_title="occupancy", filename=output_pdf, maximum=maximum)
                    plotting.plot_occupancy(hist=occupancy_array_masked, filename=output_pdf, z_max='median')
        if self._create_tot_hist:
            plotting.plot_tot(hist=out_file_h5.root.HistTot[:] if out_file_h5 is not None else self.tot_hist, filename=output_pdf)
        if self._create_tot_pixel_hist:
            tot_pixel_hist = out_file_h5.root.HistTotPixel[:] if out_file_h5 is not None else self.tot_pixel_hist_array
            total_hits_masked = np.ma.masked_equal(np.sum(tot_pixel_hist, axis=2), 0)
            mean_pixel_tot = np.average(tot_pixel_hist, axis=2, weights=range(16)) * sum(range(0, 16)) / total_hits_masked
            plotting.plot_three_way(mean_pixel_tot, title='Mean ToT', x_axis_title='mean ToT', filename=output_pdf, minimum=0, maximum=15)
        if self._create_tdc_counter_hist:
            plotting.plot_tdc_counter(hist=out_file_h5.root.HistTdcCounter[:] if out_file_h5 is not None else self.tdc_hist_counter, filename=output_pdf)
        if self._create_tdc_hist:
            plotting.plot_tdc(hist=out_file_h5.root.HistTdc[:] if out_file_h5 is not None else self.tdc_hist, filename=output_pdf)
        if self._create_cluster_size_hist:
            plotting.plot_cluster_size(hist=out_file_h5.root.HistClusterSize[:] if out_file_h5 is not None else self.cluster_size_hist, filename=output_pdf)
        if self._create_cluster_tot_hist:
            plotting.plot_cluster_tot(hist=out_file_h5.root.HistClusterTot[:] if out_file_h5 is not None else self.cluster_tot_hist, filename=output_pdf)
        if self._create_cluster_tot_hist and self._create_cluster_size_hist:
            plotting.plot_cluster_tot_size(hist=out_file_h5.root.HistClusterTot[:] if out_file_h5 is not None else self.cluster_tot_hist, filename=output_pdf)
        if self._create_rel_bcid_hist:
            if self.set_stop_mode:
                plotting.plot_relative_bcid_stop_mode(hist=out_file_h5.root.HistRelBcid[:] if out_file_h5 is not None else self.rel_bcid_hist, filename=output_pdf)
            else:
                plotting.plot_relative_bcid(hist=out_file_h5.root.HistRelBcid[0:16] if out_file_h5 is not None else self.rel_bcid_hist[0:16], filename=output_pdf)
        if self._create_tdc_pixel_hist:
            tdc_pixel_hist = out_file_h5.root.HistTdcPixel[:, :, :1024] if out_file_h5 is not None else self.tdc_pixel_hist_array[:, :, :1024]  # only take first 1024 values, otherwise memory error likely
            total_hits_masked = np.ma.masked_equal(np.sum(tdc_pixel_hist, axis=2), 0)
            mean_pixel_tdc = np.average(tdc_pixel_hist, axis=2, weights=range(1024)) * sum(range(0, 1024)) / total_hits_masked
            plotting.plot_three_way(mean_pixel_tdc, title='Mean TDC', x_axis_title='mean TDC', maximum=2 * np.ma.median(np.ma.masked_invalid(mean_pixel_tdc)), filename=output_pdf)
        if not create_hit_hists_only:
            if analyzed_data_file is None and self._create_error_hist:
                plotting.plot_event_errors(hist=out_file_h5.root.HistErrorCounter[:] if out_file_h5 is not None else self.error_counter_hist, filename=output_pdf)
            if analyzed_data_file is None and self._create_service_record_hist:
                plotting.plot_service_records(hist=out_file_h5.root.HistServiceRecord[:] if out_file_h5 is not None else self.service_record_hist, filename=output_pdf)
            if analyzed_data_file is None and self._create_trigger_error_hist:
                plotting.plot_trigger_errors(hist=out_file_h5.root.HistTriggerErrorCounter[:] if out_file_h5 is not None else self.trigger_error_counter_hist, filename=output_pdf)

        if close_analyzed_data_file:
            out_file_h5.close()
        if close_pdf:
            logging.info('Closing output PDF file: %s', str(output_pdf._file.fh.name))
            output_pdf.close()