Identify errors in this python code " import sys
import pandas as pd
import numpy as np
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                               QTableView, QListView, QSplitter, QToolBar, QStatusBar,
                               QFileDialog, QInputDialog, QMessageBox, QComboBox, QLineEdit,
                               QDialog, QFormLayout, QPushButton,
                               QSpinBox, QDoubleSpinBox, QLabel)
from PySide6.QtGui import QAction, QStandardItemModel, QStandardItem, QUndoStack, QUndoCommand
from PySide6.QtCore import Qt, QAbstractTableModel, Signal, Slot, QModelIndex, QRunnable, QThreadPool, QRibbonBar, QRibbonTab, QRibbonGroup
from concurrent.futures import ThreadPoolExecutor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from pyEDM import EmbedDimension


class PandasModel(QAbstractTableModel):
    def __init__(self, data):
        super().__init__()
        self._data = data

    def rowCount(self, index):
        return self._data.shape[0]

    def columnCount(self, index):
        return self._data.shape[1]

    def data(self, index, role):
        if role == Qt.DisplayRole:
            value = self._data.iloc[index.row(), index.column()]
            return str(value)

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return str(self._data.columns[section])
            if orientation == Qt.Vertical:
                return str(self._data.index[section])


class EmbeddingDimensionPlot(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.figure = Figure(figsize=(10, 8), dpi=100)
        self.canvas = FigureCanvas(self.figure)
        layout = QVBoxLayout()
        layout.addWidget(self.canvas)
        self.setLayout(layout)

    def plot_embedding_dimension(self, results):
        self.figure.clear()

        # Forecast Skill plot
        ax1 = self.figure.add_subplot(221)
        ax1.plot(results['E'], results['rho'], marker='o')
        ax1.set_xlabel('Embedding Dimension')
        ax1.set_ylabel('Forecast Skill (ρ)')
        ax1.set_title('Forecast Skill vs Embedding Dimension')

        # MAE plot
        ax2 = self.figure.add_subplot(222)
        ax2.plot(results['E'], results['MAE'], marker='s')
        ax2.set_xlabel('Embedding Dimension')
        ax2.set_ylabel('Mean Absolute Error')
        ax2.set_title('MAE vs Embedding Dimension')

        # RMSE plot
        ax3 = self.figure.add_subplot(223)
        ax3.plot(results['E'], results['RMSE'], marker='^')
        ax3.set_xlabel('Embedding Dimension')
        ax3.set_ylabel('Root Mean Square Error')
        ax3.set_title('RMSE vs Embedding Dimension')

        # Statistics
        ax4 = self.figure.add_subplot(224)
        ax4.axis('off')
        optimal_e = results.loc[results['rho'].idxmax(), 'E']
        best_rho = results['rho'].max()
        stats_text = f"Optimal Embedding Dimension: {optimal_e}\n"
        stats_text += f"Best Forecast Skill (ρ): {best_rho:.4f}\n"
        stats_text += f"MAE at optimal E: {results.loc[results['rho'].idxmax(), 'MAE']:.4f}\n"
        stats_text += f"RMSE at optimal E: {results.loc[results['rho'].idxmax(), 'RMSE']:.4f}"
        ax4.text(0.1, 0.5, stats_text, fontsize=10, verticalalignment='center')

        self.figure.tight_layout()
        self.canvas.draw()


class EmbedDimensionParamsDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Embedding Dimension Parameters")
        layout = QFormLayout()

        self.column_combo = QComboBox()
        self.max_e_spin = QSpinBox()
        self.max_e_spin.setRange(1, 100)
        self.max_e_spin.setValue(10)
        self.tp_spin = QSpinBox()
        self.tp_spin.setRange(1, 100)
        self.tp_spin.setValue(1)
        self.tau_spin = QSpinBox()
        self.tau_spin.setRange(1, 100)
        self.tau_spin.setValue(1)

        layout.addRow("Column:", self.column_combo)
        layout.addRow("Max Embedding Dimension:", self.max_e_spin)
        layout.addRow("Time to Predict (Tp):", self.tp_spin)
        layout.addRow("Time Delay (tau):", self.tau_spin)

        buttons = QHBoxLayout()
        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")
        buttons.addWidget(self.ok_button)
        buttons.addWidget(self.cancel_button)

        layout.addRow(buttons)

        self.setLayout(layout)

        self.ok_button.clicked.connect(self.accept)
        self.cancel_button.clicked.connect(self.reject)

    def set_columns(self, columns):
        self.column_combo.clear()
        self.column_combo.addItems(columns)


class EmbedDimensionWorker(QRunnable):
    def __init__(self, df, column, max_e, tp, tau, callback):
        super().__init__()
        self.df = df
        self.column = column
        self.max_e = max_e
        self.tp = tp
        self.tau = tau
        self.callback = callback

    def run(self):
        try:
            results = EmbedDimension(dataFrame=self.df, columns=self.column, lib="all", pred="all",
                                     maxE=self.max_e, Tp=self.tp, tau=self.tau, showPlot=False)
            self.callback(results)
        except Exception as e:
            self.callback(None, str(e))


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Data Editor")
        self.setGeometry(100, 100, 1200, 800)

        self.df = pd.DataFrame()
        self.undo_stack = QUndoStack(self)

        self.create_ui()
        self.create_actions()
        self.create_ribbon()
        self.create_statusbar()

        self.data_model_connection = None

    def create_ui(self):
        main_widget = QWidget()
        main_layout = QHBoxLayout()

        # Create splitter
        splitter = QSplitter(Qt.Horizontal)

        # Variable selection window
        self.variable_list = QListView()
        self.variable_model = QStandardItemModel()
        self.variable_list.setModel(self.variable_model)
        self.variable_list.doubleClicked.connect(self.edit_data_type)

        # Data viewer
        self.data_view = QTableView()
        self.data_model = PandasModel(self.df)
        self.data_view.setModel(self.data_model)
        self.connect_data_model()

        # Embedding Dimension Plot
        self.embedding_plot = EmbeddingDimensionPlot()

        splitter.addWidget(self.variable_list)
        splitter.addWidget(self.data_view)
        splitter.addWidget(self.embedding_plot)
        splitter.setSizes([200, 600, 400])

        main_layout.addWidget(splitter)
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

    def create_actions(self):
        self.open_action = QAction("Open", self)
        self.open_action.triggered.connect(self.open_file)

        self.save_action = QAction("Save", self)
        self.save_action.triggered.connect(self.save_file)

        self.undo_action = QAction("Undo", self)
        self.undo_action.triggered.connect(self.undo_stack.undo)

        self.redo_action = QAction("Redo", self)
        self.redo_action.triggered.connect(self.undo_stack.redo)

        self.calc_embedding_action = QAction("Calculate Optimal Embedding", self)
        self.calc_embedding_action.triggered.connect(self.calculate_optimal_embedding)

    def create_ribbon(self):
        ribbon = QRibbonBar(self)
        self.setMenuBar(ribbon)

        # File tab
        file_tab = QRibbonTab("File")
        ribbon.addTab(file_tab)

        # File operations group
        file_group = QRibbonGroup("File Operations")
        file_group.addAction(self.open_action)
        file_group.addAction(self.save_action)
        file_tab.addGroup(file_group)

        # Edit tab
        edit_tab = QRibbonTab("Edit")
        ribbon.addTab(edit_tab)

        # Edit operations group
        edit_group = QRibbonGroup("Edit Operations")
        edit_group.addAction(self.undo_action)
        edit_group.addAction(self.redo_action)
        edit_tab.addGroup(edit_group)

        # Optimal Embedding tab
        embedding_tab = QRibbonTab("Optimal Embedding")
        ribbon.addTab(embedding_tab)

        # Embedding group
        embedding_group = QRibbonGroup("Embedding Analysis")
        embedding_group.addAction(self.calc_embedding_action)
        embedding_tab.addGroup(embedding_group)

    def create_statusbar(self):
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

    def connect_data_model(self):
        if self.data_model_connection:
            self.data_model.dataChanged.disconnect(self.data_model_connection)
        self.data_model_connection = self.data_model.dataChanged.connect(self.on_data_changed)

    def on_data_changed(self, topLeft, bottomRight, roles):
        row = topLeft.row()
        col = topLeft.column()
        new_value = self.data_model._data.iloc[row, col]
        old_value = self.df.iloc[row, col]
        if new_value != old_value:
            change_command = ChangeDataCommand(self.df, row, col, old_value, new_value)
            self.undo_stack.push(change_command)

    def open_file(self):
        file_name, _ = QFileDialog.getOpenFileName(self, "Open File", "", "CSV Files (*.csv);;All Files (*)")
        if file_name:
            try:
                self.df = pd.read_csv(file_name)
                self.update_data_view()
                self.update_variable_list()
                self.statusBar.showMessage(f"File loaded: {file_name}")
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Could not load file: {str(e)}")

    def save_file(self):
        file_name, _ = QFileDialog.getSaveFileName(self, "Save File", "", "CSV Files (*.csv);;All Files (*)")
        if file_name:
            try:
                self.df.to_csv(file_name, index=False)
                self.statusBar.showMessage(f"File saved: {file_name}")
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Could not save file: {str(e)}")

    def update_data_view(self):
        self.data_model = PandasModel(self.df)
        self.data_view.setModel(self.data_model)
        self.connect_data_model()

    def update_variable_list(self):
        self.variable_model.clear()
        for column in self.df.columns:
            item = QStandardItem(column)
            item.setData(self.df[column].dtype, Qt.UserRole)
            self.variable_model.appendRow(item)

    def edit_data_type(self, index):
        column = self.variable_model.itemFromIndex(index).text()
        current_type = self.df[column].dtype
        type_name, ok = QInputDialog.getItem(self, "Edit Data Type", f"Select new type for {column}:",
                                             ["int", "float", "str"], 0, False)
        if ok and type_name:
            try:
                self.df[column] = self.df[column].astype(type_name)
                self.update_data_view()
                self.update_variable_list()
                self.statusBar.showMessage(f"Changed type of {column} to {type_name}")
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Could not change data type: {str(e)}")

    def calculate_optimal_embedding(self):
        if self.df.empty:
            QMessageBox.warning(self, "No Data", "Please load some data first.")
            return

        dialog = EmbedDimensionParamsDialog(self)
        dialog.set_columns(self.df.columns.tolist())

        if dialog.exec():
            column = dialog.column_combo.currentText()
            max_e = dialog.max_e_spin.value()
            tp = dialog.tp_spin.value()
            tau = dialog.tau_spin.value()

            worker = EmbedDimensionWorker(self.df, column, max_e, tp, tau, self.embedding_calculation_complete)
            QThreadPool.globalInstance().start(worker)
            self.statusBar.showMessage("Calculating optimal embedding dimension...")

    def embedding_calculation_complete(self, results, error=None):
        if error:
            QMessageBox.critical(self, "Error", f"Could not calculate embedding dimension: {error}")
            self.statusBar.showMessage("Error in calculating optimal embedding dimension.")
        else:
            self.embedding_plot.plot_embedding_dimension(results)
            self.statusBar.showMessage("Optimal embedding dimension calculated.")


class ChangeDataCommand(QUndoCommand):
    def __init__(self, df, row, col, old_value, new_value):
        super().__init__()
        self.df = df
        self.row = row
        self.col = col
        self.old_value = old_value
        self.new_value = new_value

    def redo(self):
        self.df.iloc[self.row, self.col] = self.new_value

    def undo(self):
        self.df.iloc[self.row, self.col] = self.old_value


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())"