关于 metapost 创建图表的灵活性/功能

关于 metapost 创建图表的灵活性/功能

我将以下 pgfplots 图表嵌入到 TeX 文档中,对此我非常满意。最近,我在阅读 metapost 时,想尝试使用它重新创建图表。

\begin{figure}[ht]
  \centering
  \begin{tikzpicture}
    \begin{axis}[
        width            = \textwidth,
        height           = 1.1\textwidth,
        xlabel           = Days,
        ylabel           = kg,
        xmin             = 0,
        xmax             = 450,
        ymin             = 2,
        grid             = both,
        minor x tick num = 1,
        minor y tick num = 3,
      ]
      \addplot[red, mark=*] table [x=Days, y expr=\thisrow{Weight}/1000] {weight.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P01] {wfa_boys_p_exp.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P1] {wfa_boys_p_exp.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P3] {wfa_boys_p_exp.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P5] {wfa_boys_p_exp.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P10] {wfa_boys_p_exp.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P15] {wfa_boys_p_exp.txt};
      \addplot[gray, restrict x to domain=0:450] table [x=Age, y=P25] {wfa_boys_p_exp.txt};
    \end{axis}
  \end{tikzpicture}
\end{figure}

它使用两个数据文件。一个是这里另一个是这里

我使用了这个图表中的许多功能,想知道 metapost 是否支持这些功能。例如,将 x 值限制为一个域,使用值的表达式,x/y 最小值/最大值等。

是否可以使用相同的数据文件在 metapost 中重新创建这样的图表?

答案1

这是使用 Python 读取 OP 数据文件并为 Metapost 生成输入而生成的图表。

在此处输入图片描述

这是 Python 源代码。我使用了 Python3 语法。使用方法如下:

  • 用合适的名字保存 Python 源代码growth_chart.py

  • 将 OP 数据文件保存在weight.txtwfa_boys_p_exp.txt

  • python3 growth_chart.py > temp.mp && mpost temp在命令行上运行

  • 如果运行没有错误,Metapost 将生成temp1.eps您可以包含在 LaTex 中、或使用 PostScript 查看器打开、或使用convert、或ps2pdf、或 OSX Preview 等转换为 PDF 的内容...

我并没有尝试让它完全通用,例如 450 天和每公斤 40 个点的 y 缩放只是硬编码的。如果你试图让它太通用,你最终可能会重写整个 pgfplots。

weight_path = list()

with open('weight.txt', 'rt') as w:
    for line in w:
        date, days, weight, change = line.split()
        if date == 'Date':
            continue
        weight_path.append( (int(days), int(weight)/1000) )

P01_path = list()
P1_path  = list()
P3_path  = list()
P5_path  = list()
P10_path = list()
P15_path = list()
P25_path = list()

with open('wfa_boys_p_exp.txt', 'rt') as p:
    for line in p:
        Age, L, M, S, P01, P1, P3, P5, P10, P15, P25, P50, P75, P85, P90, P95, P97, P99, P999 = line.split()
        if Age == 'Age':
            continue
        if Age == '450':
            break
        P01_path.append( (int(Age), float(P01)) )
        P1_path.append(  (int(Age), float(P1)) )
        P3_path.append(  (int(Age), float(P3)) )
        P5_path.append(  (int(Age), float(P5)) )
        P10_path.append( (int(Age), float(P10)) )
        P15_path.append( (int(Age), float(P15)) )
        P25_path.append( (int(Age), float(P25)) )

print('''
prologues := 3;
outputtemplate := "%j%c.eps";
defaultfont := "phvr8r";
beginfig(1);
''')

print('path w, p[];')
print('w   = ({}) yscaled 40;'.format('--'.join(str(x) for x in weight_path)))
print('p0  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P01_path)))
print('p1  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P1_path)))
print('p2  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P3_path)))
print('p3  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P5_path)))
print('p4  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P10_path)))
print('p5  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P15_path)))
print('p6  = ({}) yscaled 40;'.format('--'.join(str(x) for x in P25_path)))

print('''
path xx, yy;
xx = origin -- (456, 0);
yy = origin -- (0, 406);
for x = 30 step 30 until 450: 
  draw yy shifted (x,0) withcolor .9 white; 
  label.bot(decimal x, (x,0));
endfor
for y = 1 upto 10:
  draw xx shifted (0,40y) withcolor .9 white;
  label.lft(decimal y, (0,40y));
endfor
drawarrow xx; label.rt("Days", point infinity of xx);
drawarrow yy; label.top("Weight (kg)", point infinity of yy);
''')

print('''
draw p0 withcolor .40[blue,white]; label.rt("0.1%" infont defaultfont scaled 0.8, point infinity of p0);
draw p1 withcolor .45[blue,white]; label.rt("1%"  infont defaultfont scaled 0.8, point infinity of p1);
draw p2 withcolor .50[blue,white]; label.rt("3%"  infont defaultfont scaled 0.8, point infinity of p2);
draw p3 withcolor .55[blue,white]; label.rt("5%"  infont defaultfont scaled 0.8, point infinity of p3);
draw p4 withcolor .60[blue,white]; label.rt("10%" infont defaultfont scaled 0.8, point infinity of p4);
draw p5 withcolor .65[blue,white]; label.rt("15%" infont defaultfont scaled 0.8, point infinity of p5);
draw p6 withcolor .70[blue,white]; label.rt("25%" infont defaultfont scaled 0.8, point infinity of p6);

draw w withcolor .67 red; 
for i=0 upto length w: 
   unfill fullcircle scaled 4 shifted point i of w;
     fill fullcircle scaled 2 shifted point i of w;
endfor
''')

print('''
endfig;end.
''')

相关内容