ujimushi(@旧sradjp(15364))の日記

旧スラドの日記の引越先です

plot_title(|vspan|location|font([hv]align)) (Plots.jl(GR))

大方の予想通り,今回はplot_title*(plot_title関係)です。 全部まとめてやる予定でしたが,色々あって2回に分けます。

それぞれplotアトリビュートです。

最初は簡単だと思ったのですが,plot_titlelocationがくせ物で分量が多くなりました。

plot_title

ほぼtitle(Subplot)と同じで図のタイトルの文字列を指定します。

別名

最近はソースに別名を列挙していましたが, 図に一つしか指定できないので,別名は箇条書きにします。

  • plot_title
  • plot_grid_title
  • plot_titles
  • plotgridtitle
  • plottitles
  • sgtitle
  • subplot_grid_title
  • subplotgridtitle
  • suptitle

多いです。一番短いのを選ぶならsgtitleでしょうか?

使用例

title(|location|font(family|size|color|rotation|[vh]align)) (Plots.jl(GR))の再掲です。

using Plots
gr()
plts = [plot(sin, title=k) for k in ["A", "B", "C", "D"]]
plot(plts...; plot_title = "ABCD")
savefig("ABCD_correct.png")

plot_titlevspan

プロットタイトルに使う高さを図全体の高さとの比で設定します。デフォルトは0.05なので, 全体の高さの5%を使う設定になっています。

別名

  • plot_titlevspan
  • plot_titlevspans
  • plottitlevspans

plottitlevspanがないのが不思議です。

概念図

大作です(?)。

これを見ると,plot_titlevspanを大きくとると,実際のグラフの領域が小さくなることが分かります。

一応ソースリストも。

using TikzPictures

function smaller(rect::@NamedTuple{x₀::Float64, y₀::Float64,
                                   x₁::Float64, y₁::Float64},
                 w::Number; type=:all)
    if type == :top
        (x₀=rect.x₀, y₀=rect.y₀, x₁=rect.x₁, y₁=rect.y₁ - w)
    elseif type == :bottom
        (x₀=rect.x₀, y₀=rect.y₀ + w, x₁=rect.x₁, y₁=rect.y₁)
    elseif type == :left
        (x₀=rect.x₀ + w, y₀=rect.y₀, x₁=rect.x₁, y₁=rect.y₁)
    elseif type == :right
        (x₀=rect.x₀, y₀=rect.y₀, x₁=rect.x₁ - w, y₁=rect.y₁)
    else
        (x₀=rect.x₀ + w, y₀=rect.y₀ + w, x₁=rect.x₁ - w, y₁=rect.y₁ - w)
    end
end

function tikzdrawrect(rect::@NamedTuple{x₀::Float64, y₀::Float64,
                                        x₁::Float64, y₁::Float64}; option="")
    "\\draw[draw, $option] ($(rect.x₀), $(rect.y₀)) rectangle ($(rect.x₁), $(rect.y₁));"
end

r_whole = (x₀=0.0, y₀=0.0, x₁=10.0, y₁=6.0)
r_sps = smaller(r_whole, r_whole.y₁ * 0.3; type=:top)
r_sp = [smaller(r_sps, r_sps.x₁ * 0.5; type=rl) for rl in [:right, :left]]
             
r_spm = smaller.(r_sp, 0.5)

x₁ = r_whole.x₁ * 0.2
x₂ = r_sp[2].x₀ + x₁
y₁ = (r_spm[1].y₀ + r_spm[1].y₁) / 2 + 0.8
y₂ = y₁ - 0.8 * 2

p_c = [(x=(r.x₀ + r.x₁) / 2,  y=(r.y₀ + r.y₁) / 2) for r in r_sp]
arrows_latex = begin
    条件s = [(p₁ = (x₁, r_sp[1].y₁), p₂ = (x₁, r_spm[1].y₁), ⚓="north", t="top\\_margin"),
             (p₁ = (x₂, r_sp[2].y₁), p₂ = (x₂, r_spm[2].y₁), ⚓="north", t="top\\_margin"),
             (p₁ = (x₁, r_sp[1].y₀), p₂ = (x₁, r_spm[1].y₀), ⚓="south", t="bottom\\_margin"),
             (p₁ = (x₂, r_sp[2].y₀), p₂ = (x₂, r_spm[2].y₀), ⚓="south", t="bottom\\_margin"),
             (p₁ = (r_sp[1].x₀, y₁), p₂ = (r_spm[1].x₀, y₁), ⚓="west", t="left\\_margin"),
             (p₁ = (r_sp[2].x₀, y₁), p₂ = (r_spm[2].x₀, y₁), ⚓="west", t="left\\_margin"),
             (p₁ = (r_sp[1].x₁, y₂), p₂ = (r_spm[1].x₁, y₂), ⚓="east", t="right\\_margin"),
             (p₁ = (r_sp[2].x₁, y₂), p₂ = (r_spm[2].x₁, y₂), ⚓="east", t="right\\_margin")]
    string(["\\draw[<->, thick, blue] $(条件.p₁) -- $(条件.p₂) node[anchor=$(条件.⚓)] {$(条件.t)};\n"
            for 条件 in 条件s]...)
end

tp = TikzPicture(
"""
$(tikzdrawrect(r_whole; option="black, fill=black!10, thick"))
$(tikzdrawrect(r_sp[1]; option="blue, thick"))
$(tikzdrawrect(r_sp[2]; option="blue, thick"))
$(tikzdrawrect(r_spm[1]; option="blue, dashed, fill=blue!30, thick"))
$(tikzdrawrect(r_spm[2]; option="blue, dashed, fill=blue!30, thick"))
$arrows_latex
\\node[red] at ($(r_sps.x₀), $(r_sps.y₁)) {(0, 0)};
\\node[red] at ($(r_whole.x₀), $(r_whole.y₁)) {(0, 1)};
\\node[red] at ($(r_sps.x₁), $(r_sps.y₁)) {(1, 0)};
\\node[red] at ($(r_whole.x₁), $(r_whole.y₁)) {(1, 1)};
\\node[red, anchor=north west] at ($(r_whole.x₀), $(r_whole.y₁)) {:left};
\\node[red, anchor=north east] at ($(r_whole.x₁), $(r_whole.y₁)) {:right};
\\node[red, anchor=north] at ($(r_sp[1].x₁), $(r_whole.y₁)) {:center};
\\node[red] at ($(r_sp[1].x₁), $((r_whole.y₁ + r_sps.y₁) / 2)) {(0.5, 0.5)};
\\node[red, anchor=south] at ($(r_sp[1].x₁), $(r_sp[1].y₁)) {\\textbf{plot\\_titlelocation}};
\\node[blue] at ($(p_c[1].x), $(p_c[1].y)) {\\textbf{Subplot(No.1)}};
\\node[blue] at ($(p_c[2].x), $(p_c[2].y)) {\\textbf{Subplot(No.2)}};
\\draw[<->, very thick] ($(x₁), $(r_sps.y₁)) -- ($(x₁), $(r_whole.y₁))
node[anchor=south, text width=4cm, align=center] {\\textbf{plot\\_titlevspan \\\\ (heightとの比を指定)}};
\\draw[<->, thick] (-0.5, $(r_whole.y₁))
 -- node[anchor=south, rotate=90] {height} (-0.5, $(r_whole.y₀));
node[anchor=south] {\\textbf{plot\\_titlevspan}};
\\begin{scope}[on background layer]
\\fill[fill=white] (current bounding box.south west) rectangle (current bounding box.north east);
\\end{scope}
"""
, preamble="""
  \\usepackage{luatexja}
  \\usetikzlibrary{arrows.meta}
  \\usetikzlibrary{backgrounds}
  """
)

save(SVG("plot_title_margin"), tp)
run(`inkscape -w 768 -o plot_title_margin.png plot_title_margin.svg`)

plot_title(location|font[vh]align)

プロットのタイトルの位置とフォントの基準位置の設定関係です。 titleでは位置が左右真ん中しか決められないのですが,plot_titleでは裏技で位置が 自由に変えられます。(知りませんでした)

ただ,自動でよしなにという感じではないので,マニュアルで位置を指定する必要があります。 位置の設定については,前項の概念図が参考になるでしょう。

別名

  • plot_titlelocation, plot_titlelocations, plottitlelocations
  • plot_titlefontvalign, plot_titlefontvaligns, plottitlefontvaligns
  • plot_titlefonthalign, plot_titlefonthaligns, plottitlefonthaligns

使用例

まずは,:left:center,:rightの指定例です。 plot_titlevspanはどの位置に配置されるか分かりやすくするため0.5 と極端な値(図の上半分)で設定しています。

using Plots
using TikzPictures
gr()
default(fontfamily="ipag", size=(300, 600), plot_titlevspan=0.5)

plts_lcr = [plot(sin, plot_title=pt, plot_titlelocation=loc)
            for (pt, loc)
                in zip([":left", ":center", ":right"],
                       [:left, :center, :right])]
pngnames = "plot_titlelocation_" .* ["left", "center", "right"] .* ".png"
for (plt, fname) in zip(plts_lcr, pngnames)
    savefig(plt, fname)
end

tp_lcr = TikzPicture(
"""
\\node (left) {\\includegraphics[width=5cm]{$(pngnames[1])}};
\\node[anchor=west] (center) at (left.east) {\\includegraphics[width=5cm]{$(pngnames[2])}};
\\node[anchor=west] (right) at (center.east) {\\includegraphics[width=5cm]{$(pngnames[3])}};
"""
, preamble="""
  \\usepackage{luatexja}
  \\usepackage{graphicx}
  """
)

save(SVG("plot_titlelocation_lcr"), tp_lcr)
run(`inkscape -w 768 -o plot_titlelocation_lcr.png plot_titlelocation_lcr.svg`)

次は,座標で指定します。plot_titleの表示範囲の四隅に配置します。 何も工夫しない例です。

using Plots
using TikzPictures
gr()
default(fontfamily="ipag", size=(400, 300), plot_titlevspan=0.5)
座標s = [(0, 1), (1, 1), (0, 0), (1, 0)]
plts = [plot(sin, plot_title=string(座標), plot_titlelocation=座標) for 座標 in 座標s]
pngnames = ["plot_titlelocation_$(座標[1])_$(座標[2]).png" for 座標 in 座標s]
for (plt, pngname) in zip(plts, pngnames)
   savefig(plt, pngname) 
end

tp_01 = TikzPicture(
"""
\\node (01) {\\includegraphics[width=6cm]{$(pngnames[1])}};
\\node[anchor=west] (11) at (01.east) {\\includegraphics[width=6cm]{$(pngnames[2])}};
\\node[anchor=north] (00) at (01.south) {\\includegraphics[width=6cm]{$(pngnames[3])}};
\\node[anchor=north] (10) at (11.south) {\\includegraphics[width=6cm]{$(pngnames[4])}};
"""
, preamble="""
  \\usepackage{luatexja}
  \\usepackage{graphicx}
  """
)
save(SVG("plot_titlelocation_01"), tp_01)
run(`inkscape -w 768 -o plot_titlelocation_01.png plot_titlelocation_01.svg`)

デフォルトではタイトルの基準位置は中央なので文字が見切れます。

次のようにアラインメントを調整するとうまくいきます。

using Plots
using TikzPictures
gr()
default(fontfamily="ipag", size=(400, 300), plot_titlevspan=0.5)
vs = [:top, :top, :bottom, :bottom]
hs = [:left, :right, :left, :right]

座標s = [(0, 1), (1, 1), (0, 0), (1, 0)]
plts_fix = [plot(sin, plot_title=string(座標), plot_titlelocation=座標,
                 plot_titlefontvalign=v, plot_titlefonthalign=h)
            for (座標, v, h) in zip(座標s, vs, hs)]
pngnames_fix = ["plot_titlelocation_$(座標[1])_$(座標[2])_fix.png" for 座標 in 座標s]
for (plt, pngname) in zip(plts_fix, pngnames_fix)
   savefig(plt, pngname) 
end

tp_01_fix = TikzPicture(
"""
\\node (01) {\\includegraphics[width=6cm]{$(pngnames_fix[1])}};
\\node[anchor=west] (11) at (01.east) {\\includegraphics[width=6cm]{$(pngnames_fix[2])}};
\\node[anchor=north] (00) at (01.south) {\\includegraphics[width=6cm]{$(pngnames_fix[3])}};
\\node[anchor=north] (10) at (11.south) {\\includegraphics[width=6cm]{$(pngnames_fix[4])}};
"""
, preamble="""
  \\usepackage{luatexja}
  \\usepackage{graphicx}
  """
)
save(SVG("plot_titlelocation_01_fix"), tp_01_fix)
run(`inkscape -w 768 -o plot_titlelocation_01_fix.png plot_titlelocation_01_fix.svg`)

座標はマイナスの値も設定可能なので,うまくやれば図の下側に全体のタイトルを設定する ことも可能です。

using Plots
gr()
default(plot_titlevspan=0.05)
plot(plot(sin), plot(cos); plot_title="Bottom Title", bottom_margin=(20, :pt),
     plot_titlelocation=(0.5, -18.0), plot_titlevalign=:bottom)
savefig("plot_titlelocation_bt.png")

bottom_marginsubplotの下側のマージンで,図の下側に空白を作ってそこに収まるように y座標の位置をマイナスで設定します。

予想ではy座標は-19だと思ったのですが,-18が一番良さそうでした。この辺りは論理的な値ではなく 試行錯誤が必要でしょう。

まとめ

今回は予想外に調査に時間がかかりました。 Plots.jl(GR Backend)はまだまだ知らないバッドノウハウがありそうです。

説明もしていないのにしれっと使っているアトリビュートも増えてきましたが,そのうち説明する予定です。 自分が忘れた時のためにも。