modified: eloss_calculations/Eloss.py trying out with 0.89/0.9 multiplier on all particles

modified:   eloss_calculations/alpha_lookup_50MeV_250torr_3pc.dat
	modified:   eloss_calculations/aluminum_lookup_80MeV_250torr_3pc.dat
	modified:   eloss_calculations/deutron_lookup_30MeV_250torr_3pc.dat
	modified:   eloss_calculations/fluorine_lookup_70MeV_250torr_3pc.dat
	modified:   eloss_calculations/oxygen_lookup_70MeV_250torr_3pc.dat
	modified:   eloss_calculations/proton_lookup_30MeV_250torr_3pc.dat
	new file:   scratch/overlay_2d.C small script to overlay multiple 2d histograms from the same file
    various scripts used to optimise the different parameters in the analysis
	new file:   scratch/CompareElasticLocus.C
	new file:   scratch/PlotDedxScan.C
	new file:   scratch/RunMultiFit.C
	new file:   scratch/ScanDedxScale.C
This commit is contained in:
Vignesh Sitaraman 2026-09-01 11:43:28 -04:00
parent d245fc2679
commit 461d60a50c
12 changed files with 192954 additions and 135449 deletions

View File

@ -81,10 +81,11 @@ def generate_lookup(z, mass_u, e_start_mev, label):
projectile.T(e_u)
# dedx returns MeV / (g/cm2)
if(mass_u >=10.0):
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2 * DEDX_SCALE
else:
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2 * DEDX_SCALE
# if(mass_u >=10.0):
# loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2 * DEDX_SCALE
# else:
# loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2
current_e_total = max(0.0, current_e_total - loss_mev)
current_thickness_g_cm2 += step_g_cm2

File diff suppressed because it is too large Load Diff

View File

@ -1,397 +1,560 @@
# Energy(MeV) mg/cm2 cm
# Starting Energy: 80 MeV
80.000000 0.000000 0.000000
79.766654 0.015000 0.210854
79.532996 0.030000 0.421708
79.299025 0.045000 0.632562
79.064738 0.060000 0.843416
78.830135 0.075000 1.054270
78.595215 0.090000 1.265124
78.359976 0.105000 1.475978
78.124416 0.120000 1.686832
77.888535 0.135000 1.897686
77.652331 0.150000 2.108540
77.415803 0.165000 2.319394
77.178950 0.180000 2.530248
76.941769 0.195000 2.741102
76.704260 0.210000 2.951956
76.466421 0.225000 3.162810
76.228251 0.240000 3.373664
75.989748 0.255000 3.584518
75.750912 0.270000 3.795372
75.511739 0.285000 4.006226
75.272230 0.300000 4.217080
75.032383 0.315000 4.427934
74.792195 0.330000 4.638788
74.551666 0.345000 4.849642
74.310794 0.360000 5.060496
74.069578 0.375000 5.271350
73.828016 0.390000 5.482204
73.586107 0.405000 5.693058
73.343848 0.420000 5.903912
73.101239 0.435000 6.114766
72.858278 0.450000 6.325620
72.614963 0.465000 6.536474
72.371292 0.480000 6.747328
72.127265 0.495000 6.958182
71.882879 0.510000 7.169036
71.638133 0.525000 7.379890
71.393026 0.540000 7.590744
71.147555 0.555000 7.801598
70.901718 0.570000 8.012452
70.655515 0.585000 8.223306
70.408943 0.600000 8.434160
70.162001 0.615000 8.645014
69.914687 0.630000 8.855868
69.666999 0.645000 9.066722
69.418936 0.660000 9.277576
69.170496 0.675000 9.488430
68.921676 0.690000 9.699284
68.672475 0.705000 9.910138
68.422892 0.720000 10.120992
68.172925 0.735000 10.331846
67.922571 0.750000 10.542700
67.671828 0.765000 10.753554
67.420696 0.780000 10.964408
67.169172 0.795000 11.175262
66.917254 0.810000 11.386116
66.664939 0.825000 11.596970
66.412227 0.840000 11.807825
66.159116 0.855000 12.018679
65.905602 0.870000 12.229533
65.651685 0.885000 12.440387
65.397362 0.900000 12.651241
65.142631 0.915000 12.862095
64.887491 0.930000 13.072949
64.631938 0.945000 13.283803
64.375971 0.960000 13.494657
64.119588 0.975000 13.705511
63.862787 0.990000 13.916365
63.605566 1.005000 14.127219
63.347922 1.020000 14.338073
63.089853 1.035000 14.548927
62.831356 1.050000 14.759781
62.572431 1.065000 14.970635
62.313074 1.080000 15.181489
62.053284 1.095000 15.392343
61.793057 1.110000 15.603197
61.532392 1.125000 15.814051
61.271286 1.140000 16.024905
61.009737 1.155000 16.235759
60.747742 1.170000 16.446613
60.485299 1.185000 16.657467
60.222406 1.200000 16.868321
59.959060 1.215000 17.079175
59.695259 1.230000 17.290029
59.431000 1.245000 17.500883
59.166280 1.260000 17.711737
58.901097 1.275000 17.922591
58.635449 1.290000 18.133445
58.369332 1.305000 18.344299
58.102744 1.320000 18.555153
57.835683 1.335000 18.766007
57.568146 1.350000 18.976861
57.300129 1.365000 19.187715
57.031631 1.380000 19.398569
56.762648 1.395000 19.609423
56.493177 1.410000 19.820277
56.223216 1.425000 20.031131
55.952762 1.440000 20.241985
55.681811 1.455000 20.452839
55.410362 1.470000 20.663693
55.138410 1.485000 20.874547
54.865953 1.500000 21.085401
54.592988 1.515000 21.296255
54.319511 1.530000 21.507109
54.045519 1.545000 21.717963
53.771010 1.560000 21.928817
53.495980 1.575000 22.139671
53.220426 1.590000 22.350525
52.944344 1.605000 22.561379
52.667731 1.620000 22.772233
52.390583 1.635000 22.983087
52.112898 1.650000 23.193941
51.834672 1.665000 23.404795
51.555901 1.680000 23.615649
51.276581 1.695000 23.826503
50.996710 1.710000 24.037357
50.716282 1.725000 24.248211
50.435296 1.740000 24.459065
50.153746 1.755000 24.669919
49.871629 1.770000 24.880773
49.588941 1.785000 25.091627
49.305678 1.800000 25.302481
49.021837 1.815000 25.513335
48.737412 1.830000 25.724189
48.452400 1.845000 25.935043
48.166797 1.860000 26.145897
47.880599 1.875000 26.356751
47.593801 1.890000 26.567605
47.306399 1.905000 26.778459
47.018388 1.920000 26.989313
46.729764 1.935000 27.200167
46.440522 1.950000 27.411021
46.150658 1.965000 27.621875
45.860166 1.980000 27.832729
45.569043 1.995000 28.043583
45.277283 2.010000 28.254437
44.984881 2.025000 28.465291
44.691832 2.040000 28.676145
44.398131 2.055000 28.886999
44.103773 2.070000 29.097853
43.808752 2.085000 29.308707
43.513062 2.100000 29.519561
43.216700 2.115000 29.730415
42.919657 2.130000 29.941269
42.621930 2.145000 30.152123
42.323512 2.160000 30.362977
42.024397 2.175000 30.573831
41.724578 2.190000 30.784685
41.424051 2.205000 30.995539
41.122807 2.220000 31.206393
40.820842 2.235000 31.417247
40.518147 2.250000 31.628101
40.214717 2.265000 31.838955
39.910545 2.280000 32.049809
39.605623 2.295000 32.260663
39.299944 2.310000 32.471517
38.993500 2.325000 32.682371
38.686285 2.340000 32.893225
38.378291 2.355000 33.104079
38.069508 2.370000 33.314933
37.759930 2.385000 33.525787
37.449548 2.400000 33.736641
37.138353 2.415000 33.947495
36.826337 2.430000 34.158349
36.513491 2.445000 34.369203
36.199805 2.460000 34.580057
35.885269 2.475000 34.790911
35.569875 2.490000 35.001765
35.253612 2.505000 35.212619
34.936469 2.520000 35.423474
34.618436 2.535000 35.634328
34.299503 2.550000 35.845182
33.979657 2.565000 36.056036
33.658887 2.580000 36.266890
33.337182 2.595000 36.477744
33.014528 2.610000 36.688598
32.690914 2.625000 36.899452
32.366325 2.640000 37.110306
32.040748 2.655000 37.321160
31.714169 2.670000 37.532014
31.386576 2.685000 37.742868
31.058108 2.700000 37.953722
30.728863 2.715000 38.164576
30.398840 2.730000 38.375430
30.068036 2.745000 38.586284
29.736448 2.760000 38.797138
29.404071 2.775000 39.007992
29.070902 2.790000 39.218846
28.736938 2.805000 39.429700
28.402175 2.820000 39.640554
28.066610 2.835000 39.851408
27.730240 2.850000 40.062262
27.393061 2.865000 40.273116
27.055071 2.880000 40.483970
26.716265 2.895000 40.694824
26.376641 2.910000 40.905678
26.036197 2.925000 41.116532
25.694928 2.940000 41.327386
25.352833 2.955000 41.538240
25.009908 2.970000 41.749094
24.666151 2.985000 41.959948
24.321560 3.000000 42.170802
23.976132 3.015000 42.381656
23.629866 3.030000 42.592510
23.282758 3.045000 42.803364
22.934808 3.060000 43.014218
22.586015 3.075000 43.225072
22.236376 3.090000 43.435926
21.885892 3.105000 43.646780
21.534561 3.120000 43.857634
21.182384 3.135000 44.068488
20.829361 3.150000 44.279342
20.475493 3.165000 44.490196
20.120781 3.180000 44.701050
19.765227 3.195000 44.911904
19.408835 3.210000 45.122758
19.051609 3.225000 45.333612
18.693552 3.240000 45.544466
18.334793 3.255000 45.755320
17.975875 3.270000 45.966174
17.616919 3.285000 46.177028
17.257970 3.300000 46.387882
16.899079 3.315000 46.598736
16.540297 3.330000 46.809590
16.181683 3.345000 47.020444
15.823299 3.360000 47.231298
15.465212 3.375000 47.442152
15.107493 3.390000 47.653006
14.750223 3.405000 47.863860
14.393487 3.420000 48.074714
14.037378 3.435000 48.285568
13.681997 3.450000 48.496422
13.327455 3.465000 48.707276
12.973871 3.480000 48.918130
12.621377 3.495000 49.128984
12.270117 3.510000 49.339838
11.920246 3.525000 49.550692
11.571935 3.540000 49.761546
11.225370 3.555000 49.972400
10.880755 3.570000 50.183254
10.538310 3.585000 50.394108
10.198276 3.600000 50.604962
9.860913 3.615000 50.815816
9.526502 3.630000 51.026670
9.194786 3.645000 51.237524
8.864425 3.660000 51.448378
8.535501 3.675000 51.659232
8.208281 3.690000 51.870086
7.883066 3.705000 52.080940
7.560188 3.720000 52.291794
7.240018 3.735000 52.502648
6.922960 3.750000 52.713502
6.609459 3.765000 52.924356
6.299994 3.780000 53.135210
5.995077 3.795000 53.346064
5.695251 3.810000 53.556918
5.401081 3.825000 53.767772
5.113148 3.840000 53.978626
4.832038 3.855000 54.189480
4.558329 3.870000 54.400334
4.292583 3.885000 54.611188
4.035323 3.900000 54.822042
3.787028 3.915000 55.032896
3.548111 3.930000 55.243750
3.318917 3.945000 55.454604
3.099704 3.960000 55.665458
2.890645 3.975000 55.876312
2.691822 3.990000 56.087166
2.503225 4.005000 56.298020
2.324760 4.020000 56.508874
2.156254 4.035000 56.719728
1.997466 4.050000 56.930582
1.966849 4.053000 56.972753
1.936606 4.056000 57.014924
1.906734 4.059000 57.057095
1.877231 4.062000 57.099266
1.848094 4.065000 57.141436
1.819319 4.068000 57.183607
1.790904 4.071000 57.225778
1.762846 4.074000 57.267949
1.735142 4.077000 57.310120
1.707788 4.080000 57.352290
1.680781 4.083000 57.394461
1.654118 4.086000 57.436632
1.627796 4.089000 57.478803
1.601811 4.092000 57.520974
1.576161 4.095000 57.563144
1.550841 4.098000 57.605315
1.525848 4.101000 57.647486
1.501179 4.104000 57.689657
1.476831 4.107000 57.731828
1.452799 4.110000 57.773998
1.429081 4.113000 57.816169
1.405673 4.116000 57.858340
1.382572 4.119000 57.900511
1.359773 4.122000 57.942682
1.337274 4.125000 57.984852
1.315070 4.128000 58.027023
1.293159 4.131000 58.069194
1.271536 4.134000 58.111365
1.250199 4.137000 58.153536
1.229144 4.140000 58.195706
1.208367 4.143000 58.237877
1.187864 4.146000 58.280048
1.167633 4.149000 58.322219
1.147669 4.152000 58.364390
1.127970 4.155000 58.406560
1.108531 4.158000 58.448731
1.089349 4.161000 58.490902
1.070422 4.164000 58.533073
1.051744 4.167000 58.575244
1.033314 4.170000 58.617414
1.015128 4.173000 58.659585
0.997181 4.176000 58.701756
0.979472 4.179000 58.743927
0.961996 4.182000 58.786098
0.944750 4.185000 58.828269
0.927731 4.188000 58.870439
0.910936 4.191000 58.912610
0.894362 4.194000 58.954781
0.878005 4.197000 58.996952
0.861861 4.200000 59.039123
0.845928 4.203000 59.081293
0.830203 4.206000 59.123464
0.814682 4.209000 59.165635
0.799363 4.212000 59.207806
0.784243 4.215000 59.249977
0.769318 4.218000 59.292147
0.754585 4.221000 59.334318
0.740042 4.224000 59.376489
0.725685 4.227000 59.418660
0.711512 4.230000 59.460831
0.697520 4.233000 59.503001
0.683705 4.236000 59.545172
0.670065 4.239000 59.587343
0.656575 4.242000 59.629514
0.643192 4.245000 59.671685
0.629914 4.248000 59.713855
0.616739 4.251000 59.756026
0.603668 4.254000 59.798197
0.590700 4.257000 59.840368
0.577834 4.260000 59.882539
0.565071 4.263000 59.924709
0.552409 4.266000 59.966880
0.539832 4.269000 60.009051
0.527356 4.272000 60.051222
0.514979 4.275000 60.093393
0.502701 4.278000 60.135563
0.490522 4.281000 60.177734
0.478441 4.284000 60.219905
0.466456 4.287000 60.262076
0.454569 4.290000 60.304247
0.442777 4.293000 60.346417
0.431080 4.296000 60.388588
0.419478 4.299000 60.430759
0.407969 4.302000 60.472930
0.396553 4.305000 60.515101
0.385226 4.308000 60.557271
0.373989 4.311000 60.599442
0.362838 4.314000 60.641613
0.351775 4.317000 60.683784
0.340796 4.320000 60.725955
0.329900 4.323000 60.768125
0.319087 4.326000 60.810296
0.308354 4.329000 60.852467
0.297702 4.332000 60.894638
0.287129 4.335000 60.936809
0.276633 4.338000 60.978979
0.266213 4.341000 61.021150
0.255866 4.344000 61.063321
0.245592 4.347000 61.105492
0.235388 4.350000 61.147663
0.225252 4.353000 61.189833
0.215182 4.356000 61.232004
0.205174 4.359000 61.274175
0.195225 4.362000 61.316346
0.185333 4.365000 61.358517
0.175492 4.368000 61.400687
0.165698 4.371000 61.442858
0.155946 4.374000 61.485029
0.146231 4.377000 61.527200
0.136544 4.380000 61.569371
0.126878 4.383000 61.611541
0.117222 4.386000 61.653712
0.107566 4.389000 61.695883
0.097894 4.392000 61.738054
0.088190 4.395000 61.780225
0.078430 4.398000 61.822395
0.068587 4.401000 61.864566
0.058623 4.404000 61.906737
0.048489 4.407000 61.948908
0.038115 4.410000 61.991079
0.027405 4.413000 62.033249
0.016227 4.416000 62.075420
0.004537 4.419000 62.117591
0.000722 4.420000 62.131648
79.790002 0.015000 0.210854
79.579751 0.030000 0.421708
79.369246 0.045000 0.632562
79.158487 0.060000 0.843416
78.947471 0.075000 1.054270
78.736199 0.090000 1.265124
78.524670 0.105000 1.475978
78.312882 0.120000 1.686832
78.100834 0.135000 1.897686
77.888526 0.150000 2.108540
77.675956 0.165000 2.319394
77.463123 0.180000 2.530248
77.250028 0.195000 2.741102
77.036667 0.210000 2.951956
76.823041 0.225000 3.162810
76.609149 0.240000 3.373664
76.394988 0.255000 3.584518
76.180560 0.270000 3.795372
75.965861 0.285000 4.006226
75.750892 0.300000 4.217080
75.535651 0.315000 4.427934
75.320137 0.330000 4.638788
75.104350 0.345000 4.849642
74.888287 0.360000 5.060496
74.671949 0.375000 5.271350
74.455333 0.390000 5.482204
74.238439 0.405000 5.693058
74.021265 0.420000 5.903912
73.803812 0.435000 6.114766
73.586076 0.450000 6.325620
73.368058 0.465000 6.536474
73.149756 0.480000 6.747328
72.931170 0.495000 6.958182
72.712297 0.510000 7.169036
72.493136 0.525000 7.379890
72.273688 0.540000 7.590744
72.053949 0.555000 7.801598
71.833920 0.570000 8.012452
71.613599 0.585000 8.223306
71.392984 0.600000 8.434160
71.172076 0.615000 8.645014
70.950871 0.630000 8.855868
70.729370 0.645000 9.066722
70.507570 0.660000 9.277576
70.285471 0.675000 9.488430
70.063072 0.690000 9.699284
69.840371 0.705000 9.910138
69.617366 0.720000 10.120992
69.394057 0.735000 10.331846
69.170442 0.750000 10.542700
68.946521 0.765000 10.753554
68.722291 0.780000 10.964408
68.497751 0.795000 11.175262
68.272900 0.810000 11.386116
68.047737 0.825000 11.596970
67.822260 0.840000 11.807825
67.596468 0.855000 12.018679
67.370360 0.870000 12.229533
67.143933 0.885000 12.440387
66.917188 0.900000 12.651241
66.690122 0.915000 12.862095
66.462734 0.930000 13.072949
66.235022 0.945000 13.283803
66.006985 0.960000 13.494657
65.778622 0.975000 13.705511
65.549931 0.990000 13.916365
65.320911 1.005000 14.127219
65.091560 1.020000 14.338073
64.861876 1.035000 14.548927
64.631859 1.050000 14.759781
64.401506 1.065000 14.970635
64.170817 1.080000 15.181489
63.939789 1.095000 15.392343
63.708421 1.110000 15.603197
63.476711 1.125000 15.814051
63.244658 1.140000 16.024905
63.012260 1.155000 16.235759
62.779516 1.170000 16.446613
62.546424 1.185000 16.657467
62.312982 1.200000 16.868321
62.079188 1.215000 17.079175
61.845042 1.230000 17.290029
61.610540 1.245000 17.500883
61.375683 1.260000 17.711737
61.140467 1.275000 17.922591
60.904891 1.290000 18.133445
60.668953 1.305000 18.344299
60.432652 1.320000 18.555153
60.195986 1.335000 18.766007
59.958953 1.350000 18.976861
59.721550 1.365000 19.187715
59.483777 1.380000 19.398569
59.245632 1.395000 19.609423
59.007112 1.410000 19.820277
58.768216 1.425000 20.031131
58.528941 1.440000 20.241985
58.289287 1.455000 20.452839
58.049250 1.470000 20.663693
57.808829 1.485000 20.874547
57.568022 1.500000 21.085401
57.326827 1.515000 21.296255
57.085242 1.530000 21.507109
56.843265 1.545000 21.717963
56.600894 1.560000 21.928817
56.358126 1.575000 22.139671
56.114960 1.590000 22.350525
55.871394 1.605000 22.561379
55.627425 1.620000 22.772233
55.383051 1.635000 22.983087
55.138270 1.650000 23.193941
54.893079 1.665000 23.404795
54.647478 1.680000 23.615649
54.401462 1.695000 23.826503
54.155030 1.710000 24.037357
53.908181 1.725000 24.248211
53.660910 1.740000 24.459065
53.413216 1.755000 24.669919
53.165097 1.770000 24.880773
52.916550 1.785000 25.091627
52.667572 1.800000 25.302481
52.418162 1.815000 25.513335
52.168316 1.830000 25.724189
51.918033 1.845000 25.935043
51.667309 1.860000 26.145897
51.416142 1.875000 26.356751
51.164529 1.890000 26.567605
50.912468 1.905000 26.778459
50.659956 1.920000 26.989313
50.406990 1.935000 27.200167
50.153568 1.950000 27.411021
49.899686 1.965000 27.621875
49.645342 1.980000 27.832729
49.390533 1.995000 28.043583
49.135257 2.010000 28.254437
48.879509 2.025000 28.465291
48.623288 2.040000 28.676145
48.366589 2.055000 28.886999
48.109411 2.070000 29.097853
47.851749 2.085000 29.308707
47.593602 2.100000 29.519561
47.334965 2.115000 29.730415
47.075835 2.130000 29.941269
46.816210 2.145000 30.152123
46.556085 2.160000 30.362977
46.295458 2.175000 30.573831
46.034324 2.190000 30.784685
45.772681 2.205000 30.995539
45.510525 2.220000 31.206393
45.247852 2.235000 31.417247
44.984659 2.250000 31.628101
44.720942 2.265000 31.838955
44.456697 2.280000 32.049809
44.191920 2.295000 32.260663
43.926608 2.310000 32.471517
43.660757 2.325000 32.682371
43.394362 2.340000 32.893225
43.127419 2.355000 33.104079
42.859925 2.370000 33.314933
42.591875 2.385000 33.525787
42.323265 2.400000 33.736641
42.054090 2.415000 33.947495
41.784346 2.430000 34.158349
41.514029 2.445000 34.369203
41.243133 2.460000 34.580057
40.971655 2.475000 34.790911
40.699589 2.490000 35.001765
40.426930 2.505000 35.212619
40.153674 2.520000 35.423474
39.879815 2.535000 35.634328
39.605348 2.550000 35.845182
39.330269 2.565000 36.056036
39.054570 2.580000 36.266890
38.778248 2.595000 36.477744
38.501297 2.610000 36.688598
38.223709 2.625000 36.899452
37.945481 2.640000 37.110306
37.666605 2.655000 37.321160
37.387076 2.670000 37.532014
37.106888 2.685000 37.742868
36.826033 2.700000 37.953722
36.544505 2.715000 38.164576
36.262298 2.730000 38.375430
35.979405 2.745000 38.586284
35.695819 2.760000 38.797138
35.411531 2.775000 39.007992
35.126536 2.790000 39.218846
34.840825 2.805000 39.429700
34.554390 2.820000 39.640554
34.267224 2.835000 39.851408
33.979318 2.850000 40.062262
33.690664 2.865000 40.273116
33.401252 2.880000 40.483970
33.111075 2.895000 40.694824
32.820122 2.910000 40.905678
32.528384 2.925000 41.116532
32.235851 2.940000 41.327386
31.942514 2.955000 41.538240
31.648362 2.970000 41.749094
31.353390 2.985000 41.959948
31.057731 3.000000 42.170802
30.761442 3.015000 42.381656
30.464524 3.030000 42.592510
30.166974 3.045000 42.803364
29.868788 3.060000 43.014218
29.569965 3.075000 43.225072
29.270503 3.090000 43.435926
28.970397 3.105000 43.646780
28.669647 3.120000 43.857634
28.368249 3.135000 44.068488
28.066201 3.150000 44.279342
27.763501 3.165000 44.490196
27.460146 3.180000 44.701050
27.156134 3.195000 44.911904
26.851463 3.210000 45.122758
26.546130 3.225000 45.333612
26.240133 3.240000 45.544466
25.933470 3.255000 45.755320
25.626139 3.270000 45.966174
25.318138 3.285000 46.177028
25.009465 3.300000 46.387882
24.700118 3.315000 46.598736
24.390096 3.330000 46.809590
24.079395 3.345000 47.020444
23.768016 3.360000 47.231298
23.455957 3.375000 47.442152
23.143216 3.390000 47.653006
22.829792 3.405000 47.863860
22.515684 3.420000 48.074714
22.200891 3.435000 48.285568
21.885414 3.450000 48.496422
21.569251 3.465000 48.707276
21.252402 3.480000 48.918130
20.934868 3.495000 49.128984
20.616649 3.510000 49.339838
20.297746 3.525000 49.550692
19.978161 3.540000 49.761546
19.657895 3.555000 49.972400
19.336950 3.570000 50.183254
19.015330 3.585000 50.394108
18.693038 3.600000 50.604962
18.370165 3.615000 50.815816
18.047147 3.630000 51.026670
17.724091 3.645000 51.237524
17.401030 3.660000 51.448378
17.077998 3.675000 51.659232
16.755034 3.690000 51.870086
16.432178 3.705000 52.080940
16.109472 3.720000 52.291794
15.786963 3.735000 52.502648
15.464700 3.750000 52.713502
15.142737 3.765000 52.924356
14.821130 3.780000 53.135210
14.499942 3.795000 53.346064
14.179238 3.810000 53.556918
13.859091 3.825000 53.767772
13.539577 3.840000 53.978626
13.220781 3.855000 54.189480
12.902793 3.870000 54.400334
12.585711 3.885000 54.611188
12.269640 3.900000 54.822042
11.954695 3.915000 55.032896
11.641000 3.930000 55.243750
11.328689 3.945000 55.454604
11.017906 3.960000 55.665458
10.708808 3.975000 55.876312
10.401565 3.990000 56.087166
10.096356 4.005000 56.298020
9.793379 4.020000 56.508874
9.492842 4.035000 56.719728
9.194399 4.050000 56.930582
9.134840 4.053000 56.972753
9.075321 4.056000 57.014924
9.015844 4.059000 57.057095
8.956409 4.062000 57.099266
8.897019 4.065000 57.141436
8.837674 4.068000 57.183607
8.778377 4.071000 57.225778
8.719128 4.074000 57.267949
8.659929 4.077000 57.310120
8.600783 4.080000 57.352290
8.541689 4.083000 57.394461
8.482651 4.086000 57.436632
8.423669 4.089000 57.478803
8.364746 4.092000 57.520974
8.305883 4.095000 57.563144
8.247081 4.098000 57.605315
8.188344 4.101000 57.647486
8.129671 4.104000 57.689657
8.071067 4.107000 57.731828
8.012531 4.110000 57.773998
7.954067 4.113000 57.816169
7.895676 4.116000 57.858340
7.837360 4.119000 57.900511
7.779121 4.122000 57.942682
7.720962 4.125000 57.984852
7.662884 4.128000 58.027023
7.604891 4.131000 58.069194
7.546983 4.134000 58.111365
7.489163 4.137000 58.153536
7.431433 4.140000 58.195706
7.373797 4.143000 58.237877
7.316255 4.146000 58.280048
7.258812 4.149000 58.322219
7.201468 4.152000 58.364390
7.144226 4.155000 58.406560
7.087090 4.158000 58.448731
7.030061 4.161000 58.490902
6.973143 4.164000 58.533073
6.916337 4.167000 58.575244
6.859646 4.170000 58.617414
6.803074 4.173000 58.659585
6.746623 4.176000 58.701756
6.690296 4.179000 58.743927
6.634095 4.182000 58.786098
6.578024 4.185000 58.828269
6.522085 4.188000 58.870439
6.466281 4.191000 58.912610
6.410616 4.194000 58.954781
6.355091 4.197000 58.996952
6.299712 4.200000 59.039123
6.244479 4.203000 59.081293
6.189397 4.206000 59.123464
6.134468 4.209000 59.165635
6.079697 4.212000 59.207806
6.025085 4.215000 59.249977
5.970636 4.218000 59.292147
5.916354 4.221000 59.334318
5.862241 4.224000 59.376489
5.808301 4.227000 59.418660
5.754538 4.230000 59.460831
5.700954 4.233000 59.503001
5.647553 4.236000 59.545172
5.594338 4.239000 59.587343
5.541313 4.242000 59.629514
5.488481 4.245000 59.671685
5.435845 4.248000 59.713855
5.383409 4.251000 59.756026
5.331177 4.254000 59.798197
5.279151 4.257000 59.840368
5.227335 4.260000 59.882539
5.175733 4.263000 59.924709
5.124348 4.266000 59.966880
5.073183 4.269000 60.009051
5.022242 4.272000 60.051222
4.971528 4.275000 60.093393
4.921045 4.278000 60.135563
4.870796 4.281000 60.177734
4.820784 4.284000 60.219905
4.771012 4.287000 60.262076
4.721485 4.290000 60.304247
4.672205 4.293000 60.346417
4.623176 4.296000 60.388588
4.574400 4.299000 60.430759
4.525881 4.302000 60.472930
4.477623 4.305000 60.515101
4.429628 4.308000 60.557271
4.381899 4.311000 60.599442
4.334440 4.314000 60.641613
4.287253 4.317000 60.683784
4.240342 4.320000 60.725955
4.193710 4.323000 60.768125
4.147358 4.326000 60.810296
4.101290 4.329000 60.852467
4.055510 4.332000 60.894638
4.010018 4.335000 60.936809
3.964819 4.338000 60.978979
3.919914 4.341000 61.021150
3.875307 4.344000 61.063321
3.830998 4.347000 61.105492
3.786992 4.350000 61.147663
3.743290 4.353000 61.189833
3.699894 4.356000 61.232004
3.656806 4.359000 61.274175
3.614029 4.362000 61.316346
3.571564 4.365000 61.358517
3.529414 4.368000 61.400687
3.487579 4.371000 61.442858
3.446062 4.374000 61.485029
3.404864 4.377000 61.527200
3.363987 4.380000 61.569371
3.323432 4.383000 61.611541
3.283201 4.386000 61.653712
3.243294 4.389000 61.695883
3.203714 4.392000 61.738054
3.164460 4.395000 61.780225
3.125534 4.398000 61.822395
3.086936 4.401000 61.864566
3.048668 4.404000 61.906737
3.010730 4.407000 61.948908
2.973123 4.410000 61.991079
2.935847 4.413000 62.033249
2.898902 4.416000 62.075420
2.862289 4.419000 62.117591
2.826008 4.422000 62.159762
2.790059 4.425000 62.201933
2.754442 4.428000 62.244103
2.719157 4.431000 62.286274
2.684203 4.434000 62.328445
2.649581 4.437000 62.370616
2.615290 4.440000 62.412787
2.581330 4.443000 62.454957
2.547700 4.446000 62.497128
2.514399 4.449000 62.539299
2.481427 4.452000 62.581470
2.448782 4.455000 62.623641
2.416465 4.458000 62.665811
2.384474 4.461000 62.707982
2.352807 4.464000 62.750153
2.321465 4.467000 62.792324
2.290445 4.470000 62.834495
2.259746 4.473000 62.876665
2.229368 4.476000 62.918836
2.199308 4.479000 62.961007
2.169566 4.482000 63.003178
2.140139 4.485000 63.045349
2.111026 4.488000 63.087519
2.082225 4.491000 63.129690
2.053735 4.494000 63.171861
2.025554 4.497000 63.214032
1.997680 4.500000 63.256203
1.970111 4.503000 63.298373
1.942845 4.506000 63.340544
1.915880 4.509000 63.382715
1.889215 4.512000 63.424886
1.862846 4.515000 63.467057
1.836773 4.518000 63.509228
1.810992 4.521000 63.551398
1.785502 4.524000 63.593569
1.760300 4.527000 63.635740
1.735384 4.530000 63.677911
1.710752 4.533000 63.720082
1.686402 4.536000 63.762252
1.662330 4.539000 63.804423
1.638536 4.542000 63.846594
1.615015 4.545000 63.888765
1.591767 4.548000 63.930936
1.568788 4.551000 63.973106
1.546076 4.554000 64.015277
1.523628 4.557000 64.057448
1.501443 4.560000 64.099619
1.479516 4.563000 64.141790
1.457847 4.566000 64.183960
1.436432 4.569000 64.226131
1.415269 4.572000 64.268302
1.394355 4.575000 64.310473
1.373688 4.578000 64.352644
1.353265 4.581000 64.394814
1.333084 4.584000 64.436985
1.313142 4.587000 64.479156
1.293436 4.590000 64.521327
1.273964 4.593000 64.563498
1.254723 4.596000 64.605668
1.235711 4.599000 64.647839
1.216925 4.602000 64.690010
1.198363 4.605000 64.732181
1.180021 4.608000 64.774352
1.161898 4.611000 64.816522
1.143991 4.614000 64.858693
1.126298 4.617000 64.900864
1.108815 4.620000 64.943035
1.091541 4.623000 64.985206
1.074472 4.626000 65.027376
1.057607 4.629000 65.069547
1.040943 4.632000 65.111718
1.024477 4.635000 65.153889
1.008207 4.638000 65.196060
0.992130 4.641000 65.238230
0.976244 4.644000 65.280401
0.960547 4.647000 65.322572
0.945036 4.650000 65.364743
0.929709 4.653000 65.406914
0.914564 4.656000 65.449084
0.899597 4.659000 65.491255
0.884808 4.662000 65.533426
0.870192 4.665000 65.575597
0.855748 4.668000 65.617768
0.841474 4.671000 65.659938
0.827368 4.674000 65.702109
0.813426 4.677000 65.744280
0.799648 4.680000 65.786451
0.786030 4.683000 65.828622
0.772571 4.686000 65.870792
0.759269 4.689000 65.912963
0.746120 4.692000 65.955134
0.733123 4.695000 65.997305
0.720276 4.698000 66.039476
0.707577 4.701000 66.081646
0.695023 4.704000 66.123817
0.682613 4.707000 66.165988
0.670345 4.710000 66.208159
0.658198 4.713000 66.250330
0.646139 4.716000 66.292500
0.634165 4.719000 66.334671
0.622275 4.722000 66.376842
0.610468 4.725000 66.419013
0.598746 4.728000 66.461184
0.587106 4.731000 66.503354
0.575550 4.734000 66.545525
0.564076 4.737000 66.587696
0.552684 4.740000 66.629867
0.541365 4.743000 66.672038
0.530122 4.746000 66.714208
0.518960 4.749000 66.756379
0.507878 4.752000 66.798550
0.496877 4.755000 66.840721
0.485954 4.758000 66.882892
0.475111 4.761000 66.925062
0.464347 4.764000 66.967233
0.453660 4.767000 67.009404
0.443051 4.770000 67.051575
0.432519 4.773000 67.093746
0.422064 4.776000 67.135916
0.411684 4.779000 67.178087
0.401380 4.782000 67.220258
0.391150 4.785000 67.262429
0.380992 4.788000 67.304600
0.370905 4.791000 67.346770
0.360889 4.794000 67.388941
0.350942 4.797000 67.431112
0.341064 4.800000 67.473283
0.331254 4.803000 67.515454
0.321510 4.806000 67.557624
0.311833 4.809000 67.599795
0.302220 4.812000 67.641966
0.292672 4.815000 67.684137
0.283186 4.818000 67.726308
0.273763 4.821000 67.768478
0.264401 4.824000 67.810649
0.255099 4.827000 67.852820
0.245855 4.830000 67.894991
0.236668 4.833000 67.937162
0.227536 4.836000 67.979332
0.218458 4.839000 68.021503
0.209430 4.842000 68.063674
0.200452 4.845000 68.105845
0.191521 4.848000 68.148016
0.182634 4.851000 68.190187
0.173788 4.854000 68.232357
0.164979 4.857000 68.274528
0.156204 4.860000 68.316699
0.147458 4.863000 68.358870
0.138737 4.866000 68.401041
0.130033 4.869000 68.443211
0.121341 4.872000 68.485382
0.112652 4.875000 68.527553
0.103957 4.878000 68.569724
0.095245 4.881000 68.611895
0.086501 4.884000 68.654065
0.077709 4.887000 68.696236
0.068846 4.890000 68.738407
0.059887 4.893000 68.780578
0.050794 4.896000 68.822749
0.041522 4.899000 68.864919
0.032004 4.902000 68.907090
0.022153 4.905000 68.949261
0.011872 4.908000 68.991432
0.001362 4.911000 69.033603

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,428 @@
/***************************************************
*
* CompareElasticLocus.C
*
* DEDX_SCALE calibration check that sidesteps the excitation-energy
* peak-fitting degeneracy entirely (see ScanDedxScalePosition.C's
* pinning/boundary problems for why that approach got compromised).
*
* The idea: overlay a THEORETICAL kinematic curve on top of a
* MEASURED locus.
*
* MEASURED : m27Alax_Ef_vs_theta_p_sx3 -- proton angle (purely
* geometric) vs Efix (built from the UNSCALED proton
* tables, per Eloss.py's mass_u>=10 condition). Neither
* ingredient depends on DEDX_SCALE, so this locus
* should be essentially identical across every scale
* folder -- this macro cross-checks that directly.
*
* THEORETICAL: for each trial DEDX_SCALE, pull that scale's own
* reconstructed beam_energy_at_vertex from
* m27Alax_BeamEnergy_vs_VertexZ_sx3 (this DOES depend
* on DEDX_SCALE, via the aluminum/beam table), build a
* Kinematics object with it, and root-find the Ex=0
* (elastic/ground-state) locus across angle using
* predictElasticEnergy() -- copied verbatim from
* TrackRecon.C so the physics matches exactly.
*
* The DEDX_SCALE whose theoretical curve best tracks the measured
* (DEDX_SCALE-independent) locus is your best calibration -- a
* direct kinematic comparison, no spectral fitting involved.
*
* Only load THIS file. Requires Armory/Kinematics.h to be reachable
* from wherever you compile this -- adjust the #include path below
* if your directory layout differs from TrackRecon.C's.
*
* Usage:
*
* .L CompareElasticLocus.C+
*
* std::vector<double> scales = {0.70, 0.75, 0.80, 0.85, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.95, 1.00, 1.05, 1.10, 1.15};
*
* ScoreElasticLocusEdge(scales, -1, "Output_27Al_", "output_27Al.root","_m27Alax+misc_sx3_p/m27Alax_Ef_vs_theta_p_sx3", "_m27Alax+misc_sx3/m27Alax_BeamEnergy_vs_VertexZ_sx3", 15, 50, 5);
*
* CompareElasticLocus(scales);
*
***************************************************/
#ifndef CompareElasticLocus_C
#define CompareElasticLocus_C
#include "Armory/Kinematics.h"
#include <TFile.h>
#include <TH2.h>
#include <TProfile.h>
#include <TGraph.h>
#include <TCanvas.h>
#include <TLegend.h>
#include <cmath>
#include <vector>
// ---- mass constants, copied from TrackRecon.C to match exactly ----
static const double mass_27Al = 26.981538;
static const double mass_4He = 4.002603254;
static const double mass_1H = 1.007825032;
static const double mass_30Si = 29.973770;
// ---- predictElasticEnergy, copied verbatim from TrackRecon.C ----
// Root-finds the ejectile kinetic energy t3 at a given angle such
// that Kinematics::getExc(t3, angle) == 0 (the elastic/ground-state
// locus). Returns -1 if no single root exists in [t3_lo, t3_hi]
// (kinematically forbidden angle, or an ambiguous multi-valued locus).
inline double predictElasticEnergy(Kinematics &kin, double angle3_deg, double t3_lo = 0.001, double t3_hi = 60.0, int iters = 60)
{
const int N = 200;
double dt = (t3_hi - t3_lo) / N;
int n_sign_changes = 0;
double seg_lo = t3_lo, seg_hi = t3_hi;
double prev = kin.getExc(t3_lo, angle3_deg);
for (int k = 1; k <= N; ++k)
{
double t = t3_lo + k * dt;
double cur = kin.getExc(t, angle3_deg);
if (std::isfinite(prev) && std::isfinite(cur) && prev * cur < 0.0)
{
++n_sign_changes;
seg_lo = t - dt;
seg_hi = t;
}
if (std::isfinite(cur))
prev = cur;
}
if (n_sign_changes == 0)
return -1.0; // no root in range (e.g. kinematically forbidden angle)
if (n_sign_changes > 1)
return -1.0; // ambiguous (multi-valued) locus -> reject
double f_lo = kin.getExc(seg_lo, angle3_deg);
for (int i = 0; i < iters; ++i)
{
double t3_mid = 0.5 * (seg_lo + seg_hi);
double f_mid = kin.getExc(t3_mid, angle3_deg);
if (!std::isfinite(f_mid))
return -1.0;
if (f_mid * f_lo <= 0.0)
seg_hi = t3_mid;
else
{
seg_lo = t3_mid;
f_lo = f_mid;
}
}
return 0.5 * (seg_lo + seg_hi);
}
// ---- shared helper: pull a scale's representative beam_energy_at_vertex ----
// Returns -1 on any failure (file/histogram missing, invalid profile bin).
inline double GetBeamEnergyAtVertex(TString folder, TString fileName, TString beamHist, double &repZ_out) {
TFile *f = TFile::Open(folder + "/" + fileName, "READ");
if (!f || f->IsZombie()) return -1;
TH2 *hBeam = (TH2*) f->Get(beamHist);
if (!hBeam) { f->ls(); return -1; }
TProfile *prof = hBeam->ProfileX(Form("beamProf_%s", folder.Data()));
double repZ = prof->GetMean();
int zBin = prof->FindBin(repZ);
double beamE = prof->GetBinContent(zBin);
repZ_out = repZ;
return beamE;
}
// ============================================================
// scales : DEDX_SCALE values to overlay theoretical curves for
// referenceScale : which scale's folder to pull the MEASURED locus
// from -- shouldn't matter which, since the locus is
// independent of DEDX_SCALE (this is cross-checked
// automatically against a second folder, see below)
// folderPrefix, fileName : same convention as the other scan macros
// lociHist : the measured (theta, Ef) 2D histogram
// beamHist : the (vertex_z, beam_energy_at_vertex) 2D histogram
// used to read off each scale's beam_energy_at_vertex
// thetaMin,thetaMax : angle range (degrees) to draw theoretical curves over
// ============================================================
void CompareElasticLocus(
std::vector<double> scales,
double referenceScale = -1, // -1 = use scales[0]
TString folderPrefix = "Output_27Al_",
TString fileName = "output_27Al.root",
TString lociHist = "_m27Alax+misc_sx3_p/m27Alax_Ef_vs_theta_p_sx3",
TString beamHist = "_m27Alax+misc_sx3/m27Alax_BeamEnergy_vs_VertexZ_sx3",
double thetaMin = 20,
double thetaMax = 160
){
if (scales.empty()) { printf("CompareElasticLocus: no scale values given.\n"); return; }
if (referenceScale < 0) referenceScale = scales[0];
// ---------- 1) measured locus from the reference folder ----------
TString refFolder = Form("%s%.2f", folderPrefix.Data(), referenceScale);
TFile *fref = TFile::Open(refFolder + "/" + fileName, "READ");
if (!fref || fref->IsZombie()) {
printf("ERROR: could not open reference folder file: %s\n", (refFolder + "/" + fileName).Data());
return;
}
TH2 *hLocus = (TH2*) fref->Get(lociHist);
if (!hLocus) {
printf("ERROR: '%s' not found in reference folder\n", lociHist.Data());
fref->ls();
return;
}
hLocus->SetDirectory(0);
// ---------- cross-check: does the locus actually look the same in
// a different scale's folder? (validates the core
// assumption this whole approach rests on) ----------
if (scales.size() > 1) {
double otherScale = (scales[0] == referenceScale && scales.size() > 1) ? scales[1] : scales[0];
TString otherFolder = Form("%s%.2f", folderPrefix.Data(), otherScale);
TFile *fother = TFile::Open(otherFolder + "/" + fileName, "READ");
if (fother && !fother->IsZombie()) {
TH2 *hOther = (TH2*) fother->Get(lociHist);
if (hOther) {
double n1 = hLocus->GetEntries(), n2 = hOther->GetEntries();
double m1x = hLocus->GetMean(1), m2x = hOther->GetMean(1);
double m1y = hLocus->GetMean(2), m2y = hOther->GetMean(2);
printf("Cross-check: locus entries/means at scale %.2f vs %.2f:\n", referenceScale, otherScale);
printf(" entries: %.0f vs %.0f\n", n1, n2);
printf(" <theta>: %.3f vs %.3f\n", m1x, m2x);
printf(" <Ef> : %.3f vs %.3f\n", m1y, m2y);
if (n1 > 0 && std::abs(n1 - n2) / n1 > 0.05)
printf(" NOTE: entry counts differ by >5%% -- something upstream of this\n"
" histogram (a cut, a gate) may depend on DEDX_SCALE after all;\n"
" worth investigating before trusting the overlay below.\n");
}
fother->Close();
}
}
// ---------- 2) draw the measured locus ----------
TCanvas *c = new TCanvas("cElasticLocus", "Measured Ef vs theta with theoretical DEDX_SCALE curves", 1000, 700);
hLocus->SetStats(0);
hLocus->Draw("colz");
int colors[] = {kRed, kOrange+7, kSpring+4, kGreen+2, kCyan+2, kAzure+1, kBlue, kViolet, kMagenta+1, kPink+1, kGray+2, kBlack};
int nColors = 12;
TLegend *leg = new TLegend(0.15, 0.60, 0.4, 0.90);
leg->SetBorderSize(0);
leg->SetFillStyle(0);
leg->SetHeader("DEDX_SCALE");
// ---------- 3) for each scale: get beam_energy_at_vertex, build the
// theoretical curve, overlay it ----------
printf("\n%-10s %10s %16s\n", "scale", "rep. Z", "beamE@vertex");
int idx = 0;
for (double scale : scales) {
TString folder = Form("%s%.2f", folderPrefix.Data(), scale);
TFile *f = TFile::Open(folder + "/" + fileName, "READ");
if (!f || f->IsZombie()) {
printf("%-10.2f ERROR: could not open folder\n", scale);
continue;
}
TH2 *hBeam = (TH2*) f->Get(beamHist);
if (!hBeam) {
printf("%-10.2f ERROR: '%s' not found\n", scale, beamHist.Data());
f->ls();
continue;
}
TProfile *prof = hBeam->ProfileX(Form("beamProf_%.2f", scale));
double repZ = prof->GetMean(); // entries-weighted mean vertex_z
int zBin = prof->FindBin(repZ);
double beamE = prof->GetBinContent(zBin);
f->Close();
if (beamE <= 0) {
printf("%-10.2f ERROR: invalid beam energy at representative Z=%.1f\n", scale, repZ);
continue;
}
printf("%-10.2f %10.1f %16.4f\n", scale, repZ, beamE);
Kinematics kin(mass_27Al, mass_4He, mass_1H, mass_30Si, beamE / mass_27Al);
TGraph *g = new TGraph();
for (double th = thetaMin; th <= thetaMax; th += 1.0) {
double Ef = predictElasticEnergy(kin, th);
if (Ef > 0) g->SetPoint(g->GetN(), th, Ef);
}
if (g->GetN() < 2) {
printf("%-10.2f WARNING: theoretical curve has <2 valid points over [%.0f,%.0f] deg\n",
scale, thetaMin, thetaMax);
}
g->SetLineColor(colors[idx % nColors]);
g->SetLineWidth(2);
g->Draw("L SAME");
leg->AddEntry(g, Form("%.2f", scale), "l");
idx++;
}
leg->Draw();
printf("\nThe DEDX_SCALE whose colored curve best tracks the underlying measured\n"
"(colz) density band is your best calibration candidate -- this comparison\n"
"doesn't involve fitting the excitation-energy spectrum at all, so it's\n"
"immune to the mean/sigma degeneracies we ran into scanning peak positions.\n\n");
}
// ============================================================
// ScoreElasticLocusEdge
//
// Quantifies what CompareElasticLocus's plot asks you to eyeball: in
// narrow angle slices across the DISCRIMINATING region (where
// theoretical curves for different DEDX_SCALE actually separate --
// typically low angle; check your CompareElasticLocus plot to see
// where curves diverge vs collapse together before trusting the
// default range here), extract the measured edge (a high percentile
// of Ef, since the Ex=0 locus is a boundary/edge feature, not the
// bulk of the statistics) and compare it against each scale's
// theoretical curve at the same angles. Reports summed squared
// residual vs DEDX_SCALE -- the minimum is your best candidate,
// as an actual number instead of a judgment call.
//
// thetaMin,thetaMax,thetaStep : angle slices to score at -- restrict
// to wherever CompareElasticLocus showed real
// separation between curves
// edgePercentile : the measured "edge" in each angle slice is defined
// as the Ef below which this fraction of that slice's
// counts lie (0.98 default -- near the top of the
// distribution without being thrown off by single
// stray high-Ef outlier bins)
// minEntriesPerSlice : angle slices with fewer total counts than this
// are skipped (too little data to define an edge)
// ============================================================
void ScoreElasticLocusEdge(
std::vector<double> scales,
double referenceScale = -1,
TString folderPrefix = "Output_27Al_",
TString fileName = "output_27Al.root",
TString lociHist = "m27Alax_Ef_vs_theta_p_sx3",
TString beamHist = "m27Alax_BeamEnergy_vs_VertexZ_sx3",
double thetaMin = 15,
double thetaMax = 50,
double thetaStep = 5,
double edgePercentile = 0.98,
int minEntriesPerSlice = 50
){
if (scales.empty()) { printf("ScoreElasticLocusEdge: no scale values given.\n"); return; }
if (referenceScale < 0) referenceScale = scales[0];
TString refFolder = Form("%s%.2f", folderPrefix.Data(), referenceScale);
TFile *fref = TFile::Open(refFolder + "/" + fileName, "READ");
if (!fref || fref->IsZombie()) {
printf("ERROR: could not open reference folder file: %s\n", (refFolder + "/" + fileName).Data());
return;
}
TH2 *hLocus = (TH2*) fref->Get(lociHist);
if (!hLocus) {
printf("ERROR: '%s' not found in reference folder\n", lociHist.Data());
fref->ls();
return;
}
hLocus->SetDirectory(0);
// ---------- 1) extract the measured edge in each angle slice ----------
std::vector<double> thetaSlices, measuredEdge;
TAxis *xax = hLocus->GetXaxis();
for (double th = thetaMin; th <= thetaMax; th += thetaStep) {
int b1 = xax->FindBin(th - thetaStep/2.0);
int b2 = xax->FindBin(th + thetaStep/2.0);
TH1D *slice = hLocus->ProjectionY(Form("slice_%.1f", th), b1, b2);
double total = slice->Integral();
if (total < minEntriesPerSlice) {
printf("theta=%.1f: skipped (only %.0f entries, need >= %d)\n", th, total, minEntriesPerSlice);
delete slice;
continue;
}
double cum = 0, edge = -1;
int nb = slice->GetNbinsX();
for (int b = 1; b <= nb; b++) {
cum += slice->GetBinContent(b);
if (cum / total >= edgePercentile) { edge = slice->GetBinCenter(b); break; }
}
delete slice;
if (edge <= 0) continue;
thetaSlices.push_back(th);
measuredEdge.push_back(edge);
printf("theta=%.1f: measured edge (p%.0f) = %.3f MeV\n", th, edgePercentile*100, edge);
}
if (thetaSlices.empty()) {
printf("ERROR: no usable angle slices -- widen [thetaMin,thetaMax], lower minEntriesPerSlice,\n"
"or lower edgePercentile.\n");
return;
}
// ---------- 2) score each scale against the measured edge ----------
TGraph *gScore = new TGraph();
gScore->SetTitle("Sum-squared edge residual vs DEDX_SCALE;DEDX_SCALE;#Sigma(theory - measured edge)^{2} [MeV^{2}]");
gScore->SetMarkerStyle(20);
printf("\n%-10s %16s\n", "scale", "sum sq. resid.");
double bestScale = -1, bestScore = 1e18;
for (double scale : scales) {
TString folder = Form("%s%.2f", folderPrefix.Data(), scale);
double repZ;
double beamE = GetBeamEnergyAtVertex(folder, fileName, beamHist, repZ);
if (beamE <= 0) {
printf("%-10.2f ERROR: invalid/missing beam energy\n", scale);
continue;
}
Kinematics kin(mass_27Al, mass_4He, mass_1H, mass_30Si, beamE / mass_27Al);
double sumSq = 0;
int nUsed = 0;
for (size_t i = 0; i < thetaSlices.size(); i++) {
double theory = predictElasticEnergy(kin, thetaSlices[i]);
if (theory <= 0) continue; // kinematically forbidden / ambiguous at this angle
double resid = theory - measuredEdge[i];
sumSq += resid * resid;
nUsed++;
}
if (nUsed == 0) {
printf("%-10.2f ERROR: theoretical curve invalid at every scored angle\n", scale);
continue;
}
printf("%-10.2f %16.4f (%d/%d angles used)\n", scale, sumSq, nUsed, (int)thetaSlices.size());
gScore->SetPoint(gScore->GetN(), scale, sumSq);
if (sumSq < bestScore) { bestScore = sumSq; bestScale = scale; }
}
TCanvas *c = new TCanvas("cScoreElasticLocusEdge", "DEDX_SCALE via elastic-locus edge matching", 900, 650);
gScore->Draw("APL");
if (bestScale > 0) {
printf("\nBest-matching DEDX_SCALE among tested values (minimum summed residual): %.2f\n", bestScale);
// ---------- parabolic refinement near the minimum ----------
// Fit only the points close to the discrete minimum, rather than
// the whole curve, since the score isn't parabolic far from the
// minimum (see the steep rise at the edges of your scan) -- a
// global parabola fit would be pulled around by those points.
double fitWindow = 3 * (scales.size() > 1 ? std::abs(scales[1]-scales[0]) : 0.1);
// widen the window a bit so at least a handful of points are
// typically included even with uneven scale spacing
fitWindow = std::max(fitWindow, 0.08);
TF1 *parab = new TF1("parab", "pol2", bestScale - fitWindow, bestScale + fitWindow);
TFitResultPtr fr = gScore->Fit(parab, "RSQ"); // R: restrict to window, S: get result, Q: quiet
parab->SetLineColor(kRed);
parab->SetLineStyle(2);
parab->Draw("SAME");
double a = parab->GetParameter(2), b = parab->GetParameter(1);
if (a > 0) { // sanity: should open upward near a true minimum
double vertexScale = -b / (2*a);
printf("Parabolic refinement (fit window: scale in [%.3f, %.3f]):\n", bestScale-fitWindow, bestScale+fitWindow);
printf(" analytic minimum at DEDX_SCALE = %.4f\n\n", vertexScale);
} else {
printf("Parabolic fit near the minimum did not open upward (a=%.3g) -- the\n"
"points there may be too flat/noisy for a reliable sub-grid estimate;\n"
"trust the discrete best value (%.2f) instead.\n\n", a, bestScale);
}
}
}
#endif

107
scratch/PlotDedxScan.C Normal file
View File

@ -0,0 +1,107 @@
/***************************************************
*
* PlotDedxScan.C
*
* Builds the comma-separated file/label lists make_pretty.C's
* multi-file overlay function expects, straight from your
* DEDX_SCALE scan -- so you can superimpose every scale's histogram
* for a given gate (a1c2fix, a1c1c2, etc.) in one call, without
* typing out each file path and label by hand.
*
* Only load THIS file -- it already #includes make_pretty.C.
*
* Usage:
*
* .L PlotDedxScan.C
** std::vector<double> scales = {0.70, 0.75, 0.80, 0.85, 0.87, 0.90, 0.92, 0.95, 1.00, 1.05, 1.10, 1.15};
* PlotDedxScan(scales,
* "_m27Alax+misc_sx3_p/m27Alax_Ex_from_p_a1c1c2_sx3");
*
* // or for the a1c2fix gate:
* PlotDedxScan(scales,
* "_m27Alax+misc_sx3_p/m27Alax_Ex_from_p_a1c2fix_sx3");
*
***************************************************/
#ifndef PlotDedxScan_C
#define PlotDedxScan_C
#include "scratch/make_prettyplots.C"
#include <vector>
// ============================================================
// scales : the DEDX_SCALE values from your bash scan, e.g.
// {0.70, 0.75, ..., 1.20} -- MUST match your folder
// names exactly (same decimal formatting), since each
// path is built as folderPrefix + scale + "/" + fileName
// histPath : histogram path inside each file (same for every
// scale), e.g. "_m27Alax+misc_sx3_p/m27Alax_Ex_from_p_a1c1c2_sx3"
// folderPrefix : e.g. "Output_27Al_"
// fileName : ROOT file name inside each folder, e.g. "output_27Al.root"
// xlabel,ylabel: axis titles for the overlay plot
// xMin,xMax : x-axis zoom range -- set these to the region where your
// peaks actually live (e.g. -3, 9) to cut out the flat,
// empty tails and make the overlaid curves easier to read.
// Leave at -9999 for the full auto range.
// yMin,yMax : optional y-axis range; leave at -9999 for auto
// canvasW,canvasH : output image size in pixels. Defaults here (3000x2100)
// are larger than make_pretty.C's own defaults (2100x1575)
// since a busy multi-curve overlay benefits from the extra
// resolution -- especially once zoomed in with xMin/xMax.
// maxOverlay : if scales.size() exceeds this, evenly subsample down to
// maxOverlay curves (always keeping the first and last)
// rather than plotting everything -- past ~5-6 overlapping
// histograms in the same narrow x-range, more curves stops
// helping and just makes the plot harder to read regardless
// of resolution. Set to 0 to disable subsampling entirely.
// ============================================================
void PlotDedxScan(
std::vector<double> scales,
TString histPath,
TString folderPrefix = "Output_27Al_",
TString fileName = "output_27Al.root",
TString xlabel = "Excitation Energy [MeV]",
TString ylabel = "Counts",
double xMin = -4.0,
double xMax = 8.0,
double yMin = -9999.0,
double yMax = -9999.0,
int canvasW = 3000,
int canvasH = 2100,
int maxOverlay = 6
){
if (maxOverlay > 0 && (int)scales.size() > maxOverlay) {
std::vector<double> subset;
int n = (int) scales.size();
for (int k = 0; k < maxOverlay; k++) {
int idx = (maxOverlay == 1) ? 0 : (int) std::round(k * (n - 1) / double(maxOverlay - 1));
subset.push_back(scales[idx]);
}
printf("PlotDedxScan: %d scales given, subsampling to %d for readability: ", n, maxOverlay);
for (double s : subset) printf("%.2f ", s);
printf("\n(pass maxOverlay=0, or maxOverlay >= %d, to plot all of them)\n", n);
scales = subset;
}
if (scales.empty()) {
printf("PlotDedxScan: no scale values given.\n");
return;
}
TString filesCSV, labelsCSV;
for (size_t i = 0; i < scales.size(); i++) {
TString folder = Form("%s%.2f", folderPrefix.Data(), scales[i]);
TString path = folder + "/" + fileName;
if (i > 0) { filesCSV += ","; labelsCSV += ","; }
filesCSV += path;
labelsCSV += Form("%.2f", scales[i]);
}
printf("Overlaying %d scale value(s) for histogram: %s\n", (int) scales.size(), histPath.Data());
// matches make_pretty.C's multi-file overlay overload exactly:
// (filesCSV, labelsCSV, histName, xAxisLabel, yAxisLabel, yMin, yMax, xMin, xMax, canvasW, canvasH)
make_prettyplots(filesCSV, labelsCSV, histPath, xlabel, ylabel, yMin, yMax, xMin, xMax, canvasW, canvasH);
}
#endif

548
scratch/RunMultiFit.C Normal file
View File

@ -0,0 +1,548 @@
/***************************************************
*
* RunMultiFit.C
*
* Two fitting functions for multi-Gaussian excitation-energy spectra:
*
* RunMultiFit(...) -- wrapper around AutoFit.C's fitNGaussPol():
* 1) opens a ROOT file living anywhere on disk
* 2) pulls out a histogram, including ones nested inside
* TDirectories within the file (e.g. "subdir/histname")
* 3) auto-generates the AutoFit-style parameter text file
* from a plain list of peak positions
* 4) runs the n-Gauss + polynomial-background fit
* 5) prints peak-amplitude correlations (via PrintCorrelations)
*
* RunMultiFitWithTail(...) -- same idea, but builds its own TF1
* directly (bypassing fitNGaussPol) to add an extra background
* term -- an exponential or Fermi/sigmoid tail -- for modeling a
* fusion-evaporation-like continuum on the low-Ex side, which
* fitNGaussPol's gaus(i)+pol(deg)-only parameter file has no way
* to express.
*
* Only load THIS file -- it already #includes AutoFit.C,
* so don't separately .L AutoFit.C or you'll double-load it.
*
* Usage (from the ROOT prompt, with both files in the same dir):
*
* .L RunMultiFit.C+
*
* std::vector<double> peaks = {0, 2.2, 3.4, 4.8, 5.6, 6.55};
*
* RunMultiFit(
* "/full/path/to/your/folder/yourfile.root",
* "_m27Alax+misc_sx3_p/m27Alax_EX_from_p_a2c0_sx3",
* peaks
* );
*
* // or, with a fusion-evaporation tail on the low-Ex background:
* RunMultiFitWithTail(
* "/full/path/to/your/folder/yourfile.root",
* "_m27Alax+misc_sx3_p/m27Alax_EX_from_p_a2c0_sx3",
* peaks
* );
*
***************************************************/
#ifndef RunMultiFit_C
#define RunMultiFit_C
// AutoFit.C uses TH1F*, ifstream, TCanvas, gROOT, gStyle, TLatex, and TList
// throughout but only gets forward declarations (or nothing at all) for
// several of them via its own includes -- fine for cling's interpreter,
// not enough for ACLiC's real compiler. Pull in full definitions here,
// before AutoFit.C is included, so they're available everywhere in this
// translation unit.
#include <fstream>
#include <TH1.h>
#include <TF1.h>
#include <TROOT.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TLatex.h>
#include <TList.h>
#include "AutoFit.C"
#include <TFile.h>
#include <TVirtualFitter.h>
#include <fstream>
#include <vector>
// ============================================================
// PrintCorrelations: prints the correlation coefficient between every
// pair of peak amplitudes from the most recently run fit. Deliberately
// uses TVirtualFitter rather than the TFitResultPtr returned by
// h->Fit(f,"S") -- on some ROOT/cling builds, holding a TFitResultPtr
// at the interactive prompt crashes with a
// "cling::runtime::internal::LifetimeHandler" linker error. Reading
// straight from TVirtualFitter's covariance matrix gets the same
// numbers without touching that code path.
//
// f : the fit TF1 (e.g. from h->GetFunction("fit"))
// nPeaks : number of Gaussian peaks in the fit (not counting the
// background parameters)
// warnThreshold: |correlation| at or above this gets flagged -- pairs
// this correlated shouldn't be trusted individually;
// treat their combined area as the meaningful number
// stride : parameters per peak before the shared/background block
// -- 3 (default) for independent amp/mean/sigma per peak,
// 2 for RunMultiFitWithTail's sharedSigma=true mode
// (amp/mean per peak, sigma shared separately)
// ============================================================
void PrintCorrelations(TF1 *f, int nPeaks, double warnThreshold = 0.8, int stride = 3) {
if (!f) {
printf("PrintCorrelations: no fit function given (was the fit successful?).\n");
return;
}
TVirtualFitter *fitter = TVirtualFitter::GetFitter();
if (!fitter) {
printf("PrintCorrelations: no active fitter found -- run the fit first.\n");
return;
}
printf("\n================ Peak-amplitude correlations ================\n");
printf("%-8s %-8s %10s\n", "peakA", "peakB", "corr");
std::vector<TString> flagged;
for (int i = 0; i < nPeaks; i++) {
for (int j = i + 1; j < nPeaks; j++) {
int pi = stride * i, pj = stride * j; // amplitude is the first of each peak's params
double covij = fitter->GetCovarianceMatrixElement(pi, pj);
double si = f->GetParError(pi);
double sj = f->GetParError(pj);
double corr = (si > 0 && sj > 0) ? covij / (si * sj) : 0;
bool isHigh = TMath::Abs(corr) >= warnThreshold;
printf("%-8d %-8d %10.3f%s\n", i, j, corr, isHigh ? " <-- high" : "");
if (isHigh) flagged.push_back(Form("peak %d <-> peak %d (corr = %.3f)", i, j, corr));
}
}
if (!flagged.empty()) {
printf("\n %d pair(s) at |corr| >= %.2f -- their individual areas are not\n"
" reliably separable; treat the combined area as the trustworthy number:\n",
(int) flagged.size(), warnThreshold);
for (auto &s : flagged) printf(" %s\n", s.Data());
}
printf("===============================================================\n\n");
}
// ============================================================
// fileName : full path to the .root file (the "folder" part
// of the path is just the directory it lives in --
// TFile::Open handles that directly, see below)
// histPath : name of the histogram inside the file. If the
// histogram lives inside a TDirectory, include the
// directory the same way you would in TBrowser,
// e.g. "dirName/histName" (works for nested dirs too:
// "dir1/dir2/histName")
// peakEnergies : your peak positions, e.g. {0,2.2,3.4,4.8,5.6,6.55}
// sigmaGuess : default initial sigma (same units as x-axis) used
// for every peak unless overridden per-peak below
// meanWindow : half-width allowed around each mean during the fit
// (used only for peaks not covered by meanWindowOverride).
// 0 -> auto: half the distance to the nearest
// neighboring peak on each side (tighter
// windows automatically appear for closely
// spaced peaks, e.g. two peaks 0.8 apart
// each get +/-0.4 max)
// >0 -> fixed +/- meanWindow
// degPol : degree of the polynomial background (0=flat,
// 1=linear, 2=quadratic, ...)
// xMin, xMax : fit range; leave both at 0 to use the full
// histogram range
// fixMeans : true locks every mean at its input value instead
// of letting it float within its window
// fixSigmas : true locks every sigma at its guess instead of
// letting it float up to that value
// paraFile : where the auto-generated parameter file is written
// (plain text, human-readable/editable afterward)
// sigmaOverride : optional per-peak sigma guesses; if given, overrides
// sigmaGuess for peaks with a matching index
// printCorr : if true (default), automatically prints the peak-
// amplitude correlation matrix after fitting, flagging
// any pair whose areas aren't reliably separable
// corrWarnThreshold : |correlation| at/above this gets flagged in the
// printout (see PrintCorrelations above)
// ============================================================
void RunMultiFit(
TString fileName,
TString histPath,
std::vector<double> peakEnergies,
double sigmaGuess = 0.15,
double meanWindow = 0,
int degPol = 1,
double xMin = 0,
double xMax = 0,
bool fixMeans = false,
bool fixSigmas = false,
TString paraFile = "AutoFit_para_auto.txt",
std::vector<double> sigmaOverride = {},
bool printCorr = true,
double corrWarnThreshold = 0.8,
std::vector<double> meanWindowOverride = {}
){
// ---------- 1) open the file ----------
// TFile::Open takes the full path, folder included, e.g.
// "/home/user/data/run074/analysis.root" -- no separate step
// needed to "open the folder" first.
TFile *f = TFile::Open(fileName, "READ");
if (!f || f->IsZombie()) {
printf("ERROR: could not open file: %s\n", fileName.Data());
return;
}
// ---------- 2) get the histogram ----------
TH1F *h = (TH1F*) f->Get(histPath);
if (!h) {
printf("ERROR: histogram not found at path: %s\n", histPath.Data());
printf("---- top-level contents of the file, for reference ----\n");
f->ls();
return;
}
h->SetDirectory(0); // detach from file so it's safe even after f closes
// ---------- 3) build the AutoFit parameter file ----------
int n = (int) peakEnergies.size();
if (n == 0) {
printf("ERROR: no peak energies given.\n");
return;
}
std::ofstream out(paraFile.Data());
out << "# energy lowE highE eFlag sigma sFlag height\n";
for (int i = 0; i < n; i++) {
double e = peakEnergies[i];
double lo, hi;
double thisWindow = (i < (int)meanWindowOverride.size()) ? meanWindowOverride[i] : meanWindow;
if (thisWindow > 0) {
lo = e - thisWindow;
hi = e + thisWindow;
} else {
// half the gap to each neighbor; edge peaks reuse their
// only neighbor's gap on both sides
double dLeft = (i == 0) ? (peakEnergies[i+1] - e) : (e - peakEnergies[i-1]);
double dRight = (i == n - 1) ? (e - peakEnergies[i-1]) : (peakEnergies[i+1] - e);
lo = e - dLeft / 2.0;
hi = e + dRight / 2.0;
}
double sig = (i < (int)sigmaOverride.size()) ? sigmaOverride[i] : sigmaGuess;
double guess = h->GetBinContent(h->FindBin(e));
if (guess <= 0) guess = h->GetMaximum() * 0.05; // avoid a zero starting amplitude
out << e << " "
<< lo << " "
<< hi << " "
<< (fixMeans ? 1 : 0) << " "
<< sig << " "
<< (fixSigmas ? 1 : 0) << " "
<< guess << "\n";
}
out.close();
printf("Wrote %d-peak parameter file: %s\n", n, paraFile.Data());
for (int i = 0; i < n; i++) {
printf(" peak %d : E = %.4f\n", i, peakEnergies[i]);
}
// ---------- 4) run the fit ----------
fitNGaussPol(h, degPol, paraFile, xMin, xMax);
// ---------- 5) report peak-amplitude correlations ----------
// fitNGaussPol names its internal TF1 "fit" and fits directly on h,
// so ROOT attaches it to h's list of functions -- retrieve it from
// there rather than needing fitNGaussPol to return anything.
if (printCorr) {
TF1 *fit = h->GetFunction("fit");
PrintCorrelations(fit, n, corrWarnThreshold);
}
}
// ============================================================
// RunMultiFitWithTail
//
// Fits N Gaussians + a polynomial background + an extra background
// term representing a fusion-evaporation-like continuum tail on the
// low-Ex side of the spectrum.
//
// AutoFit.C's fitNGaussPol has no way to express this extra term --
// its parameter file only knows gaus(i) + pol(deg) -- so this builds
// and fits its own TF1 directly instead of routing through it, then
// reuses PrintCorrelations above (which works with any TF1*, not
// tied to fitNGaussPol internals).
//
// tailShape:
// "fermi" (default) : A / (1 + exp((x - x0)/d))
// Smooth sigmoid: ~flat at A for low x, turns off toward 0
// above x0. BOUNDED for all x -- numerically safe regardless
// of fit range. x0 is interpretable as roughly where the
// continuum "turns off"; d is the turn-off width.
// "exp" : A * exp(-x / tau)
// Simpler, more directly matches "evaporation spectrum"
// language, but can blow up for x well below 0 if tau is
// small (e.g. tau=0.1 at x=-3 gives exp(30)). Only use this
// if your fit range doesn't extend far below the peaks, or if
// you've confirmed tau stays large enough to behave.
//
// fileName, histPath : same as RunMultiFit
// peakEnergies : peak means (fixed by default -- see fixMeans)
// sigmaGuess : default initial sigma used for every peak,
// unless overridden per-peak by sigmaOverride
// degPol : background polynomial degree
// xMin, xMax : fit range (required here -- no "full range"
// default, since the tail shape depends on
// where the range actually starts)
// tailAmpGuess : initial tail amplitude; -1 = auto (0.5x hist max)
// tailScaleGuess : tau (exp) or d/width (fermi)
// tailX0Guess : only used for "fermi" -- initial turn-off location
// fixMeans : true (default) locks peak means at peakEnergies,
// consistent with how you've been running RunMultiFit
// fixSigmas : true locks every sigma at its guess/override
// instead of letting it float (default false)
// sigmaOverride : optional per-peak sigma guesses, e.g.
// {1.2, 1.0, 0.3, 0.3, 0.4, 0.4, 0.4} -- overrides
// sigmaGuess for peaks with a matching index. Use
// this the same way you've been using it in
// RunMultiFit to give wide peaks (like your 0 and
// 2.2 MeV ones) more room without loosening
// everyone else's ceiling too. IGNORED if
// sharedSigma=true (see below).
// sharedSigma : if true, every peak shares ONE sigma parameter
// instead of getting its own -- tests the
// hypothesis that peak width is genuinely
// constant across the spectrum, rather than
// assuming it. sigmaOverride is ignored in this
// mode (there's only one sigma to set, from
// sigmaGuess); fixSigmas still works to lock
// that single shared value. Compare chi2/ndf and
// the residuals against a free-sigma run: if
// shared-sigma fits comparably well, your
// instinct that width shouldn't vary was right;
// if it fits noticeably worse -- especially
// around peaks you know are blended multi-level
// clusters (4.8, 5.6, 6.55) -- that's evidence
// the width differences are physically real,
// not fit noise.
// ============================================================
void RunMultiFitWithTail(
TString fileName,
TString histPath,
std::vector<double> peakEnergies,
double sigmaGuess = 0.5,
int degPol = 1,
double xMin = -3,
double xMax = 9,
TString tailShape = "fermi",
double tailAmpGuess = -1,
double tailScaleGuess = 1.0,
double tailX0Guess = 0.0,
bool fixMeans = true,
bool fixSigmas = false,
std::vector<double> sigmaOverride = {},
bool sharedSigma = false
){
// ---------- open file + histogram ----------
TFile *f = TFile::Open(fileName, "READ");
if (!f || f->IsZombie()) {
printf("ERROR: could not open file: %s\n", fileName.Data());
return;
}
TH1 *h = (TH1*) f->Get(histPath);
if (!h) {
printf("ERROR: histogram not found at path: %s\n", histPath.Data());
printf("---- top-level contents of the file, for reference ----\n");
f->ls();
return;
}
h->SetDirectory(0);
int nPeaks = (int) peakEnergies.size();
if (nPeaks == 0) { printf("ERROR: no peak energies given.\n"); return; }
if (tailShape != "fermi" && tailShape != "exp") {
printf("ERROR: tailShape must be \"fermi\" or \"exp\", got \"%s\"\n", tailShape.Data());
return;
}
// ---------- index layout ----------
// Normal mode: each peak gets 3 params [amp, mean, sigma] at 3*i.
// Shared-sigma mode: each peak gets 2 params [amp, mean] at 2*i, and
// ALL peaks reference the same single sigma parameter index, placed
// right after the last peak's amp/mean pair.
int stride = sharedSigma ? 2 : 3;
auto ampIdx = [&](int i){ return stride*i; };
auto meanIdx = [&](int i){ return stride*i + 1; };
int sharedSigmaIdx = stride*nPeaks; // only meaningful if sharedSigma
auto sigIdx = [&](int i){ return sharedSigma ? sharedSigmaIdx : (stride*i + 2); };
if (sharedSigma && !sigmaOverride.empty())
printf("NOTE: sharedSigma=true -- sigmaOverride is ignored; using sigmaGuess (%.3f) for the single shared sigma.\n", sigmaGuess);
// ---------- build the formula: gaussians + poly + tail ----------
TString formula;
for (int i = 0; i < nPeaks; i++) {
if (i > 0) formula += "+";
formula += Form("[%d]*exp(-0.5*((x-[%d])/[%d])*((x-[%d])/[%d]))",
ampIdx(i), meanIdx(i), sigIdx(i), meanIdx(i), sigIdx(i));
}
int polOffset = sharedSigma ? (stride*nPeaks + 1) : (stride*nPeaks);
formula += Form("+pol%d(%d)", degPol, polOffset);
int tailOffset = polOffset + (degPol + 1);
int nTailPar = (tailShape == "exp") ? 2 : 3;
if (tailShape == "exp")
formula += Form("+[%d]*exp(-x/[%d])", tailOffset, tailOffset+1);
else
formula += Form("+[%d]/(1+exp((x-[%d])/[%d]))", tailOffset, tailOffset+1, tailOffset+2);
TF1 *fitT = new TF1("fitWithTail", formula, xMin, xMax);
// ---------- initial guesses: peaks ----------
for (int i = 0; i < nPeaks; i++) {
double e = peakEnergies[i];
double guess = h->GetBinContent(h->FindBin(e));
if (guess <= 0) guess = h->GetMaximum() * 0.3;
fitT->SetParameter(ampIdx(i), guess);
fitT->SetParLimits(ampIdx(i), 0, h->GetMaximum() * 2);
fitT->SetParameter(meanIdx(i), e);
if (fixMeans) fitT->FixParameter(meanIdx(i), e);
else fitT->SetParLimits(meanIdx(i), e - 0.2, e + 0.2);
if (!sharedSigma) {
double sig = (i < (int)sigmaOverride.size()) ? sigmaOverride[i] : sigmaGuess;
fitT->SetParameter(sigIdx(i), sig);
if (fixSigmas) fitT->FixParameter(sigIdx(i), sig);
else fitT->SetParLimits(sigIdx(i), 0.02, 3.0);
}
}
if (sharedSigma) {
fitT->SetParameter(sharedSigmaIdx, sigmaGuess);
if (fixSigmas) fitT->FixParameter(sharedSigmaIdx, sigmaGuess);
else fitT->SetParLimits(sharedSigmaIdx, 0.02, 3.0);
}
// ---------- initial guesses: polynomial ----------
for (int i = 0; i <= degPol; i++)
fitT->SetParameter(polOffset + i, (i == 0) ? 1.0 : 0.0);
// ---------- initial guesses: tail ----------
double ampGuess = (tailAmpGuess > 0) ? tailAmpGuess : h->GetMaximum() * 0.5;
fitT->SetParameter(tailOffset, ampGuess);
fitT->SetParLimits(tailOffset, 0, h->GetMaximum() * 3);
if (tailShape == "exp") {
fitT->SetParameter(tailOffset+1, tailScaleGuess);
fitT->SetParLimits(tailOffset+1, 0.3, 10); // kept away from very small tau -- see header caution
} else {
fitT->SetParameter(tailOffset+1, tailX0Guess);
fitT->SetParLimits(tailOffset+1, xMin, xMax);
fitT->SetParameter(tailOffset+2, tailScaleGuess);
fitT->SetParLimits(tailOffset+2, 0.02, 5);
}
// ---------- fit ----------
// "R0": R restricts to the given range; 0 suppresses TH1::Fit's default
// behavior of auto-drawing the fit function (in red) onto whatever pad
// is currently active -- without this, that auto-draw can land on a
// leftover pad from a previous call (e.g. if you're comparing a
// free-sigma run against a sharedSigma run back-to-back) and show up
// as a stray extra curve wherever gPad happened to be pointing.
h->Fit(fitT, "R0");
// unique run tag so re-running with different settings (e.g. comparing
// sharedSigma true/false) gets its own canvas instead of colliding by
// name with a previous run's
TString runTag = Form("%s_%s", tailShape.Data(), sharedSigma ? "shared" : "free");
// ---------- draw: two-pad canvas (fit + residual), matching the
// fitNGaussPol look you've been using throughout ----------
TCanvas *c = new TCanvas("cFitWithTail_" + runTag, "Fit with fusion-evap tail: " + runTag, 900, 900);
c->Divide(1, 2);
// ---- top pad: histogram + total fit + individual peaks + background ----
c->cd(1);
gPad->SetPad(0, 0.3, 1, 1);
h->SetStats(0);
h->Draw();
int colors[] = {kRed, kGreen+2, kBlue, kMagenta+1, kOrange+7, kCyan+2, kViolet, kSpring+4, kPink+1, kAzure+1};
int nColors = 10;
std::vector<TF1*> peakCurves(nPeaks);
for (int i = 0; i < nPeaks; i++) {
peakCurves[i] = new TF1(Form("peak%d_%s", i, runTag.Data()), "gaus", xMin, xMax);
peakCurves[i]->SetParameter(0, fitT->GetParameter(ampIdx(i)));
peakCurves[i]->SetParameter(1, fitT->GetParameter(meanIdx(i)));
peakCurves[i]->SetParameter(2, fitT->GetParameter(sigIdx(i)));
peakCurves[i]->SetLineColor(colors[i % nColors]);
peakCurves[i]->SetLineWidth(2);
peakCurves[i]->Draw("SAME");
}
// combined background (polynomial + tail), so its shape under the peaks is visible
TString bgFormula = Form("pol%d(0)", degPol);
int bgTailOffset = degPol + 1;
if (tailShape == "exp")
bgFormula += Form("+[%d]*exp(-x/[%d])", bgTailOffset, bgTailOffset+1);
else
bgFormula += Form("+[%d]/(1+exp((x-[%d])/[%d]))", bgTailOffset, bgTailOffset+1, bgTailOffset+2);
TF1 *bgCurve = new TF1("bgCurve_" + runTag, bgFormula, xMin, xMax);
for (int i = 0; i <= degPol; i++) bgCurve->SetParameter(i, fitT->GetParameter(polOffset+i));
for (int i = 0; i < nTailPar; i++) bgCurve->SetParameter(bgTailOffset+i, fitT->GetParameter(tailOffset+i));
bgCurve->SetLineColor(kGray+2);
bgCurve->SetLineStyle(2);
bgCurve->SetLineWidth(2);
bgCurve->Draw("SAME");
fitT->SetLineColor(kBlack);
fitT->SetLineWidth(3);
fitT->Draw("SAME");
double chi2 = fitT->GetChisquare();
int ndf = fitT->GetNDF();
TLatex latex;
latex.SetNDC();
latex.SetTextSize(0.06);
latex.DrawLatex(0.15, 0.85, Form("#bar{#chi}^{2} : %.3f", ndf > 0 ? chi2/ndf : chi2));
// ---- bottom pad: residual (Hist - fit), same convention as fitNGaussPol ----
c->cd(2);
gPad->SetPad(0, 0, 1, 0.3);
TH1 *hRes = (TH1*) h->Clone("hRes_" + runTag);
hRes->Add(fitT, -1);
hRes->SetTitle("Residual");
hRes->GetYaxis()->SetTitle("Hist - fit");
hRes->SetStats(0);
hRes->Draw();
// ---------- report ----------
printf("\n---- tail parameters (%s) ----\n", tailShape.Data());
if (tailShape == "exp") {
printf(" amplitude = %.4f +/- %.4f\n", fitT->GetParameter(tailOffset), fitT->GetParError(tailOffset));
printf(" tau = %.4f +/- %.4f\n", fitT->GetParameter(tailOffset+1), fitT->GetParError(tailOffset+1));
} else {
printf(" amplitude = %.4f +/- %.4f\n", fitT->GetParameter(tailOffset), fitT->GetParError(tailOffset));
printf(" x0 (turn-off) = %.4f +/- %.4f\n", fitT->GetParameter(tailOffset+1), fitT->GetParError(tailOffset+1));
printf(" d (width) = %.4f +/- %.4f\n", fitT->GetParameter(tailOffset+2), fitT->GetParError(tailOffset+2));
}
printf("chi2/ndf = %.3f / %d = %.3f\n\n",
fitT->GetChisquare(), fitT->GetNDF(), fitT->GetChisquare()/fitT->GetNDF());
if (sharedSigma) {
printf("shared sigma (all peaks) = %.4f +/- %.4f\n\n",
fitT->GetParameter(sharedSigmaIdx), fitT->GetParError(sharedSigmaIdx));
}
PrintCorrelations(fitT, nPeaks, 0.8, stride);
}
#endif

183
scratch/ScanDedxScale.C Normal file
View File

@ -0,0 +1,183 @@
/***************************************************
*
* ScanDedxGasCalib.C
*
* Direct first-principles DEDX_SCALE calibration check, using
* TrackRecon.C's "BeamEnergy_ETrack_vs_EKin" plot -- NOT
* dEgasPred_vs_dEgasCalib (an earlier dead end: that histogram is
* built entirely from the UNSCALED proton tables, so it's blind to
* DEDX_SCALE and would look identical at every scale).
*
* From TrackRecon.C:
* double snapped_level = snapToNearestLevel(Ex, levels_30Si_MeV, level_residual);
* double ebeam_kin_MeV = invertBeamEnergyMeV(m_beam, mass_4He, m3, m4,
* Efix, theta * 180/M_PI, snapped_level);
* Fill2D(..., beam_energy_at_vertex, ebeam_kin_MeV, ...);
*
* x = beam_energy_at_vertex : built from the ALUMINUM table --
* DEPENDS on DEDX_SCALE
* y = ebeam_kin_MeV : the beam energy at the vertex REQUIRED
* for this event's measured (Efix, theta)
* to exactly match a known literature
* level, solved purely from Efix
* (unscaled proton tables) and theta
* (geometry) -- INDEPENDENT of DEDX_SCALE
*
* If DEDX_SCALE is correct, x should equal y for every event -- a
* clean y=x diagonal. This covers FIVE literature levels at once
* (levels_30Si_MeV = {0.0, 2.235, 3.498, 6.550, 6.870}), not just the
* ground state the way CompareElasticLocus.C did, giving more
* statistics and letting you check whether the y=x offset is
* constant (a flat DEDX_SCALE correction is the right model) or
* drifts with beam energy (it isn't -- see the QQQ/SX3 discussion).
*
* Usage:
*
* .L ScanDedxScale.C+
*
* std::vector<double> scales = {0.70,0.75,0.80,0.85,0.87,0.88,0.89,0.90,0.91,0.92,0.95,1.00,1.05,1.10,1.15};
*
* ScanDedxScale(scales); // SX3
* ScanDedxScale(scales, "Output_27Al_", "output_27Al.root", "_m27Alax+misc_qqq_p/m27Alax_BeamEnergy_ETrack_vs_EKin_p_a2c0_qqq"); // QQQ
*
***************************************************/
#ifndef ScanDedxScale_C
#define ScanDedxScale_C
#include <TFile.h>
#include <TH2.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <TCanvas.h>
#include <vector>
// ============================================================
// scales : the DEDX_SCALE values from your bash scan -- MUST
// match your folder names exactly (same decimal
// formatting)
// folderPrefix : e.g. "Output_27Al_"
// fileName : ROOT file name inside each folder, e.g. "output_27Al.root"
// histName : the BeamEnergy_ETrack_vs_EKin histogram. Swap "sx3"
// for "qqq" (and adjust the gate tag if needed) to run
// the QQQ side with the exact same macro.
// fitMin,fitMax: x-range (beam_energy_at_vertex, in MeV) to fit the
// profile over. Histogram range is 0 to beamE0*1.5
// (~84 MeV) with 400 bins, but real events cluster in
// a much narrower band -- check your printed
// "beamE@vertex" values from earlier scans (roughly
// 6-27 MeV across DEDX_SCALE 0.70-1.15) before
// trusting these defaults; widen/narrow as needed.
// minEntriesPerBin : profile bins with fewer raw entries than this
// are dropped from the line fit (noisy tails can
// otherwise pull the slope around)
// ============================================================
void ScanDedxScale(
std::vector<double> scales,
TString folderPrefix = "Output_27Al_",
TString fileName = "output_27Al.root",
TString histName = "_m27Alax+misc_sx3_p/m27Alax_BeamEnergy_ETrack_vs_EKin_p_a2c0_sx3",
double fitMin = 5.0,
double fitMax = 25.0,
int minEntriesPerBin = 20
){
int nScales = (int) scales.size();
if (nScales == 0) { printf("ScanDedxGasCalib: no scale values given.\n"); return; }
TGraphErrors *gSlope = new TGraphErrors();
gSlope->SetTitle("Slope (ebeam_kin/beam_energy_at_vertex) vs DEDX_SCALE;DEDX_SCALE;slope");
gSlope->SetMarkerStyle(20);
TGraphErrors *gIntercept = new TGraphErrors();
gIntercept->SetTitle("Intercept vs DEDX_SCALE;DEDX_SCALE;intercept [MeV]");
gIntercept->SetMarkerStyle(20);
gIntercept->SetMarkerColor(kRed+1);
gIntercept->SetLineColor(kRed+1);
printf("\n%-8s %12s %12s %12s %10s\n", "scale", "slope", "+/-", "intercept", "chi2/ndf");
for (int s = 0; s < nScales; s++) {
TString folder = Form("%s%.2f", folderPrefix.Data(), scales[s]);
TString path = folder + "/" + fileName;
TFile *f = TFile::Open(path, "READ");
if (!f || f->IsZombie()) {
printf("%-8.2f ERROR: could not open %s\n", scales[s], path.Data());
continue;
}
TH2 *h2 = (TH2*) f->Get(histName);
if (!h2) {
printf("%-8.2f ERROR: histogram '%s' not found\n", scales[s], histName.Data());
f->ls();
continue;
}
// Profile: mean ebeam_kin_MeV (y) in bins of beam_energy_at_vertex (x)
TProfile *profile = h2->ProfileX(Form("profile_%.2f", scales[s]));
// Build a filtered graph: only bins inside [fitMin,fitMax] with at
// least minEntriesPerBin raw entries, so sparsely populated bins
// (noisy tails) don't pull the line fit around.
TGraphErrors *gFit = new TGraphErrors();
int nb = profile->GetNbinsX();
for (int b = 1; b <= nb; b++) {
double xc = profile->GetBinCenter(b);
if (xc < fitMin || xc > fitMax) continue;
if (profile->GetBinEntries(b) < minEntriesPerBin) continue;
int gi = gFit->GetN();
gFit->SetPoint(gi, xc, profile->GetBinContent(b));
gFit->SetPointError(gi, 0, profile->GetBinError(b));
}
if (gFit->GetN() < 2) {
printf("%-8.2f ERROR: fewer than 2 usable bins after entry-count filtering "
"(try lowering minEntriesPerBin or widening [fitMin,fitMax])\n", scales[s]);
continue;
}
TF1 *line = new TF1(Form("line_%.2f", scales[s]), "pol1", fitMin, fitMax);
gFit->Fit(line, "RQ"); // Q: quiet, don't spam per-scale fit output
double slope = line->GetParameter(1);
double slopeErr = line->GetParError(1);
double icept = line->GetParameter(0);
double icptErr = line->GetParError(0);
int ndf = line->GetNDF();
double chi2 = line->GetChisquare();
printf("%-8.2f %12.4f %12.4f %12.4f %10.3f\n",
scales[s], slope, slopeErr, icept, ndf > 0 ? chi2/ndf : -1.0);
int n = gSlope->GetN();
gSlope->SetPoint(n, scales[s], slope);
gSlope->SetPointError(n, 0, slopeErr);
gIntercept->SetPoint(n, scales[s], icept);
gIntercept->SetPointError(n, 0, icptErr);
}
TCanvas *c = new TCanvas("ScanDedxScale", "DEDX_SCALE via BeamEnergy_ETrack_vs_EKin", 1000, 700);
c->Divide(1, 2);
c->cd(1);
gSlope->Draw("APL");
TF1 *targetSlope = new TF1("targetSlope", "1", scales.front(), scales.back());
targetSlope->SetLineColor(kGray+1);
targetSlope->SetLineStyle(2);
targetSlope->Draw("SAME");
c->cd(2);
gIntercept->Draw("APL");
TF1 *targetIcept = new TF1("targetIcept", "0", scales.front(), scales.back());
targetIcept->SetLineColor(kGray+1);
targetIcept->SetLineStyle(2);
targetIcept->Draw("SAME");
printf("\nLook for where the slope curve (top) crosses the dashed slope=1\n"
"line AND the intercept curve (bottom) crosses dashed intercept=0 --\n"
"ideally near the same DEDX_SCALE. If they cross at different scales,\n"
"a single multiplicative DEDX_SCALE may not fully capture the real\n"
"correction (e.g. an additive offset might also be needed).\n\n");
}
#endif

82
scratch/overlay_2d.C Normal file
View File

@ -0,0 +1,82 @@
#include "TFile.h"
#include "TH2.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TLegend.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TF1.h"
#include <iostream>
#include <vector>
void overlay_2d(TString rootFile, TString histsCSV, TString labelsCSV, TString xAxisLabel, TString yAxisLabel) {
gROOT->SetStyle("Plain");
gStyle->SetOptStat(0);
TObjArray* histArr = histsCSV.Tokenize(",");
TObjArray* labelArr = labelsCSV.Tokenize(",");
// Standard ANASEN color sequence
int colors[] = {kBlack, kRed+1, kAzure+2, kGreen+2, kMagenta+1};
std::vector<TH2*> hists;
TFile *f = TFile::Open(rootFile, "READ");
if (!f || f->IsZombie()) return;
for (int i = 0; i < histArr->GetEntriesFast(); i++) {
TString hName = ((TObjString*)histArr->At(i))->GetString();
TH2 *h = (TH2 *)f->Get(hName);
if (h) {
TH2 *clone = (TH2 *)h->Clone(Form("h_%d", i));
clone->SetDirectory(0); // Detach from file
hists.push_back(clone);
} else {
std::cerr << "Warning: Could not find " << hName << "\n";
}
}
f->Close();
if (hists.empty()) return;
TCanvas *c = new TCanvas("c", "", 1800, 1800);
c->SetLeftMargin(0.12);
c->SetBottomMargin(0.12);
// Turn on the X and Y grid lines
c->SetGridx(1);
c->SetGridy(1);
TLegend *leg = new TLegend(0.65, 0.75, 0.9, 0.9);
leg->SetBorderSize(1);
leg->SetFillStyle(1001); // Solid background so grid doesn't bleed through
leg->SetFillColor(kWhite);
leg->SetTextSize(0.03);
for (size_t i = 0; i < hists.size(); i++) {
hists[i]->SetMarkerColor(colors[i % 5]);
hists[i]->SetMarkerStyle(6); // Small dot for scatter
if (i == 0) {
hists[i]->GetXaxis()->SetTitle(xAxisLabel);
hists[i]->GetYaxis()->SetTitle(yAxisLabel);
hists[i]->GetXaxis()->CenterTitle();
hists[i]->GetYaxis()->CenterTitle();
hists[i]->Draw("scat");
// Draw the y = x diagonal dashed line
TF1 *diag = new TF1("diag", "x", -1000, 1000);
diag->SetLineStyle(2);
diag->SetLineColor(kGray+2);
diag->Draw("same");
} else {
hists[i]->Draw("scat same");
}
TString label = ((TObjString*)labelArr->At(i))->GetString();
leg->AddEntry(hists[i], label.Data(), "p");
}
leg->Draw();
c->SaveAs("kinematic_states_overlay.png");
std::cout << "Saved: kinematic_states_overlay.png\n";
}