diff --git a/src/iamap/iamap.py b/src/iamap/iamap.py
deleted file mode 100644
index a0a36a04b2e46e524943d893f9e614773bdd63b4..0000000000000000000000000000000000000000
--- a/src/iamap/iamap.py
+++ /dev/null
@@ -1,234 +0,0 @@
-import processing
-from PyQt5.QtWidgets import (
-    QAction,
-    QToolBar,
-    QApplication,
-    QDialog
-)
-from PyQt5.QtCore import pyqtSignal, QObject
-from qgis.core import QgsApplication
-from qgis.gui import QgisInterface
-from .provider import IAMapProvider
-from .icons import QIcon_EncoderTool, QIcon_ReductionTool, QIcon_ClusterTool, QIcon_SimilarityTool, QIcon_RandomforestTool
-
-
-class IAMap(QObject):
-    execute_iamap = pyqtSignal()
-
-    def __init__(self, iface: QgisInterface, cwd: str):
-        super().__init__()
-        self.iface = iface
-        self.cwd = cwd
-
-    def initProcessing(self):
-        self.provider = IAMapProvider()
-        QgsApplication.processingRegistry().addProvider(self.provider)
-
-    def initGui(self):
-        self.initProcessing()
-
-        self.toolbar: QToolBar = self.iface.addToolBar('IAMap Toolbar')
-        self.toolbar.setObjectName('IAMapToolbar')
-        self.toolbar.setToolTip('IAMap Toolbar')
-
-        self.actionEncoder = QAction(
-            QIcon_EncoderTool,
-            "Deep Learning Image Encoder",
-            self.iface.mainWindow()
-        )
-        self.actionReducer = QAction(
-            QIcon_ReductionTool,
-            "Reduce dimensions",
-            self.iface.mainWindow()
-        )
-        self.actionCluster = QAction(
-            QIcon_ClusterTool,
-            "Cluster raster",
-            self.iface.mainWindow()
-        )
-        self.actionSimilarity = QAction(
-            QIcon_SimilarityTool,
-            "Compute similarity",
-            self.iface.mainWindow()
-        )
-        self.actionRF = QAction(
-            QIcon_RandomforestTool,
-            "Use Random Forest algorithm",
-            self.iface.mainWindow()
-        )
-        self.actionEncoder.setObjectName("mActionEncoder")
-        self.actionReducer.setObjectName("mActionReducer")
-        self.actionCluster.setObjectName("mActionCluster")
-        self.actionSimilarity.setObjectName("mactionSimilarity")
-        self.actionRF.setObjectName("mactionRF")
-
-        self.actionEncoder.setToolTip(
-            "Encode a raster with a deep learning backbone")
-        self.actionReducer.setToolTip(
-            "Reduce raster dimensions")
-        self.actionCluster.setToolTip(
-            "Cluster raster")
-        self.actionSimilarity.setToolTip(
-            "Compute similarity")
-        self.actionRF.setToolTip(
-            "Use Random Forest ")
-
-        self.actionEncoder.triggered.connect(self.encodeImage)
-        self.actionReducer.triggered.connect(self.reduceImage)
-        self.actionCluster.triggered.connect(self.clusterImage)
-        self.actionSimilarity.triggered.connect(self.similarityImage)
-        self.actionRF.triggered.connect(self.rfImage)
-
-        self.toolbar.addAction(self.actionEncoder)
-        self.toolbar.addAction(self.actionReducer)
-        self.toolbar.addAction(self.actionCluster)
-        self.toolbar.addAction(self.actionSimilarity)
-        self.toolbar.addAction(self.actionRF)
-
-    def unload(self):
-        # self.wdg_select.setVisible(False)
-        self.iface.removeToolBarIcon(self.actionEncoder)
-        self.iface.removeToolBarIcon(self.actionReducer)
-        self.iface.removeToolBarIcon(self.actionCluster)
-        self.iface.removeToolBarIcon(self.actionSimilarity)
-        self.iface.removeToolBarIcon(self.actionRF)
-
-        del self.actionEncoder
-        del self.actionReducer
-        del self.actionCluster
-        del self.actionSimilarity
-        del self.actionRF
-        del self.toolbar
-        QgsApplication.processingRegistry().removeProvider(self.provider)
-
-    def encodeImage(self):
-        '''
-        '''
-        result = processing.execAlgorithmDialog('iamap:encoder', {})
-        print(result)
-                # Check if algorithm execution was successful
-        if result:
-            # Retrieve output parameters from the result dictionary
-            if 'OUTPUT_RASTER' in result:
-                output_raster_path = result['OUTPUT_RASTER']
-
-                # Add the output raster layer to the map canvas
-                self.iface.addRasterLayer(str(output_raster_path), 'merged features')
-            else:
-                # Handle missing or unexpected output
-                print('Output raster not found in algorithm result.')
-        else:
-            # Handle algorithm execution failure or cancellation
-            print('Algorithm execution was not successful.')
-        # processing.execAlgorithmDialog('', {})
-        # self.close_all_dialogs()
-
-
-    def reduceImage(self):
-        '''
-        '''
-        result = processing.execAlgorithmDialog('iamap:reduction', {})
-        print(result)
-                # Check if algorithm execution was successful
-        if result:
-            # Retrieve output parameters from the result dictionary
-            if 'OUTPUT_RASTER' in result:
-                output_raster_path = result['OUTPUT_RASTER']
-
-                # Add the output raster layer to the map canvas
-                self.iface.addRasterLayer(str(output_raster_path), 'reduced features')
-            else:
-                # Handle missing or unexpected output
-                print('Output raster not found in algorithm result.')
-        else:
-            # Handle algorithm execution failure or cancellation
-            print('Algorithm execution was not successful.')
-        # processing.execAlgorithmDialog('', {})
-
-
-    def clusterImage(self):
-        '''
-        '''
-        result = processing.execAlgorithmDialog('iamap:cluster', {})
-        print(result)
-                # Check if algorithm execution was successful
-        if result:
-            # Retrieve output parameters from the result dictionary
-            if 'OUTPUT_RASTER' in result:
-                output_raster_path = result['OUTPUT_RASTER']
-
-                # Add the output raster layer to the map canvas
-                self.iface.addRasterLayer(str(output_raster_path), 'clustering')
-            else:
-                # Handle missing or unexpected output
-                print('Output raster not found in algorithm result.')
-        else:
-            # Handle algorithm execution failure or cancellation
-            print('Algorithm execution was not successful.')
-        # processing.execAlgorithmDialog('', {})
-
-
-    def similarityImage(self):
-        '''
-        '''
-        result = processing.execAlgorithmDialog('iamap:similarity', {})
-        print(result)
-                # Check if algorithm execution was successful
-        if result:
-            # Retrieve output parameters from the result dictionary
-            if 'OUTPUT_RASTER' in result:
-                output_raster_path = result['OUTPUT_RASTER']
-
-                # Add the output raster layer to the map canvas
-                self.iface.addRasterLayer(str(output_raster_path), 'similarity map')
-            else:
-                # Handle missing or unexpected output
-                print('Output raster not found in algorithm result.')
-        else:
-            # Handle algorithm execution failure or cancellation
-            print('Algorithm execution was not successful.')
-        # processing.execAlgorithmDialog('', {})
-        
-    def rfImage(self):
-        '''
-        '''
-        result = processing.execAlgorithmDialog('iamap:Random_forest', {})
-        print(result)
-                # Check if algorithm execution was successful
-        if result:
-            # Retrieve output parameters from the result dictionary
-            if 'OUTPUT_RASTER' in result:
-                output_raster_path = result['OUTPUT_RASTER']
-
-                # Add the output raster layer to the map canvas
-                self.iface.addRasterLayer(str(output_raster_path), 'random forest map')
-            else:
-                # Handle missing or unexpected output
-                print('Output raster not found in algorithm result.')
-        else:
-            # Handle algorithm execution failure or cancellation
-            print('Algorithm execution was not successful.')
-        # processing.execAlgorithmDialog('', {})
-
-
-
-    def close_all_dialogs(self):
-        # Get the main QGIS window (QgisInterface)
-        qgis_main_window = self.iface.mainWindow()
-
-        # Get all open dialogs associated with the main window
-        open_dialogs = qgis_main_window.findChildren(QDialog)
-
-        # Iterate through the open dialogs and close them
-        for dialog in open_dialogs:
-            # Check if the dialog is visible (to avoid closing hidden dialogs)
-            if dialog.isVisible():
-                # Close the dialog
-                dialog.close()
-
-
-
-
-
-
-
diff --git a/src/iamap/provider.py b/src/iamap/provider.py
deleted file mode 100644
index 5d7797bfc1ddd3afd46f225265754a7fe4465730..0000000000000000000000000000000000000000
--- a/src/iamap/provider.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from qgis.core import QgsProcessingProvider
-
-from .encoder import EncoderAlgorithm
-from .reduction import ReductionAlgorithm
-from .clustering import ClusterAlgorithm
-from .similarity import SimilarityAlgorithm
-from .random_forest import RFAlgorithm
-from .icons import QIcon_EncoderTool
-
-
-class IAMapProvider(QgsProcessingProvider):
-
-    def loadAlgorithms(self, *args, **kwargs):
-        self.addAlgorithm(EncoderAlgorithm())
-        self.addAlgorithm(ReductionAlgorithm())
-        self.addAlgorithm(ClusterAlgorithm())
-        self.addAlgorithm(SimilarityAlgorithm())
-        self.addAlgorithm(RFAlgorithm())
-        # add additional algorithms here
-        # self.addAlgorithm(MyOtherAlgorithm())
-
-    def id(self, *args, **kwargs):
-        """The ID of your plugin, used for identifying the provider.
-
-        This string should be a unique, short, character only string,
-        eg "qgis" or "gdal". This string should not be localised.
-        """
-        return 'iamap'
-
-    def name(self, *args, **kwargs):
-        """The human friendly name of your plugin in Processing.
-
-        This string should be as short as possible (e.g. "Lastools", not
-        "Lastools version 1.0.1 64-bit") and localised.
-        """
-        return self.tr('IAMap')
-
-    def icon(self):
-        """Should return a QIcon which is used for your provider inside
-        the Processing toolbox.
-        """
-        return QIcon_EncoderTool
-
-    def longName(self) -> str:
-        return self.name()
-
diff --git a/src/iamap/utils/geo.py b/src/iamap/utils/geo.py
deleted file mode 100644
index 4d5d6f84774f83adc7fe471440e1e348da3b47a8..0000000000000000000000000000000000000000
--- a/src/iamap/utils/geo.py
+++ /dev/null
@@ -1,118 +0,0 @@
-from typing import Callable, Union
-import rasterio
-import geopandas as gpd
-import numpy as np
-import warnings
-from rasterio.io import MemoryFile
-from rasterio.merge import merge
-
-def replace_nan_with_zero(array):
-    array[array != array] = 0  # Replace NaN values with zero
-    return array
-
-def custom_method_avg(merged_data, new_data, merged_mask, new_mask, **kwargs):
-    """Returns the average value pixel.
-    cf. https://amanbagrecha.github.io/posts/2022-07-31-merge-rasters-the-modern-way-using-python/index.html
-    """
-    mask = np.empty_like(merged_mask, dtype="bool")
-    np.logical_or(merged_mask, new_mask, out=mask)
-    np.logical_not(mask, out=mask)
-    np.nanmean([merged_data, new_data], axis=0, out=merged_data, where=mask)
-    np.logical_not(new_mask, out=mask)
-    np.logical_and(merged_mask, mask, out=mask)
-    np.copyto(merged_data, new_data, where=mask, casting="unsafe")
-
-def merge_tiles(
-        tiles:list, 
-        dst_path,
-        dtype:str = 'float32',
-        nodata=None,
-        #method:str | Callable ='first',
-        method: Union[str, Callable] = 'first',
-        ):
-    """
-    cf. https://amanbagrecha.github.io/posts/2022-07-31-merge-rasters-the-modern-way-using-python/index.html
-    """
-
-    file_handler = [rasterio.open(ds) for ds in tiles]
-    extents = [ds.bounds for ds in file_handler]
-    # Extract individual bounds
-    lefts, bottoms, rights, tops = zip(*extents)
-    union_extent = (
-        min(lefts),     # Left
-        min(bottoms),   # Bottom
-        max(rights),    # Right
-        max(tops)       # Top
-    )
-
-    if method == 'average':
-        method = custom_method_avg
-
-    # memfile = MemoryFile()
-    merge(datasets=file_handler, # list of dataset objects opened in 'r' mode
-        bounds=union_extent, # tuple
-        nodata=nodata, # float
-        dtype=dtype, # dtype
-        # resampling=Resampling.nearest,
-        method=method, # strategy to combine overlapping rasters
-        # dst_path=memfile.name, # str or PathLike to save raster
-        dst_path=dst_path,
-        # dst_kwds={'blockysize':512, 'blockxsize':512} # Dictionary
-      )
-
-def get_mean_sd_by_band(path, force_compute=True, ignore_zeros=True):
-    '''
-    Reads metadata or computes mean and sd of each band of a geotiff.
-    If the metadata is not available, mean and standard deviation can be computed via numpy.
-
-    Parameters
-    ----------
-    path : str
-        path to a geotiff file
-    ignore_zeros : boolean
-        ignore zeros when computing mean and sd via numpy
-
-    Returns
-    -------
-    means : list
-        list of mean values per band
-    sds : list
-        list of standard deviation values per band
-    '''
-
-    src = rasterio.open(path)
-    means = []
-    sds = []
-    if force_compute:
-        for band in range(1, src.count+1):
-            arr = src.read(band)
-            arr = replace_nan_with_zero(arr)
-            if ignore_zeros:
-                mean = np.ma.masked_equal(arr, 0).mean()
-                sd = np.ma.masked_equal(arr, 0).std()
-            else:
-                mean = np.mean(arr)
-                sd = np.std(arr)
-            means.append(float(mean))
-            sds.append(float(sd))
-
-    else:
-        for band in range(1, src.count+1):
-            try:
-                tags = src.tags(band)
-                if 'STATISTICS_MEAN' in tags and 'STATISTICS_STDDEV' in tags:
-                    mean = float(tags['STATISTICS_MEAN'])
-                    sd = float(tags['STATISTICS_STDDEV'])
-                    means.append(mean)
-                    sds.append(sd)
-                else:
-                    raise KeyError("Statistics metadata not found.")
-
-            except KeyError:
-                    warnings.warn("Statistics metadata not found and computation not enabled.", UserWarning)
-            except Exception as e:
-                print(f"Error processing band {band}: {e}")
-
-    src.close()
-    return means, sds
-