diff --git a/docs/_source/_plots/conditional_quantiles_cali-ref_plot-2.png b/docs/_source/_plots/conditional_quantiles_cali-ref_plot-2.png
deleted file mode 100644
index bedc075b8cc3bc75e1dabfbbec02cbdb6c69123a..0000000000000000000000000000000000000000
Binary files a/docs/_source/_plots/conditional_quantiles_cali-ref_plot-2.png and /dev/null differ
diff --git a/docs/_source/_plots/conditional_quantiles_cali-ref_plot-3.png b/docs/_source/_plots/conditional_quantiles_cali-ref_plot-3.png
deleted file mode 100644
index ccc454211e5dbf16374ebbee522ea584e24a4fbd..0000000000000000000000000000000000000000
Binary files a/docs/_source/_plots/conditional_quantiles_cali-ref_plot-3.png and /dev/null differ
diff --git a/docs/_source/_plots/conditional_quantiles_cali-ref_plot-1.png b/docs/_source/_plots/conditional_quantiles_cali-ref_plot.png
similarity index 100%
rename from docs/_source/_plots/conditional_quantiles_cali-ref_plot-1.png
rename to docs/_source/_plots/conditional_quantiles_cali-ref_plot.png
diff --git a/docs/_source/_plots/conditional_quantiles_like-bas_plot-2.png b/docs/_source/_plots/conditional_quantiles_like-bas_plot-2.png
deleted file mode 100644
index c851f8f58a33cc2b37917e8964faa65243b3e8a6..0000000000000000000000000000000000000000
Binary files a/docs/_source/_plots/conditional_quantiles_like-bas_plot-2.png and /dev/null differ
diff --git a/docs/_source/_plots/conditional_quantiles_like-bas_plot-3.png b/docs/_source/_plots/conditional_quantiles_like-bas_plot-3.png
deleted file mode 100644
index 302862bc61d881f879a4bb7c860a2a55d46a76af..0000000000000000000000000000000000000000
Binary files a/docs/_source/_plots/conditional_quantiles_like-bas_plot-3.png and /dev/null differ
diff --git a/docs/_source/_plots/conditional_quantiles_like-bas_plot-1.png b/docs/_source/_plots/conditional_quantiles_like-bas_plot.png
similarity index 100%
rename from docs/_source/_plots/conditional_quantiles_like-bas_plot-1.png
rename to docs/_source/_plots/conditional_quantiles_like-bas_plot.png
diff --git a/src/helpers.py b/src/helpers.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/helpers/time_tracking.py b/src/helpers/time_tracking.py
index 3a4dad595d63eec17bc9ba35f08421fd341a3d57..c85a6a047943a589a9d076584ae40186634db767 100644
--- a/src/helpers/time_tracking.py
+++ b/src/helpers/time_tracking.py
@@ -3,6 +3,7 @@ import datetime as dt
 import logging
 import math
 import time
+import types
 from functools import wraps
 from typing import Optional
 
@@ -38,6 +39,10 @@ class TimeTrackingWrapper:
         with TimeTracking(name=self.__wrapped__.__name__):
             return self.__wrapped__(*args, **kwargs)
 
+    def __get__(self, instance, cls):
+        """Create bound method object and supply self argument to the decorated method."""
+        return types.MethodType(self, instance)
+
 
 class TimeTracking(object):
     """
diff --git a/src/plotting/postprocessing_plotting.py b/src/plotting/postprocessing_plotting.py
index 36039073c16e26f430ad607639b8c31e3efb7467..e1bf1c1a59ba308539597087a68b0df493612d6b 100644
--- a/src/plotting/postprocessing_plotting.py
+++ b/src/plotting/postprocessing_plotting.py
@@ -256,10 +256,29 @@ class PlotStationMap(AbstractPlotClass):
 @TimeTrackingWrapper
 class PlotConditionalQuantiles(AbstractPlotClass):
     """
-    This class creates cond.quantile plots as originally proposed by Murphy, Brown and Chen (1989) [But in log scale]
+    Create cond.quantile plots as originally proposed by Murphy, Brown and Chen (1989) [But in log scale].
 
     Link to paper: https://journals.ametsoc.org/doi/pdf/10.1175/1520-0434%281989%29004%3C0485%3ADVOTF%3E2.0.CO%3B2
+
+    .. image:: ../../../../../_source/_plots/conditional_quantiles_cali-ref_plot.png
+        :width: 400
+
+    .. image:: ../../../../../_source/_plots/conditional_quantiles_like-bas_plot.png
+        :width: 400
+
+    For each time step ahead a separate plot is created. If parameter plot_per_season is true, data is split by season
+    and conditional quantiles are plotted for each season in addition.
+
+    :param stations: all stations to plot
+    :param data_pred_path: path to dir which contains the forecasts as .nc files
+    :param plot_folder: path where the plots are stored
+    :param plot_per_seasons: if `True' create cond. quantile plots for _seasons (DJF, MAM, JJA, SON) individually
+    :param rolling_window: smoothing of quantiles (3 is used by Murphy et al.)
+    :param model_mame: name of the model prediction as stored in netCDF file (for example "CNN")
+    :param obs_name: name of observation as stored in netCDF file (for example "obs")
+    :param kwargs: Some further arguments which are listed in self._opts
     """
+
     # ignore warnings if nans appear in quantile grouping
     warnings.filterwarnings("ignore", message="All-NaN slice encountered")
     # ignore warnings if mean is calculated on nans
@@ -269,46 +288,33 @@ class PlotConditionalQuantiles(AbstractPlotClass):
 
     def __init__(self, stations: List, data_pred_path: str, plot_folder: str = ".", plot_per_seasons=True,
                  rolling_window: int = 3, model_mame: str = "CNN", obs_name: str = "obs", **kwargs):
-        """
-
-        :param stations: all stations to plot
-        :param data_pred_path: path to dir which contains the forecasts as .nc files
-        :param plot_folder: path where the plots are stored
-        :param plot_per_seasons: if `True' create cond. quantile plots for seasons (DJF, MAM, JJA, SON) individually
-        :param rolling_window: smoothing of quantiles (3 is used by Murphy et al.)
-        :param model_mame: name of the model prediction as stored in netCDF file (for example "CNN")
-        :param obs_name: name of observation as stored in netCDF file (for example "obs")
-        :param kwargs: Some further arguments which are listed in self._opts
-        """
+        """Initialise."""
         super().__init__(plot_folder, "conditional_quantiles")
-
         self._data_pred_path = data_pred_path
         self._stations = stations
         self._rolling_window = rolling_window
         self._model_name = model_mame
         self._obs_name = obs_name
-
-        self._opts = {"q": kwargs.get("q", [.1, .25, .5, .75, .9]),
-                      "linetype": kwargs.get("linetype", [':', '-.', '--', '-.', ':']),
-                      "legend": kwargs.get("legend",
-                                           ['.10th and .90th quantile', '.25th and .75th quantile', '.50th quantile',
-                                            'reference 1:1']),
-                      "data_unit": kwargs.get("data_unit", "ppb"),
-                      }
-        if plot_per_seasons is True:
-            self.seasons = ['DJF', 'MAM', 'JJA', 'SON']
-        else:
-            self.seasons = ""
+        self._opts = self._get_opts(kwargs)
+        self._seasons = ['DJF', 'MAM', 'JJA', 'SON'] if plot_per_seasons is True else ""
         self._data = self._load_data()
         self._bins = self._get_bins_from_rage_of_data()
-
         self._plot()
 
-    def _load_data(self):
+    @staticmethod
+    def _get_opts(kwargs):
+        """Extract options from kwargs."""
+        return {"q": kwargs.get("q", [.1, .25, .5, .75, .9]),
+                "linetype": kwargs.get("linetype", [':', '-.', '--', '-.', ':']),
+                "legend": kwargs.get("legend", ['.10th and .90th quantile', '.25th and .75th quantile',
+                                                '.50th quantile', 'reference 1:1']),
+                "data_unit": kwargs.get("data_unit", "ppb"), }
+
+    def _load_data(self) -> xr.DataArray:
         """
-        This method loads forcast data
+        Load plot data.
 
-        :return:
+        :return: plot data
         """
         logging.debug("... load data")
         data_collector = []
@@ -319,13 +325,14 @@ class PlotConditionalQuantiles(AbstractPlotClass):
         res = xr.concat(data_collector, dim='station').transpose('index', 'type', 'ahead', 'station')
         return res
 
-    def _segment_data(self, data, x_model):
+    def _segment_data(self, data: xr.DataArray, x_model: str) -> xr.DataArray:
         """
-        This method creates segmented data which is used for cond. quantile plots
+        Segment data into bins.
 
-        :param data:
-        :param x_model:
-        :return:
+        :param data: data to segment
+        :param x_model: name of x dimension
+
+        :return: segmented data
         """
         logging.debug("... segment data")
         # combine index and station to multi index
@@ -334,17 +341,18 @@ class PlotConditionalQuantiles(AbstractPlotClass):
         data.coords['z'] = range(len(data.coords['z']))
         # segment data of x_model into bins
         data.loc[x_model, ...] = data.loc[x_model, ...].to_pandas().T.apply(pd.cut, bins=self._bins,
-                                                                                labels=self._bins[1:]).T.values
+                                                                            labels=self._bins[1:]).T.values
         return data
 
     @staticmethod
-    def _labels(plot_type, data_unit="ppb"):
+    def _labels(plot_type: str, data_unit: str = "ppb") -> Tuple[str, str]:
         """
-        Helper method to correctly assign (x,y) labels to plots, depending on like-base or cali-ref factorization
+        Assign (x,y) labels to plots correctly, depending on like-base or cali-ref factorization.
 
-        :param plot_type:
-        :param data_unit:
-        :return:
+        :param plot_type: type of plot, either `obs` or a model name
+        :param data_unit: unit of data to add to labels (default ppb)
+
+        :return: tuple with y and x labels
         """
         names = (f"forecast concentration (in {data_unit})", f"observed concentration (in {data_unit})")
         if plot_type == "obs":
@@ -352,22 +360,23 @@ class PlotConditionalQuantiles(AbstractPlotClass):
         else:
             return names[::-1]
 
-    def _get_bins_from_rage_of_data(self):
+    def _get_bins_from_rage_of_data(self) -> np.ndarray:
         """
-        Get array of bins to use for quantiles
+        Get array of bins to use for quantiles.
 
-        :return:
+        :return: range from 0 to data's maximum + 1 (rounded down)
         """
         return np.arange(0, math.ceil(self._data.max().max()) + 1, 1).astype(int)
 
-    def _create_quantile_panel(self, data, x_model, y_model):
+    def _create_quantile_panel(self, data: xr.DataArray, x_model: str, y_model: str) -> xr.DataArray:
         """
-        Clculate quantiles
+        Calculate quantiles.
 
-        :param data:
-        :param x_model:
-        :param y_model:
-        :return:
+        :param data: data to calculate quantiles
+        :param x_model: name of x dimension
+        :param y_model: name of y dimension
+
+        :return: quantile panel with binned data
         """
         logging.debug("... create quantile panel")
         # create empty xarray with dims: time steps ahead, quantiles, bin index (numbers create in previous step)
@@ -379,83 +388,69 @@ class PlotConditionalQuantiles(AbstractPlotClass):
         # calculate for each bin of the pred_name data the quantiles of the ref_name data
         for bin in self._bins[1:]:
             mask = (data.loc[x_model, ...] == bin)
-            quantile_panel.loc[..., bin] = data.loc[y_model, ...].where(mask).quantile(self._opts["q"],
-                                                                                                    dim=['z']).T
+            quantile_panel.loc[..., bin] = data.loc[y_model, ...].where(mask).quantile(self._opts["q"], dim=['z']).T
         return quantile_panel
 
     @staticmethod
-    def add_affix(x):
+    def add_affix(affix: str) -> str:
         """
-        Helper method to add additional information on plot name
+        Add additional information to plot name with leading underscore or add empty string if affix is empty.
 
-        :param x:
-        :return:
+        :param affix: string to add
+
+        :return: affix with leading underscore or empty string.
         """
-        return f"_{x}" if len(x) > 0 else ""
+        return f"_{affix}" if len(affix) > 0 else ""
 
-    def _prepare_plots(self, data, x_model, y_model):
+    def _prepare_plots(self, data: xr.DataArray, x_model: str, y_model: str) -> Tuple[xr.DataArray, xr.DataArray]:
         """
-        Get segmented_data and quantile_panel
+        Get segmented data and quantile panel.
 
-        :param data:
-        :param x_model:
-        :param y_model:
-        :return:
+        :param data: plot data
+        :param x_model: name of x dimension
+        :param y_model: name of y dimension
+
+        :return: segmented data and quantile panel
         """
         segmented_data = self._segment_data(data, x_model)
         quantile_panel = self._create_quantile_panel(segmented_data, x_model, y_model)
         return segmented_data, quantile_panel
 
     def _plot(self):
-        """
-        Main plot call
-
-        :return:
-        """
-        logging.info(f"start plotting {self.__class__.__name__}, scheduled number of plots: {(len(self.seasons) + 1) * 2}")
+        """Start plotting routines: overall plot and seasonal (if enabled)."""
+        logging.info(f"start plotting {self.__class__.__name__}, scheduled number of plots: {(len(self._seasons) + 1) * 2}")
 
-        if len(self.seasons) > 0:
+        if len(self._seasons) > 0:
             self._plot_seasons()
         self._plot_all()
 
     def _plot_seasons(self):
-        """
-        Seasonal plot call
-
-        :return:
-        """
-        for season in self.seasons:
+        """Create seasonal plots."""
+        for season in self._seasons:
             self._plot_base(data=self._data.where(self._data['index.season'] == season), x_model=self._model_name,
                             y_model=self._obs_name, plot_name_affix="cali-ref", season=season)
             self._plot_base(data=self._data.where(self._data['index.season'] == season), x_model=self._obs_name,
                             y_model=self._model_name, plot_name_affix="like-base", season=season)
 
     def _plot_all(self):
-        """
-        Full plot call
-
-        :return:
-        """
+        """Plot overall conditional quantiles on full data."""
         self._plot_base(data=self._data, x_model=self._model_name, y_model=self._obs_name, plot_name_affix="cali-ref")
         self._plot_base(data=self._data, x_model=self._obs_name, y_model=self._model_name, plot_name_affix="like-base")
 
     @TimeTrackingWrapper
-    def _plot_base(self, data, x_model, y_model, plot_name_affix, season=""):
+    def _plot_base(self, data: xr.DataArray, x_model: str, y_model: str, plot_name_affix: str, season: str = ""):
         """
-        Base method to create cond. quantile plots. Is called from _plot_all and _plot_seasonal
+        Create conditional quantile plots.
 
         :param data: data which is used to create cond. quantile plot
         :param x_model: name of model on x axis (can also be obs)
         :param y_model: name of model on y axis (can also be obs)
         :param plot_name_affix: should be `cali-ref' or `like-base'
-        :param season: List of seasons to use
-        :return:
+        :param season: List of _seasons to use
         """
-
         segmented_data, quantile_panel = self._prepare_plots(data, x_model, y_model)
         ylabel, xlabel = self._labels(x_model, self._opts["data_unit"])
         plot_name = f"{self.plot_name}{self.add_affix(season)}{self.add_affix(plot_name_affix)}_plot.pdf"
-        #f"{base_name}{add_affix(season)}{add_affix(plot_name_affix)}_plot.pdf"
         plot_path = os.path.join(os.path.abspath(self.plot_folder), plot_name)
         pdf_pages = matplotlib.backends.backend_pdf.PdfPages(plot_path)
         logging.debug(f"... plot path is {plot_path}")