|
| 1 | +""" |
| 2 | +========================= |
| 3 | +Combining Transformations |
| 4 | +========================= |
| 5 | +
|
| 6 | +This example showcases how to combine transformations, including Affine |
| 7 | +and blended transformations. |
| 8 | +
|
| 9 | +Some time data is plotted on axes that have significant disparity |
| 10 | +between the x- and y-scales. To place circular markers on some events |
| 11 | +that scale in the y-direction proprtionally to the data, while |
| 12 | +remaining perfectly circular in display space, we blend a reflected |
| 13 | +version of the y-data transform into the x axis. |
| 14 | +
|
| 15 | +As a secondary item, this example shows how to work with datetimes |
| 16 | +along one axis when constructing patches such as rectangles. |
| 17 | +""" |
| 18 | + |
| 19 | +fromdatetimeimportdatetime |
| 20 | +frommatplotlibimport ( |
| 21 | +datesasmdate, |
| 22 | +patchesasmpatch, |
| 23 | +pyplotasplt, |
| 24 | +transformsasmtrans |
| 25 | +) |
| 26 | +importnumpyasnp |
| 27 | + |
| 28 | +data= { |
| 29 | +"A": [datetime(2024,4,10,3,10,22), |
| 30 | +datetime(2024,4,10,3,21,13), |
| 31 | +datetime(2024,4,10,3,25,41)], |
| 32 | +"B": [datetime(2024,4,10,3,15,55), |
| 33 | +datetime(2024,4,10,3,40,8)], |
| 34 | +"C": [datetime(2024,4,10,3,12,18), |
| 35 | +datetime(2024,4,10,3,23,32), |
| 36 | +datetime(2024,4,10,3,32,12)], |
| 37 | +} |
| 38 | + |
| 39 | +fig,ax=plt.subplots(constrained_layout=True) |
| 40 | +ax.invert_yaxis() |
| 41 | + |
| 42 | +# Some of the transforms only need to be set up once |
| 43 | +vertical_scale_transform=mtrans.AffineDeltaTransform(ax.transData) |
| 44 | +reflection=mtrans.Affine2D.from_values(0,1,1,0,0,0) |
| 45 | +uniform_scale_transform=mtrans.blended_transform_factory( |
| 46 | +reflection+vertical_scale_transform+reflection,vertical_scale_transform) |
| 47 | + |
| 48 | +# Draw some rectangle spanning each dataset |
| 49 | +fori,datesinenumerate(data.values()): |
| 50 | +start=mdate.date2num(dates[0]) |
| 51 | +end=mdate.date2num(dates[-1]) |
| 52 | +width=end-start |
| 53 | +color=ax._get_lines.get_next_color() |
| 54 | +ax.add_patch(mpatch.Rectangle((start,i-0.4),width,0.8,color=color)) |
| 55 | + |
| 56 | +# Draw a circle at each event |
| 57 | +foreventindates: |
| 58 | +x=mdate.date2num(event) |
| 59 | +ax.add_patch(mpatch.Circle((0,0),0.2,facecolor="w",edgecolor="k",linewidth=2, |
| 60 | +transform=uniform_scale_transform+mtrans.ScaledTranslation(x,i,ax.transData))) |
| 61 | + |
| 62 | +# Set the y-axis to show the data labels |
| 63 | +ax.set_yticks(np.arange(len(data))) |
| 64 | +ax.set_yticklabels(list(data)) |
| 65 | + |
| 66 | +# Set the x-axis to display datetimes |
| 67 | +ax.xaxis.set_major_locator(locator:=mdate.AutoDateLocator()) |
| 68 | +ax.xaxis.set_major_formatter(mdate.AutoDateFormatter(locator)) |
| 69 | + |
| 70 | +ax.autoscale_view() |
| 71 | + |
| 72 | +plt.show() |