Skip to content

v0.2.6 #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Oct 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
1ce30cc
made mean diff plot with inset axes
anekimken Sep 27, 2019
7260702
implemented inset axes for Cumming plot
anekimken Sep 27, 2019
6402c32
implemented optional target axes
anekimken Sep 27, 2019
9f3d11a
Replace manual dependency specification with install_requires to fix …
mje-nz Sep 29, 2019
c62f6e9
Add Python>=3.5 requirement
mje-nz Sep 29, 2019
b450980
Remove broken distutils fallback
mje-nz Sep 29, 2019
1fd7850
Update readme
mje-nz Sep 29, 2019
464e37f
Specify test requirements in setup.py
mje-nz Sep 29, 2019
9bb5c40
Merge pull request #71 from mje-nz/fix-dependencies
josesho Sep 29, 2019
080fc27
bump v0.2.6
josesho Sep 29, 2019
51dbe11
bump v0.2.6.
josesho Sep 29, 2019
d1ca3bc
removed hardcoded axes positions for inset axes. Made test script
anekimken Oct 1, 2019
d1a8dc9
Returned trailing whitespace to original so PR is easier to read
anekimken Oct 1, 2019
135b654
Some more spacing fixes for PR aesthetics
anekimken Oct 1, 2019
5b25e46
and a bit more spacing aesthetics
anekimken Oct 1, 2019
2c2d759
Merge pull request #73 from anekimken/inset_axes
josesho Oct 2, 2019
c5c67e5
fix typo
josesho Oct 2, 2019
73bc6b7
add inline note about addition of inset plotting
josesho Oct 2, 2019
5710d07
fix bug in despining of Cumming plots in inset axes
josesho Oct 2, 2019
9925ce4
remove double assignment
josesho Oct 2, 2019
97cff61
update docstring for new `ax` kwarg.
josesho Oct 2, 2019
15a28cd
update docstring and example for new `ax` kwarg.
josesho Oct 2, 2019
1ffc5de
Merge branch 'v0.2.6' of https://github.com/ACCLAB/DABEST-python into…
josesho Oct 2, 2019
66ad912
make full use of hypothetical figure
josesho Oct 2, 2019
37aa119
Merge pull request #76 from ACCLAB/master
josesho Oct 3, 2019
55e1f9c
fix some typos
josesho Oct 3, 2019
0b41df9
better handling of bootstrap plotting when infinities are present (#72)
josesho Oct 3, 2019
177f9df
version bump DOCS
josesho Oct 3, 2019
5587fca
update tutorial DOCS
josesho Oct 3, 2019
62b1527
add notes and contributors
josesho Oct 4, 2019
ddf0cd2
standardize references to DABEST
josesho Oct 4, 2019
d99055d
set tight_layout=True
josesho Oct 7, 2019
a8a953d
use pytest-mpl plugin for plot testing
josesho Oct 7, 2019
b0a8833
update testing description
josesho Oct 7, 2019
71aec35
update release notes
josesho Oct 7, 2019
b744f20
add pytest-mpl in extra_require
josesho Oct 7, 2019
2e3d329
update to pytest==5.2
josesho Oct 7, 2019
8accfd1
register mpl_image_compare marker
josesho Oct 7, 2019
c9f0f72
fix `extras_require`
josesho Oct 8, 2019
77e37be
reduce tolerance for inset plot comparison
josesho Oct 8, 2019
36f573e
misplaced the `tolerance` keyword!!!!
josesho Oct 8, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ install:
- conda config --add channels conda-forge
- conda create -n testenv --yes pip python=$PYTHON matplotlib
- source activate testenv
- pip install pytest==4.3
- pip install .
- pip install .[dev]


script: pytest dabest
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@


## Did you write a patch that fixes a bug?
- Open a new GitHub [pull request](https://help.github.com/en/articles/about-pull-requests)(PR for short) with the patch.
- Open a new GitHub [pull request](https://help.github.com/en/articles/about-pull-requests) (PR for short) with the patch.

- Create the PR into the development branch, which is indicated by `v{latest version number}_dev`.
- Create the PR into the development branch, which is indicated by `v{latest version number}-dev`.

- Clearly state the problem and solution in the PR description. Include the relevant [issue number](https://guides.github.com/features/issues/) if applicable.

Expand Down
18 changes: 6 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[![Free-to-view citation](https://zenodo.org/badge/DOI/10.1038/s41592-019-0470-3.svg)](https://rdcu.be/bHhJ4)
[![License](https://img.shields.io/badge/License-BSD%203--Clause--Clear-orange.svg)](https://spdx.org/licenses/BSD-3-Clause-Clear.html)


## About

DABEST is a package for **D**ata **A**nalysis using **B**ootstrap-Coupled **EST**imation.
Expand All @@ -22,21 +23,12 @@ An estimation plot has two key features.

DABEST powers [estimationstats.com](https://www.estimationstats.com/), allowing everyone access to high-quality estimation plots.

## Requirements

DABEST has been tested on Python 3.5, 3.6, and 3.7.

In addition, the following packages are also required:
- [numpy](https://www.numpy.org) (1.15)
- [scipy](https://www.scipy.org) (1.2)
- [matplotlib](https://www.matplotlib.org) (3.0)
- [seaborn](https://seaborn.pydata.org) (0.9)
- [pandas](https://pandas.pydata.org) (0.24).

To obtain these package dependencies easily, it is highly recommended to download the [Anaconda distribution](https://www.continuum.io/downloads) of Python.

## Installation

This package is tested on Python 3.5, 3.6, and 3.7.
It is highly recommended to download the [Anaconda distribution](https://www.continuum.io/downloads) of Python in order to obtain the dependencies easily.

You can install this package via `pip`.

To install, at the command line run
Expand All @@ -56,6 +48,7 @@ Then, navigate to the cloned repo in the command line and run
pip install .
```


## Usage

```python3
Expand Down Expand Up @@ -99,6 +92,7 @@ All contributions are welcome; please read the [Guidelines for contributing](htt

We also have a [Code of Conduct](https://github.com/ACCLAB/DABEST-python/blob/master/CODE_OF_CONDUCT.md) to foster an inclusive and productive space.


## Acknowledgements

We would like to thank alpha testers from the [Claridge-Chang lab](https://www.claridgechang.net/): [Sangyu Xu](https://github.com/sangyu), [Xianyuan Zhang](https://github.com/XYZfar), [Farhan Mohammad](https://github.com/farhan8igib), Jurga Mituzaitė, and Stanislav Ott.
Expand Down
2 changes: 1 addition & 1 deletion dabest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
from ._stats_tools import effsize as effsize
from ._classes import TwoGroupsEffectSize

__version__ = "0.2.5"
__version__ = "0.2.6"
40 changes: 36 additions & 4 deletions dabest/_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ def __init__(self, control, test, effect_size,
'statistic_wilcoxon': nan}
"""

from numpy import array, isnan
from numpy import array, isnan, isinf
from numpy import sort as npsort
from numpy.random import choice, seed

Expand Down Expand Up @@ -522,6 +522,20 @@ def __init__(self, control, test, effect_size,
control, test, is_paired, effect_size,
resamples, random_seed)
self.__bootstraps = npsort(bootstraps)

# Added in v0.2.6.
# Raises a UserWarning if there are any infiinities in the bootstraps.
num_infinities = len(self.__bootstraps[isinf(self.__bootstraps)])

if num_infinities > 0:
warn_msg = "There are {} bootstrap(s) that are not defined. "\
"This is likely due to smaple sample sizes. "\
"The values in a bootstrap for a group will be more likely "\
"to be all equal, with a resulting variance of zero. "\
"The computation of Cohen's d and Hedges' g thus "\
"involved a division by zero. "
warnings.warn(warn_msg.format(num_infinities),
category=UserWarning)

self.__bias_correction = ci2g.compute_meandiff_bias_correction(
self.__bootstraps, self.__difference)
Expand Down Expand Up @@ -1103,6 +1117,7 @@ def plot(self, color_col=None,

fig_size=None,
dpi=100,
ax=None,

swarmplot_kwargs=None,
violinplot_kwargs=None,
Expand All @@ -1112,6 +1127,7 @@ def plot(self, color_col=None,
legend_kwargs=None):
"""
Creates an estimation plot for the effect size of interest.


Parameters
----------
Expand Down Expand Up @@ -1176,6 +1192,9 @@ def plot(self, color_col=None,
The desired dimensions of the figure as a (length, width) tuple.
dpi : int, default 100
The dots per inch of the resulting figure.
ax : matplotlib.Axes, default None
Provide an existing Axes for the plots to be created. If no Axes is
specified, a new matplotlib Figure will be created.
swarmplot_kwargs : dict, default None
Pass any keyword arguments accepted by the seaborn `swarmplot`
command here, as a dict. If None, the following keywords are
Expand Down Expand Up @@ -1206,9 +1225,14 @@ def plot(self, color_col=None,

Returns
-------
A :class:`matplotlib.figure.Figure` with 2 Axes.

A :class:`matplotlib.figure.Figure` with 2 Axes, if ``ax = None``.
The first axes (accessible with ``FigName.axes[0]``) contains the rawdata swarmplot; the second axes (accessible with ``FigName.axes[1]``) has the bootstrap distributions and effect sizes (with confidence intervals) plotted on it.

If ``ax`` is specified, the rawdata swarmplot is accessed at ``ax``
itself, while the effect size axes is accessed at ``ax.contrast_axes``.
See the last example below.


Examples
--------
Expand Down Expand Up @@ -1244,6 +1268,14 @@ def plot(self, color_col=None,
... "Test 2", "Test 3")
... )
>>> fig6 = my_shared_control.mean_diff.plot()

Creating estimation plots in individual panels of a figure.

>>> f, axx = plt.subplots(nrows=2, ncols=2, figsize=(15, 15))
>>> my_data.mean_diff.plot(ax=axx.flat[0])
>>> my_data_paired.mean_diff.plot(ax=axx.flat[1])
>>> my_shared_control.mean_diff.plot(ax=axx.flat[2])
>>> my_shared_control.mean_diff.plot(ax=axx.flat[3], float_contrast=False)

"""

Expand Down Expand Up @@ -1344,4 +1376,4 @@ def dabest_obj(self):
Returns the `dabest` object that invoked the current EffectSizeDataFrame
class.
"""
return self.__dabest_obj
return self.__dabest_obj
19 changes: 18 additions & 1 deletion dabest/_stats_tools/confint_2group_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,24 @@ def compute_bootstrapped_diff(x0, x1, is_paired, effect_size,

# reset seed
np.random.seed()


# check whether there are any infinities in the bootstrap,
# which likely indicates the sample sizes are too small as
# the computation of Cohen's d and Hedges' g necessitated
# a division by zero.
# Added in v0.2.6.

# num_infinities = len(out[np.isinf(out)])
# print(num_infinities)
# if num_infinities > 0:
# warn_msg = "There are {} bootstraps that are not defined. "\
# "This is likely due to smaple sample sizes. "\
# "The values in a bootstrap for a group will be more likely "\
# "to be all equal, with a resulting variance of zero. "\
# "The computation of Cohen's d and Hedges' g will therefore "\
# "involved a division by zero. "
# warnings.warn(warn_msg.format(num_infinities), category="UserWarning")

return out


Expand Down
6 changes: 4 additions & 2 deletions dabest/_stats_tools/effsize.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,13 @@ def cohens_d(control, test, is_paired=False):
# assume the two arrays are ordered already.
delta = test - control
M = np.mean(delta)
return M / average_sd
divisor = average_sd

else:
M = np.mean(test) - np.mean(control)
return M / pooled_sd
divisor = pooled_sd

return M / divisor



Expand Down
98 changes: 74 additions & 24 deletions dabest/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):

fig_size=None,
dpi=100,
ax=None,

swarmplot_kwargs=None,
violinplot_kwargs=None,
Expand Down Expand Up @@ -254,28 +255,76 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):

# Initialise the figure.
# sns.set(context="talk", style='ticks')
init_fig_kwargs = dict(figsize=fig_size, dpi=plot_kwargs["dpi"])
init_fig_kwargs = dict(figsize=fig_size, dpi=plot_kwargs["dpi"],
tight_layout=True)

width_ratios_ga = [2.5, 1]
h_space_cummings = 0.3
if plot_kwargs["ax"] is not None:
# New in v0.2.6.
# Use inset axes to create the estimation plot inside a single axes.
# Author: Adam L Nekimken. (PR #73)
inset_contrast = True
rawdata_axes = plot_kwargs["ax"]
ax_position = rawdata_axes.get_position() # [[x0, y0], [x1, y1]]

fig = rawdata_axes.get_figure()

if float_contrast is True:
axins = rawdata_axes.inset_axes(
[1, 0,
width_ratios_ga[1]/width_ratios_ga[0], 1])
rawdata_axes.set_position( # [l, b, w, h]
[ax_position.x0,
ax_position.y0,
(ax_position.x1 - ax_position.x0) * (width_ratios_ga[0] /
sum(width_ratios_ga)),
(ax_position.y1 - ax_position.y0)])

contrast_axes = axins

# Here, we hardcode some figure parameters.
if float_contrast is True:
fig, axx = plt.subplots(ncols=2,
gridspec_kw={"width_ratios": [2.5, 1],
"wspace": 0},
**init_fig_kwargs)
else:
axins = rawdata_axes.inset_axes([0, -1 - h_space_cummings, 1, 1])
plot_height = ((ax_position.y1 - ax_position.y0) /
(2 + h_space_cummings))
rawdata_axes.set_position(
[ax_position.x0,
ax_position.y0 + (1 + h_space_cummings) * plot_height,
(ax_position.x1 - ax_position.x0),
plot_height])

# If the contrast axes are NOT floating, create lists to store
# raw ylims and raw tick intervals, so that I can normalize
# their ylims later.
contrast_ax_ylim_low = list()
contrast_ax_ylim_high = list()
contrast_ax_ylim_tickintervals = list()
contrast_axes = axins
rawdata_axes.contrast_axes = axins

else:
fig, axx = plt.subplots(nrows=2,
gridspec_kw={"hspace": 0.3},
**init_fig_kwargs)

# If the contrast axes are NOT floating, create lists to store raw ylims
# and raw tick intervals, so that I can normalize their ylims later.
contrast_ax_ylim_low = list()
contrast_ax_ylim_high = list()
contrast_ax_ylim_tickintervals = list()
inset_contrast = False
# Here, we hardcode some figure parameters.
if float_contrast is True:
fig, axx = plt.subplots(
ncols=2,
gridspec_kw={"width_ratios": width_ratios_ga,
"wspace": 0},
**init_fig_kwargs)

rawdata_axes = axx[0]
contrast_axes = axx[1]
else:
fig, axx = plt.subplots(nrows=2,
gridspec_kw={"hspace": 0.3},
**init_fig_kwargs)
# If the contrast axes are NOT floating, create lists to store
# raw ylims and raw tick intervals, so that I can normalize
# their ylims later.
contrast_ax_ylim_low = list()
contrast_ax_ylim_high = list()
contrast_ax_ylim_tickintervals = list()

rawdata_axes = axx[0]
contrast_axes = axx[1]

rawdata_axes.set_frame_on(False)
contrast_axes.set_frame_on(False)
Expand Down Expand Up @@ -423,7 +472,8 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):
current_ci_high = results.bca_high[j]

# Create the violinplot.
v = contrast_axes.violinplot(current_bootstrap,
# New in v0.2.6: drop negative infinities before plotting.
v = contrast_axes.violinplot(current_bootstrap[~np.isinf(current_bootstrap)],
positions=[tick],
**violinplot_kwargs)
# Turn the violinplot into half, and color it the same as the swarmplot.
Expand Down Expand Up @@ -651,19 +701,19 @@ def EffectSizeDataFramePlotter(EffectSizeDataFrame, **plot_kwargs):

# Compute the end of each x-axes line.
rightend_ticks = np.array([len(i)-1 for i in idx]) + np.array(ticks_to_skip)

for ax in fig.axes:
for ax in [rawdata_axes, contrast_axes]:
sns.despine(ax=ax, bottom=True)

ylim = ax.get_ylim()
xlim = ax.get_xlim()
redraw_axes_kwargs['y'] = ylim[0]

for k, start_tick in enumerate(ticks_to_skip):
end_tick = rightend_ticks[k]
ax.hlines(xmin=start_tick, xmax=end_tick,
**redraw_axes_kwargs)

ax.set_ylim(ylim)
del redraw_axes_kwargs['y']

Expand Down
7 changes: 6 additions & 1 deletion dabest/pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
[pytest]
filterwarnings =
ignore::UserWarning
ignore::DeprecationWarning
ignore::DeprecationWarning

addopts = --mpl --mpl-baseline-path=dabest/tests/baseline_images

markers =
mpl_image_compare: mark a test as implementing mpl image comparison.
3 changes: 1 addition & 2 deletions dabest/tests/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Testing

We use [pytest](https://docs.pytest.org/en/latest) to execute the tests. More documentation of the testing paradigm will be added in the near future.
We use [pytest](https://docs.pytest.org/en/latest) to execute the tests. For testing of plot generation, we use the [mpl plugin](https://github.com/matplotlib/pytest-mpl) for pytest. A range of different plots are created, and compared against the baseline images in the `baseline_images` subfolder.

To run the tests, go to the root of this repo directory and run

```shell
pytest dabest
```
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dabest/tests/baseline_images/test_18_desat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading