def run(cls, fnames=[], project=None, engine=None, plot_method=None, name=None, dims=None, encoding=None, enable_post=False, seaborn_style=None, concat_dim=get_default_value(xr.open_mfdataset, 'concat_dim'), chname={}, show=True): """ Create a mainwindow and open the given files or project This class method creates a new mainwindow instance and sets the global :attr:`mainwindow` variable. Parameters ---------- %(MainWindow.open_external_files.parameters)s %(MainWindow.parameters)s Notes ----- - There can be only one mainwindow at the time - This method does not create a QApplication instance! See :meth:`run_app` See Also -------- run_app """ mainwindow = cls(show=show) _set_mainwindow(mainwindow) if fnames or project: mainwindow.open_external_files( fnames, project, engine, plot_method, name, dims, encoding, enable_post, seaborn_style, concat_dim, chname) psyplot.with_gui = True return mainwindow
def open_external_files(self, fnames=[], project=None, engine=None, plot_method=None, name=None, dims=None, encoding=None, enable_post=False, seaborn_style=None, concat_dim=get_default_value( xr.open_mfdataset, 'concat_dim'), chname={}): """ Open external files Parameters ---------- %(make_plot.parameters.fnames|project|engine|plot_method|name|dims|encoding|enable_post|seaborn_style|concat_dim|chname)s """ if seaborn_style is not None: import seaborn as sns sns.set_style(seaborn_style) if project is not None: fnames = [s.split(',') for s in fnames] if not isinstance(project, dict): project = psyd.safe_list(project)[0] single_files = (l[0] for l in fnames if len(l) == 1) alternative_paths = defaultdict(lambda: next(single_files, None)) alternative_paths.update(list(l for l in fnames if len(l) == 2)) p = psy.Project.load_project( project, alternative_paths=alternative_paths, engine=engine, main=not psy.gcp(), encoding=encoding, enable_post=enable_post, chname=chname) if isinstance(project, six.string_types): p.attrs.setdefault('project_file', project) return True else: self.new_plots(False) self.plot_creator.open_dataset(fnames, engine=engine, concat_dim=concat_dim) if name == 'all': ds = self.plot_creator.get_ds() name = sorted(set(ds.variables) - set(ds.coords)) self.plot_creator.insert_array( list(filter(None, psy.safe_list(name)))) if dims is not None: ds = self.plot_creator.get_ds() dims = {key: ', '.join( map(str, val)) for key, val in six.iteritems( dims)} for i, vname in enumerate( self.plot_creator.array_table.vnames): self.plot_creator.array_table.selectRow(i) self.plot_creator.array_table.update_selected( ) self.plot_creator.array_table.selectAll() var = ds[vname[0]] self.plot_creator.array_table.update_selected( dims=var.psy.decoder.correct_dims(var, dims.copy())) if plot_method: self.plot_creator.pm_combo.setCurrentIndex( self.plot_creator.pm_combo.findText(plot_method)) self.plot_creator.exec_() return True
def open_external_files(self, fnames=[], project=None, engine=None, plot_method=None, name=None, dims=None, encoding=None, enable_post=False, seaborn_style=None, concat_dim=get_default_value( xr.open_mfdataset, 'concat_dim')): """ Open external files Parameters ---------- %(make_plot.parameters.fnames|project|engine|plot_method|name|dims|encoding|enable_post|seaborn_style|concat_dim)s """ if seaborn_style is not None: import seaborn as sns sns.set_style(seaborn_style) if project is not None: fnames = [s.split(',') for s in fnames] single_files = (l[0] for l in fnames if len(l) == 1) alternative_paths = defaultdict(lambda: next(single_files, None)) alternative_paths.update(list(l for l in fnames if len(l) == 2)) p = psy.Project.load_project(project, alternative_paths=alternative_paths, engine=engine, main=not psy.gcp(), encoding=encoding, enable_post=enable_post) if isinstance(project, six.string_types): p.attrs.setdefault('project_file', project) else: self.new_plots(False) self.plot_creator.open_dataset(fnames, engine=engine, concat_dim=concat_dim) self.plot_creator.insert_array(name) if dims is not None: self.plot_creator.array_table.selectAll() self.plot_creator.array_table.update_selected( dims={ key: ', '.join(map(str, val)) for key, val in six.iteritems(dims) }) if plot_method: self.plot_creator.pm_combo.setCurrentText(plot_method) self.plot_creator.exec_()
def make_plot(fnames=[], name=[], dims=None, plot_method=None, output=None, project=None, engine=None, formatoptions=None, tight=False, rc_file=None, encoding=None, enable_post=False, seaborn_style=None, output_project=None, concat_dim=get_default_value(xr.open_mfdataset, 'concat_dim'), chname={}): """ Eventually start the QApplication or only make a plot Parameters ---------- fnames: list of str Either the filenames to show, or, if the `project` parameter is set, the a list of `,`-separated filenames to make a mapping from the original filename to a new one name: list of str The variable names to plot if the `output` parameter is set dims: dict A mapping from coordinate names to integers if the `project` is not given plot_method: str The name of the plot_method to use output: str or list of str If set, the data is loaded and the figures are saved to the specified filename and now graphical user interface is shown project: str If set, the project located at the given file name is loaded engine: str The engine to use for opening the dataset (see :func:`psyplot.data.open_dataset`) formatoptions: dict A dictionary of formatoption that is applied to the data visualized by the chosen `plot_method` tight: bool If True/set, it is tried to figure out the tight bbox of the figure and adjust the paper size of the `output` to it rc_file: str The path to a yaml configuration file that can be used to update the :attr:`~psyplot.config.rcsetup.rcParams` encoding: str The encoding to use for loading the project. If None, it is automatically determined by pickle. Note: Set this to ``'latin1'`` if using a project created with python2 on python3. enable_post: bool Enable the :attr:`~psyplot.plotter.Plotter.post` processing formatoption. If True/set, post processing scripts are enabled in the given `project`. Only set this if you are sure that you can trust the given project file because it may be a security vulnerability. seaborn_style: str The name of the style of the seaborn package that can be used for the :func:`seaborn.set_style` function output_project: str The name of a project file to save the project to concat_dim: str The concatenation dimension if multiple files in `fnames` are provided chname: dict A mapping from variable names in the project to variable names in the datasets that should be used instead """ 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_file is not None: rcParams.load_from_file(rc_file) if dims is not None and not isinstance(dims, dict): dims = dict(chain(*map(six.iteritems, dims))) if len(output) == 1: output = output[0] if not fnames and not project: raise ValueError( "Either a filename or a project file must be provided if " "the output parameter is set!") elif project is None and plot_method is None: raise ValueError( "A plotting method must be provided if the output parameter " "is set and not the project!") if seaborn_style is not None: import seaborn as sns sns.set_style(seaborn_style) import psyplot.project as psy if project is not None: fnames = [s.split(',') for s in fnames] chname = dict(chname) single_files = (l[0] for l in fnames if len(l) == 1) alternative_paths = defaultdict(lambda: next(single_files, None)) alternative_paths.update([l for l in fnames if len(l) == 2]) p = psy.Project.load_project(project, alternative_paths=alternative_paths, engine=engine, encoding=encoding, enable_post=enable_post, chname=chname) if formatoptions is not None: p.update(fmt=formatoptions) p.export(output, tight=tight) else: pm = getattr(psy.plot, plot_method, None) if pm is None: raise ValueError("Unknown plot method %s!" % plot_method) kwargs = {'name': name} if name else {} p = pm(fnames, dims=dims or {}, engine=engine, fmt=formatoptions or {}, mf_mode=True, concat_dim=concat_dim, **kwargs) p.export(output, tight=tight) if output_project is not None: p.save_project(output_project) return
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, 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 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