Pythonでborbを使ってPDFにMatplotlibのグラフを統合する

Portable Document Format (PDF) は、WYSIWYG (What You See is What You Get) フォーマットではありません。

プラットフォームに依存せず、基盤となるオペレーティングシステムやレンダリングエンジンから独立するように開発されました。

これを実現するために、PDFはプログラミング言語のようなもので操作できるように構築されており、結果を得るためには一連の命令と操作に依存することになります。

実際、PDFはスクリプト言語であるPostScriptをベースにしています。

PostScriptは、デバイスに依存しない最初のページ記述言語でした。

このガイドでは、PDF文書の読み取り、操作、生成に特化したPythonライブラリであるborbを使用します。

borbは、低レベルモデル(正確な座標とレイアウトにアクセスできる)と高レベルモデル(余白や位置などの正確な計算をレイアウトマネージャーに委ねることができる)の両方を提供します。

Matplotlib は、データの可視化を始めるエンジニアの全世代に刺激を与えたデータ可視化ライブラリであり、Seaborn のような他の多くの人気ライブラリの背後にあるエンジンでもあります。

PDF文書がレポート作成によく使われる(グラフを含むことが多い)ことを考慮して、borbを使ってPDF文書にMatplotlibのチャートを統合する方法を見ていきます。

borb (とMatplotlib)のインストール

borbはGitHubのソースからダウンロードするか、pip経由でインストールすることができます。

$ pip install borb


Matplotlib は pip 経由でインストールできます。

$ pip install matplotlib


borb による Matplotlib のグラフの PDF 文書への統合

円グラフのようなチャートを作る前に、色スペクトルの中から均等に配分された N 色を生成する小さなユーティリティ関数を書きます。

これはプロットを作成し、各セクションに色をつける必要があるときに役立ちます。

from borb.pdf.canvas.color.color import HSVColor, HexColor
from decimal import Decimal
import typing


def create_n_colors(n: int) -> typing.List[str]:
  # The base color is borb-blue
  base_hsv_color: HSVColor = HSVColor.from_rgb(HexColor("56cbf9"))
  # This array comprehension creates n HSVColor objects, transforms then to RGB, and then returns their hex string
  return [HSVColor(base_hsv_color.hue + Decimal(x / 360), Decimal(1), Decimal(1)).to_rgb().to_hex_string() for x in range(0, 360, int(360/n))]


注:HSL (hue, saturation, lightness) と HSV/HSB (hue, saturation, value/hue, saturation, brightness) は RGB カラーモデルの代替表現である。

HSLとHSV/HSBは、1970年代にコンピュータグラフィックス研究者によって、人間の視覚が色を作る属性を認識する方法により近い形で設計されました。

これらのモデルでは、各色相の色は、下は黒から上は白までの中間色の中心軸を中心に、放射状にスライスして配置されています。

出典 ウィキメディア (CC BY-SA 3.0) ライセンス
この表現方法を Color に用いる利点は、色スペクトルを簡単に等分できることです。

これで create_pie_chart() 関数 (または他のタイプのプロット用の関数) を定義することができます。

# New import(s)
import matplotlib.pyplot as plt
from borb.pdf.canvas.layout.image.chart import Chart
from borb.pdf.canvas.layout.layout_element import Alignment


def create_piechart(labels: typing.List[str], data: typing.List[float]):


# Symetric figure to ensure equal aspect ratio
  fig1, ax1 = plt.subplots(figsize=(4, 4))
  ax1.pie(
    data,
    explode=[0 for _ in range(0, len(labels))],
    labels=labels,
    autopct="%1.1f%%",
    shadow=True,
    startangle=90,
    colors=create_n_colors(len(labels)),
  )


ax1.axis("equal")  # Equal aspect ratio ensures that pie is drawn as a circle.


return Chart(
    plt.gcf(),
    width=Decimal(200),
    height=Decimal(200),
    horizontal_alignment=Alignment.CENTERED,
  )


ここでは、Matplotlib を使って、 pie() 関数により円グラフを作成します。

>
円グラフの作成についてもっと知りたい方は、Matplotlib 円グラフ作成ガイドをご覧ください! &gt.
をご覧ください。

PyPlotインスタンスのgcf()関数は、現在の図を返します (get current figure)。

この図をPDFドキュメントに埋め込むには、Chartコンストラクタに、width,height,horizontal_alignment` といったカスタマイズした引数と共に指定します。

これだけです! Matplotlib の図形を Chart コンストラクタに渡すだけです。

Matplotlib のグラフを PDF 文書に追加する

さて、いよいよ基本的な PDF Document を作成し、それにコンテンツを追加してみましょう。

# New import(s)
from borb.pdf.document import Document
from borb.pdf.page.page import Page
from borb.pdf.pdf import PDF
from borb.pdf.canvas.layout.page_layout.multi_column_layout import MultiColumnLayout
from borb.pdf.canvas.layout.page_layout.page_layout import PageLayout
from borb.pdf.canvas.layout.text.paragraph import Paragraph


# Create empty Document
pdf = Document()


# Create empty Page
page = Page()


# Add Page to Document
pdf.append_page(page)


# Create PageLayout
layout: PageLayout = MultiColumnLayout(page)


# Write title
layout.add(Paragraph("About Lorem Ipsum", 
                     font_size=Decimal(20), 
                     font="Helvetica-Bold"))


この PDF では、テキストをよりスムーズにレイアウトするためにハイフネーションを使用します。

borbでのハイフネーションはとても簡単です。

# New import(s)
from borb.pdf.canvas.layout.hyphenation.hyphenation import Hyphenation


# Create hyphenation algorithm
hyphenation_algorithm: Hyphenation = Hyphenation("en-gb")


# Write paragraph
layout.add(Paragraph(
    """
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. 
    Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, 
    when an unknown printer took a galley of type and scrambled it to make a type specimen book. 
    It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. 
    It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, 
    and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    """, text_alignment=Alignment.JUSTIFIED, hyphenation=hyphenation_algorithm))


さて、先ほど宣言した関数を使って、円グラフを追加してみましょう。

# Write graph
layout.add(create_piechart(["Loren", "Ipsum", "Dolor"], 
                           [0.6, 0.3, 0.1]))


次に、さらに3つの Paragraph オブジェクトを書きます。

そのうちの1つは引用文のようなものです(ボーダーが横にあったり、フォントが違ったり)。

# Write paragraph
layout.add(Paragraph(
    """
    Contrary to popular belief, Lorem Ipsum is not simply random text. 
    It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. 
    Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, 
    consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, 
    discovered the undoubtable source.
    """, text_alignment=Alignment.JUSTIFIED, hyphenation=hyphenation_algorithm))


# Write paragraph
layout.add(Paragraph(
    """
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. 
    """, 
    font="Courier-Bold",
    text_alignment=Alignment.JUSTIFIED, 
    hyphenation=hyphenation_algorithm,
    border_color=HexColor("56cbf9"),
    border_width=Decimal(3),
    border_left=True,
    padding_left=Decimal(5),
    padding_bottom=Decimal(5),
))


# Write paragraph
layout.add(Paragraph(
    """
    Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" 
    (The Extremes of Good and Evil) by Cicero, written in 45 BC. 
    This book is a treatise on the theory of ethics, very popular during the Renaissance.
    """, text_alignment=Alignment.JUSTIFIED, hyphenation=hyphenation_algorithm))


別のプロットを追加してみましょう

# Write graph
layout.add(create_piechart(["Loren", "Ipsum", "Dolor", "Sit", "Amet"], 
                           [600, 30, 89, 100, 203]))


そしてもう一つ、コンテンツの Paragraph を追加します。

# Write paragraph
layout.add(Paragraph(
    """
    It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. 
    The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', 
    making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, 
    and a search for 'lorem ipsum' will uncover many web sites still in their infancy. 
    Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
    """, text_alignment=Alignment.JUSTIFIED, hyphenation=hyphenation_algorithm))


最後に、Document を格納します。

# Write to disk
with open("output.pdf", "wb") as pdf_file_handle:
  PDF.dumps(pdf_file_handle, pdf)


このコードを実行すると、次のようなPDF文書ができあがります。

結論

このガイドでは、borb を使って Matplotlib のグラフを PDF に統合する方法を学びました。

ここから先は無限大です! データ可視化でよりクリエイティブになればなるほど、あなたのPDFはより素敵なものになるはずです。

タイトルとURLをコピーしました