Back to Blog
(I had to adjust some parameters here, of course) Solution 3 Texts.append(plt.text(x, y, y, horizontalalignment='center', color='b'))Īdjust_text(texts, add_objects=bars, autoalign='y', expand_objects=(0.1, 1), I think it's probably significantly slower that the accepted answer (it slows down considerably with a lot of bars), but much more general and configurable. Plt.ylim(0,max(text_positions)+2*txt_height)Īx.text(x - txt_width, 1.01*y, '%d'%int(y),rotation=0)Īnother option using my library adjustText, written specially for this purpose ( ). Text_plotter(x_data, y_data, text_positions, ax2, txt_width, txt_height) Text_positions = get_text_positions(x_data, y_data, txt_width, txt_height) #Get the corrected text positions, then write the text. Here is the code producing these plots, showing the usage: #random test data: Head_width=txt_width, head_length=txt_height*0.5, Text_positions = sorted_ltp + txt_heightĭef text_plotter(x_data, y_data, text_positions, axis,txt_width,txt_height):įor x,y,t in zip(x_data, y_data, text_positions):Īxis.text(x - txt_width, 1.01*t, '%d'%int(y),rotation=0, color='blue')Īxis.arrow(x, t,0,y-t, color='red',alpha=0.3, width=txt_width*0.1, Local_text_positions = > (y - txt_height)Īnd (abs(i - x) txt_height * 2: #if True then room to fit a word inĪ = (sorted_ltp + txt_height, a) It also puts in nice arrows.įor a fairly extreme example, it will produce this (none of the numbers overlap):ĭef get_text_positions(x_data, y_data, txt_width, txt_height): If there is a collision it changes its position to the next available collision free place. """Add a sloped annotation to *line* at position *x* with *text*I've written a quick solution, which checks each annotation position against default bounding boxes for all the other annotations. Xytext = Affine2D().rotate_deg(self.get_rotation()).transform(self.xytext)ĭef line_annotate(text, line, x, *args, **kwargs): """Updates relative position of annotation text """Determines angle of the slope of the neighbours in display coordinate systemĭx, dy = np.diff(ansform(self.neighbours), axis=0).squeeze() Super()._init_(text, (x, y), xytext=xytext, textcoords=textcoords, **kwargs) # Calculate y by interpolating neighbouring points Self.neighbours = n1, n2 = neighbours(x, xs, ys) Return neighbours(x, xs, ys, try_invert=False) # Determine points of line immediately to the left and right of xĭef neighbours(x, xs, ys, try_invert=True): ), "*textcoords* must be 'offset points' or 'offset pixels'" The coordinate system is determined by *textcoords*.Īdditional keyword arguments are passed on to `Annotation`. The position *(x, y)* relative to the point *x* on the *line* to place the y is calculated from the points on the line. Graph at a relative position *xytext* above it (perpendicularly above).Īn arrow pointing from the text to the annotated point *xy* can """Annotate the point at *x* of the graph *line* with text *text*.īy default, the text is displayed with the same rotation as the slope of the Self, text, line, x, xytext=(0, 5), textcoords="offset points", **kwargs Optionally an arrow pointing from the text to the graph at *x* can be drawn.Īx.add_artist(LineAnnotation("text", line, 1.5)) """A sloped annotation to *line* at position *x* with *text* import numpy as npįrom ansforms import Affine2D I originally put it into a public gist, but asked me to include it here. accepts a relative offset perpendicular to the slope.works with re-layouting and resizing, and.I reworked it into a class LineAnnotation and helper line_annotate such that it Even though this question is old, I keep coming across it and get frustrated, that it does not quite work.
0 Comments
Read More
Leave a Reply. |