Reputation: 55
I have some questions regarding data fitting in gnuplot. Suppose I have data formatted as follows example of data: test.txt
# x y y_unc
1 0.20124531 2415.58 8.25706
2 0.20516169 2416.44 8.20651
3 0.21008456 2418.48 8.12084
4 0.21531272 2420.98 8.14102
5 0.22070909 2423.81 8.08436
6 0.2259568 2426.22 8.11353
7 0.23033106 2426.90 8.10172
8 0.23536205 2428.67 8.12772
9 0.24108887 2431.43 8.0769
10 0.24623346 2433.40 8.10201
11 0.252087 2436.33 8.19167
12 0.25853813 2439.53 8.14111
13 0.2634114 2441.27 8.14649
14 0.26842701 2442.58 8.19902
15 0.27422249 2444.09 8.25536
16 0.2799958 2447.22 8.32832
17 0.28573883 2449.42 8.37259
18 0.29226887 2452.35 8.34731
19 0.29696763 2453.71 8.32749
20 0.3020314 2454.80 8.40804
21 0.30853319 2457.60 8.3655
22 0.31335223 2459.26 8.41802
23 0.31937134 2461.96 8.4152
24 0.32383776 2461.80 8.45517
25 0.32963562 2464.02 8.49144
26 0.33469725 2465.15 8.37373
27 0.34041607 2467.62 8.30546
28 0.34591591 2469.44 8.30957
29 0.35146141 2471.29 8.37891
30 0.35608864 2471.50 8.30454
31 0.36138475 2472.98 8.31596
32 0.36773384 2476.24 8.43088
33 0.37238193 2476.59 8.34855
34 0.37814891 2478.86 8.26447
35 0.38311863 2479.65 8.28821
36 0.38847184 2481.35 8.25968
37 0.39456666 2484.14 8.21979
38 0.40007389 2486.06 8.16865
39 0.40610838 2488.30 8.25412
40 0.41157734 2490.10 8.29775
41 0.41630316 2491.59 8.31229
42 0.42112446 2492.40 8.26294
43 0.42697787 2494.75 8.32757
44 0.43137014 2495.07 8.36824
45 0.43700123 2496.25 8.46014
46 0.4422034 2497.68 8.45171
47 0.44765294 2500.41 8.42395
48 0.45317519 2502.29 8.48215
49 0.45835781 2503.81 8.50099
50 0.46392608 2505.78 8.61147
51 0.46943402 2508.04 8.60481
52 0.47533679 2510.15 8.58076
53 0.47967601 2510.77 8.6058
54 0.48523116 2513.11 8.63744
55 0.49090195 2515.74 8.8106
56 0.49617493 2517.32 8.8445
57 0.50119078 2518.77 8.87158
58 0.5066849 2520.57 8.93972
59 0.51132584 2522.25 8.91477
60 0.51644492 2524.03 8.89287
61 0.52197838 2526.33 9.00516
62 0.52705693 2528.27 8.92575
63 0.53193879 2529.73 8.95115
64 0.53704453 2531.44 8.99157
65 0.54210413 2532.46 9.03761
66 0.54626262 2533.34 9.00458
67 0.55056 2534.07 8.99342
68 0.55507934 2535.02 9.04953
69 0.55982471 2536.35 8.97597
70 0.56411815 2536.96 9.01189
71 0.56895626 2537.75 9.01932
72 0.57330275 2539.28 8.99917
73 0.57795715 2540.63 8.98475
74 0.58263767 2541.96 9.01778
75 0.58747137 2543.59 9.08297
76 0.59117234 2543.47 9.07999
77 0.59538865 2543.54 9.11839
78 0.59938073 2544.33 9.1549
79 0.60377049 2545.28 9.18278
80 0.60801435 2545.99 9.17474
81 0.61249495 2547.23 9.21996
82 0.61721373 2548.98 9.13147
83 0.62135947 2549.96 9.15198
84 0.6255244 2550.66 9.09919
85 0.629843 2551.9 9.15456
86 0.63427138 2553.34 9.21929
87 0.6376698 2552.96 9.19235
88 0.6422739 2554.31 9.24774
89 0.6468153 2555.74 9.1766
90 0.65102458 2556.53 9.22202
91 0.65579379 2558.13 9.16892
92 0.66031909 2559.52 9.20696
93 0.66545904 2561.28 9.29657
94 0.66935432 2561.9 9.23281
95 0.67299354 2562.15 9.28052
96 0.67770863 2564.20 9.37245
97 0.68189645 2565.98 9.48318
98 0.68605471 2566.81 9.56233
99 0.69018805 2567.83 9.59128
100 0.69424725 2568.67 9.63816
I try to fit the data in column 2 agains column 3. Up to now I can do the fit by using the following code
# Fitting data from file
reset session
set terminal qt size 800,480
set key left
FILE = 'test.txt'
# fit function
f(x) = a*x+b
fit [0.25:0.58] f(x) FILE u 2:3 via a,b
chi2=(FIT_STDFIT*FIT_STDFIT)
# setting label
set label 1 'Fit Parameters' left at graph 0.7, graph 0.95 font "arial,15"
set label 2 sprintf("y= %.2fx + %.2f", a,b)left at graph 0.7, graph 0.90 font "arial,10"
set label 3 sprintf("a = %.2f %.2s %.2f",a,'±',a_err) left at graph 0.7, graph 0.86 font "arial,10"
set label 4 sprintf("b = %.2f %.2s %.2f",b,'±',b_err) left at graph 0.7, graph 0.82 font "arial,10"
set label 5 sprintf("ndf = %.2f ", FIT_NDF) left at graph 0.7, graph 0.78 font "arial,10"
set label 6 sprintf("{/Symbol c}^2/ndf = %.2f ", chi2) left at graph 0.7, graph 0.74 font "arial,10"
# setting label box
set arrow 1 nohead at 0.51, 2755 to 0.75, 2755
set obj 10 rect at 0.63, 2710 size 0.25, 160
set obj 10 fillstyle empty border -1 front
# setting range
set xrange [0:0.8]
set yrange [2200:2800]
set ytics nomirror
set y2range [-50:300]
set y2tics
set x2zeroaxis lt -1
set xlabel 'x-axis'
set ylabel 'y-axis'
set y2label 'residual'
# plotting
plot FILE u 2:3:4 w yerr pt 7 lc rgb 'black' ti 'data',\
[0:0.58] f(x) w l lw 2 lc rgb 'red' ti 'fit',\
[0.25:0.58] FILE u 2:(f($2)-$3) pt 1 axes x1y2 ti 'residual'
# end code
and using the test data I can obtain this result:
My main question is: is it possible to use 3rd variable, e.g. the line number in column 1, as the fitting range, instead of using the x value? For example, using [1:5] to fit the first 5 data instead of using [0.20:0.22].
Additional question regarding my code above, I plot the residual in together with the fit, but I want to limit the residual plot only within the fitted data. Using the above code, the residual is plotted for the whole data and I got warning: "Ignoring sample range in non-sampled data" when running this code. Is there any way to fix this one?
And last one, is there a simpler way to print the fit parameters in the plot instead of using label?
Upvotes: 2
Views: 179
Reputation: 25714
As I understand, you have several questions:
ad 1: write a filter function, e.g. myRange(colD,colR,min,max)
which returns NaN
outside the desired range. colD
is the data column, colR
is the column for the range, min,max
are the limits of the range.
ad 2: you can use newline \n
in a label and use enhanced text. Check help enhanced
. You can make a box around using set style textbox
, might not work for all terminals, check help textbox
. Still a bit confusing but certainly simpler than drawing many manually placed labels and arrows and boxes.
ad 3: again limit your plot via your filter function (see ad 1)
So, the following code:
[0:0.58]
Maybe there are simpler solutions which I am currently not aware of.
Code:
### limit fit and plotting range via 3rd column
reset session
$Data <<EOD
# x y y_unc
1 0.20124531 2415.58 8.25706
2 0.20516169 2416.44 8.20651
3 0.21008456 2418.48 8.12084
4 0.21531272 2420.98 8.14102
5 0.22070909 2423.81 8.08436
6 0.2259568 2426.22 8.11353
7 0.23033106 2426.90 8.10172
8 0.23536205 2428.67 8.12772
9 0.24108887 2431.43 8.0769
10 0.24623346 2433.40 8.10201
20 0.4 2500 8.0 # just added to show the larger range
30 0.5 2560 8.0
EOD
# filter function
myRange(colD,colR,min,max) = column(colR)>=min && column(colR)<=max ? column(colD) : NaN
# fit function
f(x) = a*x+b
fit f(x) $Data u (myRange(2,1,1,5)):3 via a,b
chi2=(FIT_STDFIT*FIT_STDFIT)
# setting label
set label 1 at graph 0.7, graph 0.95 boxed \
sprintf("%s\n%s\n%s\n%s\n%s\n%s", \
"{/'Arial':Bold=14 Fit Parameters}", \
sprintf("y= %.2fx + %.2f", a,b), \
sprintf("a = %.2f %.2s %.2f",a,'±',a_err), \
sprintf("b = %.2f %.2s %.2f",b,'±',b_err), \
sprintf("ndf = %.2f ", FIT_NDF), \
sprintf("{/Symbol c}^2/ndf = %.2f ", chi2))
set style textbox border
set key left
# setting range
set xlabel 'x-axis'
set xrange [0:0.8]
set ylabel 'y-axis'
set yrange [2200:2800]
set ytics nomirror
set y2label 'residual'
set y2range [-50:300]
set y2tics
set x2zeroaxis lt -1
plot $Data u 2:3:4 w yerr pt 7 lc rgb 'black' ti 'data',\
[0:0.58] f(x) w l lw 2 lc rgb 'red' ti 'fit',\
$Data u (myRange(2,1,1,5)):(f($2)-$3) pt 1 axes x1y2 ti 'residual'
### end of code
Result:
Upvotes: 1