67{
70
72
75 string function;
77 bool writeFits;
80 string option;
82
83 try {
84
86
87 JParser<> zap(
"Program to fit time-slewing histogram in output of JCalibrateMuon.");
88
89 zap[
'f'] =
make_field(inputFile,
"input files (output from JCalibrateMuon).");
91 zap[
'F'] =
make_field(function,
"fit function") = gauss_t, emg_t;
92 zap[
'T'] =
make_field(T_ns,
"ROOT fit range around maximum [ns].") =
JRange_t(-7.5,+7.5);
93 zap[
'w'] =
make_field(writeFits,
"write fit results.");
95 zap[
'x'] =
make_field(X,
"ROOT fit range for time-over threshold") =
JRange_t(0.0, 256.0);
96 zap[
'O'] =
make_field(option,
"ROOT fit option, see TH1::Fit.") =
"";
98
99 zap(argc, argv);
100 }
101 catch(const exception &error) {
102 FATAL(error.what() << endl);
103 }
104
105
107 FATAL(
"Invalid fit range [ns] " << T_ns << endl);
108 }
109
110 cpu.setPMTParameters(parameters);
111
112 if (option.find('S') == string::npos) { option += 'S'; }
114
115
116
117 const Double_t
x[] = {
118 -0.5, 3.5, 6.5, 9.5, 12.5, 15.5, 18.5,
119 20.5, 21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5,
120 30.5, 31.5, 32.5, 33.5, 34.5, 35.5, 36.5, 37.5, 38.5, 39.5,
121 40.5, 42.5, 44.5, 46.5, 48.5,
122 50.5, 52.5, 54.5, 56.5, 58.5,
123 60.5, 65.5,
124 70.5, 75.5,
125 80.5, 85.5,
126 90.5, 95.5,
127 100.5, 120.5, 140.5, 160.5, 180.5, 200.5, 250.5
128 };
129
130 const int N =
sizeof(
x)/
sizeof(x[0]);
131
132 TH2D* h2 = NULL;
133
134 for (vector<string>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
135
136 NOTICE(
"Processing " << *i << endl);
137
138 TFile in(i->c_str(), "exist");
139
140 if (!in.IsOpen()) {
141 FATAL(
"File " << *i <<
" not opened." << endl);
142 }
143
144 TH2D* p =
dynamic_cast<TH2D*
>(in.Get(
h2_t));
145
146 if (p == NULL) {
147 FATAL(
"File " << *i <<
" has no histogram <" <<
h2_t <<
">." << endl);
148 }
149
150 if (h2 == NULL)
151 h2 = (TH2D*) p->Clone();
152 else
153 h2->Add(p);
154
155 h2->SetDirectory(0);
156
157 in.Close();
158 }
159
160 if (h2 == NULL) {
161 FATAL(
"No histogram <" <<
h2_t <<
">." << endl);
162 }
163
164
165
166 TH1D h0("h0", NULL, N-1, x);
167
169
170 for (int i = 1; i <= h0.GetXaxis()->GetNbins(); ++i) {
171
172 const Int_t imin = h2->GetXaxis()->FindBin(h0.GetXaxis()->GetBinLowEdge(i));
173 const Int_t imax = h2->GetXaxis()->FindBin(h0.GetXaxis()->GetBinUpEdge (i));
174
175 TH1D h1(
MAKE_CSTRING(i <<
".1D"), NULL, h2->GetYaxis()->GetNbins(), h2->GetYaxis()->GetXmin(), h2->GetYaxis()->GetXmax());
176
177
178
179 Double_t ymax = 0.0;
180 Double_t x0 = 0.0;
181 Double_t
sigma = 3.5;
182
183 for (int iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
184
185 Double_t
x = h1.GetBinCenter (iy);
187
188 for (int ix = imin; ix != imax; ++ix) {
189 y += h2->GetBinContent(ix,iy);
190 }
191
192 h1.SetBinContent(iy, y);
193
194 if (y > ymax) {
197 }
198 }
199
200
202
203 if (function == gauss_t) {
204
205 f1 =
new TF1(function.c_str(),
"[0]*TMath::Gaus(x,[1],[2]) + [3]");
206
207 f1->SetParameter(0, ymax);
208 f1->SetParameter(1, x0);
209 f1->SetParameter(2, sigma);
210 f1->SetParameter(3, 0.0);
211
212 f1->SetParLimits(3, 0.0, ymax);
213
214 } else if (function == emg_t) {
215
216 f1 =
new TF1(function.c_str(),
"[0]*TMath::Exp(0.5*[3]*(2.0*[1]+[3]*[2]*[2]-2.0*x))*TMath::Erfc(([1]+[3]*[2]*[2]-x)/(TMath::Sqrt(2.0)*[2])) +[4]");
217
218 f1->SetParameter(0, ymax);
219 f1->SetParameter(1, x0 - 0.5*sigma);
220 f1->SetParameter(2, sigma);
221 f1->SetParameter(3, 0.04);
222 f1->SetParameter(4, 0.0);
223
224 f1->SetParLimits(4, 0.0, ymax);
225
226 } else {
227
228 FATAL(
"Unknown fit function " << function << endl);
229 }
230
231
232
235
236 if (xmin < h1.GetXaxis()->GetXmin()) {
xmin = h1.GetXaxis()->GetXmin(); }
237 if (xmax > h1.GetXaxis()->GetXmax()) {
xmax = h1.GetXaxis()->GetXmax(); }
238
239 TFitResultPtr
result = h1.Fit(f1, option.c_str(),
"same", xmin, xmax);
240
241 if (
result.Get() == NULL) {
242 FATAL(
"Invalid TFitResultPtr " << h1.GetName() << endl);
243 }
244
246 cout << "Bin: "
247 << setw(4) << i << ' '
248 <<
FIXED(7,3) <<
f1->GetParameter(1) <<
" +/- "
249 <<
FIXED(7,3) <<
f1->GetParError (1) <<
' '
252 << (
result->IsValid() ?
"" :
"failed") << endl;
253 }
254
256 h0.SetBinContent(i,
f1->GetParameter(1));
257 h0.SetBinError (i,
f1->GetParError (1));
258 }
259
260 if (writeFits) {
261 h1.Write();
262 }
263
265 }
266
267
268
269 TF1
f1(
"f1", getRisetime, x[0], x[N-1], 3);
270
271 f1.SetParameter(0, 0.0);
272 f1.SetParameter(1, 2.0e-2);
273 f1.FixParameter(2, -7.0);
274
276
278 cout << "Time-slewing correction" << endl;
281 << (
result->IsValid() ?
"" :
"failed") << endl;
282
283 for (
int i = 0; i !=
f1.GetNpar(); ++i) {
284 cout <<
"parameter[" << i <<
"] = " <<
FIXED(8,4) <<
f1.GetParameter(i) <<
" +/- " <<
FIXED(8,4) <<
f1.GetParError (i) << endl;
285 }
286 }
287
288 cout << "// Produced by JFrodo.cc; to be included on JGetRiseTime.hh." << endl;
289
291
292 for (int i = 0; i != 256; ++i) {
293 cout <<
"this->push_back(" <<
FIXED(6,2) <<
f1.Eval((Double_t) i) - t0 <<
");" << endl;
294 }
295
296 h0.Write();
297
298 out.Close();
299}
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
#define MAKE_CSTRING(A)
Make C-string.
Data structure for PMT parameters.
JProperties getProperties(const JEquationParameters &equation=JPMTParameters::getEquationParameters())
Get properties of this class.
Utility class to parse parameter values.
Utility class to parse command line options.
const JPolynome f1(1.0, 2.0, 3.0)
Function.
const double TIME_OVER_THRESHOLD_NS
Specification for time-over-threshold corresponding to a one photo-electron pulse.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
const char *const h2_t
Name of histogram with results from JMuonCompass.cc.
Auxiliary data structure for floating point format specification.
Type definition of range.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...