diff --git a/pyqt/mainwindow.ui b/pyqt/mainwindow.ui
index 11d9858cc6171d831d6f7b6693a34fcd928516f2..ea0e8e85cad6ee316fb9a20bd56906aeef3e6332 100644
--- a/pyqt/mainwindow.ui
+++ b/pyqt/mainwindow.ui
@@ -49,6 +49,9 @@
         <height>201</height>
        </rect>
       </property>
+      <property name="selectionBehavior">
+       <enum>QAbstractItemView::SelectColumns</enum>
+      </property>
       <column>
        <property name="text">
         <string>Instrument</string>
@@ -155,12 +158,80 @@
        </item>
       </layout>
      </widget>
-     <zorder>explo_graphicsview_top</zorder>
-     <zorder>explo_tablewidget_variables</zorder>
-     <zorder>horizontalLayoutWidget_2</zorder>
-     <zorder>explo_pushbutton_add_row</zorder>
-     <zorder>horizontalLayoutWidget_3</zorder>
-     <zorder>explo_checkbox_manualevent</zorder>
+     <widget class="QGroupBox" name="explo_groupbox_setups">
+      <property name="geometry">
+       <rect>
+        <x>950</x>
+        <y>10</y>
+        <width>391</width>
+        <height>241</height>
+       </rect>
+      </property>
+      <property name="title">
+       <string>Save/load setups</string>
+      </property>
+      <widget class="QWidget" name="horizontalLayoutWidget_4">
+       <property name="geometry">
+        <rect>
+         <x>10</x>
+         <y>20</y>
+         <width>371</width>
+         <height>31</height>
+        </rect>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <item>
+         <widget class="QLabel" name="explo_label_setup_name">
+          <property name="text">
+           <string>File name:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="explo_lineedit_setup_name"/>
+        </item>
+        <item>
+         <widget class="QPushButton" name="explo_pushbutton_setup_save">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="text">
+           <string>Save current setup</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QListWidget" name="explo_listwidget_setup_list">
+       <property name="geometry">
+        <rect>
+         <x>15</x>
+         <y>70</y>
+         <width>281</width>
+         <height>161</height>
+        </rect>
+       </property>
+       <property name="selectionBehavior">
+        <enum>QAbstractItemView::SelectRows</enum>
+       </property>
+      </widget>
+      <widget class="QPushButton" name="explo_pushbutton_setup_load">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="geometry">
+        <rect>
+         <x>301</x>
+         <y>70</y>
+         <width>81</width>
+         <height>23</height>
+        </rect>
+       </property>
+       <property name="text">
+        <string>Load selected</string>
+       </property>
+      </widget>
+     </widget>
     </widget>
     <widget class="QWidget" name="tab_conductcalib">
      <attribute name="title">
@@ -387,7 +458,7 @@
      <x>0</x>
      <y>0</y>
      <width>1355</width>
-     <height>26</height>
+     <height>20</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuInstrument">
diff --git a/src/dataprovider/exploprovider.py b/src/dataprovider/exploprovider.py
index 17203a9087f1fed98d0aa66f3e8d542f3093f153..c8b4c096dfa484e1e912db0cf385f2b635758230 100644
--- a/src/dataprovider/exploprovider.py
+++ b/src/dataprovider/exploprovider.py
@@ -3,6 +3,8 @@ import datetime
 import os
 import re
 import xmltodict
+import xml.etree.cElementTree as ET
+from io import StringIO
 
 import utils
 from dataprovider.picarroprovider import PicarroProvider
@@ -69,6 +71,10 @@ class Dataset:
         self.instlogs = {}
         self.manual_event_log = None
 
+        # Setup save/load
+        self.saved_setup_dir = self.full_directory_name + "/saved_setups/"
+        self.saved_setup_ext = ".xml"
+
         self.explore_dataset()
 
     def explore_dataset(self) -> None:
@@ -123,6 +129,80 @@ class Dataset:
             picarro_log = InstrumentPeriodicLog(self.full_directory_name, picarro_filename, "PICARRO")
             self.instlogs["PICARRO_periodic"] = picarro_log
 
+    def save_setup(self, setup_name: str, variable_df: pd.DataFrame, view_range: list) -> None:
+        # Build 'saved setup' full file name
+        if not os.path.exists(self.saved_setup_dir):
+            os.mkdir(self.saved_setup_dir)
+        filename = self.saved_setup_dir + setup_name + self.saved_setup_ext
+
+        # Variables table
+        variables_str = variable_df.to_csv(sep=";",
+                                           index=False,
+                                           mode='w')
+
+        # Create XML file
+        root_elmt = ET.Element("save")
+        ET.SubElement(root_elmt, "variables").text = variables_str
+        view_range_elmt = ET.SubElement(root_elmt, "view_range")
+        ET.SubElement(view_range_elmt, "xmin").text = "{:.2f}".format(view_range[0][0])
+        ET.SubElement(view_range_elmt, "xmax").text = "{:.2f}".format(view_range[0][1])
+        ET.SubElement(view_range_elmt, "ymin").text = "{:.4f}".format(view_range[1][0])
+        ET.SubElement(view_range_elmt, "ymax").text = "{:.4f}".format(view_range[1][1])
+
+        tree = ET.ElementTree(root_elmt)
+        tree.write(filename)
+
+    def load_setup(self, filename: str) -> tuple:
+        full_filename = self.saved_setup_dir + filename + self.saved_setup_ext
+
+        # Open XML file
+        tree = ET.parse(full_filename)
+        root = tree.getroot()
+
+        # Variable CSV table as pd.Dataframe
+        variables_str = root.findall("variables")[0].text
+        variable_io = StringIO(variables_str)
+        variable_df = pd.read_csv(variable_io, sep=";")
+
+        # View range
+        view_range_elmt = root.findall("view_range")[0]
+        view_range_dict = {"xmin": float(view_range_elmt.findall("xmin")[0].text),
+                           "xmax": float(view_range_elmt.findall("xmax")[0].text),
+                           "ymin": float(view_range_elmt.findall("ymin")[0].text),
+                           "ymax": float(view_range_elmt.findall("ymax")[0].text)}
+
+        return variable_df, view_range_dict
+
+    def setup_filename_is_valid(self, filename: str) -> tuple:
+        """Check if the file name is valid: no special characters, file does not already exists.
+
+        Parameters
+        ----------
+        filename: str
+            filename (without extension) to be tested.
+
+        Returns
+        -------
+        bool:
+            True if the file name is valid, False otherwise
+        str:
+            The error message explaining why the file name is not valid ; an empty string if file name is valid.
+        """
+        if not re.match("^[A-Za-z0-9_-]*$", filename):
+            error_msg = "File name can only contain letters, digits and '-' or '_'. File extension is automatically set."
+            return False, error_msg
+        elif filename in self.get_setup_saved_files():
+            error_msg = "File already exists."
+            return False, error_msg
+        else:
+            return True, ""
+
+    def get_setup_saved_files(self) -> list:
+        """Get a list of the 'setup' file names (without extension) existing in the 'saved_setups' directory."""
+        filenames = os.listdir(self.saved_setup_dir)
+        files_without_ext = [os.path.splitext(filename)[0] for filename in filenames]
+        return files_without_ext
+
 
 class InstrumentLog:
 
diff --git a/src/gui/uimainwindow.py b/src/gui/uimainwindow.py
index f050c65c63f203653170308e5ce718f558f81701..2322e2334cdc65eaa500e40002ed28867c795206 100644
--- a/src/gui/uimainwindow.py
+++ b/src/gui/uimainwindow.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-# Form implementation generated from reading ui file '../pyqt/mainwindow.ui'
+# Form implementation generated from reading ui file '..\pyqt\mainwindow.ui'
 #
 # Created by: PyQt5 UI code generator 5.11.3
 #
@@ -24,6 +24,7 @@ class Ui_MainWindow(object):
         self.explo_graphicsview_top.setObjectName("explo_graphicsview_top")
         self.explo_tablewidget_variables = QtWidgets.QTableWidget(self.tab_explo)
         self.explo_tablewidget_variables.setGeometry(QtCore.QRect(20, 50, 921, 201))
+        self.explo_tablewidget_variables.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectColumns)
         self.explo_tablewidget_variables.setObjectName("explo_tablewidget_variables")
         self.explo_tablewidget_variables.setColumnCount(9)
         self.explo_tablewidget_variables.setRowCount(0)
@@ -70,12 +71,33 @@ class Ui_MainWindow(object):
         self.explo_checkbox_manualevent = QtWidgets.QCheckBox(self.horizontalLayoutWidget_3)
         self.explo_checkbox_manualevent.setObjectName("explo_checkbox_manualevent")
         self.horizontalLayout_3.addWidget(self.explo_checkbox_manualevent)
-        self.explo_graphicsview_top.raise_()
-        self.explo_tablewidget_variables.raise_()
-        self.horizontalLayoutWidget_2.raise_()
-        self.explo_pushbutton_add_row.raise_()
-        self.horizontalLayoutWidget_3.raise_()
-        self.explo_checkbox_manualevent.raise_()
+        self.explo_groupbox_setups = QtWidgets.QGroupBox(self.tab_explo)
+        self.explo_groupbox_setups.setGeometry(QtCore.QRect(950, 10, 391, 241))
+        self.explo_groupbox_setups.setObjectName("explo_groupbox_setups")
+        self.horizontalLayoutWidget_4 = QtWidgets.QWidget(self.explo_groupbox_setups)
+        self.horizontalLayoutWidget_4.setGeometry(QtCore.QRect(10, 20, 371, 31))
+        self.horizontalLayoutWidget_4.setObjectName("horizontalLayoutWidget_4")
+        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_4)
+        self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
+        self.explo_label_setup_name = QtWidgets.QLabel(self.horizontalLayoutWidget_4)
+        self.explo_label_setup_name.setObjectName("explo_label_setup_name")
+        self.horizontalLayout_4.addWidget(self.explo_label_setup_name)
+        self.explo_lineedit_setup_name = QtWidgets.QLineEdit(self.horizontalLayoutWidget_4)
+        self.explo_lineedit_setup_name.setObjectName("explo_lineedit_setup_name")
+        self.horizontalLayout_4.addWidget(self.explo_lineedit_setup_name)
+        self.explo_pushbutton_setup_save = QtWidgets.QPushButton(self.horizontalLayoutWidget_4)
+        self.explo_pushbutton_setup_save.setEnabled(False)
+        self.explo_pushbutton_setup_save.setObjectName("explo_pushbutton_setup_save")
+        self.horizontalLayout_4.addWidget(self.explo_pushbutton_setup_save)
+        self.explo_listwidget_setup_list = QtWidgets.QListWidget(self.explo_groupbox_setups)
+        self.explo_listwidget_setup_list.setGeometry(QtCore.QRect(15, 70, 281, 161))
+        self.explo_listwidget_setup_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        self.explo_listwidget_setup_list.setObjectName("explo_listwidget_setup_list")
+        self.explo_pushbutton_setup_load = QtWidgets.QPushButton(self.explo_groupbox_setups)
+        self.explo_pushbutton_setup_load.setEnabled(False)
+        self.explo_pushbutton_setup_load.setGeometry(QtCore.QRect(301, 70, 81, 23))
+        self.explo_pushbutton_setup_load.setObjectName("explo_pushbutton_setup_load")
         self.tabWidget.addTab(self.tab_explo, "")
         self.tab_conductcalib = QtWidgets.QWidget()
         self.tab_conductcalib.setObjectName("tab_conductcalib")
@@ -155,7 +177,7 @@ class Ui_MainWindow(object):
         self.tabWidget.addTab(self.tab_conductcalib, "")
         MainWindow.setCentralWidget(self.centralwidget)
         self.menubar = QtWidgets.QMenuBar(MainWindow)
-        self.menubar.setGeometry(QtCore.QRect(0, 0, 1355, 26))
+        self.menubar.setGeometry(QtCore.QRect(0, 0, 1355, 20))
         self.menubar.setObjectName("menubar")
         self.menuInstrument = QtWidgets.QMenu(self.menubar)
         self.menuInstrument.setObjectName("menuInstrument")
@@ -212,6 +234,10 @@ class Ui_MainWindow(object):
         self.explo_label_dataset.setText(_translate("MainWindow", "Dataset:"))
         self.explo_pushbutton_add_row.setText(_translate("MainWindow", "+ Add Row"))
         self.explo_checkbox_manualevent.setText(_translate("MainWindow", "Display manual events"))
+        self.explo_groupbox_setups.setTitle(_translate("MainWindow", "Save/load setups"))
+        self.explo_label_setup_name.setText(_translate("MainWindow", "File name:"))
+        self.explo_pushbutton_setup_save.setText(_translate("MainWindow", "Save current setup"))
+        self.explo_pushbutton_setup_load.setText(_translate("MainWindow", "Load selected"))
         self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_explo), _translate("MainWindow", "Data exploration"))
         item = self.conduct_tablewidget_set.horizontalHeaderItem(0)
         item.setText(_translate("MainWindow", "Date"))
diff --git a/src/uim/explouim.py b/src/uim/explouim.py
index 1125dbd1330ecea49c4f78eacd6c042740bb350a..e3a9167912cfce731a7e8ec1980b6dab91e48c61 100644
--- a/src/uim/explouim.py
+++ b/src/uim/explouim.py
@@ -1,4 +1,5 @@
 import datetime
+import re
 import pyqtgraph as pg
 from PyQt5.QtWidgets import *
 from PyQt5.QtGui import QColor
@@ -57,6 +58,14 @@ class ExploUim:
 
         self.main_ui.explo_checkbox_manualevent.stateChanged.connect(self.__update_manual_event__)
 
+        # Save/load current setup
+        self.main_ui.explo_lineedit_setup_name.textChanged.connect(self.__check_setup_save_name__)
+        self.main_ui.explo_pushbutton_setup_save.clicked.connect(self.__save_setup__)
+        self.__refresh_existing_setups__()
+        self.main_ui.explo_listwidget_setup_list.itemClicked.connect(
+            lambda: self.main_ui.explo_pushbutton_setup_load.setEnabled(True))
+        self.main_ui.explo_pushbutton_setup_load.clicked.connect(self.__load_setup__)
+
     def __initialize_dataset_combobox__(self):
         """Populate the "datasets" combobox with the existing dataset directory names."""
         data_root_dir = self.config.read("DATA_SOURCE", "absolute_root_dir")
@@ -68,6 +77,7 @@ class ExploUim:
         self.__update_current_dataset__(dataset_dirs[0])
 
     def __update_current_dataset__(self, dataset_dir: str, ask_confirmation: bool = True):
+        # Clear table and plot
         self.main_ui.explo_tablewidget_variables.setRowCount(0)
         self.__initialize_plot__()
 
@@ -79,6 +89,10 @@ class ExploUim:
         self.main_ui.explo_checkbox_manualevent.setEnabled(self.current_dataset.manual_event_log is not None)
         self.main_ui.explo_checkbox_manualevent.setChecked(False)
 
+        # Update 'existing setups'
+        self.__refresh_existing_setups__()
+        self.main_ui.explo_pushbutton_setup_load.setEnabled(False)
+
     ####################################################################################################################
     # "Variables" table
 
@@ -162,6 +176,9 @@ class ExploUim:
 
         self.__update_instruments_combobox__(row_id)
 
+        if hasattr(self, "plot_item"):
+            self.plot_item.getViewBox().enableAutoRange(enable=True)
+
     def __update_instruments_combobox__(self, row_id: int):
         instrument_combobox = self.main_ui.explo_tablewidget_variables.cellWidget(row_id, self.INSTRUMENT_COL)
         instrument_combobox.clear()
@@ -232,10 +249,6 @@ class ExploUim:
         # Get variable visibility
         visible = table.cellWidget(row_id, self.VISIBLE_COL).isChecked()
 
-        if variable_name == "event":
-            self.__update_manual_event__(timeseries, row_id, color, visible)
-            return
-
         # Get position adjustment variables (offset, multiplicative factor and time shift)
         offset = table.cellWidget(row_id, self.OFFSET_COL).value()
         mult = table.cellWidget(row_id, self.MULT_COL).value()
@@ -397,4 +410,102 @@ class ExploUim:
         """
         # if self.step_curves[0].sceneBoundingRect().contains(pos):
         mouse_point = self.step_curves[0].getViewBox().mapSceneToView(pos)
-        self.cursor_vline.setPos(mouse_point.x())
\ No newline at end of file
+        self.cursor_vline.setPos(mouse_point.x())
+
+    ####################################################################################################################
+    # Save/load current setup
+
+    def __check_setup_save_name__(self, filename: str):
+        valid, error_msg = self.current_dataset.setup_filename_is_valid(filename)
+        if not valid:
+            self.main_ui.statusbar.showMessage(error_msg, 5000)
+            self.main_ui.explo_lineedit_setup_name.setStyleSheet("color: 'red';")
+            self.main_ui.explo_pushbutton_setup_save.setEnabled(False)
+        else:
+            self.main_ui.explo_pushbutton_setup_save.setEnabled(True)
+            self.main_ui.explo_lineedit_setup_name.setStyleSheet("color: 'black';")
+
+    def __save_setup__(self):
+        # Dataset
+        dataset = self.current_dataset
+
+        # File name
+        filename = self.main_ui.explo_lineedit_setup_name.text()
+
+        # Variables
+        variable_df = pd.DataFrame()
+        table = self.main_ui.explo_tablewidget_variables
+        for row_id in range(table.rowCount()):
+            row_dict = {"instrument": table.cellWidget(row_id, self.INSTRUMENT_COL).currentText(),
+                        "variable": table.cellWidget(row_id, self.VARIABLE_COL).currentText(),
+                        "color": table.item(row_id, self.COLOR_COL).background().color().name(),
+                        "offset": table.cellWidget(row_id, self.OFFSET_COL).value(),
+                        "mult": table.cellWidget(row_id, self.MULT_COL).value(),
+                        "timeshift": table.cellWidget(row_id, self.TIMESHIFT_COL).value(),
+                        "visible": table.cellWidget(row_id, self.VISIBLE_COL).checkState() == 2}
+            variable_df = variable_df.append(row_dict, ignore_index=True)
+
+        # View range
+        view_range = self.plot_item.getViewBox().viewRange()
+
+        dataset.save_setup(filename, variable_df, view_range)
+        self.__refresh_existing_setups__()
+
+        # Reset filename input widgets
+        self.main_ui.explo_lineedit_setup_name.setText(None)
+        self.main_ui.explo_pushbutton_setup_save.setEnabled(False)
+
+    def __load_setup__(self):
+        # Clear table and plot
+        self.main_ui.explo_tablewidget_variables.setRowCount(0)
+        self.__initialize_plot__()
+
+        # Get a dataframe containing the variables data
+        filename = self.main_ui.explo_listwidget_setup_list.selectedItems()[0].text()
+        variable_df, view_range_dict = self.current_dataset.load_setup(filename)
+
+        # Variables: table (and automatically: plot)
+        table = self.main_ui.explo_tablewidget_variables
+        for row_id, row in variable_df.iterrows():
+            self.__add_new_row_in_variable_table__()
+
+            # Instrument
+            instrument_index = table.cellWidget(row_id, self.INSTRUMENT_COL).findText(row["instrument"])
+            table.cellWidget(row_id, self.INSTRUMENT_COL).setCurrentIndex(instrument_index)
+
+            # Variable
+            variable_index = table.cellWidget(row_id, self.VARIABLE_COL).findText(row["variable"])
+            table.cellWidget(row_id, self.VARIABLE_COL).setCurrentIndex(variable_index)
+
+            # Color
+            color = QColor(row["color"])
+            table.item(row_id, self.COLOR_COL).setBackground(color)
+
+            # Offset
+            table.cellWidget(row_id, self.OFFSET_COL).setValue(row["offset"])
+
+            # Mult
+            table.cellWidget(row_id, self.MULT_COL).setValue(row["mult"])
+
+            # Timeshift
+            table.cellWidget(row_id, self.TIMESHIFT_COL).setValue(row["timeshift"])
+
+            # Visible
+            table.cellWidget(row_id, self.VISIBLE_COL).setChecked(row["visible"])
+
+            self.__apply_variable_change__(row_id)  # Useful only for color change
+
+        # Plot view range
+        self.plot_item.getViewBox().enableAutoRange(enable=False)
+        # self.plot_item.getViewBox().setYRange(view_range_dict["ymin"], view_range_dict["ymax"], padding=0)
+        # self.plot_item.getViewBox().setXRange(view_range_dict["xmin"], view_range_dict["xmax"], padding=0)
+
+        self.plot_item.getViewBox().setRange(xRange=(view_range_dict["xmin"], view_range_dict["xmax"]),
+                                             yRange=(view_range_dict["ymin"], view_range_dict["ymax"]),
+                                             padding=0)
+
+    def __refresh_existing_setups__(self):
+        files = self.current_dataset.get_setup_saved_files()
+        self.main_ui.explo_listwidget_setup_list.clear()
+        for file in files:
+            self.main_ui.explo_listwidget_setup_list.addItem(file)