Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

PulserTimingPoint.cxx

Go to the documentation of this file.
00001 #include "PulserTimingPoint.h"
00002 #include "RawData/RawLITimingSummaryBlock.h"
00003 #include "RawData/RawLITimingSummary.h"
00004 #include "Plex/PlexHandle.h"
00005 #include "MessageService/MsgService.h"
00006 #include "DatabaseInterface/DbiWriter.h"
00007 #include <cassert>
00008 #include <fstream>
00009 #include <set>
00010 #include "PulserTimeDrift.h"
00011 
00012 CVSID("$Id: PulserTimingPoint.cxx,v 1.9 2007/03/01 17:06:40 rhatcher Exp $");
00013 
00014 using namespace std;
00015 
00016 PulserTimingPoint::PulserTimingPoint()
00017 {
00018   // Null constructor. For ROOT only.
00019 }
00020 
00021 PulserTimingPoint::PulserTimingPoint(const RawLITimingSummaryBlock* startblock)
00022 {
00026   assert(startblock);
00027   
00028   fCalibType = startblock->GetCalibType();
00029   fCalibPoint = startblock->GetCalibPoint();
00030   fPulserBox = startblock->GetPulserBox();
00031   fLed       = startblock->GetLed();
00032   fPulseHeight = startblock->GetPulseHeight();
00033   fPulses      = startblock->GetPulses();
00034   fPeriod      = startblock->GetPeriod();
00035   fTotalCount  = startblock->GetCount();
00036   fStartContext = fEndContext = startblock->GetVldContext();
00037 
00038   fValidChannels.clear();
00039   ValidChannelList_t::iterator vcit = fValidChannels.end();
00040 
00041   PlexHandle plex(fStartContext);
00042   PlexLedId led(fStartContext.GetDetector(),fPulserBox,fLed);
00043   
00044   // Make a list of channels that this LED connects to.
00045   const std::vector<PlexStripEndId>& ends = plex.GetAllStripEnds();
00046   for(UInt_t i=0;i<ends.size();i++) {
00047     if(plex.GetLedId(ends[i])==led) {
00048       RawChannelId rcid = plex.GetRawChannelId(ends[i]);
00049       UInt_t chindex = PulserTimeDrift::GetIndex(rcid);
00050       vcit = fValidChannels.insert(vcit,chindex); // Insert with time-saving device.
00051     }
00052   }
00053 
00054 
00055   fMaxEntries = fMinEntries = 0;
00056   AddSummaryBlock(startblock);
00057 }
00058 
00059 
00060 PulserTimingPoint::~PulserTimingPoint()
00061 {
00062   ChannelMap_t::iterator it;
00063   for(it = fChannelMap.begin(); it!=fChannelMap.end(); it++) {
00064     if(it->second) delete it->second;
00065   }
00066   fChannelMap.clear();
00067 }
00068 
00069 Bool_t PulserTimingPoint::AddSummaryBlock(const RawLITimingSummaryBlock* sumblock)
00070 {
00075   assert(sumblock);
00076   if(fCalibType !=sumblock->GetCalibType())  return false;
00077   if(fCalibPoint!=sumblock->GetCalibPoint()) return false;
00078   if(fPulserBox !=sumblock->GetPulserBox())  return false;
00079   if(fLed       !=sumblock->GetLed())        return false;
00080 
00081   // Ok, looks good. Add the sucker.
00082   fEndContext = sumblock->GetVldContext();
00083   fTotalCount += sumblock->GetCount();
00084 
00085   // Go through the entries. Use only one per VA chip.
00086   // We only want the summary with the MOST entries for
00087   // each VA chip (to ensure we get max statistics, not a
00088   // crosstalk channel that only occasionaly fires.)
00089 
00090   // Which to use maps my chindex to best At() index.
00091   std::map<UInt_t,Int_t>           whichToUse;
00092   std::map<UInt_t,Int_t>::iterator useItr;
00093 
00094   for(Int_t i=0;i<sumblock->GetNumberOfSummaries(); i++) {
00095     const RawLITimingSummary* summary = sumblock->At(i);
00096     if(!summary) continue; // protection against null entries.
00097     
00098     UInt_t chindex = PulserTimeDrift::GetIndex(summary->GetChannel());
00099     if(!ChannelBelongsToPoint(chindex)) continue; // Ignore illegal channels.
00100     
00101     useItr = whichToUse.find(chindex);
00102     if(useItr==whichToUse.end()) {
00103       // First instance of this channel. Add it.
00104       whichToUse[chindex] = i;
00105     } else {
00106       int index2 = useItr->second;
00107       if(sumblock->At(i)->GetEntries() > sumblock->At(index2)->GetEntries())
00108         useItr->second = i;
00109     }
00110   }
00111 
00112   fMaxEntries = -1;
00113   fMinEntries  = 1e10;
00114 
00115   for(Int_t i=0;i<sumblock->GetNumberOfSummaries();i++) {
00116     const RawLITimingSummary* summary = sumblock->At(i);
00117     if(!summary) continue; // protection against null entries.
00118     
00119     UInt_t chindex = PulserTimeDrift::GetIndex(summary->GetChannel());
00120     if(!ChannelBelongsToPoint(chindex)) continue; // Ignore illegal channels.
00121 
00122     // Is this the right entry to use?
00123     if(whichToUse[chindex]==i) {
00124 
00125       ChannelMap_t::iterator it = fChannelMap.find(chindex);
00126       if(it==fChannelMap.end()) {
00127         // Gotta make a new one.
00128         // Note: aggregate number is pulser box number.
00129         it = 
00130           fChannelMap.insert(ChannelMap_t::value_type
00131                              (chindex,new PulserTimeDrift(fPulserBox,chindex))
00132                              ).first;   
00133       }
00134       it->second->Add(summary->GetEntries(),
00135                       summary->GetMean(),
00136                       summary->GetRms() );
00137 
00138       // Update summary stats:
00139       if(it->second->GetEntries() > fMaxEntries) 
00140         fMaxEntries = it->second->GetEntries();
00141       if(it->second->GetEntries() < fMinEntries) 
00142         fMinEntries = it->second->GetEntries();
00143     }
00144   }
00145   // We added it successfully.
00146   return true;
00147 }
00148 
00149 Bool_t PulserTimingPoint::PointTimedOut(const VldTimeStamp& currentTime,
00150                                         double timeout)
00151 {
00156 
00157   // See if we've timed out.
00158   int currentSec = currentTime.GetSec();
00159   int currentNsec= currentTime.GetNanoSec();
00160   int endSec = fEndContext.GetTimeStamp().GetSec();
00161   int endNsec= fEndContext.GetTimeStamp().GetNanoSec();
00162   
00163   double dt = (double)(currentSec-endSec) + 1e-9*(double)(currentNsec-endNsec);
00164   if(dt>timeout)  return true; 
00165   return false;
00166 }
00167 
00168 
00169 Bool_t PulserTimingPoint::PointIsFinished()
00170 {
00176 
00177   // If we've collected all the stats we're supposed to...
00178   if(fMinEntries >= fPulses) return true;
00179 
00180   // Otherwise, point has has to time out
00181   // or the system has to go onto a new point, or the job has to end.
00182   return false; 
00183 }
00184 
00185 
00186 Bool_t PulserTimingPoint::PointIsGood()
00187 {
00194 
00195   // Only use drift point:
00196   if(fCalibType!=1) return false;
00197 
00198   int badChips = 0;
00199   int goodChips = 0;
00200 
00201   // Enough stats: 
00202   // Look at each channel.
00203   ChannelMap_t::iterator it;
00204   for(it = fChannelMap.begin(); it!=fChannelMap.end(); it++) {
00205     //if(ChannelBelongsToPoint(it->first))  // they all do
00206     if(it->second->GetEntries() < (float)(fPulses)*0.9) {
00207       MSG("PulserTiming",Msg::kInfo) << "Channel " 
00208                                         << it->second->GetRawChannelId().AsString() 
00209                                         << " has only " << it->second->GetEntries()
00210                                         << " and point expected " << fPulses << " entries."
00211                                         << std::endl;
00212       badChips++;
00213     } else 
00214       goodChips++;    
00215   }  
00216 
00217   bool retval = true;
00218   
00219   if(badChips>0)
00220     MSG("PulserTiming",Msg::kWarning) << "--->" << badChips 
00221                                       << "Bad chips, "
00222                                       << goodChips << " good chips on " << AsString() << endl;
00223   
00224   // Fail if there are no good chips, or more than 4 bad chips.
00225   if((goodChips<1)||(badChips>10)) {
00226     MSG("PulserTiming",Msg::kWarning) << "--->Point is judged bad. Storing anyway. " << AsString() << endl;
00227   //MSG("PulserTiming",Msg::kWarning) << "--->Point is judged bad and won't be stored " << AsString() << endl;
00228   // retval = false;
00229   }
00230 
00231   
00232   return retval;
00233 }
00234 
00235 Bool_t PulserTimingPoint::WriteToTextfile(const char* name)
00236 {
00237   const char* filename = Form("%s_%d_%d",
00238                               name,
00239                               fPulserBox,
00240                               fLed);
00241   ofstream outfile(filename);
00242   outfile << "CalibType:  \t" << fCalibType << endl;
00243   outfile << "CalibPoint: \t" << fCalibPoint << endl;
00244   outfile << "PulserBox:  \t" << fPulserBox << endl;
00245   outfile << "Led:        \t" << fLed << endl;
00246   outfile << "PulseHeight:\t" << fPulseHeight << endl;
00247   outfile << "PulseWidth: \t" << fPulseWidth << endl;
00248   outfile << "Pulses:     \t" << fPulses << endl;
00249   outfile << "Period:     \t" << fPeriod << endl;
00250   outfile << "TotalCounts:\t" << fTotalCount << endl;
00251   outfile << "Start:      \t" << fStartContext.AsString() << endl;  
00252   outfile << "End:        \t" << fEndContext.AsString() << endl;
00253   outfile << endl << endl << endl << endl;
00254 
00255   outfile << "Entries:    \t" << fChannelMap.size() << endl;
00256 
00257   for(ChannelMap_t::iterator it=fChannelMap.begin();
00258       it!=fChannelMap.end();
00259       it++) {
00260     outfile << Form("%10d ",it->first)
00261             << Form("%8d " ,(int)(it->second->GetEntries()))
00262             << Form("%6.2f ",it->second->GetMean())
00263             << Form("%6.2f ",it->second->GetRms())
00264             << it->second->GetRawChannelId().AsString()
00265             << endl;
00266   }
00267 
00268   outfile.close();
00269   return true;
00270 }
00271 
00272 Bool_t PulserTimingPoint::WriteToDatabase()
00273 {
00274   VldTimeStamp endtime = fStartContext.GetTimeStamp();
00275   VldTimeStamp offset(60*60*24*30*2,0); // Two months from now.
00276   endtime.Add(offset);
00277 
00278   VldRange range(fStartContext.GetDetector(),
00279                  fStartContext.GetSimFlag(),
00280                  fStartContext.GetTimeStamp(),
00281                  endtime,
00282                  "Automatic generation of time drift. $Id ");
00283 
00284   Int_t aggNo = fPulserBox;
00285   Int_t task  = fLed;
00286   std::string comment("Automatic generation of time drift. $Id ");
00287 
00288   MSG("PulserTiming",Msg::kInfo) << "Writing pulser table.  Aggregate(Crate) = " << aggNo 
00289                                  << " Task(Led) = " << task << endl;
00290   MSG("PulserTiming",Msg::kDebug) << "  VldRange = " << range.AsString() << endl;
00291   MSG("PulserTiming",Msg::kDebug) << "  Comment = " << comment << endl;
00292 
00293   DbiWriter<PulserTimeDrift> writer(range,      // vld range
00294                                     aggNo,
00295                                     task,
00296                                     fStartContext.GetTimeStamp(), // creation date, of the data generated.
00297                                     0,          // db no
00298                                     "" // comment
00299                                     );
00300 
00301   for(ChannelMap_t::iterator it=fChannelMap.begin();
00302       it!=fChannelMap.end();
00303       it++) {
00304     if(it->second) writer <<  *(it->second);
00305   }
00306 
00307   writer.Close();
00308 
00309   return true;
00310 }
00311 
00312 
00313 Bool_t PulserTimingPoint::ChannelBelongsToPoint(UInt_t chindex)
00314 {
00315   if(fValidChannels.find(chindex)==fValidChannels.end()) return false;
00316   return true;
00317 }
00318 
00319 
00320 const char* PulserTimingPoint::AsString()
00321 {
00322   return Form("Point: PulserBox %2d  LED %2d  %s",
00323               fPulserBox,
00324               fLed,
00325               fEndContext.AsString()
00326               );
00327 }

Generated on Sat Nov 7 01:27:15 2009 for loon by  doxygen 1.3.9.1