# ============================================================================== #
    # mainwindow.py - AcouSed                                   #
    # Copyright (C) 2024  INRAE                                              #
    #                                                                        #
    # This program is free software: you can redistribute it and/or modify   #
    # it under the terms of the GNU General Public License as published by   #
    # the Free Software Foundation, either version 3 of the License, or      #
    # (at your option) any later version.                                    #
    #                                                                        #
    # This program is distributed in the hope that it will be useful,        #
    # but WITHOUT ANY WARRANTY; without even the implied warranty of         #
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
    # GNU General Public License for more details.                           #
    #                                                                        #
    # You should have received a copy of the GNU General Public License      #
    # along with this program.  If not, see <https://www.gnu.org/licenses/>. #

#                                                      by Brahim MOUDJED #
# ============================================================================== #

# -*- coding: utf-8 -*-

import os
import logging

import numpy as np
import pandas as pd
import itertools

import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm, BASE_COLORS
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolBar

from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QLabel,
    QSpacerItem, QSizePolicy, QTableWidget, QPushButton, QLineEdit,
    QTableWidgetItem, QComboBox, QFileDialog, QGridLayout, QMessageBox
)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QCoreApplication, pyqtSignal

from Model.granulo_loader import GranuloLoader

from View.checkable_combobox import CheckableComboBox

import Translation.constant_string as cs

import settings as stg

_translate = QCoreApplication.translate

logger = logging.getLogger()

class SampleDataTab(QWidget):

    clickedState = pyqtSignal(bool)
    ShowPopUpWindowSignal = pyqtSignal()

    def __init__(self, widget_tab):
        super().__init__()

        icon_folder = QIcon(os.path.join("icons", "folder.png"))

        ### --- General layout of widgets ---

        self.verticalLayout_sampleDataTab = QVBoxLayout(widget_tab)

        self.horizontalLayoutTop_sampleDataTab = QHBoxLayout()
        self.verticalLayout_sampleDataTab.addLayout(self.horizontalLayoutTop_sampleDataTab, 5)

        self.horizontalLayoutBottom_sampleDataTab = QHBoxLayout()
        self.verticalLayout_sampleDataTab.addLayout(self.horizontalLayoutBottom_sampleDataTab, 5)

        # --------------------------------------------------------------------------------------------------------------
        ### --- Layout of groupbox in the Top horizontal layout box

        #   Sample position     |     Table of values fines
        #   Display options     |     Table of values sand

        self.verticalLayout_groupboxes_plot_sample_position_display_option = QVBoxLayout()
        self.horizontalLayoutTop_sampleDataTab.addLayout(self.verticalLayout_groupboxes_plot_sample_position_display_option, 4)

        self.groupbox_plot_sample_position_on_transect = QGroupBox()
        self.verticalLayout_groupboxes_plot_sample_position_display_option.addWidget(self.groupbox_plot_sample_position_on_transect, 7)

        self.groupbox_display_option = QGroupBox()
        self.verticalLayout_groupboxes_plot_sample_position_display_option.addWidget(self.groupbox_display_option, 3)

        self.groupbox_fine = QGroupBox()
        self.horizontalLayoutTop_sampleDataTab.addWidget(self.groupbox_fine, 4)

        self.groupbox_sand = QGroupBox()
        self.horizontalLayoutTop_sampleDataTab.addWidget(self.groupbox_sand, 4)

        # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        # +++ --- GroupBox download and visualize tables of values --- +++
        # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        # --- Download + Table of values : fine sediments ---
        self.verticalLayout_groupbox_fine = QVBoxLayout(self.groupbox_fine)
        self.groupbox_fine.setTitle("Fine sediments")

        self.horizontalLayout_download_fine_sediment = QHBoxLayout()
        self.verticalLayout_groupbox_fine.addLayout(self.horizontalLayout_download_fine_sediment)
        self.pushbutton_fine_sediment = QPushButton()
        self.pushbutton_fine_sediment.setIcon(icon_folder)
        self.horizontalLayout_download_fine_sediment.addWidget(self.pushbutton_fine_sediment)
        self.lineEdit_fine_sediment = QLineEdit()
        self.horizontalLayout_download_fine_sediment.addWidget(self.lineEdit_fine_sediment)
        self.horizontalSpacerItem_fine = QSpacerItem(50, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout_download_fine_sediment.addItem(self.horizontalSpacerItem_fine)

        self.tableWidget_fine = QTableWidget()
        self.row_fine = self.tableWidget_fine.setRowCount(10)
        self.column_fine = self.tableWidget_fine.setColumnCount(10)
        self.verticalLayout_groupbox_fine.addWidget(self.tableWidget_fine)

        # --- Download + Table of values : sand sediments ---
        self.verticalLayout_groupbox_sand = QVBoxLayout(self.groupbox_sand)
        self.groupbox_sand.setTitle("Sand sediments")

        self.horizontalLayout_download_sand_sediment = QHBoxLayout()
        self.verticalLayout_groupbox_sand.addLayout(self.horizontalLayout_download_sand_sediment)
        self.pushbutton_sand_sediment = QPushButton()
        self.pushbutton_sand_sediment.setIcon(icon_folder)
        self.horizontalLayout_download_sand_sediment.addWidget(self.pushbutton_sand_sediment)
        self.lineEdit_sand_sediment = QLineEdit()
        self.horizontalLayout_download_sand_sediment.addWidget(self.lineEdit_sand_sediment)
        self.horizontalSpacerItem_sand = QSpacerItem(50, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout_download_sand_sediment.addItem(self.horizontalSpacerItem_sand)

        self.tableWidget_sand = QTableWidget()
        self.row_sand = self.tableWidget_sand.setRowCount(10)
        self.column_sand = self.tableWidget_sand.setColumnCount(10)
        self.verticalLayout_groupbox_sand.addWidget(self.tableWidget_sand)


        # +++++++++++++++++++++++++++++++++++++++++++++
        # +++ --- GroupBox plot sample position --- +++
        # +++++++++++++++++++++++++++++++++++++++++++++

        self.verticalLayout_groupbox_plot_sample_position_on_transect = QVBoxLayout(
            self.groupbox_plot_sample_position_on_transect)
        self.groupbox_plot_sample_position_on_transect.setTitle("Plot samples positions")

        self.horizontalLayout_pushbutton_comboboxes_sample_position_on_transect = QHBoxLayout()
        self.verticalLayout_groupbox_plot_sample_position_on_transect.addLayout(self.horizontalLayout_pushbutton_comboboxes_sample_position_on_transect)

        self.pushbutton_plot_transect = QPushButton()
        self.pushbutton_plot_transect.setText("Plot Acoustic data")
        self.horizontalLayout_pushbutton_comboboxes_sample_position_on_transect.addWidget(self.pushbutton_plot_transect)

        self.combobox_acoustic_data = QComboBox()
        self.horizontalLayout_pushbutton_comboboxes_sample_position_on_transect.addWidget(self.combobox_acoustic_data)

        self.combobox_frequencies = QComboBox()
        self.horizontalLayout_pushbutton_comboboxes_sample_position_on_transect.addWidget(self.combobox_frequencies)

        self.groupbox_plot_transect = QGroupBox()
        self.verticalLayout_groupbox_plot_transect = QVBoxLayout(self.groupbox_plot_transect)
        self.verticalLayout_groupbox_plot_sample_position_on_transect.addWidget(self.groupbox_plot_transect)

        self.canvas_plot_sample_position_on_transect = FigureCanvas()
        self.verticalLayout_groupbox_plot_transect.addWidget(self.canvas_plot_sample_position_on_transect)

        self.verticalLayout_groupbox_display_option = QVBoxLayout(self.groupbox_display_option)
        self.groupbox_display_option.setTitle("Display options")

        # +++++++++++++++++++++++++++++++++++++++
        # +++ --- GroupBox display option --- +++
        # +++++++++++++++++++++++++++++++++++++++

        self.horizontalLayout_pushbutton_combobox_transect = QHBoxLayout()
        self.verticalLayout_groupbox_display_option.addLayout(self.horizontalLayout_pushbutton_combobox_transect)

        self.horizontalLayout_Ctot_PSD_plot = QHBoxLayout()
        self.verticalLayout_groupbox_display_option.addLayout(self.horizontalLayout_Ctot_PSD_plot)

        self.groupbox_option_total_concentration_plot = QGroupBox()
        self.groupbox_option_total_concentration_plot.setTitle("Total concentration plot")
        self.horizontalLayout_Ctot_PSD_plot.addWidget(self.groupbox_option_total_concentration_plot)

        self.gridLayout_groupbox_option_total_concentration_plot = QGridLayout(
            self.groupbox_option_total_concentration_plot)
        self.label_x_axis = QLabel()
        self.label_x_axis.setText("x axis")
        self.gridLayout_groupbox_option_total_concentration_plot.addWidget(self.label_x_axis, 0, 0)

        self.combobox_x_axis = QComboBox()
        self.combobox_x_axis.addItems(['Concentration (g/L)', 'Concentration (%)'])
        self.gridLayout_groupbox_option_total_concentration_plot.addWidget(self.combobox_x_axis, 0, 1)

        self.label_y_axis = QLabel()
        self.label_y_axis.setText("y axis")
        self.gridLayout_groupbox_option_total_concentration_plot.addWidget(self.label_y_axis, 1, 0)

        self.combobox_y_axis = QComboBox()
        self.combobox_y_axis.addItems(['z (m)', 'z / h'])
        self.gridLayout_groupbox_option_total_concentration_plot.addWidget(self.combobox_y_axis, 1, 1)

        # --- Group box PSD plot ---
        self.groupbox_option_PSD_plot = QGroupBox()
        self.groupbox_option_PSD_plot.setTitle("Particle Size Distribution plot")
        self.horizontalLayout_Ctot_PSD_plot.addWidget(self.groupbox_option_PSD_plot)

        self.verticalLayout__groupbox_option_PSD_plot = QHBoxLayout(self.groupbox_option_PSD_plot)
        self.combobox_PSD_plot = QComboBox()
        self.combobox_PSD_plot.addItems(["Class PSD", "Cumulative PSD"])
        self.verticalLayout__groupbox_option_PSD_plot.addWidget(self.combobox_PSD_plot)

        # --------------------------------------------------------------------------------------------------------------
        ### --- Layout of groupbox in the Bottom horizontal layout box

        #   Plot Ctot   |   Plot PSD fine + sand

        # --- Groupbox plot total concentration of sediments ---
        self.groupbox_plot_total_concentration = QGroupBox()
        self.horizontalLayoutBottom_sampleDataTab.addWidget(self.groupbox_plot_total_concentration, 3)

        self.verticalLayout_groupbox_plot_total_concentration = QVBoxLayout(self.groupbox_plot_total_concentration)
        self.groupbox_plot_total_concentration.setTitle("Plot total concentration")

        self.canvas_plot_total_concentration = FigureCanvas()
        self.toolbar_plot_total_concentration = NavigationToolBar(self.canvas_plot_total_concentration, self)
        self.verticalLayout_groupbox_plot_total_concentration.addWidget(self.toolbar_plot_total_concentration)
        self.verticalLayout_groupbox_plot_total_concentration.addWidget(self.canvas_plot_total_concentration)

        # --- Groupbox plot Particle Size Distributions ---
        self.groupbox_plot_PSD = QGroupBox()
        self.horizontalLayoutBottom_sampleDataTab.addWidget(self.groupbox_plot_PSD, 6)

        self.verticalLayout_groupbox_plot_PSD = QVBoxLayout(self.groupbox_plot_PSD)
        self.groupbox_plot_PSD.setTitle("Plot particle size distribution")

        self.canvas_plot_PSD = FigureCanvas()
        self.toolbar_plot_PSD = NavigationToolBar(self.canvas_plot_PSD, self)
        self.verticalLayout_groupbox_plot_PSD.addWidget(self.toolbar_plot_PSD)
        self.verticalLayout_groupbox_plot_PSD.addWidget(self.canvas_plot_PSD)

        # --------------------------------------------------------------------------------------------------------------
        # --- Connect signal of widget ---

        self.pushbutton_fine_sediment.clicked.connect(self.open_dialog_box_fine_sediment)
        self.pushbutton_sand_sediment.clicked.connect(self.open_dialog_box_sand_sediment)

        self.pushbutton_plot_transect.clicked.connect(self.fill_comboboxes_and_plot_transect)

        self.combobox_PSD_plot.currentTextChanged.connect(self.plot_PSD_fine_and_sand_sediments)

    # -------------------- Functions for Sample Data Tab --------------------

    def retranslate_data_sample_tab(self):

        self.groupbox_download.setTitle(_translate("CONSTANT_STRING", cs.DOWNLOAD))
        self.groupbox_particle_size_file.setTitle(_translate("CONSTANT_STRING", cs.PARTICLE_SIZE_DISTRIBUTION_FILE))
        self.groupbox_fine_sediment.setTitle(_translate("CONSTANT_STRING", cs.FINE_SEDIMENTS))
        self.groupbox_sand.setTitle(_translate("CONSTANT_STRING", cs.SAND_SEDIMENTS))
        # self.groupbox_total_concentration.setTitle(_translate("CONSTANT_STRING", cs.TOTAL_CONCENTRATION))

        self.groupbox_table.setTitle(_translate("CONSTANT_STRING", cs.TABLE_VALUES))
        self.pushbutton_fill_table.setText(_translate("CONSTANT_STRING", cs.FILL_TABLE))
        self.allChkBox.setText(_translate("CONSTANT_STRING", cs.CHECK_ALL))
        self.pushButton_export_table.setText(_translate("CONSTANT_STRING", cs.EXPORT_TABLE))

        self.groupbox_plot_sample_position.setTitle(_translate("CONSTANT_STRING", cs.PLOT_SAMPLE_POSITION))

        self.groupbox_display_option.setTitle(_translate("CONSTANT_STRING", cs.OPTIONS))

        self.groupbox_plot_total_concentration.setTitle(_translate("CONSTANT_STRING", cs.PLOT_TOTAL_CONCENTRATION))

        self.groupbox_plot_PSD.setTitle(_translate("CONSTANT_STRING", cs.DISTRIBUTION_PLOT))


    def last_opened_file_path(self, priority="sand"):
        lst = []

        if priority == "sand":
            lst += [stg.path_sand]
            lst += [stg.path_fine]
        else:
            lst += [stg.path_fine]
            lst += [stg.path_sand]

        lst += stg.path_BS_raw_data

        for path in lst:
            if path != "":
                return path

        return ""

    def open_dialog_box_fine_sediment(self):
        filename_fine_sediment = QFileDialog.getOpenFileName(
            self, "Fine sediment file",
            self.last_opened_file_path(priority="fine"),
            "Fine sediment file (*.xlsx, *xls, *.ods)",
            options=QFileDialog.DontUseNativeDialog
        )

        try:
            stg.path_fine = os.path.dirname(filename_fine_sediment[0])
            stg.filename_fine = os.path.basename(filename_fine_sediment[0])
            self.load_fine_sediment_data()
        except IsADirectoryError:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Download Error")
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setText("Please select a file")
            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.exec()
        except Exception as e:
            logger.error(e)
        else:
            self.lineEdit_fine_sediment.clear()
            self.lineEdit_fine_sediment.setText(stg.filename_fine)
            self.lineEdit_fine_sediment.setToolTip(stg.path_fine)
            self.fill_table_fine()

    def open_dialog_box_sand_sediment(self):
        filename_sand_sediment = QFileDialog.getOpenFileName(
            self, "Sand sediment file",
            self.last_opened_file_path(priority="sand"),
            "Sand sediment file (*.xlsx, *xls, *.ods)",
            options=QFileDialog.DontUseNativeDialog)

        try:
            stg.path_sand = os.path.dirname(filename_sand_sediment[0])
            stg.filename_sand = os.path.basename(filename_sand_sediment[0])
            self.load_sand_sediment_data()
        except IsADirectoryError:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Download Error")
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setText("Please select a file")
            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.exec()
        except Exception as e:
            logger.error(e)
        else:
            self.lineEdit_sand_sediment.setText(stg.filename_sand)
            self.lineEdit_sand_sediment.setToolTip(stg.path_sand)
            self.fill_table_sand()

    def load_fine_sediment_data(self):
        fine_granulo_data = GranuloLoader(
            os.path.join(stg.path_fine, stg.filename_fine)
        )
        stg.columns_fine = fine_granulo_data._data.columns
        stg.time_fine = fine_granulo_data._time
        stg.distance_from_bank_fine = fine_granulo_data._y
        stg.depth_fine = fine_granulo_data._z
        stg.radius_grain_fine = fine_granulo_data._r_grain
        stg.Ctot_fine = fine_granulo_data._Ctot
        stg.D50_fine = fine_granulo_data._D50
        stg.frac_vol_fine = fine_granulo_data._frac_vol
        stg.frac_vol_fine_cumul = fine_granulo_data._frac_vol_cumul

    def load_sand_sediment_data(self):
        sand_granulo_data = GranuloLoader(
            os.path.join(stg.path_sand, stg.filename_sand)
        )
        stg.columns_sand = sand_granulo_data._data.columns
        stg.time_sand = sand_granulo_data._time
        stg.distance_from_bank_sand = sand_granulo_data._y
        stg.depth_sand = sand_granulo_data._z
        stg.radius_grain_sand = sand_granulo_data._r_grain
        stg.Ctot_sand = sand_granulo_data._Ctot
        stg.D50_sand = sand_granulo_data._D50
        stg.frac_vol_sand = sand_granulo_data._frac_vol
        stg.frac_vol_sand_cumul = sand_granulo_data._frac_vol_cumul

    def compute_Ctot_per_cent(self):
        if (self.lineEdit_fine_sediment.text()) and not (self.lineEdit_sand_sediment.text()):
            stg.Ctot_fine_per_cent = [100 * f / f for f in stg.Ctot_fine]
        elif not (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand_sediment.text()):
            stg.Ctot_sand_per_cent = [100 * s / s for s in stg.Ctot_sand]
        elif (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand_sediment.text()):
            stg.Ctot_fine_per_cent = [100 * f / (f + s) for f, s in zip(stg.Ctot_fine, stg.Ctot_sand)]
            stg.Ctot_sand_per_cent = [100 * s / (f + s) for f, s in zip(stg.Ctot_fine, stg.Ctot_sand)]

    # ------------------------------------------------------------------------------------------------------------------
    # --- Function to fill table of values ---
    def fill_table_fine(self):
        self.tableWidget_fine.blockSignals(True)

        if self.lineEdit_fine_sediment.text():
            self.row_fine = self.tableWidget_fine.setRowCount(
                len(stg.depth_fine)
            )
            self.column_fine = self.tableWidget_fine.setColumnCount(
                6 + stg.radius_grain_fine.shape[0]
            )

            # --- Set horizontal header ---
            horizontal_header = list(
                itertools.chain(
                    ["Color", "Sample"],
                    list(map(str, stg.columns_fine[[0, 2]])),
                    list(map(str, stg.columns_fine[3:]))
                )
            )

            for horizontal_header_text in horizontal_header:
                self.horizontal_header_item_fine = QTableWidgetItem()
                self.tableWidget_fine.setHorizontalHeaderItem(
                    horizontal_header.index(horizontal_header_text),
                    self.horizontal_header_item_fine
                )
                self.horizontal_header_item_fine.setText(horizontal_header_text)

            # --- Set vertical header (color) ---
            self.tableWidget_fine.verticalHeader().setVisible(False)
            color_list = BASE_COLORS

            self.comboBox_sample_table_fine = []
            for i in range(self.tableWidget_fine.rowCount()):
                self.comboBox_sample_table_fine.append(
                    QComboBox()
                )

                self.comboBox_sample_table_fine[i].addItems(color_list)
                self.tableWidget_fine.setCellWidget(
                    i, 0, self.comboBox_sample_table_fine[i]
                )

                self.comboBox_sample_table_fine[i]\
                    .currentTextChanged\
                    .connect(self.plot_total_concentration)
                self.comboBox_sample_table_fine[i]\
                    .currentTextChanged\
                    .connect(self.plot_PSD_fine_and_sand_sediments)
                self.comboBox_sample_table_fine[i]\
                    .currentTextChanged\
                    .connect(self.update_plot_sample_position_on_transect)

            # --- Fill Sample column with checkbox ---
            for i in range(self.tableWidget_fine.rowCount()):
                self.item_checkbox_fine = QTableWidgetItem()
                self.item_checkbox_fine.setCheckState(Qt.Checked)
                self.tableWidget_fine.setItem(i, 1, self.item_checkbox_fine)
                self.item_checkbox_fine.setText("F" + str(i + 1))
                stg.sample_fine.append(("F" + str(i + 1), i))

            # --- Fill table with data ---
            for i in range(stg.frac_vol_fine.shape[0]):
                for j in range(stg.frac_vol_fine.shape[1]):
                    self.tableWidget_fine.setItem(
                        i, 2, QTableWidgetItem(str(stg.time_fine[i]))
                    )
                    self.tableWidget_fine.setItem(
                        i, 3, QTableWidgetItem(str(stg.depth_fine[i]))
                    )
                    self.tableWidget_fine.setItem(
                        i, 4, QTableWidgetItem(str(stg.Ctot_fine[i]))
                    )
                    self.tableWidget_fine.setItem(
                        i, 5, QTableWidgetItem(str(stg.D50_fine[i]))
                    )
                    self.tableWidget_fine.setItem(
                        i, j + 6, QTableWidgetItem(str(stg.frac_vol_fine[i, j]))
                    )

            # --- Connect checkbox to all checkboxes of tableWidget ---
            # self.allChkBox.stateChanged.connect(self.check_allChkBox)

            # --- Connect checkbox items of tableWidget to update plots ---
            self.tableWidget_fine.itemChanged.connect(self.update_plot_sample_position_on_transect)
            self.tableWidget_fine.itemChanged.connect(self.plot_total_concentration)
            self.tableWidget_fine.itemChanged.connect(self.plot_PSD_fine_and_sand_sediments)

            self.combobox_x_axis.currentIndexChanged.connect(self.plot_total_concentration)
            self.combobox_y_axis.currentIndexChanged.connect(self.plot_total_concentration)

            self.plot_sample_position_on_transect()
            self.plot_total_concentration()
            self.plot_PSD_fine_and_sand_sediments()

            self.tableWidget_fine.blockSignals(False)
        else:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Fill table Error")
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setText("Download files before fill table")
            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.exec()

    def fill_table_sand(self):
        self.tableWidget_sand.blockSignals(True)

        if self.lineEdit_sand_sediment.text():
            self.row_sand = self.tableWidget_sand.setRowCount(len(stg.depth_sand))
            self.column_sand = self.tableWidget_sand.setColumnCount(6 + stg.radius_grain_sand.shape[0])
            # --- Set horizontal header ---
            horizontal_header = list(
                itertools.chain(
                    ["Color", "Sample"],
                    list(map(str, stg.columns_sand[[0, 2]])),
                    list(map(str, stg.columns_sand[3:]))
                )
            )

            for horizontal_header_text in horizontal_header:
                self.horizontal_header_item_sand = QTableWidgetItem()
                self.tableWidget_sand.setHorizontalHeaderItem(
                    horizontal_header.index(horizontal_header_text),
                    self.horizontal_header_item_sand
                )
                self.horizontal_header_item_sand.setText(horizontal_header_text)

            # --- Set vertical header (color) ---
            self.tableWidget_sand.verticalHeader().setVisible(False)
            color_list = BASE_COLORS

            self.comboBox_sample_table_sand = []
            for i in range(self.tableWidget_sand.rowCount()):
                self.comboBox_sample_table_sand.append(QComboBox())

                self.comboBox_sample_table_sand[i].addItems(color_list)
                self.tableWidget_sand.setCellWidget(
                    i, 0, self.comboBox_sample_table_sand[i]
                )

                self.comboBox_sample_table_sand[i]\
                    .currentTextChanged\
                    .connect(self.plot_total_concentration)
                self.comboBox_sample_table_sand[i]\
                    .currentTextChanged\
                    .connect(self.plot_PSD_fine_and_sand_sediments)
                self.comboBox_sample_table_sand[i]\
                    .currentTextChanged\
                    .connect(self.update_plot_sample_position_on_transect)

            # --- Fill Sample column with checkbox ---
            for i in range(self.tableWidget_sand.rowCount()):
                self.item_checkbox_sand = QTableWidgetItem()
                self.item_checkbox_sand.setCheckState(Qt.Checked)
                self.tableWidget_sand.setItem(i, 1, self.item_checkbox_sand)
                self.item_checkbox_sand.setText("S" + str(i + 1))
                stg.sample_sand.append(("S" + str(i + 1), i))

            # --- Fill table with data ---
            for i in range(stg.frac_vol_sand.shape[0]):
                for j in range(stg.frac_vol_sand.shape[1]):
                    self.tableWidget_sand.setItem(
                        i, 2, QTableWidgetItem(str(stg.time_sand[i]))
                    )
                    self.tableWidget_sand.setItem(
                        i, 3, QTableWidgetItem(str(stg.depth_sand[i]))
                    )
                    self.tableWidget_sand.setItem(
                        i, 4, QTableWidgetItem(str(stg.Ctot_sand[i]))
                    )
                    self.tableWidget_sand.setItem(
                        i, 5, QTableWidgetItem(str(stg.D50_sand[i]))
                    )
                    self.tableWidget_sand.setItem(
                        i, j + 6, QTableWidgetItem(str(stg.frac_vol_sand[i, j]))
                    )

            # --- Connect checkbox items of tableWidget to update plots ---
            self.tableWidget_sand\
                .itemChanged\
                .connect(self.update_plot_sample_position_on_transect)
            self.tableWidget_sand\
                .itemChanged\
                .connect(self.plot_total_concentration)
            self.tableWidget_sand\
                .itemChanged\
                .connect(self.plot_PSD_fine_and_sand_sediments)

            self.combobox_x_axis.currentIndexChanged\
                                .connect(self.plot_total_concentration)
            self.combobox_y_axis.currentIndexChanged\
                                .connect(self.plot_total_concentration)

            self.plot_sample_position_on_transect()
            self.plot_total_concentration()
            self.plot_PSD_fine_and_sand_sediments()

            self.tableWidget_sand.blockSignals(False)

    # --- Function to extract position of sample from table checkboxes to update plots ---
    def extract_position_list_and_color_list_from_table_checkboxes_fine(self):
        position = []
        color_list = []
        sample_checkbox = np.zeros((1, len(range(self.tableWidget_fine.rowCount()))))
        for i in range(self.tableWidget_fine.rowCount()):
            if self.tableWidget_fine.item(i, 1).checkState() == 2:
                if self.tableWidget_fine.item(i, 1).checkState() == Qt.Checked:
                    position.append(i)
                    color_list.append(self.comboBox_sample_table_fine[i].currentText())
                    sample_checkbox[0, i] = 2

        return position, color_list

    def read_select_samples_fine(self):

        # --- Read selected samples (checkboxes) ---
        position_list_fine, _ = self.extract_position_list_and_color_list_from_table_checkboxes_fine()
        Ctot_fine_to_plot = []
        Ctot_fine_percent_to_plot = []
        sample_depth_to_plot_fine = []
        indices_bottom_fine = []
        depth_bottom_to_plot_fine = []
        for k in range(len(position_list_fine)):
            Ctot_fine_to_plot.append(stg.Ctot_fine[position_list_fine[k]])
            Ctot_fine_percent_to_plot.append(stg.Ctot_fine_per_cent[position_list_fine[k]])
            sample_depth_to_plot_fine.append(stg.depth_fine[position_list_fine[k]])

            if stg.time_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                indices_bottom_fine.append(np.where(
                    np.abs(stg.time_cross_section[self.combobox_acoustic_data.currentIndex()][
                               self.combobox_frequencies.currentIndex()] - stg.time_fine[position_list_fine[k]]) ==
                    np.nanmin(
                        np.abs(stg.time_cross_section[self.combobox_acoustic_data.currentIndex()][
                                   self.combobox_frequencies.currentIndex()] - stg.time_fine[position_list_fine[k]])))[
                                               0][0])


            else:

                indices_bottom_fine.append(np.where(
                    np.abs(stg.time[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()] -
                           stg.time_fine[position_list_fine[k]]) ==
                    np.nanmin(
                        np.abs(
                            stg.time[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()] -
                            stg.time_fine[position_list_fine[k]])))[
                                               0][0])

            if stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                depth_bottom_to_plot_fine.append(
                    stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()][
                        self.combobox_frequencies.currentIndex(), -1])

            else:

                depth_bottom_to_plot_fine.append(
                    stg.depth[self.combobox_acoustic_data.currentIndex()][
                        self.combobox_frequencies.currentIndex(), -1])

            if stg.depth_bottom[self.combobox_acoustic_data.currentIndex()].shape != (0,):
                depth_bottom_to_plot_fine.append(
                stg.depth_bottom[self.combobox_acoustic_data.currentIndex()][indices_bottom_fine[-1]])

        return Ctot_fine_to_plot, Ctot_fine_percent_to_plot, sample_depth_to_plot_fine, indices_bottom_fine, depth_bottom_to_plot_fine

    def extract_position_list_and_color_list_from_table_checkboxes_sand(self):
        if self.tableWidget_sand.columnCount() > 10:
            position = []
            color_list = []
            sample_checkbox = np.zeros((1, len(range(self.tableWidget_sand.rowCount()))))
            for i in range(self.tableWidget_sand.rowCount()):
                if self.tableWidget_sand.item(i, 1).checkState() == 2:
                    if self.tableWidget_sand.item(i, 1).checkState() == Qt.Checked:
                        position.append(i)
                        color_list.append(
                            self.comboBox_sample_table_sand[i].currentText()
                        )
                        sample_checkbox[0, i] = 2
            return position, color_list

    def read_select_samples_sand(self):

        # --- Read selected sand samples (checkboxes) ---
        position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()
        Ctot_sand_to_plot = []
        Ctot_sand_percent_to_plot = []
        sample_depth_to_plot_sand = []
        indices_bottom_sand = []
        depth_bottom_to_plot_sand = []
        for k in range(len(position_list_sand)):
            Ctot_sand_to_plot.append(stg.Ctot_sand[position_list_sand[k]])
            Ctot_sand_percent_to_plot.append(stg.Ctot_sand_per_cent[position_list_sand[k]])
            sample_depth_to_plot_sand.append(stg.depth_sand[position_list_sand[k]])

            if stg.time_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                indices_bottom_sand.append(np.where(
                    np.abs(stg.time_cross_section[self.combobox_acoustic_data.currentIndex()][
                               self.combobox_frequencies.currentIndex()] - stg.time_sand[position_list_sand[k]]) ==
                    np.nanmin(
                        np.abs(stg.time_cross_section[self.combobox_acoustic_data.currentIndex()][
                                   self.combobox_frequencies.currentIndex()] - stg.time_sand[position_list_sand[k]])))[
                                               0][0])
                depth_bottom_to_plot_sand.append(
                    stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()][
                        self.combobox_frequencies.currentIndex(), -1])

            else:

                indices_bottom_sand.append(np.where(
                    np.abs(
                        stg.time[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()] -
                        stg.time_sand[position_list_sand[k]]) ==
                    np.nanmin(
                        np.abs(stg.time[self.combobox_acoustic_data.currentIndex()][
                                   self.combobox_frequencies.currentIndex()] - stg.time_sand[position_list_sand[k]])))[
                                               0][0])

            if stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                depth_bottom_to_plot_sand.append(
                    stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()][
                        self.combobox_frequencies.currentIndex(), -1])

            else:

                depth_bottom_to_plot_sand.append(
                    stg.depth[self.combobox_acoustic_data.currentIndex()][
                        self.combobox_frequencies.currentIndex(), -1])

            if stg.depth_bottom[self.combobox_acoustic_data.currentIndex()].shape != (0,):
                depth_bottom_to_plot_sand.append(
                    stg.depth_bottom[self.combobox_acoustic_data.currentIndex()][indices_bottom_sand[-1]])

        return Ctot_sand_to_plot, Ctot_sand_percent_to_plot, sample_depth_to_plot_sand, indices_bottom_sand, depth_bottom_to_plot_sand

    def check_allChkBox(self, state):
        for i in range(self.tableWidget_sample.rowCount()):
            self.tableWidget_sample.item(i, 1).setCheckState(state)

    # --- Function to export data of table ---

    def event_combobobx_acoustic_data(self):
        self.ShowPopUpWindowSignal.emit()

        self.combobox_acoustic_data.clear()
        for i in range(len(stg.filename_BS_raw_data)):
            self.combobox_acoustic_data.addItem(stg.filename_BS_raw_data[i])

        self.combobox_acoustic_data.showPopup()

    def fill_comboboxes_and_plot_transect(self):
        self.combobox_acoustic_data.clear()
        for n, m in enumerate(stg.noise_method):
            if stg.noise_method[n] == 0:
                self.combobox_acoustic_data.addItem(stg.filename_BS_raw_data[n])
            elif stg.noise_method[n]!=0:
                self.combobox_acoustic_data.addItem(stg.data_preprocessed[n])

        self.plot_sample_position_on_transect()
        self.combobox_acoustic_data.currentIndexChanged.connect(self.update_plot_sample_position_on_transect)
        self.combobox_frequencies.currentIndexChanged.connect(self.update_plot_sample_position_on_transect)

    def plot_sample_position_on_transect(self):
        self.verticalLayout_groupbox_plot_transect\
            .removeWidget(self.canvas_plot_sample_position_on_transect)

        fig, axis = plt.subplots(nrows=1, ncols=1, layout="constrained")

        self.figure_plot_sample_position_on_transect = fig
        self.axis_plot_sample_position_on_transect = axis

        self.canvas_plot_sample_position_on_transect = FigureCanvas(
            self.figure_plot_sample_position_on_transect
        )

        self.verticalLayout_groupbox_plot_transect\
            .addWidget(self.canvas_plot_sample_position_on_transect)

        if self.combobox_acoustic_data.count() == 0:
            if self.tableWidget_fine.columnCount() > 10:
                position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()

                self.axis_plot_sample_position_on_transect.scatter(
                    stg.time_fine, stg.depth_fine,
                    linestyle='None', marker="x", s=15, c=color_list_fine, label='fine')

                for i in range(len(stg.time_fine)):
                    self.axis_plot_sample_position_on_transect.text(
                        stg.time_fine[i] - 25, stg.depth_fine[i] - .1, "F" + str(i+1),
                        fontstyle="normal", fontweight="light", fontsize=8)

            if self.tableWidget_sand.columnCount() > 10:
                position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()

                self.axis_plot_sample_position_on_transect.scatter(
                    stg.time_sand, stg.depth_sand,
                    linestyle='None', marker="o", s=60, facecolors='None', edgecolors=color_list_sand, label='sand')

                for i in range(len(stg.time_sand)):
                    self.axis_plot_sample_position_on_transect.text(
                        stg.time_sand[i] + 10, stg.depth_sand[i] - .1, "S" + str(i+1),
                        fontstyle="normal", fontweight="light", fontsize=8)

        else:

            self.combobox_frequencies.clear()
            self.combobox_frequencies.addItems(stg.freq_text[self.combobox_acoustic_data.currentIndex()])

            if stg.time_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                if stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time_cross_section[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()]

                elif stg.depth[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time_cross_section[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth[self.combobox_acoustic_data.currentIndex()]

            else:

                if stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()]

                elif stg.depth[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth[self.combobox_acoustic_data.currentIndex()]

            if stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

                self.axis_plot_sample_position_on_transect.plot(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -stg.depth_bottom[self.combobox_acoustic_data.currentIndex()], color='black', linewidth=1,
                    linestyle="solid")

            elif stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

                self.axis_plot_sample_position_on_transect.plot(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -stg.depth_bottom[self.combobox_acoustic_data.currentIndex()], color='black', linewidth=1,
                    linestyle="solid")

            elif stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

                self.axis_plot_sample_position_on_transect.plot(
                        x_time[self.combobox_frequencies.currentIndex(), :],
                        -stg.depth_bottom[self.combobox_acoustic_data.currentIndex()], color='black', linewidth=1, linestyle="solid")

            elif stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(
                    stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(
                    stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(
                    stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                                    self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            if self.tableWidget_fine.columnCount() > 10:

                position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()

                self.axis_plot_sample_position_on_transect.scatter(
                    stg.time_fine, stg.depth_fine,
                    linestyle='None', marker="x", s=15, c=color_list_fine, label='fine')

                for i in range(len(stg.time_fine)):
                    self.axis_plot_sample_position_on_transect.text(
                        stg.time_fine[i] - 25, stg.depth_fine[i] - .1, "F" + str(i+1),
                        fontstyle="normal", fontweight="light", fontsize=8)

            if self.tableWidget_sand.columnCount() > 10:
                position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()

                self.axis_plot_sample_position_on_transect.scatter(
                    stg.time_sand, stg.depth_sand,
                    linestyle='None', marker="o", s=60, facecolors='None', edgecolors=color_list_sand, label='sand')

                for i in range(len(stg.time_sand)):
                    self.axis_plot_sample_position_on_transect.text(
                        stg.time_sand[i] + 10, stg.depth_sand[i] - .1, "S" + str(i+1),
                        fontstyle="normal", fontweight="light", fontsize=8)

        self.axis_plot_sample_position_on_transect.text(
            1, .85, stg.freq_text[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()],
            fontsize=14, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.5,
            horizontalalignment='right', verticalalignment='bottom',
            transform=self.axis_plot_sample_position_on_transect.transAxes)

        self.axis_plot_sample_position_on_transect.tick_params(axis='y', labelrotation=90)
        self.axis_plot_sample_position_on_transect.tick_params(axis='both', labelsize=8)

        self.axis_plot_sample_position_on_transect.text(.98, .03, "Time (sec)",
                                    fontsize=10, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.9,
                                    horizontalalignment='right', verticalalignment='bottom', rotation='horizontal',
                                    transform=self.axis_plot_sample_position_on_transect.transAxes)
        self.axis_plot_sample_position_on_transect.text(.04, .53, "Depth (m)",
                                    fontsize=10, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.9,
                                    horizontalalignment='right', verticalalignment='bottom', rotation='vertical',
                                    transform=self.axis_plot_sample_position_on_transect.transAxes)

        self.axis_plot_sample_position_on_transect.legend(loc="lower left")
        self.figure_plot_sample_position_on_transect.canvas.draw_idle()

    def update_plot_sample_position_on_transect(self):

        self.axis_plot_sample_position_on_transect.cla()

        if self.combobox_acoustic_data.count() == 0:

            if self.tableWidget_fine.columnCount() > 10:

                position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()

                if len(position_list_fine) != 0:
                    time_fine_to_plot = []
                    depth_fine_to_plot = []
                    for k in position_list_fine:
                        time_fine_to_plot.append(stg.time_fine[k])
                        depth_fine_to_plot.append(stg.depth_fine[k])

                    self.axis_plot_sample_position_on_transect.scatter(
                        time_fine_to_plot, depth_fine_to_plot,
                        linestyle='None', marker="x", s=15, c=color_list_fine, label='fine')

                    for i in range(len(time_fine_to_plot)):
                        self.axis_plot_sample_position_on_transect.text(
                            time_fine_to_plot[i] - 25, depth_fine_to_plot[i] - .1, "F" + str(i+1),
                            fontstyle="normal", fontweight="light", fontsize=8)

            if self.tableWidget_sand.columnCount() > 10:

                position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()

                if len(position_list_sand) != 0:
                    time_sand_to_plot = []
                    depth_sand_to_plot = []
                    for k in position_list_sand:
                        time_sand_to_plot.append(stg.time_sand[k])
                        depth_sand_to_plot.append(stg.depth_sand[k])

                    self.axis_plot_sample_position_on_transect.scatter(
                        time_sand_to_plot, depth_sand_to_plot,
                        linestyle='None', marker="o", s=60, facecolors='None', edgecolors=color_list_sand, label='sand')

                    for i in range(len(time_sand_to_plot)):
                        self.axis_plot_sample_position_on_transect.text(
                            time_sand_to_plot[i] + 10, depth_sand_to_plot[i] - .1, "S" + str(i+1),
                            fontstyle="normal", fontweight="light", fontsize=8)

        else:

            if stg.time_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                if stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time_cross_section[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()]

                elif stg.depth[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time_cross_section[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth[self.combobox_acoustic_data.currentIndex()]

            else:

                if stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth_cross_section[self.combobox_acoustic_data.currentIndex()]

                elif stg.depth[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                    x_time = stg.time[self.combobox_acoustic_data.currentIndex()]
                    y_depth = stg.depth[self.combobox_acoustic_data.currentIndex()]

            # --- Create canvas of Matplotlib figure ---
            if stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_stream_bed_pre_process_average[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

                self.axis_plot_sample_position_on_transect.plot(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -stg.depth_bottom[self.combobox_acoustic_data.currentIndex()],
                    color='black', linewidth=1, linestyle="solid")

            elif stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_stream_bed_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

                self.axis_plot_sample_position_on_transect.plot(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -stg.depth_bottom[self.combobox_acoustic_data.currentIndex()],
                    color='black', linewidth=1, linestyle="solid")

            elif stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                val_max = np.nanmax(stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(), :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

                self.axis_plot_sample_position_on_transect.plot(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -stg.depth_bottom[self.combobox_acoustic_data.currentIndex()],
                    color='black', linewidth=1, linestyle="solid")

            elif stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_cross_section_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_cross_section_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_cross_section[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_raw_data_pre_process_average[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_raw_data_pre_process_SNR[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            elif stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                val_min = np.nanmin(
                    stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                val_max = np.nanmax(
                    stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :])
                if val_min == 0:
                    val_min = 1e-5

                self.axis_plot_sample_position_on_transect.pcolormesh(
                    x_time[self.combobox_frequencies.currentIndex(), :],
                    -y_depth[self.combobox_frequencies.currentIndex(), :],
                    stg.BS_raw_data[self.combobox_acoustic_data.currentIndex()][
                    self.combobox_frequencies.currentIndex(),
                    :, :],
                    cmap='viridis', norm=LogNorm(vmin=val_min, vmax=val_max))

            # --- Read selected samples (checkboxes) ---
            if self.tableWidget_fine.columnCount() > 10:

                position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()

                if len(position_list_fine) != 0:
                    time_fine_to_plot = []
                    depth_fine_to_plot = []
                    label_fine_to_plot = []
                    for k in position_list_fine:
                        time_fine_to_plot.append(stg.time_fine[k])
                        depth_fine_to_plot.append(stg.depth_fine[k])
                        label_fine_to_plot.append(stg.sample_fine[k][0])

                    self.axis_plot_sample_position_on_transect.scatter(
                        time_fine_to_plot, depth_fine_to_plot,
                        linestyle='None', marker="x", s=15, c=color_list_fine, label='fine')

                    for i in range(len(time_fine_to_plot)):
                        self.axis_plot_sample_position_on_transect.text(
                            time_fine_to_plot[i] - 25, depth_fine_to_plot[i] - .1, label_fine_to_plot[i],
                            fontstyle="normal", fontweight="light", fontsize=8)

            if self.tableWidget_sand.columnCount() > 10:

                position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()

                if len(position_list_sand) != 0:
                    time_sand_to_plot = []
                    depth_sand_to_plot = []
                    label_sand_to_plot = []
                    for k in position_list_sand:
                        time_sand_to_plot.append(stg.time_sand[k])
                        depth_sand_to_plot.append(stg.depth_sand[k])
                        label_sand_to_plot.append(stg.sample_sand[k][0])

                    self.axis_plot_sample_position_on_transect.scatter(
                        time_sand_to_plot, depth_sand_to_plot,
                        linestyle='None', marker="o", s=60, facecolors='None', edgecolors=color_list_sand, label='sand')

                    for i in range(len(time_sand_to_plot)):
                        self.axis_plot_sample_position_on_transect.text(
                            time_sand_to_plot[i] + 10, depth_sand_to_plot[i] - .1, label_sand_to_plot[i],
                            fontstyle="normal", fontweight="light", fontsize=8)

        self.axis_plot_sample_position_on_transect.text(
            1, .85, stg.freq_text[self.combobox_acoustic_data.currentIndex()][self.combobox_frequencies.currentIndex()],
            fontsize=14, fontweight='bold', fontname="Ubuntu", c="black", alpha=0.5,
            horizontalalignment='right', verticalalignment='bottom',
            transform=self.axis_plot_sample_position_on_transect.transAxes)

        self.axis_plot_sample_position_on_transect.tick_params(axis='y', labelrotation=90)
        self.axis_plot_sample_position_on_transect.tick_params(axis='both', labelsize=8)

        self.axis_plot_sample_position_on_transect.text(.98, .03, "Time (sec)",
                                                        fontsize=10, fontweight='bold', fontname="Ubuntu", c="black",
                                                        alpha=0.9,
                                                        horizontalalignment='right', verticalalignment='bottom',
                                                        rotation='horizontal',
                                                        transform=self.axis_plot_sample_position_on_transect.transAxes)
        self.axis_plot_sample_position_on_transect.text(.04, .53, "Depth (m)",
                                                        fontsize=10, fontweight='bold', fontname="Ubuntu", c="black",
                                                        alpha=0.9,
                                                        horizontalalignment='right', verticalalignment='bottom',
                                                        rotation='vertical',
                                                        transform=self.axis_plot_sample_position_on_transect.transAxes)

        self.axis_plot_sample_position_on_transect.legend(loc="lower right")
        self.figure_plot_sample_position_on_transect.canvas.draw_idle()



    # ------------------------------------------------------------------------------------------------------------------
    # --- Functions to plot total concentration ---

    def plot_total_concentration(self):

        """ Update total concentration plot according to choices of x-axis and y-axis combo-boxes """

        if (self.tableWidget_fine.columnCount() == 10) and (self.tableWidget_sand.columnCount() == 10):

            msgBox = QMessageBox()
            msgBox.setWindowTitle("Axis choice Error")
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setText("Fill table and select sample(s) before changing axis")
            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.exec()

        else:

            self.verticalLayout_groupbox_plot_total_concentration.removeWidget(self.canvas_plot_total_concentration)
            self.verticalLayout_groupbox_plot_total_concentration.removeWidget(self.toolbar_plot_total_concentration)

            self.figure_total_concentration, self.axis_total_concentration \
                = plt.subplots(nrows=1, ncols=1, layout="constrained")
            self.canvas_plot_total_concentration = FigureCanvas(self.figure_total_concentration)
            self.toolbar_plot_total_concentration = NavigationToolBar(self.canvas_plot_total_concentration, self)

            self.verticalLayout_groupbox_plot_total_concentration.addWidget(self.toolbar_plot_total_concentration)
            self.verticalLayout_groupbox_plot_total_concentration.addWidget(self.canvas_plot_total_concentration)

            # ===================================================
            # --- FINE file uploaded / SAND file NOT uploaded ---
            if (self.lineEdit_fine_sediment.text()) and not (self.lineEdit_sand_sediment.text()):

                self.compute_Ctot_per_cent()

                _, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()

                (Ctot_fine_to_plot, Ctot_fine_percent_to_plot, sample_depth_to_plot_fine, indices_bottom_fine,
                 depth_bottom_to_plot_fine) = self.read_select_samples_fine()

                # --- Concentration (g/L) VS z (m) ---
                if (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 0):
                    self.axis_total_concentration.cla()
                    self.axis_total_concentration.scatter(Ctot_fine_to_plot,
                                                            sample_depth_to_plot_fine,
                                                            s=100, facecolor=color_list_fine, edgecolor="None", alpha=0.5, label='fine')
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (%) VS z (m) ---
                elif (self.combobox_x_axis.currentIndex() == 1) and (self.combobox_y_axis.currentIndex() == 0):
                    self.axis_total_concentration.cla()
                    self.axis_total_concentration.scatter(Ctot_fine_percent_to_plot, sample_depth_to_plot_fine,
                                                            s=100, facecolor=color_list_fine, edgecolor="None", alpha=0.5, label='fine')
                    self.axis_total_concentration.set_xlim(0, 100)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (g/L) VS z / h ---
                elif (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 1):
                    self.axis_total_concentration.cla()
                    if stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                        self.axis_total_concentration.scatter(
                            Ctot_fine_to_plot,
                            [x / y for x, y in zip(sample_depth_to_plot_fine, depth_bottom_to_plot_fine)],
                            s=100, facecolor=color_list_fine, edgecolor="None", alpha=0.5, label='fine')

                    else:

                        msgBox = QMessageBox()
                        msgBox.setWindowTitle("Axis choice Error")
                        msgBox.setIcon(QMessageBox.Warning)
                        msgBox.setText("Please detect bottom before plotting axis z/h")
                        msgBox.setStandardButtons(QMessageBox.Ok)
                        msgBox.exec()

                    self.axis_total_concentration.set_ylim(-1, 0)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (%) VS z / h ---
                elif (self.combobox_x_axis.currentIndex() == 1) and (self.combobox_y_axis.currentIndex() == 1):
                    self.axis_total_concentration.cla()
                    if stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                        self.axis_total_concentration.scatter(
                                Ctot_fine_percent_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_fine, depth_bottom_to_plot_fine)],
                                s=100, facecolor=color_list_fine, edgecolor="None", alpha=0.5, label='fine')

                    else:

                        msgBox = QMessageBox()
                        msgBox.setWindowTitle("Axis choice Error")
                        msgBox.setIcon(QMessageBox.Warning)
                        msgBox.setText("Please detect bottom before plotting axis z/h")
                        msgBox.setStandardButtons(QMessageBox.Ok)
                        msgBox.exec()

                    self.axis_total_concentration.set_xlim(0, 100)
                    self.axis_total_concentration.set_ylim(-1, 0)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

            # ===================================================
            # --- FINE file NOT uploaded / SAND file uploaded ---
            elif not (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand_sediment.text()):

                self.compute_Ctot_per_cent()

                _, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()
                (Ctot_sand_to_plot, Ctot_sand_percent_to_plot, sample_depth_to_plot_sand, indices_bottom_sand,
                 depth_bottom_to_plot_sand) = self.read_select_samples_sand()

                # --- Concentration (g/L) VS z (m) ---
                if (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 0):
                    self.axis_total_concentration.cla()
                    self.axis_total_concentration.scatter(Ctot_sand_to_plot,
                                                              sample_depth_to_plot_sand,
                                                              s=300, facecolor="None", edgecolor=color_list_sand,
                                                              alpha=0.5, label='sand')
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (%) VS z (m) ---
                elif (self.combobox_x_axis.currentIndex() == 1) and (self.combobox_y_axis.currentIndex() == 0):
                    self.axis_total_concentration.cla()
                    self.axis_total_concentration.scatter(Ctot_sand_percent_to_plot, sample_depth_to_plot_sand,
                                                              s=300, facecolor="None", edgecolor=color_list_sand,
                                                              alpha=0.5, label='sand')
                    self.axis_total_concentration.set_xlim(0, 100)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (g/L) VS z / h ---
                elif (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 1):
                    self.axis_total_concentration.cla()
                    if stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                        self.axis_total_concentration.scatter(
                                Ctot_sand_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_sand, depth_bottom_to_plot_sand)],
                                # stg.depth_bottom[self.combobox_acoustic_data.currentIndex()][indices_bottom_sand],
                                s=300, facecolor="None", edgecolor=color_list_sand, alpha=0.5, label='sand')

                    else:

                        msgBox = QMessageBox()
                        msgBox.setWindowTitle("Axis choice Error")
                        msgBox.setIcon(QMessageBox.Warning)
                        msgBox.setText("Please detect bottom before plotting axis z/h")
                        msgBox.setStandardButtons(QMessageBox.Ok)
                        msgBox.exec()

                    self.axis_total_concentration.set_ylim(-1, 0)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (%) VS z / h ---
                elif (self.combobox_x_axis.currentIndex() == 1) and (self.combobox_y_axis.currentIndex() == 1):
                    self.axis_total_concentration.cla()
                    if stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                        self.axis_total_concentration.scatter(
                                Ctot_sand_percent_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_sand, depth_bottom_to_plot_sand)],
                                # stg.depth_bottom[self.combobox_acoustic_data.currentIndex()][indices_bottom_sand],
                                s=300, facecolor="None", edgecolor=color_list_sand, alpha=0.5, label='sand')

                    else:

                        msgBox = QMessageBox()
                        msgBox.setWindowTitle("Axis choice Error")
                        msgBox.setIcon(QMessageBox.Warning)
                        msgBox.setText("Please detect bottom before plotting axis z/h")
                        msgBox.setStandardButtons(QMessageBox.Ok)
                        msgBox.exec()

                    self.axis_total_concentration.set_xlim(0, 100)
                    self.axis_total_concentration.set_ylim(-1, 0)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

            # ===============================================
            # --- FINE file uploaded / SAND file uploaded ---
            elif (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand_sediment.text()):

                self.compute_Ctot_per_cent()

                _, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()
                (Ctot_fine_to_plot, Ctot_fine_percent_to_plot, sample_depth_to_plot_fine, indices_bottom_fine,
                 depth_bottom_to_plot_fine) = self.read_select_samples_fine()

                _, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()
                (Ctot_sand_to_plot, Ctot_sand_percent_to_plot, sample_depth_to_plot_sand, indices_bottom_sand,
                 depth_bottom_to_plot_sand) = self.read_select_samples_sand()

                # --- Concentration (g/L) VS z (m) ---
                if (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 0):
                    self.axis_total_concentration.cla()
                    self.axis_total_concentration.scatter(Ctot_fine_to_plot,
                                                              sample_depth_to_plot_fine,
                                                              s=100, facecolor=color_list_fine, edgecolor="None",
                                                              alpha=0.5, label='fine')
                    self.axis_total_concentration.scatter(Ctot_sand_to_plot,
                                                              sample_depth_to_plot_sand,
                                                              s=300, facecolor="None", edgecolor=color_list_sand,
                                                              alpha=0.5, label='sand')
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (%) VS z (m) ---
                elif (self.combobox_x_axis.currentIndex() == 1) and (self.combobox_y_axis.currentIndex() == 0):
                    self.axis_total_concentration.cla()
                    self.axis_total_concentration.scatter(Ctot_fine_percent_to_plot, sample_depth_to_plot_fine,
                                                              s=100, facecolor=color_list_fine, edgecolor="None",
                                                              alpha=0.5, label='fine')
                    self.axis_total_concentration.scatter(Ctot_sand_percent_to_plot, sample_depth_to_plot_sand,
                                                              s=300, facecolor="None", edgecolor=color_list_sand,
                                                              alpha=0.5, label='sand')
                    self.axis_total_concentration.set_xlim(0, 100)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (g/L) VS z / h ---
                elif (self.combobox_x_axis.currentIndex() == 0) and (self.combobox_y_axis.currentIndex() == 1):
                    self.axis_total_concentration.cla()
                    if stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):
                        self.axis_total_concentration.scatter(
                                Ctot_fine_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_fine, depth_bottom_to_plot_fine)],
                                s=100, facecolor=color_list_fine, edgecolor="None", alpha=0.5, label='fine')
                        self.axis_total_concentration.scatter(
                                Ctot_sand_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_sand, depth_bottom_to_plot_sand)],
                                s=300, facecolor="None", edgecolor=color_list_sand, alpha=0.5, label='sand')

                    else:

                        msgBox = QMessageBox()
                        msgBox.setWindowTitle("Axis choice Error")
                        msgBox.setIcon(QMessageBox.Warning)
                        msgBox.setText("Please detect bottom before plotting axis z/h")
                        msgBox.setStandardButtons(QMessageBox.Ok)
                        msgBox.exec()

                    self.axis_total_concentration.set_ylim(-1, 0)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

                # --- Concentration (%) VS z / h ---
                elif (self.combobox_x_axis.currentIndex() == 1) and (self.combobox_y_axis.currentIndex() == 1):
                    self.axis_total_concentration.cla()
                    if stg.BS_stream_bed[self.combobox_acoustic_data.currentIndex()].shape != (0,):

                        self.axis_total_concentration.scatter(
                                Ctot_fine_percent_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_fine, depth_bottom_to_plot_fine)],
                                s=100, facecolor=color_list_fine, edgecolor="None", alpha=0.5, label='fine')

                        self.axis_total_concentration.scatter(
                                Ctot_sand_percent_to_plot,
                                [x / y for x, y in zip(sample_depth_to_plot_sand, depth_bottom_to_plot_sand)],
                                s=300, facecolor="None", edgecolor=color_list_sand, alpha=0.5, label='sand')

                    else:

                        msgBox = QMessageBox()
                        msgBox.setWindowTitle("Axis choice Error")
                        msgBox.setIcon(QMessageBox.Warning)
                        msgBox.setText("Please detect bottom before plotting axis z/h")
                        msgBox.setStandardButtons(QMessageBox.Ok)
                        msgBox.exec()

                    self.axis_total_concentration.set_xlim(0, 100)
                    self.axis_total_concentration.set_ylim(-1, 0)
                    self.axis_total_concentration.set_xlabel(self.combobox_x_axis.currentText())
                    self.axis_total_concentration.set_ylabel(self.combobox_y_axis.currentText())

            self.axis_total_concentration.legend(loc="upper right")
            self.figure_total_concentration.canvas.draw_idle()

    def plot_PSD_fine_and_sand_sediments(self):

        """ Update the plot of Particle Size Distribution according to choices of x-axis and y-axis combo-boxes """

        if (self.tableWidget_fine.columnCount() == 10) and (self.tableWidget_sand.columnCount() == 10):

            msgBox = QMessageBox()
            msgBox.setWindowTitle("Axis choice Error")
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setText("Fill table and select sample(s) before changing axis")
            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.exec()

        else:

            self.verticalLayout_groupbox_plot_PSD.removeWidget(self.canvas_plot_PSD)
            self.verticalLayout_groupbox_plot_PSD.removeWidget(self.toolbar_plot_PSD)

            self.figure_plot_PSD, self.axis_plot_PSD \
                = plt.subplots(nrows=1, ncols=2, layout="constrained")
            self.canvas_plot_PSD = FigureCanvas(self.figure_plot_PSD)
            self.toolbar_plot_PSD = NavigationToolBar(self.canvas_plot_PSD, self)

            self.verticalLayout_groupbox_plot_PSD.addWidget(self.toolbar_plot_PSD)
            self.verticalLayout_groupbox_plot_PSD.addWidget(self.canvas_plot_PSD)

            # --- FINE file uploaded / SAND file NOT uploaded ---
            if (self.lineEdit_fine_sediment.text()) and not (self.lineEdit_sand_sediment.text()):

                self.axis_plot_PSD[0].cla()
                self.axis_plot_PSD[1].cla()

                position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()

                if self.combobox_PSD_plot.currentIndex() == 0:

                    for profil_position_num, color_plot in zip(position_list_fine, color_list_fine):
                        self.axis_plot_PSD[0].plot(stg.radius_grain_fine,
                                                   stg.frac_vol_fine[profil_position_num, :],
                                                   color=color_plot)
                        self.axis_plot_PSD[0].set_xscale('log')
                        self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[0].set_ylabel('Class size volume fraction')

                        self.axis_plot_PSD[1].plot()
                        self.axis_plot_PSD[1].set_xscale('log')
                        self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[1].set_ylabel('Class size volume fraction')

                elif self.combobox_PSD_plot.currentIndex() == 1:

                    for profil_position_num, color_plot in zip(position_list_fine, color_list_fine):
                        self.axis_plot_PSD[0].plot(stg.radius_grain_fine,
                                                   stg.frac_vol_fine_cumul[profil_position_num, :],
                                                   color=color_plot)
                        self.axis_plot_PSD[0].set_xscale('log')
                        self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[0].set_ylabel('Cumulative size volume fraction')

                        self.axis_plot_PSD[1].plot()
                        self.axis_plot_PSD[1].set_xscale('log')
                        self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[1].set_ylabel('Class size volume fraction')

                self.figure_plot_PSD.canvas.draw_idle()

            # --- FINE file NOT uploaded / SAND file uploaded ---
            if not (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand_sediment.text()):

                self.axis_plot_PSD[0].cla()
                self.axis_plot_PSD[1].cla()

                position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()

                if self.combobox_PSD_plot.currentIndex() == 0:

                    for profil_position_num, color_plot in zip(position_list_sand, color_list_sand):

                        self.axis_plot_PSD[0].plot()
                        self.axis_plot_PSD[0].set_xscale('log')
                        self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[0].set_ylabel('Class size volume fraction')

                        self.axis_plot_PSD[1].plot(stg.radius_grain_sand,
                                                   stg.frac_vol_sand[profil_position_num, :],
                                                   color=color_plot)
                        self.axis_plot_PSD[1].set_xscale('log')
                        self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[1].set_ylabel('Class size volume fraction')

                elif self.combobox_PSD_plot.currentIndex() == 1:

                    for profil_position_num, color_plot in zip(position_list_sand, color_list_sand):

                        self.axis_plot_PSD[0].plot()
                        self.axis_plot_PSD[0].set_xscale('log')
                        self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[0].set_ylabel('Cumulative size volume fraction')

                        self.axis_plot_PSD[1].plot(stg.radius_grain_sand,
                                                   stg.frac_vol_sand_cumul[profil_position_num, :],
                                                   color=color_plot)
                        self.axis_plot_PSD[1].set_xscale('log')
                        self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[1].set_ylabel('Cumulative size volume fraction')

                self.figure_plot_PSD.canvas.draw_idle()

            # --- FINE file uploaded / SAND file uploaded ---
            if (self.lineEdit_fine_sediment.text()) and (self.lineEdit_sand_sediment.text()):

                self.axis_plot_PSD[0].cla()
                self.axis_plot_PSD[1].cla()

                position_list_fine, color_list_fine = self.extract_position_list_and_color_list_from_table_checkboxes_fine()
                position_list_sand, color_list_sand = self.extract_position_list_and_color_list_from_table_checkboxes_sand()

                if self.combobox_PSD_plot.currentIndex() == 0:

                    for profil_position_num_fine, color_plot_fine in zip(position_list_fine, color_list_fine):

                        self.axis_plot_PSD[0].plot(stg.radius_grain_fine,
                                                   stg.frac_vol_fine[profil_position_num_fine, :],
                                                   color=color_plot_fine)
                        self.axis_plot_PSD[0].set_xscale('log')
                        self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[0].set_ylabel('Class size volume fraction')

                    for profil_position_num_sand, color_plot_sand in zip(position_list_sand, color_list_sand):

                        self.axis_plot_PSD[1].plot(stg.radius_grain_sand,
                                                   stg.frac_vol_sand[profil_position_num_sand, :],
                                                   color=color_plot_sand)
                        self.axis_plot_PSD[1].set_xscale('log')
                        self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[1].set_ylabel('Class size volume fraction')

                elif self.combobox_PSD_plot.currentIndex() == 1:

                    for profil_position_num_fine, color_plot_fine in zip(position_list_fine, color_list_fine):
                        self.axis_plot_PSD[0].plot(stg.radius_grain_fine,
                                                   stg.frac_vol_fine_cumul[profil_position_num_fine, :],
                                                   color=color_plot_fine)
                        self.axis_plot_PSD[0].set_xscale('log')
                        self.axis_plot_PSD[0].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[0].set_ylabel('Cumulative size volume fraction')

                    for profil_position_num_sand, color_plot_sand in zip(position_list_sand, color_list_sand):
                        self.axis_plot_PSD[1].plot(stg.radius_grain_sand,
                                                       stg.frac_vol_sand_cumul[profil_position_num_sand, :],
                                                       color=color_plot_sand)
                        self.axis_plot_PSD[1].set_xscale('log')
                        self.axis_plot_PSD[1].set_xlabel('Radius ($\mu m$)')
                        self.axis_plot_PSD[1].set_ylabel('Cumulative size volume fraction')

                self.figure_plot_PSD.canvas.draw_idle()
