def __init__(self, preferences: Preferences):
     """
     Create data model from given preferences object.  This also lists all the fetch/settable values
     :param preferences:     Program preferences to establish model's default values
     """
     self._master_combine_method: int = preferences.get_master_combine_method(
     )
     self._min_max_number_clipped_per_end: int = preferences.get_min_max_number_clipped_per_end(
     )
     self._sigma_clip_threshold: float = preferences.get_sigma_clip_threshold(
     )
     self._input_file_disposition: int = preferences.get_input_file_disposition(
     )
     self._disposition_subfolder_name: str = preferences.get_disposition_subfolder_name(
     )
     self._precalibration_type: int = preferences.get_precalibration_type()
     self._precalibration_pedestal: int = preferences.get_precalibration_pedestal(
     )
     self._precalibration_fixed_path: str = preferences.get_precalibration_fixed_path(
     )
     self._precalibration_auto_directory: str = preferences.get_precalibration_auto_directory(
     )
     self._auto_directory_recursive: bool = preferences.get_auto_directory_recursive(
     )
     self._auto_directory_bias_only: bool = preferences.get_auto_directory_bias_only(
     )
     self._group_by_size: bool = preferences.get_group_by_size()
     self._group_by_temperature: bool = preferences.get_group_by_temperature(
     )
     self._group_by_filter: bool = preferences.get_group_by_filter()
     self._temperature_group_bandwidth: float = preferences.get_temperature_group_bandwidth(
     )
     self._ignore_file_type: bool = False
     self._ignore_groups_fewer_than: bool = preferences.get_ignore_groups_fewer_than(
     )
     self._minimum_group_size: int = preferences.get_minimum_group_size()
     self._display_average_adus: bool = preferences.get_display_average_adus(
     )
     self._display_auto_select_results: bool = preferences.get_display_auto_select_results(
     )
    def __init__(self, preferences: Preferences, data_model: DataModel):
        """
        Initialize the main window controller
        :param preferences: Preferences object for application defaults
        :param data_model:  Data model object for the current run
        """
        self._preferences = preferences
        self._data_model = data_model
        QMainWindow.__init__(self)
        self.ui = uic.loadUi(
            MultiOsUtil.path_for_file_in_program_directory("MainWindow.ui"))
        self._field_validity: {object, bool} = {}
        self._table_model: FitsFileTableModel
        self._indent_level = 0
        self._adu_values_known = False

        # Load algorithm from preferences

        algorithm = data_model.get_master_combine_method()
        if algorithm == Constants.COMBINE_MEAN:
            self.ui.combineMeanRB.setChecked(True)
        elif algorithm == Constants.COMBINE_MEDIAN:
            self.ui.combineMedianRB.setChecked(True)
        elif algorithm == Constants.COMBINE_MINMAX:
            self.ui.combineMinMaxRB.setChecked(True)
        else:
            assert (algorithm == Constants.COMBINE_SIGMA_CLIP)
            self.ui.combineSigmaRB.setChecked(True)

        self.ui.minMaxNumDropped.setText(
            str(data_model.get_min_max_number_clipped_per_end()))
        self.ui.sigmaThreshold.setText(
            str(data_model.get_sigma_clip_threshold()))

        # Load disposition from preferences

        disposition = data_model.get_input_file_disposition()
        if disposition == Constants.INPUT_DISPOSITION_SUBFOLDER:
            self.ui.dispositionSubFolderRB.setChecked(True)
        else:
            assert (disposition == Constants.INPUT_DISPOSITION_NOTHING)
            self.ui.dispositionNothingRB.setChecked(True)
        self.ui.subFolderName.setText(
            data_model.get_disposition_subfolder_name())

        # Pre-calibration options

        precalibration_option = data_model.get_precalibration_type()
        if precalibration_option == Constants.CALIBRATION_FIXED_FILE:
            self.ui.fixedPreCalFileRB.setChecked(True)
        elif precalibration_option == Constants.CALIBRATION_NONE:
            self.ui.noPreClalibrationRB.setChecked(True)
        elif precalibration_option == Constants.CALIBRATION_AUTO_DIRECTORY:
            self.ui.autoPreCalibrationRB.setChecked(True)
        else:
            assert precalibration_option == Constants.CALIBRATION_PEDESTAL
            self.ui.fixedPedestalRB.setChecked(True)
        self.ui.fixedPedestalAmount.setText(
            str(data_model.get_precalibration_pedestal()))
        self.ui.precalibrationPathDisplay.setText(
            os.path.basename(data_model.get_precalibration_fixed_path()))
        self.ui.autoDirectoryName.setText(
            os.path.basename(data_model.get_precalibration_auto_directory()))

        self.ui.autoRecursive.setChecked(
            data_model.get_auto_directory_recursive())
        self.ui.autoBiasOnly.setChecked(
            data_model.get_auto_directory_bias_only())
        self.ui.displayAutoResultsCB.setChecked(
            data_model.get_display_auto_select_results())

        # Grouping boxes and parameters

        self.ui.groupBySizeCB.setChecked(data_model.get_group_by_size())
        self.ui.groupByTemperatureCB.setChecked(
            data_model.get_group_by_temperature())
        self.ui.groupByFilterCB.setChecked(data_model.get_group_by_filter())
        self.ui.ignoreSmallGroupsCB.setChecked(
            data_model.get_ignore_groups_fewer_than())

        self.ui.temperatureGroupBandwidth.setText(
            f"{data_model.get_temperature_group_bandwidth()}")
        self.ui.minimumGroupSize.setText(
            str(data_model.get_minimum_group_size()))

        # Display average ADUs

        self.ui.displayAvgADUs.setChecked(
            data_model.get_display_average_adus())

        # Set up the file table
        self._table_model = FitsFileTableModel(
            self.ui.filesTable, data_model.get_ignore_file_type(),
            preferences.get_display_average_adus())
        self.ui.filesTable.setModel(self._table_model)
        # Columns should resize to best fit their contents
        self.ui.filesTable.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)

        # Write a summary, in the main tab, of the settings from the options tab (and data model)
        self.fill_options_readout()

        self.connect_responders()

        # If a window size is saved, set the window size
        window_size = self._preferences.get_main_window_size()
        if window_size is not None:
            self.ui.resize(window_size)

        self.enable_fields()
        self.enable_buttons()
    def set_up_ui(self, preferences: Preferences):
        """Set UI fields in the dialog from the given preferences settings"""
        self._preferences = preferences

        # Fill in the UI fields from the preferences object

        # Disable algorithm text fields, then re-enable with the corresponding radio button
        self.ui.minMaxNumDropped.setEnabled(False)
        self.ui.sigmaThreshold.setEnabled(False)

        # Combination algorithm radio buttons
        algorithm = preferences.get_master_combine_method()
        if algorithm == Constants.COMBINE_MEAN:
            self.ui.combineMeanRB.setChecked(True)
        elif algorithm == Constants.COMBINE_MEDIAN:
            self.ui.combineMedianRB.setChecked(True)
        elif algorithm == Constants.COMBINE_MINMAX:
            self.ui.combineMinMaxRB.setChecked(True)
        else:
            assert (algorithm == Constants.COMBINE_SIGMA_CLIP)
            self.ui.combineSigmaRB.setChecked(True)

        self.ui.minMaxNumDropped.setText(
            str(preferences.get_min_max_number_clipped_per_end()))
        self.ui.sigmaThreshold.setText(
            str(preferences.get_sigma_clip_threshold()))

        # Disposition of input files
        disposition = preferences.get_input_file_disposition()
        if disposition == Constants.INPUT_DISPOSITION_SUBFOLDER:
            self.ui.dispositionSubFolderRB.setChecked(True)
        else:
            assert (disposition == Constants.INPUT_DISPOSITION_NOTHING)
            self.ui.dispositionNothingRB.setChecked(True)
        self.ui.subFolderName.setText(
            preferences.get_disposition_subfolder_name())

        # Precalibration information
        precalibration_option = preferences.get_precalibration_type()
        if precalibration_option == Constants.CALIBRATION_FIXED_FILE:
            self.ui.FixedPreCalFileRB.setChecked(True)
        elif precalibration_option == Constants.CALIBRATION_NONE:
            self.ui.noPreClalibrationRB.setChecked(True)
        elif precalibration_option == Constants.CALIBRATION_AUTO_DIRECTORY:
            self.ui.autoPreCalibrationRB.setChecked(True)
        else:
            assert precalibration_option == Constants.CALIBRATION_PEDESTAL
            self.ui.fixedPedestalRB.setChecked(True)
        self.ui.fixedPedestalAmount.setText(
            str(preferences.get_precalibration_pedestal()))
        self.ui.precalibrationPathDisplay.setText(
            os.path.basename(preferences.get_precalibration_fixed_path()))
        self.ui.autoDirectoryName.setText(
            os.path.basename(preferences.get_precalibration_auto_directory()))

        self.ui.autoRecursive.setChecked(
            preferences.get_auto_directory_recursive())
        self.ui.autoBiasOnly.setChecked(
            preferences.get_auto_directory_bias_only())
        self.ui.displayAutoResultsCB.setChecked(
            preferences.get_display_auto_select_results())

        # Grouping information
        self.ui.groupBySizeCB.setChecked(preferences.get_group_by_size())
        self.ui.groupByTemperatureCB.setChecked(
            preferences.get_group_by_temperature())
        self.ui.groupByFilterCB.setChecked(preferences.get_group_by_filter())
        self.ui.ignoreSmallGroupsCB.setChecked(
            preferences.get_ignore_groups_fewer_than())

        self.ui.temperatureGroupBandwidth.setText(
            f"{preferences.get_temperature_group_bandwidth()}")
        self.ui.minimumGroupSize.setText(
            str(preferences.get_minimum_group_size()))

        # Display average ADUs
        self.ui.displayAverageADUs.setChecked(
            preferences.get_display_average_adus())

        # Set up responders for buttons and fields
        self.ui.combineMeanRB.clicked.connect(self.combine_mean_button_clicked)
        self.ui.combineMedianRB.clicked.connect(
            self.combine_median_button_clicked)
        self.ui.combineMinMaxRB.clicked.connect(
            self.combine_minmax_button_clicked)
        self.ui.combineSigmaRB.clicked.connect(
            self.combine_sigma_button_clicked)

        self.ui.dispositionNothingRB.clicked.connect(
            self.disposition_nothing_clicked)
        self.ui.dispositionSubFolderRB.clicked.connect(
            self.disposition_sub_folder_clicked)

        self.ui.noPreClalibrationRB.clicked.connect(
            self.precalibration_none_clicked)
        self.ui.fixedPedestalRB.clicked.connect(
            self.precalibration_pedestal_clicked)
        self.ui.FixedPreCalFileRB.clicked.connect(
            self.precalibration_file_clicked)
        self.ui.autoPreCalibrationRB.clicked.connect(
            self.precalibration_auto_clicked)

        self.ui.selectPreCalFile.clicked.connect(
            self.select_precalibration_file_clicked)
        self.ui.setAutoDirectory.clicked.connect(
            self.select_auto_calibration_directory_clicked)

        self.ui.groupBySizeCB.clicked.connect(self.group_by_size_clicked)
        self.ui.groupByTemperatureCB.clicked.connect(
            self.group_by_temperature_clicked)
        self.ui.groupByFilterCB.clicked.connect(self.group_by_filter_clicked)
        self.ui.ignoreSmallGroupsCB.clicked.connect(
            self.ignore_small_groups_clicked)

        self.ui.autoRecursive.clicked.connect(self.auto_recursive_clicked)
        self.ui.autoBiasOnly.clicked.connect(self.auto_bias_only_clicked)
        self.ui.displayAutoResultsCB.clicked.connect(
            self.display_auto_results_clicked)

        self.ui.displayAverageADUs.clicked.connect(
            self.display_average_adus_clicked)

        self.ui.closeButton.clicked.connect(self.close_button_clicked)

        # Input fields
        self.ui.minMaxNumDropped.editingFinished.connect(
            self.min_max_drop_changed)
        self.ui.sigmaThreshold.editingFinished.connect(
            self.sigma_threshold_changed)
        self.ui.subFolderName.editingFinished.connect(
            self.sub_folder_name_changed)
        self.ui.fixedPedestalAmount.editingFinished.connect(
            self.pedestal_amount_changed)
        self.ui.temperatureGroupBandwidth.editingFinished.connect(
            self.temperature_group_bandwidth_changed)
        self.ui.minimumGroupSize.editingFinished.connect(
            self.minimum_group_size_changed)

        # Tiny fonts in path display fields
        tiny_font = self.ui.precalibrationPathDisplay.font()
        tiny_font.setPointSize(10)
        self.ui.precalibrationPathDisplay.setFont(tiny_font)
        self.ui.autoDirectoryName.setFont(tiny_font)

        self.enableFields()