我能够使用 Ti 创建以下自旋回波序列(NMR、NQR 光谱)图表钾Z:
它是使用以下代码片段生成的:
\begin{tikzpicture}
\coordinate (yoffset) at (0, -2);
\coordinate (start) at (12, 0);
\coordinate (acq_start) at ($(start) + 1*(yoffset)$);
\coordinate (end) at (0, 0);
\coordinate (acq_end) at ($(end) + 1*(yoffset)$);
\coordinate (rf_1_ll) at ($(end) + (1,-0.5)$);
\coordinate (rf_1_ur) at ($(end) + (2,0.5)$);
\coordinate (rf_dash1) at ($(end) + (1,0)$);
\coordinate (rf_dash2) at ($(end) + (2,0)$);
\coordinate (rf_2_ll) at ($(end) + (4,-0.5)$);
\coordinate (rf_2_ur) at ($(end) + (6,0.5)$);
\coordinate (rf_1_midway) at ($(end) + (1.5,0)$);
\coordinate (rf_2_midway) at ($(end) + (5,0)$);
\coordinate (te_half) at ($(rf_2_midway) - (rf_1_midway)$);
\coordinate (acq_ll) at ($(acq_end) + 2*(te_half) - (-0.5, -0.5) + (1.5, 0)$);
\coordinate (acq_ur) at ($(acq_end) + 2*(te_half) - (0.5, 0.5) + (1.5, 0)$);
\draw[dashed] (rf_1_midway) -- ($(rf_1_midway) + 3*(yoffset)$) node [midway, name=te_1] {};
\draw[dashed] (rf_2_midway) -- ($(rf_2_midway) + 3*(yoffset)$) node [midway, name=te_2] {};
\draw[<->] (te_1) -- (te_2) node [midway, anchor = south] {$\frac{T_E}{2}$};
\draw[dashed] ($(rf_2_midway) + (te_half)$) -- ($(rf_2_midway) + (te_half) +3*(yoffset)$) node [midway, name=te_3] {};
\draw[<->] (te_2) -- (te_3) node [midway, anchor = south] {$\frac{T_E}{2}$};
\draw[dashed] (rf_dash1) -- ($(rf_dash1) + (0, 1)$) node [name = tp_lab1] {};
\draw[dashed] (rf_dash2) -- ($(rf_dash2) + (0, 1)$) node [name = tp_lab2] {};
\draw[<->] (tp_lab1) -- (tp_lab2) node [midway, anchor = south] {$T_P$};
\draw ($(start) + 0*(yoffset)$) -- ($(end) + 0*(yoffset)$) node[anchor = east] {RF pulse};
\draw[fill=black!50] (rf_1_ll) rectangle (rf_1_ur);
\draw[fill=black!50] (rf_2_ll) rectangle (rf_2_ur);
\draw (acq_start) -- (acq_end) node[anchor = east] {Acquisition};
\draw[fill=black!50] (acq_ll) rectangle (acq_ur);
\draw[->] ($(end) + 3*(yoffset)$) -- ($(start) + 3*(yoffset)$) node[anchor = north] {time};
\draw[->] ($(end) + 3*(yoffset) + (0.5, -0.5)$) -- ($(end) + 3*(yoffset) + (0.5, 2.5)$) node [anchor = north east] {Signal};
\draw[domain=0:3.5,smooth, line width = 1pt,variable=\x,shift={(1.5,-6)}] plot ({\x},{2*2.718^-\x - 0.02});
\begin{scope}[yscale=1,xscale=-1]
\draw[domain=0:3.5, line width = 1pt,smooth,variable=\x,shift={(-8.5,-6)}] plot ({\x},{1.3*2.718^-\x});
\end{scope}
\draw[domain=0:3.5, line width = 1pt, smooth,variable=\x,shift={(8.5,-6)}] plot ({\x},{1.3*2.718^-\x});
\draw[dashed, line width = 1pt, domain=0:10.5,smooth,variable=\x,shift={(1.5,-6)}] plot ({\x},{2*2.718^(-\x/16)});
\draw node at (3.5, -5) {\footnotesize FID $\propto \exp{-\frac{t}{T_2^*}}$};
\draw node at (10, -4.5) {\footnotesize SE $\propto \exp{-\frac{t}{T_2}}$};
\end{tikzpicture}
其中存在一些问题,这就是我问这个问题的原因。
- 首先,它非常冗长 - 可能比它应该的还要冗长 - 但并没有很好地表达出实际发生的事情。
- 我知道 Ti 中的“路径”概念钾Z,但是在这个例子中我无法很好地使用它。
- 它的可扩展性不是很好,也就是说,如果我想在块的开始和结束处添加更多虚线,我必须手动为每条线添加。此外,我在块之间绘制箭头的方式要求我在虚线的开始和结束之间设置 2 个辅助节点,然后绘制连接它们的箭头。我相信有更好的方法来做到这一点。
- calc tikzlibrary 的广泛使用。我不太喜欢它的语法,我觉得它不必要地复杂。我也没能想出一个好方法,只使用节点的 x 和 y 坐标,即构造一个点 (node_A.x, node_B.Y)。这可能也有助于简化这一点。
我想特别问以下问题:我该如何改进此代码,尤其是针对上述几点?
答案1
做同一件事总是有多种方法。
在这里,我更大程度地参数化了绘图,为绘图和整个过程中使用的常量创建样式并声明函数。我calc
根本不使用库,也不使用垂直坐标(-|
)。我确实使用了相对坐标,用 表示++
,几次。
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[
mybox/.style={
draw=black,
fill=black!50,
minimum size=1cm
},
axis/.style={
thick,
-stealth
},
annotation/.style={
latex-latex
},
myplot/.style={
domain=0:T/2,
smooth,
line width = 1pt
},
declare function={
f(\x,\c)={\c*exp(\x)};
T=7;
RFheight=6;
Aqheight=4;
plotshift=1.5;
Tmax=12;
Tmin=-1;
}
]
% draw axes
\draw [axis] (0,-1) -- (0,3) node[below left] {Signal};
\draw [axis] (Tmin,0) -- (Tmax,0) node[below] {time};
% draw horizontal lines
\draw (Tmax,Aqheight) -- (Tmin, Aqheight) node[left] {Aquisition};
\draw (Tmax,RFheight) -- (Tmin, RFheight) node[left] {RF Pulse};
% plots with annotations
\draw[myplot] plot ({\x+plotshift},{f(-\x,2)-0.02});
\node[above right,font=\footnotesize] at (plotshift+1,{f(-1,2)}) {FID $\propto \exp{-\frac{t}{T_2^*}}$};
\draw[myplot] plot ({-\x+T+plotshift},{f(-\x,1.3)});
\draw[myplot] plot ({\x+T+plotshift},{f(-\x,1.3)});
\draw[myplot,dashed,domain=0:1.5*T] plot ({\x+plotshift},{f(-\x/16,2)});
\node[above right,font=\footnotesize] at (plotshift+T+1,{f(-(T+1)/16,2)}) {SE $\propto \exp{-\frac{t}{T_2}}$};
% dashed lines
% note addition of coordinate
\foreach [count=\i] \x in {0,0.5,1}
\draw [dashed] (\x*T+plotshift,0) -- ++(0,RFheight) coordinate[pos=0.45] (T-\i);
% arrowed lines between dashed lines
\foreach [evaluate={\j=int(\i+1)}] \i in {1,2}
\draw [annotation] (T-\i) -- node[above] {$\frac{T_E}{2}$} (T-\j);
% grey boxes
\node [mybox] (a) at (plotshift,RFheight) {};
\node [mybox, minimum width=2cm] at (plotshift+T/2,RFheight) {};
\node [mybox] at (plotshift+T,Aqheight) {};
% annotation of first box
\draw [dashed] (a.north west) -- ++(0,0.5) coordinate(tmpa);
\draw [dashed] (a.north east) -- ++(0,0.5) coordinate(tmpb);
\draw [annotation] (tmpa) -- node[above] {$T_P$} (tmpb);
\end{tikzpicture}
\end{document}
答案2
既然你问的是编程风格,下面是元帖子,让您了解一种替代方法,我希望它能“更好地传达实际发生的事情”。
这包含在 中luamplib
,因此请使用 -- 进行编译,lualatex
或者弄清楚如何将其改编为良好生产规范或普通的 Metapost。
\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\usepackage{luatex85}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
% start by defining a unit size
numeric u;
u = 5mm;
% now define the axes
path xx, yy;
xx = (left -- 21 right) scaled u;
yy = (down -- 5 up) scaled u;
% and draw & label them
drawarrow xx; label.bot("time", point 1 of xx);
drawarrow yy; label.lft("Signal", point 0.9 of yy);
% the other horizontal lines are defined by copying the x-axis and shifting up
path aa, pp;
aa = xx shifted (0, 8u);
pp = xx shifted (0, 12u);
% and draw & label them too
draw aa withcolor 1/2 white; label.lft("Acquisition", point 0 of aa);
draw pp withcolor 1/2 white; label.lft("RF pulse", point 0 of pp);
% now define the vertical lines
path t[];
t1 = (point 0 of xx -- point 0 of pp) shifted (3u,0);
t2 = (point 0 of xx -- point 0 of pp) shifted (9u,0);
t3 = (point 0 of xx -- point 0 of pp) shifted (15u,0);
% and the three boxes
path b[];
b1 = unitsquare shifted -(1/2, 1/2) scaled 2u shifted point 1 of t1;
b2 = unitsquare shifted -(1/2, 1/2) xscaled 4u yscaled 2u shifted point 1 of t2;
b3 = unitsquare shifted -(1/2, 1/2) scaled 2u shifted (aa intersectionpoint t3);
% draw the lines and boxes in a loop
forsuffixes $=1,2,3:
draw t$ dashed evenly withcolor 1/2 white;
fill b$ withcolor 7/8[blue, white];
draw b$;
endfor
% define the two signal lines
% the first is defined as bezier cubic splines connecting various points...
path s[];
s1 = point 1/3 of t1 .. point 0 of t2 shifted 1 up {right} .. point 1/4 of t3
& point 1/4 of t3 .. point 0.96 of xx shifted 1 up {right};
% the second picks out points from the first, the final shift up done by eye
s2 = point 0 of s1 .. point 2 of s1 .. point 4 of s1 shifted 36 up;
% draw the signal lines using some color (for emphasis)
draw s1 withcolor 2/3 blue;
draw s2 dashed withdots scaled 1/2 withcolor 2/3 blue;
% add labels along the lines
label.urt("$\hbox{FID}\propto e^{-t/T_2^*}$", point 1/4 of s1);
label.urt("$\hbox{SE}\propto e^{-t/T_2}$", point 9/8 of s2);
% finally write a short function to do the "double arrow" annotation
vardef annotate(expr description, a, b) =
interim ahangle := 25; % smaller arrow heads...
interim ahlength := 3;
path p; % straight path from a to b, but shortened a bit
p = a--b cutbefore fullcircle scaled 3 shifted a
cutafter fullcircle scaled 3 shifted b;
% draw the arrow and put the label near the middle
drawdblarrow p;
label(description, point 1/2 of p shifted (unitvector(direction 1/2 of p) rotated 90 scaled 3 labeloffset));
enddef;
% add the three annotations
annotate("$\frac12T_E$", point 1/2 of t1, point 1/2 of t2);
annotate("$\frac12T_E$", point 1/2 of t2, point 1/2 of t3);
annotate("$T_P$", point 3 of b1 shifted 5 up, point 2 of b1 shifted 5 up);
endfig;
\end{mplibcode}
\end{document}
答案3
您的代码看起来已经很不错了,但如果我必须绘制它,我可能会先从情节开始,然后再添加其他所有内容。这是一个不太复杂的提议,除其他外,它还利用了-|
Torbjørn T. 宣传的语法。
\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
%1. start with the plot
\draw[-latex] (0,-1) -- (0,3) node[left,pos=0.9]{signal};
\draw[-latex] (-1,0) -- (12,0) node[below]{time};
\draw[domain=0:3.5,smooth, line width = 1pt,variable=\x,shift={(1,0)}] plot ({\x},{2*2.718^-\x - 0.02})
node[pos=0,above,xshift=1.8cm,yshift=0.7cm] {\footnotesize FID $\propto \exp{-\frac{t}{T_2^*}}$};
\begin{scope}[yscale=1,xscale=-1]
\draw[domain=0:3.5, line width = 1pt,smooth,variable=\x,shift={(-8,0)}] plot ({\x},{1.3*2.718^-\x});
\end{scope}
\draw[domain=0:3.5, line width = 1pt, smooth,variable=\x,shift={(8,0)}] plot ({\x},{1.3*2.718^-\x});
\draw[dashed, line width = 1pt, domain=0:10.5,smooth,variable=\x,shift={(1,0)}]
plot ({\x},{2*2.718^(-\x/16)}) node[above,xshift=-2cm,yshift=0.2cm] {\footnotesize SE $\propto \exp{-\frac{t}{T_2}}$};
%2. add the dashed lines
\foreach [count=\n] \X in {1,4.5,8}
{
\draw [dashed] (\X,0) coordinate (X-\n) -- (\X,6.5) coordinate (Y-\n);
}
\draw[latex-latex,shorten >=2pt,shorten <=2pt] ($(X-1)!0.5!(Y-1)$)
--($(X-2)!0.5!(Y-2)$) node[midway,above] {$T_E/2$};
\draw[latex-latex,shorten >=2pt,shorten <=2pt] ($(X-2)!0.5!(Y-2)$)
--($(X-3)!0.5!(Y-3)$) node[midway,above] {$T_E/2$};
%3. draw the horizontal lines
\foreach [count=\n]\X/\Y in {4.5/Aquisition,6.5/RF Pulse}
{
\draw[-] (-1,\X) coordinate[label=left:\Y] (H-\n) -- (12.5,\X);
}
\node[fill=gray,minimum width=1cm,minimum height=1cm] (box-1) at (H-2 -| X-1){};
\draw[dashed] (box-1.north west) -- ++(0,0.4cm) coordinate (B-1);
\draw[dashed] (box-1.north east) -- ++(0,0.4cm) coordinate (B-2);
\draw[latex-latex,shorten >=2pt,shorten <=2pt] (B-1) -- (B-2)
node[midway,above] {$T_F$};
\node[fill=gray,minimum width=2cm,minimum height=1cm] at (H-2 -| X-2){};
\node[fill=gray,minimum width=1cm,minimum height=1cm] at (H-1 -| X-3){};
\end{tikzpicture}
\end{document}