筆者(物性物理系M2)が修論を書くのに使った小ネタをテンプレとしてメモしておきます.
LaTeX
環境はpLaTeX,\documentclass[a4paper,10pt]{jsarticle}
とします.
図
\usepackage[dviout]{graphicx}
\usepackage{here} %[H] オプションを使用する場合
図の挿入
\begin{figure}[ht]
%オプション h:その場, t:ページ上端, b:ページ下端, p:専用ページを作成
% H:その場で強制出力
\centering
\includegraphics[keepaspectratio, width=0.8\linewidth]{fig1.png}
%オプション keepaspectratio:アス比を固定, width,height:サイズ指定
% 0.8\linewidthなど紙幅との比や 8cmなど単位付き長さでの指定
\caption{キャプション}
\label{fig:1} %相互参照用のラベル
\end{figure}
昔はTeXで画像を扱うならepsと相場が決まっていましたが,今はPDFが一番速いです.その他の場合でもdvipdfmxでPDFに変換されるのでPNGやJPEGならそのまま使って問題ありません.
http://www.yamamo10.jp/~yamamoto/comp/latex/make_doc/insert_fig/index.php#CONTEMPORARY
\includegraphics...
の行を増やせば並ぶだけ適当に並べてくれますが,こちらでちゃんとコントロールして2カラムにしたい場合等は
\begin{figure}[ht]
\begin{tabular}{cc}
\begin{minipage}[t]{0.45\hsize}
\centering
\includegraphics[keepaspectratio, width=\linewidth]{fig2.png}
\caption{キャプション1}
\label{fig:2}
\end{minipage} &
\begin{minipage}[t]{0.45\hsize}
\centering
\includegraphics[keepaspectratio, width=\linewidth]{fig3.png}
\caption{キャプション2}
\label{fig:3}
\end{minipage}
\end{tabular}
\end{figure}
のようにtabular環境を使います.
図に文字を回り込ませたいときはwrapfigure環境を使います.
abstructなどページ制限があるときなんかに便利.
普通のfigureと混ぜて使うと出力される順番がおかしくなったりするので注意が必要です.
オプション等の詳細は次を参照. http://www.yamamo10.jp/~yamamoto/comp/latex/make_doc/insert_fig/index.php#WRAPFIG
\begin{wrapfigure}{R}{0.5\hsize}
\centering
\includegraphics[keepaspectratio, width=\linewidth]{fig4.png}
\caption{キャプション3}
\label{fig:4}
\end{wrapfigure}
表
表です.罫線を全部引いたりするとダサいのでほどほどにしておきます.
\begin{table}[ht]
\centering
\caption{キャプション}
\begin{tabular}{c|ccc}
\hline
X & A & B & C\\
\hline \hline
1 & a & b & c \\
2 & s & t & u \\
3 & p & q & r \\
\hline
\end{tabular}
\label{tab:1}
\end{table}
{c|ccc}
のところは項目数と左右中央寄せ(l,r,c),縦罫線の設定です.
横罫線は\hline
で引きます.
相互参照
図表や数式中に\label{<適当な文字列>}
を入れておくと\ref{<その文字列>}
で図表番号を出力できます.執筆中に順序を入れ替えたりしても問題ないよう,手でベタ打ちするのではなく相互参照を使いましょう.
そのラベルが図なのか表なのか数式なのかは環境から自動で判断してくれますが,ユーザー側が判別しやすいようにfigやtabなどをprefixにつけておくと良いです.
なお,1度目のタイプセットでlabelの位置やら番号やらを書き出して,それをrefで参照することになるので2回以上のタイプセットが必要になります.目次や数字が入ることでページ数が変化することもありうるので万全を期すならば3回タイプセットしておくと安全です1.
図表番号を章立てにする
図表番号はjsarticleでは通し番号が付けられますが,sectionごとにリセットする場合は次のようにします.
\makeatletter
% sectionが変わるごとにfigureカウンタをリセット
\@addtoreset{figure}{section}
% 図番号の出力を「<章番号>.<図番号>」にする
\renewcommand{\thefigure}{\thesection.\arabic{figure}}
%
\@addtoreset{table}{section}
\renewcommand{\thetable}{\thesection.\arabic{table}}
\makeatother
参考: [LaTeX] 図表数式番号を通し番号にする・章ごとに分ける
参考文献の参照
参考文献管理はthebibliography環境,またはBibTeXを使うのが一般的.
thebibliography環境を使用する場合は
\usepackage{cite}
\begin{thebibliography}{99}
\bibitem{label1} hogehoge.
\bibitem{label2} fugafuga.
\end{thebibliography}
のようにして\cite{<ラベル名>}
で参照します.
\cite{label1,label2}
のように2つ以上並べたり\cite[pp12--34]{label1}
のようにページ数などを付記することが可能.
PDFにハイパーリンクを埋め込む
hyperref パッケージを使用すると相互参照にハイパーリンクが張られるので長いPDFを生成する場合,ワンクリックであっちこっち飛べて便利.
リンク文字列の色などの設定が可能.(デフォルトは赤とか緑なのでだいぶ見づらいと思う.)
\usepackage[dvipdfmx]{hyperref}
\usepackage{pxjahyper}
\hypersetup{
setpagesize=false,
bookmarksnumbered=true,
bookmarksopen=true,
colorlinks=true,
linkcolor=black,
citecolor=black,
}
参考: ハイパーリンク付きLaTeX文書
自作カウンタの参照
自分で定義したカウンタも相互参照することができます.
subscript
という名前のカウンタを作成し,呼ばれたときの挙動を定義しておきます.
\newcounter{subscript}
\setcounter{subscript}{0}
\renewcommand{\thesubscript}{\arabic{subscript}}
\newcommand{\subscript}{\refstepcounter{subscript}\thesubscript}
$$ T_{\subscript\label{sub:hoge}} = hoge $$
$$ T_{\subscript\label{sub:fuga}} = fuga $$
$$ T_{\subscript\label{sub:piyo}} = piyo $$
$T_{\ref{sub:fuga}}$ はfugaです.
SI単位
\usepackage{siunitx}
\si{kg.m/s^2}
のように使用.
°は\si{\degree}
,℃は\si{\degreeCelsius}
など
また、$\rm\LaTeX$ では \AA
でÅを印字できますが,これは「上リング付きA」2で,テキスト環境で使う想定のものなので\si
内で使用するとLaTeX Warning: Command \r invalid in math mode on input line XX
のような警告が出ます.
\angstrom
を使えば警告は出なくなります.
参考:
SI単位(国際単位系) - siunitxパッケージのマクロ
command \r invalid
化学式
上付き,下付きは数式環境でしか使えないが元素記号はローマン体なのでいちいち$\mathrm{H}_2\mathrm{O}$
のようにしなければいけなくてとても面倒.
パッケージを使用すると楽.
\usepackage[version=3]{mhchem}
\ce{SrTiO3}
,\ce{HSO4-}
などのようにすると自動で上付き,下付きなどを適用してくれます(1桁に限る.SO42-
等ではどこで区切るか決定できないので自分で上付き,下付きを設定する).
数式環境内でもローマン体にしてくれるし,テキスト環境でも上付き^
,下付き_
が効く.
$\mathrm{FeSe}_ {1-x} \mathrm{Te}_ {x}$のような変数が入った置換系などで
\ce{FeSe_{$1-x$}Te_{$x$}}
のようにすると1-x
のマイナスがハイフンになってしまうようなので$\ce{FeSe}_{1-x}\ce{Te}_x$
のようにしたほうが良い.
mhchemパッケージの環境で数式モードにして`-`を使うとマイナスじゃなくてハイフンになってる?
— ❄雪下❄ (@Mopepe51) January 5, 2021
上が
\ce{FeSe_{$1-x$}Te_{$x$}}
下が
$\mathrm{FeSe}_{1-x}\mathrm{Te}_{x}$ pic.twitter.com/FODodQtwHN
参考: TeXによる化学組版 - TeX Alchemist Online
マクロ内容の確認
このマクロ,どう動作するんだっけ?と気になることがあります.
$\rm\LaTeX$マクロであれなlatex.ltxを開いて検索すれば良いのですが再定義していたりパッケージで定義されたものだったりすると探すのも面倒です.
現環境での定義内容を確認するには,\show<トークン>
のようにすればログにマクロを展開した結果が出力されます.
例えば上で出てきた\AA
でやってみると
> \AA=macro:
->\r A.
l.11 \show\AA
?
のように出力されます.A
にアクセント記号\r
を付けたものであるということがわかります.
マクロ以外のトークン(例えば&
では>alignment tab character &.
など)でも可.
またレジスタ数値などを出力する\showthe
など色々なデバッグ用コマンドも用意されています(以下略. 参考: TeX プログラムのデバッグで絶望する前に知るべきこと (1) - マクロツイーター )
その他
- 「1から5まで」のように範囲を書くときは「~」
\sim
ではなくen-dash--
を使おう(~はニアリーイコールの記号). LaTeXで論文作成のいろいろ #ダッシュとハイフンの使い分け - 強制改行コマンド
\\
はオプション引数を取ります(改行の行間を指定する).
$\rm\LaTeX$ 標準の動作では空白や改行を挟んでも[……]
があればオプション引数と解釈されるため不用意に[1]
とか[p, H]
とかを強制改行直後に書くとエラーで停止する可能性があります.(なお、AMSMath系の環境(alignなど)ではこうならないように実装されています.)LaTeX における行区切りの \ とオプション引数
bibliographyを端折る
BibTeXを使わずに3参考文献を書く時は
\begin{thebibliography}{99}
\bibitem{Josephson} B. D. Josephson, Phys. Lett. 1, 251-253 (1962).
\end{thebibliography}
のようにすればよいのですが,このままだと特に書式のないテキストで
[1] B. D. Josephson, Phys. Lett. 1, 251-253 (1962).
のように書き出されます.
私の分野の書式にあわせようとすると
[1] B. D. Josephson, Phys. Lett. 1, 251-253 (1962).
のように雑誌名をイタリック,巻数をボールドにしたいのですが,いちいちB. D. Josephson, \textit{Phys. Lett.} \textbf{1}, 251-253 (1962).
と毎度書くのはもちろん,
\newcommand{\paper}[4]{#1 \textit{#2} \textbf{#3} #4}
とマクロを定義して\paper{B. D. Josephson,}{Phys. Lett.,}{1,}{251-253 (1962).}
とするのもカッコを書くのが面倒4だったので\def
を使ってもう少し入力数を減らしてみました.
$\rm\LaTeX$では基本的に\newcommand
を使うべきなのですが,\def
を使うと便利な場面もあります.
\def
特有の機能のうちにパターンマッチングが使えるというものがあり,
\def\paper#1;#2;#3;#4.{#1\textit{#2}\textbf{#3}#4.}
\paper B. D. Josephson,;Phys. Lett.,;1,;251-253 (1962).
のようにすると B. D. Josephson,
,Phys. Lett.,
,1,
,251-253 (1962)
がそれぞれ#1,#2,#3,#4 に格納され展開されます.便利ですね.
横着するためだけに($\rm\LaTeX$ではなく)$\rm\TeX$を書かないといけないのであまり真似しないほうが良いと思いますが.
Python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
あたりは前置きなく使用します.
グラフ
目標はこんな感じのグラフです.
[出典 : E. Snider, et al. "Room-temperature superconductivity in a carbonaceous sulfur hydride." Nature 586, 373–377 (2020).]
目盛り設定
デフォルトの設定だと目盛りが外向き・補助目盛り無しなので表示させます.
plt.rcParams['font.family'] ='sans-serif' #フォント選択
plt.rcParams['font.size'] = 12 #フォントの大きさ
plt.rcParams["xtick.minor.visible"] = True #補助目盛りの追加
plt.rcParams["ytick.minor.visible"] = True
plt.gca().xaxis.set_tick_params(which='both', direction='in',bottom=True, top=True)
plt.gca().yaxis.set_tick_params(which='both', direction='in',left=True, right=True)
その他の設定項目.備忘録 Matplotlibのグラフの見た目の調整
マーカーを白抜きにする
markerfacecolor
を"None"
にするとマーカーが枠線だけになる."white"
だと後ろが透過しない.
markeredgecolor
を設定すれば線と別の色で描画もできる.
散布図plt.scatter
の場合はそれぞれ引数名がedgecolors
,facecolor
になる.
plt.plot([0, 1, 2], [1, 0, 1], marker="o", markersize=10)
plt.plot([0, 1, 2], [0, 1, 2], marker="s", markerfacecolor="None", markersize=10)
plt.plot([0, 1, 2], [2, 1, 0], marker="^", markeredgecolor="C3", markerfacecolor="white", markersize=10)
plt.scatter([0, 1, 2], [0, 2, 1], marker="v", edgecolors="C4", facecolor='None', s=100)
matplotlib グラフ作成Tips (3) 白抜き記号と矢印
凡例をグラフ外部に表示する
plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left", ncol=2)
matplotlibの凡例(legend)レイアウト関連メモ
重ねてプロット
第2軸と重ねて書く場合.
プロット色に合わせて軸の色も変えようとすると結構面倒です.
fig = plt.figure()
ax1 = fig.subplots()
plt.rcParams['font.family'] ='sans-serif'
plt.rcParams['font.size'] = 10
plt.rcParams["xtick.minor.visible"] = True
plt.rcParams["ytick.minor.visible"] = True
ax1.xaxis.set_tick_params(which='both', direction='in',bottom=True, top=True)
# 1軸 目盛色の変更
ax1.yaxis.set_tick_params(which='both', direction='in',left=True, color="C0")
# 目盛ラベル色の変更
ax1.tick_params(axis="y", colors="C0")
ax2 = ax1.twinx()
# 2軸 目盛色の変更
ax2.tick_params(axis="y", which='both', direction='in', right=True, color="C1")
# 目盛ラベル色の変更
ax2.tick_params(axis='y', colors="C1")
# 枠線色の変更
ax2.spines['left'].set_color("C0") # ax2のほうが"上"にあるのでax2を変える
ax2.spines['right'].set_color("C1")
ax1.plot([0, 1, 2], [1, 0, 1], marker="o", markersize=10, color="C0")
ax2.plot([0, 1, 2], [0, 1, 2], marker="s", markerfacecolor="None", markersize=10, color="C1")
plt.show()
[Python]matplotlibで左右に2つの軸があるグラフを書く方法
時系列データを複数縦に並べてプロットしたい,しかもそのうち2つは2軸で重ねて描画したいなんていうときはこんな感じ.
fig = plt.figure(figsize=(8, 6))
plt.rcParams['font.family'] ='sans-serif' #フォント選択
plt.rcParams['font.size'] = 10 #フォントの大きさ
plt.rcParams["xtick.minor.visible"] = True #補助目盛りの追加
plt.rcParams["ytick.minor.visible"] = True
#plt.gca().xaxis.set_tick_params(which='both', direction='in',bottom=True, top=True)
#plt.gca().yaxis.set_tick_params(which='both', direction='in',left=True, right=True)
# 画面を4x1に分割
ax1 = plt.subplot2grid((4,1), (0,0)) # (0,0) の画面に描画
ax2 = plt.subplot2grid((4,1), (1,0)) # (1,0) の画面に描画
ax3 = plt.subplot2grid((4,1), (2,0), rowspan=2) # (2,0) から2つ縦にぶち抜いた画面に描画
ax4 = ax3.twinx() # ax3に重ねて描画
ax1.xaxis.set_tick_params(which='both', direction='in', bottom=True, top=True, labelbottom=False)
ax1.yaxis.set_tick_params(which='both', direction='in', left=True, right=True)
ax2.xaxis.set_tick_params(which='both', direction='in', bottom=True, top=True, labelbottom=False)
ax2.yaxis.set_tick_params(which='both', direction='in', left=True, right=True)
ax3.xaxis.set_tick_params(which='both', direction='in', bottom=True, top=True)
ax3.yaxis.set_tick_params(which='both', direction='in', color="C2")
ax4.spines['left'].set_color("C2")
ax4.yaxis.set_tick_params(which='both', direction='in', color="C3")
ax4.tick_params(axis='y', colors="C3")
ax4.spines['right'].set_color("C3")
ax1.plot([0, 1, 2], [1, 0, 1], marker="o", color="C0", markersize=10, label="A")
ax1.set_ylabel("A")
ax2.plot([0, 1, 2], [0, 1, 2], marker="s", color="C1", markerfacecolor="None", markersize=10, label="B")
ax2.set_ylabel("B")
ax3.plot([0, 1, 2], [2, 1, 0], marker="^", color="C2", markerfacecolor="white", markersize=10, label="C")
ax3.tick_params(axis='y', colors="C2")
ax3.set_xlabel("x")
ax3.set_ylabel("C", color="C2")
ax4.scatter([0, 1, 2], [0, 2, 1], marker="v", edgecolors="C3", facecolor='None', s=100, label="D")
ax4.set_ylabel("D", color="C3")
ax4.set_ylim(-1,3)
plt.xlim(-0.2, 2.2)
ax1.set_xlim(*plt.xlim()) #ax1,ax2のx軸をあわせる
ax2.set_xlim(*plt.xlim())
plt.show()
2軸にするのをx軸にしたい場合はtwinx()
をtwiny()
にします.
平滑化
ノイズを移動平均で平滑化する場合はnp.convolveが使える.
def gauss(x, a=1, mu=0, sigma=1):
return a * np.exp(-(x - mu)**2 / (2*sigma**2))
x = np.array(sorted([np.random.rand()*6-3 for _ in range(500)]))
y = np.array([gauss(i)+np.random.randn()*0.05for i in x])
width = 7
plt.plot(x,y)
plt.plot(x, np.convolve(y, np.ones(width)/width, mode='same'), color="red")
時系列データの場合,未来のデータを見るわけにはいかないのでずらします.
plt.plot(x,y)
plt.plot(x[width-1:], np.convolve(y, np.ones(width)/width, mode='valid'), color="red")
このパターンはPandasのrolling関数でも書けます.
plt.plot(x, y)
plt.plot(x, pd.Series(y).rolling(11).mean(), color="red")
Pandasだと同様に指数平滑移動平均もできる.
plt.plot(x, y)
plt.plot(x, pd.Series(y).ewm(span=width).mean(), color="red")
波形データならFFTするとか他にも色々ありますね.時系列及び波形データの平滑化3手法(smoothing)
曲線フィット
最小二乗法で曲線のパラメーターフィットを行います.
from scipy.optimize import curve_fit
def gauss(x, a=1, mu=0, sigma=1):
return a * np.exp(-(x - mu)**2 / (2*sigma**2))
x = np.array(sorted([np.random.rand()*6-3 for _ in range(500)]))
y = np.array([gauss(i, 1, 0, 1)+np.random.randn()*0.05for i in x])
popt, pcov = curve_fit(gauss, x, y)
curve_fit
関数に「第1引数にx,残りがパラメーターである関数」,x,y を与えると最適パラメーターと共分散行列が返されます.
共分散行列の対角成分はそれぞれのパラメーターの分散なので平方根を取れば標準偏差が得られます.
plt.plot(x,y)
plt.plot(np.linspace(-3,3,1000), gauss(np.linspace(-3,3,1000), *popt))
plt.show()
perr = np.sqrt(np.diag(pcov))
for i in range(3):
print(f"{popt[i]:.3f}±{perr[i]:.3f}")
# 1.012±0.005
# 0.004±0.006
# 0.996±0.006
パラメーターの初期値や範囲を与えてやればそれなりに複雑な関数もフィットできます.
def two_gauss(x, a1, m1, s1, a2, m2, s2, e):
return gauss(x, a1, m1, s1) + gauss(x, a2, m2, s2) + e
y2 = np.array([two_gauss(i, 1.5, -1, 0.5, 1.2, 0.5, 0.8, 0.1) + np.random.rand()*0.1 for i in x])
p,q = curve_fit(two_gauss, x, y2, [2, -1.5, 0.5, 1.5, 1, 1, 0],
bounds=((0, -np.inf, 0, 0, -np.inf, 0, 0), (np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf)) )
plt.plot(x,y2)
plt.plot(x, two_gauss(x, *p))
plt.plot(x, gauss(x, p[0], p[1], p[2])+p[6])
plt.plot(x, gauss(x, p[3], p[4], p[5])+p[6])
曲線で補間する
適切な関数で表せればそれで良いですが,それができず適当な曲線でつなぎたいだけという場合はスプラインでつないでしまいます.
from scipy.interpolate import make_interp_spline, BSpline
x = [0,1,2,3,4,5]
y = [0,3,5,6,6,5]
smooth = make_interp_spline(x, y)
plt.scatter(x, y)
plt.plot(np.linspace(0,5,100), smooth(np.linspace(0,5,100)), color="black", linewidth=0.5)
make_interp_spline(x, y)
でx,yを制御点とするB-スプライン曲線を表す関数ができるので適当なxの値でプロットすれば曲線が引けます.
他の曲線による補間もいろいろあります. Scipy.interpolate を使った様々な補間法
DataFrameの操作
温度を変えながら抵抗を測ってR-Tプロットするというとき,降温時は速度を固定していないので邪魔です.
そんなときに昇温期間だけにトリムするコード.
df = pd.read_csv("data.csv")
df = df.iloc[1:, :] #2行目の単位の行があるとfloatにできないので削除
df = df.astype('float64')
cond = df.index>=df["Temperature"].idxmin()
plt.plot(df[cond]["Temperature"], df[cond]["Resistance"])
トリム条件は&
や|
で繋げられる.(真偽値のarrayの演算なのでbool演算ではなくビット演算)
# 変分はdiffで取れる
cond = (df.index>=df["Temperature"].idxmin()) & (df["Temperature"].diff() > 0.02)
cond = (df.index>=df["Temperature"].idxmin()) | ((df["Time"] > 100) & (df["Time"]<2000))
水平部分の抽出
こんな時系列データ(ノイズ±0.01くらい乗ってる)から水平部分のyの値のset(これだと{10, 15, …, 37, 38, 38.5, 39})を取得するの、どうするのが早いかな pic.twitter.com/MX7oSuIeaU
— ❄雪下❄ (@ykstprg) January 6, 2021
水平部分のyの値を取ってきたい.
width = 0.01
z = plt.hist(y, bins=np.arange(0, 40, width)-width/2)
plt.ylim(0,50)
threshold=300
print((z[1][:-1]+width/2)[z[0]>threshold])
# [ 2.5 5. 10. 15. 20. 25. 30. 33. 35. 35.5 36. 36.5 37. 37.5]
width
とthreshold
を適当に変えるといい感じになる.
-
https://texwiki.texjp.org/?LaTeX%E5%85%A5%E9%96%80%2F%E7%9B%B8%E4%BA%92%E5%8F%82%E7%85%A7%E3%81%A8%E3%83%AA%E3%83%B3%E3%82%AF#h84e81eb ↩
-
ノルウェー語などで使用される記号.ドイツ語なんかで言うウムラウト付き文字のようなもの.もっと雑に言えば日本語でいう半濁音みたいな? ↩
-
過去のパワポなどから持ってくるものが多いので
B. D. Josephson, Phys. Lett. 1, 251-253 (1962).
というような文字列を持ってくるのが一番楽だったんですよね. ↩ -
ブレースってShiftが必要だしキーボードの端にあるしで入力しづらくて好きではないんですよね. ↩