Настраиваемая шкала широты в проекции Меркатора в Matplotlib

PythonPythonBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Matplotlib - это мощная библиотека визуализации данных для Python. Она предоставляет ряд встроенных шкал для построения графиков данных, но иногда вам может потребоваться кастомная шкала для вашего конкретного сценария использования. В этом лабе мы покажем, как создать кастомную шкалу, которая использует проекцию Меркатора для данных о широте.

Советы по работе с ВМ

После завершения запуска ВМ нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится полностью. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.

Импортируем необходимые библиотеки

Начнем с импорта необходимых библиотек.

import numpy as np
from numpy import ma

from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import FixedLocator, FuncFormatter

Определяем класс MercatorLatitudeScale

Далее мы определим класс MercatorLatitudeScale, который реализует кастомную шкалу. Этот класс будет наследоваться от mscale.ScaleBase.

class MercatorLatitudeScale(mscale.ScaleBase):
    """
    Масштабирует данные в диапазоне от -pi/2 до pi/2 (-90 до 90 градусов) с использованием
    системы, используемой для масштабирования широт в проекции Меркатора__.

    Функция масштабирования:
      ln(tan(y) + sec(y))

    Обратная функция масштабирования:
      atan(sinh(y))

    Поскольку масштаб Меркатора стремится к бесконечности при +/- 90 градусах,
    существует пользовательский порог, выше и ниже которого ничего не будет нарисовано.
    Это по умолчанию равно +/- 85 градусов.

    __ https://en.wikipedia.org/wiki/Mercator_projection
    """

Реализуем класс MercatorLatitudeTransform

Внутри класса MercatorLatitudeScale мы определим класс MercatorLatitudeTransform, который на самом деле будет преобразовывать данные. Этот класс будет наследоваться от mtransforms.Transform.

    class MercatorLatitudeTransform(mtransforms.Transform):
        ## Должен быть определен два члена значения.
        ## ``input_dims`` и ``output_dims`` определяют количество входных
        ## размерностей и выходных размерностей преобразования.
        ## Они используются фреймворком преобразования для выполнения
        ## некоторых проверок на ошибки и предотвращения соединения
        ## несовместимых преобразований.  При определении преобразований
        ## для шкалы, которые, по определению, являются разделяемыми и
        ## имеют только одну размерность, эти члены должны всегда быть
        ## установлены в 1.
        input_dims = output_dims = 1

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, a):
            """
            Это преобразование принимает numpy-массив и возвращает преобразованную копию.
            Поскольку диапазон шкалы Меркатора ограничен пользовательским
            порогом, входной массив должен быть замаскирован, чтобы
            содержать только допустимые значения. Matplotlib будет обрабатывать
            замаскированные массивы и удалять из графика данные за пределами
            допустимого диапазона.  Однако возвращаемый массив *должен* иметь
            ту же форму, что и входной массив, так как эти значения должны
            оставаться синхронизированы с значениями в другой размерности.
            """
            masked = ma.masked_where((a < -self.thresh) | (a > self.thresh), a)
            if masked.mask.any():
                return ma.log(np.abs(ma.tan(masked) + 1 / ma.cos(masked)))
            else:
                return np.log(np.abs(np.tan(a) + 1 / np.cos(a)))

        def inverted(self):
            """
            Переопределите этот метод, чтобы Matplotlib знал, как получить
            обратное преобразование для этого преобразования.
            """
            return MercatorLatitudeScale.InvertedMercatorLatitudeTransform(
                self.thresh)

Реализуем класс InvertedMercatorLatitudeTransform

Мы также определим класс InvertedMercatorLatitudeTransform, который будет использоваться для получения обратного преобразования для этой шкалы.

    class InvertedMercatorLatitudeTransform(mtransforms.Transform):
        input_dims = output_dims = 1

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, a):
            return np.arctan(np.sinh(a))

        def inverted(self):
            return MercatorLatitudeScale.MercatorLatitudeTransform(self.thresh)

Регистрируем кастомную шкалу

Мы зарегистрируем кастомную шкалу с Matplotlib с использованием mscale.register_scale.

mscale.register_scale(MercatorLatitudeScale)

Используем кастомную шкалу

Теперь мы можем использовать кастомную шкалу в наших графиках. Вот пример использования кастомной шкалы для данных о широте в проекции Меркатора.

if __name__ == '__main__':
    import matplotlib.pyplot as plt

    t = np.arange(-180.0, 180.0, 0.1)
    s = np.radians(t)/2.

    plt.plot(t, s, '-', lw=2)
    plt.yscale('mercator')

    plt.xlabel('Longitude')
    plt.ylabel('Latitude')
    plt.title('Mercator projection')
    plt.grid(True)

    plt.show()

Резюме

В этом практическом занятии мы узнали, как создавать кастомную шкалу в Matplotlib с использованием проекции Меркатора для данных о широте. Мы определили классы MercatorLatitudeScale и MercatorLatitudeTransform и зарегистрировали кастомную шкалу с Matplotlib с использованием mscale.register_scale. Мы также показали пример использования кастомной шкалы для данных о широте в проекции Меркатора.