<spanid="sphx-glr-gallery-api-custom-scale-example-py"></span><h1>Custom scale<aclass="headerlink" href="#custom-scale" title="Permalink to this headline">¶</a></h1>
<p>Create a custom scale, by implementing the
scaling use for latitude data in a Mercator Projection.</p>
<spanclass="kn">from</span><spanclass="nn">matplotlib.ticker</span><spanclass="kn">import</span><ahref="../../api/ticker_api.html#matplotlib.ticker.Formatter" title="View documentation for matplotlib.ticker.Formatter"><spanclass="n">Formatter</span></a><spanclass="p">,</span><ahref="../../api/ticker_api.html#matplotlib.ticker.FixedLocator" title="View documentation for matplotlib.ticker.FixedLocator"><spanclass="n">FixedLocator</span></a>
<spanclass="kn">from</span><spanclass="nn">matplotlib</span><spanclass="kn">import</span><ahref="../../api/matplotlib_configuration_api.html#matplotlib.rcParams" title="View documentation for matplotlib.rcParams"><spanclass="n">rcParams</span></a>
<spanclass="c1"># BUG: this example fails with any other setting of axisbelow</span>
<ahref="../../api/matplotlib_configuration_api.html#matplotlib.rcParams" title="View documentation for matplotlib.rcParams"><spanclass="n">rcParams</span></a><spanclass="p">[</span><spanclass="s1">'axes.axisbelow'</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="bp">False</span>
<spanclass="k">class</span><spanclass="nc">MercatorLatitudeScale</span><spanclass="p">(</span><ahref="../../api/scale_api.html#matplotlib.scale.ScaleBase" title="View documentation for matplotlib.scale.ScaleBase"><spanclass="n">mscale</span><spanclass="o">.</span><spanclass="n">ScaleBase</span></a><spanclass="p">):</span>
<spanclass="sd">"""</span>
<spanclass="sd"> Scales data in range -pi/2 to pi/2 (-90 to 90 degrees) using</span>
<spanclass="sd"> the system used to scale latitudes in a Mercator projection.</span>
<spanclass="sd"> The scale function:</span>
<spanclass="sd"> ln(tan(y) + sec(y))</span>
<spanclass="sd"> The inverse scale function:</span>
<spanclass="sd"> atan(sinh(y))</span>
<spanclass="sd"> Since the Mercator scale tends to infinity at +/- 90 degrees,</span>
<spanclass="sd"> there is user-defined threshold, above and below which nothing</span>
<spanclass="sd"> will be plotted. This defaults to +/- 85 degrees.</span>
<spanclass="sd"> Any keyword arguments passed to ``set_xscale`` and</span>
<spanclass="sd"> ``set_yscale`` will be passed along to the scale's</span>
<spanclass="sd"> constructor.</span>
<spanclass="sd"> thresh: The degree above which to crop the data.</span>
<spanclass="sd"> """</span>
<ahref="../../api/scale_api.html#matplotlib.scale.ScaleBase" title="View documentation for matplotlib.scale.ScaleBase"><spanclass="n">mscale</span><spanclass="o">.</span><spanclass="n">ScaleBase</span></a><spanclass="o">.</span><spanclass="fm">__init__</span><spanclass="p">(</span><spanclass="bp">self</span><spanclass="p">)</span>
<spanclass="n">thresh</span><spanclass="o">=</span><spanclass="n">kwargs</span><spanclass="o">.</span><spanclass="n">pop</span><spanclass="p">(</span><spanclass="s2">"thresh"</span><spanclass="p">,</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.radians.html#numpy.radians" title="View documentation for numpy.radians"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">radians</span></a><spanclass="p">(</span><spanclass="mi">85</span><spanclass="p">))</span>
<spanclass="k">raise</span><spanclass="ne">ValueError</span><spanclass="p">(</span><spanclass="s2">"thresh must be less than pi/2"</span><spanclass="p">)</span>
<spanclass="sd"> Override to set up the locators and formatters to use with the</span>
<spanclass="sd"> scale. This is only required if the scale requires custom</span>
<spanclass="sd"> locators and formatters. Writing custom locators and</span>
<spanclass="sd"> formatters is rather outside the scope of this example, but</span>
<spanclass="sd"> there are many helpful examples in ``ticker.py``.</span>
<spanclass="sd"> In our case, the Mercator example uses a fixed locator from</span>
<spanclass="sd"> -90 to 90 degrees and a custom formatter class to put convert</span>
<spanclass="sd"> the radians to degrees and put a degree symbol after the</span>
<spanclass="sd"> value::</span>
<spanclass="sd"> """</span>
<spanclass="k">class</span><spanclass="nc">DegreeFormatter</span><spanclass="p">(</span><ahref="../../api/ticker_api.html#matplotlib.ticker.Formatter" title="View documentation for matplotlib.ticker.Formatter"><spanclass="n">Formatter</span></a><spanclass="p">):</span>
<spanclass="k">return</span><spanclass="s2">"</span><spanclass="si">%d</span><spanclass="se">\N{DEGREE SIGN}</span><spanclass="s2">"</span><spanclass="o">%</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.degrees.html#numpy.degrees" title="View documentation for numpy.degrees"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">degrees</span></a><spanclass="p">(</span><spanclass="n">x</span><spanclass="p">)</span>
<spanclass="n">axis</span><spanclass="o">.</span><spanclass="n">set_major_locator</span><spanclass="p">(</span><ahref="../../api/ticker_api.html#matplotlib.ticker.FixedLocator" title="View documentation for matplotlib.ticker.FixedLocator"><spanclass="n">FixedLocator</span></a><spanclass="p">(</span>
<ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.radians.html#numpy.radians" title="View documentation for numpy.radians"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">radians</span></a><spanclass="p">(</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html#numpy.arange" title="View documentation for numpy.arange"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">arange</span></a><spanclass="p">(</span><spanclass="o">-</span><spanclass="mi">90</span><spanclass="p">,</span><spanclass="mi">90</span><spanclass="p">,</span><spanclass="mi">10</span><spanclass="p">))))</span>
<spanclass="k">class</span><spanclass="nc">MercatorLatitudeTransform</span><spanclass="p">(</span><ahref="../../api/transformations.html#matplotlib.transforms.Transform" title="View documentation for matplotlib.transforms.Transform"><spanclass="n">mtransforms</span><spanclass="o">.</span><spanclass="n">Transform</span></a><spanclass="p">):</span>
<spanclass="c1"># There are two value members that must be defined.</span>
<spanclass="c1"># ``input_dims`` and ``output_dims`` specify number of input</span>
<spanclass="c1"># dimensions and output dimensions to the transformation.</span>
<spanclass="c1"># These are used by the transformation framework to do some</span>
<spanclass="c1"># error checking and prevent incompatible transformations from</span>
<spanclass="c1"># being connected together. When defining transforms for a</span>
<spanclass="c1"># scale, which are, by definition, separable and have only one</span>
<spanclass="c1"># dimension, these members should always be set to 1.</span>
<ahref="../../api/transformations.html#matplotlib.transforms.Transform" title="View documentation for matplotlib.transforms.Transform"><spanclass="n">mtransforms</span><spanclass="o">.</span><spanclass="n">Transform</span></a><spanclass="o">.</span><spanclass="fm">__init__</span><spanclass="p">(</span><spanclass="bp">self</span><spanclass="p">)</span>
<spanclass="sd"> This transform takes an Nx1 ``numpy`` array and returns a</span>
<spanclass="sd"> transformed copy. Since the range of the Mercator scale</span>
<spanclass="sd"> is limited by the user-specified threshold, the input</span>
<spanclass="sd"> array must be masked to contain only valid values.</span>
<spanclass="sd"> ``matplotlib`` will handle masked arrays and remove the</span>
<spanclass="sd"> out-of-range data from the plot. Importantly, the</span>
<spanclass="sd"> ``transform`` method *must* return an array that is the</span>
<spanclass="sd"> same shape as the input array, since these values need to</span>
<spanclass="sd"> remain synchronized with values in the other dimension.</span>
<spanclass="sd"> """</span>
<spanclass="n">masked</span><spanclass="o">=</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.masked_where.html#numpy.ma.masked_where" title="View documentation for numpy.ma.masked_where"><spanclass="n">ma</span><spanclass="o">.</span><spanclass="n">masked_where</span></a><spanclass="p">((</span><spanclass="n">a</span><spanclass="o"><</span><spanclass="o">-</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">thresh</span><spanclass="p">)</span><spanclass="o">|</span><spanclass="p">(</span><spanclass="n">a</span><spanclass="o">></span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">thresh</span><spanclass="p">),</span><spanclass="n">a</span><spanclass="p">)</span>
<spanclass="k">return</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.log.html#numpy.log" title="View documentation for numpy.log"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">log</span></a><spanclass="p">(</span><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">abs</span><spanclass="p">(</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.tan.html#numpy.tan" title="View documentation for numpy.tan"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">tan</span></a><spanclass="p">(</span><spanclass="n">a</span><spanclass="p">)</span><spanclass="o">+</span><spanclass="mf">1.0</span><spanclass="o">/</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.cos.html#numpy.cos" title="View documentation for numpy.cos"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">cos</span></a><spanclass="p">(</span><spanclass="n">a</span><spanclass="p">)))</span>
<spanclass="k">class</span><spanclass="nc">InvertedMercatorLatitudeTransform</span><spanclass="p">(</span><ahref="../../api/transformations.html#matplotlib.transforms.Transform" title="View documentation for matplotlib.transforms.Transform"><spanclass="n">mtransforms</span><spanclass="o">.</span><spanclass="n">Transform</span></a><spanclass="p">):</span>
<ahref="../../api/transformations.html#matplotlib.transforms.Transform" title="View documentation for matplotlib.transforms.Transform"><spanclass="n">mtransforms</span><spanclass="o">.</span><spanclass="n">Transform</span></a><spanclass="o">.</span><spanclass="fm">__init__</span><spanclass="p">(</span><spanclass="bp">self</span><spanclass="p">)</span>
<spanclass="k">return</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.arctan.html#numpy.arctan" title="View documentation for numpy.arctan"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">arctan</span></a><spanclass="p">(</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.sinh.html#numpy.sinh" title="View documentation for numpy.sinh"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">sinh</span></a><spanclass="p">(</span><spanclass="n">a</span><spanclass="p">))</span>
<spanclass="c1"># Now that the Scale class has been defined, it must be registered so</span>
<spanclass="c1"># that ``matplotlib`` can find it.</span>
<ahref="../../api/scale_api.html#matplotlib.scale.register_scale" title="View documentation for matplotlib.scale.register_scale"><spanclass="n">mscale</span><spanclass="o">.</span><spanclass="n">register_scale</span></a><spanclass="p">(</span><spanclass="n">MercatorLatitudeScale</span><spanclass="p">)</span>
<spanclass="n">t</span><spanclass="o">=</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html#numpy.arange" title="View documentation for numpy.arange"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">arange</span></a><spanclass="p">(</span><spanclass="o">-</span><spanclass="mf">180.0</span><spanclass="p">,</span><spanclass="mf">180.0</span><spanclass="p">,</span><spanclass="mf">0.1</span><spanclass="p">)</span>
<spanclass="n">s</span><spanclass="o">=</span><ahref="https://docs.scipy.org/doc/numpy/reference/generated/numpy.radians.html#numpy.radians" title="View documentation for numpy.radians"><spanclass="n">np</span><spanclass="o">.</span><spanclass="n">radians</span></a><spanclass="p">(</span><spanclass="n">t</span><spanclass="p">)</span><spanclass="o">/</span><spanclass="mf">2.</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot" title="View documentation for matplotlib.pyplot.plot"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">plot</span></a><spanclass="p">(</span><spanclass="n">t</span><spanclass="p">,</span><spanclass="n">s</span><spanclass="p">,</span><spanclass="s1">'-'</span><spanclass="p">,</span><spanclass="n">lw</span><spanclass="o">=</span><spanclass="mi">2</span><spanclass="p">)</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.gca.html#matplotlib.pyplot.gca" title="View documentation for matplotlib.pyplot.gca"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">gca</span></a><spanclass="p">()</span><spanclass="o">.</span><spanclass="n">set_yscale</span><spanclass="p">(</span><spanclass="s1">'mercator'</span><spanclass="p">)</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.xlabel.html#matplotlib.pyplot.xlabel" title="View documentation for matplotlib.pyplot.xlabel"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">xlabel</span></a><spanclass="p">(</span><spanclass="s1">'Longitude'</span><spanclass="p">)</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.ylabel.html#matplotlib.pyplot.ylabel" title="View documentation for matplotlib.pyplot.ylabel"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">ylabel</span></a><spanclass="p">(</span><spanclass="s1">'Latitude'</span><spanclass="p">)</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.title.html#matplotlib.pyplot.title" title="View documentation for matplotlib.pyplot.title"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">title</span></a><spanclass="p">(</span><spanclass="s1">'Mercator: Projection of the Oppressor'</span><spanclass="p">)</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.grid.html#matplotlib.pyplot.grid" title="View documentation for matplotlib.pyplot.grid"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">grid</span></a><spanclass="p">(</span><spanclass="bp">True</span><spanclass="p">)</span>
<ahref="../../api/_as_gen/matplotlib.pyplot.show.html#matplotlib.pyplot.show" title="View documentation for matplotlib.pyplot.show"><spanclass="n">plt</span><spanclass="o">.</span><spanclass="n">show</span></a><spanclass="p">()</span>