diff --git a/scenes/core.py b/scenes/core.py
index 94f94f3ef50e08a3a0e4cd7e26ab98c7ccdaf276..502468bec3f7d4cd35c2826590dc3bc661273820 100644
--- a/scenes/core.py
+++ b/scenes/core.py
@@ -12,6 +12,7 @@ class Source(pyotb.Output):
     Source class.
     Holds common operations on image sources (e.g. drill, resample, extract an ROI, etc.)
     """
+
     def __init__(self, root_imagery, out, parent=None):
         """
         :param root_imagery: root Imagery instance
@@ -96,6 +97,20 @@ class Source(pyotb.Output):
                                                  "mode": "fit",
                                                  "mode.fit.vec": ref_vec}))
 
+    def reproject(self, epsg, interpolator="nn"):
+        """
+        Reproject the source into the specified EPSG
+        :param epsg: EPSG (int)
+        :param interpolator: interpolator
+        :return: reprojected source
+        """
+        if self.root_imagery.root_scene.epsg != epsg:
+            return self.new_source(pyotb.Orthorectification({"io.in": self,
+                                                             "map": "epsg",
+                                                             "map.epsg": epsg,
+                                                             "interpolator": interpolator}))
+        return self  # Nothing but a soft copy of the source
+
 
 class Imagery:
     """
@@ -140,13 +155,18 @@ class Scene(ABC):
         :return: Imagery instance
         """
 
-    def __repr__(self):
+    def get_metadata(self):
         """
         Enable one instance to be used with print()
         """
-        out = {
+        return {
             "Acquisition date": self.acquisition_date,
             "Bounding box (WGS84)": self.bbox_wgs84,
             "EPSG": self.epsg,
         }
-        return "\n".join(["{}: {}".format(key, value) for key, value in out.items()])
+
+    def __repr__(self):
+        """
+        Enable one instance to be used with print()
+        """
+        return "\n".join(["{}: {}".format(key, value) for key, value in self.get_metadata().items()])
diff --git a/scenes/spot.py b/scenes/spot.py
index be13d46699775a0ec595bc29f0baa742d9572006..1ddaf76e8ebde4fa62d6f183de40df7864411d3e 100644
--- a/scenes/spot.py
+++ b/scenes/spot.py
@@ -12,6 +12,7 @@ class Spot67Source(Source):
     """
     Spot 6/7 source class
     """
+
     def cld_msk_drilled(self, nodata=0):
         """
         Return the source drilled from the cloud mask
@@ -26,39 +27,25 @@ class Spot67Imagery(Imagery):
     Spot 6/7 imagery class.
     This class carry the base image source, which can be radiometrically or geometrically corrected.
     """
-    def __init__(self, root_scene, epsg=None, reflectance=None):
+
+    def __init__(self, root_scene, reflectance):
         """
         :param root_scene: The Scene of which the Imagery instance is attached
-        :param epsg: optional option to project PAN and MS images
-        :param reflectance: optional level of reflectance
+        :param reflectance: optional level of reflectance (can be "dn", "toa")
         """
         super().__init__(root_scene=root_scene)
 
         # Base
         self.xs = self.root_scene.dimap_file_xs
         self.pan = self.root_scene.dimap_file_pan
-        self.pxs = None
 
         # Radiometry correction
-        if reflectance:
-            if reflectance.lower() == "toa":
-                def _toa(inp):
-                    return pyotb.OpticalCalibration({"in": inp, "level": "toa"})
-
-                self.toa_xs = _toa(self.xs)
-                self.toa_pan = _toa(self.pan)
-                self.xs = self.toa_xs
-                self.pan = self.toa_pan
-
-        # Geometry correction
-        if epsg:
-            def _reproj(inp):
-                return pyotb.Orthorectification({"io.in": inp, "map": "epsg", "map.epsg": epsg, "interpolator": "nn"})
-
-            self.reproj_xs = _reproj(self.xs)
-            self.reproj_pan = _reproj(self.pan)
-            self.xs = self.reproj_xs
-            self.pan = self.reproj_pan
+        if reflectance.lower() == "toa":
+            def _toa(inp):
+                return pyotb.OpticalCalibration({"in": inp, "level": "toa"})
+
+            self.xs = _toa(self.xs)
+            self.pan = _toa(self.pan)
 
     def get_xs(self):
         """
@@ -207,20 +194,21 @@ class Spot67Scene(Scene):
         """
         return self.pxs_overlap < self.PXS_OVERLAP_THRESH
 
-    def get_imagery(self, epsg=None, reflectance=None):  # pylint: disable=arguments-differ
+    def get_imagery(self, reflectance="dn"):  # pylint: disable=arguments-differ
         """
         Return the Spot 6/7 imagery
-        :param epsg: optional option to project PAN and MS images
         :param reflectance: optional level of reflectance
         :return: Imagery instance
         """
-        return Spot67Imagery(self, epsg=epsg, reflectance=reflectance)
+        return Spot67Imagery(self, reflectance=reflectance)
 
-    def __repr__(self):
+    def get_metadata(self):
         """
-        Enable the class to be used with print()
+        Return the metadata
+        :return: metadata (dict)
         """
-        out = {
+        metadata = super().get_metadata()
+        metadata.update({
             "DIMAP XS": self.dimap_file_xs,
             "DIMAP PAN": self.dimap_file_pan,
             "Cloud mask": self.cld_msk_file,
@@ -238,5 +226,5 @@ class Spot67Scene(Scene):
             "Sun azimuth": self.sun_azimuth,
             "Bounding box XS (WGS84)": self.bbox_wgs84_xs,
             "Bounding box PAN (WGS84)": self.bbox_wgs84_pan
-        }
-        return super().__repr__() + "\n".join(["{}: {}".format(key, value) for key, value in out.items()])
+        })
+        return metadata