10 #include <tracking/eventTimeExtraction/findlets/HitBasedT0Extractor.h>
11 #include <tracking/eventTimeExtraction/findlets/BaseEventTimeExtractor.icc.h>
13 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
15 #include <framework/core/ModuleParamList.h>
17 #include <framework/logging/Logger.h>
18 #include <framework/utilities/ScopeGuard.h>
22 #include <TFitResult.h>
25 #include <boost/lexical_cast.hpp>
30 using namespace TrackFindingCDC;
34 return "Extracts the T0 time of an event only using CDC Hits";
39 m_eventMetaData.isRequired();
44 const std::string& prefix)
46 moduleParamList->
addParameter(prefixed(prefix,
"searchWindow"),
48 "Size of the time distance (in ns) to search for t0 in both direction from the current best t0",
49 m_param_searchWindow);
51 moduleParamList->
addParameter(prefixed(prefix,
"fitWindow"),
53 "Size of the time distance (in ns) to used for fitting",
56 moduleParamList->
addParameter(prefixed(prefix,
"refitWindow"),
58 "Size of the time distance (in ns) to used for re-fitting",
61 moduleParamList->
addParameter(prefixed(prefix,
"binCountTimeHistogram"),
62 m_param_binCountTimeHistogram,
63 "Number of bins in the timing histogram used for fitting",
64 m_param_binCountTimeHistogram);
66 moduleParamList->
addParameter(prefixed(prefix,
"rejectByBackgroundFlag"),
67 m_param_rejectByBackgroundFlag,
68 "Don't consider hits if they have the background flag set",
69 m_param_rejectByBackgroundFlag);
71 moduleParamList->
addParameter(prefixed(prefix,
"rejectIfNotTakenFlag"),
72 m_param_rejectIfNotTakenFlag,
73 "Don't consider hits which have not been assigned during track finding. The CDC track finding has "
74 "to be run before for this flag to be useful.",
75 m_param_rejectIfNotTakenFlag);
77 moduleParamList->
addParameter(prefixed(prefix,
"rejectIfChiSquareLargerThan"),
78 m_param_rejectIfChiSquareLargerThan,
79 "consider the t0 fit failed which have larger chi2 than this number",
80 m_param_rejectIfChiSquareLargerThan);
82 moduleParamList->
addParameter(prefixed(prefix,
"rejectIfUncertaintyLargerThan"),
83 m_param_rejectIfUncertaintyLargerThan,
84 "consider the t0 fit if the uncertainty on t0 is larger than this value",
85 m_param_rejectIfUncertaintyLargerThan);
87 moduleParamList->
addParameter(prefixed(prefix,
"storeAllFits"),
89 "store images for all fits",
90 m_param_storeAllFits);
92 moduleParamList->
addParameter(prefixed(prefix,
"minHitCount"),
94 "Minimum amount of hits which is required to try the extraction",
97 Super::exposeParameters(moduleParamList, prefix);
102 const auto timeHistogramName =
"HitBasedT0Extractor_time_hist";
103 const std::string debugImageName =
"HitBasedT0Extractor_debug_" + boost::lexical_cast<std::string>
104 (m_eventMetaData->getEvent()) +
".png";
106 auto timingHistgram = TH1D(timeHistogramName, timeHistogramName,
107 m_param_binCountTimeHistogram, -m_param_fitWindow,
113 TCanvas canvas(debugImageName.c_str(), debugImageName.c_str(), 800, 600);
115 if (inputWireHits.size() == 0) {
116 B2WARNING(
"No input CDC hits available for the CDC hit based t0 extraction.");
120 for (
auto const& wireHit : inputWireHits) {
122 if (m_param_rejectByBackgroundFlag
123 && wireHit.getAutomatonCell().hasBackgroundFlag())
126 if (m_param_rejectIfNotTakenFlag
127 && !wireHit.getAutomatonCell().hasTakenFlag())
133 if (m_param_rejectIfNotTakenFlag
134 && wireHit.getAutomatonCell().hasTakenFlag()
135 && wireHit.getAutomatonCell().hasBackgroundFlag())
140 timingHistgram.Fill(wireHit.getDriftTime());
143 if (timingHistgram.GetEntries() < m_param_minHitCount) {
144 B2DEBUG(50,
"Only " << timingHistgram.GetEntries() <<
" hits satisfied the requirements for t0 extraction, " << m_param_minHitCount
145 <<
" are required.");
151 timingHistgram.SetBinContent(1, timingHistgram.GetBinContent(1) + 1);
154 "Filled histogram with " << timingHistgram.GetEntries() <<
" Entries");
156 std::unique_ptr<TH1> cumTimingHistogram(timingHistgram.GetCumulative());
158 cumTimingHistogram->SetDirectory(0);
162 double errPrevBin = 0.0f;
163 double errThisBin = 0.0f;
164 for (
int i = 0; i < cumTimingHistogram->GetNbinsX(); i++) {
166 const double prevEntries = cumTimingHistogram->GetBinContent(i - 1);
167 const double addedEntries = cumTimingHistogram->GetBinContent(i) - prevEntries;
168 if (addedEntries > 0.0) {
170 const double errNewEntries = 1.0 / std::sqrt(addedEntries);
171 errThisBin = errPrevBin + errNewEntries;
175 if (cumTimingHistogram->GetBinContent(i) > 0) {
176 errThisBin = 1.0 / std::sqrt(cumTimingHistogram->GetBinContent(i));
180 cumTimingHistogram->SetBinError(i, errThisBin);
181 errPrevBin = errThisBin;
184 if (m_param_storeAllFits) {
185 cumTimingHistogram->Draw();
188 auto rangeBkg = std::make_pair(-m_param_fitWindow, -m_param_searchWindow);
189 auto rangeSig = std::make_pair(m_param_searchWindow, m_param_fitWindow);
191 TF1 fitfuncBkg = TF1(
"HitBasedT0Extractor_fit_bkg",
"[0]*x + [1]",
192 rangeBkg.first, rangeBkg.second);
193 TF1 fitfuncSig = TF1(
"HitBasedT0Extractor_fit_sig",
"[0]*x + [1]",
194 rangeSig.first, rangeSig.second);
196 auto fitresBkg = cumTimingHistogram->Fit(&fitfuncBkg,
"LQS",
"",
197 rangeBkg.first, rangeBkg.second);
198 auto fitresSig = cumTimingHistogram->Fit(&fitfuncSig,
"LQS",
"",
199 rangeSig.first, rangeSig.second);
201 if (m_param_storeAllFits) {
202 fitfuncBkg.Draw(
"SAME");
203 fitfuncSig.Draw(
"SAME");
206 TF1 fitfuncSegmented = TF1(
"HitBasedT0Extractor_fit_seg",
207 "[1]*(x+TMath::Abs(x+[3])) + [2]*(x-TMath::Abs(x+[3])) + [0]",
208 -m_param_fitWindow, m_param_fitWindow);
210 if (fitresSig->IsValid() && fitresBkg->IsValid()) {
211 double t0_estimate = (fitresBkg->Parameter(1) - fitresSig->Parameter(1))
212 / (fitresSig->Parameter(0) - fitresBkg->Parameter(0));
215 std::array<double, 4> fit_params = { 0,
216 fitresSig->Parameter(0),
217 fitresBkg->Parameter(0),
222 if (std::abs(t0_estimate) < m_param_searchWindow) {
223 fit_params[3] = t0_estimate;
226 fitfuncSegmented.SetParameters(fit_params.data());
228 auto fitresFull = cumTimingHistogram->Fit(&fitfuncSegmented,
"QS",
"", -m_param_fitWindow, m_param_fitWindow);
229 if (m_param_storeAllFits) {
230 fitfuncSegmented.Draw(
"SAME");
235 const double fitted_t0_first = -fitresFull->Parameter(3);
236 bool refitSuccess =
false;
237 if (std::abs(fitted_t0_first) < m_param_searchWindow) {
238 fitresFull = cumTimingHistogram->Fit(&fitfuncSegmented,
"QS",
"",
239 fitted_t0_first - m_param_refitWindow, fitted_t0_first + m_param_refitWindow);
242 B2DEBUG(50,
"First t0 estimate not in proper range" << fitted_t0_first);
245 if (m_param_storeAllFits) {
246 fitfuncSegmented.Draw(
"SAME");
250 if (refitSuccess && fitresFull->IsValid()) {
251 const double fitted_t0 = -fitresFull->Parameter(3);
252 const double fitted_t0_error = fitresFull->Error(3);
254 const double norm_chi2 = fitresFull->Chi2() / double(fitresFull->Ndf());
256 B2DEBUG(50,
"T0 fit with t0 " << fitted_t0 <<
" +- " << fitted_t0_error <<
" and normalized chi2 " << norm_chi2 <<
" and " <<
257 timingHistgram.GetEntries() <<
" hits");
260 if (norm_chi2 > m_param_rejectIfChiSquareLargerThan) {
262 "T0 fit has too large Chi2 " << fitresFull->Chi2());
263 }
else if (std::abs(fitted_t0_error) > m_param_rejectIfUncertaintyLargerThan) {
265 "T0 fit has too large error " << fitted_t0_error);
270 double lastEventT0 = m_eventT0->hasEventT0() ? m_eventT0->getEventT0() : 0;
271 EventT0::EventT0Component eventT0Component(fitted_t0 + lastEventT0, fitted_t0_error, Const::CDC,
"hit based", norm_chi2);
272 m_eventT0->addTemporaryEventT0(eventT0Component);
273 m_eventT0->setEventT0(eventT0Component);
274 m_wasSuccessful =
true;
276 "Successful t0 extraction with CDC hits: " << fitted_t0 <<
" +- " << fitted_t0_error);
280 "Cannot fit t0 from CDC hits only. Won't set EventT0 for now.");
284 "Cannot extract background or signal segment because fit failed. Won't set EventT0 for now.");
287 if (m_param_storeAllFits) {
289 canvas.SaveAs(debugImageName.c_str());