/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 //***************************** 00002 // 00003 // AD Coincidence Tag/Data 00004 // chao@bnl.gov 2011-09-26 00005 // 00006 //***************************** 00007 00008 #include "CoincidenceTight.h" 00009 00010 #include "Context/Context.h" 00011 #include "Context/TimeStamp.h" 00012 00013 #include "Event/HeaderObject.h" 00014 #include "Event/RecHeader.h" 00015 #include "Event/UserDataHeader.h" 00016 #include "DataUtilities/DybArchiveList.h" 00017 #include "DataSvc/IDaqDetailsSvc.h" 00018 00019 #include "Context/ServiceMode.h" 00020 #include "GaudiKernel/SystemOfUnits.h" 00021 00022 #include <iomanip> 00023 using namespace std; 00024 using namespace Gaudi; 00025 using namespace DayaBay; 00026 00027 CoincidenceTight::CoincidenceTight(const string& name, ISvcLocator* svcloc) 00028 : DybBaseAlg(name, svcloc), 00029 m_nTagged(0), m_nTaggedTriggers(0) 00030 { 00031 declareProperty("RecLocation", m_recHeaderLoc="/Event/Rec/AdSimple", 00032 "the TES path of target event header location"); 00033 declareProperty("Location", m_location="/Event/Data/Physics/CoincidenceTight", 00034 "the TES path of AD Coincidence Data location"); 00035 declareProperty("TagLocation", m_tagLocation="/Event/Tag/Physics/CoincidenceTight", 00036 "the TES path of AD Coincidence Tag location"); 00037 declareProperty("TimeWindow", m_timeWindow=400*Gaudi::Units::microsecond, 00038 "AD coincidence time window"); 00039 declareProperty("MaxGapWindow", m_maxGapWindow=0.2*Gaudi::Units::second, 00040 "Maximum Gap between two triggers in one AD"); 00041 } 00042 00043 00044 CoincidenceTight::~CoincidenceTight() 00045 { 00046 } 00047 00048 00049 StatusCode CoincidenceTight::initialize() 00050 { 00051 info() << "initialize: coincidence time window: " << m_timeWindow/Gaudi::Units::microsecond << " microseconds" << endreq; 00052 m_daqDetailsSvc = svc<IDaqDetailsSvc>("DetailsFromRecordSvc", true); 00053 if (!m_daqDetailsSvc) { 00054 error() << "Failed to load IDaqDetailsSvc" << endreq; 00055 return StatusCode::FAILURE; 00056 } 00057 00058 StatusCode sc = service("EventDataArchiveSvc", m_archiveSvc); 00059 if (sc == StatusCode::FAILURE) { 00060 error() << "Failed to retrieve EventDataArchiveSvc" << endreq; 00061 return StatusCode::FAILURE; 00062 } 00063 00064 // initialize 00065 DetectorId::DetectorId_t detectorId[4] = { 00066 DetectorId::kAD1, DetectorId::kAD2, DetectorId::kAD3, DetectorId::kAD4 00067 }; 00068 for (int i=0; i<4; i++) { 00069 DetectorId::DetectorId_t detector = detectorId[i]; 00070 m_inputHeaders[detector] = vector<const IHeader*>(); 00071 m_adScaledHeaders[detector] = vector<RecHeader*>(); 00072 m_integratedLiveTime_sec[detector] = 0; 00073 m_integratedGapTime_sec[detector] = 0; 00074 m_extendTimeMultiplet_sec[detector] = 0; 00075 } 00076 m_detName[DetectorId::kAD1] = "AD1"; m_detName[DetectorId::kAD2] = "AD2"; 00077 m_detName[DetectorId::kAD3] = "AD3"; m_detName[DetectorId::kAD4] = "AD4"; 00078 00079 00080 m_integratedNGaps = 0; 00081 00082 m_execNum = 0; 00083 return StatusCode::SUCCESS; 00084 } 00085 00086 00087 00088 StatusCode CoincidenceTight::execute() 00089 { 00090 // m_execNum++; 00091 // info() << "exec#: " << m_execNum << endreq; 00092 00093 RecHeader* recHeader = get<RecHeader>(m_recHeaderLoc); 00094 if ( !recHeader ) { 00095 warning() << "Cannot find header at " << m_recHeaderLoc << endreq; 00096 return StatusCode::FAILURE; 00097 } 00098 00099 RecHeader* adScaledHeader = get<RecHeader>("/Event/Rec/AdScaled"); 00100 00101 TimeStamp ts = recHeader->context().GetTimeStamp(); 00102 DetectorId::DetectorId_t detectorId = recHeader->context().GetDetId(); 00103 00104 TimeStamp lastTS = ts; 00105 00106 if(m_lastTimeStamp.find(detectorId) != m_lastTimeStamp.end()){ 00107 lastTS = m_lastTimeStamp[detectorId]; 00108 } 00109 m_lastTimeStamp[detectorId] = ts; 00110 00111 // only look for AD Coincidence 00112 if ( detectorId == DetectorId::kIWS 00113 || detectorId == DetectorId::kOWS 00114 || detectorId == DetectorId::kRPC) { 00115 return StatusCode::SUCCESS; 00116 } 00117 00118 TimeStamp dt = TimeStamp(ts); 00119 dt.Subtract(lastTS); 00120 double dt_sec = dt.GetSeconds(); 00121 // info() << "AD: " << detectorId << ", DtSec: " << dt_sec << endreq; 00122 00123 if (dt_sec*Gaudi::Units::second > m_maxGapWindow) { 00124 // long gap in DAQ, considered as deadtime in coincidence tree. 00125 m_integratedGapTime_sec[detectorId] += dt_sec; 00126 m_integratedNGaps++; 00127 } 00128 else { 00129 m_integratedLiveTime_sec[detectorId] += dt_sec; 00130 } 00131 00132 if (dt_sec*Gaudi::Units::second > m_timeWindow) { 00133 int multiplicity = m_inputHeaders[detectorId].size(); 00134 if (multiplicity < 2) { 00135 m_inputHeaders[detectorId].clear(); 00136 m_adScaledHeaders[detectorId].clear(); 00137 } 00138 else { 00139 // found a gap 00140 00141 if (dt_sec*Gaudi::Units::second > m_maxGapWindow) { 00142 // protection: long gap in DAQ, the previous multiplets may not in memory any more 00143 warning() << "Event gap in AD " << detectorId << ": " << dt_sec << " sec" << endreq; 00144 m_integratedLiveTime_sec[detectorId] -= m_extendTimeMultiplet_sec[detectorId]; 00145 } 00146 else { 00147 // info() << "start saving: dtLast: " << dt_sec << endreq; 00148 // found a conincident multiplet 00149 vector<const IHeader*>& inputHeaders = m_inputHeaders[detectorId]; 00150 00151 // info() << "making user tag: size of input headers: " << inputHeaders.size() << endreq; 00152 // save a (redundant) tag header object into the tag location 00153 HeaderObject *tag = MakeHeader<HeaderObject>(inputHeaders); 00154 put(tag, m_tagLocation); 00155 00156 // make the UserData 00157 UserDataHeader* data = MakeHeader<UserDataHeader>(inputHeaders); 00158 00159 // store user-defined data 00160 SaveRecData(inputHeaders, data); 00161 SaveAdScaledData(m_adScaledHeaders[detectorId], data); 00162 SaveCalibStatsData(inputHeaders, data); 00163 SaveMuonData(data); 00164 SaveOtherData(inputHeaders, data); 00165 00166 data->set("integratedLiveTime_sec", m_integratedLiveTime_sec[detectorId]); 00167 data->set("integratedGapTime_sec", m_integratedGapTime_sec[detectorId]); 00168 data->set("integratedNGaps", m_integratedNGaps); 00169 data->set("extendTimeMultiplet_sec", m_extendTimeMultiplet_sec[detectorId]); 00170 00171 if (PreSelection(data)) { 00172 // save UserData to TES 00173 put(data, m_location); 00174 m_nTagged++; 00175 m_nTaggedTriggers += multiplicity; 00176 // info() << "found one: multiplicty " << multiplicity 00177 // << " execNumber: " << execNumber << endreq; 00178 } 00179 else { 00180 delete data; 00181 } 00182 } 00183 00184 m_inputHeaders[detectorId].clear(); 00185 m_adScaledHeaders[detectorId].clear(); 00186 m_extendTimeMultiplet_sec[detectorId] = 0; 00187 } 00188 } 00189 else { 00190 m_extendTimeMultiplet_sec[detectorId] += dt_sec; 00191 // info() << "extented time AD " << detectorId << " : " << m_extendTimeMultiplet_sec[detectorId] << endreq; 00192 } 00193 00194 m_inputHeaders[detectorId].push_back(recHeader); 00195 m_adScaledHeaders[detectorId].push_back(adScaledHeader); 00196 00197 return StatusCode::SUCCESS; 00198 } 00199 00200 00201 StatusCode CoincidenceTight::finalize() 00202 { 00203 info() << m_nTagged << " multiplets (" << m_nTaggedTriggers 00204 << " triggers) tagged at " << m_location << endreq; 00205 return StatusCode::SUCCESS; 00206 } 00207 00208 00209 // helper methods 00210 void CoincidenceTight::SaveRecData(vector<const IHeader*>& inputHeaders, UserDataHeader* dataHeader) 00211 { 00212 // initialize data vectors 00213 vector<float> e, x, y, z, rawEvis; 00214 vector<int> triggerNumber, triggerType, t_s, t_ns, dt_ns, energyStatus, positionStatus; 00215 00216 int t0_s = 0; 00217 int t0_ns = 0; 00218 for (size_t i=0; i<inputHeaders.size(); i++) { 00219 const RecHeader* recHeader = dynamic_cast<const RecHeader*>(inputHeaders[i]); 00220 RecTrigger result = recHeader->recTrigger(); 00221 e.push_back(result.energy()/Units::MeV); 00222 x.push_back(result.position().x()/Units::mm); 00223 y.push_back(result.position().y()/Units::mm); 00224 z.push_back(result.position().z()/Units::mm); 00225 rawEvis.push_back(result.rawEvis()/Units::MeV); 00226 00227 triggerNumber.push_back(result.triggerNumber()); 00228 triggerType.push_back(result.triggerType()); 00229 00230 energyStatus.push_back(result.energyStatus()); 00231 positionStatus.push_back(result.positionStatus()); 00232 int thisT_s = recHeader->timeStamp().GetSec(); 00233 int thisT_ns = recHeader->timeStamp().GetNanoSec(); 00234 if (0 == i) { 00235 t0_s = thisT_s; 00236 t0_ns = thisT_ns; 00237 } 00238 t_s.push_back(thisT_s); 00239 t_ns.push_back(thisT_ns); 00240 dt_ns.push_back( int((thisT_s-t0_s)*1e9 + thisT_ns - t0_ns)); 00241 } 00242 00243 dataHeader->set("e", e); 00244 dataHeader->set("x", x); 00245 dataHeader->set("y", y); 00246 dataHeader->set("z", z); 00247 dataHeader->set("rawEvis", rawEvis); 00248 00249 dataHeader->set("triggerNumber", triggerNumber); 00250 dataHeader->set("triggerType", triggerType); 00251 dataHeader->set("t_s", t_s); 00252 dataHeader->set("t_ns", t_ns); 00253 dataHeader->set("dt_ns", dt_ns); 00254 dataHeader->set("energyStatus", energyStatus); 00255 dataHeader->set("positionStatus", positionStatus); 00256 } 00257 00258 void CoincidenceTight::SaveAdScaledData(vector<DayaBay::RecHeader*>& inputHeaders, UserDataHeader* dataHeader) 00259 { 00260 // initialize data vectors 00261 vector<float> e, x, y, z, rawEvis; 00262 vector<int> energyStatus, positionStatus; 00263 00264 00265 for (size_t i=0; i<inputHeaders.size(); i++) { 00266 RecHeader* recHeader = inputHeaders[i]; 00267 RecTrigger result = recHeader->recTrigger(); 00268 e.push_back(result.energy()/Units::MeV); 00269 x.push_back(result.position().x()/Units::mm); 00270 y.push_back(result.position().y()/Units::mm); 00271 z.push_back(result.position().z()/Units::mm); 00272 rawEvis.push_back(result.rawEvis()/Units::MeV); 00273 energyStatus.push_back(result.energyStatus()); 00274 positionStatus.push_back(result.positionStatus()); 00275 } 00276 00277 dataHeader->set("e_AdScaled", e); 00278 dataHeader->set("x_AdScaled", x); 00279 dataHeader->set("y_AdScaled", y); 00280 dataHeader->set("z_AdScaled", z); 00281 dataHeader->set("rawEvis_AdScaled", rawEvis); 00282 dataHeader->set("energyStatus_AdScaled", energyStatus); 00283 dataHeader->set("positionStatus_AdScaled", positionStatus); 00284 } 00285 00286 00287 void CoincidenceTight::SaveCalibStatsData(vector<const IHeader*>& inputHeaders, UserDataHeader* dataHeader) 00288 { 00289 int nDataInt = 1; 00290 int nDataFloat = 23; // + dtLastAD/dtNextAD 00291 string dataStrInt[] = { "nHit" }; 00292 string dataStrFloat[] = { 00293 "nPESum", "nPERMS", "nPulseSum", "nPulseRMS", // PE distribution 00294 "tEarliest", "tLatest", "tMean", // time distribution 00295 "EarlyCharge", "NominalCharge", "LateCharge", "PeakCharge", // 4 diffrent charges 00296 "MaxQ", "Quadrant", "flasher_flag", "time_PSD", "time_PSD1", "MaxQ_2inchPMT", // for flashers 00297 "dtLastIWS_ms", "dtLastOWS_ms", "dtLastRPC_ms", "dtNextIWS_ms", "dtNextOWS_ms", "dtNextRPC_ms", // last/next trigger (deprecated) 00298 }; 00299 vector< vector<int> > dataInt(nDataInt); 00300 vector< vector<float> > dataFloat(nDataFloat); 00301 vector<float> dtLastAD_ms; 00302 vector<float> dtNextAD_ms; 00303 00304 DetectorId::DetectorId_t detectorId = dataHeader->context().GetDetId(); 00305 string detName = m_detName[detectorId]; 00306 string name_dtLastAD = string("dtLast")+detName+"_ms"; 00307 string name_dtNextAD = string("dtNext")+detName+"_ms"; 00308 00309 for (size_t i=0; i<inputHeaders.size(); i++) { 00310 const RecHeader* recHeader = dynamic_cast<const RecHeader*>(inputHeaders[i]); 00311 vector<const IHeader*> inputHeaders = recHeader->findHeaders("/Event/Data/CalibStats"); 00312 if ( 1 == inputHeaders.size() ) { 00313 // Fix:: UserDataHeader class need to make getBlahBlah() methods const. 00314 UserDataHeader* calibStats = const_cast<UserDataHeader*>(dynamic_cast<const UserDataHeader*>(inputHeaders[0])); 00315 for (int j=0; j<nDataInt; j++ ) { 00316 int value = calibStats->getInt(dataStrInt[j]); 00317 dataInt[j].push_back(value); 00318 } 00319 for (int j=0; j<nDataFloat; j++ ) { 00320 float value = calibStats->getFloat(dataStrFloat[j]); 00321 dataFloat[j].push_back(value); 00322 } 00323 dtLastAD_ms.push_back(calibStats->getFloat(name_dtLastAD)); 00324 dtNextAD_ms.push_back(calibStats->getFloat(name_dtNextAD)); 00325 } 00326 else { 00327 warning() << inputHeaders.size() << " Data at /Event/Data/CalibStats" << endreq; 00328 } 00329 } 00330 00331 for (int j=0; j<nDataInt; j++ ) { 00332 dataHeader->set( string("calib_")+dataStrInt[j], dataInt[j] ); 00333 } 00334 for (int j=0; j<nDataFloat; j++ ) { 00335 dataHeader->set( string("calib_")+dataStrFloat[j], dataFloat[j] ); 00336 } 00337 dataHeader->set("calib_dtLastAD_ms", dtLastAD_ms); 00338 dataHeader->set("calib_dtNextAD_ms", dtNextAD_ms); 00339 } 00340 00341 00342 void CoincidenceTight::SaveMuonData(UserDataHeader* dataHeader) 00343 { 00344 vector<int> t_s = dataHeader->getIntArray("t_s"); 00345 vector<int> t_ns = dataHeader->getIntArray("t_ns"); 00346 00347 int firstCoinc_t_s = t_s.at(0); 00348 int firstCoinc_t_ns = t_ns.at(0); 00349 int multiplicity = t_s.size(); 00350 00351 SmartDataPtr<DybArchiveList> muons(m_archiveSvc, "/Event/Data/Physics/MuonData"); 00352 if (!muons) { 00353 debug() << "no Muons in archive?? " << endreq; 00354 dataHeader->set("isGap", 1); 00355 dataHeader->set("nMuon", 0); 00356 dataHeader->set("mu_t_s", vector<int>()); 00357 dataHeader->set("mu_t_ns", vector<int>()); 00358 dataHeader->set("mu_nHitIWS", vector<int>()); 00359 dataHeader->set("mu_nHitOWS", vector<int>()); 00360 dataHeader->set("mu_hitRPC", vector<int>()); 00361 dataHeader->set("mu_nPESumAD", vector<float>()); 00362 dataHeader->set("mu_triggerNumberIWS", vector<int>()); 00363 dataHeader->set("mu_triggerNumberOWS", vector<int>()); 00364 dataHeader->set("mu_triggerNumberRPC", vector<int>()); 00365 dataHeader->set("mu_triggerNumberAD", vector<int>()); 00366 dataHeader->set("dtLastWPMuon_ms", vector<float>(multiplicity, 1e7)); 00367 dataHeader->set("dtLastADMuon_ms", vector<float>(multiplicity, 1e7)); 00368 dataHeader->set("dtLastRPCMuon_ms", vector<float>(multiplicity, 1e7)); 00369 dataHeader->set("dtLastShowerMuon_ms", vector<float>(multiplicity, 1e7)); 00370 dataHeader->set("nPESumLastShowerMuon", vector<float>(multiplicity, 0)); 00371 return; 00372 } 00373 00374 00375 DetectorId::DetectorId_t detectorId = dataHeader->context().GetDetId(); 00376 00377 string detName = m_detName[detectorId]; 00378 string name_nPESumAD = string("calib_nPESum_")+detName; 00379 string name_triggerNumberAD = string("triggerNumber_")+detName; 00380 00381 vector<int> mu_t_s, mu_t_ns, mu_nHit_IWS, mu_nHit_OWS, mu_hitRPC; 00382 vector<int> mu_triggerNumberIWS, mu_triggerNumberOWS, mu_triggerNumberRPC, mu_triggerNumberAD; 00383 vector<float> mu_nPESum_AD; 00384 00385 int nMuon=0; 00386 DybArchiveList::const_iterator iter = muons->begin(); 00387 for (; iter != muons->end(); iter++) { 00388 UserDataHeader* muonData = dynamic_cast<UserDataHeader*> (*iter); 00389 int tMu_s = muonData->getInt("tMu_s"); 00390 00391 int tMu_ns = muonData->getInt("tMu_ns"); 00392 int calib_nHit_IWS = muonData->getInt("calib_nHit_IWS"); 00393 int calib_nHit_OWS = muonData->getInt("calib_nHit_OWS"); 00394 int hitRPC = muonData->getInt("hitRPC"); 00395 float calib_nPESum_AD = muonData->getFloat(name_nPESumAD); 00396 int triggerNumberIWS = muonData->getInt("triggerNumber_IWS"); 00397 int triggerNumberOWS = muonData->getInt("triggerNumber_OWS"); 00398 int triggerNumberRPC = muonData->getInt("triggerNumber_RPC"); 00399 int triggerNumberAD = muonData->getInt(name_triggerNumberAD); 00400 00401 double dtMax_ms = (double(firstCoinc_t_s-tMu_s)*1e9 + (firstCoinc_t_ns-tMu_ns))/1e6; 00402 if (dtMax_ms > 2) { 00403 // store shower muons between (2ms, 1s) 00404 if (dtMax_ms>1000) break; 00405 if (calib_nPESum_AD > 2e5) { 00406 mu_t_s.push_back(tMu_s); 00407 mu_t_ns.push_back(tMu_ns); 00408 mu_nHit_IWS.push_back(calib_nHit_IWS); 00409 mu_nHit_OWS.push_back(calib_nHit_OWS); 00410 mu_hitRPC.push_back(hitRPC); 00411 mu_nPESum_AD.push_back(calib_nPESum_AD); 00412 mu_triggerNumberIWS.push_back(triggerNumberIWS); 00413 mu_triggerNumberOWS.push_back(triggerNumberOWS); 00414 mu_triggerNumberRPC.push_back(triggerNumberRPC); 00415 mu_triggerNumberAD.push_back(triggerNumberAD); 00416 nMuon++; 00417 } 00418 continue; 00419 } 00420 else { // store non-shower muons between (~-0.4ms, 2ms) 00421 // cout << tMu_s << ", " << tMu_ns << endl; 00422 // cout << firstCoinc_t_s << ", " << firstCoinc_t_ns << endl; 00423 // cout << dtMax_ms << endl; 00424 // cout << "---" << endl; 00425 mu_t_s.push_back(tMu_s); 00426 mu_t_ns.push_back(tMu_ns); 00427 mu_nHit_IWS.push_back(calib_nHit_IWS); 00428 mu_nHit_OWS.push_back(calib_nHit_OWS); 00429 mu_hitRPC.push_back(hitRPC); 00430 mu_nPESum_AD.push_back(calib_nPESum_AD); 00431 mu_triggerNumberIWS.push_back(triggerNumberIWS); 00432 mu_triggerNumberOWS.push_back(triggerNumberOWS); 00433 mu_triggerNumberRPC.push_back(triggerNumberRPC); 00434 mu_triggerNumberAD.push_back(triggerNumberAD); 00435 nMuon++; 00436 } 00437 00438 } 00439 // info() << "# Muon: " << nMuon << endreq; // 1ms before first to 200us after last 00440 00441 // for convenience to use in TTree::Draw(), however if need redefintion of muons, please don't use those 00442 vector<float> dtLastWPMuon_ms(multiplicity); 00443 vector<float> dtLastADMuon_ms(multiplicity); 00444 vector<float> dtLastRPCMuon_ms(multiplicity); 00445 vector<float> dtLastShowerMuon_ms(multiplicity); 00446 vector<float> nPESumLastShowerMuon(multiplicity); 00447 00448 // cout << "multiplicity: " << multiplicity << endl; 00449 for (int i=0; i<multiplicity; i++) { 00450 dtLastWPMuon_ms[i] = 1e7; // any large number 00451 dtLastADMuon_ms[i] = 1e7; 00452 dtLastRPCMuon_ms[i] = 1e7; 00453 dtLastShowerMuon_ms[i] = 1e7; 00454 nPESumLastShowerMuon[i] = 0; 00455 00456 bool hasSetWPMuon = false; 00457 bool hasSetADMuon = false; 00458 bool hasSetRPCMuon = false; 00459 bool hasSetShowerMuon = false; 00460 for (int j=0; j<nMuon; j++) { 00461 double dtMuon_ms = (double(t_s[i]-mu_t_s[j])*1e9 + (t_ns[i]-mu_t_ns[j]))/1e6; 00462 if (dtMuon_ms < -2e-3) { continue; } // too far in the future, must not be correlated 00463 00464 bool isWPMuon = mu_nHit_IWS[j]>12 || mu_nHit_OWS[j]>12; 00465 bool isADMuon = mu_nPESum_AD[j] > 3000; 00466 bool isRPCMuon = mu_hitRPC[j] == 1; 00467 bool isShowerMuon = mu_nPESum_AD[j] > 5.5e5; 00468 00469 if (isWPMuon && !hasSetWPMuon) { dtLastWPMuon_ms[i] = dtMuon_ms; hasSetWPMuon = true; } 00470 if (isADMuon && !hasSetADMuon) { dtLastADMuon_ms[i] = dtMuon_ms; hasSetADMuon = true; } 00471 if (isRPCMuon && !hasSetRPCMuon) { dtLastRPCMuon_ms[i] = dtMuon_ms; hasSetRPCMuon = true; } 00472 if (isShowerMuon && !hasSetShowerMuon) { 00473 dtLastShowerMuon_ms[i] = dtMuon_ms; 00474 nPESumLastShowerMuon[i] = mu_nPESum_AD[j]; 00475 hasSetShowerMuon = true; 00476 } 00477 00478 } 00479 00480 } 00481 dataHeader->set("isGap", 0); 00482 dataHeader->set("nMuon", nMuon); 00483 00484 dataHeader->set("mu_t_s", mu_t_s); 00485 dataHeader->set("mu_t_ns", mu_t_ns); 00486 dataHeader->set("mu_nHitIWS", mu_nHit_IWS); 00487 dataHeader->set("mu_nHitOWS", mu_nHit_OWS); 00488 dataHeader->set("mu_hitRPC", mu_hitRPC); 00489 dataHeader->set("mu_nPESumAD", mu_nPESum_AD); 00490 dataHeader->set("mu_triggerNumberIWS", mu_triggerNumberIWS); 00491 dataHeader->set("mu_triggerNumberOWS", mu_triggerNumberOWS); 00492 dataHeader->set("mu_triggerNumberRPC", mu_triggerNumberRPC); 00493 dataHeader->set("mu_triggerNumberAD", mu_triggerNumberAD); 00494 00495 dataHeader->set("dtLastWPMuon_ms", dtLastWPMuon_ms); 00496 dataHeader->set("dtLastADMuon_ms", dtLastADMuon_ms); 00497 dataHeader->set("dtLastRPCMuon_ms", dtLastRPCMuon_ms); 00498 dataHeader->set("dtLastShowerMuon_ms", dtLastShowerMuon_ms); 00499 dataHeader->set("nPESumLastShowerMuon", nPESumLastShowerMuon); 00500 00501 } 00502 00503 00504 void CoincidenceTight::SaveOtherData(vector<const IHeader*>& inputHeaders, UserDataHeader* dataHeader) 00505 { 00506 // initialize data vectors 00507 vector<int> I, J; 00508 00509 int multiplicity = inputHeaders.size(); 00510 for (int i=0; i<multiplicity-1; i++) { 00511 for (int j=i+1; j<multiplicity; j++) { 00512 I.push_back(i); 00513 J.push_back(j); 00514 } 00515 } 00516 00517 dataHeader->set("multiplicity", multiplicity); 00518 dataHeader->set("I", I); 00519 dataHeader->set("J", J); 00520 00521 // get from CoincidenceLoose if exist (a hack) 00522 // SmartDataPtr<DybArchiveList> coinc(m_archiveSvc, "/Event/Data/Physics/CoincidenceLoose"); 00523 // if (coinc) { 00524 // DybArchiveList::const_iterator iter = coinc->begin(); 00525 // UserDataHeader* first = dynamic_cast<UserDataHeader*> (*iter); 00526 // dataHeader->set("runNo", first->getInt("runNo")); 00527 // dataHeader->set("fileNo", first->getInt("fileNo")); 00528 // return; 00529 // } 00530 00531 // get from file header (raw file) 00532 int runNo = 0; 00533 int fileNo = 0; 00534 ServiceMode svcMode = ServiceMode(dynamic_cast<const HeaderObject*>(inputHeaders.at(0))->context(), 0); 00535 const DaqRunDetails& runDetails = m_daqDetailsSvc->runDetails(svcMode); 00536 if (&runDetails) { 00537 runNo = runDetails.runNumber(); 00538 } 00539 const DaqFileDetails& fileDetails = m_daqDetailsSvc->fileDetails(svcMode); 00540 if (&fileDetails) { 00541 fileNo = fileDetails.fileNumber(); 00542 } 00543 dataHeader->set("runNo", runNo); 00544 dataHeader->set("fileNo", fileNo); 00545 } 00546 00547 // returns false for obvious useless multiplets 00548 // (some obvious non-IBD multipets are still useful for other studies) 00549 bool CoincidenceTight::PreSelection(UserDataHeader* dataHeader) 00550 { 00551 int multiplicity = dataHeader->getInt("multiplicity"); 00552 00553 // Pre Energy cut, only true if all events in multipets satisfy 00554 float cutElow = 0.5; float cutEHigh = 80; bool allOutsideCutE = true; 00555 vector<float> rawEvis = dataHeader->getFloatArray("rawEvis"); 00556 for (int i=0; i<multiplicity; i++) { 00557 if (rawEvis.at(i) > cutElow && rawEvis.at(i) < cutEHigh) { 00558 allOutsideCutE = false; 00559 break; 00560 } 00561 } 00562 if (allOutsideCutE) return false; 00563 00564 return true; 00565 } 00566 00567