Source code for GUIBRUSHR.GUI.Input_Output_Panels.Input_Panels.TabPanels.FrameCCNIght.FrameCCNight

"""
Frame for handling Cross-Correlation Night selection and configuration.

This module provides a GUI panel for selecting and configuring cross-correlation
parameters for night observations, including target selection, instrument settings,
and night simulation options.
"""
from pathlib import Path

# Local application imports
from GUIBRUSHR.GUI.Input_Output_Panels.Input_Panels.Frame_Cross_Correlation.Notebook_Cross_Correlation import (
    NotebookCrossCorrelation
)
from GUIBRUSHR.GUI.LAYOUT.MyPanel import MyPanel
from GUIBRUSHR.GUI.WIDGET.MyButton import MyButton
from GUIBRUSHR.GUI.WIDGET.MyCheckBox import MyCheckBox
from GUIBRUSHR.GUI.WIDGET.MyDropDown import MyDropdown
from GUIBRUSHR.GUI.WIDGET.MyTextField import MyTextField
from GUIBRUSHR.General_Constants.FunctionsAndConstants.Constant_Variables import ConstantVariables
from GUIBRUSHR.GUI.DataInterface.DataInterface import (
    get_target_info,
    get_target_list,
    get_target_instruments,
    get_target_nights,
    get_list_cross_corr_models
)
from GUIBRUSHR.General_Constants.Classes.HelpButton import HelpButton


[docs] class FrameCCNight(MyPanel): """ Panel for managing cross-correlation night selection and configuration. This class provides a GUI interface for selecting targets, instruments, and configuring cross-correlation parameters for night observations. """
[docs] def __init__(self, parent, color, row, column, path_default, frame_input, width_GUI, height_GUI, window, **kwargs): """ Initialize the FrameCCNight panel. Args: parent: Parent widget color: Background color row: Row position column: Column position path_default: Default path for resources frame_input: Input frame reference width_GUI: GUI width height_GUI: GUI height window: Main window reference **kwargs: Additional keyword arguments """ # Initialize instance variables self.path_folder_targets = frame_input.frame_path.path_folder_targets.get_text() self.global_exc = 0 self.frame_input = frame_input self.path_default = path_default self.window = window self.color = color self.dropdown_target = None # Initialize parent class super().__init__(parent, color, row, column, **kwargs) # Create panel rows self._create_panel_rows() # Create and configure widgets self._create_widgets() # Set up event bindings self._setup_event_bindings() # Create cross-correlation notebook self._create_cc_notebook(width_GUI, height_GUI) self.global_exc = 1
def _create_panel_rows(self): """Create the three panel rows for widget organization.""" self.row1 = MyPanel(self, self.color, 0, 1) self.row2 = MyPanel(self, self.color, 1, 1) self.row3 = MyPanel(self, self.color, 2, 1) def _create_widgets(self): """Create and configure all widgets in the panel.""" self.target_list = get_target_list(self.path_folder_targets) self.target_information = get_target_info(self.path_folder_targets, self.target_list[0]) self.list_hr_instrument = get_target_instruments( self.path_folder_targets, self.target_list[0], "HR", "Transmission", Path(__file__).name ) self.nights = get_target_nights( self.path_folder_targets, self.target_list[0], "Transmission", self.list_hr_instrument[0], 0 ) self.dict_list_cc = get_list_cross_corr_models( self.path_folder_targets, self.target_list[0], "Transmission" ) # Help text dictionary help_text = { "Target": "Select the exoplanet target for cross-correlation analysis. Only targets previously added to the database (via the Target tab) appear in this list. The target must have associated observational data organized in the correct folder structure.", "Model CC": "Select the cross-correlation template model to use for signal detection. Models are pre-computed atmospheric transmission/emission spectra stored in the target's Models directory. These typically represent different atmospheric compositions (e.g., different molecular abundances or T-P profiles).", "Rad. Transf. Mode": "Radiative transfer mode: 'Transmission' for primary transit observations (planet in front of star, atmospheric absorption features) or 'Emission' for secondary eclipse observations (planet behind star, thermal emission features).", "HR Instrument": "Select the high-resolution spectrograph used for observations. Only instruments with data in the target's folder structure appear. Different instruments may have different wavelength coverage, resolution, and observing nights.", "Order Selection": "Specify which spectral orders to process.", "Tell rm method": "Telluric removal method previously applied to the data (from the Telluric Removal tab)..", "Nights": "Available observation nights for the selected target, instrument, and mode. Nights are detected automatically from the folder structure. Format: YYYY-MM-DD. Multiple nights can be selected by listing them comma-separated.", "Night sim/syn": "When checked, loads simulated or synthetic observation nights instead of real observational data. Simulated nights are useful for testing, validation, and injection-recovery experiments.", "Selection for CC": "Multi-instrument/multi-night selection string for cross-correlation. Format: 'Instrument1:Night1,Night2;Instrument2:Night3,Night4'. Use 'UPDATE SELECTION' button to add each instrument's nights to this field. This allows combining data from different instruments or multiple nights in a single cross-correlation analysis." } # Create help button self.help_button = HelpButton( self.row1, 0, 0, "Cross-Correlation Night Selection Help", help_text, columnspan=1 ) # Row 1 widgets self.dropdown_target = MyDropdown( self.row1, 0, 1, self.target_list, "Target:", color=self.color, columnspan=2 ) self.dropdown_cross_corr = MyDropdown( self.row1, 0, 3, list(sorted(self.dict_list_cc.keys())), "Model CC", initial_value=0, color=self.color, columnspan=2 ) self.dropdown_rad_mode = MyDropdown( self.row1, 0, 5, ConstantVariables.LIST_RAD_MODE, "Rad. Transf. Mode:", initial_value=0, color=self.color, columnspan=2 ) self.dropdown_hr_instrument = MyDropdown( self.row1, 0, 7, self.list_hr_instrument, "HR Instrument:", color=self.color, columnspan=2 ) self.textfield_order_selection = MyTextField( self.row1, 0, 9, "full", "Order Selection:", color=self.color, columnspan=3, width=20 ) self.dropdown_tell_rm_method = MyDropdown( self.row1, 0, 12, ConstantVariables.LIST_TELL_TABLE, "Tell rm method:", color=self.color, columnspan=2 ) # Row 2 widgets self.textfield_nights = MyTextField( self.row2, 0, 1, self.nights, "Nights:", color=self.color, columnspan=3, width=40, height=3 ) self.check_nights_sim = MyCheckBox(self.row2, 0, 4, "Night sim/syn") self.button_add_selection = MyButton( self.row2, 0, 5, 'UPDATE SELECTION', "#00AA00", command=self.update_selection ) self.textfield_selection = MyTextField( self.row2, 0, 7, "", "Selection for CC:", color=self.color, columnspan=3, width=80, height=3, rowspan=9 ) def _setup_event_bindings(self): """Set up event bindings for widgets.""" self.check_nights_sim.var.trace("w", lambda *args: self.update_night_sim()) self.dropdown_target.chosen_var.trace("w", lambda *args: self.update_target()) self.dropdown_hr_instrument.chosen_var.trace("w", lambda *args: self.update_hr()) self.dropdown_rad_mode.chosen_var.trace("w", lambda *args: self.update_from_rad_mode()) def _create_cc_notebook(self, width_GUI, height_GUI): """Create the cross-correlation notebook widget.""" self.notebook_CC = NotebookCrossCorrelation( self.row3, self.color, 0, 1, self.path_default, self.frame_input, self.window, ConstantVariables.list_tab_cross_correlation_2, width_GUI, height_GUI, widget_nights=self )
[docs] def update_selection(self): """Update the selection text field with current instrument and nights.""" past_txt = self.textfield_selection.get_text() if past_txt: past_txt += ";" nights = self.textfield_nights.get_text() new_instrument = f"{self.dropdown_hr_instrument.get_value()}:{nights}" self.textfield_selection.insert_text(past_txt + new_instrument)
[docs] def update_target(self): """Update widgets when target selection changes.""" if self.global_exc == 0: return target_id = self.dropdown_target.get_value() self._update_target_data(target_id) self._refresh_target_widgets(target_id)
def _update_target_data(self, target_id): """Update data based on selected target.""" self.list_hr_instrument = get_target_instruments( self.path_folder_targets, target_id, "HR", self.dropdown_rad_mode.get_value(), Path(__file__).name ) self.nights = get_target_nights( self.path_folder_targets, target_id, self.dropdown_rad_mode.get_value(), self.list_hr_instrument[0], self.check_nights_sim.get_value() ) self.target_information = get_target_info( self.path_folder_targets, target_id, self.dropdown_rad_mode.get_value() ) self.textfield_nights.insert_text(self.nights) def _refresh_target_widgets(self, target_id): """Refresh widgets with new target data.""" self.dropdown_hr_instrument.clean_widget() self.dropdown_cross_corr.clean_widget() self.dict_list_cc = get_list_cross_corr_models( self.path_folder_targets, target_id, self.dropdown_rad_mode.get_value() ) self.dropdown_cross_corr = MyDropdown( self.row1, 0, 3, list(sorted(self.dict_list_cc.keys())), "Model CC", initial_value=0, color=self.color, columnspan=2 ) self.dropdown_hr_instrument = MyDropdown( self.row1, 0, 7, self.list_hr_instrument, "HR Instrument:", color=self.color, columnspan=2 ) self.dropdown_hr_instrument.chosen_var.trace("w", lambda *args: self.update_hr()) self.update_hr()
[docs] def update_night_sim(self): """Update nights when simulation checkbox changes.""" if self.global_exc == 0: return target_id = self.dropdown_target.get_value() nights = get_target_nights( self.path_folder_targets, target_id, self.dropdown_rad_mode.get_value(), self.dropdown_hr_instrument.get_value(), self.check_nights_sim.get_value() ) self.textfield_nights.insert_text(nights)
[docs] def update_hr(self): """Update nights when HR instrument changes.""" instrument = self.dropdown_hr_instrument.get_value() target_id = self.dropdown_target.get_value() nights = get_target_nights( self.path_folder_targets, target_id, self.dropdown_rad_mode.get_value(), instrument, self.check_nights_sim.get_value() ) self.textfield_nights.insert_text(nights)
[docs] def modify_target_list(self, target_list): """Update the target dropdown with a new list of targets.""" self.dropdown_target.clean_widget() self.dropdown_target = MyDropdown( self.row1, 0, 1, target_list, "Target:", color=self.color, columnspan=2 ) self.dropdown_target.chosen_var.trace("w", lambda *args: self.update_target())
[docs] def update_from_rad_mode(self): """Update widgets when radiation mode changes.""" target_id = self.dropdown_target.get_value() self._update_rad_mode_data(target_id) self._refresh_rad_mode_widgets(target_id)
def _update_rad_mode_data(self, target_id): """Update data based on radiation mode.""" self.list_hr_instrument = get_target_instruments( self.path_folder_targets, target_id, "HR", self.dropdown_rad_mode.get_value(), Path(__file__).name ) def _refresh_rad_mode_widgets(self, target_id): """Refresh widgets with new radiation mode data.""" self.dropdown_hr_instrument.clean_widget() self.dropdown_cross_corr.clean_widget() self.dict_list_cc = get_list_cross_corr_models( self.path_folder_targets, target_id, self.dropdown_rad_mode.get_value() ) self.dropdown_cross_corr = MyDropdown( self.row1, 0, 3, list(sorted(self.dict_list_cc.keys())), "Model CC", initial_value=0, color=self.color, columnspan=2 ) self.dropdown_hr_instrument = MyDropdown( self.row1, 0, 7, self.list_hr_instrument, "HR Instrument:", color=self.color, columnspan=2 ) self.dropdown_hr_instrument.chosen_var.trace("w", lambda *args: self.update_hr()) self.update_hr()