def plot(self, ax: matplotlib.axes.Axes): # individual points ax.scatter(self.mean, self.diff, s=20, alpha=0.6, color=self.color_points, **self.point_kws) # mean difference and SD lines ax.axhline(self.mean_diff, color=self.color_mean, linestyle='-') ax.axhline(self.mean_diff + self.loa_sd, color=self.color_loa, linestyle='--') ax.axhline(self.mean_diff - self.loa_sd, color=self.color_loa, linestyle='--') if self.reference: ax.axhline(0, color='grey', linestyle='-', alpha=0.4) # confidence intervals (if requested) if self.CI is not None: ax.axhspan(self.CI_mean[0], self.CI_mean[1], color=self.color_mean, alpha=0.2) ax.axhspan(self.CI_upper[0], self.CI_upper[1], color=self.color_loa, alpha=0.2) ax.axhspan(self.CI_lower[0], self.CI_lower[1], color=self.color_loa, alpha=0.2) # text in graph trans: matplotlib.transform = transforms.blended_transform_factory( ax.transAxes, ax.transData) offset: float = (((self.loa * self.sd_diff) * 2) / 100) * 1.2 ax.text(0.98, self.mean_diff + offset, 'Mean', ha="right", va="bottom", transform=trans) ax.text(0.98, self.mean_diff - offset, f'{self.mean_diff:.2f}', ha="right", va="top", transform=trans) ax.text(0.98, self.mean_diff + self.loa_sd + offset, f'+{self.loa:.2f} SD', ha="right", va="bottom", transform=trans) ax.text(0.98, self.mean_diff + self.loa_sd - offset, f'{self.mean_diff + self.loa_sd:.2f}', ha="right", va="top", transform=trans) ax.text(0.98, self.mean_diff - self.loa_sd - offset, f'-{self.loa:.2f} SD', ha="right", va="top", transform=trans) ax.text(0.98, self.mean_diff - self.loa_sd + offset, f'{self.mean_diff - self.loa_sd:.2f}', ha="right", va="bottom", transform=trans) # transform graphs ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) # set X and Y limits if self.xlim is not None: ax.set_xlim(self.xlim[0], self.xlim[1]) if self.ylim is not None: ax.set_ylim(self.ylim[0], self.ylim[1]) # graph labels ax.set_ylabel(self.y_title) ax.set_xlabel(self.x_title) if self.graph_title is not None: ax.set_title(self.graph_title)
def plot( self, x_label: str = "Mean of methods", y_label: str = "Difference between methods", graph_title: str = None, reference: bool = False, xlim: Tuple = None, ylim: Tuple = None, color_mean: str = "#008bff", color_loa: str = "#FF7000", color_points: str = "#000000", point_kws: Dict = None, ci_alpha: float = 0.2, loa_linestyle: str = "--", ax: matplotlib.axes.Axes = None, ): """Provide a method comparison using Bland-Altman plotting. This is an Axis-level function which will draw the Bland-Altman plot onto the current active Axis object unless ``ax`` is provided. Parameters ---------- x_label : str, optional The label which is added to the X-axis. If None is provided, a standard label will be added. y_label : str, optional The label which is added to the Y-axis. If None is provided, a standard label will be added. graph_title : str, optional Title of the Bland-Altman plot. If None is provided, no title will be plotted. reference : bool, optional If True, a grey reference line at y=0 will be plotted in the Bland-Altman. xlim : list, optional Minimum and maximum limits for X-axis. Should be provided as list or tuple. If not set, matplotlib will decide its own bounds. ylim : list, optional Minimum and maximum limits for Y-axis. Should be provided as list or tuple. If not set, matplotlib will decide its own bounds. color_mean : str, optional Color of the mean difference line that will be plotted. color_loa : str, optional Color of the limit of agreement lines that will be plotted. color_points : str, optional Color of the individual differences that will be plotted. point_kws : dict of key, value mappings, optional Additional keyword arguments for `plt.scatter`. ci_alpha: float, optional Alpha value of the confidence interval. loa_linestyle: str, optional Linestyle of the limit of agreement lines. ax : matplotlib Axes, optional Axes in which to draw the plot, otherwise use the currently-active Axes. Returns ------- ax : matplotlib Axes Axes object with the Bland-Altman plot. """ ax = ax or plt.gca() pkws = self.DEFAULT_POINTS_KWS.copy() pkws.update(point_kws or {}) # Get parameters mean, mean_CI = self.result["mean"], self.result["mean_CI"] loa_upper, loa_upper_CI = self.result["loa_upper"], self.result[ "loa_upper_CI"] loa_lower, loa_lower_CI = self.result["loa_lower"], self.result[ "loa_lower_CI"] sd_diff = self.result["sd_diff"] # individual points ax.scatter(self.mean, self.diff, **pkws) # mean difference and SD lines ax.axhline(mean, color=color_mean, linestyle=loa_linestyle) ax.axhline(loa_upper, color=color_loa, linestyle=loa_linestyle) ax.axhline(loa_lower, color=color_loa, linestyle=loa_linestyle) if reference: ax.axhline(0, color="grey", linestyle="-", alpha=0.4) # confidence intervals (if requested) if self.CI is not None: ax.axhspan(*mean_CI, color=color_mean, alpha=ci_alpha) ax.axhspan(*loa_upper_CI, color=color_loa, alpha=ci_alpha) ax.axhspan(*loa_lower_CI, color=color_loa, alpha=ci_alpha) # text in graph trans: matplotlib.transform = transforms.blended_transform_factory( ax.transAxes, ax.transData) offset: float = (((self.loa * sd_diff) * 2) / 100) * 1.2 ax.text( 0.98, mean + offset, "Mean", ha="right", va="bottom", transform=trans, ) ax.text( 0.98, mean - offset, f"{mean:.2f}", ha="right", va="top", transform=trans, ) ax.text( 0.98, loa_upper + offset, f"+{self.loa:.2f} SD", ha="right", va="bottom", transform=trans, ) ax.text( 0.98, loa_upper - offset, f"{loa_upper:.2f}", ha="right", va="top", transform=trans, ) ax.text( 0.98, loa_lower - offset, f"-{self.loa:.2f} SD", ha="right", va="top", transform=trans, ) ax.text( 0.98, loa_lower + offset, f"{loa_lower:.2f}", ha="right", va="bottom", transform=trans, ) # transform graphs ax.spines["right"].set_visible(False) ax.spines["top"].set_visible(False) # set X and Y limits if xlim is not None: ax.set_xlim(xlim[0], xlim[1]) if ylim is not None: ax.set_ylim(ylim[0], ylim[1]) # graph labels ax.set(xlabel=x_label, ylabel=y_label, title=graph_title) return ax