Source code for WORC.plotting.plot_boxplot_performance

#!/usr/bin/env python

# Copyright 2016-2020 Biomedical Imaging Group Rotterdam, Departments of
# Medical Informatics and Radiology, Erasmus MC, Rotterdam, The Netherlands
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import numpy as np
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
import tikzplotlib


[docs]def generate_performance_boxplots(performances, metrics, outputfolder, colors=None): """Generate boxplots for performance of various models.""" if colors is None: colors = list() for p in performances: colors.append(np.random.rand(3,)) linecolor = [0.1, 0.1, 0.1] nperf = len(performances) f = plt.figure(figsize=(nperf*2.5, nperf)) ax = plt.subplot(1,1,1) # Define the middle label position if np.mod(nperf, 2) == 0: # Even, pick a middle position middle = None else: middle = (nperf - 1) / 2.0 xdist = 0 markersize = 0.3 xmaindelta = nperf / 2.5 xdelta = 1.5 / nperf y_all = list() linepositions = list() labelpositions = list() labelnames = list() for m in metrics: xdist += xmaindelta if middle is None: labelpositions.append(xdist + nperf / 2.0 * xdelta - xdelta / 2.0) labelnames.append('\n' + m) for pnum, p in enumerate(performances): y = p[m] x = xdist + xdelta*pnum color = colors[pnum] ax.scatter([x] * len(y), y, color=color, s=markersize) y_all.append(y) color = [color[0], color[1], color[2], 0.4] facecolor = [color[0], color[1], color[2], 0.2] plt.boxplot(y, positions=[x], widths=xdelta*0.75, patch_artist=True, boxprops=dict(facecolor=facecolor, color=color), capprops=dict(color=color), whiskerprops=dict(color=color), flierprops=dict(color=color, markeredgecolor=color), medianprops=dict(color=color)) labelpositions.append(x) if middle is not None: if pnum == middle: labelnames.append(str(pnum + 1) + '\n' + m) continue labelnames.append(str(pnum + 1)) linepositions.append((x + xdist + xmaindelta)/2.0) # Draw vertical lines for x in linepositions[0:-1]: ax.axvline(x=x, linestyle='dashed', color=linecolor, linewidth=0.5) # Put in the labels / xticks plt.xticks(labelpositions, labelnames) # Changes all colors of the axes for axis in ['top', 'bottom', 'left', 'right']: ax.spines[axis].set_linewidth(0.5) ax.spines[axis].set_color(linecolor) ax.tick_params(axis='x', colors=linecolor) ax.tick_params(axis='y', colors=linecolor) ax.yaxis.label.set_color(linecolor) ax.xaxis.label.set_color(linecolor) # High DTI to make sure we save the maximized image fname = 'boxplot_test.png' outputname_png = os.path.join(outputfolder, fname) plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0) f.savefig(outputname_png, dpi=600, bbox_inches='tight', pad_inches=0) print(("Boxplot saved as {} !").format(outputname_png)) fname = 'boxplot_test.tex' outputname_tex = os.path.join(outputfolder, fname) tikzplotlib.save(outputname_tex)
[docs]def test(): """Test functionality with synthetic data.""" perf1 = dict() perf1['AUC'] = np.random.randint(low=50, high=100, size=100) / 100.0 perf1['Accuracy'] = np.random.randint(low=50, high=100, size=100) / 100.0 perf1['Sensitivity'] = np.random.randint(low=70, high=90, size=100) / 100.0 perf1['Specificity'] = np.random.randint(low=70, high=90, size=100) / 100.0 perf2 = dict() perf2['AUC'] = np.random.randint(low=75, high=100, size=100) / 100.0 perf2['Accuracy'] = np.random.randint(low=75, high=100, size=100) / 100.0 perf2['Sensitivity'] = np.random.randint(low=80, high=100, size=100) / 100.0 perf2['Specificity'] = np.random.randint(low=80, high=100, size=100) / 100.0 perf3 = dict() perf3['AUC'] = np.random.randint(low=50, high=75, size=100) / 100.0 perf3['Accuracy'] = np.random.randint(low=50, high=75, size=100) / 100.0 perf3['Sensitivity'] = np.random.randint(low=60, high=80, size=100) / 100.0 perf3['Specificity'] = np.random.randint(low=60, high=80, size=100) / 100.0 perf4 = dict() perf4['AUC'] = np.random.randint(low=50, high=75, size=100) / 100.0 perf4['Accuracy'] = np.random.randint(low=50, high=75, size=100) / 100.0 perf4['Sensitivity'] = np.random.randint(low=60, high=80, size=100) / 100.0 perf4['Specificity'] = np.random.randint(low=60, high=80, size=100) / 100.0 perf5 = dict() perf5['AUC'] = np.random.randint(low=50, high=75, size=100) / 100.0 perf5['Accuracy'] = np.random.randint(low=50, high=75, size=100) / 100.0 perf5['Sensitivity'] = np.random.randint(low=60, high=80, size=100) / 100.0 perf5['Specificity'] = np.random.randint(low=60, high=80, size=100) / 100.0 performances = [perf1, perf2, perf3, perf4] metrics = list(perf1.keys()) out = os.getcwd() colors = [[0.5, 0, 0], [0, 0.5, 0], [0, 0, 0.5], [0, 0.5, 0.5], [0.5, 0, 0.5]] generate_performance_boxplots(performances, metrics, out, colors)
if __name__ == '__main__': test()