def validate_marker(val): """Does not really make a validation because markers can be quite of different types""" if val is None: return None else: return safe_list(val)
def make_plot(self, ds, name, exec_=None): from psyplot_gui.main import mainwindow mainwindow.new_plots() mainwindow.plot_creator.switch2ds(ds) mainwindow.plot_creator.insert_array(safe_list(name)) if exec_: mainwindow.plot_creator.exec_()
def validate_sym_lims(val): validator = try_and_error( validate_none, ValidateInStrings('sym_links', ['min', 'max'], True)) val = safe_list(val) if len(val) != 2: val = val + val if not len(val) == 2: raise ValueError("Need two values for the symmetric limits, not %i" % (len(val))) return list(map(validator, val))
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 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 test_param(self, check_index_duplicates=True, check_data_duplicates=False, to_csv=True, **kwargs): def get_data(task): if not isinstance(task.data, pd.DataFrame): return task.data return [task.data] def no_duplicates(df): return df.ix[~df.index.duplicated(keep=False)] if self.param_cls is None: return to_db = self.use_db name = self.name self._test_init() kwargs.setdefault(name, {}) kwargs.setdefault('to_return', [name]) manager = self.organizer.param(stations=self.stations_file, to_csv=to_csv, to_db=to_db, **kwargs) task = manager.get_task(name) ref_data = get_data(task) # check if run worked if task.has_run: self.assertEqual( set(task.namelist_keys), set(self.organizer.exp_config['namelist']['weathergen_ctl'])) setup_from_file = False for fname in filter(None, safe_list(task.datafile)): setup_from_file = True self.assertTrue(osp.exists(fname), msg='Datafile %s of %s task does not exist!' % (fname, name)) if check_index_duplicates: for df in get_data(task): idx = df.index self.assertFalse( idx.has_duplicates, msg='%s task index data has duplicates!\n%s' % (name, idx.values[idx.duplicated(keep=False)])) if check_data_duplicates: self.assertFalse( task.data.duplicated().any(), msg='%s task data has duplicates!\n%s' % (name, task.data[task.data.duplicated(keep=False)])) engine = task.engine setup_from_db = False if engine is not None: sql_dtypes = task._split_kwargs(task.sql_dtypes) for i, table in enumerate(safe_list(task.dbname)): if table is not None: setup_from_db = True self.assertTrue(engine.has_table(table), msg='Database has no table %s of %s task' % (table, name)) data = task._get_data(i) data_cols = set(data.columns) | set(data.index.names) self.assertEqual(set(sql_dtypes[i]) & data_cols, data_cols, msg='Missing sql dtype for %s' % name) # check setup from file if setup_from_file: manager = self.organizer.param(stations=self.stations_file, **kwargs) new_task = manager.get_task(name) self.assertEqual(new_task.setup_from, 'file', msg='setup_from of %s task should be "file"!' % (name)) new_data = get_data(new_task) self.assertEqual(len(new_data), len(ref_data), msg=('Number of dataframes for %s task are not ' 'equal after setup from file!') % name) for df, df_ref in zip(new_data, ref_data): df.sort_index(inplace=True) df_ref.sort_index(inplace=True) df = no_duplicates(df) df_ref = no_duplicates(df_ref) mask = (df != df_ref).values.any(axis=1) self.assertIsNone(df_equals(df, df_ref, check_dtype=False), msg=df_diff_msg % (df.ix[mask], df_ref.ix[mask])) # check setup from db if setup_from_db: for fname in filter(None, safe_list(task.datafile)): os.remove(fname) manager = self.organizer.param(stations=self.stations_file, **kwargs) new_task = manager.get_task(name) self.assertEqual(new_task.setup_from, 'db', msg='setup_from of %s task should be "db"!' % (name)) new_data = get_data(new_task) self.assertEqual(len(new_data), len(ref_data), msg=('Number of dataframes for %s task are not ' 'equal after setup from db!') % name) for df, df_ref in zip(new_data, ref_data): df.sort_index(inplace=True) df_ref.sort_index(inplace=True) df = no_duplicates(df) df_ref = no_duplicates(df_ref) mask = (df != df_ref).values.any(axis=1) self.assertIsNone(df_equals(df, df_ref, check_dtype=False), msg=df_diff_msg % (df.ix[mask], df_ref.ix[mask])) return manager
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