def Noise_Removal(
        self,
        df,
        value_col="distance",
        sampling_interval=5,
        cutoff_frequency=0.05,
        filter_order=4,
        to_plot_graphs=True,
        date_range=["2024-07-21", "2024-07-22"],
    ):
        """
        Cleans and processes time series data by removing outliers, applying STL decomposition,
        filtering, and calculating the Power Spectral Density (PSD).

        This method:
        1. Applies STL decomposition to remove outliers.
        2. Replaces NaN values in the cleaned data.
        3. Applies a Butterworth lowpass filter to the cleaned data.
        4. Calculates and optionally plots the PSD of the original and cleaned signals.
        5. Optionally plots the original, no-outlier, and filtered signals.

        Parameters:
        df (pd.DataFrame): DataFrame containing the time series data.
        value_col (str): Name of the column containing the values.
        period (int): Periodicity in the data for STL decomposition.
        seasonal (int): Length of the seasonal component for STL decomposition.
        sampling_interval (float): Time interval between consecutive data points (in seconds).
        cutoff_frequency (float): The cutoff frequency for the Butterworth filter.
        filter_order (int): The order of the Butterworth filter.
        to_plot_graphs (bool): Whether to plot the graphs or not.

        Returns:
        pd.DataFrame: DataFrame with the cleaned and filtered data.
        """

        df = df.copy()

        # Calculate sampling rate
        sampling_rate = 1 / sampling_interval  # Hz

        # Calculate the PSD of the original signal
        freqs, psd = self.calculate_psd(df[value_col], sampling_rate)

        # Apply Butterworth filter on the cleaned data
        df["filtered_distance"] = self.butter_lowpass_filter(
            df["distance"], cutoff_frequency, sampling_rate, filter_order
        )

        if to_plot_graphs:

            # Plot the PSD of the original signal
            plt.figure(figsize=(14, 7))
            plt.semilogy(freqs, psd)
            plt.title("Power Spectral Density (PSD) of the Original Signal")
            plt.xlabel("Frequency (Hz)")
            plt.ylabel("Power/Frequency (dB/Hz)")
            plt.show()

            # Interactive plot with Plotly

            start_date, end_date = date_range

            trace1 = go.Scatter(
                x=df[start_date:end_date].index,
                y=df["distance"][start_date:end_date],
                mode="lines",
                name="Original Signal",
            )
            trace3 = go.Scatter(
                x=df[start_date:end_date].index,
                y=df["filtered_distance"][start_date:end_date],
                mode="lines",
                name="Filtered Signal",
                line=dict(color="red"),
            )

            layout = go.Layout(
                title="Signal Before and After  Filtering",
                xaxis=dict(title="Sample Number"),
                yaxis=dict(title="Distance"),
                legend=dict(x=0, y=1),
            )

            fig = go.Figure(data=[trace1, trace3], layout=layout)
            fig.show()

        df_clean = df.drop(columns=["distance"])
        df_clean.rename(columns={"filtered_distance": "distance"}, inplace=True)

        return df_clean, df


calculate the 10 % point of amplitude in the y axis of plot from higest to lowest of psd plot and print the 10% point  . for example if the higest point is 100000 and lowest is 1000 then 100000-1000 = 99000 then 10 % of 99000 is 9900 . also print the x-axis frequency value at 10 % point . draw the line of 10% and intersection at x-axis line in the plot