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()
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)
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)
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)
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)
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
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)
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