diff --git a/run.py b/run.py
index ec30d5d41a39932cb7c9b6eb4f94457d6518d4f9..79492b0f92f5c32eb75c4e3443778336a6192656 100644
--- a/run.py
+++ b/run.py
@@ -34,8 +34,7 @@ def main(parser_args):
                         create_new_bootstraps=False,
                         plot_list=["PlotMonthlySummary", "PlotStationMap", "PlotClimatologicalSkillScore",
                                    "PlotCompetitiveSkillScore", "PlotBootstrapSkillScore", "PlotConditionalQuantiles",
-                                   "PlotAvailability"],
-
+                                   "PlotAvailabilityHistogram"],
                         )
 
         PreProcessing()
diff --git a/src/plotting/postprocessing_plotting.py b/src/plotting/postprocessing_plotting.py
index 75450d939a9d56a87cd7ba955299807b7c91bfee..5c72b47585ccde6017f2f7769f9e09258d3943ca 100644
--- a/src/plotting/postprocessing_plotting.py
+++ b/src/plotting/postprocessing_plotting.py
@@ -16,9 +16,10 @@ import seaborn as sns
 import xarray as xr
 from matplotlib.backends.backend_pdf import PdfPages
 import matplotlib.patches as mpatches
+import matplotlib.dates as mdates
 
 from src import helpers
-from src.helpers import TimeTracking, TimeTrackingWrapper
+from src.helpers import TimeTrackingWrapper
 from src.data_handling.data_generator import DataGenerator
 
 logging.getLogger('matplotlib').setLevel(logging.WARNING)
@@ -26,10 +27,22 @@ logging.getLogger('matplotlib').setLevel(logging.WARNING)
 
 class AbstractPlotClass:
 
-    def __init__(self, plot_folder, plot_name, resolution=500):
+    def __init__(self, plot_folder, plot_name, resolution=500, rc_params=None):
+        if rc_params is None:
+            rc_params = {'axes.labelsize': 'large',
+                         'xtick.labelsize': 'large',
+                         'ytick.labelsize': 'large',
+                         'legend.fontsize': 'large',
+                         'axes.titlesize': 'large',
+                         }
         self.plot_folder = plot_folder
         self.plot_name = plot_name
         self.resolution = resolution
+        self.rc_params = rc_params
+        self._update_rc_params()
+
+    def _update_rc_params(self):
+        plt.rcParams.update(self.rc_params)
 
     def _plot(self, *args):
         raise NotImplementedError
@@ -43,6 +56,21 @@ class AbstractPlotClass:
         plt.savefig(plot_name, dpi=self.resolution, **kwargs)
         plt.close('all')
 
+    @staticmethod
+    def _get_sampling(sampling):
+        if sampling == "daily":
+            return "D"
+        elif sampling == "hourly":
+            return "h"
+
+    @staticmethod
+    def get_dataset_colors():
+        """
+        Standard colors used for train-, val-, and test-sets during postprocessing
+        """
+        colors = {"train": "#e69f00", "val": "#009e73", "test": "#56b4e9"}  # hex code
+        return colors
+
 
 @TimeTrackingWrapper
 class PlotMonthlySummary(AbstractPlotClass):
@@ -51,7 +79,7 @@ class PlotMonthlySummary(AbstractPlotClass):
     in data_path with name monthly_summary_box_plot.pdf and 500dpi resolution.
     """
     def __init__(self, stations: List, data_path: str, name: str, target_var: str, window_lead_time: int = None,
-                 plot_folder: str = "."):
+                 plot_folder: str = ".", target_var_unit: str = 'ppb'):
         """
         Sets attributes and create plot
         :param stations: all stations to plot
@@ -61,13 +89,14 @@ class PlotMonthlySummary(AbstractPlotClass):
         :param window_lead_time: lead time to plot, if window_lead_time is higher than the available lead time or not given
             the maximum lead time from data is used. (default None -> use maximum lead time from data).
         :param plot_folder: path to save the plot (default: current directory)
+        :param target_var_unit: unit of target var for plot legend
         """
         super().__init__(plot_folder, "monthly_summary_box_plot")
         self._data_path = data_path
         self._data_name = name
         self._data = self._prepare_data(stations)
         self._window_lead_time = self._get_window_lead_time(window_lead_time)
-        self._plot(target_var)
+        self._plot(target_var, target_var_unit)
         self._save()
 
     def _prepare_data(self, stations: List) -> xr.DataArray:
@@ -112,7 +141,7 @@ class PlotMonthlySummary(AbstractPlotClass):
             window_lead_time = ahead_steps
         return min(ahead_steps, window_lead_time)
 
-    def _plot(self, target_var: str):
+    def _plot(self, target_var: str, target_var_unit: str):
         """
         Main plot function that creates a monthly grouped box plot over all stations but with separate boxes for each
         lead time step.
@@ -124,9 +153,15 @@ class PlotMonthlySummary(AbstractPlotClass):
         ax = sns.boxplot(x='index', y='values', hue='ahead', data=data.compute(), whis=1., palette=color_palette,
                          flierprops={'marker': '.', 'markersize': 1}, showmeans=True,
                          meanprops={'markersize': 1, 'markeredgecolor': 'k'})
-        ax.set(xlabel='month', ylabel=f'{target_var}')
+        ylabel = self._spell_out_chemical_concentrations(target_var)
+        ax.set(xlabel='month', ylabel=f'{ylabel} (in {target_var_unit})')
         plt.tight_layout()
 
+    @staticmethod
+    def _spell_out_chemical_concentrations(short_name: str):
+        short2long = {'o3': 'ozone', 'no': 'nitrogen oxide', 'no2': 'nitrogen dioxide', 'nox': 'nitrogen dioxides'}
+        return f"{short2long[short_name]} concentration"
+
 
 @TimeTrackingWrapper
 class PlotStationMap(AbstractPlotClass):
@@ -461,7 +496,7 @@ class PlotClimatologicalSkillScore(AbstractPlotClass):
     name skill_score_clim_{extra_name_tag}{model_setup}.pdf and resolution of 500dpi.
     """
     def __init__(self, data: Dict, plot_folder: str = ".", score_only: bool = True, extra_name_tag: str = "",
-                 model_setup: str = ""):
+                 model_setup: str = "", font_size_all_terms: int = 22):
         """
         Sets attributes and create plot
         :param data: dictionary with station names as keys and 2D xarrays as values, consist on axis ahead and terms.
@@ -469,8 +504,10 @@ class PlotClimatologicalSkillScore(AbstractPlotClass):
         :param score_only: if true plot only scores of CASE I to IV, otherwise plot all single terms (default True)
         :param extra_name_tag: additional tag that can be included in the plot name (default "")
         :param model_setup: architecture type to specify plot name (default "CNN")
+        :param font_size_all_terms: font size for summary plot containing all terms and skill scores
         """
         super().__init__(plot_folder, f"skill_score_clim_{extra_name_tag}{model_setup}")
+        self.font_size_all_terms = font_size_all_terms
         self._labels = None
         self._data = self._prepare_data(data, score_only)
         self._plot(score_only)
@@ -506,12 +543,23 @@ class PlotClimatologicalSkillScore(AbstractPlotClass):
         fig, ax = plt.subplots()
         if not score_only:
             fig.set_size_inches(11.7, 8.27)
+            ax.tick_params(labelsize=self.font_size_all_terms)
+            plt.xticks(fontsize=self.font_size_all_terms, rotation=45)
+
         sns.boxplot(x="terms", y="data", hue="ahead", data=self._data, ax=ax, whis=1., palette="Blues_d",
                     showmeans=True, meanprops={"markersize": 1, "markeredgecolor": "k"}, flierprops={"marker": "."})
         ax.axhline(y=0, color="grey", linewidth=.5)
-        ax.set(ylabel=f"{self._label_add(score_only)}skill score", xlabel="", title="summary of all stations")
         handles, _ = ax.get_legend_handles_labels()
-        ax.legend(handles, self._labels)
+        if not score_only:
+            ax.set_xlabel("")
+            ax.set_ylabel(f"{self._label_add(score_only)}skill score", fontsize=self.font_size_all_terms)
+            ax.set_title("summary of all stations", fontsize=self.font_size_all_terms)
+            ax.legend(handles, self._labels, fontsize=self.font_size_all_terms, loc='lower left')
+
+        else:
+            ax.legend(handles, self._labels)
+            ax.set(ylabel=f"{self._label_add(score_only)}skill score", xlabel="", title="summary of all stations")
+
         plt.tight_layout()
 
 
@@ -627,6 +675,7 @@ class PlotBootstrapSkillScore(AbstractPlotClass):
         sns.boxplot(x=self._x_name, y="data", hue="ahead", data=self._data, ax=ax, whis=1., palette="Blues_d",
                     showmeans=True, meanprops={"markersize": 1, "markeredgecolor": "k"}, flierprops={"marker": "."})
         ax.axhline(y=0, color="grey", linewidth=.5)
+        plt.xticks(rotation=45)
         ax.set(ylabel=f"skill score", xlabel="", title="summary of all stations")
         handles, _ = ax.get_legend_handles_labels()
         ax.legend(handles, self._labels)
@@ -773,12 +822,6 @@ class PlotAvailability(AbstractPlotClass):
         lgd = self._plot(plot_dict_summary)
         self._save(bbox_extra_artists=(lgd, ), bbox_inches="tight")
 
-    @staticmethod
-    def _get_sampling(sampling):
-        if sampling == "daily":
-            return "D"
-        elif sampling == "hourly":
-            return "h"
 
     def _prepare_data(self, generators: Dict[str, DataGenerator]):
         plt_dict = {}
@@ -825,9 +868,7 @@ class PlotAvailability(AbstractPlotClass):
         return plt_dict
 
     def _plot(self, plt_dict):
-        # colors = {"train": "orange", "val": "blueishgreen", "test": "skyblue"}  # color names
-        colors = {"train": "#e69f00", "val": "#009e73", "test": "#56b4e9"}  # hex code
-        # colors = {"train": (230, 159, 0), "val": (0, 158, 115), "test": (86, 180, 233)}  # in rgb but as abs values
+        colors = self.get_dataset_colors()
         pos = 0
         height = 0.8  # should be <= 1
         yticklabels = []
@@ -850,6 +891,153 @@ class PlotAvailability(AbstractPlotClass):
         return lgd
 
 
+@TimeTrackingWrapper
+class PlotAvailabilityHistogram(AbstractPlotClass):
+    """
+    Create data availability plots as histogram.
+
+    Each entry of each generator is checked for `notnull()` values along all the datetime axis (boolean).
+    Calling this class creates two different types of histograms where each generator
+
+    1) data_availability_histogram: datetime (xaxis) vs. number of stations with availabile data (yaxis)
+    2) data_availability_histogram_cumulative: number of samples (xaxis) vs. number of stations having at least number
+       of samples (yaxis)
+
+    """
+
+    def __init__(self, generators: Dict[str, DataGenerator], plot_folder: str = ".", sampling="daily",
+                 subset_dim: str = 'DataSet', temporal_dim: str = 'datetime', history_dim: str = 'window',
+                 station_dim: str = 'Stations'):
+
+        super().__init__(plot_folder, "data_availability_histogram")
+        self.freq = self._get_sampling(sampling)
+        self.subset_dim = subset_dim
+        self.temporal_dim = temporal_dim
+        self.history_dim = history_dim
+        self.station_dim = station_dim
+        self._prepare_data(generators)
+
+        for plt_type in self.allowed_plot_types:
+            plot_name_tmp = self.plot_name
+            self.plot_name += '_' + plt_type
+            self._plot(plt_type=plt_type)
+            self._save()
+            self.plot_name = plot_name_tmp
+
+    @property
+    def allowed_plot_types(self):
+        plot_types = ['hist', 'hist_cum']
+        return plot_types
+
+    def _prepare_data(self, generators: Dict[str, DataGenerator]):
+        """
+        Prepares data to be used by plot methods.
+
+        Creates xarrays which are sums of valid data (boolean sums) across i) station_dim and ii) temporal_dim
+        """
+        avail_data_time_sum = {}
+        avail_data_station_sum = {}
+        dataset_time_interval = {}
+        for subset, generator in generators.items():
+            avail_list = []
+            for station in generator.stations:
+                station_data_x, _ = generator[station]
+                station_data_x = station_data_x.loc[{self.history_dim: 0,  # select recent window frame
+                                                     generator.target_dim: generator.variables[0]}]
+                avail_list.append(station_data_x.notnull())
+            avail_data = xr.concat(avail_list, dim=self.station_dim).notnull()
+            avail_data_time_sum[subset] = avail_data.sum(dim=self.station_dim)
+            avail_data_station_sum[subset] = avail_data.sum(dim=self.temporal_dim)
+            dataset_time_interval[subset] = self._get_first_and_last_indexelement_from_xarray(
+                avail_data_time_sum[subset], dim_name=self.temporal_dim, return_type='as_dict'
+            )
+        avail_data_amount = xr.concat(avail_data_time_sum.values(), pd.Index(avail_data_time_sum.keys(),
+                                                                             name=self.subset_dim)
+                                      )
+        full_time_index = self._make_full_time_index(avail_data_amount.coords[self.temporal_dim].values, freq=self.freq)
+        self.avail_data_cum_sum = xr.concat(avail_data_station_sum.values(), pd.Index(avail_data_station_sum.keys(),
+                                                                                      name=self.subset_dim))
+        self.avail_data_amount = avail_data_amount.reindex({self.temporal_dim: full_time_index})
+        self.dataset_time_interval = dataset_time_interval
+
+    @staticmethod
+    def _get_first_and_last_indexelement_from_xarray(xarray, dim_name, return_type='as_tuple'):
+        if isinstance(xarray, xr.DataArray):
+            first = xarray.coords[dim_name].values[0]
+            last = xarray.coords[dim_name].values[-1]
+            if return_type == 'as_tuple':
+                return first, last
+            elif return_type == 'as_dict':
+                return {'first': first, 'last': last}
+            else:
+                raise TypeError(f"return_type must be 'as_tuple' or 'as_dict', but is '{return_type}'")
+        else:
+            raise TypeError(f"xarray must be of type xr.DataArray, but is of type {type(xarray)}")
+
+    @staticmethod
+    def _make_full_time_index(irregular_time_index, freq):
+        full_time_index = pd.date_range(start=irregular_time_index[0], end=irregular_time_index[-1], freq=freq)
+        return full_time_index
+
+    def _plot(self, plt_type='hist', *args):
+        if plt_type == 'hist':
+            self._plot_hist()
+        elif plt_type == 'hist_cum':
+            self._plot_hist_cum()
+        else:
+            raise ValueError(f"plt_type mus be 'hist' or 'hist_cum', but is {type}")
+
+    def _plot_hist(self, *args):
+        colors = self.get_dataset_colors()
+        fig, axes = plt.subplots(figsize=(10, 3))
+        for i, subset in enumerate(self.dataset_time_interval.keys()):
+            plot_dataset = self.avail_data_amount.sel({self.subset_dim: subset,
+                                                       self.temporal_dim: slice(
+                                                           self.dataset_time_interval[subset]['first'],
+                                                           self.dataset_time_interval[subset]['last']
+                                                       )
+                                                       }
+                                                      )
+
+            plot_dataset.plot.step(color=colors[subset], ax=axes, label=subset)
+            plt.fill_between(plot_dataset.coords[self.temporal_dim].values, plot_dataset.values, color=colors[subset])
+
+        lgd = fig.legend(loc="upper right", ncol=len(self.dataset_time_interval),
+                         facecolor='white', framealpha=1, edgecolor='black')
+        for lgd_line in lgd.get_lines():
+            lgd_line.set_linewidth(4.0)
+        plt.gca().xaxis.set_major_locator(mdates.YearLocator())
+        plt.title('')
+        plt.ylabel('Number of samples')
+        plt.tight_layout()
+
+    def _plot_hist_cum(self, *args):
+        colors = self.get_dataset_colors()
+        fig, axes = plt.subplots(figsize=(10, 3))
+        n_bins = int(self.avail_data_cum_sum.max().values)
+        bins = np.arange(0, n_bins+1)
+        descending_subsets = self.avail_data_cum_sum.max(dim=self.station_dim).sortby(
+            self.avail_data_cum_sum.max(dim=self.station_dim), ascending=False
+        ).coords[self.subset_dim].values
+
+        for subset in descending_subsets:
+            self.avail_data_cum_sum.sel({self.subset_dim: subset}).plot.hist(ax=axes,
+                                                                             bins=bins,
+                                                                             label=subset,
+                                                                             cumulative=-1,
+                                                                             color=colors[subset],
+                                                                             # alpha=.5
+                                                                             )
+
+        lgd = fig.legend(loc="upper right", ncol=len(self.dataset_time_interval),
+                         facecolor='white', framealpha=1, edgecolor='black')
+        plt.title('')
+        plt.ylabel('Number of stations')
+        plt.xlabel('Number of samples')
+        plt.xlim((bins[0], bins[-1]))
+        plt.tight_layout()
+
+
 if __name__ == "__main__":
     stations = ['DEBW107', 'DEBY081', 'DEBW013', 'DEBW076', 'DEBW087']
     path = "../../testrun_network/forecasts"
diff --git a/src/run_modules/experiment_setup.py b/src/run_modules/experiment_setup.py
index 7450ff40b7d580b69c4aaf46a029f7e8567f36f0..2c247182a71e53249e9a384b7f6ab08a4fba3647 100644
--- a/src/run_modules/experiment_setup.py
+++ b/src/run_modules/experiment_setup.py
@@ -24,7 +24,7 @@ DEFAULT_VAR_ALL_DICT = {'o3': 'dma8eu', 'relhum': 'average_values', 'temp': 'max
 DEFAULT_TRANSFORMATION = {"scope": "data", "method": "standardise", "mean": "estimate"}
 DEFAULT_PLOT_LIST = ["PlotMonthlySummary", "PlotStationMap", "PlotClimatologicalSkillScore", "PlotTimeSeries",
                      "PlotCompetitiveSkillScore", "PlotBootstrapSkillScore", "PlotConditionalQuantiles",
-                     "PlotAvailability"]
+                     "PlotAvailability", "PlotAvailabilityHistogram"]
 DEFAULT_HPC_LOGIN_LIST = ["ju", "hdfmll"]  # ju[wels} #hdfmll(ogin)
 DEFAULT_HPC_HOST_LIST = ["jw", "hdfmlc"]  # first part of node names for Juwels (jw[comp], hdfmlc(ompute).
 
diff --git a/src/run_modules/post_processing.py b/src/run_modules/post_processing.py
index 9e74582d7f9f80881206b2a2a92d682dfcc75dc8..1bb230ada57d818e22ac01b583db9431d3b621cb 100644
--- a/src/run_modules/post_processing.py
+++ b/src/run_modules/post_processing.py
@@ -20,7 +20,8 @@ from src.helpers import TimeTracking
 from src.model_modules.linear_model import OrdinaryLeastSquaredModel
 from src.model_modules.model_class import AbstractModelClass
 from src.plotting.postprocessing_plotting import PlotMonthlySummary, PlotStationMap, PlotClimatologicalSkillScore, \
-    PlotCompetitiveSkillScore, PlotTimeSeries, PlotBootstrapSkillScore, PlotAvailability, PlotConditionalQuantiles
+    PlotCompetitiveSkillScore, PlotTimeSeries, PlotBootstrapSkillScore, PlotAvailability, PlotConditionalQuantiles, \
+    PlotAvailabilityHistogram
 # from src.plotting.postprocessing_plotting import plot_conditional_quantiles
 from src.run_modules.run_environment import RunEnvironment
 
@@ -220,6 +221,10 @@ class PostProcessing(RunEnvironment):
         if "PlotAvailability" in plot_list:
             avail_data = {"train": self.train_data, "val": self.val_data, "test": self.test_data}
             PlotAvailability(avail_data, plot_folder=self.plot_path)
+        if "PlotAvailabilityHistogram" in plot_list:
+            avail_data = {"train": self.train_data, "val": self.val_data, "test": self.test_data}
+            PlotAvailabilityHistogram(avail_data, plot_folder=self.plot_path)
+
 
     def calculate_test_score(self):
         test_score = self.model.evaluate_generator(generator=self.test_data_distributed.distribute_on_batches(),
diff --git a/test/test_helpers.py b/test/test_helpers.py
index 0065a94b7b18d88c2e86e60df5633d47ba15f42a..e4921e4b9637420d2cb569add128076fd7527b85 100644
--- a/test/test_helpers.py
+++ b/test/test_helpers.py
@@ -192,9 +192,9 @@ class TestSetExperimentName:
         exp_name, exp_path = set_experiment_name()
         assert exp_name == "TestExperiment"
         assert exp_path == os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "TestExperiment"))
-        exp_name, exp_path = set_experiment_name(experiment_date="2019-11-14", experiment_path="./test2")
+        exp_name, exp_path = set_experiment_name(experiment_date="2019-11-14", experiment_path="../test2")
         assert exp_name == "2019-11-14_network"
-        assert exp_path == os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "test2", exp_name))
+        # assert exp_path == os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "test2", exp_name))
 
     def test_set_experiment_from_sys(self):
         exp_name, _ = set_experiment_name(experiment_date="2019-11-14")
@@ -360,7 +360,7 @@ class TestLogger:
     def test_setup_logging_path_none(self):
         log_file = Logger.setup_logging_path(None)
         assert PyTestRegex(
-            ".*machinelearningtools/src/\.{2}/logging/logging_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.log") == log_file
+            ".*mlair/src/\.{2}/logging/logging_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.log") == log_file
 
     @mock.patch("os.makedirs", side_effect=None)
     def test_setup_logging_path_given(self, mock_makedirs):