Provide a reproducible scientific report and document generation pipeline, realizing automation from code → execution → documentation.
When to Use
- When creating a reproducible scientific document with Quarto
- When building a multi-chapter document with Jupyter Book
- When automating parametric execution with Papermill
- When converting notebooks to various formats with nbconvert
- When automatically generating analysis reports in CI/CD
- When repeatedly executing analyses with multiple parameter sets
Quick Start
1. Quarto Scientific Document Template
import os
def generate_quarto_document(title="Scientific Analysis Report",
author="SATORI",
format_type="html",
output_dir="quarto_project"):
"""
Quarto 科学文書テンプレート生成。
Parameters:
title: str — ドキュメントタイトル
author: str — 著者名
format_type: str — "html" / "pdf" / "docx" / "revealjs"
output_dir: str — 出力ディレクトリ
"""
os.makedirs(output_dir, exist_ok=True)
# _quarto.yml
quarto_config = f"""project:
type: default
output-dir: _output
format:
{format_type}:
toc: true
toc-depth: 3
number-sections: true
code-fold: true
code-tools: true
theme: cosmo
execute:
echo: true
warning: false
cache: true
bibliography: references.bib
csl: nature.csl
"""
# メインドキュメント
main_qmd = f"""---
title: "{title}"
author: "{author}"
date: today
format:
{format_type}:
code-fold: true
code-tools: true
jupyter: python3
---
## はじめに
このレポートは SATORI スキルを用いた再現可能な科学解析文書です。
```{{python}}
#| label: setup
#| echo: false
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
# パラメータ (Papermill 互換)
n_samples = 1000
random_seed = 42
Data Overview
#| label: data-summary
#| tbl-cap: "データセット概要"
np.random.seed(random_seed)
df = pd.DataFrame({{
"x": np.random.randn(n_samples),
"y": np.random.randn(n_samples),
"group": np.random.choice(["A", "B", "C"], n_samples)
}})
df.describe()
Visualization
#| label: fig-scatter
#| fig-cap: "散布図"
fig, ax = plt.subplots(figsize=(8, 6))
for g, sub in df.groupby("group"):
ax.scatter(sub["x"], sub["y"], label=g, alpha=0.6, s=20)
ax.legend()
ax.set_xlabel("X")
ax.set_ylabel("Y")
plt.show()
Conclusion
Describe the summary of the analysis results.
ToolUniverse Integration
| TU Key | Tool Name | Integration Details |
|---|---|---|
biotools |
bio.tools | Reproducible reporting tool search |
References
"""
# references.bib (空テンプレート)
bib_template = """@article{example2024,
title={Example Reference}, author={Author, A.}, journal={Journal}, year={2024} } """
with open(os.path.join(output_dir, "_quarto.yml"), "w") as f:
f.write(quarto_config)
with open(os.path.join(output_dir, "report.qmd"), "w") as f:
f.write(main_qmd)
with open(os.path.join(output_dir, "references.bib"), "w") as f:
f.write(bib_template)
print(f"Quarto project → {output_dir}/")
print(f" Build: cd {output_dir} && quarto render report.qmd")
return output_dir
## 2. Papermill パラメトリック実行
```python
def papermill_parametric_run(template_notebook, output_dir,
parameter_sets, kernel="python3"):
"""
Papermill パラメトリック実行 — 複数パラメータセットで自動実行。
Parameters:
template_notebook: str — テンプレートノートブックパス
output_dir: str — 出力ディレクトリ
parameter_sets: list[dict] — パラメータセットのリスト
kernel: str — カーネル名
"""
import papermill as pm
os.makedirs(output_dir, exist_ok=True)
results = []
for i, params in enumerate(parameter_sets):
output_path = os.path.join(output_dir, f"run_{i:03d}.ipynb")
try:
pm.execute_notebook(
template_notebook,
output_path,
parameters=params,
kernel_name=kernel)
results.append({
"run": i, "params": params,
"output": output_path, "status": "success"})
except Exception as e:
results.append({
"run": i, "params": params,
"output": output_path, "status": f"error: {str(e)}"})
import pandas as pd
results_df = pd.DataFrame(results)
n_success = (results_df["status"] == "success").sum()
print(f"Papermill: {n_success}/{len(parameter_sets)} runs succeeded")
return results_df
3. Jupyter Book Multi-Chapter Structure
def generate_jupyter_book(title="Scientific Analysis Book",
chapters=None,
output_dir="jupyter_book"):
"""
Jupyter Book プロジェクトテンプレート生成。
Parameters:
title: str — 書籍タイトル
chapters: list[dict] | None — 章情報 [{"title": ..., "file": ...}]
output_dir: str — 出力ディレクトリ
"""
os.makedirs(output_dir, exist_ok=True)
if chapters is None:
chapters = [
{"title": "Introduction", "file": "intro"},
{"title": "Data Loading", "file": "ch01_data"},
{"title": "Exploratory Analysis", "file": "ch02_eda"},
{"title": "Modeling", "file": "ch03_model"},
{"title": "Results", "file": "ch04_results"},
]
# _config.yml
config = f"""title: "{title}"
author: SATORI
execute:
execute_notebooks: auto
timeout: 600
repository:
url: ""
launch_buttons:
binderhub_url: ""
sphinx:
extra_extensions:
- sphinx_proof
"""
# _toc.yml
toc_entries = "\n".join(
[f" - file: {ch['file']}" for ch in chapters])
toc = f"""format: jb-book
root: intro
chapters:
{toc_entries}
"""
with open(os.path.join(output_dir, "_config.yml"), "w") as f:
f.write(config)
with open(os.path.join(output_dir, "_toc.yml"), "w") as f:
f.write(toc)
# 各章テンプレート
for ch in chapters:
filepath = os.path.join(output_dir, f"{ch['file']}.md")
if not os.path.exists(filepath):
content = f"# {ch['title']}\n\nThis chapter covers {ch['title'].lower()}.\n"
with open(filepath, "w") as f:
f.write(content)
print(f"Jupyter Book → {output_dir}/")
print(f" Build: jupyter-book build {output_dir}")
return output_dir
4. nbconvert Automatic Conversion
def batch_convert_notebooks(notebook_dir, output_format="html",
output_dir=None, execute=True):
"""
ノートブック一括変換。
Parameters:
notebook_dir: str — ノートブックディレクトリ
output_format: str — "html" / "pdf" / "markdown" / "script"
output_dir: str | None — 出力先 (None=同ディレクトリ)
execute: bool — 実行後に変換
"""
import subprocess
import glob
notebooks = sorted(glob.glob(os.path.join(notebook_dir, "*.ipynb")))
if output_dir:
os.makedirs(output_dir, exist_ok=True)
results = []
for nb_path in notebooks:
cmd = ["jupyter", "nbconvert", f"--to={output_format}"]
if execute:
cmd.append("--execute")
if output_dir:
cmd.extend(["--output-dir", output_dir])
cmd.append(nb_path)
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
results.append({"notebook": nb_path, "status": "success"})
except subprocess.CalledProcessError as e:
results.append({"notebook": nb_path, "status": f"error: {e.stderr[:100]}"})
import pandas as pd
results_df = pd.DataFrame(results)
n_ok = (results_df["status"] == "success").sum()
print(f"nbconvert ({output_format}): {n_ok}/{len(notebooks)} converted")
return results_df
Pipeline Integration
[解析完了] → reproducible-reporting → presentation-design
(レポート自動生成) (プレゼン作成)
│ ↓
interactive-dashboard academic-writing
(ダッシュボード) (論文執筆)
Pipeline Output
| File | Description | Next Skill |
|---|---|---|
quarto_project/ |
Quarto Project | → quarto render |
papermill_runs/ |
Parametric execution results | → Aggregation |
jupyter_book/ |
Jupyter Book Project | → jb build |