00001
00034 #include <cmath>
00035 #include <numeric>
00036 #include <cassert>
00037 #include <algorithm>
00038 #include <functional>
00039
00040 #include "MessageService/MsgService.h"
00041
00042 #include "LIPatternFinderSimple.h"
00043
00044 ClassImp(LIPatternFinderSimple)
00045
00046
00047 CVSID(
00048 "$Id: LIPatternFinderSimple.cxx,v 1.5 2006/05/27 08:58:13 rhatcher Exp $"
00049 );
00050
00051
00052
00053
00054 struct is_east_side: public unary_function<CandDigitHandle *, bool>
00055 {
00056 bool operator()(CandDigitHandle * digit) {
00057
00058 const PlexSEIdAltL & seid = digit->GetPlexSEIdAltL();
00059 return (seid.GetEnd() == StripEnd::kEast);
00060 }
00061 };
00062
00063 struct sum_q :
00064 public binary_function<double, CandDigitHandle *, double>
00065 {
00066 double operator()(double sum, CandDigitHandle * current_digit) {
00067
00068 return (sum + current_digit->GetCharge());
00069 }
00070 };
00071
00072 struct is_in_plane_and_above_thr:
00073 public unary_function<CandDigitHandle *, bool>
00074 {
00075 int _plane;
00076 double _threshold;
00077
00078 is_in_plane_and_above_thr(int plane, double threshold) :
00079 _plane(plane), _threshold(threshold) { }
00080
00081 bool operator()(CandDigitHandle * digit) {
00082
00083 const PlexSEIdAltL & seid = digit->GetPlexSEIdAltL();
00084
00085 return ( (digit->GetCharge() > _threshold) &&
00086 (seid.GetPlane() == _plane) );
00087 }
00088 };
00089
00090 struct is_in_plane_range_and_above_thr:
00091 public unary_function<CandDigitHandle *, bool>
00092 {
00093 int _pl_min, _pl_max;
00094 double _threshold;
00095
00096 is_in_plane_range_and_above_thr(
00097 int pl_min, int pl_max, double threshold) :
00098 _pl_min(pl_min), _pl_max(pl_max), _threshold(threshold) { }
00099
00100 bool operator()(CandDigitHandle * digit) {
00101
00102 const PlexSEIdAltL & seid = digit->GetPlexSEIdAltL();
00103
00104 return ( (digit->GetCharge() > _threshold) &&
00105 (seid.GetPlane() >= _pl_min) &&
00106 (seid.GetPlane() <= _pl_max) );
00107 }
00108 };
00109
00110 struct min_plane:
00111 public binary_function<CandDigitHandle *, CandDigitHandle *, bool> {
00112 bool operator()(CandDigitHandle * a, CandDigitHandle * b) {
00113 return a->GetPlexSEIdAltL().GetPlane() <
00114 b->GetPlexSEIdAltL().GetPlane();
00115 }
00116 };
00117
00118 LIPatternFinderSimple::LIPatternFinderSimple()
00119 {
00120 MSG("LIPatternFinder", Msg::kVerbose)
00121 << "LIPatternFinderSimple ctor\n";
00122 DefaultConfig();
00123 }
00124
00125 LIPatternFinderSimple::~LIPatternFinderSimple()
00126 {
00127 MSG("LIPatternFinder", Msg::kVerbose)
00128 << "LIPatternFinderSimple dtor\n";
00129 }
00130
00131 void LIPatternFinderSimple::DefaultConfig(void)
00132 {
00133
00134
00135 fMaxEWAsymmetry = 5.e+5;
00136 fPulseHeightThreshold = 200;
00137 fMaxNDigits = 1000;
00138 fMaxCharge = 1.e+6;
00139 fHighActivityThreshold = 0.90;
00140 fLowActivityThreshold = 0.20;
00141 }
00142
00143 void LIPatternFinderSimple::Configure(const Registry & registry)
00144 {
00145 double tmpd;
00146
00147 if (registry.Get("MaxEWAsymmetry", tmpd)) fMaxEWAsymmetry = tmpd;
00148 if (registry.Get("MaxNDigits", tmpd)) fMaxNDigits = tmpd;
00149 if (registry.Get("MaxCharge", tmpd)) fMaxCharge = tmpd;
00150 if (registry.Get("PulseHeightThreshold", tmpd))
00151 fPulseHeightThreshold = tmpd;
00152 if (registry.Get("HighActivityThreshold", tmpd))
00153 fHighActivityThreshold = tmpd;
00154 if (registry.Get("LowActivityThreshold", tmpd))
00155 fLowActivityThreshold = tmpd;
00156 }
00157
00158 bool LIPatternFinderSimple::IsLightInjectionTrash(
00159 CandDigitListHandle * cdlh)
00160 {
00161 MSG("LIPatternFinder", Msg::kVerbose)
00162 << "LIPatternFinderSimple running" << endl;
00163
00164 CandDigitHandleItr cdh_iter ( cdlh->GetDaughterIterator() );
00165
00166 vector<CandDigitHandle *> digits;
00167
00168 while ( CandDigitHandle * digit = cdh_iter.Ptr() ) {
00169
00170 digits.push_back(digit);
00171
00172 cdh_iter.Next();
00173 }
00174
00175 sort(digits.begin(), digits.end(), min_plane());
00176
00177
00178
00179 double asymmetry = GetEWAsymmetry(digits);
00180 double tot_charge = GetTotalCharge(digits);
00181
00182 vector<double> segment_activity =
00183 ActivityBetweenCrateBoundaries(digits);
00184
00185 sort(segment_activity.begin(), segment_activity.end());
00186
00187 double first_max = segment_activity[ segment_activity.size()-1 ];
00188 double second_max = segment_activity[ segment_activity.size()-2 ];
00189
00190 MSG("LIPatternFinder", Msg::kVerbose)
00191 << "------------------------- LIPatternFinderSimple summary:"
00192 << endl;
00193 MSG("LIPatternFinder", Msg::kVerbose)
00194 << "E-W Asymmetry = " << asymmetry << endl;
00195 MSG("LIPatternFinder", Msg::kVerbose)
00196 << "N-Digits = " << digits.size() << endl;
00197 MSG("LIPatternFinder", Msg::kVerbose)
00198 << "Total charge = " << tot_charge << endl;
00199 MSG("LIPatternFinder", Msg::kVerbose)
00200 << "Fraction of active planes between crate boundaries" << endl;
00201 MSG("LIPatternFinder", Msg::kVerbose)
00202 << " - 1st max = " << first_max << endl;
00203 MSG("LIPatternFinder", Msg::kVerbose)
00204 << " - 2nd max = " << second_max << endl;
00205
00206
00207 bool exceeds_max_EW_asymmetry = (asymmetry > fMaxEWAsymmetry);
00208
00209
00210 bool exceeds_max_n_digits = (digits.size() > fMaxNDigits);
00211
00212
00213 bool exceeds_max_charge = (tot_charge > fMaxCharge);
00214
00215
00216
00217
00218
00219
00220 bool shows_segment_asymmetry =
00221 (first_max > fHighActivityThreshold) &&
00222 (second_max < fLowActivityThreshold);
00223
00224 bool is_LI = exceeds_max_EW_asymmetry &&
00225 exceeds_max_n_digits &&
00226 exceeds_max_charge &&
00227 shows_segment_asymmetry;
00228 return is_LI;
00229 }
00230
00231 double LIPatternFinderSimple::GetEWAsymmetry(
00232 const vector<CandDigitHandle *> & digits) const
00233 {
00234
00235
00236
00237
00238 vector<CandDigitHandle *> digits_cp( digits.size() );
00239
00240 copy( digits.begin(), digits.end(), digits_cp.begin() );
00241
00242
00243
00244 vector<CandDigitHandle *>::iterator part_iter = partition(
00245 digits_cp.begin(), digits_cp.end(), is_east_side() );
00246
00247
00248
00249 double q_east = accumulate(
00250 digits_cp.begin(), part_iter, 0.0, sum_q());
00251 double q_west = accumulate(
00252 part_iter, digits_cp.end(), 0.0, sum_q());
00253
00254 MSG("LIPatternFinder", Msg::kVerbose) << "Q_W = " << q_west << endl;
00255 MSG("LIPatternFinder", Msg::kVerbose) << "Q_E = " << q_east << endl;
00256
00257
00258
00259 double asymmetry = fabs(q_west-q_east);
00260
00261 return asymmetry;
00262 }
00263
00264 double LIPatternFinderSimple::GetTotalCharge(
00265 const vector<CandDigitHandle *> & digits) const
00266 {
00267
00268
00269 double q = accumulate(digits.begin(), digits.end(), 0.0, sum_q());
00270
00271 return q;
00272 }
00273
00274 double LIPatternFinderSimple::FractionOfActivePlanesInRange(
00275 int plane_min, int plane_max,
00276 const vector<CandDigitHandle *> & digits) const
00277 {
00278
00279
00280 int n_total_planes = 1 + plane_max - plane_min;
00281 int n_active_planes = 0;
00282
00283 assert(n_total_planes > 0);
00284
00285 for(int plane = plane_min; plane < plane_max; plane++) {
00286
00287 int n_digits = count_if(digits.begin(), digits.end(),
00288 is_in_plane_and_above_thr(plane, fPulseHeightThreshold));
00289
00290 if(n_digits > 0) n_active_planes++;
00291 }
00292
00293 double fraction = (double) n_active_planes / (double) n_total_planes;
00294
00295 return fraction;
00296 }
00297
00298 vector<double>
00299 LIPatternFinderSimple::ActivityBetweenCrateBoundaries(
00300 const vector<CandDigitHandle *> & digits) const
00301 {
00302 vector<double> active_fraction;
00303
00304 const int kNDetectorSegments = 8;
00305
00306 const int kMinPlane[kNDetectorSegments] = {
00307 1, 65, 129, 193, 250, 314, 378, 442 };
00308 const int kMaxPlane[kNDetectorSegments] = {
00309 64, 128, 192, 248, 313, 377, 441, 485 };
00310
00311 for(int isegment = 0; isegment < kNDetectorSegments; isegment++)
00312 active_fraction.push_back(
00313 FractionOfActivePlanesInRange(
00314 kMinPlane[isegment], kMaxPlane[isegment], digits) );
00315
00316 return active_fraction;
00317 }
00318
00319 void LIPatternFinderSimple::PrintSnarl(
00320 const vector<CandDigitHandle *> & digits) const
00321 {
00322 vector<CandDigitHandle *>::const_iterator digit_iter;
00323
00324 for(digit_iter = digits.begin();
00325 digit_iter != digits.end(); ++digit_iter) {
00326
00327 const PlexSEIdAltL & seid = (*digit_iter)->GetPlexSEIdAltL();
00328 RawChannelId rawchid = (*digit_iter)->GetChannelId();
00329
00330 MSG("LIPatternFinder", Msg::kVerbose)
00331 << " PL = " << seid.GetPlane()
00332 << " END = " << seid.GetEnd()
00333 << " CRATE = " << rawchid.GetCrate()
00334 << " VARC = " << rawchid.GetVarcId()
00335 << " VMM = " << rawchid.GetVmm()
00336 << " Q = " << (*digit_iter)->GetCharge() << endl;
00337 }
00338 }
00339