def test_axescreator_subplots(self): """Test the :class:`psyplot_gui.plot_creator.SubplotCreator`""" import matplotlib.pyplot as plt from psyplot_gui.plot_creator import AxesCreatorCollection # load dataset self.test_load_external_file() # create arrays self.test_plusplus() # use all items atab = self.pc.array_table items = [atab.item(i, atab.axes_col) for i in range(atab.rowCount())] # create the widget to select the subplots ac = AxesCreatorCollection('subplot') w = ac.tb.currentWidget() w.fig_edit.setText('') w.cols_edit.setText('2') w.rows_edit.setText('2') w.num1_edit.setText('2') w.num2_edit.setText('2') ac.okpressed.connect(lambda it: atab._change_axes(items, it)) QTest.mouseClick(ac.bt_ok, Qt.LeftButton) nvar = self.pc.array_table.rowCount() # create the subplots axes = self.pc.array_table.axes # test rows, cols and figure numbers self.assertEqual([ax.numCols for ax in axes], [2] * nvar) self.assertEqual([ax.numRows for ax in axes], [2] * nvar) self.assertEqual([ax.rowNum for ax in axes], [0] * nvar) self.assertEqual([ax.colNum for ax in axes], [1] * nvar) self.assertEqual([ax.get_figure().number for ax in axes], list( range(1, nvar + 1))) # close figures plt.close('all')
def test_axescreator_axes(self): """Test the :class:`psyplot_gui.plot_creator.AxesCreator`""" import matplotlib.pyplot as plt from psyplot_gui.plot_creator import AxesCreatorCollection # load dataset self.test_load_external_file() # create arrays self.test_plusplus() # use all items atab = self.pc.array_table items = [atab.item(i, atab.axes_col) for i in range(atab.rowCount())] # create the widget to select the subplots ac = AxesCreatorCollection('axes') w = ac.tb.currentWidget() w.fig_edit.setText('') w.x0_edit.setText('0.3') w.y0_edit.setText('0.4') w.x1_edit.setText('0.7') w.y1_edit.setText('0.8') ac.okpressed.connect(lambda it: atab._change_axes(items, it)) QTest.mouseClick(ac.bt_ok, Qt.LeftButton) nvar = self.pc.array_table.rowCount() # create the subplots axes = self.pc.array_table.axes boxes = [ax.get_position() for ax in axes] # test rows, cols and figure numbers self.assertEqual([box.x0 for box in boxes], [0.3] * nvar) self.assertEqual([box.y0 for box in boxes], [0.4] * nvar) self.assertEqual([box.x1 for box in boxes], [0.7] * nvar) self.assertEqual([box.y1 for box in boxes], [0.8] * nvar) self.assertEqual([ax.get_figure().number for ax in axes], list( range(1, nvar + 1))) # close figures plt.close('all')
def test_plusplus(self): """Test the add all button""" # loag a dataset self.test_load_external_file() QTest.mouseClick(self.pc.bt_add_all, Qt.LeftButton) atab = self.pc.array_table vtab = self.pc.variables_table self.assertEqual( [asstring(atab.item(irow, 0).text()) for irow in range( atab.rowCount())], [asstring(vtab.item(irow, 0).text()) for irow in range( vtab.rowCount())])
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_variables(self): def load(band): band = ds.GetRasterBand(band) a = band.ReadAsArray() no_data = band.GetNoDataValue() if no_data is not None: try: a[a == no_data] = a.dtype.type(nan) except ValueError: pass return a ds = self.ds dims = ['lat', 'lon'] chunks = ((ds.RasterYSize, ), (ds.RasterXSize, )) shape = (ds.RasterYSize, ds.RasterXSize) variables = OrderedDict() for iband in range(1, ds.RasterCount + 1): band = ds.GetRasterBand(iband) dt = dtype(gdal_array.codes[band.DataType]) if with_dask: dsk = {('x', 0, 0): (load, iband)} arr = Array(dsk, 'x', chunks, shape=shape, dtype=dt) else: arr = load(iband) attrs = band.GetMetadata_Dict() try: dt.type(nan) attrs['_FillValue'] = nan except ValueError: no_data = band.GetNoDataValue() attrs.update({'_FillValue': no_data} if no_data else {}) variables['Band%i' % iband] = Variable(dims, arr, attrs) variables['lat'], variables['lon'] = self._load_GeoTransform() return FrozenOrderedDict(variables)
def refresh_plots_item(self, item, vname, mp=None, sp=None): expand = item.isExpanded() item.takeChildren() try: num = self.ds().psy.num except AttributeError: return if mp is None: mp = gcp(True) if sp is None: sp = gcp() for i in range(len(mp)): sub = mp[i:i + 1] array_info = sub.array_info(ds_description={'arr', 'num'}) arrs = sub._get_ds_descriptions(array_info).get(num, {}) if arrs and any(vname in arr.psy.base_variables for arr in arrs['arr']): child = QTreeWidgetItem(0) prefix = '*' if sub[0] in sp else '' text = sub[0].psy._short_info() child.setText(0, prefix + text) child.setToolTip(0, text) item.addChild(child) if expand and item.childCount(): item.setExpanded(True)
def test_minus(self): """Test the minus button""" self.test_plusplus() vtab = self.pc.variables_table atab = self.pc.array_table nvar = atab.rowCount() rows = [nvar - 2, nvar - 1] for row in rows: atab.item(row, 0).setSelected(True) QTest.mouseClick(self.pc.bt_remove, Qt.LeftButton) variables = [asstring(vtab.item(row, 0).text()) for row in range(vtab.rowCount()) if row not in rows] self.assertEqual( [asstring(atab.item(irow, 0).text()) for irow in range( atab.rowCount())], variables)
def get_variables(self): # pragma: no cover def load(band): band = ds.GetRasterBand(band) a = band.ReadAsArray() no_data = band.GetNoDataValue() if no_data is not None: try: a[a == no_data] = a.dtype.type(nan) except ValueError: pass return a ds = self.ds dims = ['lat', 'lon'] chunks = ((ds.RasterYSize,), (ds.RasterXSize,)) shape = (ds.RasterYSize, ds.RasterXSize) variables = OrderedDict() for iband in range(1, ds.RasterCount+1): if with_dask: dsk = {('x', 0, 0): (load, iband)} dt = dtype(gdal_array.codes[ds.GetRasterBand(iband).DataType]) arr = Array(dsk, 'x', chunks, shape=shape, dtype=dt) else: arr = load(iband) try: dt.type(nan) attrs = {'_FillValue': nan} except ValueError: no_data = ds.GetRasterBand(iband).GetNoDataValue() attrs = {'_FillValue': no_data} if no_data else {} variables['band%i' % iband] = Variable(dims, arr, attrs) variables['lat'], variables['lon'] = self._load_GeoTransform() return FrozenOrderedDict(variables)
def test_drag_drop(self): """Test the drag and drop of the :class:`psyplot_gui.plot_creator.ArrayTable`""" self.pc.show() # XXX Try to use directly the dropEvent method by setting the source of # the event! point = QtCore.QPoint(0, 0) data = QtCore.QMimeData() event = QtGui.QDropEvent(point, Qt.MoveAction, data, Qt.LeftButton, Qt.NoModifier, QtCore.QEvent.Drop) # open dataset fname = self.get_file('test-t2m-u-v.nc') ds = psy.open_dataset(fname) self.pc.bt_get_ds.get_from_shell(ds) # add data arrays QTest.mouseClick(self.pc.bt_add_all, Qt.LeftButton) # move rows atab = self.pc.array_table old = list(atab.arr_names_dict.items()) atab.selectRow(2) atab.dropOn(event) resorted = [old[i] for i in [2, 0, 1] + list(range(3, len(old)))] self.assertEqual(list(atab.arr_names_dict.items()), resorted, msg="Rows not moved correctly!") ds.close()
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 test_1D_cf_bounds(self): final_bounds = np.arange(-180, 181, 30) lon = np.arange(-165, 166, 30) cf_bounds = np.zeros((len(lon), 2)) for i in range(len(lon)): cf_bounds[i, :] = final_bounds[i:i+2] decoder = psyd.CFDecoder() self.assertEqual(list(final_bounds), list(decoder._get_plotbounds_from_cf(lon, cf_bounds)))
def update(self, value): value = safe_list(value) if np.ndim(value) == 1: value = [value] value = cycle(value) if isinstance(self.raw_data, InteractiveList) and (self.index_in_list is None): self._range = [[] for _ in range(len(self.raw_data))] for i, da in enumerate(list(self.iter_raw_data)): self.index_in_list = i super(XFitRange, self).update(next(value)) self.index_in_list = None elif not isinstance(self.raw_data, InteractiveList) and ( self.index_in_list is not None): self._range = [[] for _ in range(self.index_in_list + 1)] super(XFitRange, self).update(next(value)) else: super(XFitRange, self).update(next(value))
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 _poly_fit(self, x, y, x_line, **kwargs): params, pcov = self.model(x, y) d = dict(zip(('c%i' % i for i in range(len(params))), params[::-1])) if pcov.size == 1: d['c0_err'] = np.sqrt(pcov)[0, 0] # calculate rsquared residuals = y - np.poly1d(params)(x) ss_res = (residuals**2).sum() ss_tot = ((y - y.mean())**2).sum() d['rsquared'] = 1 - (ss_res / ss_tot) return x_line, np.poly1d(params)(x_line), d, pcov
def test_load_external_file(self): """Test whether an external netCDF file can be loaded""" fname = self.get_file('test-t2m-u-v.nc') self.pc.open_dataset([fname]) vtab = self.pc.variables_table ds = psy.open_dataset(fname) self.assertIn(fname, self.pc.ds_combo.currentText()) self.assertEqual( {asstring(vtab.item(irow, 0).text()) for irow in range( vtab.rowCount())}, set(ds.variables) - set(ds.coords)) ds.close()
def test_plus(self): """Test the add button""" self.test_load_external_file() vtab = self.pc.variables_table atab = self.pc.array_table nvar = vtab.rowCount() rows = [nvar - 2, nvar - 1] for row in rows: vtab.item(row, 0).setSelected(True) QTest.mouseClick(self.pc.bt_add, Qt.LeftButton) self.assertEqual( [asstring(atab.item(irow, 0).text()) for irow in range( atab.rowCount())], [asstring(vtab.item(irow, 0).text()) for irow in rows])
def test_update_with_dims(self): """Test the update with the given dimensions""" self.test_plusplus() atab = self.pc.array_table atab.selectAll() atab.update_selected(dims={'time': '3'}) icol = len(atab.desc_cols) + atab.dims.index('time') vars3d = {var for var, varo in atab.get_ds().variables.items() if 'time' in varo.dims} for irow in range(atab.rowCount()): vname = atab.item(irow, atab.var_col).text() if vname in vars3d: item = atab.item(irow, icol) self.assertEqual( item.text(), '3', msg='Wrong time value %s in row %s' % ( item.text(), irow))
def bootstrap(x, y, func, n_boot, random_seed=None, **kwargs): """ Simple bootstrap algorithm used to estimate the confidence interval This function is motivated by seaborns bootstrap algorithm :func:`seaborn.algorithms.bootstrap` """ boot_dist = [] n = len(x) rs = np.random.RandomState( random_seed if random_seed is not None else rcParams[ 'plotter.linreg.bootstrap.random_seed']) for i in range(int(n_boot)): resampler = rs.randint(0, n, n) x_ = x.take(resampler, axis=0) y_ = y.take(resampler, axis=0) boot_dist.append(func(x_, y_, **kwargs)) return np.array(boot_dist)
def bootstrap(x, y, func, n_boot, random_seed=None, **kwargs): """ Simple bootstrap algorithm used to estimate the confidence interval This function is motivated by seaborns bootstrap algorithm :func:`seaborn.algorithms.bootstrap` """ boot_dist = [] n = len(x) rs = np.random.RandomState( random_seed if random_seed is not None else rcParams['plotter.linreg.bootstrap.random_seed']) for i in range(int(n_boot)): resampler = rs.randint(0, n, n) x_ = x.take(resampler, axis=0) y_ = y.take(resampler, axis=0) boot_dist.append(func(x_, y_, **kwargs)) return np.array(boot_dist)
def test_load_from_console(self): """Test whether a dataset can be loaded that is defined in the console""" fname = self.get_file('test-t2m-u-v.nc') if sys.platform == 'win32': fname = fname.replace('\\', '\\\\') self.window.console.execute( "ds = psy.open_dataset('%s')" % fname) vtab = self.pc.variables_table ds = psy.open_dataset(self.get_file('test-t2m-u-v.nc')) self.pc.bt_get_ds.get_from_shell('ds') self.assertIn('ds', self.pc.ds_combo.currentText()) self.assertEqual( {asstring(vtab.item(irow, 0).text()) for irow in range( vtab.rowCount())}, set(ds.variables) - set(ds.coords)) ds.close() self.window.console.execute("ds.close()")
def test_axescreator_select(self): """Test the :class:`psyplot_gui.plot_creator.AxesSelector`""" import matplotlib.pyplot as plt import numpy as np from matplotlib.backend_bases import MouseEvent, PickEvent from psyplot_gui.plot_creator import AxesCreatorCollection # load dataset self.test_load_external_file() # create arrays self.test_plusplus() # use all items atab = self.pc.array_table items = [atab.item(i, atab.axes_col) for i in range(2)] # create the widget to select the subplots ax1 = plt.axes([0.3, 0.4, 0.6, 0.3]) plt.figure() ax2 = plt.subplot(211) ac = AxesCreatorCollection('choose') w = ac.tb.currentWidget() fig = ax1.get_figure() mouseevent1 = MouseEvent( 'button_release_event', fig.canvas, *np.mean(ax1.get_position().get_points().T, axis=1)) w.get_picked_ax(PickEvent('pick', fig.canvas, mouseevent1, artist=ax1)) fig = ax2.get_figure() mouseevent2 = MouseEvent( 'button_release_event', ax2.get_figure().canvas, *np.mean(ax2.get_position().get_points().T, axis=1)) w.get_picked_ax(PickEvent('pick', fig.canvas, mouseevent2, artist=ax2)) ac.okpressed.connect(lambda it: atab._change_axes(items, it)) QTest.mouseClick(ac.bt_ok, Qt.LeftButton) # create the subplots axes = self.pc.array_table.axes # check them self.assertIs(axes[0], ax1) self.assertIs(axes[1], ax2) # close figures plt.close('all')
def test_add_single_subplots(self): """Test the add single subplot button""" import matplotlib.pyplot as plt self.test_load_external_file() self.test_plusplus() self.pc.cols_axis_edit.setText('2') self.pc.rows_axis_edit.setText('2') self.pc.row_axis_edit.setText('1') self.pc.col_axis_edit.setText('2') self.pc.array_table.selectAll() QTest.mouseClick(self.pc.bt_add_single_axes, Qt.LeftButton) nvar = self.pc.array_table.rowCount() # create the subplots axes = self.pc.array_table.axes # test rows, cols and figure numbers self.assertEqual([ax.numCols for ax in axes], [2] * nvar) self.assertEqual([ax.numRows for ax in axes], [2] * nvar) self.assertEqual([ax.rowNum for ax in axes], [0] * nvar) self.assertEqual([ax.colNum for ax in axes], [1] * nvar) self.assertEqual([ax.get_figure().number for ax in axes], list( range(1, nvar + 1))) plt.close('all')
def test_add_subplots(self): """Test the add subplots button""" from math import ceil import matplotlib.pyplot as plt self.test_load_external_file() self.test_plusplus() self.pc.cols_axis_edit.setText('2') self.pc.rows_axis_edit.setText('2') self.pc.max_axis_edit.setText('3') QTest.mouseClick(self.pc.bt_add_axes, Qt.LeftButton) nvar = self.pc.array_table.rowCount() nfigs = int(ceil(nvar / 3.)) # create the subplots axes = self.pc.array_table.axes self.assertEqual([ax.numCols for ax in axes], [2] * nvar) self.assertEqual([ax.numRows for ax in axes], [2] * nvar) rows = [0, 0, 1] * nfigs cols = [0, 1, 0] * nfigs self.assertEqual([ax.rowNum for ax in axes], rows) self.assertEqual([ax.colNum for ax in axes], cols) fig_nums = list(chain(*([i] * 3 for i in range(1, nfigs + 1)))) self.assertEqual([ax.get_figure().number for ax in axes], fig_nums) plt.close('all')
def get_plots_item(self, item): for child in map(item.child, range(item.childCount())): if child.text(0) == 'Plots': return child
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 current_names(self): return [self.itemText(i) for i in range(self.count())]