def expanded_items(self): "Create a mapping from dataset numbers to variables that are expanded." ret = {} for item in map(self.topLevelItem, range(self.topLevelItemCount())): if item.isExpanded() and item.ds() is not None: ds = item.ds() ret[ds.psy.num] = d = {} for child in map(item.child, range(item.childCount())): if child.childCount() and child.isExpanded(): d[child.text(0)] = variables = [] for vchild in map(child.child, range(child.childCount())): if vchild.childCount() and vchild.isExpanded(): variables.append(vchild.text(0)) return ret
def get_files(self, pattern): """Get input and output notebooks This method gets the files from the input directory that matches `pattern` and returns both, input files and output files Parameters ---------- pattern: str or re pattern The pattern that has to match the filenames Returns ------- dict A mapping from filenames in the :attr:`in_dir` to the corresponding filenames in the :attr:`out_dir`""" def get_ofile(odir, indir, infile): return infile.replace(indir, odir) if isinstance(pattern, six.string_types): pattern = re.compile(pattern) ret = defaultdict(dict) for indir, odir, paths in zip(self.in_dir, self.out_dir, map(os.walk, self.in_dir)): for file_dir, dirs, files in paths: if 'README.rst' not in files: continue foutdir = file_dir.replace(indir, odir + os.path.sep) for f in filter(pattern.match, files): ret[(file_dir, foutdir)][os.path.join(file_dir, f)] = \ os.path.join(foutdir, f) return ret
def validate_line_xlim(val): if isinstance(val, six.string_types): val = (val, val) val = asarray(safe_list(val)) if val.ndim == 1: val = asarray([val]) return list(map(validate_limits, val.tolist()))
def _get_abs_names(fnames): """Return the absolute paths of the given filenames""" if fnames is None: return for i, fname in enumerate(fnames): fnames[i] = ','.join(map(osp.abspath, fname.split(','))) return fnames
def __call__(self, l): """Validate whether `l` is a list with contents of :attr:`dtype` Parameters ---------- l: list-like Returns ------- list list with values of dtype :attr:`dtype` Raises ------ ValueError""" try: if self.dtype is None: l = self.listtype(l) else: l = self.listtype(map(self.dtype, l)) except TypeError: if self.dtype is None: raise ValueError( "Could not convert to list!") else: raise ValueError( "Could not convert to list of type %s!" % str(self.dtype)) if self.length is not None and len(l) != self.length: raise ValueError('List with length %i is required! Not %i!' % ( self.length, len(l))) return l
def setup_fmt_completion_model(self): fmtos = list(unique_everseen(map( self.get_name, chain.from_iterable(self.fmtos)))) model = self.fmto_completer.model() model.setRowCount(len(fmtos)) for i, name in enumerate(fmtos): model.setItem(i, QStandardItem(name))
def refresh_items(self, item=None): if item is not None: item.add_variables() else: for item in map(self.topLevelItem, range(self.topLevelItemCount())): item.add_variables()
def _get_abs_names(fnames): """Return the absolute paths of the given filenames""" if fnames is None: return for i, fname in enumerate(fnames): if fname: fnames[i] = ','.join(map(osp.abspath, fname.split(','))) return fnames
def setup_fmt_completion_model(self): fmtos = list( unique_everseen(map(self.get_name, chain.from_iterable(self.fmtos)))) model = self.fmto_completer.model() model.setRowCount(len(fmtos)) for i, name in enumerate(fmtos): model.setItem(i, QStandardItem(name))
def start_app(fnames=[], name=[], dims=None, plot_method=None, backend=False, output=None, project=None, engine=None, formatoptions=None, tight=False, new_instance=False, rc_file=None, rc_gui_file=None): """ Eventually start the QApplication or only make a plot Parameters ---------- %(make_plot.parameters)s backend: None or str The backend to use. By default, the ``'gui.backend'`` key in the :attr:`psyplot.rcParams` dictionary is used. Otherwise it can be None to use the standard matplotlib backend or a string identifying the backend new_instance: bool If True/set and the `output` parameter is not set, a new application is created rc_gui_file: str The path to a yaml configuration file that can be used to update the :attr:`psyplot_gui.rcParams` """ if project is not None and (name != [] or dims is not None): warn('The `name` and `dims` parameter are ignored if the `project`' ' parameter is set!') if rc_gui_file is not None: rcParams.load_from_file(rc_gui_file) if dims is not None and not isinstance(dims, dict): dims = dict(chain(*map(six.iteritems, dims))) if output is not None: return make_plot( fnames=fnames, name=name, dims=dims, plot_method=plot_method, output=output, project=project, engine=engine, formatoptions=formatoptions, tight=tight, rc_file=rc_file) # Lock file creation lock_file = osp.join(get_configdir(), 'psyplot.lock') lock = fasteners.InterProcessLock(lock_file) # Try to lock psyplot.lock. If it's *possible* to do it, then # there is no previous instance running and we can start a # new one. If *not*, then there is an instance already # running, which is locking that file lock_created = lock.acquire(False) if lock_created: # Start a new instance atexit.register(lock.release) elif not new_instance: send_files_to_psyplot(fnames, project, engine, plot_method, name, dims) return if backend is not False: rcParams['backend'] = backend from psyplot_gui.main import run_psyplot run_psyplot(fnames, project, engine, plot_method, name, dims)
def expand_items(self, expanded_items): """Expand tree items Parameters ---------- expanded_items: dict A mapping as returned by the :meth:`expanded_items` method""" for top in map(self.topLevelItem, range(self.topLevelItemCount())): ds = top.ds() if ds.psy.num in expanded_items: self.expandItem(top) d = expanded_items[ds.psy.num] for child in map(top.child, range(top.childCount())): if child.text(0) in d: self.expandItem(child) for vchild in map(child.child, range(child.childCount())): if vchild.text(0) in d[child.text(0)]: self.expandItem(vchild)
def fmto(self, value): name = self.get_name(value) for i, fmtos in enumerate(self.fmtos): if i == 1: # all formatoptions continue if name in map(self.get_name, fmtos): with self.no_fmtos_update: self.group_combo.setCurrentIndex(i) self.fill_fmt_combo(i, name) return
def fill_fmt_combo(self, i): """Fill the :attr:`fmt_combo` combobox based on the current group name """ if not self.no_fmtos_update: with self.no_fmtos_update: current_text = self.fmt_combo.currentText() self.fmt_combo.clear() self.fmt_combo.addItems(list(map(self.get_name, self.fmtos[i]))) ind = self.fmt_combo.findText(current_text) self.fmt_combo.setCurrentIndex(ind if ind >= 0 else 0) self.show_fmt_info(self.fmt_combo.currentIndex())
def _set_quiver_density(self, value): if all(val == 1.0 for val in value): self.plot._kwargs.pop('regrid_shape', None) elif self.decoder.is_unstructured(self.raw_data): warn("Quiver plot of unstructered data does not support the " "density keyword!", PsyPlotRuntimeWarning, logger=self.logger) elif self.decoder.is_circumpolar(self.raw_data): warn("Quiver plot of circumpolar data does not support the " "density keyword!", PsyPlotRuntimeWarning, logger=self.logger) else: shape = self.data.shape[-2:] value = map(int, [value[0]*shape[0], value[1]*shape[1]]) self.plot._kwargs['regrid_shape'] = tuple(value)
def add_figures_from_cp(self, project): """Add the items in this tree based upon the figures in the given project""" if project is None or not project.is_main: return for item in map(self.takeTopLevelItem, [0] * self.topLevelItemCount()): for child in item.takeChildren(): child.disconnect_from_array() for fig, arrays in six.iteritems(project.figs): item = QTreeWidgetItem(0) item.setText(0, fig.canvas.get_window_title()) item.addChildren([FiguresTreeItem(arr, 0) for arr in arrays]) self.addTopLevelItem(item)
def update(self, value): for fmto in map(lambda key: getattr(self, key), self.dependencies): try: gl = fmto._gridliner except AttributeError: continue if self.plotter._initializing or self.plotter.has_changed( fmto.key): gl.xlabel_style['size'] = value gl.ylabel_style['size'] = value else: for text in chain(gl.xlabel_artists, gl.ylabel_artists): text.set_size(value)
def add_figures_from_cp(self, project): """Add the items in this tree based upon the figures in the given project""" if project is None or not project.is_main: return for item in map(self.takeTopLevelItem, [0] * self.topLevelItemCount()): for child in item.takeChildren(): child.disconnect_from_array() for fig, arrays in six.iteritems(project.figs): item = QTreeWidgetItem(0) item.setText(0, fig.canvas.get_window_title()) item.addChildren( [FiguresTreeItem(weakref.ref(arr), 0) for arr in arrays]) self.addTopLevelItem(item)
def add_base_str(self, base_str, pattern='.+', pattern_base=None, append=True): """ Add further base string to this instance Parameters ---------- base_str: str or list of str Strings that are used as to look for keys to get and set keys in the :attr:`base` dictionary. If a string does not contain ``'%(key)s'``, it will be appended at the end. ``'%(key)s'`` will be replaced by the specific key for getting and setting an item. pattern: str Default: ``'.+'``. This is the pattern that is inserted for ``%(key)s`` in a base string to look for matches (using the :mod:`re` module) in the `base` dictionary. The default `pattern` matches everything without white spaces. pattern_base: str or list or str If None, the whatever is given in the `base_str` is used. Those strings will be used for generating the final search patterns. You can specify this parameter by yourself to avoid the misinterpretation of patterns. For example for a `base_str` like ``'my.str'`` it is recommended to additionally provide the `pattern_base` keyword with ``'my\.str'``. Like for `base_str`, the ``%(key)s`` is appended if not already in the string. append: bool If True, the given `base_str` are appended (i.e. it is first looked for them in the :attr:`base` dictionary), otherwise they are put at the beginning""" base_str = safe_list(base_str) pattern_base = safe_list(pattern_base or []) for i, s in enumerate(base_str): if '%(key)s' not in s: base_str[i] += '%(key)s' if pattern_base: for i, s in enumerate(pattern_base): if '%(key)s' not in s: pattern_base[i] += '%(key)s' else: pattern_base = base_str self.base_str = base_str + self.base_str self.patterns = list(map(lambda s: re.compile(s.replace( '%(key)s', '(?P<key>%s)' % pattern)), pattern_base)) + \ self.patterns
def validate_fit(val): def validate(val): if isinstance(val, six.string_types) and val.startswith('poly'): try: int(val[4:]) except ValueError: raise ValueError("Polynomials must be of the form 'poly<deg>' " "(e.g. 'poly3'), not %s!" % val) else: return val elif hasattr(val, 'fit') and hasattr(val, 'predict'): return val return try_and_error( validate_callable, validate_none, ValidateInStrings('fit', ['fit', 'linear', 'robust'], True))(val) return list(map(validate, safe_list(val)))
def fill_combos_from_project(self, project): """Fill :attr:`group_combo` and :attr:`fmt_combo` from a project Parameters ---------- project: psyplot.project.Project The project to use""" current_text = self.group_combo.currentText() with self.no_fmtos_update: self.group_combo.clear() if project is None or project.is_main or not len(project.plotters): self.fmt_combo.clear() self.groups = [] self.fmtos = [] self.line_edit.setEnabled(False) return self.line_edit.setEnabled(True) # get dimensions coords = sorted(project.coords_intersect) coords_name = [COORDSGROUP] if coords else [] coords_verbose = ['Dimensions'] if coords else [] coords = [coords] if coords else [] # get formatoptions and group them alphabetically grouped_fmts = defaultdict(list) for fmto in project._fmtos: grouped_fmts[fmto.group].append(fmto) for val in six.itervalues(grouped_fmts): val.sort(key=self.get_name) grouped_fmts = OrderedDict( sorted(six.iteritems(grouped_fmts), key=lambda t: psyp.groups.get(t[0], t[0]))) fmt_groups = list(grouped_fmts.keys()) # save original names self.groups = coords_name + [ALLGROUP] + fmt_groups # save verbose group names (which are used in the combo box) self.groupnames = coords_verbose + ['All formatoptions'] + list( map(lambda s: psyp.groups.get(s, s), fmt_groups)) # save formatoptions fmtos = list(grouped_fmts.values()) self.fmtos = coords + [sorted(chain(*fmtos), key=self.get_name) ] + fmtos self.group_combo.addItems(self.groupnames) ind = self.group_combo.findText(current_text) self.group_combo.setCurrentIndex(ind if ind >= 0 else 0) self.fill_fmt_combo(self.group_combo.currentIndex())
def fill_fmt_combo(self, i, current_text=None): """Fill the :attr:`fmt_combo` combobox based on the current group name """ if not self.no_fmtos_update: with self.no_fmtos_update: if current_text is None: current_text = self.fmt_combo.currentText() self.fmt_combo.clear() self.fmt_combo.addItems( list(map(self.get_name, self.fmtos[i]))) ind = self.fmt_combo.findText(current_text) self.fmt_combo.setCurrentIndex(ind if ind >= 0 else 0) # update completer model self.setup_fmt_completion_model() idx = self.fmt_combo.currentIndex() self.show_fmt_info(idx) self.load_fmt_widget(idx) self.set_current_fmt_value(idx)
def fill_fmt_combo(self, i, current_text=None): """Fill the :attr:`fmt_combo` combobox based on the current group name """ if not self.no_fmtos_update: with self.no_fmtos_update: if current_text is None: current_text = self.fmt_combo.currentText() self.fmt_combo.clear() self.fmt_combo.addItems(list(map(self.get_name, self.fmtos[i]))) ind = self.fmt_combo.findText(current_text) self.fmt_combo.setCurrentIndex(ind if ind >= 0 else 0) # update completer model self.setup_fmt_completion_model() idx = self.fmt_combo.currentIndex() self.show_fmt_info(idx) self.load_fmt_widget(idx) self.set_current_fmt_value(idx)
def filter_members(self, *args, **kwargs): ret = super(AutoSummClassDocumenter, self).filter_members( *args, **kwargs) if self.options.get('show-formatoptions') and hasattr( self.object, '_get_formatoptions'): fmt_members = defaultdict(set) all_fmt = set(self.object._get_formatoptions()) for i, (mname, member, isattr) in enumerate(ret): if isinstance(member, Formatoption): fmt_members[member.group].add((mname, member, isattr)) all_fmt.remove(mname) for fmt in all_fmt: fmto = getattr(self.object, fmt) fmt_members[fmto.group].add((fmt, fmto, True)) ret.extend( (tup for tup in chain(*map(sorted, fmt_members.values())) if tup not in ret)) return ret
def validate_fix(val): if val is None: return [None] try: val = validate_float(val) return [[0, val]] except ValueError: pass msg = 'Values for the fix formatoptions must be of length 2!' validator = try_and_error(validate_none, validate_list(float)) try: val = validator(val) except ValueError: val = list(map(validator, val)) if not all(v is None or len(v) == 2 for v in val): raise ValueError(msg) else: if val is not None and len(val) != 2: raise ValueError(msg) return val
def create_py(self, nb, force=False): """Create the python script from the notebook node""" # Although we would love to simply use ``nbconvert.export_python(nb)`` # this causes troubles in other cells processed by the ipython # directive. Instead of getting something like ``Out [5]:``, we get # some weird like '[0;31mOut[[1;31m5[0;31m]: [0m' which look like # color information if we allow the call of nbconvert.export_python if list(map(int, re.findall('\d+', nbconvert.__version__))) >= [4, 2]: py_file = os.path.basename(self.py_file) else: py_file = self.py_file spr.call(['jupyter', 'nbconvert', '--to=python', '--output=' + py_file, '--log-level=%s' % logger.level, self.outfile]) with open(self.py_file) as f: py_content = f.read() # comment out ipython magics py_content = re.sub('^\s*get_ipython\(\).magic.*', '# \g<0>', py_content, flags=re.MULTILINE) with open(self.py_file, 'w') as f: f.write(py_content)
def add_datasets_from_cp(self, project=None): """Clear the tree and add the datasets based upon the given `project` Parameters ---------- project: psyplot.project.Project The project containing the data array. If the project is not a main project, it's main project is used. """ if project is None: project = gcp(True) sp_arrs = ArrayList().arrays elif project.is_main: sp_arrs = gcp().arrays else: sp_arrs = project.arrays project = project.main expanded_items = self.expanded_items() # remove items from the tree self.clear() for i, ds_desc in six.iteritems( project._get_ds_descriptions( project.array_info(ds_description='all'))): top_item = DatasetTreeItem(ds_desc['ds'], self.attr_columns, 0) if ds_desc['fname'] is not None and not all( s is None for s in ds_desc['fname']): ds_desc['fname'] = ', '.join( map(osp.basename, safe_list(ds_desc['fname']))) else: ds_desc['fname'] = None top_item.setText( 0, '%s%i: %s' % ('*' if any( any(arr is arr2 for arr2 in sp_arrs) for arr in ds_desc['arr']) else '', i, ds_desc['fname'])) for arr in ds_desc['arr']: arr.psy.onbasechange.connect(self.add_datasets_from_cp) self.addTopLevelItem(top_item) self.expand_items(expanded_items)
def validate_stringlist(s): """Validate a list of strings Parameters ---------- val: iterable of strings Returns ------- list list of str Raises ------ ValueError""" if isinstance(s, six.string_types): return [six.text_type(v.strip()) for v in s.split(',') if v.strip()] else: try: return list(map(validate_str, s)) except TypeError as e: raise ValueError(e.message)
def lola_from_pattern(self, s): """ Calculate the longitude-latitude box based upon a pattern This method uses the psyplot.rcParams ``'extents.boxes'`` item to find longitude that match `s` and takes the surrounding box. Parameters ---------- s: str The pattern to use for the keys in the :attr:`psyplot.plotter.maps.lonlatboxes` dictionary and the ``'extents.boxes'`` item in the :attr:`psyplot.rcParams` Returns ------- float: lonmin, lonmax, latmin, latmax or None The surrounding longitude-latitude box of all items in ``psyplot.rcParams['extents.boxes']`` whose key match `s` if there was any match. Otherwise None is returned """ patt = re.compile(s) boxes = np.array([ box for key, box in chain(*map( six.iteritems, [lonlatboxes, rcParams['lonlatbox.boxes']])) if patt.search(key)]) if len(boxes) == 0: similar_keys = get_close_matches(s, rcParams['lonlatbox.boxes']) message = "Did not find any matches for %s!" % s if similar_keys: message += " Maybe you mean on of " + ', '.join( similar_keys) warn(message, PsyPlotRuntimeWarning, logger=self.logger) return return [boxes[:, 0].min(), boxes[:, 1].max(), boxes[:, 2].min(), boxes[:, 3].max()]
def fill_combos_from_project(self, project): """Fill :attr:`group_combo` and :attr:`fmt_combo` from a project Parameters ---------- project: psyplot.project.Project The project to use""" if rcParams['fmt.sort_by_key']: def sorter(fmto): return fmto.key else: sorter = self.get_name current_text = self.group_combo.currentText() with self.no_fmtos_update: self.group_combo.clear() if project is None or project.is_main or not len(project): self.fmt_combo.clear() self.groups = [] self.fmtos = [] self.line_edit.setEnabled(False) return self.line_edit.setEnabled(True) # get dimensions it_vars = chain.from_iterable( arr.psy.iter_base_variables for arr in project.arrays) dims = next(it_vars).dims sdims = set(dims) for var in it_vars: sdims.intersection_update(var.dims) coords = [d for d in dims if d in sdims] coords_name = [COORDSGROUP] if coords else [] coords_verbose = ['Dimensions'] if coords else [] coords = [coords] if coords else [] if len(project.plotters): # get formatoptions and group them alphabetically grouped_fmts = defaultdict(list) for fmto in project._fmtos: grouped_fmts[fmto.group].append(fmto) for val in six.itervalues(grouped_fmts): val.sort(key=sorter) grouped_fmts = OrderedDict( sorted(six.iteritems(grouped_fmts), key=lambda t: psyp.groups.get(t[0], t[0]))) fmt_groups = list(grouped_fmts.keys()) # save original names self.groups = coords_name + [ALLGROUP] + fmt_groups # save verbose group names (which are used in the combo box) self.groupnames = ( coords_verbose + ['All formatoptions'] + list( map(lambda s: psyp.groups.get(s, s), fmt_groups))) # save formatoptions fmtos = list(grouped_fmts.values()) self.fmtos = coords + [sorted( chain(*fmtos), key=sorter)] + fmtos else: self.groups = coords_name self.groupnames = coords_verbose self.fmtos = coords self.group_combo.addItems(self.groupnames) ind = self.group_combo.findText(current_text) self.group_combo.setCurrentIndex(ind if ind >= 0 else 0) self.fill_fmt_combo(self.group_combo.currentIndex())
def _iter_base_and_pattern(self, key): return zip( map(lambda s: safe_modulo(s, {'key': key}), self.base_str), self.patterns)
def process_directories(self): """Create the rst files from the input directories in the :attr:`in_dir` attribute""" for base_dir, target_dir, paths in zip(self.in_dir, self.out_dir, map( os.walk, self.in_dir)): self.recursive_processing(base_dir, target_dir, paths)
def recursive_processing(self, base_dir, target_dir, it): """Method to recursivly process the notebooks in the `base_dir` Parameters ---------- base_dir: str Path to the base example directory (see the `examples_dir` parameter for the :class:`Gallery` class) target_dir: str Path to the output directory for the rst files (see the `gallery_dirs` parameter for the :class:`Gallery` class) it: iterable The iterator over the subdirectories and files in `base_dir` generated by the :func:`os.walk` function""" try: file_dir, dirs, files = next(it) except StopIteration: return '', [] readme_files = {'README.md', 'README.rst', 'README.txt'} if readme_files.intersection(files): foutdir = file_dir.replace(base_dir, target_dir) create_dirs(foutdir) this_nbps = [ NotebookProcessor( infile=f, outfile=os.path.join(foutdir, os.path.basename(f)), disable_warnings=self.disable_warnings, preprocess=( (self.preprocess is True or f in self.preprocess) and not (self.dont_preprocess is True or f in self.dont_preprocess)), clear=((self.clear is True or f in self.clear) and not (self.dont_clear is True or f in self.dont_clear))) for f in map(lambda f: os.path.join(file_dir, f), filter(self.pattern.match, files))] readme_file = next(iter(readme_files.intersection(files))) else: return '', [] labels = OrderedDict() this_label = 'gallery_' + foutdir.replace(os.path.sep, '_') if this_label.endswith('_'): this_label = this_label[:-1] for d in dirs: label, nbps = self.recursive_processing( base_dir, target_dir, it) if label: labels[label] = nbps s = ".. _%s:\n\n" % this_label with open(os.path.join(file_dir, readme_file)) as f: s += f.read().rstrip() + '\n\n' s += "\n\n.. toctree::\n\n" s += ''.join(' %s\n' % os.path.splitext(os.path.basename( nbp.get_out_file()))[0] for nbp in this_nbps) for d in dirs: findex = os.path.join(d, 'index.rst') if os.path.exists(os.path.join(foutdir, findex)): s += ' %s\n' % os.path.splitext(findex)[0] s += '\n' for nbp in this_nbps: s += nbp.thumbnail_div + '\n' s += "\n.. raw:: html\n\n <div style='clear:both'></div>\n" for label, nbps in labels.items(): s += '\n.. only:: html\n\n .. rubric:: :ref:`%s`\n\n' % ( label) for nbp in nbps: s += nbp.thumbnail_div + '\n' s += "\n.. raw:: html\n\n <div style='clear:both'></div>\n" s += '\n' with open(os.path.join(foutdir, 'index.rst'), 'w') as f: f.write(s) return this_label, list(chain(this_nbps, *labels.values()))
from sphinx.ext.autodoc import ( ClassDocumenter, ModuleDocumenter, ALL, AutoDirective, PycodeError, ModuleAnalyzer, bool_option, DataDocumenter, AttributeDocumenter, is_builtin_class_method, formatargspec, getargspec, force_decode, prepare_docstring) import inspect import sphinx.ext.autodoc as ad from sphinx.ext.autosummary import Autosummary, ViewList, mangle_signature from docutils import nodes from psyplot.compat.pycompat import OrderedDict, map, filterfalse try: from psyplot.plotter import Formatoption except ImportError: pass sphinx_version = list(map(float, re.findall('\d+', sphinx.__version__)[:3])) class AutosummaryDocumenter(object): """Abstract class for for extending Documenter methods This classed is used as a base class for Documenters in order to provide the necessary methods for the :class:`AutoSummDirective`.""" def __init__(self): raise NotImplementedError def get_grouped_documenters(self, all_members=False): """Method to return the member documenters This method is somewhat like a combination of the
def start_app(fnames=[], name=[], dims=None, plot_method=None, output=None, project=None, engine=None, formatoptions=None, tight=False, encoding=None, enable_post=False, seaborn_style=None, concat_dim=get_default_value(xr.open_mfdataset, 'concat_dim'), backend=False, new_instance=False, rc_file=None, rc_gui_file=None, include_plugins=rcParams['plugins.include'], exclude_plugins=rcParams['plugins.exclude'], offline=False, pwd=None, script=None, command=None, exec_=True, callback=None): """ Eventually start the QApplication or only make a plot Parameters ---------- %(make_plot.parameters)s backend: None or str The backend to use. By default, the ``'gui.backend'`` key in the :attr:`psyplot.rcParams` dictionary is used. Otherwise it can be None to use the standard matplotlib backend or a string identifying the backend new_instance: bool If True/set and the `output` parameter is not set, a new application is created rc_gui_file: str The path to a yaml configuration file that can be used to update the :attr:`psyplot_gui.rcParams` include_plugins: list of str The plugin widget to include. Can be either None to load all that are not explicitly excluded by `exclude_plugins` or a list of plugins to include. List items can be either module names, plugin names or the module name and widget via ``'<module_name>:<widget>'`` exclude_plugins: list of str The plugin widgets to exclude. Can be either ``'all'`` to exclude all plugins or a list like in `include_plugins`. offline: bool If True/set, psyplot will be started in offline mode without intersphinx and remote access for the help explorer pwd: str The path to the working directory to use. Note if you do not provide any `fnames` or `project`, but set the `pwd`, it will switch the `pwd` of the current GUI. script: str The path to a python script that shall be run in the GUI. If the GUI is already running, the commands will be executed in this GUI. command: str Python commands that shall be run in the GUI. If the GUI is already running, the commands will be executed in this GUI exec_: bool If True, the main loop is entered. callback: str A unique identifier for the method that should be used if psyplot is already running. Set this parameter to None to avoid sending Returns ------- None or :class:`psyplot_gui.main.MainWindow` ``None`` if `exec_` is True, otherwise the created :class:`~psyplot_gui.main.MainWindow` instance """ if pwd is not None: os.chdir(pwd) if script is not None: script = osp.abspath(script) if project is not None and (name != [] or dims is not None): warn('The `name` and `dims` parameter are ignored if the `project`' ' parameter is set!') # load rcParams from file if rc_gui_file is not None: rcParams.load_from_file(rc_gui_file) # set plugins rcParams['plugins.include'] = include_plugins rcParams['plugins.exclude'] = exclude_plugins if offline: rcParams['help_explorer.online'] = False rcParams['help_explorer.use_intersphinx'] = False if dims is not None and not isinstance(dims, dict): dims = dict(chain(*map(six.iteritems, dims))) if output is not None: return make_plot( fnames=fnames, name=name, dims=dims, plot_method=plot_method, output=output, project=project, engine=engine, formatoptions=formatoptions, tight=tight, rc_file=rc_file, encoding=encoding, enable_post=enable_post, seaborn_style=seaborn_style, concat_dim=concat_dim) # Lock file creation lock_file = osp.join(get_configdir(), 'psyplot.lock') lock = fasteners.InterProcessLock(lock_file) # Try to lock psyplot.lock. If it's *possible* to do it, then # there is no previous instance running and we can start a # new one. If *not*, then there is an instance already # running, which is locking that file lock_created = lock.acquire(False) if lock_created: # Start a new instance atexit.register(lock.release) elif not new_instance: if callback is None: if fnames or project: callback = 'new_plot' elif pwd is not None: callback = 'change_cwd' fnames = [pwd] elif script is not None: callback = 'run_script' fnames = [script] elif command is not None: callback = 'command' engine = command if callback: send_files_to_psyplot( callback, fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim) return elif new_instance: rcParams['main.listen_to_port'] = False if backend is not False: rcParams['backend'] = backend from psyplot_gui.main import MainWindow fnames = _get_abs_names(fnames) if project is not None: project = _get_abs_names([project])[0] if exec_: from psyplot_gui.compat.qtcompat import QApplication app = QApplication(sys.argv) mainwindow = MainWindow.run(fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim) if script is not None: mainwindow.console.run_script_in_shell(script) if command is not None: mainwindow.console.kernel_manager.kernel.shell.run_code(command) if exec_: sys.exit(app.exec_()) else: return mainwindow
def start_app(fnames=[], name=[], dims=None, plot_method=None, output=None, project=None, engine=None, formatoptions=None, tight=False, encoding=None, enable_post=False, seaborn_style=None, output_project=None, concat_dim=get_default_value(xr.open_mfdataset, 'concat_dim'), chname={}, backend=False, new_instance=False, rc_file=None, rc_gui_file=None, include_plugins=rcParams['plugins.include'], exclude_plugins=rcParams['plugins.exclude'], offline=False, pwd=None, script=None, command=None, exec_=True, use_all=False, callback=None): """ Eventually start the QApplication or only make a plot Parameters ---------- %(make_plot.parameters)s backend: None or str The backend to use. By default, the ``'gui.backend'`` key in the :attr:`~psyplot_gui.config.rcsetup.rcParams` dictionary is used. Otherwise it can be None to use the standard matplotlib backend or a string identifying the backend new_instance: bool If True/set and the `output` parameter is not set, a new application is created rc_gui_file: str The path to a yaml configuration file that can be used to update the :attr:`~psyplot_gui.config.rcsetup.rcParams` include_plugins: list of str The plugin widget to include. Can be either None to load all that are not explicitly excluded by `exclude_plugins` or a list of plugins to include. List items can be either module names, plugin names or the module name and widget via ``'<module_name>:<widget>'`` exclude_plugins: list of str The plugin widgets to exclude. Can be either ``'all'`` to exclude all plugins or a list like in `include_plugins`. offline: bool If True/set, psyplot will be started in offline mode without intersphinx and remote access for the help explorer pwd: str The path to the working directory to use. Note if you do not provide any `fnames` or `project`, but set the `pwd`, it will switch the `pwd` of the current GUI. script: str The path to a python script that shall be run in the GUI. If the GUI is already running, the commands will be executed in this GUI. command: str Python commands that shall be run in the GUI. If the GUI is already running, the commands will be executed in this GUI use_all: bool If True, use all variables. Note that this is the default if the `output` is specified and not `name` exec_: bool If True, the main loop is entered. callback: str A unique identifier for the method that should be used if psyplot is already running. Set this parameter to None to avoid sending Returns ------- None or :class:`psyplot_gui.main.MainWindow` ``None`` if `exec_` is True, otherwise the created :class:`~psyplot_gui.main.MainWindow` instance """ if pwd is not None: os.chdir(pwd) if script is not None: script = osp.abspath(script) if project is not None and (name != [] or dims is not None): warn('The `name` and `dims` parameter are ignored if the `project`' ' parameter is set!') # load rcParams from file if rc_gui_file is not None: rcParams.load_from_file(rc_gui_file) # set plugins rcParams['plugins.include'] = include_plugins rcParams['plugins.exclude'] = exclude_plugins if offline: rcParams['help_explorer.online'] = False rcParams['help_explorer.use_intersphinx'] = False if dims is not None and not isinstance(dims, dict): dims = dict(chain(*map(six.iteritems, dims))) if output is not None: return make_plot( fnames=fnames, name=name, dims=dims, plot_method=plot_method, output=output, project=project, engine=engine, formatoptions=formatoptions, tight=tight, rc_file=rc_file, encoding=encoding, enable_post=enable_post, seaborn_style=seaborn_style, output_project=output_project, concat_dim=concat_dim, chname=chname) if use_all: name = 'all' else: name = safe_list(name) # Lock file creation if not new_instance: lock_file = osp.join(get_configdir(), 'psyplot.lock') lock = fasteners.InterProcessLock(lock_file) # Try to lock psyplot.lock. If it's *possible* to do it, then # there is no previous instance running and we can start a # new one. If *not*, then there is an instance already # running, which is locking that file lock_created = lock.acquire(False) else: lock_created = False chname = dict(chname) if lock_created: # Start a new instance atexit.register(lock.release) elif not new_instance: if callback is None: if fnames or project: callback = 'new_plot' elif pwd is not None: callback = 'change_cwd' fnames = [pwd] elif script is not None: callback = 'run_script' fnames = [script] elif command is not None: callback = 'command' engine = command if callback: send_files_to_psyplot( callback, fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim, chname) return elif new_instance: rcParams['main.listen_to_port'] = False if backend is not False: rcParams['backend'] = backend from psyplot_gui.main import MainWindow fnames = _get_abs_names(fnames) if project is not None: project = _get_abs_names([project])[0] if exec_: from psyplot_gui.compat.qtcompat import QApplication app = QApplication(sys.argv) if isinstance(new_instance, MainWindow): mainwindow = new_instance else: mainwindow = MainWindow.run(fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim, chname) if script is not None: mainwindow.console.run_script_in_shell(script) if command is not None: mainwindow.console.run_command_in_shell(command) if exec_: sys.excepthook = mainwindow.excepthook sys.exit(app.exec_()) else: return mainwindow
def __init__(self, examples_dirs=['../examples'], gallery_dirs=None, pattern='example_.+.ipynb', disable_warnings=True, dont_preprocess=[], preprocess=True, clear=True, dont_clear=[]): """ Parameters ---------- examples_dirs list containing the directories to loop through. Default: ``['../examples']`` gallerys_dirs None or list of directories where the rst files shall be created. If None, the current working directory and the name of the corresponding directory in the `examples_dirs` is used. Default: ``None`` pattern str. The pattern to use to find the ipython notebooks. Default: ``'example_.+.ipynb'`` disable_warnings Boolean controlling whether warnings shall be disabled when processing the examples. Defaultt: True preprocess If True, all examples (except those specified in the `dont_preprocess` item) will be preprocessed when creating the rst files. Otherwise it might be a list of files that shall be preprocessed. dont_preprocess If True, no example will be preprocessed when creating the rst files. Otherwise it might be a list of files that shall not be preprocessed clear If True, the output in all notebooks to download will be cleared. Otherwise it might be a list of notebook files of whom to clear the output dont_clear If True, the output in all notebooks to download will not be cleared. Otherwise it might be a list of notebook files of whom not to clear the output""" if isinstance(examples_dirs, six.string_types): examples_dirs = [examples_dirs] if gallery_dirs is None: gallery_dirs = list(map(os.path.basename, examples_dirs)) if isinstance(gallery_dirs, six.string_types): gallery_dirs = [gallery_dirs] for i, s in enumerate(examples_dirs): if not s.endswith(os.path.sep): examples_dirs[i] += os.path.sep for i, s in enumerate(gallery_dirs): if not s.endswith(os.path.sep): gallery_dirs[i] += os.path.sep self.in_dir = examples_dirs self.out_dir = gallery_dirs if isinstance(pattern, six.string_types): pattern = re.compile(pattern) self.pattern = pattern self.disable_warnings = disable_warnings self.dont_preprocess = dont_preprocess self.preprocess = preprocess self.clear = clear self.dont_clear = dont_clear
def array_items(self): """Iterable of :class:`ArrayItem` items in this list""" return filter(lambda i: i is not None, map(self.item, range(self.count())))
def start_app(fnames=[], name=[], dims=None, plot_method=None, output=None, project=None, engine=None, formatoptions=None, tight=False, encoding=None, enable_post=False, seaborn_style=None, output_project=None, concat_dim=get_default_value(xr.open_mfdataset, 'concat_dim'), chname={}, backend=False, new_instance=False, rc_file=None, rc_gui_file=None, include_plugins=rcParams['plugins.include'], exclude_plugins=rcParams['plugins.exclude'], offline=False, pwd=None, script=None, command=None, exec_=True, use_all=False, callback=None, preset=None, opengl_implementation=None, webengineview=True): """ Eventually start the QApplication or only make a plot Parameters ---------- %(make_plot.parameters)s backend: None or str The backend to use. By default, the ``'gui.backend'`` key in the :attr:`~psyplot_gui.config.rcsetup.rcParams` dictionary is used. Otherwise it can be None to use the standard matplotlib backend or a string identifying the backend new_instance: bool If True/set and the `output` parameter is not set, a new application is created rc_gui_file: str The path to a yaml configuration file that can be used to update the :attr:`~psyplot_gui.config.rcsetup.rcParams` include_plugins: list of str The plugin widget to include. Can be either None to load all that are not explicitly excluded by `exclude_plugins` or a list of plugins to include. List items can be either module names, plugin names or the module name and widget via ``'<module_name>:<widget>'`` exclude_plugins: list of str The plugin widgets to exclude. Can be either ``'all'`` to exclude all plugins or a list like in `include_plugins`. offline: bool If True/set, psyplot will be started in offline mode without intersphinx and remote access for the help explorer pwd: str The path to the working directory to use. Note if you do not provide any `fnames` or `project`, but set the `pwd`, it will switch the `pwd` of the current GUI. script: str The path to a python script that shall be run in the GUI. If the GUI is already running, the commands will be executed in this GUI. command: str Python commands that shall be run in the GUI. If the GUI is already running, the commands will be executed in this GUI use_all: bool If True, use all variables. Note that this is the default if the `output` is specified and not `name` exec_: bool If True, the main loop is entered. callback: str A unique identifier for the method that should be used if psyplot is already running. Set this parameter to None to avoid sending opengl_implementation: {'software', 'desktop', 'gles', 'automatic'} OpenGL implementation to pass to Qt. Possible options are 'software', 'desktop', 'gles' and 'automatic' (which let's PyQt decide). webengineview: bool If True (default), use an HTML help widget. This might not be available for all builds of PyQt5 under all circumstances. If not set, the rcParams key ``'help_explorer.use_webengineview'`` is used. Returns ------- None or :class:`psyplot_gui.main.MainWindow` ``None`` if `exec_` is True, otherwise the created :class:`~psyplot_gui.main.MainWindow` instance """ if pwd is not None: os.chdir(pwd) if script is not None: script = osp.abspath(script) if project is not None and (name != [] or dims is not None): warn('The `name` and `dims` parameter are ignored if the `project`' ' parameter is set!') # load rcParams from file if rc_gui_file is not None: rcParams.load_from_file(rc_gui_file) # set plugins rcParams['plugins.include'] = include_plugins rcParams['plugins.exclude'] = exclude_plugins if webengineview is not None: rcParams['help_explorer.use_webengineview'] = webengineview if offline: rcParams['help_explorer.online'] = False rcParams['help_explorer.use_intersphinx'] = False if dims is not None and not isinstance(dims, dict): dims = dict(chain(*map(six.iteritems, dims))) if output is not None: return make_plot( fnames=fnames, name=name, dims=dims, plot_method=plot_method, output=output, project=project, engine=engine, formatoptions=formatoptions, tight=tight, rc_file=rc_file, encoding=encoding, enable_post=enable_post, seaborn_style=seaborn_style, output_project=output_project, concat_dim=concat_dim, chname=chname, preset=preset) if use_all: name = 'all' else: name = safe_list(name) if formatoptions is not None: if not isinstance(formatoptions, dict): # list of dicts for fmt in formatoptions[1:]: formatoptions[0].update(fmt) formatoptions = formatoptions[0] if preset is not None: import psyplot.project as psy preset_data = psy.Project._load_preset(preset) else: preset_data = {} preset_data.update(formatoptions) preset = tempfile.NamedTemporaryFile(prefix='psy_', suffix='.yml').name with open(preset, 'w') as f: yaml.dump(preset_data, f) # make preset path absolute if preset is not None and not isinstance(preset, dict) and \ osp.exists(preset): preset = osp.abspath(preset) # Lock file creation if not new_instance: lock_file = osp.join(get_configdir(), 'psyplot.lock') lock = fasteners.InterProcessLock(lock_file) # Try to lock psyplot.lock. If it's *possible* to do it, then # there is no previous instance running and we can start a # new one. If *not*, then there is an instance already # running, which is locking that file lock_created = lock.acquire(False) else: lock_created = False chname = dict(chname) if lock_created: # Start a new instance atexit.register(lock.release) elif not new_instance: if callback is None: if fnames or project: callback = 'new_plot' elif pwd is not None: callback = 'change_cwd' fnames = [pwd] elif script is not None: callback = 'run_script' fnames = [script] elif command is not None: callback = 'command' engine = command if callback: send_files_to_psyplot( callback, fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim, chname, preset) return elif new_instance: rcParams['main.listen_to_port'] = False if backend is not False: rcParams['backend'] = backend from psyplot_gui.main import MainWindow fnames = _get_abs_names(fnames) if project is not None: project = _get_abs_names([project])[0] if exec_: from psyplot_gui.compat.qtcompat import QApplication app = QApplication(sys.argv) _set_opengl_implementation(opengl_implementation) if isinstance(new_instance, MainWindow): mainwindow = new_instance else: mainwindow = MainWindow.run(fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim, chname, preset) if script is not None: mainwindow.console.run_script_in_shell(script) if command is not None: mainwindow.console.run_command_in_shell(command) if exec_: sys.excepthook = mainwindow.excepthook sys.exit(app.exec_()) else: return mainwindow
def get_plots_item(self, item): for child in map(item.child, range(item.childCount())): if child.text(0) == 'Plots': return child