/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 "ADCoincTagging.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 00017 #include "DataSvc/IDaqDetailsSvc.h" 00018 00019 #include "Context/ServiceMode.h" 00020 #include "GaudiKernel/SystemOfUnits.h" 00021 00022 00023 using namespace std; 00024 using namespace Gaudi; 00025 using namespace DayaBay; 00026 00027 ADCoincTagging::ADCoincTagging(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/CoincidenceLoose", 00034 "the TES path of AD Coincidence Data location"); 00035 declareProperty("TagLocation", m_tagLocation="/Event/Tag/Physics/CoincidenceLoose", 00036 "the TES path of AD Coincidence Tag location"); 00037 declareProperty("TimeWindow", m_timeWindow=200*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 ADCoincTagging::~ADCoincTagging() 00045 { 00046 } 00047 00048 00049 StatusCode ADCoincTagging::initialize() 00050 { 00051 info() << "initialize: coincidence time window: " << m_timeWindow/Gaudi::Units::microsecond << " microseconds" << endreq; 00052 00053 m_daqDetailsSvc = svc<IDaqDetailsSvc>("DetailsFromRecordSvc", true); 00054 if (!m_daqDetailsSvc) { 00055 error() << "Failed to load IDaqDetailsSvc" << endreq; 00056 return StatusCode::FAILURE; 00057 } 00058 00059 // initialize 00060 m_inputHeaders[DetectorId::kAD1] = vector<const IHeader*>(); 00061 m_inputHeaders[DetectorId::kAD2] = vector<const IHeader*>(); 00062 m_inputHeaders[DetectorId::kAD3] = vector<const IHeader*>(); 00063 m_inputHeaders[DetectorId::kAD4] = vector<const IHeader*>(); 00064 00065 return StatusCode::SUCCESS; 00066 } 00067 00068 00069 00070 StatusCode ADCoincTagging::execute() 00071 { 00072 RecHeader* recHeader = get<RecHeader>(m_recHeaderLoc); 00073 if ( !recHeader ) { 00074 warning() << "Cannot find header at " << m_recHeaderLoc << endreq; 00075 return StatusCode::FAILURE; 00076 } 00077 00078 TimeStamp ts = recHeader->context().GetTimeStamp(); 00079 DetectorId::DetectorId_t detectorId = recHeader->context().GetDetId(); 00080 00081 TimeStamp lastTS = ts; 00082 00083 if(m_lastTimeStamp.find(detectorId) != m_lastTimeStamp.end()){ 00084 lastTS = m_lastTimeStamp[detectorId]; 00085 } 00086 m_lastTimeStamp[detectorId] = ts; 00087 00088 // only look for AD Coincidence 00089 if ( detectorId == DetectorId::kIWS 00090 || detectorId == DetectorId::kOWS 00091 || detectorId == DetectorId::kRPC) { 00092 return StatusCode::SUCCESS; 00093 } 00094 00095 TimeStamp dt = TimeStamp(ts); 00096 dt.Subtract(lastTS); 00097 double dt_sec = dt.GetSeconds(); 00098 00099 if (dt_sec*Gaudi::Units::second > m_timeWindow) { 00100 int multiplicity = m_inputHeaders[detectorId].size(); 00101 if (multiplicity < 2) { 00102 m_inputHeaders[detectorId].clear(); 00103 } 00104 else { 00105 // found a gap 00106 00107 if (dt_sec*Gaudi::Units::second > m_maxGapWindow) { 00108 // long gap in DAQ, the previous multiplets not in memory any more 00109 warning() << "Event gap in AD " << detectorId << ": " << dt_sec << " sec" << endreq; 00110 } 00111 else { 00112 // found a conincident multiplet 00113 vector<const IHeader*>& inputHeaders = m_inputHeaders[detectorId]; 00114 00115 // save a (redundant) tag header object into the tag location 00116 HeaderObject *tag = MakeHeader<HeaderObject>(inputHeaders); 00117 put(tag, m_tagLocation); 00118 00119 // make the UserData 00120 UserDataHeader* data = MakeHeader<UserDataHeader>(inputHeaders); 00121 00122 // store user-defined data 00123 SaveRecData(inputHeaders, data); 00124 SaveCalibStatsData(inputHeaders, data); 00125 SaveOtherData(inputHeaders, data); 00126 00127 // save UserData to TES 00128 put(data, m_location); 00129 00130 m_nTagged++; 00131 m_nTaggedTriggers += multiplicity; 00132 // info() << "found one: multiplicty " << multiplicity 00133 // << " execNumber: " << execNumber << endreq; 00134 } 00135 00136 m_inputHeaders[detectorId].clear(); 00137 } 00138 } 00139 00140 m_inputHeaders[detectorId].push_back(recHeader); 00141 00142 return StatusCode::SUCCESS; 00143 } 00144 00145 00146 StatusCode ADCoincTagging::finalize() 00147 { 00148 info() << m_nTagged << " multiplets (" << m_nTaggedTriggers 00149 << " triggers) tagged at " << m_location << endreq; 00150 return StatusCode::SUCCESS; 00151 } 00152 00153 00154 // helper methods 00155 void ADCoincTagging::SaveRecData(vector<const IHeader*>& inputHeaders, UserDataHeader* dataHeader) 00156 { 00157 // initialize data vectors 00158 vector<float> e, x, y, z; 00159 vector<int> triggerNumber, triggerType, t_s, t_ns, dt_ns, energyStatus, positionStatus; 00160 00161 int t0_s = 0; 00162 int t0_ns = 0; 00163 for (size_t i=0; i<inputHeaders.size(); i++) { 00164 const RecHeader* recHeader = dynamic_cast<const RecHeader*>(inputHeaders[i]); 00165 RecTrigger result = recHeader->recTrigger(); 00166 e.push_back(result.energy()/Units::MeV); 00167 x.push_back(result.position().x()/Units::mm); 00168 y.push_back(result.position().y()/Units::mm); 00169 z.push_back(result.position().z()/Units::mm); 00170 triggerNumber.push_back(result.triggerNumber()); 00171 triggerType.push_back(result.triggerType()); 00172 00173 energyStatus.push_back(result.energyStatus()); 00174 positionStatus.push_back(result.positionStatus()); 00175 int thisT_s = recHeader->timeStamp().GetSec(); 00176 int thisT_ns = recHeader->timeStamp().GetNanoSec(); 00177 if (0 == i) { 00178 t0_s = thisT_s; 00179 t0_ns = thisT_ns; 00180 } 00181 t_s.push_back(thisT_s); 00182 t_ns.push_back(thisT_ns); 00183 dt_ns.push_back( int((thisT_s-t0_s)*1e9 + thisT_ns - t0_ns)); 00184 } 00185 00186 dataHeader->set("e", e); 00187 dataHeader->set("x", x); 00188 dataHeader->set("y", y); 00189 dataHeader->set("z", z); 00190 dataHeader->set("triggerNumber", triggerNumber); 00191 dataHeader->set("triggerType", triggerType); 00192 dataHeader->set("t_s", t_s); 00193 dataHeader->set("t_ns", t_ns); 00194 dataHeader->set("dt_ns", dt_ns); 00195 dataHeader->set("energyStatus", energyStatus); 00196 dataHeader->set("positionStatus", positionStatus); 00197 } 00198 00199 00200 void ADCoincTagging::SaveCalibStatsData(vector<const IHeader*>& inputHeaders, UserDataHeader* dataHeader) 00201 { 00202 int nDataInt = 1; 00203 int nDataFloat = 32; 00204 string dataStrInt[] = { "nHit" }; 00205 string dataStrFloat[] = { 00206 "nPESum", "nPERMS", "nPulseSum", "nPulseRMS", // PE distribution 00207 "tEarliest", "tLatest", "tMean", // time distribution 00208 "EarlyCharge", "NominalCharge", "LateCharge", // 3 diffrent charges 00209 "MaxQ", "Quadrant", "Kurtosis", "PeakRMS", "MiddleTimeRMS", // for flashers 00210 "dtLastAD1_ms", "dtLastAD2_ms", "dtLastAD3_ms", "dtLastAD4_ms", "dtLastIWS_ms", "dtLastOWS_ms", "dtLastRPC_ms", 00211 "dtNextAD1_ms", "dtNextAD2_ms", "dtNextAD3_ms", "dtNextAD4_ms", "dtNextIWS_ms", "dtNextOWS_ms", "dtNextRPC_ms", 00212 "dtLast_ADMuon_ms", "dtLast_ADShower_ms", "ELast_ADShower_pe" 00213 }; 00214 vector< vector<int> > dataInt(nDataInt); 00215 vector< vector<float> > dataFloat(nDataFloat); 00216 00217 for (size_t i=0; i<inputHeaders.size(); i++) { 00218 const RecHeader* recHeader = dynamic_cast<const RecHeader*>(inputHeaders[i]); 00219 vector<const IHeader*> inputHeaders = recHeader->findHeaders("/Event/Data/CalibStats"); 00220 if ( 1 == inputHeaders.size() ) { 00221 // Fix:: UserDataHeader class need to make getBlahBlah() methods const. 00222 UserDataHeader* calibStats = const_cast<UserDataHeader*>(dynamic_cast<const UserDataHeader*>(inputHeaders[0])); 00223 for (int j=0; j<nDataInt; j++ ) { 00224 int value = calibStats->getInt(dataStrInt[j]); 00225 dataInt[j].push_back(value); 00226 } 00227 for (int j=0; j<nDataFloat; j++ ) { 00228 float value = calibStats->getFloat(dataStrFloat[j]); 00229 dataFloat[j].push_back(value); 00230 } 00231 } 00232 else { 00233 warning() << inputHeaders.size() << " Data at /Event/Data/CalibStats" << endreq; 00234 } 00235 } 00236 for (int j=0; j<nDataInt; j++ ) { 00237 dataHeader->set( string("calib_")+dataStrInt[j], dataInt[j] ); 00238 } 00239 for (int j=0; j<nDataFloat; j++ ) { 00240 dataHeader->set( string("calib_")+dataStrFloat[j], dataFloat[j] ); 00241 } 00242 } 00243 00244 00245 void ADCoincTagging::SaveOtherData(vector<const IHeader*>& inputHeaders, UserDataHeader* dataHeader) 00246 { 00247 // initialize data vectors 00248 vector<int> I, J; 00249 00250 int multiplicity = inputHeaders.size(); 00251 for (int i=0; i<multiplicity-1; i++) { 00252 for (int j=i+1; j<multiplicity; j++) { 00253 I.push_back(i); 00254 J.push_back(j); 00255 } 00256 } 00257 00258 dataHeader->set("multiplicity", multiplicity); 00259 dataHeader->set("I", I); 00260 dataHeader->set("J", J); 00261 00262 int runNo = 0; 00263 int fileNo = 0; 00264 ServiceMode svcMode = ServiceMode(dynamic_cast<const HeaderObject*>(inputHeaders.at(0))->context(), 0); 00265 const DaqRunDetails& runDetails = m_daqDetailsSvc->runDetails(svcMode); 00266 if (&runDetails) { 00267 runNo = runDetails.runNumber(); 00268 } 00269 const DaqFileDetails& fileDetails = m_daqDetailsSvc->fileDetails(svcMode); 00270 if (&fileDetails) { 00271 fileNo = fileDetails.fileNumber(); 00272 } 00273 dataHeader->set("runNo", runNo); 00274 dataHeader->set("fileNo", fileNo); 00275 } 00276