diff --git a/src/plotting/postprocessing_plotting.py b/src/plotting/postprocessing_plotting.py
index 03f0c5c5c12fd22e7bcb349662adc6c3e3154549..b1434cd52d9b98586631228153e04e426d7d2a4c 100644
--- a/src/plotting/postprocessing_plotting.py
+++ b/src/plotting/postprocessing_plotting.py
@@ -91,45 +91,65 @@ class PlotMonthlySummary(RunEnvironment):
                          meanprops={'markersize': 1, 'markeredgecolor': 'k'})
         ax.set(xlabel='month', ylabel=f'{target_var}')
         plt.tight_layout()
+        self._save(plot_folder)
+
+    @staticmethod
+    def _save(plot_folder):
         plot_name = os.path.join(os.path.abspath(plot_folder), 'monthly_summary_box_plot.pdf')
         logging.debug(f"... save plot to {plot_name}")
         plt.savefig(plot_name, dpi=500)
         plt.close('all')
 
 
-def plot_station_map(generators: Dict, plot_folder: str = "."):
+class PlotStationMap(RunEnvironment):
     """
     Plot geographical overview of all used stations. Different data sets can be colorised by its key in the input
     dictionary generators. The key represents the color to plot on the map. Currently, there is only a white background,
     but this can be adjusted by loading locally stored topography data (not implemented yet). The plot is saved under
     plot_path with the name station_map.pdf
-    :param generators: dictionary with the plot color of each data set as key and the generator containing all stations
-        as value.
-    :param plot_folder: path to save the plot (default: current directory)
     """
-    logging.debug("run station_map()")
-    fig = plt.figure(figsize=(10, 5))
-    ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
-    ax.set_extent([0, 20, 42, 58], crs=ccrs.PlateCarree())
-    ax.add_feature(cfeature.COASTLINE.with_scale("10m"), edgecolor='black')
-    ax.add_feature(cfeature.LAKES.with_scale("50m"))
-    ax.add_feature(cfeature.OCEAN.with_scale("50m"))
-    ax.add_feature(cfeature.RIVERS.with_scale("10m"))
-    ax.add_feature(cfeature.BORDERS.with_scale("10m"), facecolor='none', edgecolor='black')
-
-    if generators is not None:
-        for color, gen in generators.items():
-            for k, v in enumerate(gen):
-                station_coords = gen.get_data_generator(k).meta.loc[['station_lon', 'station_lat']]
-                # station_names = gen.get_data_generator(k).meta.loc[['station_id']]
-                IDx, IDy = float(station_coords.loc['station_lon'].values), float(
-                    station_coords.loc['station_lat'].values)
-                ax.plot(IDx, IDy, mfc=color, mec='k', marker='s', markersize=6, transform=ccrs.PlateCarree())
-
-    plot_name = os.path.join(os.path.abspath(plot_folder), 'station_map.pdf')
-    logging.debug(f"... save plot to {plot_name}")
-    plt.savefig(plot_name, dpi=500)
-    plt.close('all')
+    def __init__(self, generators: Dict, plot_folder: str = "."):
+        """
+        Sets attributes and create plot
+        :param generators: dictionary with the plot color of each data set as key and the generator containing all stations
+        as value.
+        :param plot_folder: path to save the plot (default: current directory)
+        """
+        super().__init__()
+        self._ax = None
+        self._plot(generators, plot_folder)
+
+    def _draw_background(self):
+        self._ax.add_feature(cfeature.COASTLINE.with_scale("10m"), edgecolor='black')
+        self._ax.add_feature(cfeature.LAKES.with_scale("50m"))
+        self._ax.add_feature(cfeature.OCEAN.with_scale("50m"))
+        self._ax.add_feature(cfeature.RIVERS.with_scale("10m"))
+        self._ax.add_feature(cfeature.BORDERS.with_scale("10m"), facecolor='none', edgecolor='black')
+
+    def _plot_stations(self, generators):
+        if generators is not None:
+            for color, gen in generators.items():
+                for k, v in enumerate(gen):
+                    station_coords = gen.get_data_generator(k).meta.loc[['station_lon', 'station_lat']]
+                    # station_names = gen.get_data_generator(k).meta.loc[['station_id']]
+                    IDx, IDy = float(station_coords.loc['station_lon'].values), float(
+                        station_coords.loc['station_lat'].values)
+                    self._ax.plot(IDx, IDy, mfc=color, mec='k', marker='s', markersize=6, transform=ccrs.PlateCarree())
+
+    def _plot(self, generators, plot_folder):
+        fig = plt.figure(figsize=(10, 5))
+        self._ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
+        self._ax.set_extent([0, 20, 42, 58], crs=ccrs.PlateCarree())
+        self._draw_background()
+        self._plot_stations(generators)
+        self._save(plot_folder)
+
+    @staticmethod
+    def _save(plot_folder):
+        plot_name = os.path.join(os.path.abspath(plot_folder), 'station_map.pdf')
+        logging.debug(f"... save plot to {plot_name}")
+        plt.savefig(plot_name, dpi=500)
+        plt.close('all')
 
 
 def plot_conditional_quantiles(stations: list, plot_folder: str = ".", rolling_window: int = 3, ref_name: str = 'orig',
@@ -267,76 +287,108 @@ def plot_conditional_quantiles(stations: list, plot_folder: str = ".", rolling_w
     logging.info(f"plot_conditional_quantiles() finished after {time}")
 
 
-def plot_climatological_skill_score(data: Dict, plot_folder: str = ".", score_only: bool = True,
-                                    extra_name_tag: str = "", model_setup: str = ""):
+class PlotClimatologicalSkillScore(RunEnvironment):
     """
     Create plot of climatological skill score after Murphy (1988) as box plot over all stations. A forecast time step
     (called "ahead") is separately shown to highlight the differences for each prediction time step. Either each single
     term is plotted (score_only=False) or only the resulting scores CASE I to IV are displayed (score_only=True,
     default). Y-axis is adjusted following the data and not hard coded. The plot is saved under plot_folder path with
     name skill_score_clim_{extra_name_tag}{model_setup}.pdf and resolution of 500dpi.
-    :param data: dictionary with station names as keys and 2D xarrays as values, consist on axis ahead and terms.
-    :param plot_folder: path to save the plot (default: current directory)
-    :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 (default "CNN")
     """
-    logging.debug("run plot_climatological_skill_score()")
-    data = helpers.dict_to_xarray(data, "station")
-    labels = [str(i) + "d" for i in data.coords["ahead"].values]
-    fig, ax = plt.subplots()
-    if score_only:
-        data = data.loc[:, ["CASE I", "CASE II", "CASE III", "CASE IV"], :]
-        lab_add = ''
-    else:
-        fig.set_size_inches(11.7, 8.27)
-        lab_add = "terms and "
-    data = data.to_dataframe("data").reset_index(level=[0, 1, 2])
-    sns.boxplot(x="terms", y="data", hue="ahead", data=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"{lab_add}skill score", xlabel="", title="summary of all stations")
-    handles, _ = ax.get_legend_handles_labels()
-    ax.legend(handles, labels)
-    plt.tight_layout()
-    plot_name = os.path.join(plot_folder, f"skill_score_clim_{extra_name_tag}{model_setup}.pdf")
-    logging.debug(f"... save plot to {plot_name}")
-    plt.savefig(plot_name, dpi=500)
-    plt.close('all')
+    def __init__(self, data: Dict, plot_folder: str = ".", score_only: bool = True, extra_name_tag: str = "",
+                 model_setup: str = ""):
+        """
+        Sets attributes and create plot
+        :param data: dictionary with station names as keys and 2D xarrays as values, consist on axis ahead and terms.
+        :param plot_folder: path to save the plot (default: current directory)
+        :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 (default "CNN")
+        """
+        super().__init__()
+        self._labels = None
+        self._data = self._process_data(data, score_only)
+        self._plot(plot_folder, score_only, extra_name_tag, model_setup)
+
+    def _process_data(self, data, score_only):
+        data = helpers.dict_to_xarray(data, "station")
+        self._labels = [str(i) + "d" for i in data.coords["ahead"].values]
+        if score_only:
+            data = data.loc[:, ["CASE I", "CASE II", "CASE III", "CASE IV"], :]
+        return data.to_dataframe("data").reset_index(level=[0, 1, 2])
+
+    def _label_add(self, score_only):
+        return "" if score_only else "terms and "
+
+    def _plot(self, plot_folder, score_only, extra_name_tag, model_setup):
+        fig, ax = plt.subplots()
+        if not score_only:
+            fig.set_size_inches(11.7, 8.27)
+        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)
+        plt.tight_layout()
+        self._save(plot_folder, extra_name_tag, model_setup)
+
+    @staticmethod
+    def _save(plot_folder, extra_name_tag, model_setup):
+        plot_name = os.path.join(plot_folder, f"skill_score_clim_{extra_name_tag}{model_setup}.pdf")
+        logging.debug(f"... save plot to {plot_name}")
+        plt.savefig(plot_name, dpi=500)
+        plt.close('all')
 
 
-def plot_competitive_skill_score(data: pd.DataFrame, plot_folder=".", model_setup="CNN"):
+class PlotCompetitiveSkillScore(RunEnvironment):
     """
     Create competitive skill score for the given model setup and the reference models ordinary least squared ("ols") and
     the persistence forecast ("persi") for all lead times ("ahead"). The plot is saved under plot_folder with the name
     skill_score_competitive_{model_setup}.pdf and resolution of 500dpi.
-    :param data: data frame with index=['cnn-persi', 'ols-persi', 'cnn-ols'] and columns "ahead" containing the pre-
-        calculated comparisons for cnn, persistence and ols.
-    :param plot_folder: path to save the plot (default: current directory)
-    :param model_setup: architecture type (default "CNN")
     """
-    logging.debug("run plot_general_skill_score()")
-
-    data = pd.concat(data, axis=0)
-    data = xr.DataArray(data, dims=["stations", "ahead"]).unstack("stations")
-    data = data.rename({"stations_level_0": "stations", "stations_level_1": "comparison"})
-    data = data.to_dataframe("data").unstack(level=1).swaplevel()
-    data.columns = data.columns.levels[1]
-
-    labels = [str(i) + "d" for i in data.index.levels[1].values]
-    data = data.stack(level=0).reset_index(level=2, drop=True).reset_index(name="data")
-
-    fig, ax = plt.subplots()
-    sns.boxplot(x="comparison", y="data", hue="ahead", data=data, whis=1., ax=ax, palette="Blues_d", showmeans=True,
-                meanprops={"markersize": 3, "markeredgecolor": "k"}, flierprops={"marker": "."},
-                order=["cnn-persi", "ols-persi", "cnn-ols"])
-    ax.axhline(y=0, color="grey", linewidth=.5)
-    ax.set(ylabel="skill score", xlabel="competing models", title="summary of all stations",
-           ylim=(np.min([0, helpers.float_round(data.min()[2], 2) - 0.1]), helpers.float_round(data.max()[2], 2) + 0.1))
-    handles, _ = ax.get_legend_handles_labels()
-    ax.legend(handles, labels)
-    plt.tight_layout()
-    plot_name = os.path.join(plot_folder, f"skill_score_competitive_{model_setup}.pdf")
-    logging.debug(f"... save plot to {plot_name}")
-    plt.savefig(plot_name, dpi=500)
-    plt.close()
+    def __init__(self, data: pd.DataFrame, plot_folder=".", model_setup="CNN"):
+        """
+        :param data: data frame with index=['cnn-persi', 'ols-persi', 'cnn-ols'] and columns "ahead" containing the pre-
+            calculated comparisons for cnn, persistence and ols.
+        :param plot_folder: path to save the plot (default: current directory)
+        :param model_setup: architecture type (default "CNN")
+        """
+        super().__init__()
+        self._labels = None
+        self._data = self._prepare_data(data)
+        self._plot(plot_folder, model_setup)
+
+    def _prepare_data(self, data):
+        data = pd.concat(data, axis=0)
+        data = xr.DataArray(data, dims=["stations", "ahead"]).unstack("stations")
+        data = data.rename({"stations_level_0": "stations", "stations_level_1": "comparison"})
+        data = data.to_dataframe("data").unstack(level=1).swaplevel()
+        data.columns = data.columns.levels[1]
+        self._labels = [str(i) + "d" for i in data.index.levels[1].values]
+        return data.stack(level=0).reset_index(level=2, drop=True).reset_index(name="data")
+
+    def _plot(self, plot_folder, model_setup):
+        fig, ax = plt.subplots()
+        sns.boxplot(x="comparison", y="data", hue="ahead", data=self._data, whis=1., ax=ax, palette="Blues_d",
+                    showmeans=True, meanprops={"markersize": 3, "markeredgecolor": "k"}, flierprops={"marker": "."},
+                    order=["cnn-persi", "ols-persi", "cnn-ols"])
+        ax.axhline(y=0, color="grey", linewidth=.5)
+
+        ax.set(ylabel="skill score", xlabel="competing models", title="summary of all stations", ylim=self._ylim())
+        handles, _ = ax.get_legend_handles_labels()
+        ax.legend(handles, self._labels)
+        plt.tight_layout()
+        self._save(plot_folder, model_setup)
+
+    def _ylim(self):
+        lower = np.min([0, helpers.float_round(self._data.min()[2], 2) - 0.1])
+        upper = helpers.float_round(self._data.max()[2], 2) + 0.1
+        return lower, upper
+
+    @staticmethod
+    def _save(plot_folder, model_setup):
+        plot_name = os.path.join(plot_folder, f"skill_score_competitive_{model_setup}2.pdf")
+        logging.debug(f"... save plot to {plot_name}")
+        plt.savefig(plot_name, dpi=500)
+        plt.close()
diff --git a/src/run_modules/post_processing.py b/src/run_modules/post_processing.py
index c8fde35cb39df00e94aeeb2ca218e6c65c248b54..b935aa8355fe5eba1890d49cd6b7ac3c8a3a87e1 100644
--- a/src/run_modules/post_processing.py
+++ b/src/run_modules/post_processing.py
@@ -15,8 +15,8 @@ from src.data_handling.data_distributor import Distributor
 from src.data_handling.data_generator import DataGenerator
 from src.model_modules.linear_model import OrdinaryLeastSquaredModel
 from src import statistics
-from src.plotting.postprocessing_plotting import plot_station_map, plot_conditional_quantiles, \
-    plot_climatological_skill_score, plot_competitive_skill_score, PlotMonthlySummary
+from src.plotting.postprocessing_plotting import plot_conditional_quantiles
+from src.plotting.postprocessing_plotting import PlotMonthlySummary, PlotStationMap, PlotClimatologicalSkillScore, PlotCompetitiveSkillScore
 from src.datastore import NameNotFoundInDataStore
 
 
@@ -61,14 +61,13 @@ class PostProcessing(RunEnvironment):
                                    forecast_path=path, plot_name_affix="cali-ref", plot_folder=self.plot_path)
         plot_conditional_quantiles(self.test_data.stations, pred_name="orig", ref_name="CNN",
                                    forecast_path=path, plot_name_affix="like-bas", plot_folder=self.plot_path)
-        plot_station_map(generators={'b': self.test_data}, plot_folder=self.plot_path)
+        PlotStationMap(generators={'b': self.test_data}, plot_folder=self.plot_path)
         PlotMonthlySummary(self.test_data.stations, path, r"forecasts_%s_test.nc", target_var,
                            plot_folder=self.plot_path)
-        #
-        plot_climatological_skill_score(self.skill_scores[1], plot_folder=self.plot_path, model_setup="CNN")
-        plot_climatological_skill_score(self.skill_scores[1], plot_folder=self.plot_path, score_only=False,
-                                        extra_name_tag="all_terms_", model_setup="CNN")
-        plot_competitive_skill_score(self.skill_scores[0], plot_folder=self.plot_path, model_setup="CNN")
+        PlotClimatologicalSkillScore(self.skill_scores[1], plot_folder=self.plot_path, model_setup="CNN")
+        PlotClimatologicalSkillScore(self.skill_scores[1], plot_folder=self.plot_path, score_only=False,
+                                     extra_name_tag="all_terms_", model_setup="CNN")
+        PlotCompetitiveSkillScore(self.skill_scores[0], plot_folder=self.plot_path, model_setup="CNN")
 
     def calculate_test_score(self):
         test_score = self.model.evaluate_generator(generator=self.test_data_distributed.distribute_on_batches(),