Example #1
0
    def __init__(self, kwargs_dict_dialog_obj, name, std_entries,
                 banned_entries, *args, **kwargs):
        """
        Initialize an instance of the :class:`~KwargsDictDialogPage` class.

        Parameters
        ----------
        kwargs_dict_dialog_obj : :obj:`~KwargsDictDialog` object
            Instance of the :class:`~KwargsDictDialog` class that initialized
            this kwargs dict page.
        name : str
            The name of this kwargs dict page.
        std_entries : list of str
            A list of all standard entry types that this kwargs dict should
            accept.
        banned_entries : list of str
            A list of all entry types that this kwargs dict should not accept.
            Usually, these entry types are used by *PRISM* and therefore should
            not be modified by the user.

        %(optional)s

        """

        # Save provided kwargs_dict_dialog_obj
        self.entry_height = kwargs_dict_dialog_obj.entry_height
        self.name = name
        self.std_entries = sset(std_entries)
        self.banned_entries = sset(banned_entries)

        # Call super constructor
        super().__init__(*args, **kwargs)

        # Create the kwargs dict window
        self.init()
Example #2
0
    def _get_model_par_seq(self, par_seq, name):
        """
        Converts a provided sequence `par_seq` of model parameter names and
        indices to a list of indices, removes duplicates and checks if every
        provided name/index is valid.

        Parameters
        ----------
        par_seq : 1D array_like of {int, str}
            A sequence of integers and strings determining which model
            parameters need to be used for a certain operation.
        name : str
            A string stating the name of the variable the result of this method
            will be stored in. Used for error messages.

        Returns
        -------
        par_seq_conv : list of int
            The provided sequence `par_seq` converted to a sorted list of
            model parameter indices.

        """

        # Do some logging
        logger = getCLogger('INIT')
        logger.info("Converting sequence of model parameter names/indices.")

        # Remove all unwanted characters from the string and split it up
        par_seq = split_seq(par_seq)

        # Check elements if they are ints or strings, and if they are valid
        for i, par_idx in enumerate(par_seq):
            try:
                # If par_idx is a string, try to use it as a parameter name
                if isinstance(par_idx, str):
                    par_seq[i] = self._par_name.index(par_idx)
                # If not, try to use it as a parameter index
                else:
                    self._par_name[par_idx]
                    par_seq[i] = par_idx % self._n_par
            # If any operation above fails, raise error
            except Exception as error:
                err_msg = ("Input argument %r[%i] is invalid! (%s)" %
                           (name, i, error))
                raise_error(err_msg, InputError, logger)

        # If everything went without exceptions, check if list is not empty and
        # remove duplicates
        if par_seq:
            par_seq = list(sset(par_seq))
        else:
            err_msg = "Input argument %r is empty!" % (name)
            raise_error(err_msg, ValueError, logger)

        # Log end
        logger.info("Finished converting sequence of model parameter "
                    "names/indices.")

        # Return it
        return (par_seq)
Example #3
0
    def addBannedNames(self, banned_names):
        """
        Adds the given `banned_names` list to the set of names that are banned
        from being used as entry names.

        Note that banned names are only used when :meth:`~get_entry_name_box`
        returns an editable combobox.

        Parameters
        ----------
        banned_names : list of str
            List containing entry names that are not allowed.

        """

        # Convert banned_names to a set
        banned_names = sset(banned_names)

        # Make sure that '' is not in banned_names
        banned_names.discard('')

        # Update the current set of banned names
        self.banned_names.update(banned_names)

        # Determine if there are any types in entry_types that are now banned
        banned_types = banned_names.intersection(self.entry_types.keys())

        # Remove all new banned types from entry_types
        for banned_type in banned_types:
            self.entry_types.pop(banned_type)
Example #4
0
    def init(self):
        """
        Sets up the kwargs dict page after it has been initialized.

        This function is mainly responsibe for creating the layout of the page;
        determining what entry types are available; and preparing for the user
        to add entries.

        """

        # Create page layout
        page_layout = QW.QVBoxLayout(self)

        # Create a grid for this layout
        self.kwargs_grid = QW.QGridLayout()
        self.kwargs_grid.setColumnStretch(1, 1)
        self.kwargs_grid.setColumnStretch(2, 2)
        page_layout.addLayout(self.kwargs_grid)

        # Add a header
        self.kwargs_grid.addWidget(QW_QLabel(""), 0, 0)
        self.kwargs_grid.addWidget(QW_QLabel("Entry type"), 0, 1)
        self.kwargs_grid.addWidget(QW_QLabel("Field value"), 0, 2)

        # Make sure that '' is not in std_entries or banned_entries
        self.std_entries.discard('')
        self.banned_entries.discard('')

        # Create list of available entry types
        self.avail_entries = sset([
            attr[12:] for attr in dir(self) if attr.startswith('create_type_')
        ])

        # Convert std_entries to solely contain valid available entry types
        self.std_entries.intersection_update(self.avail_entries)
        self.std_entries.difference_update(self.banned_entries)

        # Add an 'add' button at the bottom of this layout
        add_but = QW.QToolButton()
        add_but.setFixedSize(self.entry_height, self.entry_height)
        add_but.setToolTip("Add a new entry")
        add_but.clicked.connect(self.add_editable_entry)
        self.add_but = add_but

        # If this theme has an 'add' icon, use it
        if QG.QIcon.hasThemeIcon('add'):  # pragma: no cover
            add_but.setIcon(QG.QIcon.fromTheme('add'))
        # Else, use a simple plus
        else:
            add_but.setText('+')

        # Add button to layout
        page_layout.addWidget(add_but)
        page_layout.addStretch()

        # Set a minimum width for the first grid column
        self.kwargs_grid.setColumnMinimumWidth(0, self.entry_height)
Example #5
0
    def init(self):
        """
        Sets up the entries box after it has been initialized.

        """

        # Set the height of a single entry
        self.entry_height = 24

        # Create empty dict of non-generic entry types
        self.entry_types = {}

        # Create empty dict of entry defaults
        self.entry_defaults = {}

        # Create empty set of banned entry names
        self.banned_names = sset()

        # Create the box_layout
        box_layout = GL.QVBoxLayout(self)
        box_layout.setContentsMargins(0, 0, 0, 0)

        # Create the entries_grid
        entries_grid = GL.QGridLayout()
        entries_grid.setContentsMargins(0, 0, 0, 0)
        entries_grid.setColumnStretch(1, 1)
        entries_grid.setColumnStretch(2, 2)
        box_layout.addLayout(entries_grid)
        self.entries_grid = entries_grid

        # Add a header
        entries_grid.addWidget(GW.QLabel(""), 0, 0)
        entries_grid.addWidget(GW.QLabel("Entry name"), 0, 1)
        entries_grid.addWidget(GW.QLabel("Entry value"), 0, 2)

        # Add an 'Add'-button
        add_but = GW.QToolButton()
        add_but.setFixedSize(self.entry_height, self.entry_height)
        add_but.setToolTip("Add new entry")
        get_modified_signal(add_but).connect(self.add_entry)
        box_layout.addWidget(add_but)

        # If this theme has an 'add' icon, use it
        if QG.QIcon.hasThemeIcon('add'):
            add_but.setIcon(QG.QIcon.fromTheme('add'))
        # Else, use a simple plus
        else:
            add_but.setText('+')

        # Set size policy
        self.setSizePolicy(QW.QSizePolicy.Preferred, QW.QSizePolicy.Fixed)

        # Set a minimum width for the first column
        self.entries_grid.setColumnMinimumWidth(0, self.entry_height)
Example #6
0
    def first_init(self):
        # Obtain all colormaps that are registered in MPL
        cmaps = plt.colormaps()

        # Split cmaps up into their cmap types
        cm_types = ['sequential', 'diverging', 'cyclic', 'qualitative', 'misc']
        cmaps_cd = {cm_type: sset() for cm_type in cm_types}
        for cmap in cmaps:
            cmaps_cd[get_cmap_type(cmap)].add(cmap)

        # Create empty list of cmaps sorted on type
        cmaps_cl = []
        cum_len = []

        # Loop over every type
        for cmaps_cs in cmaps_cd.values():
            # Take all base versions of the colormaps
            cmaps_cl.extend(
                [cmap for cmap in cmaps_cs if not cmap.endswith('_r')])
            cum_len.extend([len(cmaps_cl)])

            # Also add all the reversed versions
            cmaps_cl.extend([cmap for cmap in cmaps_cs if cmap.endswith('_r')])
            cum_len.extend([len(cmaps_cl)] * 2)

        # Store list of colormaps and the category lengths
        ColorMapBox.cmaps_cl = cmaps_cl
        ColorMapBox.cum_len = cum_len

        # Create the colormap icons
        cmap_icons = sdict()
        for cmap in cmaps:
            cmap_icons[cmap] = self.create_cmap_icon(cmap, self.cmap_size)
        ColorMapBox.cmap_icons = cmap_icons

        # Save that class has been initialized for the first time
        ColorMapBox.init_flag = True
Example #7
0
def _processFileDialogArguments(parent=None,
                                caption='',
                                basedir=None,
                                filters=None,
                                initial_filter='',
                                options=None):
    # If basedir is None, set it to the current directory
    if basedir is None:
        basedir = os.getcwd()

    # Check what filters are given and act accordingly
    if filters is None:
        # If no filters are given, set filters and initial_filter to ''
        filters = ''
        initial_filter = ''
    else:
        # Loop over all filters and grab their formats and exts
        formats = sset({
            FILE_FORMATS.get(file_filter.lower(), '')
            for file_filter in filters
        })
        exts = sset({
            FILE_EXTS.get(file_filter.lower(), '')
            for file_filter in filters
        })

        # Remove all empty strings from formats and exts
        if '' in formats:
            formats.remove('')
        if '' in exts:
            exts.remove('')

        # Combine all exts together to a single string
        exts = ' '.join(exts)

        # Convert formats to a list
        formats = list(formats)

        # Add 'All Supported Files' to formats
        formats.append("All supported files (%s)" % (exts))

        # Add 'All Files' to formats
        formats.append("All files (*)")

        # Combine all formats into a single string
        filters = ';;'.join(formats)

        # Process given initial_filter
        if "*" + initial_filter.lower() in exts.split():
            # If initial_filter is in the filters, set it to the proper format
            initial_filter = FILE_FORMATS[initial_filter.lower()]
        else:
            # Else, set to 'All Supported Files'
            initial_filter = formats[-2]

    # Do not use native dialog on Linux, as it is pretty bad
    if platform.startswith('linux'):
        if options is None:
            options = GW.QFileDialog.DontUseNativeDialog
        else:
            options = options | GW.QFileDialog.DontUseNativeDialog

    # Create dict with all arguments
    args_dict = {
        'parent': parent,
        'caption': caption,
        'directory': basedir,
        'filter': filters,
        'initialFilter': initial_filter
    }

    # If options is not None, add it as well
    if options is not None:
        args_dict['options'] = options

    # Return args_dict
    return (args_dict)
Example #8
0
    def init(self):
        # Define set of CMasher colormaps that should be at the top
        cmr_cmaps = sset(
            ['dusk', 'freeze', 'gothic', 'heat', 'rainforest', 'sunburst'])

        # Check that all of those colormaps are available in CMasher
        cmr_cmaps.intersection_update(cmr.cm.cmap_d)

        # Obtain a set with default MPL colormaps that should be at the top
        std_cmaps = sset(['cividis', 'inferno', 'magma', 'plasma', 'viridis'])

        # Add CMasher colormaps to it
        std_cmaps.update(['cmr.' + cmap for cmap in cmr_cmaps])

        # Obtain reversed set of recommended colormaps
        std_cmaps_r = sset([cmap + '_r' for cmap in std_cmaps])

        # Obtain a list with all colormaps and their reverses
        all_cmaps = sset(
            [cmap for cmap in cm.cmap_d if not cmap.endswith('_r')])
        all_cmaps_r = sset([cmap for cmap in cm.cmap_d if cmap.endswith('_r')])

        # Gather all sets together
        cmaps = (std_cmaps, std_cmaps_r, all_cmaps, all_cmaps_r)

        # Determine the cumulative lengths of all four sets
        cum_len = np.cumsum(list(map(len, cmaps)))

        # Set the size for the colormap previews
        cmap_size = (100, 15)

        # If the colormap icons have not been created yet, do that now
        if not hasattr(self, 'cmap_icons'):
            cmap_icons = sdict()
            for cmap in chain(all_cmaps, all_cmaps_r):
                cmap_icons[cmap] = self.create_cmap_icon(cmap, cmap_size)
            ColorMapBox.cmap_icons = cmap_icons

        # Create a layout for this widget
        box_layout = QW.QHBoxLayout(self)
        box_layout.setContentsMargins(0, 0, 0, 0)
        self.setToolTip("Colormap to be used for the corresponding plot type")

        # Create a combobox for cmaps
        cmaps_box = QW_QComboBox()
        for cmap in chain(*cmaps):
            cmap_icon = self.cmap_icons[cmap]
            cmaps_box.addItem(cmap_icon, cmap)

        # Add some separators
        for i in reversed(cum_len[:-1]):
            cmaps_box.insertSeparator(i)
        cmaps_box.insertSeparator(cum_len[1] + 1)

        # Set remaining properties
        set_box_value(cmaps_box, rcParams['image.cmap'])
        cmaps_box.setIconSize(QC.QSize(*cmap_size))
        cmaps_box.currentTextChanged.connect(self.cmap_selected)

        # Add cmaps_box to layout
        box_layout.addWidget(cmaps_box)
        self.cmaps_box = cmaps_box