Как создать строки с интервалом da sh и шириной в единицах данных? - PullRequest
2 голосов
/ 17 апреля 2020

Я пытаюсь создать подкласс matplotlib.lines.Line2D, чтобы создать линии, ширина которых и интервалы da sh совпадают с координатами отображаемых данных. Я расширил этот ответ , чтобы попытаться поддержать пунктирные линии (с промежутками da sh, также находящимися в единицах данных) и теперь иметь следующий код:

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

class LineDataUnits(Line2D):
    """
    A Line2D object, but with the linewidth and dash properties defined in data coordinates.
    """
    def __init__(self, *args, **kwargs):
        _lw_data = kwargs.pop("linewidth", 1)
        _dashes_data = kwargs.pop("dashes", (1,))
        super().__init__(*args, **kwargs)
        self._lw_data = _lw_data
        self._dashes_data = _dashes_data
        self._dashOffset = 0

    def _get_lw(self):
        if self.axes is not None:
            ppd = 72./self.axes.figure.dpi
            trans = self.axes.transData.transform
            return ((trans((1, self._lw_data))-trans((0, 0)))*ppd)[1]
        else:
            return 1

    def _set_lw(self, lw):
        self._lw_data = lw

    def _get_dashes(self):
        if self.axes is not None:
            ppd = 72./self.axes.figure.dpi
            trans = self.axes.transData.transform
            return tuple([((trans((1, dash_data))-trans((0, 0)))*ppd)[1] for dash_data in self._dashes_data])
        else:
            return tuple((1, 0))

    def _set_dashes(self, dashes):
        self._dashes_data = dashes

    _linewidth = property(_get_lw, _set_lw)
    _dashSeq = property(_get_dashes, _set_dashes)


if __name__ == "__main__":
    fig, ax = plt.subplots()
    line1 = Line2D([0, 10], [3, 3], linewidth=10, color="blue", dashes=(3, 3), dash_capstyle="round")
    line2 = LineDataUnits([0, 10], [6, 6], linewidth=0.5, color="red", dashes=(1, 1), dash_capstyle="round")
    print("dash_capstyle:", line2.get_dash_capstyle())
    ax.add_line(line1)
    ax.add_line(line2)
    ax.set_xticks(range(10))
    ax.grid()
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    plt.show()

Какие выдает следующий график: graph of dashed Line2D and LineDataUnits

При увеличении и уменьшении расстояния da sh, кажется, остаются постоянными в единицах данных, однако, как вы можете видеть на графике, их значения не рассчитано правильно. Кроме того, кажется, что установка параметра dash_capstyle в этом классе, похоже, не имеет никакого эффекта.

Любая помощь будет принята с благодарностью.

Редактировать: Решение

После гораздо большего экспериментируя, мне удалось заставить его работать должным образом. Во-первых, несмотря на то, что линия строилась черточками, для параметра Line2D по-прежнему был установлен параметр _linestyle, равный "-" (solid), что приводило к игнорированию аргумента стиля cap. Во-вторых, произошла ошибка в моем преобразовании из единиц данных в точки. С изменениями ниже, теперь он работает отлично.

# in __init__()
    super().__init__(*args, **kwargs):
+   self.set_linestyle("--")
    self._lw_data = _lw_data

# in _get_dashes()
-   return tuple([((trans((1, dash_data))-trans((0, 0)))*ppd)[1] for dash_data in self._dashes_data])
+   dpu = (trans((1, 1)) - trans((0, 0)))[0]
+   return tuple([u*dpu*ppd for u in self._dashes_data])

1 Ответ

1 голос
/ 17 апреля 2020
# in __init__()
    super().__init__(*args, **kwargs):
+   self.set_linestyle("--")
    self._lw_data = _lw_data

# in _get_dashes()
-   return tuple([((trans((1, dash_data))-trans((0, 0)))*ppd)[1] for dash_data in self._dashes_data])
+   dpu = (trans((1, 1)) - trans((0, 0)))[0]
+   return tuple([u*dpu*ppd for u in self._dashes_data])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...