diff --git a/src/data_handling/bootstraps.py b/src/data_handling/bootstraps.py
index 3fdabe4c9ef6faafa447967b86cce1aaab6d2bcf..46fa7c2be39d3dadb1922a1b710065aa42d9e2d2 100644
--- a/src/data_handling/bootstraps.py
+++ b/src/data_handling/bootstraps.py
@@ -15,15 +15,22 @@ from typing import List, Union, Pattern, Tuple
 
 
 class BootStrapGenerator(keras.utils.Sequence):
-
-    def __init__(self, number_of_boots, history, shuffled, variables, shuffled_variable):
+    """
+    generator for bootstraps as keras sequence inheritance. Initialise with number of boots, the original history, the
+    shuffled data, all used variables and the current shuffled variable. While iterating over this generator, it returns
+    the bootstrapped history for given boot index (this is the iterator index) in the same format like the original
+    history ready to use. Note, that in some cases some samples can contain nan values (in these cases the entire data
+    row is null, not only single entries).
+    """
+    def __init__(self, number_of_boots: int, history: xr.DataArray, shuffled: xr.DataArray, variables: List[str],
+                 shuffled_variable: str):
         self.number_of_boots = number_of_boots
         self.variables = variables
         self.history_orig = history
         self.history = history.sel(variables=helpers.list_pop(self.variables, shuffled_variable))
         self.shuffled = shuffled.sel(variables=shuffled_variable)
 
-    def __len__(self):
+    def __len__(self) -> int:
         return self.number_of_boots
 
     def __getitem__(self, index: int) -> xr.DataArray:
@@ -48,14 +55,17 @@ class BootStrapGenerator(keras.utils.Sequence):
 
 
 class CreateShuffledData:
-
-    def __init__(self, data: DataGenerator, number_of_bootstraps, bootstrap_path):
+    """
+    Verify and create shuffled data for all data contained in given data generator class. Starts automatically on
+    initialisation, no further calls are required. Check and new creations are all performed inside bootstrap_path.
+    """
+    def __init__(self, data: DataGenerator, number_of_bootstraps: int, bootstrap_path: str):
         self.data = data
         self.number_of_bootstraps = number_of_bootstraps
         self.bootstrap_path = bootstrap_path
         self.create_shuffled_data()
 
-    def create_shuffled_data(self):
+    def create_shuffled_data(self) -> None:
         """
         Create shuffled data. Use original test data, add dimension 'boots' with length number of bootstraps and insert
         randomly selected variables. If there is a suitable local file for requested window size and number of
@@ -102,10 +112,12 @@ class CreateShuffledData:
         from this class. Furthermore, this functions deletes local files, if the match the station pattern but don't fit
         the window and bootstrap condition. This is performed, because it is assumed, that the corresponding file will
         be created with a longer or at the least same window size and numbers of bootstraps.
-        :param station:
-        :param variables:
-        :param window:
-        :return:
+        :param station: name of the station to validate
+        :param variables: all variables already merged in single string seperated by underscore
+        :param window: required window size
+        :return: tuple containing information if valid file was found first and second the number of boots that needs to
+            be used for the new boot creation (this is only relevant, if no valid file was found - otherwise the return
+            statement is anyway None).
         """
         regex = re.compile(rf"{station}_{variables}_hist(\d+)_nboots(\d+)_shuffled")
         max_nboot = self.number_of_bootstraps
@@ -134,51 +146,63 @@ class CreateShuffledData:
 
 
 class BootStraps:
-
-    def __init__(self, data, bootstrap_path, number_of_bootstraps=10):
-        self.data: DataGenerator = data
+    """
+    Main class to perform bootstrap operations. This class requires a DataGenerator object and a path, where to find and
+    store all data related to the bootstrap operation. In initialisation, this class will automatically call the class
+    CreateShuffleData to set up the shuffled data sets. How to use BootStraps:
+    * call .get_generator(<station>, <variable>) to get a generator for given station and variable combination that
+        iterates over all bootstrap realisations (as keras sequence)
+    * call .get_labels(<station>) to get the measured observations in the same format as bootstrap predictions
+    * call .get_bootstrap_predictions(<station>, <variable>) to get the bootstrapped predictions
+    * call .get_orig_prediction(<station>) to get the non-bootstrapped predictions (referred as original predictions)
+    """
+
+    def __init__(self, data: DataGenerator, bootstrap_path: str, number_of_bootstraps: int = 10):
+        self.data = data
         self.number_of_bootstraps = number_of_bootstraps
         self.bootstrap_path = bootstrap_path
         CreateShuffledData(data, number_of_bootstraps, bootstrap_path)
 
     @property
-    def stations(self):
+    def stations(self) -> List[str]:
         return self.data.stations
 
     @property
-    def variables(self):
+    def variables(self) -> List[str]:
         return self.data.variables
 
     @property
-    def window_history_size(self):
+    def window_history_size(self) -> int:
         return self.data.window_history_size
 
-    def get_generator(self, station, var):
+    def get_generator(self, station: str, variable: str) -> BootStrapGenerator:
         """
-        This is the implementation of the __next__ method of the iterator protocol. Get the data generator, and return
-        the history and label data of this generator.
-        :return:
+        Returns the actual generator to use for the bootstrap evaluation. The generator requires information on station
+        and bootstrapped variable. There is only a loop on the bootstrap realisation and not on stations or variables.
+        :param station: name of the station
+        :param variable: name of the variable to bootstrap
+        :return: BootStrapGenerator class ready to use.
         """
         hist, _ = self.data[station]
         shuffled_data = self._load_shuffled_data(station, self.variables).reindex_like(hist)
-        return BootStrapGenerator(self.number_of_bootstraps, hist, shuffled_data, self.variables, var)
+        return BootStrapGenerator(self.number_of_bootstraps, hist, shuffled_data, self.variables, variable)
 
-    def get_labels(self, key: Union[str, int]):
+    def get_labels(self, station: str) -> np.ndarray:
         """
-        Repeats labels for given key by the number of boots and yield it one by one.
-        :param key: key of station (either station name as string or the position in generator as integer)
-        :return: yields labels for length of boots
+        Repeats labels for given key by the number of boots and returns as single array.
+        :param station: name of station
+        :return: repeated labels as single array
         """
-        labels = self.data[key][1]
+        labels = self.data[station][1]
         return np.tile(labels.data, (self.number_of_bootstraps, 1))
 
-    def get_orig_prediction(self, path: str, file_name: str, prediction_name: str = "CNN"):
+    def get_orig_prediction(self, path: str, file_name: str, prediction_name: str = "CNN") -> np.ndarray:
         """
         Repeats predictions from given file(_name) in path by the number of boots.
         :param path: path to file
         :param file_name: file name
-        :param prediction_name: name of the prediction to select from loaded file
-        :return: yields predictions for length of boots
+        :param prediction_name: name of the prediction to select from loaded file (default CNN)
+        :return: repeated predictions
         """
         file = os.path.join(path, file_name)
         prediction = xr.open_dataarray(file).sel(type=prediction_name).squeeze()
@@ -190,15 +214,21 @@ class BootStraps:
         Load shuffled data from bootstrap path. Data is stored as
         '<station>_<var1>_<var2>_..._hist<histsize>_nboots<nboots>_shuffled.nc', e.g.
         'DEBW107_cloudcover_no_no2_temp_u_v_hist13_nboots20_shuffled.nc'
-        :param station:
-        :param variables:
+        :param station: name of station
+        :param variables: list of variables
         :return: shuffled data as xarray
         """
         file_name = self._get_shuffled_data_file(station, variables)
         shuffled_data = xr.open_dataarray(file_name, chunks=100)
         return shuffled_data
 
-    def _get_shuffled_data_file(self, station, variables):
+    def _get_shuffled_data_file(self, station: str, variables: List[str]) -> str:
+        """
+        Looks for data file using regular expressions and returns found file or raise FileNotFoundError
+        :param station: name of station
+        :param variables: name of variables
+        :return: found file with complete path
+        """
         files = os.listdir(self.bootstrap_path)
         regex = self._create_file_regex(station, variables)
         file = self._filter_files(regex, files, self.window_history_size, self.number_of_bootstraps)
diff --git a/test/test_data_handling/test_bootstraps.py b/test/test_data_handling/test_bootstraps.py
index 45d8c86fb24547e870b190885abeda82aacb882c..c2b814b7bf173b61b4967c83611cdd3de08ed91b 100644
--- a/test/test_data_handling/test_bootstraps.py
+++ b/test/test_data_handling/test_bootstraps.py
@@ -14,38 +14,6 @@ import numpy as np
 import xarray as xr
 
 
-### old ###
-
-
-class TestBootStrapsOld:
-
-    @pytest.fixture
-    def boot_gen(self, orig_generator):
-        path = os.path.join(os.path.dirname(__file__), 'data')
-        dummy_content = xr.DataArray([1, 2, 3], dims="dummy")
-        dummy_content.to_netcdf(os.path.join(path, "DEBW107_o3_temp_hist7_nboots20_shuffled.nc"))
-        dummy_content.to_netcdf(os.path.join(path, "DEBW013_o3_temp_hist7_nboots20_shuffled.nc"))
-        dummy_content = dummy_content.expand_dims({"type": ["CNN"]})
-        dummy_content.to_netcdf(os.path.join(path, "forecasts_norm_DEBW107_test.nc"))
-        return BootStraps(orig_generator, path, 20)
-
-    def test_get_orig_prediction(self, boot_gen):
-        path = boot_gen.orig_generator.data_path
-        res = []
-        for pred in boot_gen.get_orig_prediction(path, "forecasts_norm_DEBW107_test.nc"):
-            res.append(pred)
-        assert len(res) == boot_gen.number_of_boots
-        assert PyTestAllEqual(res).is_true()
-
-    def test_load_shuffled_data(self, boot_gen):
-        shuffled_data = boot_gen._load_shuffled_data("DEBW107", ["o3", "temp"])
-        assert isinstance(shuffled_data, xr.DataArray)
-        assert all(shuffled_data.compute().values == [1, 2, 3])
-
-
-### new ###
-
-
 @pytest.fixture
 def orig_generator(data_path):
     return DataGenerator(data_path, 'AIRBASE', ['DEBW107', 'DEBW013'],
@@ -245,6 +213,22 @@ class TestBootStraps:
         assert xr.testing.assert_equal(gen.history, expected.sel(variables=var_others)) is None
         assert gen.shuffled.variables == "o3"
 
+    @mock.patch("src.data_handling.data_generator.DataGenerator._load_pickle_data", side_effect=FileNotFoundError)
+    def test_get_generator_different_generator(self, mock_load_pickle, data_path, orig_generator):
+        BootStraps(orig_generator, data_path, 20)  # to create
+        orig_generator.window_history_size = 4
+        bootstrap = BootStraps(orig_generator, data_path, 20)
+        station = bootstrap.stations[0]
+        var = bootstrap.variables[0]
+        var_others = bootstrap.variables[1:]
+        gen = bootstrap.get_generator(station, var)
+        expected = orig_generator.get_data_generator(station, load_local_tmp_storage=False).get_transposed_history()
+        assert xr.testing.assert_equal(gen.history_orig, expected) is None
+        assert xr.testing.assert_equal(gen.history, expected.sel(variables=var_others)) is None
+        assert gen.shuffled.variables == "o3"
+        assert gen.shuffled.shape[:-1] == expected.shape[:-1]
+        assert gen.shuffled.shape[-1] == 20
+
     def test_get_labels(self, bootstrap, orig_generator):
         station = bootstrap.stations[0]
         labels = bootstrap.get_labels(station)
@@ -252,11 +236,30 @@ class TestBootStraps:
         assert labels.shape == (labels_orig.shape[0] * bootstrap.number_of_bootstraps, *labels_orig.shape[1:])
         assert np.testing.assert_array_equal(labels[:labels_orig.shape[0], :], labels_orig.values) is None
 
-    def test_get_orig_prediction(self):
-        pass
-
-    def test_load_shuffled_data(self):
-        pass
+    def test_get_orig_prediction(self, bootstrap, data_path, orig_generator):
+        station = bootstrap.stations[0]
+        labels = orig_generator.get_data_generator(station).get_transposed_label()
+        predictions = labels.expand_dims({"type": ["CNN"]}, -1)
+        file_name = "test_prediction.nc"
+        predictions.to_netcdf(os.path.join(data_path, file_name))
+        res = bootstrap.get_orig_prediction(data_path, file_name)
+        assert (*res.shape, 1) == (predictions.shape[0] * bootstrap.number_of_bootstraps, *predictions.shape[1:])
+        assert np.testing.assert_array_equal(res[:predictions.shape[0], :], predictions.squeeze().values) is None
+
+    def test_load_shuffled_data(self, bootstrap, orig_generator):
+        station = bootstrap.stations[0]
+        hist = orig_generator.get_data_generator(station).get_transposed_history()
+        shuffled_data = bootstrap._load_shuffled_data(station, ["o3", "temp"])
+        assert isinstance(shuffled_data, xr.DataArray)
+        assert hist.shape[0] >= shuffled_data.shape[0]  # longer window length lead to shorter datetime axis in shuffled
+        assert hist.shape[1] <= shuffled_data.shape[1]  # longer window length in shuffled
+        assert hist.shape[2] == shuffled_data.shape[2]
+        assert hist.shape[3] <= shuffled_data.shape[3]  # potentially more variables in shuffled
+        assert bootstrap.number_of_bootstraps == shuffled_data.shape[4]
+        assert shuffled_data.mean().compute()
+        assert np.testing.assert_almost_equal(shuffled_data.mean().compute(), hist.mean(), decimal=1) is None
+        assert shuffled_data.max() <= hist.max()
+        assert shuffled_data.min() >= hist.min()
 
     def test_get_shuffled_data_file(self, bootstrap):
         file_name = bootstrap._get_shuffled_data_file("DEBW107", ["o3"])
@@ -270,6 +273,11 @@ class TestBootStraps:
         assert "Could not find a file to match pattern" in e.value.args[0]
 
     def test_create_file_regex(self, bootstrap_no_shuffling):
+        regex = bootstrap_no_shuffling._create_file_regex("DEBW108", ["o3", "temp", "h2o"])
+        assert regex.match("DEBW108_h2o_hum_latent_o3_temp_h20_hist10_nboots10_shuffled.nc")
+        regex.match("DEBW108_h2o_hum_latent_o3_temp_hist10_shuffled.nc") is None
+
+    def test_filter_files(self, bootstrap_no_shuffling):
         regex = bootstrap_no_shuffling._create_file_regex("DEBW108", ["o3", "temp", "h2o"])
         test_list = ["DEBW108_o3_test23_test_shuffled.nc",
                      "DEBW107_o3_test23_test_shuffled.nc",
@@ -283,5 +291,3 @@ class TestBootStraps:
         assert f(regex, test_list, 9, 10) == "DEBW108_h2o_o3_temp_hist9_nboots20_shuffled.nc"
         assert f(regex, test_list, 9, 20) == "DEBW108_h2o_o3_temp_hist9_nboots20_shuffled.nc"
 
-    def test_filter_files(self):
-        pass