diff --git a/makeGraph.py b/makeGraph.py index c0085e1..79b1c8d 100644 --- a/makeGraph.py +++ b/makeGraph.py @@ -16,6 +16,7 @@ import matplotlib.colors as colors from mpl_toolkits.axes_grid1 import make_axes_locatable from cycler import cycler from tqdm import tqdm +from collections import UserString # Define the UQ Colours UQ_COLOURS_DICT = { @@ -39,12 +40,17 @@ UQ_COLOURS_DICT = { # Define a colour object that can do neat conversions & things, by default stores as hex value -class ColourValue(str): - def __new__(self, name, value): +class ColourValue(UserString): + def __init__(self, name, value): self.name = name self.value = colors.to_hex(value, True) + super().__init__(self.value) - return super().__new__(self, self.value) + #def __new__(self, name, value): + # self.name = name + # self.value = colors.to_hex(value, True) + # + # return super().__new__(self, self.value) def __str__(self) -> str: return self.value @@ -95,7 +101,7 @@ UQ_COLOURS = ColourList(UQ_COLOURS_DICT) # Load UQ Colours into MatPlotLib # UQ colours are prefaced with 'uq:', so UQ red is 'uq:red' # Note: Any names That have a _ also have a version with spaces so both "uq:light_purple" and "uq:light purple" work -uq_colour_mapping = {'uq:' + name: value for name, value in list(UQ_COLOURS.items()) + [(x[0].replace("_", " "), x[1]) for x in UQ_COLOURS.items() if "_" in x[0]]} +uq_colour_mapping = {'uq:' + name: str(value) for name, value in list(UQ_COLOURS.items()) + [(x[0].replace("_", " "), x[1]) for x in UQ_COLOURS.items() if "_" in x[0]]} colors.get_named_colors_mapping().update( uq_colour_mapping ) ## UQ Colour Cycler @@ -117,17 +123,17 @@ colors.get_named_colors_mapping().update( uq_colour_mapping ) # Build a colour cycler uq_colour_cycler = cycler(color=[ - UQ_COLOURS["purple"], #51247A -> C00 -> uq:purple - UQ_COLOURS["blue"], #4085C6 -> C01 -> uq:blue - UQ_COLOURS["green"], #2EA836 -> C02 -> uq:green - UQ_COLOURS["red"], #E62645 -> C03 -> uq:red - UQ_COLOURS["light_purple"], #962A8B -> C04 -> uq:light_purple - UQ_COLOURS["dark_grey"], #999490 -> C05 -> uq:dark_grey - UQ_COLOURS["orange"], #EB602B -> C06 -> uq:orange - UQ_COLOURS["yellow"], #FBB800 -> C07 -> uq:yellow - UQ_COLOURS["aqua"], #00A2C7 -> C08 -> uq:aqua - UQ_COLOURS["gold"], #BB9D65 -> C09 -> uq:gold - UQ_COLOURS["neutral"] #D7D1CC -> C10 -> uq:neutral + UQ_COLOURS["purple"].data, #51247A -> C00 -> uq:purple + UQ_COLOURS["blue"].data, #4085C6 -> C01 -> uq:blue + UQ_COLOURS["green"].data, #2EA836 -> C02 -> uq:green + UQ_COLOURS["red"].data, #E62645 -> C03 -> uq:red + UQ_COLOURS["light_purple"].data, #962A8B -> C04 -> uq:light_purple + UQ_COLOURS["dark_grey"].data, #999490 -> C05 -> uq:dark_grey + UQ_COLOURS["orange"].data, #EB602B -> C06 -> uq:orange + UQ_COLOURS["yellow"].data, #FBB800 -> C07 -> uq:yellow + UQ_COLOURS["aqua"].data, #00A2C7 -> C08 -> uq:aqua + UQ_COLOURS["gold"].data, #BB9D65 -> C09 -> uq:gold + UQ_COLOURS["neutral"].data #D7D1CC -> C10 -> uq:neutral ]) # Tell MatPlotLib to use said cycler @@ -301,23 +307,24 @@ def makeGraph(graphData, showPlot=True, doProgramBlock=True, figSavePath=None, h if "type" not in pData or pData["type"] == "plot": currentLine = ax.plot(xData, yData, label=getSafeValue("label"), color=getSafeColour, **optArgs) + currentLine = currentLine[0] currentLineColour = currentLine.get_color() if "maxPoint" in pData: - labelText = pData["maxPoint"] if type(pData["maxPoint"]) == str else "Maximum Point ({0:.2f})" + labelText = pData["maxPoint"] if type(pData["maxPoint"]) == str else "Maximum Point ({y:.2f})" x, y = np.array(xData), np.array(yData) - maxPoint = np.max(x), y[np.argmax(x)] + maxPoint = x[np.argmax(y)], np.max(y) ax.scatter(maxPoint[0], maxPoint[1], - marker=getSafeValue("maxMarker", "o"), label=labelText.format(*maxPoint), + marker=getSafeValue("maxMarker", "o"), label=labelText.format(*maxPoint, x=maxPoint[0], y=maxPoint[1]), color=currentLineColour, zorder=getSafeValue("maxZorder", 2)) if "minPoint" in pData: - labelText = pData["minPoint"] if type(pData["minPoint"]) == str else "Minimum Point ({0:.2f})" + labelText = pData["minPoint"] if type(pData["minPoint"]) == str else "Minimum Point ({1:.2f})" x, y = np.array(xData), np.array(yData) - minPoint = np.min(x), y[np.argmin(x)] + minPoint = x[np.argmin(y)], np.min(y) ax.scatter(minPoint[0], minPoint[1], marker=getSafeValue("minMarker", "*" if "maxPoint" in pData else "o"), - label=labelText.format(*minPoint), color=currentLineColour, + label=labelText.format(*minPoint, x=minPoint[0], y=minPoint[1]), color=currentLineColour, zorder=getSafeValue("minxZorder", 2)) @@ -407,15 +414,18 @@ def makeGraph(graphData, showPlot=True, doProgramBlock=True, figSavePath=None, h additional_legends.append(pData["line"]) if "fillAlpha" in pData or ("fill" in pData and ("type" not in pData or pData["type"] in ["plot"])): - currentLine = ax.get_lines()[-1] if currentLine is None else currentLine - - line_colour = colors.to_rgba(currentLine.get_color()) - - fillData = pData["fill"] if type(pData["fill"]) == dict and "fill" in pData else {} - if "fillAlpha" not in fillData: fillData["fillAlpha"] = pData["fillAlpha"] if "fillAlpha" in pData else 0.07 - line_colour = (line_colour[0], line_colour[1], line_colour[2], fillData["fillAlpha"]) + currentLine = ax.get_lines()[-1] if currentLine is None else currentLine - if "color" not in fillData: fillData["color"] = line_colour + fillData = pData["fill"] if type(pData["fill"]) == dict and "fill" in pData else {} + + if "color" not in fillData: + line_colour = colors.to_rgba(currentLine.get_color()) + + if "fillAlpha" not in fillData: fillData["fillAlpha"] = pData["fillAlpha"] if "fillAlpha" in pData else 0.07 + line_colour = (line_colour[0], line_colour[1], line_colour[2], fillData["fillAlpha"]) + + fillData["color"] = line_colour + if "y2" not in fillData: fillData["y2"] = 0 if "where" not in fillData: fillData["where"] = None if "interpolate" not in fillData: fillData["interpolate"] = False @@ -473,7 +483,7 @@ def makeGraph(graphData, showPlot=True, doProgramBlock=True, figSavePath=None, h yTicks = matplotlib.ticker.FuncFormatter(formatter) ax.yaxis.set_major_formatter(yTicks) - if "plots" in axGraphData and bool(sum([("label" in pData) for pData in axGraphData["plots"]])): + if "plots" in axGraphData and bool(sum([("label" in pData) for pData in axGraphData["plots"]])) and not ("noLedg" in axGraphData and axGraphData["noLedg"]) : locPoint = axGraphData["ledgLoc"] if "ledgLoc" in axGraphData else None add_lines, add_labels = additional_legends, [line.get_label() for line in additional_legends] lines1, labels1 = ax1.get_legend_handles_labels() @@ -544,13 +554,20 @@ if __name__ == '__main__': for i in range(4): newPlot = { "title": f"Graph {i+1}", + "noLedg": i % 2 == 0, "plots": [ {"x":[0,1,2,3,4], "y":[0,1,2,3,4], "label":"Linear"}, {"x":[0,1,2,3,4], "y":[5,5,5,5,5]}, {"x":[4,3,2,1,0], "y":[4,3,2,1,0], "label":"Linear2"}, {"x":0, "type":"axvLine", "label":"Red Vertical Line", "color":"uq:red"}, {"y":6, "type":"axhLine", "label":"Dashed Horizontal Line", "args":{"linestyle":"--"}}, - {"type":"point", "x":4, "y":4, "label":"A Random Point", "colour":"uq:purple"} + {"type":"point", "x":4, "y":4, "label":"A Random Point", "colour":"uq:purple"}, + { + "x":np.arange(0, 4, 0.1), "y": 3*np.sin(np.arange(0, 4, 0.1)), + "colour":"uq:dark_grey", "maxPoint": True, + "minPoint": "Custom Min {x:.1f}, {y:.1f}", + "fill": {"color": UQ_COLOURS["green"].alpha_adj(0.07)} + } ] } graphData["subPlots"].append(newPlot)