|
| 1 | +.. _axislines-manual: |
| 2 | + |
| 3 | +========= |
| 4 | +Axislines |
| 5 | +========= |
| 6 | + |
| 7 | +Axislines includes a derived Axes implementation. The |
| 8 | +biggest difference is that the artists responsible to draw axis line, |
| 9 | +ticks, ticklabel and axis labels are separated out from the mpl's Axis |
| 10 | +class, which are much more than artists in the original |
| 11 | +mpl. This change was strongly motivated to support curvlinear |
| 12 | +grid. Here are a few things that axes_grid.axislines.Axes is different |
| 13 | +from original Axes from mpl. |
| 14 | + |
| 15 | +* Axis elements (axis line(spine), ticks, ticklabel and axis labels) |
| 16 | + are drawn by a AxisArtist instance. Unlike Axis, left, right, top |
| 17 | + and bottom axis are drawn by separate artists. And each of them may |
| 18 | + have different tick location and different tick labels. |
| 19 | + |
| 20 | +* gridlines are drawn by a Gridlines instance. The change was |
| 21 | + motivated that in curvelinear coordinate, a gridline may not cross |
| 22 | + axislines (i.e., no associated ticks). In the original Axes class, |
| 23 | + gridlines are tied to ticks. |
| 24 | + |
| 25 | +* ticklines can be rotated if necessary (i.e, along the gridlines) |
| 26 | + |
| 27 | +In summary, all these changes was to support |
| 28 | + |
| 29 | +* a curvelinear grid. |
| 30 | +* a floating axis |
| 31 | + |
| 32 | +.. plot:: mpl_toolkits/axes_grid/figures/demo_floating_axis.py |
| 33 | + |
| 34 | + |
| 35 | +*axes_grid.axislines.Axes* defines a *axis* attribute, which is a |
| 36 | +dictionary of AxisArtist instances. By default, the dictionary has 4 |
| 37 | +AxisArtist instances, responsible for drawing of left, right, bottom |
| 38 | +and top axis. |
| 39 | + |
| 40 | +xaxis and yaxis attributes are still available, however they are set |
| 41 | +to not visible. As separate artists are used for rendering axis, some |
| 42 | +axis-related method in mpl may have no effect. |
| 43 | +In addition to AxisArtist instances, the axes_grid.axislines.Axes will |
| 44 | +have *gridlines* attribute (Gridlines), which obviously draws grid |
| 45 | +lines. |
| 46 | + |
| 47 | +In both AxisArtist and Gridlines, the calculation of tick and grid |
| 48 | +location is delegated to an instance of GridHelper class. |
| 49 | +axes_grid.axislines.Axes class uses GridHelperRectlinear as a grid |
| 50 | +helper. The GridHelperRectlinear class is a wrapper around the *xaxis* |
| 51 | +and *yaxis* of mpl's original Axes, and it was meant to work as the |
| 52 | +way how mpl's original axes works. For example, tick location changes |
| 53 | +using set_ticks method and etc. should work as expected. But change in |
| 54 | +artist properties (e.g., color) will not work in general, although |
| 55 | +some effort has been made so that some often-change attributes (color, |
| 56 | +etc.) are respected. |
| 57 | + |
| 58 | + |
| 59 | +AxisArtist |
| 60 | +========== |
| 61 | + |
| 62 | +AxisArtist can be considered as a container artist with following |
| 63 | +attributes which will draw ticks, labels, etc. |
| 64 | + |
| 65 | + * line |
| 66 | + * major_ticks, major_ticklabels |
| 67 | + * minor_ticks, minor_ticklabels |
| 68 | + * offsetText |
| 69 | + * label |
| 70 | + |
| 71 | + |
| 72 | +line |
| 73 | +---- |
| 74 | + |
| 75 | +Derived from Line2d class. Responsible for drawing a spinal(?) line. |
| 76 | + |
| 77 | +major_ticks, minor_ticks |
| 78 | +------------------------ |
| 79 | + |
| 80 | +Derived from Line2d class. Note that ticks are markers. |
| 81 | + |
| 82 | + |
| 83 | +major_ticklabels, minor_ticklabels |
| 84 | +---------------------------------- |
| 85 | + |
| 86 | +Derived from Text. Note that it is not a list of Text artist, but a |
| 87 | +single artist (similar to a collection). |
| 88 | + |
| 89 | +axislabel |
| 90 | +--------- |
| 91 | + |
| 92 | +Derived from Text. |
| 93 | + |
| 94 | + |
| 95 | +Default AxisArtists |
| 96 | +------------------- |
| 97 | + |
| 98 | +By default, following for axis artists are defined.:: |
| 99 | + |
| 100 | + ax.axis["left"], ax.axis["bottom"], ax.axis["right"], ax.axis["top"] |
| 101 | + |
| 102 | +The ticklabels and axislabel of the top and the right axis are set to |
| 103 | +not visible. |
| 104 | + |
| 105 | + |
| 106 | +HowTo |
| 107 | +===== |
| 108 | + |
| 109 | +1. Changing tick locations and label. |
| 110 | + |
| 111 | + Same as the original mpl's axes.:: |
| 112 | + |
| 113 | + ax.set_xticks([1,2,3]) |
| 114 | + |
| 115 | +2. Changing axis properties like color, etc. |
| 116 | + |
| 117 | + Change the properties of appropriate artists. For example, to change |
| 118 | + the color of the ticklabels:: |
| 119 | + |
| 120 | + ax.axis["left"].major_ticklabels.set_color("r") |
| 121 | + |
| 122 | + |
| 123 | +GridHelper |
| 124 | +========== |
| 125 | + |
| 126 | +To actually define a curvelinear coordinate, you have to use your own |
| 127 | +grid helper. A generalised version of grid helper class is supplied |
| 128 | +and this class should be suffice in most of cases. A user may provide |
| 129 | +two functions which defines a transformation (and its inverse pair) |
| 130 | +from the curved coordinate to (rectlinear) image coordinate. Note that |
| 131 | +while ticks and grids are drawn for curved coordinate, the data |
| 132 | +transform of the axes itself (ax.transData) is still rectlinear |
| 133 | +(image) coordinate. :: |
| 134 | + |
| 135 | + |
| 136 | + from mpl_toolkits.axes_grid.grid_helper_curvelinear \ |
| 137 | + import GridHelperCurveLinear |
| 138 | + from mpl_toolkits.axes_grid.axislines import Subplot |
| 139 | + |
| 140 | + # from curved coordinate to rectlinear coordinate. |
| 141 | + def tr(x, y): |
| 142 | + x, y = np.asarray(x), np.asarray(y) |
| 143 | + return x, y-x |
| 144 | + |
| 145 | + # from rectlinear coordinate to curved coordinate. |
| 146 | + def inv_tr(x,y): |
| 147 | + x, y = np.asarray(x), np.asarray(y) |
| 148 | + return x, y+x |
| 149 | + |
| 150 | + |
| 151 | + grid_helper = GridHelperCurveLinear((tr, inv_tr)) |
| 152 | + |
| 153 | + ax1 = Subplot(fig, 1, 1, 1, grid_helper=grid_helper) |
| 154 | + |
| 155 | + fig.add_subplot(ax1) |
| 156 | + |
| 157 | + |
| 158 | +You may use matplotlib's Transform instance instead (but a |
| 159 | +inverse transformation must be defined). Often, coordinate range in a |
| 160 | +curved coordinate system may have a limited range, or may have |
| 161 | +cycles. In those cases, a more customized version of grid helper is |
| 162 | +required. :: |
| 163 | + |
| 164 | + |
| 165 | + import mpl_toolkits.axes_grid.angle_helper as angle_helper |
| 166 | + |
| 167 | + # PolarAxes.PolarTransform takes radian. However, we want our coordinate |
| 168 | + # system in degree |
| 169 | + tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() |
| 170 | + |
| 171 | + |
| 172 | + # extreme finder : find a range of coordinate. |
| 173 | + # 20, 20 : number of sampling points along x, y direction |
| 174 | + # The first coordinate (longitude, but theta in polar) |
| 175 | + # has a cycle of 360 degree. |
| 176 | + # The second coordinate (latitude, but radius in polar) has a minimum of 0 |
| 177 | + extreme_finder = angle_helper.ExtremeFinderCycle(20, 20, |
| 178 | + lon_cycle = 360, |
| 179 | + lat_cycle = None, |
| 180 | + lon_minmax = None, |
| 181 | + lat_minmax = (0, np.inf), |
| 182 | + ) |
| 183 | + |
| 184 | + # Find a grid values appropriate for the coordinate (degree, |
| 185 | + # minute, second). The argument is a approximate number of grids. |
| 186 | + grid_locator1 = angle_helper.LocatorDMS(12) |
| 187 | + |
| 188 | + # And also uses an appropriate formatter. Note that,the |
| 189 | + # acceptable Locator and Formatter class is a bit different than |
| 190 | + # that of mpl's, and you cannot directly use mpl's Locator and |
| 191 | + # Formatter here (but may be possible in the future). |
| 192 | + tick_formatter1 = angle_helper.FormatterDMS() |
| 193 | + |
| 194 | + grid_helper = GridHelperCurveLinear(tr, |
| 195 | + extreme_finder=extreme_finder, |
| 196 | + grid_locator1=grid_locator1, |
| 197 | + tick_formatter1=tick_formatter1 |
| 198 | + ) |
| 199 | + |
| 200 | + |
| 201 | +Again, the *transData* of the axes is still a rectlinear coordinate |
| 202 | +(image coordinate). You may manually do conversion between two |
| 203 | +coordinates, or you may use Parasite Axes for convenience.:: |
| 204 | + |
| 205 | + ax1 = SubplotHost(fig, 1, 2, 2, grid_helper=grid_helper) |
| 206 | + |
| 207 | + # A parasite axes with given transform |
| 208 | + ax2 = ParasiteAxesAuxTrans(ax1, tr, "equal") |
| 209 | + # note that ax2.transData == tr + ax1.transData |
| 210 | + # Anthing you draw in ax2 will match the ticks and grids of ax1. |
| 211 | + ax1.parasites.append(ax2) |
| 212 | + |
| 213 | + |
| 214 | +.. plot:: mpl_toolkits/axes_grid/figures/demo_curvelinear_grid.py |
| 215 | + |
| 216 | + |
| 217 | + |
| 218 | +FloatingAxis |
| 219 | +============ |
| 220 | + |
| 221 | +A floating axis is an axis one of whose data coordinate is fixed, i.e, |
| 222 | +its location is not fixed in Axes coordinate but changes as axes data |
| 223 | +limits changes. A floating axis can be created using |
| 224 | +*new_floating_axis* method. However, it is your responsibility that |
| 225 | +the resulting AxisArtist is properly added to the axes. A recommended |
| 226 | +way is to add it as an item of Axes's axis attribute.:: |
| 227 | + |
| 228 | + # floating axis whose first (index starts from 0) coordinate |
| 229 | + # (theta) is fixed at 60 |
| 230 | + |
| 231 | + ax1.axis["lat"] = axis = ax1.new_floating_axis(0, 60) |
| 232 | + axis.label.set_text(r"$\theta = 60^{\circ}$") |
| 233 | + axis.label.set_visible(True) |
| 234 | + |
| 235 | + |
| 236 | +See the first example of this page. |
| 237 | + |
| 238 | +Current Limitations and TODO's |
| 239 | +============================== |
| 240 | + |
| 241 | +The code need more refinement. Here is a incomplete list of issues and TODO's |
| 242 | + |
| 243 | +* No easy way to support a user customized tick location (for |
| 244 | + curvelinear grid). A new Locator class needs to be created. |
| 245 | + |
| 246 | +* FloatingAxis may have coordinate limits, e.g., a floating axis of x |
| 247 | + = 0, but y only spans from 0 to 1. |
| 248 | + |
| 249 | +* The location of axislabel of FloatingAxis needs to be optionally |
| 250 | + given as a coordinate value. ex, a floating axis of x=0 with label at y=1 |
0 commit comments