File indexing completed on 2026-10-26 08:47:14
0001 import numpy as np
0002 import matplotlib.pyplot as plt
0003 from enum import IntEnum
0004 import os
0005 from matplotlib.gridspec import GridSpec
0006 from matplotlib.lines import Line2D
0007
0008
0009 def plotAlignImpacts(
0010 labels,
0011 centralValues,
0012 sigmas,
0013 formatDicts,
0014 fname="align_impacts",
0015 title=None,
0016 xLim=None,
0017 ):
0018 """
0019 "Impacts plot" style comparison of the alignment corrections.
0020
0021 Each row of the Y axis is a parameter (layer, coordinate).
0022 The X axis is the correction in mm,
0023 centred at zero.
0024
0025 Parameters
0026 ----------
0027 labels: 1D array of parameter labels - defines the number nLabels of vertical entries
0028 centralValues: 2D array of shape (nSeries, nLabels) - central parameter values for each series
0029 sigmas: 2D array of shape (nSeries, nLabels) - parameter uncertainty values for each series
0030 formatDicts: 1D list of dicts, length nSeries - format and label settings for each series
0031 fname: file name to save the plot
0032 title: a title to plot
0033 xLim: an x-axis range limit
0034
0035 Sign convention: the correction is drawn exactly as the fits return it.
0036 If truth is the INJECTED displacement, the expected correction is its
0037 opposite; pass -truth if you want to superimpose them.
0038 """
0039 nParams = labels.shape[0]
0040 nSeries = len(formatDicts)
0041 assert centralValues.shape[0] == nSeries
0042 assert centralValues.shape[1] == nParams
0043 assert sigmas.shape[1] == nParams
0044 assert sigmas.shape[1] == nParams
0045
0046
0047 height = max(4.5, 0.34 * nParams + 1.4)
0048 fig, ax = plt.subplots(figsize=(7.5, height))
0049
0050
0051 yPos = np.asarray(range(nParams), int) + 1
0052 ax.axvline(0.0, color="k", lw=1.1, zorder=2)
0053 offsetY = 0.3 / nSeries
0054 offsetSteps = nSeries - 1
0055 offsetStep = offsetSteps / 2
0056 for thing in range(nSeries):
0057 yPositions = yPos - offsetStep * offsetY
0058 means = centralValues[thing, :]
0059 errors = sigmas[thing, :]
0060 format = formatDicts[thing]
0061 hasErrs = np.count_nonzero(errors)
0062 if not hasErrs:
0063 ax.plot(means, yPositions, **format)
0064 else:
0065 ax.errorbar(means, yPositions, xerr=errors, **format)
0066 offsetStep -= 1
0067
0068
0069 ax.set_yticks(yPos)
0070 ax.set_yticklabels(labels, fontsize=9)
0071 ax.set_ylim(yPos[-1] + 0.6, yPos[0] - 0.6)
0072 ax.set_xlabel("alignment correction [mm]")
0073 ax.grid(axis="x", ls=":", color="0.8", zorder=0)
0074 ax.set_axisbelow(True)
0075
0076 if xLim is not None:
0077 ax.set_xlim(*xLim)
0078
0079 if title:
0080 ax.set_title(title, fontsize=11)
0081
0082 ax.legend(loc="upper left", fontsize=8, framealpha=0.95)
0083
0084 fig.tight_layout()
0085 fig.savefig(fname + ".png", dpi=150, bbox_inches="tight")
0086 fig.savefig(fname + ".pdf", bbox_inches="tight")
0087 return fig, ax
0088
0089
0090 if __name__ == "__main__":
0091
0092 labels = np.array([1, 2, 3, 4], int)
0093 centralValues = np.zeros(dtype=float, shape=(3, len(labels)))
0094 sigmas = np.zeros(dtype=float, shape=(3, len(labels)))
0095 centralValues[0] = [-0.11, 0.1, 0.0, 0.09]
0096 centralValues[1] = [-0.12, 0.08, 0.0, 0.11]
0097 centralValues[2] = [-0.1, 0.1, 0.0, 0.1]
0098 sigmas[0] = [0.015, 0.015, 0.015, 0.015]
0099 sigmas[1] = [0.015, 0.015, 0.015, 0.015]
0100 formatDicts = [
0101 {"label": "Series 1", "fmt": "o", "color": "k", "markersize": 5},
0102 {"label": "Series 2", "fmt": "o", "color": "blue", "markersize": 5},
0103 {
0104 "label": "Truth",
0105 "marker": "s",
0106 "markeredgecolor": "#f31d1d",
0107 "markerfacecolor": "none",
0108 "linestyle": "none",
0109 "markersize": 11,
0110 "markeredgewidth": 1.6,
0111 },
0112 ]
0113
0114 plotAlignImpacts(
0115 labels,
0116 centralValues,
0117 sigmas,
0118 formatDicts,
0119 fname="testImpacts",
0120 title=None,
0121 xLim=None,
0122 )