diff --git a/README.md b/README.md index 6e8d838..da3fbaf 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,12 @@ Some details: ### Creating plots, running analysis -- Use `./funk plot test_name` to run a plot, or `./funk plot --all` to run all plots -- Use `./funk analyse test_name` to check if a test passed or failed, or `./funk analyse --all` to check all tests +- Use `./funk plot test_name` to run a plot, or `./funk plot --all` to run all plots. +- Use `./funk analyse test_name` to check if a test passed or failed, or `./funk analyse --all` to check all tests. ### Installing -- Functional testing requires Python 3.4 or later -- When cloning, make sure to add the `--recursive` switch +- Functional testing requires Python 3.4 or later. +- When cloning, make sure to add the `--recursive` switch; `git reset --hard` within each submodule might be needed to get it working. - To install, use `python3 -m pip install -r requirements.txt`. This makes sure you have all the dependencies you know. diff --git a/pfunk/plot.py b/pfunk/plot.py index 5333d83..928b03b 100644 --- a/pfunk/plot.py +++ b/pfunk/plot.py @@ -17,6 +17,76 @@ import pfunk +def histogram(results, variable, title, xlabel, threshold=None): + """ + Creates and returns a histogram plot for a variable (over commits). + """ + fig = plt.figure(figsize=(11, 4.5)) + plt.suptitle(title + ' : ' + pfunk.date()) + + # Left plot: Variable per commit for all data as 1 histogram + plt.subplot(1, 2, 1) + fig.autofmt_xdate() + x, y, u, m, s = pfunk.gather_statistics_per_commit(results, variable) + if len(x) == 0: + plt.text(0.5, 0.5, 'No data') + else: + y = np.asarray(y) + last_commit = [i for i, k in enumerate(x) if k == u[-1]] + mask_lc = np.ones(y.shape, dtype=bool) + mask_lc[last_commit] = False + + n, _, _ = plt.hist(y[mask_lc], bins='auto', color='#607c8e', alpha=0.7, + label='All %s commits' % len(u)) + + if len(last_commit) > 25: + plt.hist(y[last_commit], bins='auto', color='#0504aa', alpha=0.5, + label='Last commit') + else: + stem_height = [np.max(n)] * len(last_commit) + ml, sl, bl = plt.stem(y[last_commit], stem_height, + label='Last commit') + plt.setp(ml, color='#0504aa', alpha=0.5) + plt.setp(sl, color='#0504aa', alpha=0.5) + plt.setp(bl, visible=False) + plt.ylabel('Frequency (total %s runs)' % len(y)) + plt.xlabel(xlabel) + plt.legend() + + # Right plot: Same, to most recent data. + plt.subplot(1, 2, 2) + n_commits = 12 + fig.autofmt_xdate() + x, y, u, m, s = pfunk.gather_statistics_per_commit(results, variable, + n=n_commits) + if len(x) == 0: + plt.text(0.5, 0.5, 'No data') + else: + y = np.asarray(y) + last_commit = [i for i, k in enumerate(x) if k == u[-1]] + mask_lc = np.ones(y.shape, dtype=bool) + mask_lc[last_commit] = False + + n, _, _ = plt.hist(y[mask_lc], bins='auto', color='#607c8e', alpha=0.7, + label='Last %s commits' % n_commits) + + if len(last_commit) > 10: + plt.hist(y[last_commit], bins='auto', color='#0504aa', alpha=0.5, + label='Last commit') + else: + stem_height = [np.max(n)] * len(last_commit) + ml, sl, bl = plt.stem(y[last_commit], stem_height, + label='Last commit') + plt.setp(ml, color='#0504aa', alpha=0.5) + plt.setp(sl, color='#0504aa', alpha=0.5) + plt.setp(bl, visible=False) + plt.ylabel('Frequency (total %s runs)' % len(y)) + plt.xlabel(xlabel) + plt.legend() + + return fig + + def variable(results, variable, title, ylabel, threshold=None): """ Creates and returns a default plot for a variable vs commits. diff --git a/pfunk/tests/mcmc_banana.py b/pfunk/tests/mcmc_banana.py index 2fddc11..fc0661b 100644 --- a/pfunk/tests/mcmc_banana.py +++ b/pfunk/tests/mcmc_banana.py @@ -157,6 +157,14 @@ def _plot(self, results): 'Kullback-Leibler divergence', 3 * self._pass_threshold) ) + # Figure: KL histogram + figs.append(pfunk.plot.histogram( + results, + 'kld', + 'Banana w. ' + self._method, + 'Kullback-Leibler divergence') + ) + # Figure: KL over time figs.append(pfunk.plot.convergence( results, @@ -176,4 +184,12 @@ def _plot(self, results): 'Effective sample size') ) + # Figure: ESS histogram + figs.append(pfunk.plot.histogram( + results, + 'ess', + 'Banana w. ' + self._method, + 'Effective sample size') + ) + return figs