"""
Cross-correlation analysis module for spectroscopic data.

This module implements cross-correlation analysis for spectroscopic observations,
allowing for both single-night and multi-night analysis. It supports different
correlation methods and can handle both transmission and emission spectroscopy.

The main class FrameRunCC provides a GUI interface for running cross-correlation
analysis with various parameters and visualization options.
"""

import os
import subprocess
import traceback
from pickle import load, dump
from tkinter import messagebox

from pathlib import Path
from pandas import read_csv

from GUIBRUSHR.GUI.WIDGET.MyDropDown import MyDropdown
from GUIBRUSHR.GUI.WIDGET.MyEntry import MyEntry
from GUIBRUSHR.GUI.WIDGET.MyFigure import MyFigure
from GUIBRUSHR.GUI.WIDGET.MyPDFWindow import MyPDFWindow
from GUIBRUSHR.GUI.WIDGET.MyButton import MyButton
from GUIBRUSHR.GUI.WIDGET.MyCheckBox import MyCheckBox
from GUIBRUSHR.GUI.WIDGET.MyTextField import MyTextField
from GUIBRUSHR.GUI.LAYOUT.MyPanel import MyPanel
from GUIBRUSHR.General_Constants.Classes.HelpButton import HelpButton
from GUIBRUSHR.General_Constants.FunctionsAndConstants.Constant_Variables import ConstantVariables
from GUIBRUSHR.General_Constants.FunctionsAndConstants.general_functions import (
    read_fits, get_csv_value, create_path_night, read_depth_fits
)


# noinspection PyTypeChecker
class FrameRunCC(MyPanel):
    """
    GUI panel for running cross-correlation analysis on spectroscopic data.

    This class provides a graphical interface for performing cross-correlation
    analysis between observed spectra and model templates. It supports both
    single-night and multi-night analysis, with options for different correlation
    methods and visualization tools.

    The panel includes controls for:
    - Radial velocity range and step size
    - Phase binning parameters
    - Correlation method selection
    - Eccentric orbit handling
    - Speed optimization options
    """

    def __init__(self, parent, color, row, column, path_default, frame_input, window,
                 filters_and_table, widget_nights, **kwargs):
        """
        Initialize the cross-correlation analysis panel.

        Args:
            parent: Parent widget
            color: Background color
            row: Row position in parent
            column: Column position in parent
            path_default: Default path for file operations
            frame_input: Input frame containing target information
            window: Main application window
            filters_and_table: Filter and table widget (optional)
            widget_nights: Nights widget (optional)
            **kwargs: Additional keyword arguments
        """
        # Initialize instance variables
        self.target_information = None
        self.path_folder_targets = frame_input.frame_path.path_folder_targets.get_text()
        self.filters_and_table = filters_and_table
        self.widget_nights = widget_nights
        self.global_exc = 0
        self.frame_input = frame_input
        self.path_default = path_default
        self.window = window
        self.color = color
        self.p = None
        self._setup_exchange_directory()

        # Set up target dropdown
        if filters_and_table is not None:
            self.target_dropdown = filters_and_table.frame_filter.dropdown_target
        else:
            self.target_dropdown = self.widget_nights.dropdown_target

        # Initialize parent panel
        super().__init__(parent, color, row, column, **kwargs)

        # Create sub-panels
        self.row1 = MyPanel(self, color, 0, 1)
        self.row2 = MyPanel(self, color, 1, 1)
        self.row3 = MyPanel(self, color, 2, 1)
        # Initialize GUI elements
        self._init_gui_elements()

        self.global_exc = 1

    def _init_gui_elements(self):
        """Initialize all GUI elements in the panel."""
        # Help text dictionary
        help_text = {
            "CCF filter": "When enabled, apply a filter to the CC functions",

            "Range inf. RV": "Lower bound of the radial velocity search range in km/s. This defines the minimum velocity shift applied to the model template during cross-correlation. Typical range: -150 to -100 km/s for negative velocities.",

            "Range sup. RV": "Upper bound of the radial velocity search range in km/s. This defines the maximum velocity shift applied to the model template during cross-correlation. Typical range: +100 to +150 km/s for positive velocities.",

            "Step RV": "Step size in km/s for the radial velocity grid. Smaller steps provide finer velocity resolution but increase computation time. Recommended: 0.5-2 km/s depending on spectral resolution and signal strength.",

            "Phases Bin Size": "Size of orbital phase bins for multi-night analysis.",

            "Type": "Cross-correlation method selection. Options include: standard cross-correlation, Pearson correlation, or weighted cross-correlation (using inverse variance weighting). Weighted methods are preferred for data with varying signal-to-noise across pixels.",

            "Ecc. Orbit": "Enable this for eccentric orbits to use the full radvel Keplerian velocity calculation instead of the circular orbit approximation. When enabled, the analysis uses the target's eccentricity and argument of periastron to compute accurate radial velocities throughout the orbit.",

            "Speed CC": "Speed optimization mode. 'Auto': uses optimized wavelength grid. 'Full': processes all wavelength solutions (slower but more thorough). Auto mode is recommended for most cases.",

            "Instrument convolution": "When enabled, convolves the model template with the instrument's spectral resolution profile before cross-correlation. Uses the instrument's HWHM (km/s) from the database. Recommended when the model resolution significantly exceeds the instrument resolution.",

            "Doppler Shadow (DS) correction": "When enabled, applies Doppler Shadow correction to the cross-correlation analysis. This correction accounts for the stellar line distortion during planetary transit when the planet blocks different parts of the rotating stellar disk.",

            "DS width": "Width parameter (in km/s) for Doppler Shadow correction. Defines the exclusion region where the planet's atmospheric trace and Doppler shadow trace overlap. Typical values: 10-30 km/s depending on stellar rotation and planetary parameters.",

            "maxfev": "Maximum number of function evaluations for the curve fitting algorithm in Doppler shadow correction. Higher values allow more iterations for convergence but increase computation time. Default: 5000. Increase if fitting fails to converge.",

            "Spectrum selection": "Selects which portion of the transit to use for Doppler shadow fitting. 'full': uses entire non-overlapping in-transit region. 'up mid transit': uses only the second half of transit (post-mid-transit). 'down mid transit': uses only the first half of transit (pre-mid-transit). Useful for analyzing asymmetric Doppler shadow features.",

            "Mask rv": "When enabled, masks (excludes) a specific radial velocity range from the cross-correlation analysis. This can be useful to remove contamination from stellar lines or other features in specific velocity regions.",

            "Min rv mask": "Minimum radial velocity (in km/s) for the RV mask region. Data between min_rv_mask and max_rv_mask will be excluded from the analysis when 'Mask rv' is enabled.",

            "Max rv mask": "Maximum radial velocity (in km/s) for the RV mask region. Data between min_rv_mask and max_rv_mask will be excluded from the analysis when 'Mask rv' is enabled.",

            "Mask night": "Per-night mask activation control. Enter comma-separated values (0 or 1) matching the number of nights being analyzed. 0 = do not apply masks to that night; 1 = apply enabled masks (RV and/or phase) to that night. For single-night analysis, enter a single value (0 or 1). Example for 5 nights: '0,1,1,0,1' will apply masks only to nights 2, 3, and 5.",

            "Mask phase": "When enabled, masks (excludes) a specific orbital phase range from the cross-correlation analysis. This can be useful to exclude problematic observations or focus on specific orbital phases.",

            "Min phase mask": "Minimum orbital phase for the phase mask region. Data between min_phase_mask and max_phase_mask will be excluded from the analysis when 'Mask phase' is enabled.",

            "Max phase mask": "Maximum orbital phase for the phase mask region. Data between min_phase_mask and max_phase_mask will be excluded from the analysis when 'Mask phase' is enabled."
        }

        # Create help button
        self.help_button = HelpButton(
            self.row1, 0, 0,
            "Cross-Correlation Run Parameters Help",
            help_text,
            columnspan=1
        )

        # Cross-correlation filter checkbox
        self.checkbox_ccf_filter = MyCheckBox(self.row1, 0, 1, "CCF filter")

        # Radial velocity range controls
        self.min_rv = MyEntry(self.row1, 0, 2, "-150", label_text="Range inf. RV:", columnspan=2)
        self.max_rv = MyEntry(self.row1, 0, 4, "150", label_text="Range sup. RV:", columnspan=2)
        self.step_rv = MyEntry(self.row1, 0, 6, "1", label_text="Step RV:", columnspan=2)

        # Phase binning control
        self.bin_multi = MyEntry(self.row1, 0, 8, "0.002", label_text="Phases Bin Size:", columnspan=2)

        # Correlation method dropdown
        self.dropdown_correlation = MyDropdown(
            self.row1, 0, 10,
            ConstantVariables.LIST_CORRELATION_METHODS,
            "Type:",
            color=self.color,
            columnspan=2
        )

        # Eccentric orbit checkbox
        self.checkbox_eccentricity = MyCheckBox(self.row1, 0, 12, "Ecc. Orbit")

        # Speed optimization dropdown
        self.speeds = ["Auto", "Full"]
        self.dropdown_speed = MyDropdown(
            self.row1, 0, 13,
            self.speeds,
            "Speed CC:",
            color=self.color,
            columnspan=2
        )

        # Transit limits dropdown (determines which limit phase to pass to Night)
        self.dropdown_transit_limits = MyDropdown(
            self.row1, 0, 15,
            ["T14", "T23"],
            "Transit limits:",
            color=self.color,
            columnspan=2
        )

        # Row 2 - Instrument convolution, Doppler Shadow correction, DS width, and action buttons
        # Instrument convolution checkbox
        self.checkbox_convolution = MyCheckBox(self.row2, 0, 1, "Instrument convolution")

        # Doppler Shadow correction checkbox
        self.checkbox_doppler_shadow = MyCheckBox(self.row2, 0, 2, "Doppler Shadow (DS) correction")

        # DS width entry
        self.entry_ds_width = MyEntry(self.row2, 0, 3, "5", label_text="DS width:", columnspan=2)

        # Max function evaluations for curve fitting
        self.entry_maxfev = MyEntry(self.row2, 0, 5, "5000", label_text="maxfev:", columnspan=2)

        # Spectrum selection dropdown
        self.spectrum_options = ["Full", "Up-Mid transit", "Down-Mid transit"]
        self.dropdown_spectrum_selection = MyDropdown(
            self.row2, 0, 7,
            self.spectrum_options,
            "Spectrum selection:",
            color=self.color,
            columnspan=2
        )

        # Colormap selection dropdown
        cmap_names = [h[1] for h in ConstantVariables.HUES]

        # Grid CCF checkbox (disabled by default, kept for reference)
        # self.checkbox_grid_ccf = MyCheckBox(self.row2, 0, 9, "Grid CCF")

        # PDF orders CCF checkbox - controls generation of corrected_orders.pdf
        self.checkbox_pdf_orders_ccf = MyCheckBox(self.row2, 0, 9, "PDF orders CCF", initial_value=1)

        self.dropdown_cmap = MyDropdown(
            self.row2, 0, 10,
            cmap_names,
            "CMAP:",
            color=self.color,
            columnspan=2,
            initial_value=31  # Default to inferno
        )

        self.entry_extra_kp = MyEntry(self.row2, 0, 12, "0", label_text="Extra Kp:", columnspan=2)
        self.entry_extra_rv = MyEntry(self.row2, 0, 14, "0", label_text="Extra rv:", columnspan=2)

        # Row 3 - Masking controls and Run CC button
        # Night mask control
        self.textfield_mask_night = MyTextField(self.row3, 0, 1, "1", "Mask night:", width=15)

        # RV masking checkbox
        self.checkbox_mask_rv = MyCheckBox(self.row3, 0, 3, "Mask rv")

        # RV mask range entries
        self.entry_min_rv_mask = MyEntry(self.row3, 0, 4, "0", label_text="Min rv mask:", columnspan=2)
        self.entry_max_rv_mask = MyEntry(self.row3, 0, 6, "0", label_text="Max rv mask:", columnspan=2)

        # Phase masking checkbox
        self.checkbox_mask_phase = MyCheckBox(self.row3, 0, 8, "Mask phase")

        # Phase mask range entries
        self.entry_min_phase_mask = MyEntry(self.row3, 0, 9, "0", label_text="Min phase mask:", columnspan=2)
        self.entry_max_phase_mask = MyEntry(self.row3, 0, 11, "0", label_text="Max phase mask:", columnspan=2)

        # Run CC button
        self.button_run_cc = MyButton(
            self.row3, 0, 13,
            'RUN',
            '#f5674a',
            self.run_cc,
            color_panel=self.color
        )

        # Show previous CC button
        self.button_show_previous_cc = MyButton(
            self.row3, 0, 14,
            'SHOW LAST PLOT',
            '#33c4ff',
            self.show_run_cc,
            color_panel=self.color
        )

    def run_cc(self):
        """
        Run cross-correlation analysis.

        Collects GUI parameters, saves them to the exchange pkl, and launches
        run_cc_background.py as a subprocess. The GUI remains responsive while
        computation runs. check_proc() polls every 500ms for completion.
        """
        if self.widget_nights is not None:
            selected_nights = self.widget_nights.textfield_selection.get_text()
            if selected_nights == "":
                messagebox.showerror("No nights selected", "Please select nights.")
                return
        try:
            target = self.target_dropdown.get_value()

            if self.widget_nights is None:  # retrieval mode
                mode = 0
                (
                    path_results, path_instruments, order_sel, dates, instruments,
                    tell_rm_method, wavelength, transit_depth, model_name, rad_mode
                ) = self._setup_retrieval_mode(target)
            else:  # night/manual mode
                mode = 1
                (
                    path_results, path_instruments, order_sel, dates, instruments,
                    tell_rm_method, wavelength, transit_depth, model_name, rad_mode, error, message
                ) = self._setup_night_mode(target)

                if error:
                    messagebox.showerror("Order Selection Path Error", message)
                    return

            # Save all parameters to exchange pkl and launch background subprocess
            self._save_exchange_pkl(
                path_results, path_instruments, order_sel, dates, instruments,
                tell_rm_method, wavelength, transit_depth, model_name, target,
                self.checkbox_ccf_filter.get_value(), mode, rad_mode,
                self.dropdown_speed.get_value(), self.checkbox_convolution.get_value()
            )
            self.button_run_cc.button.configure(state="disabled")
            self.p = subprocess.Popen(
                [
                    "python3",
                    str(Path(
                        self.path_default, "GUIBRUSHR", "GUI", "Input_Output_Panels",
                        "Input_Panels", "Frame_Cross_Correlation",
                        "run_cc_background.py"
                    )),
                    str(self.path_exchange),
                    self.path_default
                ],
                stderr=subprocess.STDOUT,
                universal_newlines=True,
            )
            self.window.after(500, self.check_proc)

        except Exception as e:
            error_run_cc = str(e) + str(traceback.format_exc())
            MyFigure(title="Error in run cc", message=error_run_cc)
            print(error_run_cc)

    def _setup_retrieval_mode(self, target):
        """
        Set up parameters for retrieval mode analysis.

        Args:
            target: Target name

        Returns:
            tuple: (path_results, path_instruments, order_sel, dates, instruments,
                   tell_rm_method, wavelength, transit_depth, model_name, rad_mode)
        """
        # Get values from filter table
        arr_values = self.filters_and_table.frame_table.table.get_arr_values()
        path_results = str(Path(
            self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER,
            arr_values[ConstantVariables.DICT_FILTER_TABLE["ID"]["index"]]
        ))

        # Load general information
        df_general_info = read_csv(str(Path(path_results, "df_general_info.csv")))
        transit_depth = read_fits(str(Path(path_results, "model_high_low_res", "transit_depth_HR.fits")))
        wavelength = read_fits(str(Path(path_results, "model_high_low_res", "wavelength_HR.fits")))

        # Extract parameters
        order_sel = get_csv_value(df_general_info, "order_sel")
        # target = get_csv_value(df_general_info, "target_name")
        instrument_hr_str = get_csv_value(df_general_info, "instruments_hr_list")
        list_instruments = instrument_hr_str.split("|")

        # Set up paths and dates
        path_instruments = []
        dates = []
        instruments = []

        # Extract username and set up temporary folder
        username = os.environ.get("USER")
        tar_folder = str(
            Path(self.path_default, "GUIBRUSHR", "Files", "Temp_Files_GUI", username, "tar_unpack")
        )

        # Process each instrument
        for curr_instrument in list_instruments:
            curr_instrument = curr_instrument.split("&")
            temp_date = curr_instrument[5].split("_")
            for tmp in temp_date:
                dates.append(tmp)
                instruments.append(curr_instrument[0])
                path_instruments.append(str(Path(tar_folder, curr_instrument[0])))
                path_tar_tmp = str(Path(tar_folder, curr_instrument[0], tmp))
                os.system("rm -rf " + path_tar_tmp)
                os.system("mkdir -p " + path_tar_tmp)
                os.system(
                    "tar -xzf " +
                    str(Path(path_results, tmp + "_" + curr_instrument[0] + ".tar.gz")) +
                    " --transform='s/.*\///' -C "
                    + path_tar_tmp
                )

        # Get additional parameters
        tell_rm_method = get_csv_value(df_general_info, "tell_rm_method")
        rad_mode = get_csv_value(df_general_info, "rad_mode")

        return (path_results, path_instruments, order_sel, dates, instruments,
                tell_rm_method, wavelength, transit_depth, None, rad_mode)

    def _setup_night_mode(self, target):
        """
        Set up parameters for night/manual mode analysis.

        Args:
            target: Target name

        Returns:
            tuple: (path_results, path_instruments, order_sel, dates, instruments,
                   tell_rm_method, wavelength, transit_depth, model_name, rad_mode, error, message)
        """
        # Get parameters from widgets
        order_sel = self.widget_nights.textfield_order_selection.get_text()
        selected_nights = self.widget_nights.textfield_selection.get_text()
        tell_rm_method = self.widget_nights.dropdown_tell_rm_method.get_value()
        model_name = self.widget_nights.dropdown_cross_corr.get_value()
        rad_mode = self.widget_nights.dropdown_rad_mode.get_value()

        # Initialize lists
        dates = []
        instruments = []
        path_instruments = []

        # Initialize error tracking
        error = False
        message = "Order selection path validation errors:\n"

        # Process each instrument's nights
        for instrument_nights in selected_nights.split(";"):
            instrument_nights = instrument_nights.split(":")
            path_results = create_path_night(
                self.path_folder_targets, target,
                rad_mode, instrument_nights[0]
            )
            new_dates = instrument_nights[1].split(",")

            # Validate order selection path exists for each night
            for night in new_dates:
                path_order = Path(path_results, night, "orders_selection", order_sel)
                # TODO Remove the mv in future updates
                if not path_order.exists():
                    path_order_tmp = Path(path_results, night, order_sel)
                    if not path_order_tmp.exists():
                        error = True
                        message += f" - Order selection {order_sel} does not exist for path \n  {path_order_tmp} or {path_order}\n"
                        continue
                    path_order_without_sel = Path(path_results, night, "orders_selection")
                    os.system(f"mkdir -p {path_order_without_sel}")
                    os.system(f"mv {path_order_tmp} {path_order_without_sel}")

            for _ in new_dates:
                path_instruments.append(path_results)
                instruments.append(instrument_nights[0])
            dates = dates + new_dates

        # Set up cross-correlation path
        path_cc = str(Path(
            self.path_folder_targets, target, "Models", rad_mode,
            model_name
        ))

        # Load model data
        transit_depth = read_depth_fits(path_cc, rad_mode)
        wavelength = read_fits(str(Path(path_cc, "wavelength.fits")))

        return (None, path_instruments, order_sel, dates, instruments,
                tell_rm_method, wavelength, transit_depth, model_name, rad_mode, error, message)


    def _setup_exchange_directory(self):
        """Set up the temporary directory for pkl-based IPC with the background process."""
        username = os.environ.get("USER")
        self.path_exchange = str(
            Path(self.path_default, "GUIBRUSHR", "Files", "Temp_Files_GUI", username, "Temp_folder")
        )
        Path(self.path_exchange).mkdir(parents=True, exist_ok=True)

    def _save_exchange_pkl(
        self, path_results, path_instruments, order_sel, dates, instruments,
        tell_rm_method, wavelength, transit_depth, model_name, target,
        ccffilter, mode, rad_mode, speed, convolve_instrument
    ):
        """Save all parameters needed by run_cc_background.py into exchange_cc.pkl."""
        # Remove stale result/error files from previous runs
        for fname in ["error_cc.pkl", "result_cc.pkl"]:
            fpath = Path(self.path_exchange, fname)
            if fpath.exists():
                fpath.unlink()

        exchange_dictionary = {
            # Function parameters
            "path_results": path_results,
            "path_instruments": path_instruments,
            "order_sel": order_sel,
            "dates": dates,
            "instruments": instruments,
            "tell_rm_method": tell_rm_method,
            "wavelength": wavelength,
            "transit_depth": transit_depth,
            "model_name": model_name,
            "target": target,
            "ccffilter": ccffilter,
            "mode": mode,
            "rad_mode": rad_mode,
            "speed": speed,
            "convolve_instrument": convolve_instrument,
            # GUI widget values
            "doppler_shadow_bool": self.checkbox_doppler_shadow.get_value(),
            "ds_width": float(self.entry_ds_width.get_value()),
            "maxfev": int(self.entry_maxfev.get_value()),
            "type_transit": self.dropdown_spectrum_selection.get_value(),
            "rv_start": int(self.min_rv.get_value()),
            "rv_end": int(self.max_rv.get_value()),
            "rv_bin": int(self.step_rv.get_value()),
            "transit_limits": self.dropdown_transit_limits.get_value(),
            "eccentricity": self.checkbox_eccentricity.get_value(),
            "mask_night_str": self.textfield_mask_night.get_text().strip(),
            "mask_rv": self.checkbox_mask_rv.get_value(),
            "min_rv_mask": float(self.entry_min_rv_mask.get_value()),
            "max_rv_mask": float(self.entry_max_rv_mask.get_value()),
            "mask_phase": self.checkbox_mask_phase.get_value(),
            "min_phase_mask": float(self.entry_min_phase_mask.get_value()),
            "max_phase_mask": float(self.entry_max_phase_mask.get_value()),
            "extra_kp": float(self.entry_extra_kp.get_value()),
            "extra_rv": float(self.entry_extra_rv.get_value()),
            "pdf_orders_ccf": self.checkbox_pdf_orders_ccf.get_value(),
            "bin_multi": float(self.bin_multi.get_value()),
            "path_folder_targets": self.path_folder_targets,
            "path_default": self.path_default,
            "type_cc": self.dropdown_correlation.get_value(),
            "selected_cmap_name": self.dropdown_cmap.get_value(),
            "speeds": self.speeds,
        }
        with open(str(Path(self.path_exchange, "exchange_cc.pkl")), "wb") as f:
            dump(exchange_dictionary, f)

    def check_proc(self):
        """Poll the background cross-correlation subprocess every 500ms.

        When the process finishes, re-enables the RUN button and either
        displays the result PDF or shows an error dialog.
        """
        if self.p.poll() is not None:
            self.button_run_cc.button.configure(state="normal")
            error_path = Path(self.path_exchange, "error_cc.pkl")
            result_path = Path(self.path_exchange, "result_cc.pkl")
            if error_path.exists():
                with open(str(error_path), "rb") as fo:
                    message = load(fo)
                MyFigure(title="Error in run cc", message=message)
            elif result_path.exists():
                with open(str(result_path), "rb") as fo:
                    result = load(fo)
                MyPDFWindow(path_pdf=result["filename_pdf_total"], title="Cross-Correlation Results")
        else:
            self.window.after(500, self.check_proc)

    def show_run_cc(self):
        """
        Display previously computed cross-correlation results.

        Loads and displays the PDF file containing cross-correlation plots
        from a previous analysis run. Locates the correct results directory
        based on the current analysis mode (retrieval or night/manual) and
        selected nights/parameters.

        The method constructs the appropriate file path based on:
        - Retrieval mode: Uses filter table to locate results in RESULTS_FOLDER
        - Night/manual mode: Uses selected nights, order, telluric method, and model name

        For multi-night analysis, looks for results with ``"multi_"`` prefix.
        Shows an error message if no nights are selected.
        """
        target = self.target_dropdown.get_value()
        if self.widget_nights is None:
            arr_values = self.filters_and_table.frame_table.table.get_arr_values()
            path_result = str(Path(
                self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER,
                arr_values[ConstantVariables.DICT_FILTER_TABLE["ID"]["index"]]
            ))
            prefix = ""
            path_cc = Path(path_result, "cross_correlation")
        else:
            selected_nights = self.widget_nights.textfield_selection.get_text()
            selected_order = self.widget_nights.textfield_order_selection.get_text()
            if selected_nights == "":
                messagebox.showerror("No nights selected", "Please select nights.")
                return
            telluric_method = self.widget_nights.dropdown_tell_rm_method.get_value()
            modelel_name = self.widget_nights.dropdown_cross_corr.get_value()
            observation_dates = []
            instruments = []
            instrument_paths = []
            for instrument_nights in selected_nights.split(";"):
                instrument_nights = instrument_nights.split(":")
                result_path = create_path_night(
                    self.path_folder_targets, target,
                    self.widget_nights.dropdown_rad_mode.get_value(), instrument_nights[0]
                )
                new_dates = instrument_nights[1].split(",")
                for _ in new_dates:
                    instrument_paths.append(result_path)
                    instruments.append(instrument_nights[0])
                observation_dates = observation_dates + new_dates
            path_cc = Path(instrument_paths[0], observation_dates[0], "cross_correlation", telluric_method,
                           selected_order, modelel_name)
            if len(observation_dates) > 1:
                str_nights = "_".join(observation_dates)
                prefix = "multi_" + str_nights
            else:
                prefix = ""
        filename_pdf_total = str(Path(path_cc, prefix, "Vrad_Phase.pdf"))
        #####################
        MyPDFWindow(path_pdf=filename_pdf_total, title="Cross-Correlation Results")
