diff --git a/mlair/helpers/helpers.py b/mlair/helpers/helpers.py
index 7911a572d25e58b96007ab26b35a3eff153acf88..0b97f826ee34a35dc62313ed9350919a94931e62 100644
--- a/mlair/helpers/helpers.py
+++ b/mlair/helpers/helpers.py
@@ -123,7 +123,7 @@ def float_round(number: float, decimals: int = 0, round_type: Callable = math.ce
     return round_type(number * multiplier) / multiplier
 
 
-def relative_round(x: float, sig: int) -> float:
+def relative_round(x: float, sig: int, ceil=False, floor=False) -> float:
     """
     Round small numbers according to given "significance".
 
@@ -135,7 +135,26 @@ def relative_round(x: float, sig: int) -> float:
     :return: rounded number
     """
     assert sig >= 1
-    return round(x, sig-int(np.floor(np.log10(abs(x))))-1)
+    assert not (ceil and floor)
+    if x == 0:
+        return 0
+    else:
+        rounded_number = round(x, sig-get_order(x)-1)
+        if floor is True and rounded_number > round(x, sig-get_order(x)):
+            res = rounded_number - 10 ** (get_order(x) - sig + 1)
+        elif ceil is True and rounded_number < round(x, sig-get_order(x)):
+            res = rounded_number + 10 ** (get_order(x) - sig + 1)
+        else:
+            res = rounded_number
+        return round(res, sig-get_order(res)-1)
+
+
+def get_order(x: float):
+    """Get order of number (as power of 10)"""
+    if x == 0:
+        return -np.inf
+    else:
+        return int(np.floor(np.log10(abs(x))))
 
 
 def remove_items(obj: Union[List, Dict, Tuple], items: Any):
diff --git a/mlair/plotting/abstract_plot_class.py b/mlair/plotting/abstract_plot_class.py
index a26023bb6cb8772623479491ac8bcc731dd42223..377dc6b7abbbb693c9d18175983101e622063a70 100644
--- a/mlair/plotting/abstract_plot_class.py
+++ b/mlair/plotting/abstract_plot_class.py
@@ -92,11 +92,10 @@ class AbstractPlotClass:  # pragma: no cover
         plt.rcParams.update(self.rc_params)
 
     @staticmethod
-    def _get_sampling(sampling):
-        if sampling == "daily":
-            return "D"
-        elif sampling == "hourly":
-            return "h"
+    def _get_sampling(sampling, pos=1):
+        sampling = (sampling, sampling) if isinstance(sampling, str) else sampling
+        sampling_letter = {"hourly": "H", "daily": "d"}.get(sampling[pos], "")
+        return sampling, sampling_letter
 
     @staticmethod
     def get_dataset_colors():
diff --git a/mlair/plotting/data_insight_plotting.py b/mlair/plotting/data_insight_plotting.py
index db2b3340e06545f988c81503df2aa27b655095bb..d33f3abb2e2cd04399a2d98f34bf2ed06acfcb6b 100644
--- a/mlair/plotting/data_insight_plotting.py
+++ b/mlair/plotting/data_insight_plotting.py
@@ -188,7 +188,7 @@ class PlotAvailability(AbstractPlotClass):  # pragma: no cover
         super().__init__(plot_folder, "data_availability")
         self.time_dim = time_dimension
         self.window_dim = window_dimension
-        self.sampling = self._get_sampling(sampling)
+        self.sampling = self._get_sampling(sampling)[1]
         self.linewidth = None
         if self.sampling == 'h':
             self.linewidth = 0.001
@@ -321,7 +321,7 @@ class PlotAvailabilityHistogram(AbstractPlotClass):  # pragma: no cover
     def _set_dims_from_datahandler(self, data_handler):
         self.temporal_dim = data_handler.id_class.time_dim
         self.target_dim = data_handler.id_class.target_dim
-        self.freq = self._get_sampling(data_handler.id_class.sampling)
+        self.freq = self._get_sampling(data_handler.id_class.sampling)[1]
 
     @property
     def allowed_plot_types(self):
diff --git a/mlair/plotting/postprocessing_plotting.py b/mlair/plotting/postprocessing_plotting.py
index fc3aa055679b2ad1f03719c6300b59f7ca2371c2..d1a68896edf0b794b644bc325014efb4c7fe785f 100644
--- a/mlair/plotting/postprocessing_plotting.py
+++ b/mlair/plotting/postprocessing_plotting.py
@@ -11,6 +11,7 @@ import itertools
 
 import matplotlib
 import matplotlib.pyplot as plt
+import matplotlib.colors as colors
 import numpy as np
 import pandas as pd
 import seaborn as sns
@@ -23,6 +24,7 @@ from scipy.stats import mannwhitneyu
 from mlair import helpers
 from mlair.data_handler.iterator import DataCollection
 from mlair.helpers import TimeTrackingWrapper
+from mlair.helpers.helpers import relative_round
 from mlair.plotting.abstract_plot_class import AbstractPlotClass
 from mlair.helpers.statistics import mann_whitney_u_test, represent_p_values_as_asteriks
 
@@ -132,8 +134,7 @@ class PlotMonthlySummary(AbstractPlotClass):  # pragma: no cover
         """
         data = self._data.to_dataset(name='values').to_dask_dataframe()
         logging.debug("... start plotting")
-        color_palette = [matplotlib.colors.cnames["green"]] + sns.color_palette("Blues_d",
-                                                                                self._window_lead_time).as_hex()
+        color_palette = [colors.cnames["green"]] + sns.color_palette("Blues_d", self._window_lead_time).as_hex()
         ax = sns.boxplot(x='index', y='values', hue='ahead', data=data.compute(), whis=1.5, palette=color_palette,
                          flierprops={'marker': '.', 'markersize': 1}, showmeans=True,
                          meanprops={'markersize': 1, 'markeredgecolor': 'k'})
@@ -747,19 +748,13 @@ class PlotFeatureImportanceSkillScore(AbstractPlotClass):  # pragma: no cover
                 data = data.assign_coords({self._x_name: new_boot_coords})
             except NotImplementedError:
                 pass
-        _, sampling_letter = self._get_target_sampling(sampling, 1)
+        _, sampling_letter = self._get_sampling(sampling, 1)
         self._labels = [str(i) + sampling_letter for i in data.coords[self._ahead_dim].values]
         if station_dim not in data.dims:
             data = data.expand_dims(station_dim)
         self._number_of_bootstraps = np.unique(data.coords[self._boot_dim].values).shape[0]
         return data.to_dataframe("data").reset_index(level=np.arange(len(data.dims)).tolist()).dropna()
 
-    @staticmethod
-    def _get_target_sampling(sampling, pos):
-        sampling = (sampling, sampling) if isinstance(sampling, str) else sampling
-        sampling_letter = {"hourly": "H", "daily": "d"}.get(sampling[pos], "")
-        return sampling, sampling_letter
-
     def _return_vars_without_number_tag(self, values, split_by, keep, as_unique=False):
         arr = np.array([v.split(split_by) for v in values])
         num = arr[:, 0]
@@ -1044,7 +1039,7 @@ class PlotTimeSeries:  # pragma: no cover
     def _plot_obs(self, ax, data):
         ahead = 1
         obs_data = data.sel(type="obs", ahead=ahead).shift(index=ahead)
-        ax.plot(obs_data, color=matplotlib.colors.cnames["green"], label="obs")
+        ax.plot(obs_data, color=colors.cnames["green"], label="obs")
 
     @staticmethod
     def _get_time_range(data):
@@ -1461,12 +1456,6 @@ class PlotSeasonalMSEStack(AbstractPlotClass):
         season_share = xr_data.sel({season_dim: "total"}) * factor
         return season_share.sortby(season_share.sum([self.season_dim, self.ahead_dim])).transpose(*self.dim_order)
 
-    @staticmethod
-    def _get_target_sampling(sampling, pos):
-        sampling = (sampling, sampling) if isinstance(sampling, str) else sampling
-        sampling_letter = {"hourly": "H", "daily": "d"}.get(sampling[pos], "")
-        return sampling, sampling_letter
-
     @staticmethod
     def _set_bar_label(ax):
         opts = {}
@@ -1480,7 +1469,7 @@ class PlotSeasonalMSEStack(AbstractPlotClass):
             ax.bar_label(c, labels=_l, label_type='center')
 
     def _plot(self, dim, split_ahead=True, sampling="daily", orientation="vertical"):
-        _, sampling_letter = self._get_target_sampling(sampling, 1)
+        _, sampling_letter = self._get_sampling(sampling, 1)
         if split_ahead is False:
             self.plot_name = self.plot_name_orig + "_total_" + orientation
             data = self._data.mean(dim)
@@ -1528,9 +1517,246 @@ class PlotSeasonalMSEStack(AbstractPlotClass):
                 fig.tight_layout(rect=[0, 0, 1, 0.95])
 
 
-if __name__ == "__main__":
-    stations = ['DEBW107', 'DEBY081', 'DEBW013', 'DEBW076', 'DEBW087']
-    path = "../../testrun_network/forecasts"
-    plt_path = "../../"
+@TimeTrackingWrapper
+class PlotErrorsOnMap(AbstractPlotClass):
+    from mlair.plotting.data_insight_plotting import PlotStationMap
+
+    def __init__(self, data_gen, errors, error_metric, plot_folder: str = ".", iter_dim: str = "station",
+                 model_type_dim: str = "type", ahead_dim: str = "ahead", sampling: str = "daily"):
+
+        super().__init__(plot_folder, f"map_plot_{error_metric}")
+        plot_path = os.path.join(self.plot_folder, f"{self.plot_name}.pdf")
+        pdf_pages = matplotlib.backends.backend_pdf.PdfPages(plot_path)
+        error_metric_units = helpers.statistics.get_error_metrics_units("ppb")[error_metric]
+        error_metric_name = helpers.statistics.get_error_metrics_long_name()[error_metric]
+        self.sampling = self._get_sampling(sampling, 1)[1]
+
+        coords = self._extract_coords(data_gen)
+        for split_ahead in [False, True]:
+            error_data = {}
+            for model_type in errors.coords[model_type_dim].values:
+                error_data[model_type] = self._prepare_data(errors, model_type_dim, model_type, ahead_dim, error_metric,
+                                                            split_ahead=split_ahead)
+            limits = self._calculate_limits(error_data)
+            for model_type, error in error_data.items():
+                if split_ahead is True:
+                    for ahead in error.index.unique(1).to_list():
+                        error_ahead = error.query(f"{ahead_dim} == {ahead}").droplevel(1)
+                        plot_data = pd.concat([coords, error_ahead], axis=1)
+                        self.plot(plot_data, error_metric, error_metric_name, error_metric_units, model_type, limits,
+                                  ahead=ahead)
+                        pdf_pages.savefig()
+                else:
+                    plot_data = pd.concat([coords, error], axis=1)
+                    self.plot(plot_data, error_metric, error_metric_name, error_metric_units, model_type, limits)
+                    pdf_pages.savefig()
+        pdf_pages.close()
+        plt.close('all')
+
+    @staticmethod
+    def _calculate_limits(data):
+        vmin, vmax = np.inf, -np.inf
+        for v in data.values():
+            vmin = min(vmin, v.min().values)
+            vmax = max(vmax, v.max().values)
+        return relative_round(float(vmin), 2, floor=True), relative_round(float(vmax), 2, ceil=True)
+
+    @staticmethod
+    def _set_bounds(limits, ncolors, error_metric):
+        bound_lims = {"ioa": [0, 1], "mnmb": [-2, 2]}.get(error_metric, limits)
+        vmin = relative_round(bound_lims[0], 2, floor=True)
+        vmax = relative_round(bound_lims[1], 2, ceil=True)
+        interval = relative_round((vmax - vmin) / ncolors, 1, ceil=True)
+        bounds = np.sort(np.arange(vmax, vmin, -interval))
+        return bounds
+
+    @staticmethod
+    def _get_colorpalette(error_metric):
+        # cmap = matplotlib.cm.coolwarm
+        # cmap = sns.color_palette("magma_r", as_cmap=True)
+        # cmap="Spectral_r", cmap="RdYlBu_r", cmap="coolwarm",
+        # cmap = sns.cubehelix_palette(8, start=2, rot=0, dark=0, light=.95, as_cmap=True)
+        if error_metric == "mnmb":
+            cmap = sns.mpl_palette("coolwarm", as_cmap=True)
+        elif error_metric == "ioa":
+            cmap = sns.mpl_palette("coolwarm_r", as_cmap=True)
+        else:
+            cmap = sns.color_palette("magma_r", as_cmap=True)
+        return cmap
+
+    def plot(self, plot_data, error_metric, error_long_name, error_units, model_type, limits, ahead=None):
+        import cartopy.crs as ccrs
+        from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
+        fig = plt.figure(figsize=(10, 5))
+        ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
+        _gl = ax.gridlines(xlocs=range(-180, 180, 5), ylocs=range(-90, 90, 2), draw_labels=True)
+        _gl.xformatter = LONGITUDE_FORMATTER
+        _gl.yformatter = LATITUDE_FORMATTER
+        self._draw_background(ax)
+        cmap = self._get_colorpalette(error_metric)
+        ncolors = 20
+        bounds = self._set_bounds(limits, ncolors, error_metric)
+        norm = colors.BoundaryNorm(bounds, cmap.N, extend='both')
+        cb = ax.scatter(plot_data["lon"], plot_data["lat"], c=plot_data[error_metric], marker='o', s=50,
+                        transform=ccrs.PlateCarree(), zorder=2, cmap=cmap, norm=norm)
+        cbar_label = f"{error_long_name} (in {error_units})" if error_units is not None else error_long_name
+        plt.colorbar(cb, label=cbar_label)
+        self._adjust_extent(ax)
+        title = model_type if ahead is None else f"{model_type} ({ahead}{self.sampling})"
+        plt.title(title)
+        plt.tight_layout()
+
+    @staticmethod
+    def _adjust_extent(ax):
+        import cartopy.crs as ccrs
+
+        def diff(arr):
+            return arr[1] - arr[0], arr[3] - arr[2]
+
+        def find_ratio(delta, reference=5):
+            return min(max(abs(reference / delta[0]), abs(reference / delta[1])), 5)
+
+        extent = ax.get_extent(crs=ccrs.PlateCarree())
+        ratio = find_ratio(diff(extent))
+        new_extent = extent + np.array([-1, 1, -1, 1]) * ratio
+        ax.set_extent(new_extent, crs=ccrs.PlateCarree())
+
+    @staticmethod
+    def _extract_coords(gen):
+        coll = []
+        for station in gen:
+            coords = station.get_coordinates()
+            coll.append((str(station), coords["lon"], coords["lat"]))
+        return pd.DataFrame(coll, columns=["station", "lon", "lat"]).set_index("station")
+
+    @staticmethod
+    def _prepare_data(errors, model_type_dim, model_type, ahead_dim, error_metric, split_ahead=False):
+        e = errors.sel({model_type_dim: model_type}, drop=True)
+        if split_ahead is False:
+            e = e.mean(ahead_dim)
+        return e.to_dataframe(error_metric)
+
+    @staticmethod
+    def _draw_background(ax):
+        """Draw coastline, lakes, ocean, rivers and country borders as background on the map."""
+
+        import cartopy.feature as cfeature
+
+        ax.add_feature(cfeature.LAND.with_scale("50m"))
+        ax.natural_earth_shp(resolution='50m')
+        ax.add_feature(cfeature.COASTLINE.with_scale("50m"), 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("50m"))
+        ax.add_feature(cfeature.BORDERS.with_scale("50m"), facecolor='none', edgecolor='black')
+
+
+
+
+
 
-    con_quan_cls = PlotConditionalQuantiles(stations, path, plt_path)
+    def _plot_individual(self):
+        import cartopy.feature as cfeature
+        import cartopy.crs as ccrs
+        from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
+        from mpl_toolkits.axes_grid1 import make_axes_locatable
+
+        for competitor in self.reference_models:
+            file_name = os.path.join(self.skill_score_report_path,
+                                     f"error_report_skill_score_{self.model_name}_-_{competitor}.csv"
+                                     )
+
+            plot_path = os.path.join(os.path.abspath(self.plot_folder),
+                                     f"{self.plot_name}_{self.model_name}_-_{competitor}.pdf")
+            pdf_pages = matplotlib.backends.backend_pdf.PdfPages(plot_path)
+
+            for i, lead_name in enumerate(df.columns[:-2]):  # last two are lat lon
+                fig = plt.figure()
+                self._ax.scatter(df.lon.values, df.lat.values, c=df[lead_name],
+                           transform=ccrs.PlateCarree(),
+                           norm=norm, cmap=cmap)
+                self._gl = self._ax.gridlines(xlocs=range(0, 21, 5), ylocs=range(44, 59, 2), draw_labels=True)
+                self._gl.xformatter = LONGITUDE_FORMATTER
+                self._gl.yformatter = LATITUDE_FORMATTER
+                label = f"Skill Score: {lead_name.replace('-', 'vs.').replace('(t+', ' (').replace(')', 'd)')}"
+                self._cbar = fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
+                                          orientation='horizontal', ticks=ticks,
+                                          label=label,
+                                          # cax=cax
+                                          )
+
+            # close all open figures / plots
+            pdf_pages.savefig()
+            pdf_pages.close()
+            plt.close('all')
+
+    def _plot(self, ncol: int = 2):
+        import cartopy.feature as cfeature
+        import cartopy.crs as ccrs
+        from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
+        import string
+        base_plot_name = self.plot_name
+        for competitor in self.reference_models:
+            file_name = os.path.join(self.skill_score_report_path,
+                                     f"error_report_skill_score_{self.model_name}_-_{competitor}.csv"
+                                     )
+
+            self.plot_name = f"{base_plot_name}_{self.model_name}_-_{competitor}"
+            df = self.open_data(file_name)
+
+            nrow = int(np.ceil(len(df.columns[:-2])/ncol))
+            bounds = np.linspace(-1, 1, 100)
+            cmap = mpl.cm.coolwarm
+            norm = colors.BoundaryNorm(bounds, cmap.N, extend='both')
+            ticks = np.arange(norm.vmin, norm.vmax + .2, .2)
+            fig, self._axes = plt.subplots(nrows=nrow, ncols=ncol, subplot_kw={'projection': ccrs.PlateCarree()})
+            for i, ax in enumerate(self._axes.reshape(-1)):  # last two are lat lon
+
+                sub_name = f"({string.ascii_lowercase[i]})"
+                lead_name = df.columns[i]
+                ax.add_feature(cfeature.LAND.with_scale("50m"))
+                ax.add_feature(cfeature.COASTLINE.with_scale("50m"), edgecolor='black')
+                ax.add_feature(cfeature.OCEAN.with_scale("50m"))
+                ax.add_feature(cfeature.RIVERS.with_scale("50m"))
+                ax.add_feature(cfeature.BORDERS.with_scale("50m"), facecolor='none', edgecolor='black')
+                ax.scatter(df.lon.values, df.lat.values, c=df[lead_name],
+                           marker='.',
+                           transform=ccrs.PlateCarree(),
+                           norm=norm, cmap=cmap)
+                gl = ax.gridlines(xlocs=range(0, 21, 5), ylocs=range(44, 59, 2), draw_labels=True)
+                gl.xformatter = LONGITUDE_FORMATTER
+                gl.yformatter = LATITUDE_FORMATTER
+                gl.top_labels = []
+                gl.right_labels = []
+                ax.text(0.01, 1.09, f'{sub_name} {lead_name.split("+")[1][:-1]}d',
+                        verticalalignment='top', horizontalalignment='left',
+                        transform=ax.transAxes,
+                        color='black',
+                        )
+            label = f"Skill Score: {lead_name.replace('-', 'vs.').split('(')[0]}"
+
+            fig.subplots_adjust(bottom=0.18)
+            cax = fig.add_axes([0.15, 0.1, 0.7, 0.02])
+            self._cbar = fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
+                                      orientation='horizontal',
+                                      ticks=ticks,
+                                      label=label,
+                                      cax=cax
+                                      )
+
+            fig.subplots_adjust(wspace=.001, hspace=.2)
+            self._save(bbox_inches="tight")
+            plt.close('all')
+
+
+    @staticmethod
+    def get_coords_from_index(name_string: str) -> List[float]:
+        """
+
+        :param name_string:
+        :type name_string:
+        :return: List of coords [lat, lon]
+        :rtype: List
+        """
+        res = [float(frac.replace("_", ".")) for frac in name_string.split(sep="__")[1:]]
+        return res
diff --git a/mlair/run_modules/post_processing.py b/mlair/run_modules/post_processing.py
index f8e2677862e23c56fe38b13f7c6dfb78c6a7f964..0fb14f55cf0d6270a8c26937b955e09758567101 100644
--- a/mlair/run_modules/post_processing.py
+++ b/mlair/run_modules/post_processing.py
@@ -24,7 +24,8 @@ from mlair.model_modules.linear_model import OrdinaryLeastSquaredModel
 from mlair.model_modules import AbstractModelClass
 from mlair.plotting.postprocessing_plotting import PlotMonthlySummary, PlotClimatologicalSkillScore, \
     PlotCompetitiveSkillScore, PlotTimeSeries, PlotFeatureImportanceSkillScore, PlotConditionalQuantiles, \
-    PlotSeparationOfScales, PlotSampleUncertaintyFromBootstrap, PlotTimeEvolutionMetric, PlotSeasonalMSEStack
+    PlotSeparationOfScales, PlotSampleUncertaintyFromBootstrap, PlotTimeEvolutionMetric, PlotSeasonalMSEStack, \
+    PlotErrorsOnMap
 from mlair.plotting.data_insight_plotting import PlotStationMap, PlotAvailability, PlotAvailabilityHistogram, \
     PlotPeriodogram, PlotDataHistogram
 from mlair.run_modules.run_environment import RunEnvironment
@@ -729,6 +730,23 @@ class PostProcessing(RunEnvironment):
             logging.error(f"Could not create plot PlotSeasonalMSEStack due to the following error: {e}"
                           f"\n{sys.exc_info()[0]}\n{sys.exc_info()[1]}\n{sys.exc_info()[2]}")
 
+        try:
+            if "PlotErrorsOnMap" in plot_list and self.errors is not None:
+                for error_metric in self.errors.keys():
+                    try:
+                        PlotErrorsOnMap(self.test_data, self.errors[error_metric], error_metric,
+                                        plot_folder=self.plot_path, sampling=self._sampling)
+                    except Exception as e:
+                        logging.error(f"Could not create plot PlotErrorsOnMap for {error_metric} due to the following "
+                                      f"error: {e}\n{sys.exc_info()[0]}\n{sys.exc_info()[1]}\n{sys.exc_info()[2]}")
+        except Exception as e:
+            logging.error(f"Could not create plot PlotErrorsOnMap due to the following error: {e}"
+                          f"\n{sys.exc_info()[0]}\n{sys.exc_info()[1]}\n{sys.exc_info()[2]}")
+
+
+
+
+
     @TimeTrackingWrapper
     def calculate_test_score(self):
         """Evaluate test score of model and save locally."""
diff --git a/test/test_helpers/test_helpers.py b/test/test_helpers/test_helpers.py
index 6f787d5835bd917fcfc55341d93a2d302f2c6e6e..22eaa102544f93511007204e6633de143c3e022c 100644
--- a/test/test_helpers/test_helpers.py
+++ b/test/test_helpers/test_helpers.py
@@ -16,7 +16,7 @@ from mlair.helpers import to_list, dict_to_xarray, float_round, remove_items, ex
     sort_like, filter_dict_by_value
 from mlair.helpers import PyTestRegex, check_nested_equality
 from mlair.helpers import Logger, TimeTracking
-from mlair.helpers.helpers import is_xarray, convert2xrda, relative_round
+from mlair.helpers.helpers import is_xarray, convert2xrda, relative_round, get_order
 
 
 class TestToList:
@@ -191,6 +191,10 @@ class TestRelativeRound:
         assert relative_round(0.03112, 1) == 0.03
         assert relative_round(0.031126, 4) == 0.03113
 
+    def test_relative_round_zero(self):
+        assert relative_round(0, 1) == 0
+        assert relative_round(0, 4) == 0
+
     def test_relative_round_negative_numbers(self):
         assert relative_round(-101.2033, 5) == -101.2
         assert relative_round(-106, 2) == -110
@@ -204,6 +208,66 @@ class TestRelativeRound:
         with pytest.raises(TypeError):
             relative_round(300, 1.1)
 
+    def test_relative_round_floor(self):
+        assert relative_round(7.5, 1, floor=True) == 7
+        assert relative_round(7.7, 1, floor=True) == 7
+        assert relative_round(7.9, 1, floor=True) == 7
+        assert relative_round(7.993, 2, floor=True) == 7.9
+        assert relative_round(17.9312, 1, floor=True) == 10
+        assert relative_round(17.9312, 2, floor=True) == 17
+        assert relative_round(127.43, 3, floor=True) == 127
+        assert relative_round(0.025, 1, floor=True) == 0.02
+
+    def test_relative_round_floor_neg_numbers(self):
+        assert relative_round(-7.9, 1, floor=True) == -8
+        assert relative_round(-7.4, 1, floor=True) == -8
+        assert relative_round(-7.42, 2, floor=True) == -7.5
+        assert relative_round(-127.43, 3, floor=True) == -128
+        assert relative_round(-127.43, 2, floor=True) == -130
+        assert relative_round(-127.43, 1, floor=True) == -200
+
+    def test_relative_round_ceil(self):
+        assert relative_round(7.5, 1, ceil=True) == 8
+        assert relative_round(7.7, 1, ceil=True) == 8
+        assert relative_round(7.2, 1, ceil=True) == 8
+        assert relative_round(7.993, 2, ceil=True) == 8
+        assert relative_round(17.9312, 1, ceil=True) == 20
+        assert relative_round(17.9312, 2, ceil=True) == 18
+        assert relative_round(127.43, 3, ceil=True) == 128
+
+    def test_relative_round_ceil_neg_numbers(self):
+        assert relative_round(-7.9, 1, ceil=True) == -7
+        assert relative_round(-7.4, 1, ceil=True) == -7
+        assert relative_round(-7.42, 2, ceil=True) == -7.4
+        assert relative_round(-127.43, 3, ceil=True) == -127
+        assert relative_round(-127.43, 2, ceil=True) == -120
+        assert relative_round(-127.43, 1, ceil=True) == -100
+
+    def test_relative_round_ceil_floor(self):
+        with pytest.raises(AssertionError):
+            relative_round(300, -1, ceil=True, floor=True)
+
+
+class TestGetOrder:
+
+    def test_get_order(self):
+        assert get_order(10) == 1
+        assert get_order(11) == 1
+        assert get_order(9.99) == 0
+        assert get_order(1000) == 3
+        assert get_order(.006) == -3
+
+    def test_get_order_neg_orders(self):
+        assert get_order(.006) == -3
+        assert np.isinf(get_order(0))
+        assert get_order(0.00622) == -3
+        assert get_order(0.00022) == -4
+
+    def test_get_order_neg_numbers(self):
+        assert get_order(-0.00622) == -3
+        assert get_order(-0.1) == -1
+        assert get_order(-622) == 2
+
 
 class TestSelectFromDict: