【问题标题】:gnuplot with broken x axis in v5.2 using nonlineargnuplot 在 v5.2 中使用非线性破坏 x 轴
【发布时间】:2019-03-04 20:27:39
【问题描述】:

5.2 版包含set nonlinear。可以按照演示 here 中的建议使用它来构造断轴。我正在尝试遵循 x 轴也是对数的步骤。当前代码以及数据如下。我无法弄清楚的问题是休息后一阶的缩放,这在这个图中说明了:

如您所见,问题在 0.1 和 1 之间。我做错了什么?

data="test2.txt"
unset nonlinear x
x1min=1e-6
x1max=1e-5
x2min=1e-1
x2max=1e+3
ymin =1e-1
ymax =1e+3
dx=(x2min - x1max)
set yrange  [ymin:ymax]
unset key
set format x "10^{%T}
set xtics font ",12"
set ytics font ",12"
set y2tics font ",12"
axis_gap=1
f(x) = (x <= x1max)  ? log10(x) : (x < x2min)            ? NaN : log10(x - dx + axis_gap)
g(x) = (x <= x1max) ? 10**x     : (x < x1max + axis_gap) ? NaN : 10**(x + dx - axis_gap)
set xrange  [x1min:x2max] nereverse nowriteback
set nonlinear x  via f(x) inverse g(x)
set logscale y
set xtics  (1e-6 0,2e-6 1,3e-6 1,4e-6 1,5e-6 1,6e-6 1,7e-6 1,8e-6 1,9e-6 1,1e-5 0,2e-5 1,3e-5 1,4e-5 1,5e-5 1,6e-5 1,7e-5 1,8e-5 1,9e-5 1,1e-2 0,2e-2 1,3e-2 1,4e-2 1,5e-2 1,6e-2 1,7e-2 1,8e-2 1,9e-2 1,1e-1 0,2e-1 1,3e-1 1,4e-1 1,5e-1 1,6e-1 1,7e-1 1,8e-1 1,9e-1 1,1 0,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9 1,10 0,20 1,30 1,40 1,50 1,60 1,70 1,80 1,90 1,100 0,200 1,300 1,400 1,500 1,600 1,700 1,800 1,900 1,1000 0)
plot data u 1:2

数据在哪里:

5 0.471238898038469
4.18879020478639e-6 0.7
4.18879020478639e-6 2
4.18879020478639e-6 8.8
4.18879020478639e-6 2.8
1 4.18879020478639e-6
1 4.18879020478639e-6
98.174770424681 1.68
98.174770424681 3.4
0.125663706143592 161.809725
0.125663706143592 425.60861
0.125663706143592 425.60861
0.125663706143592 425.60861
0.125663706143592 483.467845
144 43.14926
1 50.99458
1 51.975245
1 52.95591
1 54.91724
1 57.859235
1 66.68522
1 69.627215
1 78.4532
1.728 32.361945
1.728 40.207265
1.728 41.18793
1.728 43.14926
1.728 45.11059
1.728 48.052585
1.728 54.91724
1.728 65.704555
3.375 46.091255
3.375 50.99458
3.375 54.91724
3.375 56.87857
3.375 57.859235
3.375 64.72389
8 24.516625
8 43.14926
8 46.091255
8 51.975245
8 54.91724
8 59.820565
15.625 47.07192
15.625 48.052585
15.625 50.99458
15.625 52.95591
15.625 55.897905
64 42.168595
64 42.168595
64 48.052585
125 35.30394
125 42.168595
125 50.013915

更新

我在这个问题上开始赏金。我正在添加另一个示例,一个更简单的示例:

unset key
unset nonlinear x
unset nonlinear x2
axis_gap=1
x1min=1
x1max=3
x2min=5
x2max=20
ymin =1e-1
ymax =1e+3
dx=(x2min - x1max)
x1minp=log10(x1min)
x1maxp=log10(x1max)
x2minp=log10(x2min)
x2maxp=log10(x2max)
set yrange  [ymin:ymax]
set xrange  [x1min:x2max] noreverse nowriteback
f(x) = (x <= x1max) ? log10(x) : (x < x2min) ? NaN : log10(x/(x2min/x1max)*axis_gap)
g(x) = (x <= x1maxp) ? 10**(x) : (x < log10(x1max*axis_gap)) ? NaN :  10**(x) + dx + log10(axis_gap)
set nonlinear x  via f(x) inverse g(x)
set logscale y
set xtics (1e0 0,2e0 0,3e0 0,4e0 0,5e0 0,6e0 0,7e0 0,8e0 0,9e0 0,1e1 0,2e1 0)
plot 0 w l

在这个版本中,我终于了解了nonlinear 的概念,我更愿意考虑一个刻度距原点的距离(gnuplot 的不可见轴),它由 f(x) 确定,其中 x 是来自的数字绘制的范围和f(x)set nonlinear x via f(x) inverse g(x) 中的一个,g(x) 从原点获取与位置x 的刻度相关的数字(放入y(x) 的数字y 绘制在y-轴并显示在刻度上方/下方的 x 轴上)。这听起来可能很复杂,因为我发现这比一些非线性可见轴和线性不可见轴概念要好得多,前提是我这次实际上理解正确。

该解决方案不仅必须在两个样本上没有 warning: could not confirm linked axis inverse mapping function 的情况下工作,而且还需要解释此更新中的功能有什么问题,最好是按照上面建议的距离和数字,而不是可见/不可见gnuplot 术语。

更新 2

我也注意到了,看图片。

f(x) = (x <= x1max) ? log10(x) : (x < x2min) ? NaN : log10(x/(x2min/x1max)*axis_gap)
g(x) = (x <= x1maxp) ? 10**(x) : (x < log10(x1max*axis_gap)) ? NaN :  10**(x*(x2min/x1max)) + dx + log10(axis_gap)

您可以看到显示在窗口左下角的坐标表现如预期 (axis_gap=1.1) 但抽动(如果您绘制数据点 (1 1, 2 1, 3 1, 5 1, 6 1 ,...)) 放置错误):

【问题讨论】:

    标签: gnuplot


    【解决方案1】:

    修改后的答案:

    查看 gnuplot 文档:

    【5.2版新命令】这个命令和set link类似 命令,只是两个链接轴中只有一个是可见的。这 隐藏轴保持线性。沿可见轴的坐标是 通过将g(x) 应用于隐藏轴坐标进行映射。 f(x) 映射 可见轴坐标回到隐藏的线性轴上。

    例子:

    set xrange [1:1000]

    set nonlinear x via log10(x) inverse 10**x

    这个 示例建立一个对数缩放的 x 轴。这是一种替代方式 达到set log x的效果。在这种情况下,隐藏轴有 range [0:3],计算得到[log10(xmin):log10(xmax)]。你 必须同时提供正向和反向表达式。

    换句话说:f(x) 是一个函数,它获取您的 x 数据输入值并将其映射到线性范围。如果你set logscale x 你已经有了这样的映射并且函数f(x) 就是log10(x)。而g(x)是反函数10**x

    如果你有一个断轴,就像你的情况一样,你必须定义一个适合不同区域的映射函数。下面,我选择了一个连续函数,其中BrokenAxisPos 是第二个轴应该开始的值(相对于中断前的轴)。 见下图:

    f(x) 函数将您想要省略的范围 x1maxx2min 压缩到范围 x1maxBrokenAxisPos(我将其设置为 1e-4)。它需要一些小的计算来获得函数f(x) 正确的因子。对于x2min 以上的值,函数 f(x) 将原始 x 值移动某个适当的值。 经过一些简单的计算,g(x) 是函数 f(x) 的倒数。

    附上代码:

    ### broken nonlinear (logarithmic) axis
    reset session
    set size square 
    
    data="test2.txt"
    
    x1min=1e-6; x1max=1e-5
    x2min=1e-1; x2max=1e+3
    ymin =1e-1; ymax =1e+3
    unset key
    
    # settings x-axis
    unset logscale x
    set xrange[x1min:x2max]
    set format x "10^{%T}"
    set xtics font ",12"
    # manually set major xtics
    set xtics add ("0.1" 1e-1, "1" 1, "10" 10, "100" 100, "1000" 1000)
    set mxtics 10
    # settings y-axis
    set logscale y
    set format y "%g"
    set yrange  [ymin:ymax]
    set ytics font ",12"
    
    set grid xtics, ytics
    
    BrokenAxisPos = 1e-4
    m = log10(BrokenAxisPos/x1max)/log10(x2min/x1max)
    f(x) = (x <= x1max) ? log10(x) : x<x2min ? log10(x1max**(1-m)*x**m) : log10(x*BrokenAxisPos/x2min)
    g(x) = (x <= log10(x1max)) ? 10**x : x<log10(BrokenAxisPos) ? (10**x/x1max**(1-m))**(1/m) : (x2min/BrokenAxisPos)*10**x
    
    set nonlinear x via f(x) inverse g(x)
    
    # manually hide x1,x2 axis and y-gridlines by placing a rectangle
    set obj 1 rect from x1max*1.2, graph 0 to x2min*0.8, graph 1 fs solid 1.0 border bgnd front
    
    plot data u 1:2 w p
    ### end of code
    

    顺便说一句,您还可以通过将“间隙”部分设置为NaN 来使用不连续函数,就像您和@Ethan 所做的那样。然后就可以直接跳过m的计算和使用了。

    f(x) = (x <= x1max) ? log10(x) : x<x2min ? NaN : log10(x*BrokenAxisPos/x2min)
    g(x) = (x <= log10(x1max)) ? 10**x : x<log10(BrokenAxisPos) ? NaN : (x2min/BrokenAxisPos)*10**x
    

    但是你必须调整轴的隐藏

    set obj 1 rect from x1max*1.2, graph 0 to x2min*0.8, graph 1 fs solid 1.0 border bgnd front
    

    set obj 1 rect from x1max, graph 0 to x2min, graph 1 fs solid 1.0 border bgnd front
    

    因为x1max*1.2x2min*0.8(仍用于显示x 网格线)将映射到NaN

    连续f(x)g(x),你会得到结果:

    【讨论】:

    • 请阅读我对@Ethan 答案的第二条评论,它也适用于您的gg 应该从抽动的距离映射到抽动值,因此您无法将距离与抽动值 - x1max)。但是同样,也许我仍然不明白nonlinear,所以有必要准确解释fg的功能是什么——它们的域和图像是什么。在我的想象中,有两个空间:与原点(放置抽动的地方)的距离空间和 x 轴上用于例如的数字空间。打印抽动或评估 y(x)。而fg 在它们之间映射。
    • 你是对的。但是,该图是正确的,尽管 g(x) 不是导致警告的 f(x) 的正确反函数。检查修改后的答案。现在,希望一切都好:-)。
    • 谢谢,明天我会完整阅读您的答案,但有件事立即让我感到困扰:“f(x) 是一个函数,它获取您的 x 数据输入值并将其映射到线性范围。”这可能只是术语问题,但是当您这么说时,log 不会这样做,至少在我对“线性范围”的理解中。这通常通过映射f(x) = k x + b 来完成,它是一个线性映射,因此值之间的 1 个单位是 x 轴上的恒定距离(1 个单位或 k 个单位),但 log 的工作方式不同,x 轴上的距离是不是恒定的,因此不是线性的。
    • “映射到线性范围”不一定是“线性映射函数”f(x)。距离呈指数增长的抽动将具有(在应用f(x) 之后)可以用线性函数描述的距离。 log10(x) 会将抽动(相隔几个数量级,即非线性)映射到等距(线性)的抽动。
    【解决方案2】:

    您的方法中的逻辑错误是,要沿对数坐标轴移动,您需要乘以或除以偏移量,而不是加法或减法。所以你的映射会是这样的:

    axis_gap = 1.e4
    f(x) = (x <= x1max)  ? log10(x) : (x < x2min)            ? NaN : log10( (x/dx) / axis_gap)
    g(x) = (x <= x1max) ? 10**x     : (x < x1max + axis_gap) ? NaN : 10**( (x*dx) * axis_gap)
    

    生成下图

    【讨论】:

    • 在又一次尝试理解非线性失败后,我回到了这个问题。我可能终于明白了这个概念。但是在您的解决方案中,我认为有两个错误:f(x) 应该在最后:log10(x/(x2min/x1max)*axis_gap)g(x) 对我来说仍然是个谜,1)您将 x 线性与 x 与原点的距离进行比较,我认为这是错误的,因为 g(x) 应该从距离轴(在 gnuplot 术语中不可见)映射到数字轴(进入 y(x) 评估的可见数字)因此您无法将 x1maxx 等进行比较。
    • 2) 最后,您将刻度距原点 (x) 的距离乘以两个数字的线性距离 dx,这对我来说毫无意义。我当前的版本(显然不起作用是:f(x) = (x &lt;= x1max) ? log10(x) : (x &lt; x2min) ? NaN : log10(x/(x2min/x1max)*axis_gap)g(x) = (x &lt;= x1maxp) ? 10**(x) : (x &lt; log10(x1max*axis_gap)) ? NaN : 10**(x) + dx + log10(axis_gap)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    相关资源
    最近更新 更多