11/**
22*
3- * Fitter package for CND
3+ * Fitter package for ALERT
44*
5- * Writer: Sangbaek Lee
5+ * Writer: Sangbaek Lee, Zhiwan Xu
66*
77**/
88package org.jlab.clas.timeline.fitter
@@ -40,31 +40,170 @@ class ALERTFitter{
4040 return f1
4141 }
4242
43- static F1D tdc_minus_start_time_fitter (H1F h1 ){
44- def f1 = new F1D(" fit:" + h1. getName()," [amp]*gaus(x,[mean],[sigma])+[cst]" , -5.0 , 5.0 );
45- f1. setLineColor(33 );
46- f1. setLineWidth(10 );
47- f1. setOptStat(" 1111" );
48- double maxz = h1. getBinContent(h1. getMaximumBin());
49- double peak_location = h1. getAxis(). getBinCenter(h1. getMaximumBin());
50- f1. setRange(peak_location - 5 , peak_location + 5 );
51- f1. setParameter(0 ,maxz- h1. getBinContent(0 ));
52- f1. setParameter(1 , peak_location);
53- f1. setParameter(2 , 1.0 );
54- f1. setParameter(3 , h1. getBinContent(0 ));
55- if (maxz> 0 ) f1. setParLimits(0 , maxz* 0.9 ,maxz* 1.1 );
56- f1. setParLimits(3 , 0.0 , 0.1 * maxz);
43+ static F1D tdc_minus_start_time_fitter (H1F h1 , int component ){
44+ if (component> 9 ){// bars
45+ def f1 = new F1D(" fit:" + h1. getName()," [amp]*gaus(x,[mean],[sigma])+[cst]" , -5.0 , 5.0 );
46+ f1. setLineColor(33 );
47+ f1. setLineWidth(10 );
48+ f1. setOptStat(" 1111" );
49+ double maxz = h1. getBinContent(h1. getMaximumBin());
50+ double peak_location = h1. getAxis(). getBinCenter(h1. getMaximumBin());
51+ f1. setRange(peak_location - 5 , peak_location + 5 );
52+ f1. setParameter(0 ,maxz- h1. getBinContent(0 ));
53+ f1. setParameter(1 , peak_location);
54+ f1. setParameter(2 , 1.0 );
55+ f1. setParameter(3 , h1. getBinContent(0 ));
56+ if (maxz> 0 ) f1. setParLimits(0 , maxz* 0.9 ,maxz* 1.1 );
57+ f1. setParLimits(3 , 0.0 , 0.1 * maxz);
5758
58- double hMean, hRMS
59- def originalOut = System . out
60- System . setOut(new PrintStream (OutputStream . nullOutputStream())) // Java 11+
61-
62- // Code that prints to System.out
63- DataFitter . fit(f1, h1, " " );
59+ double hMean, hRMS
60+ def originalOut = System . out
61+ System . setOut(new PrintStream (OutputStream . nullOutputStream())) // Java 11+
6462
65- System . setOut(originalOut) // Restore the original output
63+ // Code that prints to System.out
64+ DataFitter . fit(f1, h1, " " );
65+
66+ System . setOut(originalOut) // Restore the original output
67+
68+ return f1
69+ }
70+ else {
71+ double height_fit_set = 0
72+ double mean_fit_set = 0
73+ double sigma_fit_set = 0
74+ double step = 2
75+
76+ // ----- Clone & analyze primary peak -----
77+ H1F hpy = h1. histClone(" hpy_zoom" )
78+ int maxBin = hpy. getMaximumBin()
79+ double maxY = hpy. getBinContent(maxBin)
80+ double peak = hpy. getXaxis(). getBinCenter(maxBin)
81+ double sigma0 = Math . min(step, getRestrictedRMS(hpy, peak - step, peak + step))
82+
83+ // ----- Primary Gaussian Fit -----
84+ F1D fgaus = new F1D(" fgaus" , " [amp]*gaus(x,[mean],[sigma])" ,
85+ peak - step, peak + step)
86+
87+ fgaus. setParameter(0 , maxY)
88+ fgaus. setParameter(1 , peak)
89+ if (sigma0 != null && sigma0 > 0 ) {
90+ fgaus. setParameter(2 , sigma0)
91+ } else {
92+ fgaus. setParameter(2 , 0.8 )
93+ }
94+ fgaus. setParLimits(0 , 0 , 1.2 * maxY)
95+ fgaus. setParLimits(1 , peak - step, peak + step)
96+ fgaus. setParLimits(2 , 0 , step)
97+
98+ PrintStream original = System . out
99+ System . setOut(new PrintStream (OutputStream . nullOutputStream()))
100+ DataFitter . fit(fgaus, hpy, " RQ" )
101+ System . setOut(original)
102+
103+ double height = fgaus. getParameter(0 )
104+ double mean = fgaus. getParameter(1 )
105+ double sigma = fgaus. getParameter(2 )
106+ double entriesTotal = hpy. integral()
107+
108+ // -------------------------------------------------------------------------
109+ // Utility closure to fit a left-side peak after cutting the histogram
110+ // -------------------------------------------------------------------------
111+ def fitLeftPeak = { H1F h , double prevMean , double prevSigma ->
112+ // Cut histogram to the left of the previous peak
113+ H1F hcut = h. histClone(" hcut" )
114+ int cutBin = hcut. getXaxis(). getBin(prevMean - prevSigma * 2 )
115+ for (int b = cutBin; b <= hcut. getXaxis(). getNBins(); b++ ) {
116+ hcut. setBinContent(b, 0 )
117+ hcut. setBinError(b, 0 )
118+ }
119+
120+ if (hcut. integral() < 3 ) return null
121+
122+ int mb = hcut. getMaximumBin()
123+ if (mb >= cutBin - 2 ) return null // ensure left-side peak
124+
125+ double pk = hcut. getXaxis(). getBinCenter(mb)
126+ double amp0 = hcut. getBinContent(mb)
127+
128+ F1D ftmp = new F1D(" fgaus_left" ,
129+ " [amp]*gaus(x,[mean],[sigma])" ,
130+ pk - step, pk + step)
131+
132+ ftmp. setParameter(0 , amp0)
133+ ftmp. setParameter(1 , pk)
134+ ftmp. setParameter(2 , 0.8 )
135+
136+ ftmp. setParLimits(0 , 0 , 1.2 * amp0)
137+ ftmp. setParLimits(1 , pk - step, pk + step)
138+ ftmp. setParLimits(2 , 0 , step)
139+
140+ System . setOut(new PrintStream (OutputStream . nullOutputStream()))
141+ DataFitter . fit(ftmp, hcut, " RQ" )
142+ System . setOut(original)
143+
144+ double A = ftmp. getParameter(0 )
145+ double M = ftmp. getParameter(1 )
146+ double S = ftmp. getParameter(2 )
147+
148+ // validation conditions
149+ if (A > maxY * 0.3 &&
150+ S < step && S > 0.1 &&
151+ M < prevMean - prevSigma &&
152+ hcut. integral() > 0.05 * entriesTotal)
153+ {
154+ return [A, M, S]
155+ }
156+ return null
157+ }
158+
159+ // -------------------------------------------------------------------------
160+ // Peak 1 (primary) already known: height, mean, sigma
161+ // Try Peak 2 (first left peak)
162+ // -------------------------------------------------------------------------
163+ def p2 = fitLeftPeak(hpy, mean, sigma)
164+
165+ // If Peak 2 exists, try Peak 3 (second left peak)
166+ def p3 = p2 ? fitLeftPeak(hpy, p2[1 ], p2[2 ]) : null
167+
168+ // If Peak 3 exists, try Peak 4 (third left peak)
169+ def p4 = p3 ? fitLeftPeak(hpy, p3[1 ], p3[2 ]) : null
170+
171+ // -------------------------------------------------------------------------
172+ // Choose deepest detected peak on the left: p4 > p3 > p2 > primary
173+ // -------------------------------------------------------------------------
174+ if (p4) {
175+ height_fit_set = p4[0 ]
176+ mean_fit_set = p4[1 ]
177+ sigma_fit_set = p4[2 ]
178+ } else if (p3) {
179+ height_fit_set = p3[0 ]
180+ mean_fit_set = p3[1 ]
181+ sigma_fit_set = p3[2 ]
182+ } else if (p2) {
183+ height_fit_set = p2[0 ]
184+ mean_fit_set = p2[1 ]
185+ sigma_fit_set = p2[2 ]
186+ } else {
187+ height_fit_set = height
188+ mean_fit_set = mean
189+ sigma_fit_set = sigma
190+ }
191+
192+ // Return final selected Gaussian
193+ F1D fout = new F1D(" fit:" + h1. getName(),
194+ " [amp]*gaus(x,[mean],[sigma])" ,
195+ mean_fit_set - step * 2 , mean_fit_set + step * 2 )
196+
197+ fout. setParameter(0 , height_fit_set)
198+ fout. setParameter(1 , mean_fit_set)
199+ fout. setParameter(2 , sigma_fit_set)
200+
201+ fout. setLineColor(33 )
202+ fout. setLineWidth(10 )
203+
204+ return fout
205+ }
66206
67- return f1
68207 }
69208
70209
@@ -128,4 +267,4 @@ class ALERTFitter{
128267
129268 return f1
130269 }
131- }
270+ }
0 commit comments