Repository: dlr-eoc/ukis-pysat

Issue:
Consider dimorder when initializing Image() from array
It is possible to initialize an Image() object from an existing rasterio.dataset and an array as follows:
```python
img = Image(dataset=ds, array=arr, dimorder="first")
```
To work correctly this assumes that the array is of shape (bands, rows, cols) regardless of parameter setting for dimorder.

Suggest to modify __init__ of Image to consider this case and allow passing arrays of different dimorder. The following would be a working example:

```python
    def __init__(self, path=None, dataset=None, arr=None, dimorder="first"):
        if path:
            if isinstance(path, str):
                self.dataset = rasterio.open(path)
                self.__arr = self.dataset.read()
            else:
                raise TypeError(f"path must be of type str")
        else:
            if isinstance(dataset, rasterio.io.DatasetReader) and isinstance(arr, np.ndarray):
                self.dataset = dataset
                if dimorder == "first":
                    self.__arr = arr
                elif dimorder == "last":
                    self.__arr = reshape_as_raster(arr)
                else:
                    raise AttributeError("dimorder for bands or channels must be either 'first' or 'last'.")
            else:
                raise TypeError(
                    f"dataset must be of type rasterio.io.DatasetReader and arr must be of type " f"numpy.ndarray"
                )
        self.dimorder = dimorder
        self.transform = self.dataset.transform
        self.crs = self.dataset.crs
        self.da_arr = None
```
Please note that this modification would not interfere with any internal array manipulation but just allow for consistent flexible array IO to Image().

Discussion:

Patch:
diff --git a/ukis_pysat/raster.py b/ukis_pysat/raster.py
index 1e77d2e..e34b420 100644
--- a/ukis_pysat/raster.py
+++ b/ukis_pysat/raster.py
@@ -10,7 +10,7 @@ try:
     from rasterio import windows
     from rasterio.dtypes import get_minimum_dtype
     from rasterio.io import MemoryFile
-    from rasterio.plot import reshape_as_image
+    from rasterio.plot import reshape_as_image, reshape_as_raster
     from rasterio.warp import calculate_default_transform, reproject
     from rio_toa import reflectance, brightness_temp, toa_utils
     from shapely.geometry import box, polygon
@@ -31,7 +31,8 @@ class Image:
         :param path: str, path to raster (default: None)
         :param dataset: rasterio.io.DatasetReader (default: None)
         :param arr: np.ndarray (default: None)
-        :param dimorder: order of channels or bands 'first' or 'last' (default: 'first)
+        :param dimorder: dimensions order of arr. return channels or bands as 'first' or 'last' dimension. should match
+            the dimensions order of the input array when initializing an image from an array (default: 'first)
         """
         if path:
             if isinstance(path, str):
@@ -42,7 +43,12 @@ class Image:
         else:
             if isinstance(dataset, rasterio.io.DatasetReader) and isinstance(arr, np.ndarray):
                 self.dataset = dataset
-                self.__arr = arr
+                if dimorder == "first":
+                    self.__arr = arr
+                elif dimorder == "last":
+                    self.__arr = reshape_as_raster(arr)
+                else:
+                    raise AttributeError("dimorder for bands or channels must be either 'first' or 'last'.")
             else:
                 raise TypeError(
                     f"dataset must be of type rasterio.io.DatasetReader and arr must be of type " f"numpy.ndarray"


Test patch:
diff --git a/tests/test_raster.py b/tests/test_raster.py
index 13fc996..7e7cc02 100644
--- a/tests/test_raster.py
+++ b/tests/test_raster.py
@@ -66,6 +66,13 @@ class DataTest(unittest.TestCase):
             ),
         )
 
+        img = Image(path=os.path.join(os.path.dirname(__file__), "testfiles", "dummy.tif"), dimorder="first")
+        img_first = Image(dataset=img.dataset, arr=np.ones((1, 385, 502)), dimorder="first")
+        self.assertEqual(img_first.arr.shape, (1, 385, 502))
+
+        img_last = Image(dataset=img.dataset, arr=np.ones((385, 502, 1)), dimorder="last")
+        self.assertEqual(img_last.arr.shape, (385, 502, 1))
+
         with self.assertRaises(AttributeError, msg="dimorder for bands or channels must be either 'first' or 'last'."):
             img_first = Image(path=os.path.join(os.path.dirname(__file__), "testfiles", "dummy.tif"), dimorder="middle")
             img_first.arr