8 #include <tracking/eventTimeExtraction/findlets/HitBasedT0Extractor.h>
9 #include <tracking/eventTimeExtraction/findlets/BaseEventTimeExtractor.icc.h>
11 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
13 #include <framework/core/ModuleParamList.h>
15 #include <framework/logging/Logger.h>
16 #include <framework/utilities/ScopeGuard.h>
20 #include <TFitResult.h>
23 #include <boost/lexical_cast.hpp>
28 using namespace TrackFindingCDC;
32 return "Extracts the T0 time of an event only using CDC Hits";
37 m_eventMetaData.isRequired();
42 const std::string& prefix)
44 moduleParamList->
addParameter(prefixed(prefix,
"searchWindow"),
46 "Size of the time distance (in ns) to search for t0 in both direction from the current best t0",
47 m_param_searchWindow);
49 moduleParamList->
addParameter(prefixed(prefix,
"fitWindow"),
51 "Size of the time distance (in ns) to used for fitting",
54 moduleParamList->
addParameter(prefixed(prefix,
"refitWindow"),
56 "Size of the time distance (in ns) to used for re-fitting",
59 moduleParamList->
addParameter(prefixed(prefix,
"binCountTimeHistogram"),
60 m_param_binCountTimeHistogram,
61 "Number of bins in the timing histogram used for fitting",
62 m_param_binCountTimeHistogram);
64 moduleParamList->
addParameter(prefixed(prefix,
"rejectByBackgroundFlag"),
65 m_param_rejectByBackgroundFlag,
66 "Don't consider hits if they have the background flag set",
67 m_param_rejectByBackgroundFlag);
69 moduleParamList->
addParameter(prefixed(prefix,
"rejectIfNotTakenFlag"),
70 m_param_rejectIfNotTakenFlag,
71 "Don't consider hits which have not been assigned during track finding. The CDC track finding has "
72 "to be run before for this flag to be useful.",
73 m_param_rejectIfNotTakenFlag);
75 moduleParamList->
addParameter(prefixed(prefix,
"rejectIfChiSquareLargerThan"),
76 m_param_rejectIfChiSquareLargerThan,
77 "consider the t0 fit failed which have larger chi2 than this number",
78 m_param_rejectIfChiSquareLargerThan);
80 moduleParamList->
addParameter(prefixed(prefix,
"rejectIfUncertaintyLargerThan"),
81 m_param_rejectIfUncertaintyLargerThan,
82 "consider the t0 fit if the uncertainty on t0 is larger than this value",
83 m_param_rejectIfUncertaintyLargerThan);
85 moduleParamList->
addParameter(prefixed(prefix,
"storeAllFits"),
87 "store images for all fits",
88 m_param_storeAllFits);
90 moduleParamList->
addParameter(prefixed(prefix,
"minHitCount"),
92 "Minimum amount of hits which is required to try the extraction",
95 Super::exposeParameters(moduleParamList, prefix);
100 const auto timeHistogramName =
"HitBasedT0Extractor_time_hist";
101 const std::string debugImageName =
"HitBasedT0Extractor_debug_" + boost::lexical_cast<std::string>
102 (m_eventMetaData->getEvent()) +
".png";
104 auto timingHistgram = TH1D(timeHistogramName, timeHistogramName,
105 m_param_binCountTimeHistogram, -m_param_fitWindow,
111 TCanvas canvas(debugImageName.c_str(), debugImageName.c_str(), 800, 600);
113 if (inputWireHits.size() == 0) {
114 B2WARNING(
"No input CDC hits available for the CDC hit based t0 extraction.");
118 for (
auto const& wireHit : inputWireHits) {
120 if (m_param_rejectByBackgroundFlag
121 && wireHit.getAutomatonCell().hasBackgroundFlag())
124 if (m_param_rejectIfNotTakenFlag
125 && !wireHit.getAutomatonCell().hasTakenFlag())
131 if (m_param_rejectIfNotTakenFlag
132 && wireHit.getAutomatonCell().hasTakenFlag()
133 && wireHit.getAutomatonCell().hasBackgroundFlag())
138 timingHistgram.Fill(wireHit.getDriftTime());
141 if (timingHistgram.GetEntries() < m_param_minHitCount) {
142 B2DEBUG(25,
"Only " << timingHistgram.GetEntries() <<
" hits satisfied the requirements for t0 extraction, " << m_param_minHitCount
143 <<
" are required.");
149 timingHistgram.SetBinContent(1, timingHistgram.GetBinContent(1) + 1);
152 "Filled histogram with " << timingHistgram.GetEntries() <<
" Entries");
154 std::unique_ptr<TH1> cumTimingHistogram(timingHistgram.GetCumulative());
156 cumTimingHistogram->SetDirectory(0);
160 double errPrevBin = 0.0f;
161 double errThisBin = 0.0f;
162 for (
int i = 0; i < cumTimingHistogram->GetNbinsX(); i++) {
164 const double prevEntries = cumTimingHistogram->GetBinContent(i - 1);
165 const double addedEntries = cumTimingHistogram->GetBinContent(i) - prevEntries;
166 if (addedEntries > 0.0) {
168 const double errNewEntries = 1.0 /
std::sqrt(addedEntries);
169 errThisBin = errPrevBin + errNewEntries;
173 if (cumTimingHistogram->GetBinContent(i) > 0) {
174 errThisBin = 1.0 /
std::sqrt(cumTimingHistogram->GetBinContent(i));
178 cumTimingHistogram->SetBinError(i, errThisBin);
179 errPrevBin = errThisBin;
182 if (m_param_storeAllFits) {
183 cumTimingHistogram->Draw();
186 auto rangeBkg = std::make_pair(-m_param_fitWindow, -m_param_searchWindow);
187 auto rangeSig = std::make_pair(m_param_searchWindow, m_param_fitWindow);
189 TF1 fitfuncBkg = TF1(
"HitBasedT0Extractor_fit_bkg",
"[0]*x + [1]",
190 rangeBkg.first, rangeBkg.second);
191 TF1 fitfuncSig = TF1(
"HitBasedT0Extractor_fit_sig",
"[0]*x + [1]",
192 rangeSig.first, rangeSig.second);
194 auto fitresBkg = cumTimingHistogram->Fit(&fitfuncBkg,
"LQS",
"",
195 rangeBkg.first, rangeBkg.second);
196 auto fitresSig = cumTimingHistogram->Fit(&fitfuncSig,
"LQS",
"",
197 rangeSig.first, rangeSig.second);
199 if (m_param_storeAllFits) {
200 fitfuncBkg.Draw(
"SAME");
201 fitfuncSig.Draw(
"SAME");
204 TF1 fitfuncSegmented = TF1(
"HitBasedT0Extractor_fit_seg",
205 "[1]*(x+TMath::Abs(x+[3])) + [2]*(x-TMath::Abs(x+[3])) + [0]",
206 -m_param_fitWindow, m_param_fitWindow);
208 if (fitresSig->IsValid() && fitresBkg->IsValid()) {
209 double t0_estimate = (fitresBkg->Parameter(1) - fitresSig->Parameter(1))
210 / (fitresSig->Parameter(0) - fitresBkg->Parameter(0));
213 std::array<double, 4> fit_params = { 0,
214 fitresSig->Parameter(0),
215 fitresBkg->Parameter(0),
220 if (std::abs(t0_estimate) < m_param_searchWindow) {
221 fit_params[3] = t0_estimate;
224 fitfuncSegmented.SetParameters(fit_params.data());
226 auto fitresFull = cumTimingHistogram->Fit(&fitfuncSegmented,
"QS",
"", -m_param_fitWindow, m_param_fitWindow);
227 if (m_param_storeAllFits) {
228 fitfuncSegmented.Draw(
"SAME");
233 const double fitted_t0_first = -fitresFull->Parameter(3);
234 bool refitSuccess =
false;
235 if (std::abs(fitted_t0_first) < m_param_searchWindow) {
236 fitresFull = cumTimingHistogram->Fit(&fitfuncSegmented,
"QS",
"",
237 fitted_t0_first - m_param_refitWindow, fitted_t0_first + m_param_refitWindow);
240 B2DEBUG(25,
"First t0 estimate not in proper range" << fitted_t0_first);
243 if (m_param_storeAllFits) {
244 fitfuncSegmented.Draw(
"SAME");
248 if (refitSuccess && fitresFull->IsValid()) {
249 const double fitted_t0 = -fitresFull->Parameter(3);
250 const double fitted_t0_error = fitresFull->Error(3);
252 const double norm_chi2 = fitresFull->Chi2() / double(fitresFull->Ndf());
254 B2DEBUG(25,
"T0 fit with t0 " << fitted_t0 <<
" +- " << fitted_t0_error <<
" and normalized chi2 " << norm_chi2 <<
" and " <<
255 timingHistgram.GetEntries() <<
" hits");
258 if (norm_chi2 > m_param_rejectIfChiSquareLargerThan) {
260 "T0 fit has too large Chi2 " << fitresFull->Chi2());
261 }
else if (std::abs(fitted_t0_error) > m_param_rejectIfUncertaintyLargerThan) {
263 "T0 fit has too large error " << fitted_t0_error);
268 double lastEventT0 = m_eventT0->hasEventT0() ? m_eventT0->getEventT0() : 0;
269 EventT0::EventT0Component eventT0Component(fitted_t0 + lastEventT0, fitted_t0_error, Const::CDC,
"hit based", norm_chi2);
270 m_eventT0->addTemporaryEventT0(eventT0Component);
271 m_eventT0->setEventT0(eventT0Component);
272 m_wasSuccessful =
true;
274 "Successful t0 extraction with CDC hits: " << fitted_t0 <<
" +- " << fitted_t0_error);
278 "Cannot fit t0 from CDC hits only. Won't set EventT0 for now.");
282 "Cannot extract background or signal segment because fit failed. Won't set EventT0 for now.");
285 if (m_param_storeAllFits) {
287 canvas.SaveAs(debugImageName.c_str());
The Module parameter list class.
static ScopeGuard guardBatchMode(bool batchMode=true)
Create a ScopeGuard to turn ROOT into batch mode and restore the initial batch mode status after the ...
void addParameter(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.
Structure for storing the extracted event t0s together with its detector and its uncertainty.