该存储库包含我们在撰写科学论文时发现有用/重要的工具、最佳实践、技巧和其他指南的列表。有些是风格问题(我们倾向于遵循《芝加哥风格手册》的指导方针),我们很清楚其他人喜欢以不同的方式做事,但我们无论如何都会列出它们以获得一致的指导。请随意适应、改变、忽略甚至挑战我们所写的一切!
排版是通过排列类型(即字母和符号)来组成文本。这主要是一个美学问题,但漂亮的排版使文档更容易阅读,更令人愉悦,帮助读者理解信息。
我们在下面列出了一些排版技巧和工具,可在您撰写文档时为您提供帮助。有些技巧是特定于 LaTeX 的,但其他技巧无论您使用什么都适用。
编写 LaTeX 文档时,在源文件中每行放置一个句子。写:
This is my first sentence.
This is the second one.
而不是:
This is my first sentence. This is the second one.
这样做的主要原因是源代码控制和协作:在查看提交的更改时,如果它们各自位于单独的行上,则更容易识别更改了哪些句子。因此,您的同事将能够更轻松地看到更改。
另一个好处是,当我们的 LaTeX 编译器仅给出行号时,您将能够更好地识别错误。
下面我们将提到两种大小写:
对所有章节、小节等标题使用标题格式。为了帮助您使用正确的单词大写,有一个方便的网站:capitalizemytitle.com。
有时,对象的名称(例如图、表、图形或算法)及其参考号被分成两行。例如,对象的名称可能位于一行,而参考号出现在下一行。
为了确保 LaTeX 将对象名称及其引用保留在同一行,可以在对象和引用之间使用字符~
。通过以这种方式使用波浪号字符~
,您可以避免尴尬的换行符并保持 LaTeX 文档中对象名称和引用编号的格式一致。
Figure~ ref { fig:example } displays that the project ...
为了确保您不会忘记使用波浪号字符,您可以通过创建自定义自动化命令来简化该过程。这是一个例子:
newcommand { refalg }[1]{Algorithm~ ref {# 1 }}
newcommand { refapp }[1]{Appendix~ ref {# 1 }}
newcommand { refchap }[1]{Chapter~ ref {# 1 }}
newcommand { refeq }[1]{Equation~ ref {# 1 }}
newcommand { reffig }[1]{Figure~ ref {# 1 }}
newcommand { refsec }[1]{Section~ ref {# 1 }}
newcommand { reftab }[1]{Table~ ref {# 1 }}
一旦定义了这些命令,就不必编写:
Figure~ ref { fig:example }
只需输入:
reffig {fig:example}
(完整示例)
booktabs 可以帮助您制作干净、美观的表格。
usepackage { booktabs }
% --
begin { table }
centering
begin { tabular }{lcc}
toprule
& multicolumn {2}{c}{Data} \ cmidrule (lr){2-3}
Name & Column 1 & Another column \
midrule
Some data & 10 & 95 \
Other data & 30 & 49 \
addlinespace
Different stuff & 99 & 12 \
bottomrule
end { tabular }
caption {My caption.}
label { tab-label }
end { table }
一般来说,避免在表格中使用垂直线。相反,如果您想对列进行分组,请在标题中使用cmidrule
进行分组。您还可以使用addlinespace
用间距替换水平线。
列标题应使用句子格式大写(请参阅http://www.chicagomanualofstyle.org/15/ch13/ch13_sec019.html)。
您可以在此处找到有关表格格式的更多建议:http://www.inf.ethz.ch/personal/markusp/teaching/guides/guide-tables.pdf。这是一个很好的 GIF,它说明了其中一些规则:
(完整示例)
使用 siunitx 包格式化所有数字、货币、单位等:
usepackage { siunitx }
% ---
This thing costs SI {123456}{ $ }.
There are num {987654} people in this room, SI {38}{ percent } of which are male.
您还可以使用它对数字进行四舍五入:
usepackage { siunitx }
% ---
sisetup {
round-mode = places,
round-precision = 3
} %
You can also round numbers, for example num {1.23456}.
最后,它可以帮助您更好地对齐表格中的数字:
usepackage { booktabs }
usepackage { siunitx }
% ---
begin { table }
centering
begin { tabular }{lS}
toprule
Name & {Value} \ % headers of S columns have to be in {}
midrule
Test & 2.3456 \
Blah & 34.2345 \
Foo & -6.7835 \
Bar & 5642.5 \
bottomrule
end { tabular }
caption {Numbers alignment with texttt { siunitx }.}
end { table }
(完整示例)
在编写方程时,以连贯一致的方式来编写变量、向量、矩阵等会很有帮助。它可以帮助读者识别你在说什么并记住每个符号的语义。
我们提出以下书写数学的规则:
$x$
)$mathbold{x}$
)$mathbold{X}$
)$X$
) mathbold
命令来自fixmath
软件包,类似于boldmath
或bm
,不同之处在于所有符号都为斜体,甚至是希腊字母(其他软件包不使用斜体希腊字母)。
向变量添加索引或指数时,请确保将它们添加到变量样式之外,即编写$mathbold{x}_i$
而不是$mathbold{x_i}$
。
因为我们经常引用变量,所以我们建议定义以下两个命令:
renewcommand { vec }[1]{ mathbold {#1}}
newcommand { mat }[1]{ mathbold {#1}}
然后,您可以在文档中使用$vec{x}$
和$mat{X}$
。如果您决定更改矩阵格式化方式,只需更改mat
命令,它将更新整个文档。
我们还建议为您最常使用的变量定义命令。例如,如果您经常使用vec{x}
和mat{X}
,请考虑定义以下命令:
newcommand { vx }{ vec {x}}
newcommand { vX }{ mat {X}}
然后,您可以编写更紧凑的方程: $vx^T vy = vZ$
。
请注意,您应该始终根据变量的类型来设置变量的样式。例如,向量vx
的第 $i$ 个元素是x_i
而不是vx_i
(它是一个数字)。类似地,如果您有一个矩阵vX
,则可以将其第 i列称为vx_i
(它是一个向量,因此以粗体显示),如果其元素x_{ij}
,则可以将其称为一列,而不是vX_i
和vX_{ij}
。
使用(...)
编写内联方程。您还可以使用$...$
,但它是一个 TeX 命令,会给出更晦涩的错误消息。
要在自己的行上编写中心方程,请不要使用$$...$$
(这是使用 LaTeX 的致命罪过之一)。它有效,但给出了错误的间距。使用begin{equation*}
或begin{align*}
代替。
(完整示例)
对于较长的文档,例如硕士或博士论文,在参考书目中提供回溯参考文献可能会很有用,以显示参考文献的引用位置。为此,只需将选项backref=page
添加到hyperref
包中即可:
usepackage [ backref=page ]{ hyperref }
您可以使用以下命令自定义反向引用的显示方式:
renewcommand *{ backref }[1]{}
renewcommand *{ backrefalt }[4]{{ footnotesize [ %
ifcase #1 Not cited. %
or Cited on page~#2 %
else Cited on pages #2 %
fi %
]}}
图表是任何论文的重要组成部分,因为它们可以向读者传达您的结果。您应该考虑每个图表上的信息告诉您的读者什么,并且有足够的信息来支持您的信息,而不是更多。例如,如果您想显示 2d 点中的模式(有两个分开的簇),则无需在轴上放置刻度和值(比例并不重要)?数字不宜太复杂。最好用几个图形来传达一两个消息(方法 A 比 B 更好,但收敛速度较慢),而不是用一个大而混乱的图形。
有些图是手工制作的,例如,为了解释系统或给出全局图景,而另一些图是数据驱动的,即说明一些数据。这些数据驱动的图形应该尽可能编写脚本:理想情况下,如果您的数据发生变化,您应该只需要运行一次脚本来更新您的图形,而无需任何其他干预(设置视图、缩放、保存/裁剪图形) , ETC)。同样,如果生成图形所需的数据需要花费数秒以上的时间才能生成,则您应该使用第一个脚本来计算和保存数据,并使用第二个脚本来绘制数据。这样,您在处理绘图时将节省大量时间:您不必在对图形进行每个小更改后等待查看其效果。
我们还建议将用于生成图形的命令保存在 LaTeX 文件中,例如作为图形上方的注释,尤其是在脚本需要参数的情况下。
documentclass { article }
usepackage { graphicx }
begin { document }
% python figure_example.py --save ../../examples/figure/figure.eps
begin { figure }
centering
includegraphics {figure.eps}
caption {Example of a sigmoid function}
end { figure }
end { document }
如果可能,所有图形的标签、轴等都应使用相同的字体。特别是,您不应该让一个图形具有大标签/刻度,而另一个图形具有较小的标签/刻度。实现此目的的一种解决方案是在生成图形的脚本中定义图形的大小,而不是在文档中重新调整图形的大小(例如,不要在 LaTeX 文档中将图形的宽度设置为textwidth
)。
为了获得一致的数字,我们建议使用辅助脚本,类似于我们的plot_utils.py
。使用此脚本,您只需调用figure_setup()
函数来定义所有尺寸,然后创建所需尺寸的图形并保存。
import argparse
import matplotlib . pyplot as plt
import numpy as np
import plot_utils as pu
def main ( args ):
x = np . linspace ( - 6 , 6 , 200 )
y = 1 / ( 1 + np . exp ( - x ))
pu . figure_setup ()
fig_size = pu . get_fig_size ( 10 , 5 )
fig = plt . figure ( figsize = fig_size )
ax = fig . add_subplot ( 111 )
ax . plot ( x , y , c = 'b' , lw = pu . plot_lw ())
ax . set_xlabel ( '$x$' )
ax . set_ylabel ( '$ \ sigma(x)$' )
ax . set_axisbelow ( True )
plt . grid ()
plt . tight_layout ()
if args . save :
pu . save_fig ( fig , args . save )
else :
plt . show ()
if __name__ == '__main__' :
parser = argparse . ArgumentParser ()
parser . add_argument ( '-s' , '--save' )
args = parser . parse_args ()
main ( args )
我们建议将所有数据保存为EPS
格式。这样,您就可以使用latex
和pdflatex
来生成文档,并享受美丽的矢量图形和文本。
截至 2015 年 9 月,在 Mac OS X 以及最新版本的 Python、Matplotlib 和 TeX Live 上,打印直接从 Matplotlib 保存为PDF
图形时会出现质量损失。打印在真纸上就变得清晰;亲自尝试一下。这是更喜欢将 Matplotlib 生成的图片保存在EPS
中的另一个原因。如果您确实只想保留图形的 PDF 版本,请使用epspdf
命令行工具——生成的 PDF 将比 Matplotlib 直接生成的 PDF 更好。
为了完整起见,请注意还有另一个 Matplotlib 后端 PGF,它可以产生稍微优越的结果。然而,截至 2015 年 9 月,生成的 PDF 的重量是使用默认后端和epspdf
获得的 PDF 的两倍。
Matplotlib,即使使用紧凑的布局功能,有时也会在边距中添加过多的空白。 pdfcrop
是一个漂亮的命令行工具,可将 PDF 裁剪为其最紧密的边界框。
如果绘图中有许多数据点,则生成的 EPS 文件可能会非常大。您可以将图形保存为 PNG 文件,但这会导致文本模糊。解决方案是对图形的部分进行栅格化,即告诉matplotlib
数据点必须在 EPS 文件中呈现为位图,而其余部分则采用矢量格式。
您可以将rasterized=True
关键字传递给matplotlib
中的大多数绘图函数。您还可以使用zorder
使用不同的图层,并告诉matplotlib
使用轴的set_rasterization_zorder()
方法对给定zorder
下面的所有图层进行栅格化。有关光栅化的示例,请参阅figure_rasterized_example.py 和 http://matplotlib.org/examples/misc/rasterization_demo.html。