matplotlib document : Artist tutorial(その1)



## この記事

以下の参考文献「matplotlib document 3.0.2」にある「Artist tutorial」(intermediate)の訳です。理解不足で不正確な部分もあるかと思いますが、参考になれば幸いです。

## 参考文献

[matplotlib 3.0.2 documentation](https://matplotlib.org/tutorials/intermediate/artists.html#sphx-glr-tutorials-intermediate-artists-py)

## Artist

* キャンバスに図を描くために`Artist`オブジェクトを使用する。
* `matplotlib API`には以下の3つの層が存在する。

	* 図が描かれる領域である`matplotlib.backend_bases.FigureCanvas`
	* 上記領域に描画する方法を持つ`matplotlib.backend_bases.Renderer`
	* キャンバスに描画するレンダラーの使用方法を握る` matplotlib.artist.Artist`

* `FigureCanvas`や`Renderer`はあらゆる命令を備えている一方、`Artist`は図、テキスト、線といった要素を描き配置する命令を備えており、普通は`FigureCanvas`や`Renderer`ではなく`Artist`を使用することが殆ど。

* `Artist`には二種類の要素があり、primitiveとcontainerと呼ばれている。

	* primitiveは`Line2D`や`Rectangle`といった通常のグラフオブジェクト。
	* containerは`Axis`や`Axes`、`Figure`といった入れ物の機能を持つものがが該当する。

* 通常は、`Figure`インスタンスを作成し、`Axes`インスタンスや`subplot`インスタンスを作成する。その中で、インスタンスメソッドを使ってprimitiveを作成する。
* `Figure`インスタンスを`matplotlib.pyplot.Figure`を使って作成することで、描画ツールメソッド(`plot()`など)と`figure`を関連付けてくれる。

* `Axes`は最もmatplotlib APIで重要なクラスで、ほとんどの場合でオブジェクトの描画エリアとなる。

* `Axes`オブジェクトは、`plot()`、`text()`、`hist()`、`imshow()`など多くのヘルパーメソッドを持つ。
	
* ヘルパーメソッドは、例えば`numpy`で作成されたデータを扱って、必要なprimitiveな`Artist`インスタンスを作成する。その後、適切なcontainerに追加し、必要な時に描画されるようにする。
* `Axes`インスタンスを作成するには`add_subplot()`が最もお馴染の手法(`figure`クラスのメソッド)だが、これも行列形式に配置された`Axes`の特殊なケースに過ぎない。
* もし`Axes`を任意の場所に配置したければ、`add_axes()`メソッドを、figure内の相対位置をリストで指定([left,bottom,width,height]で)使用することで実現可能。


```python:
import matplotlib.pyplot as plt

# subplotによるaxesオブジェクトの取得
fig = plt.Figure()
ax = fig.add_subplot(2,1,1) # two rows, one column, first plot

# add_axesによるaxesオブジェクトの取得
fig2 = plt.Figure()
ax2 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
```

* `ax.plot()`を呼び出すことによって`Axes.lines`のリストに描画したグラフ(`Line2D`のインスタンス)が追加される。
* 以下のように追加されるインスタンスを直接返り値として取得することもできる。

```python:
import numpy as np
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax.plot(t, s, color='blue', lw=2)
```

* ここで`line`がLine2Dインスタンスとなるが、`ax.lines`にもリストの要素として追加されているので、`ax.lines[0]`で(0の部分は変わりうる)取得及び操作可能。

	* 例えば今追加したグラフを削除したい場合には、以下のいずれかの方法で削除可能。
			
           * 二番目の方法は、Line2Dインスタンスを引数に指定することで`ax.lines`のリストから削除されており興味深い。

	* `ax.lines[0]`でも`ax.plot()`の返り値も同一のインスタンスを示しているから。

```python:
del ax.lines[0]
ax.lines.remove(line)  # one or the other, not both!
```

* `Axes`オブジェクトは,x軸を表す`XAxis`とy軸を表す`YAxis`インスタンスを持つ。
* `Axes`オブジェクトはx,y軸の目盛、目盛ラベル、軸ラベルを設定するメソッドを持つ`。例えば以下のように`ax.set_xlabel()`を実行すると`XAxis`オブジェクトが持つ`Text`インスタンスを返す。

```python:
xtext = ax.set_xlabel('my xdata') # returns a Text instance
ytext = ax.set_ylabel('my ydata')
```

## artistオブジェクトのカスタマイズ

* 図中の全ての要素は`Artist`クラスによって表現されており、見た目を変更するためのプロパティを持っている。
* figure自体は`Rectangle`を持っており大きさや背景色、透過度の設定を行うことができる。
* 同様に`Axes`のバウンディングボックスも`Rectangle`インスタンスを持ち、`Axes`の色、透過度、その他のプロパティを設定することができる。
* これらのインスタンスは`Figure.patch`及び`Axes.patch`にそれぞれ格納される。

* 具体的には以下のプロパティを持つ。

|プロパティ|説明|
|:----------:|----|
|alpha|0-1までで設定する透過度|
|animated|アニメーションさせる/させないのboolean値|
|axes|その`Artist`の中の`axes`の設定、通常はNone|
|clip_box|その`Artist`をクリップするバウンディングボックス|
|clip_on|クリッピングをするかしないかのboolean値|
|clip_path|クリップされるpath|
|contains|A picking function to test |
|figure|その`Artist`が存在するfigureインスタンス、通常はNone|
|label|テキストのラベル|
|picker|オブジェクトピッキングをコントロールするpythonオブジェクト|
|transform|transformation|
|visible|描画されるか否かのboolean値|
|zorder|描画の順番を決定する数値|
|rasterized|ベクターをラスター化するか否かのboolean値|

* 以上のプロパティは以下のようにゲッター・セッターでアクセスすることができる。また、`set`メソッドを使用することで複数のプロパティを同時に設定することもできる。

```python:

# oはartistインスタンス
a = o.get_alpha()
o.set_alpha(0.5*a)
# 上の代替手段
o.set(alpha=0.5, zorder=2)
```

* `matplotlib.artist.getp(hoge)`で、そのhoge`artist`インスタンスのプロパティを一覧表示することができる。

	* `artist`クラスのサブクラスである`Figure`や`Rectangle`などでもこの命令は有効で、`Axes`クラスのインスタンスでもプロパティが取得できる。

```python:
fig, ax = plt.subplots()
matplotlib.artist.getp(ax)

##以下結果
    adjustable = box
    agg_filter = None
    alpha = 0.1
    anchor = C
    animated = False
    aspect = auto
    autoscale_on = True
    autoscalex_on = True
    autoscaley_on = True
    axes_locator = None
    axisbelow = line
    children = [<matplotlib.spines.Spine object at 0x00000000066D...
    clip_box = None
    clip_on = True
    clip_path = None
    contains = None
    data_ratio = 1.0
    default_bbox_extra_artists = [<matplotlib.spines.Spine object at 0x00000000066D..
    facecolor = (1.0, 1.0, 1.0, 1.0)
    fc = (1.0, 1.0, 1.0, 1.0)
    figure = Figure(640x480)
    frame_on = True
    geometry = (1, 1, 1)
    gid = None
    gridspec = GridSpec(1, 1)
    images = <a list of 0 AxesImage objects>
    in_layout = True
    label =
    legend = None
    legend_handles_labels = ([], [])
    lines = <a list of 0 Line2D objects>
    navigate = True
    navigate_mode = None
    path_effects = []
    picker = None
    position = Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=...
    rasterization_zorder = None
    rasterized = None
    renderer_cache = None
    shared_x_axes = <matplotlib.cbook.Grouper object at 0x000000000620...
    shared_y_axes = <matplotlib.cbook.Grouper object at 0x000000000624...
    sketch_params = None
    snap = None
    subplotspec = <matplotlib.gridspec.SubplotSpec object at 0x00000...
    title =
    transform = IdentityTransform()
    transformed_clip_path_and_affine = (None, None)
    url = None
    visible = True
    window_extent = Bbox(x0=76.5, y0=49.3, x1=579.5, y1=425.9)
    xaxis = XAxis(80.000000,52.800000)
    xaxis_transform = BlendedGenericTransform(     CompositeGenericTrans...
    xbound = (0.0, 1.0)
    xgridlines = <a list of 6 Line2D xgridline objects>
    xlabel =
    xlim = (0.0, 1.0)
    xmajorticklabels = <a list of 6 Text xticklabel objects>
    xminorticklabels = <a list of 0 Text xticklabel objects>
    xscale = linear
    xticklabels = <a list of 6 Text xticklabel objects>
    xticklines = <a list of 12 Line2D xtickline objects>
    xticks = [0.  0.2 0.4 0.6 0.8 1. ]
    yaxis = YAxis(80.000000,52.800000)
    yaxis_transform = BlendedGenericTransform(     BboxTransformTo(     ...
    ybound = (0.0, 1.0)
    ygridlines = <a list of 6 Line2D ygridline objects>
    ylabel =
    ylim = (0.0, 1.0)
    ymajorticklabels = <a list of 6 Text yticklabel objects>
    yminorticklabels = <a list of 0 Text yticklabel objects>
    yscale = linear
    yticklabels = <a list of 6 Text yticklabel objects>
    yticklines = <a list of 12 Line2D ytickline objects>
    yticks = [0.  0.2 0.4 0.6 0.8 1. ]
    zorder = 0
```