00001
00002
00003
00004
00005
00006
00008 #include "Morgue/Coroner.h"
00009 #include "Morgue/Morgue.h"
00010 #include "MessageService/MsgService.h"
00011 #include "MinosObjectMap/MomNavigator.h"
00012 #include "JobControl/JobCModuleRegistry.h"
00013 #include "Plex/PlexHandle.h"
00014 #include "CandData/CandRecord.h"
00015 #include "CandDigit/CandDigitListHandle.h"
00016 #include "CandDigit/CandDigitHandle.h"
00017 #include "Conventions/Munits.h"
00018 #include "DataUtil/GetRawBlock.h"
00019 #include "DataUtil/GetRawHeader.h"
00020 #include "RawData/RawLiTpmtDigitsBlock.h"
00021 #include "RawData/RawHeader.h"
00022 #include "RawData/RawDigit.h"
00023 #include "Calibrator/Calibrator.h"
00024 #include <algorithm>
00025 #include <cmath>
00026
00027 JOBMODULE(Coroner, "Coroner",
00028 "Coroner");
00029 CVSID("$Id: Coroner.cxx,v 1.7 2007/11/11 06:00:01 rhatcher Exp $");
00030
00031
00032 Coroner::Coroner()
00033 {
00034 }
00035
00036
00037
00038 Coroner::~Coroner()
00039 {
00040 ClearTables();
00041 }
00042
00043
00044
00045 JobCResult Coroner::Ana(const MomNavigator* mom)
00046 {
00047
00048
00049
00050
00051 const Morgue& morgue = Morgue::GetMorgue(mom);
00052 morgue.Print("a");
00053
00054 return JobCResult::kPassed;
00055 }
00056
00057
00058
00059 JobCResult Coroner::Reco(MomNavigator* mom)
00060 {
00061
00062
00063
00064
00065
00066 UpdateLiHitList(mom);
00067
00068 JobCResult result;
00069 VldContext context;
00070
00071
00072 CandRecord *candrec = dynamic_cast<CandRecord *>
00073 (mom->GetFragment("CandRecord", "PrimaryCandidateRecord"));
00074 if (candrec == 0) {
00075 MSG("Morgue", Msg::kWarning) << "No PrimaryCandidateRecord in MOM."
00076 << endl;
00077 result.SetWarning().SetFailed();
00078 return result;
00079 }
00080
00081
00082 context = *(candrec->GetVldContext());
00083
00084
00085 Morgue* morgue = new Morgue;
00086
00087
00088 result |= RecordDeadStrips(morgue,candrec);
00089
00090
00091 result |= RecordBadStrips(morgue,context);
00092
00093
00094 result |= RecordLiHits(morgue,context);
00095
00096
00097 if(candrec)
00098 candrec->AdoptTemporary(morgue);
00099
00100 return result;
00101 }
00102
00103
00104 JobCResult Coroner::RecordDeadStrips(Morgue* morgue,
00105 const CandRecord* candrec)
00106 {
00107
00108
00109
00110
00111
00112
00113 CandDigitListHandle* cdlh = dynamic_cast<CandDigitListHandle *>
00114 (candrec->FindCandHandle("CandDigitListHandle", "canddigitlist"));
00115
00116 if(!cdlh) {
00117 MSG("Morgue", Msg::kWarning) << "No CandDigitList in MOM."
00118 << endl;
00119 return JobCResult::kFailed;
00120 }
00121
00122 VldContext context = *(cdlh->GetVldContext());
00123 morgue->SetTriggerTime((context.GetTimeStamp().GetNanoSec())*Munits::ns);
00124
00125
00126
00127
00128
00129
00130 std::map<PlexPixelSpotId, std::vector<Double_t> > firedPmts;
00131 std::map<PlexPixelSpotId, std::vector<Double_t> >::iterator pmtItr;
00132
00133 CandDigitHandleItr cdhItr(cdlh->GetDaughterIterator());
00134 while(CandDigitHandle *cdh = cdhItr()) {
00135 const PlexSEIdAltL& altl = cdh->GetPlexSEIdAltL();
00136 if(altl.size()>0) {
00137 PlexPixelSpotId tube = altl.GetBestItem().GetPixelSpotId();
00138 tube.SetSpot(1);
00139 tube.SetPixel(1);
00140 Double_t t = cdh->GetTime();
00141 std::vector<Double_t>& v = firedPmts[tube];
00142
00143
00144 bool isnew = true;
00145 for(UInt_t i=0;i<v.size();i++) { if (t==v[i]) isnew=false; };
00146
00147 if(isnew) v.push_back(t);
00148 }
00149 }
00150
00151
00152 const double kVA_1chip_FD = ( 300. * Munits::ns
00153 +22. * (1.0/5.e6)
00154 +100.* Munits::ns );
00155
00156 const double kVA_6chip_FD = ( 300. * Munits::ns
00157 +6.0 * 22. * (1.0/5.e6)
00158 +100.* Munits::ns );
00159
00160
00161 const double kVA_1chip_CalDet = ( 300. * Munits::ns
00162 +22. * (1.0/2.5e6)
00163 +100.* Munits::ns );
00164
00165 const double kVA_6chip_CalDet = ( 300. * Munits::ns
00166 +6.0 * 22. * (1.0/2.5e6)
00167 +100.* Munits::ns );
00168
00169
00170
00171
00172 const double kQIE_1pmt = 32. * 8. * (1.0/53.1e6);
00173
00174
00175 PlexHandle plex(context);
00176
00177
00178 for(pmtItr = firedPmts.begin(); pmtItr!=firedPmts.end(); pmtItr++) {
00179 PlexPixelSpotId tube = pmtItr->first;
00180 std::vector<Double_t>& v = pmtItr->second;
00181 for(UInt_t i=0;i<v.size();i++) {
00182 double t_fired = v[i];
00183 double t_maybe = t_fired;
00184 double t_recover= t_fired;
00185
00186 switch(tube.GetElecType()) {
00187 case ElecType::kVA:
00188 t_maybe = t_fired + kVA_1chip_FD;
00189 t_recover = t_fired + kVA_6chip_FD;
00190 if(tube.GetDetector()==Detector::kCalDet) {
00191 t_maybe = t_fired + kVA_1chip_CalDet;
00192 t_recover = t_fired + kVA_6chip_CalDet;
00193 }
00194 break;
00195 case ElecType::kQIE:
00196 t_maybe = t_fired + kQIE_1pmt;
00197 t_recover = t_fired + kQIE_1pmt;
00198 break;
00199 default:
00200 MSG("Morgue",Msg::kWarning) << "Unknown ElecType on PMT: " << tube.AsString() << endl;
00201 }
00202
00203 int npix = 16;
00204 int nspot = 8;
00205 if(tube.GetElecType()==ElecType::kQIE) {
00206 npix = 64;
00207 nspot= 1;
00208 }
00209 PlexPixelSpotId pixel = tube;
00210
00211 for(int ipix = 0; ipix<npix; ipix++) {
00212 for(int ispot=1; ispot<=nspot; ispot++) {
00213 pixel.SetPixel(ipix);
00214 pixel.SetSpot(ispot);
00215 PlexStripEndId seid = plex.GetStripEndId(pixel);
00216 if(seid.IsValid()) {
00217 morgue->AddDeadStrip(seid,t_fired,t_maybe,t_recover);
00218 }
00219 }
00220 }
00221
00222 }
00223 }
00224
00225 return JobCResult::kPassed;
00226 }
00227
00228
00229
00230 JobCResult Coroner::RecordBadStrips(Morgue* morgue,
00231 const VldContext& context)
00232 {
00233
00234 PlexHandle plex(context);
00235
00236 for(UInt_t itask=0;itask<fBadHardwareTasks.size();itask++) {
00237 fBadHardwareTables[itask]->NewQuery(context,fBadHardwareTasks[itask]);
00238
00239
00240 for(UInt_t irow=0;irow < fBadHardwareTables[itask]->GetNumRows(); irow++) {
00241 const BadHardware* row = fBadHardwareTables[itask]->GetRow(irow);
00242 if(row) {
00243 if(row->IsInEffect(context.GetTimeStamp())) {
00244 vector<PlexStripEndId> strips = row->GetComponent().GetStripEnds(plex);
00245 for(UInt_t istrip = 0; istrip < strips.size(); istrip++) {
00246 morgue->AddBadStrip(strips[istrip], row->GetComponent(), (Morgue::Badness_t)(row->GetBadness()), row->GetReason().c_str() );
00247 }
00248 }
00249 }
00250 }
00251 }
00252
00253
00254 return JobCResult::kPassed;
00255 }
00256
00257
00258 JobCResult Coroner::RecordLiHits(Morgue* morgue,
00259 const VldContext& context)
00260 {
00261 VldTimeStamp eventtime = context.GetTimeStamp();
00262
00263 double smallest_dt = 1e0;
00264 VldTimeStamp closest;
00265 LiHitList_t::iterator it = fRecentLiHits.begin();
00266 for(; it!= fRecentLiHits.end(); it++) {
00267 double dt = fabs((*it) - eventtime);
00268 if(dt <= smallest_dt) {
00269 smallest_dt = dt;
00270 closest = *it;
00271 }
00272 }
00273
00274 if(smallest_dt > 0.1*Munits::second) return JobCResult::kPassed;
00275
00276 double time = Munits::ns*closest.GetNanoSec();
00277 int del_secs = closest.GetSec() - eventtime.GetSec();
00278 time += (del_secs)*Munits::second;
00279 morgue->SetNearestLiTime(time);
00280 MSG("Morgue",Msg::kInfo) << "Set nearest LI time. Dt from trigger is "
00281 << morgue->GetNearestLiTime() - morgue->GetTriggerTime()
00282 << endl;
00283 return JobCResult::kPassed;
00284 }
00285
00286
00287
00288
00289
00290 void Coroner::UpdateLiHitList( const MomNavigator* mom )
00291 {
00295 const RawHeader* header = DataUtil::GetRawHeader<RawHeader>(mom);
00296 if(header) {
00297 VldTimeStamp curtime = header->GetVldContext().GetTimeStamp();
00298
00299
00300 LiHitList_t::iterator it = fRecentLiHits.begin();
00301 for( ; it!= fRecentLiHits.end(); it++) {
00302 if( fabs((*it)-curtime) < 3.0 ) break;
00303 }
00304 if(it!=fRecentLiHits.begin()) {
00305 fRecentLiHits.erase(fRecentLiHits.begin(),(it));
00306 }
00307
00308 }
00309
00310 const RawLiTpmtDigitsBlock* tpmt_block =
00311 DataUtil::GetRawBlock<RawLiTpmtDigitsBlock>(mom);
00312
00313
00314 if(tpmt_block) {
00315 MSG("Morgue",Msg::kInfo) << "Found TPMT block time "
00316 << tpmt_block->GetTimeStamp().AsString()
00317 <<" with "
00318 << tpmt_block->GetNumberOfDigits()
00319 << " digits. " << endl;
00320 for(int i=0;i< tpmt_block->GetNumberOfDigits(); i++) {
00321 const RawDigit* digit = tpmt_block->At(i);
00322 double digtime = Calibrator::Instance().GetTimeFromTDC(digit->GetTDC(),
00323 digit->GetChannel());
00324
00325 VldTimeStamp ts = tpmt_block->GetTimeStamp();
00326 ts.Add(digtime);
00327 fRecentLiHits.push_back(ts);
00328 }
00329 std::sort(fRecentLiHits.begin(),fRecentLiHits.end());
00330 }
00331
00332 }
00333
00334
00335
00336
00337
00338 const Registry& Coroner::DefaultConfig() const
00339 {
00340
00341
00342
00343 static Registry r;
00344
00345
00346 std::string name = this->GetName();
00347 name += ".config.default";
00348 r.SetName(name.c_str());
00349
00350
00351 r.UnLockValues();
00352 r.Set("BadHardwareTasks","1,2");
00353 r.LockValues();
00354
00355 return r;
00356 }
00357
00358
00359
00360 void Coroner::Config(const Registry& r)
00361 {
00362
00363
00364
00365
00366 int task;
00367 if(r.Get("BadHardwareTasks",task) ) {
00368 ClearTables();
00369 fBadHardwareTasks.push_back(task);
00370 fBadHardwareTables.push_back( new DbiResultPtr<BadHardware> );
00371 MSG("Morgue",Msg::kInfo) << "Configured to use BadHardware task " << task << endl;
00372 }
00373
00374 const char* taskstr;
00375 if(r.Get("BadHardwareTasks",taskstr) ) {
00376 ClearTables();
00377 const char* s = taskstr;
00378 int task;
00379 int n;
00380 while( sscanf(s,"%d%n",&task,&n) > 0) {
00381 s += n+1;
00382 fBadHardwareTasks.push_back(task);
00383 fBadHardwareTables.push_back( new DbiResultPtr<BadHardware> );
00384
00385 MSG("Morgue",Msg::kInfo) << "Configured to use BadHardware task " << task << endl;
00386 }
00387 }
00388
00389
00390 }
00391
00392
00393 void Coroner::ClearTables()
00394 {
00395 for(UInt_t itask=0;itask<fBadHardwareTasks.size();itask++) {
00396 delete fBadHardwareTables[itask];
00397 }
00398 fBadHardwareTasks.clear();
00399 fBadHardwareTables.clear();
00400
00401 }
00402