Skip to content

Commit

Permalink
minor bug fixes (handley-lab#314)
Browse files Browse the repository at this point in the history
* version bump to 2.0.1

* add test for `beta` kwarg in WeightedDataFrame method `neff`

* fix missing `beta` kwarg in `WeightedDataFrame.neff`

* remove the ylabel from `plot_1d`, otherwise pandas adds in the label "Frequency" messing with our plotting grid

* remove the 1d ylabel also from `plot_2d`, otherwise pandas again puts in a "Frequency" label messing with our plotting grid

* add `kind=fastkde` shortcut to `plot_2d`

* add test that checks that the 1d ylabels are indeed empty

* add `fig.align_labels()` to 2d plots, which aligns labels independent of the potentially different length of the tick labels (significantly improving appearance in my opinion)

* Neater way to correct for Frequency

* Removed blank lines

* Added a test to check for frequency

* Removed previous fix

* Fix for ranges

* Added tests to explictly check axes are adjusting correctly

* no support for horizontal

* Corrected ranges

* Bumped version

---------

Co-authored-by: Will Handley <[email protected]>
  • Loading branch information
lukashergt and williamjameshandley authored Jul 27, 2023
1 parent 0d6618e commit a9e1ea5
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 32 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
anesthetic: nested sampling post-processing
===========================================
:Authors: Will Handley and Lukas Hergt
:Version: 2.1.1
:Version: 2.1.2
:Homepage: https://github.com/handley-lab/anesthetic
:Documentation: http://anesthetic.readthedocs.io/

Expand Down
2 changes: 1 addition & 1 deletion anesthetic/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '2.1.1'
__version__ = '2.1.2'
9 changes: 6 additions & 3 deletions anesthetic/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ def make_2d_axes(params, labels=None, lower=True, diagonal=True, upper=True,
ticks=ticks,
gridspec_kw=gridspec_kw,
subplot_spec=subplot_spec)
fig.align_labels()
return fig, axes


Expand Down Expand Up @@ -966,17 +967,18 @@ def hist_plot_1d(ax, data, *args, **kwargs):
q = quantile_plot_interval(q=q)
xmin = quantile(data, q[0], weights)
xmax = quantile(data, q[-1], weights)
range = kwargs.pop('range', (xmin, xmax))

if type(bins) == str and bins in ['knuth', 'freedman', 'blocks']:
try:
h, edges, bars = hist(data, ax=ax, bins=bins,
range=(xmin, xmax), histtype=histtype,
range=range, histtype=histtype,
color=color, *args, **kwargs)
except NameError:
raise ImportError("You need to install astropy to use astropyhist")
else:
h, edges, bars = ax.hist(data, weights=weights, bins=bins,
range=(xmin, xmax), histtype=histtype,
range=range, histtype=histtype,
color=color, *args, **kwargs)

if histtype == 'bar' and not density:
Expand Down Expand Up @@ -1285,7 +1287,8 @@ def hist_plot_2d(ax, data_x, data_y, *args, **kwargs):
pdf[pdf < cmin] = np.ma.masked
if cmax is not None:
pdf[pdf > cmax] = np.ma.masked
image = ax.pcolormesh(x, y, pdf.T, cmap=cmap, vmin=vmin,
snap = kwargs.pop('snap', True)
image = ax.pcolormesh(x, y, pdf.T, cmap=cmap, vmin=vmin, snap=snap,
*args, **kwargs)

ax.add_patch(plt.Rectangle((0, 0), 0, 0, fc=cmap(0.999), ec=cmap(0.32),
Expand Down
19 changes: 17 additions & 2 deletions anesthetic/plotting/_matplotlib/hist.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
kde_plot_1d,
fastkde_plot_1d,
hist_plot_1d,
quantile_plot_interval,
)
from anesthetic.utils import quantile


class HistPlot(_WeightedMPLPlot, _HistPlot):
Expand Down Expand Up @@ -51,10 +53,9 @@ def _get_colors(self, num_colors=None, color_kwds='color'):
return super()._get_colors(num_colors, color_kwds)

def _post_plot_logic(self, ax, data):
super()._post_plot_logic(ax, data)
ax.set_xlabel(self.xlabel)
ax.set_yticks([])
ax.set_ylim(bottom=0)
ax.set_xlim(self.bins[0], self.bins[-1])


class KdePlot(HistPlot, _KdePlot):
Expand Down Expand Up @@ -138,6 +139,20 @@ class Hist1dPlot(HistPlot):
def _kind(self) -> Literal["hist_1d"]:
return "hist_1d"

def _calculate_bins(self, data):
if "range" not in self.kwds:
q = self.kwds.get('q', 5)
q = quantile_plot_interval(q=q)
weights = self.kwds.get("weights", None)
xmin = quantile(data, q[0], weights)
xmax = quantile(data, q[-1], weights)
self.kwds["range"] = (xmin, xmax)
result = super()._calculate_bins(data)
self.kwds.pop("range")
else:
result = super()._calculate_bins(data)
return result

@classmethod
def _plot(
cls,
Expand Down
1 change: 1 addition & 0 deletions anesthetic/samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ def plot_2d(self, axes=None, *args, **kwargs):
'kde': {'diagonal': 'kde_1d', 'lower': 'kde_2d'},
'kde_1d': {'diagonal': 'kde_1d'},
'kde_2d': {'lower': 'kde_2d'},
'fastkde': {'diagonal': 'fastkde_1d', 'lower': 'fastkde_2d'},
'hist': {'diagonal': 'hist_1d', 'lower': 'hist_2d'},
'hist_1d': {'diagonal': 'hist_1d'},
'hist_2d': {'lower': 'hist_2d'},
Expand Down
6 changes: 3 additions & 3 deletions anesthetic/weighted_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pandas.util._exceptions import find_stack_level
from pandas.util import hash_pandas_object
from numpy.ma import masked_array
from anesthetic.utils import (compress_weights, neff as neff_, quantile,
from anesthetic.utils import (compress_weights, neff, quantile,
temporary_seed, adjust_docstrings)
from pandas.core.dtypes.missing import notna

Expand Down Expand Up @@ -222,10 +222,10 @@ def reset_index(self, level=None, drop=False, inplace=False,
else:
return answer.__finalize__(self, "reset_index")

def neff(self, axis=0):
def neff(self, axis=0, beta=1):
"""Effective number of samples."""
if self.isweighted(axis):
return neff_(self.get_weights(axis))
return neff(self.get_weights(axis), beta=beta)
else:
return self.shape[axis]

Expand Down
115 changes: 101 additions & 14 deletions tests/test_samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,20 +990,6 @@ def test_live_points():
assert not live_points.isweighted()


def test_hist_range_1d():
"""Test to provide a solution to #89"""
np.random.seed(3)
ns = read_chains('./tests/example_data/pc')
ax = ns.plot_1d('x0', kind='hist_1d')
x1, x2 = ax['x0'].get_xlim()
assert x1 > -1
assert x2 < +1
ax = ns.plot_1d('x0', kind='hist_1d', bins=np.linspace(-1, 1, 11))
x1, x2 = ax['x0'].get_xlim()
assert x1 <= -1
assert x2 >= +1


def test_contour_plot_2d_nan():
"""Contour plots with nans arising from issue #96"""
np.random.seed(3)
Expand Down Expand Up @@ -1291,6 +1277,10 @@ def test_samples_dot_plot():
axes = samples.x2.plot.hist_1d(ax=ax)
assert len(axes.containers) == 1

fig, ax = plt.subplots()
axes = samples.x2.plot.hist_1d(ax=ax, range=[0, 0.2])
assert axes.get_xlim()[1] < 0.3

axes = samples.drop_labels().plot.kde_2d('x0', 'x1')
assert len(axes.collections) == 5
assert axes.get_xlabel() == 'x0'
Expand Down Expand Up @@ -1380,6 +1370,23 @@ def test_samples_plot_labels():
assert samples.get_label(col) == ax.get_xlabel()


@pytest.mark.parametrize('kind', ['kde', 'hist', 'fastkde']
if 'fastkde' in sys.modules else
['kde', 'hist'])
def test_samples_empty_1d_ylabels(kind):
samples = read_chains('./tests/example_data/pc')
columns = ['x0', 'x1', 'x2', 'x3', 'x4']

axes = samples.plot_1d(columns, kind=kind+'_1d')
for col in columns:
assert axes[col].get_ylabel() == ''

axes = samples.plot_2d(columns, kind=kind)
for col in columns:
assert axes[col][col].get_ylabel() == samples.get_labels_map()[col]
assert axes[col][col].twin.get_ylabel() == ''


def test_constructors():
samples = read_chains('./tests/example_data/pc')

Expand Down Expand Up @@ -1693,3 +1700,83 @@ def test_groupby_plots():
gb_colors = [p.get_facecolor() for p in gb_ax.patches]
assert_allclose(mcmc_colors, gb_colors)
plt.close('all')


def test_hist_1d_no_Frequency():
np.random.seed(42)
pc = read_chains("./tests/example_data/pc")
axes = pc.plot_2d(['x0', 'x1', 'x2'], kind={'diagonal': 'hist_1d'})
for i in range(len(axes)):
assert axes.iloc[i, i].twin.get_ylabel() != 'Frequency'

axes = pc.plot_1d(['x0', 'x1', 'x2'], kind='hist_1d')
for ax in axes:
assert ax.get_ylabel() != 'Frequency'

fig, ax = plt.subplots()
ax = pc['x0'].plot(kind='hist_1d', ax=ax)
assert ax.get_ylabel() != 'Frequency'

fig, ax = plt.subplots()
ax = pc.x0.plot.hist_1d(ax=ax)
assert ax.get_ylabel() != 'Frequency'


@pytest.mark.parametrize('kind', ['kde', 'hist'])
def test_axes_limits_1d(kind):
np.random.seed(42)
pc = read_chains("./tests/example_data/pc")

axes = pc.plot_1d('x0', kind=f'{kind}_1d')
xmin, xmax = axes['x0'].get_xlim()
assert -0.9 < xmin < 0
assert 0 < xmax < 0.9

pc.x0 += 3
pc.plot_1d(axes, kind=f'{kind}_1d')
xmin, xmax = axes['x0'].get_xlim()
assert -0.9 < xmin < 0
assert 3 < xmax < 3.9

pc.x0 -= 6
pc.plot_1d(axes, kind=f'{kind}_1d')
xmin, xmax = axes['x0'].get_xlim()
assert -3.9 < xmin < -3
assert 3 < xmax < 3.9


@pytest.mark.parametrize('kind, kwargs',
[('kde', {}),
('hist', {'levels': [0.95, 0.68]}),
])
def test_axes_limits_2d(kind, kwargs):
np.random.seed(42)
pc = read_chains("./tests/example_data/pc")

axes = pc.plot_2d(['x0', 'x1'], kind=f'{kind}_2d', **kwargs)
xmin, xmax = axes['x0']['x1'].get_xlim()
ymin, ymax = axes['x0']['x1'].get_ylim()
assert -0.9 < xmin < 0
assert 0 < xmax < 0.9
assert -0.9 < ymin < 0
assert 0 < ymax < 0.9

pc.x0 += 3
pc.x1 -= 3
pc.plot_2d(axes, kind=f'{kind}_2d', **kwargs)
xmin, xmax = axes['x0']['x1'].get_xlim()
ymin, ymax = axes['x0']['x1'].get_ylim()
assert -0.9 < xmin < 0
assert 3 < xmax < 3.9
assert -3.9 < ymin < -3
assert 0 < ymax < 0.9

pc.x0 -= 6
pc.x1 += 6
pc.plot_2d(axes, kind=f'{kind}_2d', **kwargs)
xmin, xmax = axes['x0']['x1'].get_xlim()
ymin, ymax = axes['x0']['x1'].get_ylim()
assert -3.9 < xmin < -3
assert 3 < xmax < 3.9
assert -3.9 < ymin < -3
assert 3 < ymax < 3.9
20 changes: 12 additions & 8 deletions tests/test_weighted_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,14 +379,18 @@ def test_WeightedDataFrame_sample(frame):


def test_WeightedDataFrame_neff(frame):
neff = frame.neff()
assert isinstance(neff, float)
assert neff < len(frame)
assert neff > len(frame) * np.exp(-0.25)

neff = frame.neff(1)
assert isinstance(neff, int)
assert neff == len(frame.T)
N_eff = frame.neff()
assert isinstance(N_eff, float)
assert N_eff < len(frame)
assert N_eff > len(frame) * np.exp(-0.25)

N_eff = frame.neff(1)
assert isinstance(N_eff, int)
assert N_eff == len(frame.T)

# beta kwarg
for beta in [0.5, 1, 2, np.inf, '0.5', 'equal', 'entropy', 'kish']:
assert frame.neff(beta=beta) == neff(frame.get_weights(), beta=beta)


def test_WeightedDataFrame_compress(frame):
Expand Down

0 comments on commit a9e1ea5

Please sign in to comment.