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

OltNewModule.cxx

Go to the documentation of this file.
00001 
00002 // $Id: OltNewModule.cxx,v 1.58 2006/12/03 02:15:30 gmieg Exp $
00003 //
00004 // OltNewModule.cxx
00005 //
00006 // Makes List of averages of pulser summaries
00007 //
00008 // Author: Phil Adamson 5/2002
00009 //
00010 // $Log: OltNewModule.cxx,v $
00011 // Revision 1.58  2006/12/03 02:15:30  gmieg
00012 // Add ' #include <cassert>'
00013 //
00014 // Revision 1.57  2006/05/22 19:33:13  rhatcher
00015 // Initialize some local variables that gcc is worried might be used
00016 // before they are set.
00017 //
00018 // Revision 1.56  2006/02/01 19:22:40  rhatcher
00019 // Convert from DetectorType:: to Detector::.  Also remove some unnecessary
00020 // #include lines (especially Conventions/DetectorType.h).
00021 //
00022 // Revision 1.55  2004/11/30 07:36:50  rhatcher
00023 // react to modified RawChannelId ctor
00024 //
00025 // Revision 1.54  2004/04/02 17:58:59  rhatcher
00026 // replace poor choice of variable name "TICK" with more descriptive VATICK.
00027 // (TICK is defined on some systems as a macro substitution for the number
00028 // of nanoseconds per tick; use of all caps for a non-cpp macro is still
00029 // questionable).
00030 //
00031 // Revision 1.53  2003/10/22 20:26:10  rhatcher
00032 // fill in the checksum value (via OnlineUtil's rdxsum_fill()) for the
00033 // created RawSnarlHeaderBlock, RawDigitDataBlock and RawDeadChipBlocks.
00034 // This avoids RotoObjectifier sending messages to syslog about bad
00035 // checksums.  Which then get seen by the farm managers when processing
00036 // CalDet data.  Why syslog you ask?  Because syslog is the only 'sensible'
00037 // place for output of the online rotorooter; and there's no good way
00038 // of telling OfflineTrigger's use of RotoObjectifier that it's not
00039 // running in a online situation.  Not without setting up some global
00040 // flag (and setting it in OfflineTrigger) and duplicating all the
00041 // error messages to use either syslog or MessageService.
00042 //
00043 // Revision 1.52  2003/10/05 10:28:56  phil.adamson
00044 // Fix TOF mismatch logic
00045 // CVS doesn't like pcminos01 any more...
00046 //
00047 // Revision 1.51  2003/10/03 14:59:00  phil.adamson
00048 // Add trigger bit (0x80) for SGATE
00049 //
00050 // Revision 1.50  2003/10/03 13:40:49  phil.adamson
00051 // BE a little less verbose...
00052 //
00053 // Revision 1.49  2003/10/03 13:32:58  phil.adamson
00054 // Ignore subrun end blocks - don't get confused about what file to write to.
00055 //
00056 // Revision 1.48  2003/09/19 13:49:43  phil.adamson
00057 // UberDST spawning hack for Mike and Tricia
00058 //
00059 // Revision 1.47  2003/09/09 12:44:13  phil.adamson
00060 // Cosmetic only chage to TOF printout
00061 //
00062 // Revision 1.46  2003/09/07 17:55:34  phil.adamson
00063 // Cosmetic improvements
00064 //
00065 // Revision 1.45  2003/09/04 13:10:55  phil.adamson
00066 // Minor bug-fixes - maybe crash less...
00067 //
00068 // Revision 1.44  2003/08/28 10:33:34  phil.adamson
00069 // Fast trigger, with ND dead chips...
00070 //
00071 // Revision 1.43  2003/08/27 12:52:06  phil.adamson
00072 // First commit of some CalDet debug tools
00073 //
00074 // Speed up trigger, plus add number of plane cut for event writing
00075 //
00076 // Revision 1.42  2003/08/13 15:34:05  phil.adamson
00077 // Ting bugette fixed, plus a hack to drop QIE hits with erroneously
00078 // large timestamps
00079 //
00080 // Revision 1.41  2003/08/13 11:08:07  phil.adamson
00081 // Do plane triggering on ND hits as well as FD hits.
00082 // fAllData now respects fExcludeMask, so to get all data, set AllData to true
00083 // and set ExcludeMask to 0.
00084 // Fix compile warnings in OltNewModule.cxx
00085 //
00086 // Revision 1.40  2003/04/15 17:59:28  phil.adamson
00087 // Don't try to trigger pedestal runs
00088 //
00089 // Revision 1.39  2003/04/09 19:17:12  rhatcher
00090 // * remove incorrect declaration of various static functions as "inline"
00091 // * #ifdef away declaration of various unimplemented static functions
00092 //   in OltTimeScan, OltEnds, and OltBlockScan.
00093 // * for static functions of ToChip(), ToVmm() and ToChad() in OltNewModule
00094 //   there is no point in returning "const int" (unlike cases like "const X*")
00095 //   as that int can be assigned to a "int" directly without extra effort
00096 //   (so the const hasn't protected you from modifying the result unless you
00097 //   declare the holder of the result as "const int".)
00098 //
00099 // Revision 1.38  2003/03/21 18:01:03  buckley
00100 // Replace ostrstream header with sstream to fix run time error using gcc3.2. Initialize pointers for RawTofConverter to prevent core dump
00101 //
00102 // Revision 1.37  2003/01/20 10:13:58  west
00103 // Adapt to the code movement: RawData -> OnlineUtil.
00104 //
00105 // Revision 1.36  2002/11/22 22:24:57  bv
00106 // Update to Registry::PrintStream() method
00107 //
00108 // Revision 1.35  2002/11/20 11:17:50  phil.adamson
00109 // Fix brown paper bag error in priming of chad-plane lookup table.
00110 // A VFB has 3 chips on it!
00111 //
00112 // Revision 1.34  2002/10/29 17:10:34  bv
00113 //
00114 // Turn down the firehose of memory leaks to hopefully a mere trickle.
00115 // When you do a
00116 //
00117 //     TYPE* array = new TYPE[LENGTH];
00118 //
00119 // you _must_ delete it like:
00120 //
00121 //     delete [] array;
00122 //
00123 // If you do "delete array" you only delete the first element.
00124 //
00125 // Revision 1.33  2002/10/17 05:57:22  rhatcher
00126 // various treatments to eliminate most (but not all) of the complaints
00127 // about comparing signed and unsigned values; this reduces the noise
00128 // that was hiding potentially more serious problems.
00129 //
00130 // Revision 1.32  2002/10/01 16:53:28  phil.adamson
00131 // Don't associate ToFs in a mismatched timeframe. Better Summaries. No Pizza.
00132 //
00133 // Revision 1.31  2002/09/27 17:44:57  phil.adamson
00134 // Fix exlclusion mask.
00135 //
00136 // Revision 1.30  2002/09/27 14:11:57  phil.adamson
00137 // Now write config bits in a RawRunConfigBlock, have the counter write summary
00138 // html bits as we go, and stuff
00139 //
00140 // Revision 1.29  2002/09/26 13:39:48  phil.adamson
00141 // Also put the CVS id in the comment block
00142 //
00143 // Revision 1.28  2002/09/26 13:17:52  phil.adamson
00144 // Write out config in a comment block, I hope
00145 //
00146 // Revision 1.27  2002/09/24 09:33:46  phil.adamson
00147 // Add a triger mask to the bits you can set via the Registry. olt_tof.C
00148 // does a tof-only trigger. Remember to whinge at Mark about the fact
00149 // that you can't do Set("Number = 0xff") in a .C macro.
00150 //
00151 // Revision 1.26  2002/09/19 15:03:52  phil.adamson
00152 // Allow the Counter to be turned off...
00153 //
00154 // Revision 1.25  2002/09/12 17:16:59  phil.adamson
00155 // Better error logging
00156 //
00157 // Revision 1.24  2002/09/12 17:09:59  phil.adamson
00158 // Tweak hist push-back threshold
00159 //
00160 // Revision 1.23  2002/09/11 13:00:53  phil.adamson
00161 // More stringent cut on push-back VA hits
00162 //
00163 // Revision 1.22  2002/09/11 09:18:00  phil.adamson
00164 // Sheepish admission of guilt: fix the vanishing ND hits bug
00165 //
00166 // Revision 1.21  2002/09/11 08:04:58  phil.adamson
00167 // Add TimeScan, cosmetic fixups
00168 //
00169 // Revision 1.16  2002/09/10 09:50:39  phil.adamson
00170 // Again
00171 //
00172 // Revision 1.15  2002/09/10 09:46:18  phil.adamson
00173 // Teapot
00174 //
00175 // Revision 1.14  2002/09/10 07:39:45  phil.adamson
00176 // Bug hunting...
00177 //
00178 // Revision 1.13  2002/09/09 15:00:43  phil.adamson
00179 // Fix the TOF counting business....
00180 //
00181 // Revision 1.12  2002/09/08 15:52:03  phil.adamson
00182 // *** empty log message ***
00183 //
00184 // Revision 1.11  2002/09/07 10:57:01  phil.adamson
00185 // Be less verbose
00186 //
00187 // Revision 1.10  2002/09/06 17:17:47  phil.adamson
00188 // Pass Tree in the counter...
00189 //
00190 // Revision 1.9  2002/09/06 14:30:50  phil.adamson
00191 // "Null Trigger" mode
00192 //
00193 // Revision 1.8  2002/09/06 13:22:21  phil.adamson
00194 // More configurables
00195 //
00196 // Revision 1.7  2002/09/05 09:33:45  phil.adamson
00197 // Add the Registry config for OltCounter, a few small wrinkles
00198 //
00199 // Revision 1.6  2002/09/04 10:28:01  phil.adamson
00200 // Now we use the Registry config method... phil
00201 //
00202 // Revision 1.5  2002/08/30 08:31:22  phil.adamson
00203 // Whoops!
00204 //
00205 // Revision 1.4  2002/08/30 08:29:07  phil.adamson
00206 // Now should work for the mixed CalDet mode with far and near electronics
00207 // We don't actually consider ND hits for the trigger, though, as there's only
00208 // a few PMTs
00209 //
00210 //
00212 
00213 #include "JobControl/JobCModuleRegistry.h"
00214 #include "MinosObjectMap/MomNavigator.h"
00215 #include "OfflineTrigger/OltNewModule.h"
00216 #include "MessageService/MsgService.h"
00217 #include "RawData/RawRecord.h"
00218 #include "RawData/RawHeader.h"
00219 #include "RawData/RawDataBlock.h"
00220 #include "RawData/RawDaqHeaderBlock.h"
00221 #include "RawData/RawSnarlHeaderBlock.h"
00222 #include "RawData/RawChannelId.h"
00223 #include "RawData/RawRunConfigBlock.h"
00224 #include "RawData/RawDaqHeader.h"
00225 
00226 #include "Persistency/PerOutputStreamManager.h"
00227 #include "Persistency/PerOutputStream.h"
00228 #include "Rotorooter/RotoObjectifier.h"
00229 #include "Plex/PlexHandle.h"
00230 #include "Plex/PlexSEIdAltL.h"
00231 
00232 #include "TString.h"
00233 #include "TSystem.h"
00234 #include <string>
00235 
00236 #include <algorithm>
00237 #include <cassert>
00238 #include <cstdio>
00239 #include <cstring>
00240 #include <iostream>
00241 #include <fstream>
00242 #include <sstream>
00243 #include <unistd.h>
00244 #ifndef __CINT__
00245 #include "OnlineUtil/mdBlockDefinitions.h"
00246 #endif
00247 #include "OnlineUtil/rdChecksum.h"
00248 ClassImp(OltNewModule)
00249 
00250   // ......
00251 
00252 CVSID("$Id: OltNewModule.cxx,v 1.58 2006/12/03 02:15:30 gmieg Exp $");
00253 JOBMODULE(OltNewModule,"OltNewModule","The Offline Trigger");
00254 
00255 const double OltNewModule::VATICK(1.5625);
00256 
00257 void OltNewModule::Config(const Registry& r)
00258 {
00259   const char *s;
00260   double d;
00261   int b;
00262   int i;
00263   if (r.Get("OutDir",s)) fOutDir = std::string(s);
00264   if (r.Get("CounterDir",s)) fCounterDir = std::string(s);
00265   if (r.Get("LinkDir",s)) fSymlinkDir = std::string(s);
00266   if (r.Get("SummaryDir",s)) fSummaryDir = std::string(s);
00267   if (r.Get("QieOffset",d)) fQieOffset = int(d);
00268   if (r.Get("SpyMode",b)) fSpyMode = bool(b);
00269   if (r.Get("ChadTOF",i)) chad_TOF = i;
00270   if (r.Get("ChadCER1",i)) chad_CER1 = i;
00271   if (r.Get("ChadCER2",i)) chad_CER2 = i;
00272   if (r.Get("ChadCER3",i)) chad_CER3 = i;
00273   if (r.Get("ChadTRIGPMT",i)) chad_TRIGPMT = i;
00274   if (r.Get("ChadNDTIMING",i)) chad_ND_TIMING = i;
00275   if (r.Get("AllData",b)) fAllData = bool(b);
00276   if (r.Get("UseCounter",b)) fUseCounter = bool(b);
00277   if (r.Get("TrigMask",i)) fTrigMask = i;
00278   if (r.Get("ExcludeMask",i)) fExcludeMask = i;
00279   if (r.Get("NumPlanes",i)) fNumPlanes = i;
00280   if (r.Get("NDFiducialADCCut",i)) fNDFiducialADCCut = i;
00281   if (r.Get("NewRun",b)) fNewRun = bool(b);
00282   if (r.Get("NewRunScript",s)) fNewRunScript = std::string(s);
00283 }
00284 
00285 const Registry& OltNewModule::DefaultConfig() const
00286 {
00287   static Registry r;
00288   std::string name = this->JobCModule::GetName();
00289   name +=".config.default";
00290   r.SetName(name.c_str());
00291 
00292   // Set defaults
00293   r.UnLockValues();
00294   r.Set("OutDir","/data/dataout");
00295   r.Set("CounterDir","/data/histos");
00296   r.Set("LinkDir","/data");
00297   r.Set("SummaryDir","/data");
00298   r.Set("QieOffset",float(208/VATICK)); 
00299   r.Set("SpyMode",false);
00300   r.Set("ChadTOF",CHAD_TOF);
00301   r.Set("ChadCER1",CHAD_CER1);
00302   r.Set("ChadCER2",CHAD_CER2);
00303   r.Set("ChadCER3",CHAD_CER3);
00304   r.Set("ChadTRIGPMT",CHAD_TRIGPMT);
00305   r.Set("ChadNDTIMING",CHAD_ND_TIMING);
00306   r.Set("AllData",false);
00307   r.Set("UseCounter",true);
00308   r.Set("TrigMask",0xff);
00309   r.Set("ExcludeMask",0);
00310   r.Set("NumPlanes",4);
00311   r.Set("NDFiducialADCCut",1000);
00312   r.Set("NewRun",false);
00313   r.Set("NewRunScript","/bin/echo");
00314  r.LockValues();
00315 
00316   return r;
00317 }
00318 
00319 
00320 OltNewModule::OltNewModule()
00321 {
00322   fOutputStreamManager = new PerOutputStreamManager();
00323   fSpyStreamManager = new PerOutputStreamManager();
00324 
00325   const char * dir = gSystem->Getenv("OLT_OUTPUT_DIR");
00326   if (dir) fOutDir = string(dir);
00327   dir = gSystem->Getenv("OLT_LINK_DIR");
00328   if (dir) fSymlinkDir = string(dir);
00329   fAccessMode = Per::kNew;
00330   fFileOpen = false;
00331   fSpyOpen = false;
00332   fDetector = Detector::kUnknown;
00333   fRun = 0;
00334   fSubrun = 0;
00335   fCounter = 0;
00336   fCurrentTF = 0;
00337   fLastTF = 1;
00338   fTimeframe[0] = -10;
00339   fTimeframe[1] = -10;
00340   fToFConverter[0] = 0;
00341   fToFConverter[1] = 0;
00342   fNumToFHits[0] = 0;
00343   fNumToFHits[1] = 0;
00344   fGap = 100;
00345   fFirst = true;
00346   
00347   fDeadChipBuffer = 0;
00348   fDeadChipLastBuffer = 1;
00349    for (int i=0;i<NCRATES;i++) {
00350       fExtraHits[i].reserve(4000);
00351       fSortedHits[i].reserve(400000);
00352     for (int tf=0;tf<2;tf++) {
00353       fQieFreeTime[tf].push_back(map<int,int>());
00354       fChipFreeTime[tf].push_back(map<int,int>());
00355       fVmmFreeTime[tf].push_back(map<int,int>());
00356       fHits[tf][i].reserve(400000);
00357       fCrateId[tf][i] = 0;
00358       fCrateSec[tf][i]=0;
00359       fCrateNsec[tf][i]=0;
00360       
00361       // And Set times in DeadChip maps to prehistory...
00362       for (int varc=0;varc<3;varc++) {
00363         for (int vmm=0;vmm<6;vmm++) {
00364           for (int adc=0;adc<2;adc++) {
00365             for (int chip=0;chip<3;chip++) {
00366               fChipFreeTime[tf][i][ToChad(varc,vmm,adc,chip,0)] = -1000000;   
00367             }
00368           }
00369           fVmmFreeTime[tf][i][ToChad(varc,vmm,0,0,0)] = -1000000;   
00370         }
00371       }
00372       for (int master = 0 ; master < 32 ; master++ ) {
00373         for (int minder = 0 ; minder < 8 ; minder+=4 ) {
00374           int menu=0;
00375           RawChannelId rcid(Detector::kCalDet, 
00376                             ElecType::kQIE,
00377                             i,master,minder,menu);
00378           int chadmask = rcid.GetEncoded()&0x1fff;
00379           fQieFreeTime[tf][i][chadmask] = -1000000;
00380         }
00381       }
00382     }
00383    }
00384    fBuffer = new unsigned long[200000]; //10k words should be enough
00385    fDeadBuf = new unsigned long[5000]; //1k words should be enough
00386    fToFOutputArray = new unsigned long[200]; // Will be short!
00387    fEventNo = 0;
00388    fTofIndex = 0;
00389    fRecord = 0;
00390    
00391    fHaveNDTimingHit = false;
00392 }
00393 
00394 OltNewModule::~OltNewModule()
00395 {
00396   if (fFileOpen) CloseFile(fDetector,fRun,fSubrun);
00397   if (fSpyOpen) CloseSpy(fDetector,fRun,fSubrun);
00398   if (fCounter) fCounter->WriteSummary();
00399   if (fCounter) {
00400     MSG("Olt",Msg::kInfo)<<"Deleting counter"<<endl;
00401     delete fCounter;
00402     MSG("Olt",Msg::kInfo)<<"Done"<<endl;
00403   }
00404     MSG("Olt",Msg::kInfo)<<"Deleting buffer"<<endl;
00405   delete [] fBuffer;
00406   delete [] fDeadBuf;
00407   delete [] fToFOutputArray;
00408     MSG("Olt",Msg::kInfo)<<"Done"<<endl;
00409 }
00410 
00411 JobCResult OltNewModule::Reco(MomNavigator* mom)
00412 {
00413   // Find RawRecord fragment in MOM.
00414   TIter iter = mom->FragmentIter();
00415   while (TObject *obj = iter.Next()) {
00416     RawRecord *rawrec = dynamic_cast<RawRecord *>(obj);
00417     if (rawrec) {
00418       ++fRecord;
00419       MSG("Olt",Msg::kDebug)<<"Record "<<fRecord<<endl;
00420       if (rawrec->FindRawBlock("RawSubRunEndBlock")) continue;
00421       // if (fRecord>5160) {
00422         {
00423       // Find a HeaderBlock and get Run number etc.
00424       int run=0,subrun=0,runtype=0;
00425       Detector::Detector_t detector = Detector::kUnknown;
00426       const RawDaqHeaderBlock *rdhb = dynamic_cast<const RawDaqHeaderBlock *>
00427         (rawrec->FindRawBlock("RawDaqHeaderBlock"));
00428       if (rdhb) {
00429         run = rdhb->GetRun();
00430         subrun = rdhb->GetSubRun();
00431         detector = rdhb->GetVldContext().GetDetector();
00432         runtype = rdhb->GetRunType();
00433         //MSG("Olt",Msg::kInfo)<<rdhb->GetVldContext()<<endl;
00434       }
00435       const RawSnarlHeaderBlock *rshb = dynamic_cast<const RawSnarlHeaderBlock *>(rawrec->FindRawBlock("RawSnarlHeaderBlock"));
00436       if (rshb) {
00437         run = rshb->GetRun();
00438         subrun = rshb->GetSubRun();
00439         detector = rshb->GetVldContext().GetDetector();
00440         //MSG("Olt",Msg::kInfo)<<rshb->GetVldContext()<<endl;
00441         //If first raw record, fill map for plane lookup
00442         //We only trigger on VA electronics at the moment.
00443         if (fFirst) {
00444           VldContext vld = rshb->GetVldContext();
00445           PlexHandle plex(vld);
00446           for (int crate = 0; crate<2;crate++) {
00447             for (int varc=0;varc<3;varc++) {
00448               for (int vmm=0;vmm<7;vmm++) {
00449                 for (int vaadc = 0;vaadc<2;vaadc++) {
00450                   for (int chip=0;chip<3;chip++) {
00451                     for (int channel = 2; channel < 18 ; channel ++) {
00452                       RawChannelId rcid(Detector::kCalDet,
00453                                         ElecType::kVA,
00454                                         crate,varc,vmm,vaadc,chip,channel);
00455                       PlexSEIdAltL seid = plex.GetSEIdAltL(rcid);
00456                       int plane = seid.GetPlane();
00457                       fPlane[crate][channel + (chip<<5) + (vaadc<<7) +
00458                                    (vmm<<8) + (varc<<11)] = plane+1;
00459                     }
00460                   }
00461                 }
00462               }
00463             }
00464           }
00465           // This is a bit of a hack - do this better later
00466           for (int crate = 1 ; crate < 3 ; crate++) {
00467             for (int master = 0 ; master < 32 ; master++ ) {
00468               for (int minder = 0 ; minder < 8 ; minder++ ) {
00469                 for (int menu = 0 ; menu < 16 ; menu++ ) {
00470                   RawChannelId rcid(Detector::kCalDet, 
00471                                     ElecType::kQIE,
00472                                     crate,master,minder,menu);
00473                   PlexSEIdAltL seid = plex.GetSEIdAltL(rcid);
00474                   int plane = seid.GetPlane();
00475                   if (plane>-1&&plane<60) 
00476                     fQiePlane[crate][rcid.GetEncoded()&0x1fff] = plane+1;
00477                 }
00478               }
00479             }
00480           }
00481           fFirst = false;
00482         }
00483       }
00484       if (rdhb || rshb) {
00485         //MSG("Olt",Msg::kInfo)<<"Run "<<run<<" Subrun "<<subrun<<endl;
00486         if (fRun == run && fSubrun == subrun && fFileOpen) {
00487   // OK - we have the right file open
00488         }
00489         else {
00490           if (fFileOpen) {
00491             // Process last TF before closing file.
00492             for (int i=0;i<fCrates;i++) {
00493               fSortedHits[i].resize(fHits[fLastTF][i].size());
00494               copy(fHits[fLastTF][i].begin(),fHits[fLastTF][i].end(),
00495                    fSortedHits[i].begin());
00496               if (fCrateId[fLastTF][i] & 0x40) {
00497                 // QIE electronics if this bit is set
00498                 sort(fSortedHits[i].begin(),fSortedHits[i].end(),qiesorter());
00499               } else {
00500               sort(fSortedHits[i].begin(),fSortedHits[i].end(),hitsorter());
00501               }    
00502             }
00503             MSG("Olt",Msg::kInfo)<<"Last Timeframe "
00504                                  <<fTimeframe[fLastTF]<<endl;
00505             string rotoStrmName = Form("%c%8.8d_%4.4d",
00506                                        Detector::AsString(fDetector)[0],
00507                                        fRun,fSubrun);
00508             rotoStrmName += ".DaqSnarl";
00509             if (fTimeframe[fLastTF] >0) FormEvents(fLastTF,rotoStrmName);
00510             CloseFile(fDetector,fRun,fSubrun);
00511             for (int i=0;i<fCrates;i++) {
00512               fHits[fLastTF][i].clear();
00513               fSortedHits[i].clear();
00514               fExtraHits[i].clear();
00515             }
00516              fTimeframe[fLastTF]=-10;
00517              fNumToFHits[fLastTF] =0;
00518           }
00519           if (fSpyOpen) CloseSpy(fDetector,fRun,fSubrun);
00520           if (fRun !=run) {
00521             fEventNo=0;
00522           }
00523           if (fCounter) fCounter->WriteSummary();
00524           // Hack for Mike and Tricia here!
00525           if (fNewRun && (run!=fRun)) {
00526             // New run, so run script in background.
00527             char c[100];
00528             sprintf(c,"%d",fRun);
00529             string s = fNewRunScript +" "+string(c)+ " &";
00530             system(s.c_str());
00531           }
00532         
00533           fRun = run;
00534           fSubrun = subrun;
00535           fDetector = detector;
00536           fRunType = runtype;
00537           fFileOpen = OpenFile(fDetector,fRun,fSubrun);
00538           if (fSpyMode) fSpyOpen = OpenSpy(fDetector,fRun,fSubrun);
00539           if (fCounter) delete fCounter;
00540           if (fUseCounter) fCounter = new OltCounter(fRun,fSubrun,fCounterDir.c_str(),fSummaryDir);
00541         }
00542         }
00543       if (fRunType==1) return JobCResult::kFailed;
00544 
00545       const char  *streamname =0;
00546       if ( rawrec -> GetTempTags().Get("stream",streamname) )
00547               MSG("Olt",Msg::kVerbose) << "stream " << streamname << endl;
00548       TIter recit = rawrec->GetRawBlockIter();
00549       while (TObject *obj = recit.Next()) {
00550         RawDataBlock *rawdata = dynamic_cast<RawDataBlock *>(obj);
00551         if (rawdata) {
00552           MSG("Olt",Msg::kVerbose) <<rawdata->GetBlockId()<<endl;
00553         }
00554       }
00555       // Write records
00556       string rotoStrmName = 
00557         Form("%c%8.8d_%4.4d",Detector::AsString(detector)[0],run,subrun);
00558       string sname = streamname;
00559       if (sname == "DaqSnarl") {
00560         // Do triggering here
00561         ProcessTimeframe(rawrec,rotoStrmName + "." + streamname);
00562       }
00563       else {
00564         if (sname == "DaqMonitor") {
00565           // Here's a monitor block - construct one of Mike's 
00566           // decoder objects. Have two pointers for these, like [tf].
00567           fToFConverter[fCurrentTF] = new RawTofConverter(rawrec);
00568           //  fCounter->NumTDC(fTimeframe[fCurrentTF],
00569           //               fToFConverter[fCurrentTF]->GetNumberOfRawTOFBlocks());
00570           MSG("Olt",Msg::kDebug)<<"Got TOF TDC data for "<<fCurrentTF<<"  "<<fTimeframe[fCurrentTF]<<endl;
00571         }
00572         rotoStrmName = rotoStrmName + "." + streamname;
00573         if (!fOutputStreamManager) {
00574           MSG("Olt",Msg::kError) << "No output stream manager"<<endl;
00575           return JobCResult::kFailed;
00576         }
00577         PerOutputStream* stream = 0;
00578         stream = dynamic_cast<PerOutputStream*>
00579           (fOutputStreamManager->GetOpenedStream(rotoStrmName));
00580         if (!stream) {
00581           MSG("Olt",Msg::kError) << "Can't find stream "<<rotoStrmName<<endl;
00582           return JobCResult::kFailed;
00583         }
00584         stream->SetObject(rawrec);
00585         stream->Store();
00586       }
00587     }
00588   }
00589   }
00590   return JobCResult::kAOK;
00591 }
00592 
00593 bool OltNewModule::OpenFile(Detector::Detector_t det, Int_t run, Int_t subrun)
00594 {
00595   // Open file for output. Name file *.tdaq.root for triggered data
00596   // Stolen from the Rotorooter...
00597   string fname = 
00598     Form("%c%8.8d_%4.4d",Detector::AsString(det)[0],run,subrun);
00599   
00600   string filename = fOutDir + "/" + fname + ".tdaq.root";
00601   bool ok = true;
00602   int fversion = 0;
00603   // 3 streams in daq file
00604   for (int i = Per::kDaqSnarl;i<=Per::kLightInjection;i++) {
00605     Per::EStreamType stype = (Per::EStreamType) i;
00606     string treeName = Per::AsString(stype);
00607     string rotoStrmName = fname + "." + treeName;
00608     int compressionLevel = 1; // ROOT Default
00609     PerOutputStream* astream =
00610       fOutputStreamManager->OpenStream(rotoStrmName,treeName,
00611                                        "RawRecord","","",Per::kRecSplit,
00612                                        64000,compressionLevel);
00613     if (astream) {
00614       astream->SetAutoSave(0,0); // Turn off autosave
00615       bool openok = 
00616         fOutputStreamManager->SetFile(rotoStrmName,filename,fAccessMode);
00617       MSG("Olt",Msg::kInfo) << "Opened stream "<<rotoStrmName
00618                             << " on file "<<filename<<endl;
00619       // handle potential case where file already exists
00620       // and the rotorooter is in kNew not kRecreate mode
00621       Per::EErrorCode ecode = astream->GetErrorCode();
00622       if (Per::kErrFileExists == ecode) {
00623         string basefilename = filename;
00624         string::size_type where = filename.rfind(".t");
00625         if (string::npos == where) where = filename.rfind(".root");
00626         if (string::npos == where) where = filename.length();
00627         bool keep_trying = true;
00628         // start adding version numbers
00629         do {
00630           ++fversion;
00631           filename = basefilename;  // without any attempt at versioning
00632           filename.insert(where,Form(".%d",fversion));
00633           openok = 
00634             fOutputStreamManager->SetFile(rotoStrmName,filename,fAccessMode);
00635           if (Per::kErrSuccess != ecode) {
00636           MSG("Olt",Msg::kInfo) << "Open versioned file saw Per error: "
00637                                 <<Per::AsString(ecode)<<endl;
00638           }
00639           
00640           ecode = astream->GetErrorCode();
00641           keep_trying = (fversion<100) &&
00642             (Per::kErrFileExists == ecode);
00643         } while (keep_trying);
00644         // report if there was success
00645         if (Per::kErrSuccess == ecode) 
00646           MSG("Olt",Msg::kInfo) << "Open stream on file: "
00647                                 <<filename<<endl;
00648         
00649       } // file exists error
00650       
00651       if (Per::kErrSuccess != ecode) {
00652         MSG("Olt",Msg::kInfo) << "Open stream saw Per error: "
00653                               <<Per::AsString(ecode)<<endl;
00654       }
00655      ok = ok & openok;     
00656     } 
00657     else {
00658       ok = false;
00659     }
00660 
00661   } 
00662   fCurrentFilename = filename;
00663   string rotoStrmName = 
00664     Form("%c%8.8d_%4.4d",Detector::AsString(fDetector)[0],fRun,fSubrun);
00665   WriteConfig(rotoStrmName + "." + "DaqMonitor");
00666   return ok;
00667 }
00668 
00669   
00670 bool OltNewModule::CloseFile(Detector::Detector_t det, Int_t run, Int_t subrun)
00671 {
00672   // Close output file. Name file *.tdaq.root for triggered data
00673   // Stolen from the Rotorooter...
00674   string fname = 
00675     Form("%c%8.8d_%4.4d",Detector::AsString(det)[0],run,subrun);
00676   
00677    // 3 streams in daq file
00678   for (int i = Per::kDaqSnarl;i<=Per::kLightInjection;i++) {
00679     Per::EStreamType stype = (Per::EStreamType) i;
00680     string treeName = Per::AsString(stype);
00681     string rotoStrmName = fname + "." + treeName;
00682     fOutputStreamManager->Write(rotoStrmName);
00683     fOutputStreamManager->CloseStream(rotoStrmName);
00684     MSG("Olt",Msg::kInfo)<<"Closing stream "<<rotoStrmName<<endl;
00685    }
00686 
00687   //  string filename = fOutDir + "/" + fname;
00688   string link = fOutDir + "/LastFileTriggered";
00689   string mylink = fSymlinkDir + "/" + fname + ".tdaq.root";
00690   unlink(mylink.c_str());
00691   symlink(fCurrentFilename.c_str(),mylink.c_str());
00692   unlink(link.c_str());
00693   symlink(fCurrentFilename.c_str(),link.c_str());
00694   return true;
00695 }
00696 
00697 void OltNewModule::ProcessTimeframe(RawRecord *rawrec, string rotoStrmName)
00698 {
00699   TIter iter = rawrec->GetRawBlockIter();
00700   while (RawDataBlock *rdb = dynamic_cast<RawDataBlock *>(iter.Next())) {
00701     if (rdb->InheritsFrom("RawSnarlHeaderBlock")) {
00702       RawSnarlHeaderBlock *rshb =dynamic_cast<RawSnarlHeaderBlock *>(rdb);
00703       fTimeframe[fCurrentTF] = rshb->GetTimeFrameNo();
00704       MSG("Olt",Msg::kVerbose) << "Processing Timeframe "<<fTimeframe[fCurrentTF]<<endl;
00705     }
00706     if (rdb->InheritsFrom("RawDigitDataBlock")) {
00707       int size = rdb->GetSize();
00708       const int *block = rdb->GetData();
00709       MSG("Olt",Msg::kVerbose)<<"Data block size: "<<size<<endl;
00710   
00711       int offset = 3;
00712       int thecrate = -1;
00713       while (offset< size-3) {
00714         // Pick up all the crates in the datablock
00715         ++thecrate;
00716         assert(thecrate<NCRATES);
00717         int crateid = block[offset++];
00718         int nentries = block[offset++];
00719         int t0sec = block[offset++];
00720         int t0nsec = block[offset++];
00721         int biggesttime=0; // biggest time for data that hasn;t strayed into
00722                            // the next tf
00723         fCrateId[fCurrentTF][thecrate] = crateid;
00724         fCrateSec[fCurrentTF][thecrate] = t0sec;
00725         fCrateNsec[fCurrentTF][thecrate] = t0nsec;
00726         if (fTimeframe[fCurrentTF]>0) {
00727           //assert(fCrateId[fCurrentTF][thecrate]==fCrateId[fLastTF][thecrate]);
00728         }
00729         if (crateid & 0x40) {
00730           // cout<<"Crate "<<thecrate<<" QIE\n";
00731           fElec[thecrate] = 2;
00732           // QIE
00733           for (int i=0;i<nentries;i++) {
00734             // We don't do anything with the QIE data here, just push it on
00735             // the vector...
00736             long long *qiedata = (long long *)(block + offset);
00737             // Hack to drop hits with times greater than 1s
00738             int thetime = ToVaTime((reinterpret_cast<QieHit *>(qiedata))->timeStamp);
00739             if (thetime > 650000000) {
00740               MSG("Olt",Msg::kWarning)<<"Dropping QIE hit with VA timestamp "
00741                                       << thetime<<endl;
00742             } else {
00743             fHits[fCurrentTF][thecrate].push_back(*qiedata);
00744             }
00745             offset +=2;
00746           }
00747         } else {
00748           //cout<<"Crate "<<thecrate<<" VA\n";
00749           fElec[thecrate] = 1;
00750           //VA
00751           for (int i=0;i<nentries;i++) {
00752             VaHit *hit = (VaHit *)(block + offset);
00753             if (thecrate==0 && hit->chad == (unsigned int)chad_ND_TIMING) {
00754               // Got the ND timing hit.
00755               MSG("Olt",Msg::kDebug)<<"Timeframe "<<fTimeframe[fCurrentTF]<<" timing hit: ";
00756               MSG("Olt",Msg::kDebug)<<"Timestamp "<<int(hit->timeStamp)<<" adc "<<int(hit->adcValue)<<endl;
00757               if (hit->adcValue>fNDFiducialADCCut) {
00758               fNDTimingHit[fCurrentTF] = *(reinterpret_cast<long long *>(hit));
00759               fHaveNDTimingHit = true;
00760               } else {
00761                 MSG("Olt",Msg::kWarning)<<"Ignoring ND fiducial at time "<<int(hit->timeStamp)<<" with adc "<<int(hit->adcValue)<<endl;
00762               }
00763               if (hit->timeStamp>(1000/VATICK)) MSG("Olt",Msg::kWarning)<<
00764                   "Late ND fiducial at time "<<int(hit->timeStamp)<<
00765                   " with adc "<<int(hit->adcValue)<<endl;
00766             }
00767             if (thecrate==0 && hit->chad == (unsigned int)chad_TOF) {
00768               ++fNumToFHits[fCurrentTF];
00769               // if we've produced a -ve number, push the ToF hit to the 
00770               // previous TF.
00771               // if (hit->timeStamp<TOF_TARDIS) hit->timeStamp+=ONE_SECOND;
00772               if (hit->timeStamp<TOF_TARDIS) hit->timeStamp=TOF_TARDIS;
00773               hit->timeStamp-=TOF_TARDIS;
00774             }
00775             int time = hit->timeStamp;
00776             
00777             // Might need to put the ToF tardis in here...
00778             if (time >635000000 && biggesttime < 5000000) {
00779                                                   
00780               if (thecrate==0 && hit->chad == (unsigned int)chad_TOF) --fNumToFHits[fCurrentTF];
00781                       // data really belongs to previous tf
00782               MSG("Olt",Msg::kDebug)<<"Pushing hit with time "<<time
00783                                       <<"to previous tf"<<endl;
00784               if (fTimeframe[fCurrentTF] == 1+fTimeframe[fLastTF]) {
00785                 //push the hit back
00786                 fExtraHits[thecrate].push_back(*(reinterpret_cast<long long *>(hit)));        
00787                 if (thecrate==0 && hit->chad == (unsigned int)chad_TOF) ++fNumToFHits[fLastTF];
00788               }
00789               else {
00790                 if (fTimeframe[fCurrentTF]>0) {
00791                   MSG("Olt",Msg::kWarning)<<"Not pushing hit to previous tf: "
00792                                           <<fTimeframe[fCurrentTF]
00793                                           <<" does not follow "
00794                                           <<fTimeframe[fLastTF]<<endl;
00795                 }
00796               }
00797             }
00798             else {
00799               biggesttime = time;
00800               fHits[fCurrentTF][thecrate].push_back(*(reinterpret_cast<long long *>(hit)));
00801             }
00802             
00803             offset +=2;
00804           }
00805         }
00806       }
00807       fCrates = thecrate + 1;
00808       fCrates = NCRATES;
00809     }
00810   }
00811   // Now Sort This tf, sort extras and insert into last tf.
00812 
00813   for (int i=0;i<fCrates;i++) {
00814     fSortedHits[i].resize(fHits[fLastTF][i].size() + fExtraHits[i].size());
00815     copy(fHits[fLastTF][i].begin(),fHits[fLastTF][i].end(),
00816          fSortedHits[i].begin());
00817     copy(fExtraHits[i].begin(),fExtraHits[i].end(),
00818          fSortedHits[i].begin()+fHits[fLastTF][i].size());
00819     if (fCrateId[fLastTF][i] & 0x40) {
00820       // QIE electronics if this bit is set
00821       sort(fSortedHits[i].begin(),fSortedHits[i].end(),qiesorter());
00822     } else {
00823       sort(fSortedHits[i].begin(),fSortedHits[i].end(),hitsorter());
00824     }
00825   }
00826 
00827   if ((fTimeframe[fLastTF]%60)==0) {
00828     MSG("Olt",Msg::kInfo)<<"Timeframe "
00829                          <<fTimeframe[fLastTF]<<endl;
00830   } else {
00831     MSG("Olt",Msg::kDebug)<<"Timeframe "
00832                           <<fTimeframe[fLastTF]<<endl;
00833     
00834   }
00835  // fLastTF is now guaranteed complete, so form events from it.
00836   // But ditch TF 0
00837     if (fTimeframe[fLastTF] >0) FormEvents(fLastTF,rotoStrmName);
00838   // OK - we've seen all the blocks in this record now, so swap the buffers.
00839 if ((fTofIndex>0) || (fNumToFHits[fLastTF]>0)) 
00840   MSG("Olt",Msg::kInfo) << "TOF: " << fTofIndex << " TDCs, "
00841                         << fNumToFHits[fLastTF] << " hits\n";
00842 
00843   swap(fCurrentTF,fLastTF);
00844   fNumToFHits[fCurrentTF] = 0;
00845   if (fUseCounter && (fTimeframe[fLastTF]%10)==0)fCounter->Write();
00846   if (fSpyMode && (fTimeframe[fLastTF]%120)==0)
00847     {
00848       CloseSpy(fDetector,fRun,fSubrun);
00849       fSpyOpen = OpenSpy(fDetector,fRun,fSubrun);
00850     }
00851   // Dead chip business needs resetting!
00852   for (int crate=0; crate<fCrates; crate++) {
00853     for (int buf=0;buf<2;buf++) {
00854       map<int,int>::iterator it;
00855       for (it = fVmmFreeTime[buf][crate].begin();
00856            it !=fVmmFreeTime[buf][crate].end(); it++) {
00857         (*it).second = min((*it).second-int(1.0e9/VATICK),-2*DEADTIME); // Subtract a second.
00858       }
00859       for (it = fChipFreeTime[buf][crate].begin();
00860            it !=fChipFreeTime[buf][crate].end(); it++) {
00861         (*it).second = min((*it).second-int(1.0e9/VATICK),-2*DEADTIME); // Subtract a second.
00862 
00863       }
00864       for (it = fQieFreeTime[buf][crate].begin();
00865            it!= fQieFreeTime[buf][crate].end(); it++) {
00866         (*it).second = -2*QIEDEADTIME;
00867       }
00868     }
00869   }
00870  
00871   MSG("Olt",Msg::kVerbose)<<"Timeframe "<<fLastTF<<":"
00872                           <<fTimeframe[fLastTF]<<"  "
00873                           <<fCurrentTF<<":"
00874                           <<fTimeframe[fCurrentTF]<<endl;
00875   // and clear the maps ready for the new timeframe
00876 
00877   for (int i=0;i<fCrates;i++) {
00878     fHits[fCurrentTF][i].clear();
00879     fSortedHits[i].clear();
00880     fExtraHits[i].clear();
00881   }
00882  if (fUseCounter && fToFConverter[fCurrentTF]) fCounter->NumTDC(fTimeframe[fCurrentTF],
00883                    fToFConverter[fCurrentTF]->GetNumberOfRawTOFBlocks());
00884   delete fToFConverter[fCurrentTF];
00885   fToFConverter[fCurrentTF]=0;
00886   if (fUseCounter) fCounter->NumTOF(fTimeframe[fCurrentTF],fTofIndex);
00887   fTofIndex = 0;
00888 }
00889 
00890 void OltNewModule::FormEvents(int tf,string rotoStrmName)
00891 {
00892   unsigned int start[NCRATES]={0};
00893   unsigned int end[NCRATES]={0};
00894   unsigned int hitit[NCRATES]={0};
00895   // indexes over the hitmap for a crate
00896  
00897   int teventstart;
00898   int teventend;
00899   //unused: int firstcrate;
00900 
00901   // Three iterators. start and end delimit events, hitit is the one 
00902   // that actually gets advanced over the hits.
00903   // Also meet hitplane the array. This gets a true if a plane is hit
00904   // so we can then use it in the trigger decision.
00905 
00906   bool hitplane[100]; // CalDet!!!
00907   memset(hitplane,0,sizeof(hitplane));
00908 
00909   // Let's tell the Counter how many hits each crate had:
00910   if (fUseCounter) {
00911     for (int crate=0; crate<fCrates;crate++) {
00912       fCounter->RawHits(fTimeframe[tf],crate,fSortedHits[crate].size());
00913     }
00914   }
00915 
00916   for (;;) {
00917     bool nomorehits = true;
00918     Trigbits trigbits;
00919     int n[NCRATES+1]={0};
00920     //unused: int lastchip=-1;
00921     //unused: Is not unused! Look down 8 lines, and 16 lines!
00922     int firstcrate;
00923     teventstart=1000000000L; // times are always less than this.
00924     
00925     for (int crate=0; crate<fCrates ; crate++) {
00926       bool nohitsleft=(hitit[crate] >= fSortedHits[crate].size());
00927       nomorehits &=nohitsleft;
00928       int thistime;
00929       if (fCrateId[tf][crate] & 0x40) {
00930         // QIE electronics if this bit is set 
00931         thistime = ToVaTime((reinterpret_cast<QieHit *>(&fSortedHits[crate][hitit[crate]]))->timeStamp);
00932       } else {
00933         thistime = (reinterpret_cast<VaHit *>(&fSortedHits[crate][hitit[crate]]))->timeStamp;
00934       }
00935       if (!nohitsleft && thistime < teventstart) {
00936         teventstart = thistime;
00937         firstcrate = crate;
00938       }
00939     }
00940     if (nomorehits) break;
00941     teventend = teventstart;
00942     MSG("Olt",Msg::kVerbose) << "Start at "<<teventstart<<" in crate "<<firstcrate<<" of "<<fCrates<<endl;
00943     // Suck up first crate's worth...
00944     n[firstcrate]+=SuckCrate(firstcrate,hitit[firstcrate],hitplane,
00945                              trigbits,teventend,tf);
00946     end[firstcrate] = hitit[firstcrate];
00947 
00948     // Now loop over all crates until no more added hits.
00949     for (;;) {
00950       int nAdded = 0;
00951       for (int crate=0;crate<fCrates ; crate++) {
00952         int num = SuckCrate(crate,hitit[crate],hitplane,
00953                             trigbits,teventend,tf);
00954         nAdded +=num;
00955         n[crate]+=num;
00956         end[crate] = hitit[crate];
00957       }
00958       if (nAdded == 0) break;
00959     }
00960 
00961     int sum[6][61]={{0},{0}}; // 1 = 2/3, 5 = 6/7
00962     int atplane[6]={0};
00963 
00964    for (int i=1;i<60;i++) {
00965       sum[0][i] = int(hitplane[i]) + int(hitplane[i+1]);
00966     }
00967     for (int j=1;j<6;j++) {
00968       for (int i=60;i>0;i--) {
00969         sum[j][i] = sum[j-1][i] + int(hitplane[i+j+1]);
00970         if (sum[j][i]>=j+1) atplane[j] = i;
00971       } 
00972     }
00973 
00974     int nplanes=0;
00975     int trigword = 0;
00976     
00977     for (int i=5;i>0;i--) {
00978       if (atplane[i]>0) {
00979         MSG("Olt",Msg::kDebug)<<"Trigger "<<i+1<<"/"<<i+2<<" at plane "
00980                                 <<atplane[i]<<endl;
00981         nplanes = i+1;
00982         trigword = ((i+1)<<TRIG_NUM_SHIFT) | TRIG_PLANE_MASK;
00983         break;
00984       }
00985     }
00986     int ndead = -1;
00987 
00988     if (fUseCounter) fCounter->Trigger(trigword,atplane[nplanes-1]);
00989     //if (trigword) fCounter->DeadChips(fChipFreeTime[fDeadChipLastBuffer]);
00990     if (trigbits.isli) trigword |=TRIG_LI_MASK;
00991     if (trigbits.cer1) trigword |=TRIG_CER1_MASK;
00992     if (trigbits.cer2) trigword |=TRIG_CER2_MASK;
00993     if (trigbits.cer3) trigword |=TRIG_VARC0_MASK;
00994     if (trigbits.istof) trigword |=TRIG_TOF_MASK;
00995     if (trigbits.isv0) trigword |=TRIG_VARC0_MASK;
00996     //    if (trigbits.isv1) trigword |=TRIG_VARC1_MASK;
00997     if (trigbits.issgate) trigword |=TRIG_SGATE_MASK;
00998     if (trigword) ndead = CalculateDeadChips(teventstart,fDeadChipLastBuffer,nplanes);
00999     if ((fAllData
01000          ||((TRIG_PLANE_MASK&fTrigMask)&&(nplanes>fNumPlanes))
01001          ||(trigword&(fTrigMask&(~TRIG_PLANE_MASK))))
01002         &&(!(trigword&fExcludeMask))) WriteEvent(teventstart,trigword,tf,start,end,rotoStrmName);
01003         
01004     if (fUseCounter) fCounter->Event(fTimeframe[tf],teventstart,n[0],n[1],
01005                                      nplanes,int(trigbits.istof),
01006                                      int(trigbits.cer1),int(trigbits.cer2),
01007                                      int(trigbits.cer3),
01008                                      int(trigbits.isv0), 
01009                                      int(trigbits.isv1), ndead, 
01010                                      int(trigbits.isli));
01011 
01012     // end of event...
01013 
01014     for (int crate = 0; crate<fCrates; crate++) {
01015       start[crate] = end[crate];
01016     }
01017     memset(hitplane,0,sizeof(hitplane));
01018     swap(fDeadChipBuffer,fDeadChipLastBuffer);
01019 
01020     
01021   }
01022   // No more hits
01023 }
01024 
01025 void OltNewModule::WriteEvent(unsigned long teventstart, int trigword,int tf,
01026                            unsigned int *start, 
01027                            unsigned int *end,
01028                            string rotoStrmName)
01029 {
01030   int bufpos = 0;
01031   //memset(fBuffer,0,200000*sizeof(long));
01032   //Snarl Header Block.
01033   mdBlockSnarlHeader_t *sh = reinterpret_cast<mdBlockSnarlHeader_t *>
01034     (fBuffer + bufpos);
01035   sh->gHdr.lenBlockWords = 11;
01036   sh->gHdr.checksum = 0;
01037   sh->gHdr.blockId = (kMdBlockSnarlHeader<<BLOCKID_BITPOS_IDENTIFIER) |
01038     (kMdBlockSourceCalDetector<<BLOCKID_BITPOS_DETECTOR) | (1);//minor 1
01039   sh->runNumber = fRun;
01040   sh->subRunAndType = (fSubrun<<16) & fRunType;
01041   sh->timeStamp.sec = fCrateSec[tf][0];
01042   sh->timeStamp.nsec = fCrateNsec[tf][0]+int(teventstart*VATICK);
01043   if (sh->timeStamp.nsec>1000000000L) {
01044     sh->timeStamp.nsec-=1000000000L;
01045     sh->timeStamp.sec+=1;
01046   }
01047   sh->timeFrameNumber = fTimeframe[tf];
01048   sh->snarlNumber = fEventNo;
01049   sh->triggerSource = trigword;
01050   sh->errorCode = 0;
01051   rdxsum_fill((long*)sh,0);  // fill in the checksum value
01052   bufpos +=sh->gHdr.lenBlockWords;
01053 
01054   //Crate Readout Block
01055   mdBlockGenericHeader_t *cratehead = 
01056     reinterpret_cast<mdBlockGenericHeader_t *>(fBuffer + bufpos);
01057   cratehead->checksum = 0;
01058   cratehead->blockId = (kMdBlockCrateReadout<<BLOCKID_BITPOS_IDENTIFIER) | 
01059     (kMdBlockSourceCalDetector<<BLOCKID_BITPOS_DETECTOR) | (1); // minor 1
01060   int nwords=0;
01061   unsigned long *nhits;
01062   bufpos+=3;
01063 
01064   // Special - write ND fiducial hit here.
01065  
01066   for (int crate = 0; crate<fCrates ; crate++) {
01067     if ((fHaveNDTimingHit&&crate==0)||(start[crate]!=end[crate])){
01068       nwords +=4;
01069       fBuffer[bufpos++] = fCrateId[tf][crate];
01070       nhits = fBuffer + bufpos;
01071       fBuffer[bufpos++] = 0;
01072       fBuffer[bufpos++] = fCrateSec[tf][crate]; // cratet0sec
01073       fBuffer[bufpos++] = fCrateNsec[tf][crate]; // cratet0nsec
01074       if (crate==0 && fHaveNDTimingHit) {
01075         long long *ptr = reinterpret_cast<long long *>(fBuffer + bufpos);
01076         *ptr = fNDTimingHit[tf];
01077         bufpos+=2;
01078         nwords+=2;
01079         (*nhits)+=1;
01080       }
01081       for (unsigned int it = start[crate];
01082            it!=end[crate];++it) {
01083         long long *ptr = reinterpret_cast<long long *>(fBuffer + bufpos);
01084         *ptr = fSortedHits[crate][it];
01085         bufpos+=2;
01086         nwords+=2;
01087         (*nhits)+=1;
01088       }
01089     }
01090   }
01091   cratehead->lenBlockWords = nwords + 3;
01092   rdxsum_fill((long*)cratehead,0);  // fill in the checksum value
01093  
01094   // Dead Chips
01095   memcpy(fBuffer+bufpos,fDeadBuf,fDeadBuf[0]*sizeof(long));
01096   bufpos +=fDeadBuf[0];
01097 
01098   // ToF Block
01099   if (trigword & TRIG_TOF_MASK) {
01100     memcpy(fBuffer+bufpos,fToFOutputArray,fToFOutputArray[0]*sizeof(long));
01101     bufpos +=fToFOutputArray[0];
01102     fToFOutputArray[0]=0; // Set size to 0 so we don't keep producing
01103     //the last buffer in the case of mismatched ToF hits.
01104   }
01105 
01106   int status;
01107   MomNavigator *mom = 
01108     RotoObjectifier::BufferInflate(reinterpret_cast<const char*>(fBuffer),
01109                                    bufpos*sizeof(long),status);
01110   WriteMom(mom,rotoStrmName,trigword);
01111   delete mom;
01112   ++fEventNo;
01113 } 
01114 
01115 
01116 
01117 
01118 int OltNewModule::ToChip(int chad)
01119 {
01120   return (chad & 0x1fe0);
01121 }
01122 
01123 int OltNewModule::ToVmm(int chad)
01124 {
01125 return (chad & 0x1f00);
01126 }
01127 
01128 int OltNewModule::ToChad(int varc, int vmm, int adc, int chip, int channel)
01129 {
01130   return channel + (chip<<5) + (adc<<7) + (vmm<<8) + (varc<<11);
01131 }
01132 
01133 int OltNewModule::CalculateDeadChips(int timestamp, int buf,int nplanes)
01134 {
01135   int ndead = 0;
01136   fDeadBuf[0] = 3;
01137   fDeadBuf[1] = 0;
01138   fDeadBuf[2] = (0xf00<<BLOCKID_BITPOS_IDENTIFIER) | 
01139     (kMdBlockSourceCalDetector<<BLOCKID_BITPOS_DETECTOR);
01140   unsigned long *numptr;
01141   unsigned long *lptr = fDeadBuf + 3;
01142   for (int crate=0;crate<fCrates;crate++) {
01143     numptr = lptr;
01144     ++lptr;
01145     *numptr = 0;
01146     ++(*fDeadBuf);
01147     map<int,int>::iterator it;
01148     //cout<<crate<<"  "<<fElec[crate]<<endl;
01149     if (fElec[crate]==1) {
01150       // VA
01151       for (it = fChipFreeTime[buf][crate].begin();
01152            it != fChipFreeTime[buf][crate].end();
01153            it++) {
01154         if ((*it).second >timestamp) {
01155           // This chip is dead.
01156           if (fUseCounter) {
01157             fCounter->DeadTime((*it).second - timestamp);
01158             fCounter->DeadChip(crate, (*it).first);
01159             if (nplanes>3) fCounter->DeadChipTrig(crate, (*it).first);
01160           }
01161           ++ndead;
01162           ++(*numptr);
01163           *lptr++=(*it).first;
01164           ++(*fDeadBuf);
01165         // Form the buffer here.
01166         }
01167       }
01168     }
01169     else if (fElec[crate]==2) {
01170       for (it = fChipFreeTime[buf][crate].begin();
01171            it != fChipFreeTime[buf][crate].end();
01172            it++) {
01173         if ((*it).second >timestamp) {
01174           // This chip is dead.
01175           ++ndead;
01176           ++(*numptr);
01177           *lptr++=((*it).first&(1<<19));  // Set "Qie" bit if qie
01178           ++(*fDeadBuf);
01179         }
01180       }
01181     }
01182     else {
01183       //      MSG("Olt",Msg::kFatal) << "Don't know about electronics type "<<fElec[crate]<<endl;
01184     }
01185     //    MSG("Olt",Msg::kInfo)<<"There are "<<ndead<<" dead chips up to crate "
01186     //                   <<crate<<" of "<<fCrates<<endl;
01187   }
01188   rdxsum_fill((long*)fDeadBuf,0);  // fill in the checksum value
01189   return ndead;
01190 }
01191 
01192 
01193 int OltNewModule::SuckCrate(int crate, unsigned int &it, bool *hitplane, 
01194               OltNewModule::Trigbits &trigbits, int &teventend,int tf) 
01195 {
01196   //cout<<hex<<"Crate "<<crate<<" id "<<fCrateId[fLastTF][crate]<<dec<<endl;
01197   MSG("Olt",Msg::kVerbose)<<"Will Suck Crate"<<crate<<" Id: "<<hex<<fCrateId[fLastTF][crate]<<dec<<endl;
01198   if (fCrateId[fLastTF][crate] & 0x40) {
01199       // QIE electronics if this bit is set
01200     return SuckQieCrate(crate,it,hitplane,trigbits,teventend,tf);
01201   } else {
01202     return SuckVaCrate(crate,it,hitplane,trigbits,teventend,tf);
01203   }
01204 }
01205 
01206 
01207 int OltNewModule::SuckVaCrate (int crate, unsigned int &it, bool *hitplane, 
01208                                OltNewModule::Trigbits &trigbits, 
01209                                int &teventend, int tf)
01210 {
01211   //cout<<"Suck VA "<<crate<<endl;
01212   MSG("Olt",Msg::kVerbose)<<"In Suck VA: teventend is "<<teventend<<endl;
01213   int lastchip = -1;
01214   int n=0;
01215   for (;it<fSortedHits[crate].size();++it) {
01216     VaHit *hit = reinterpret_cast<VaHit *>(&fSortedHits[crate][it]);
01217     if (int(hit->timeStamp) < fGap + teventend) {
01218       ++n;
01219       teventend = max(teventend, (int)hit->timeStamp);
01220       int chad = hit->chad;
01221       MSG("Olt",Msg::kVerbose)<<"Suck VA Hit ts: "<<int(hit->timeStamp)<<" "<<hex<<chad<<dec<<" "<<int(hit->adcValue)<<endl; 
01222      hitplane[fPlane[crate][chad]] = true;
01223      if (crate==0) {
01224         int *tof;
01225         if (chad==chad_TOF) {
01226           trigbits.istof = true;
01227           if (fUseCounter) fCounter->Tof(teventend);
01228           MSG("Olt",Msg::kDebug)<<"Got a hit in [VMM6: VARC2] (TOF)\n";
01229           // We have a TOF hit - get next TDC from the correct Mike
01230           // object here and make an output block.
01231           // shove that block into fToFOutputArray.
01232           if (fToFConverter[tf]) {
01233                     MSG("Olt",Msg::kDebug)<<"TOF Hits: "<<fNumToFHits[tf]<<" TDCs: "<<fToFConverter[tf]->GetNumberOfRawTOFBlocks()<<endl;
01234             if (fToFConverter[tf]->GetNumberOfRawTOFBlocks()==fNumToFHits[tf])
01235               {
01236                 tof =  fToFConverter[tf]->GetPackedRawTOFBlock
01237                   (fTofIndex,reinterpret_cast<long *>(hit));
01238                 if (tof) {
01239                   memcpy(fToFOutputArray,tof,tof[0]*sizeof(long));
01240                   //        ++fTofIndex;        
01241                 } 
01242                 else {
01243                   MSG("Olt",Msg::kWarning)<<"ToF mismatch: tried to assign hit "
01244                                           <<fTofIndex<<" from "
01245                                           <<fToFConverter[fLastTF]->GetNumberOfRawTOFBlocks()
01246                                           <<" TDC readouts at "<<int(hit->timeStamp)<<endl;
01247                 }
01248               }
01249             else {
01250               // Log the ToF Mismatch here
01251               fCounter->ToFMismatch(fTimeframe[tf], fNumToFHits[tf]);
01252             }
01253           }
01254           else {
01255             MSG("Olt",Msg::kWarning)<<"ToF mismatch: tried to assign hit "
01256                                     <<fTofIndex
01257                                     <<" but there was no TOF block present\n";
01258           }         
01259           ++fTofIndex;  
01260         }             
01261         else if (chad==chad_CER1) {
01262           trigbits.cer1 = true;
01263           if (fUseCounter) fCounter->Cerenkov(1,hit->adcValue,hit->timeStamp);
01264         }
01265         else if (chad== chad_CER2) {
01266           trigbits.cer2 = true;
01267           if (fUseCounter) fCounter->Cerenkov(2,hit->adcValue,hit->timeStamp);
01268         }
01269         else if (chad == chad_CER3) {
01270           trigbits.cer3 = true;
01271           if (fUseCounter) fCounter->Cerenkov(3,hit->adcValue,hit->timeStamp);
01272         }
01273         else if (chad==CHAD_VARC1){
01274           trigbits.isv1 = true;
01275           //      MSG("Olt",Msg::kInfo)<<"Got a hit in VMM6: VARC1\n";
01276         }
01277         else if (chad== CHAD_VARC0) {
01278           trigbits.isv0 = true;
01279           //      MSG("Olt",Msg::kInfo)<<"Got a hit in VMM6: VARC0\n";
01280         }
01281         else if (chad==chad_TRIGPMT) {
01282           trigbits.isli = true;
01283         }
01284      }
01285     
01286     
01287       int chip = ToChip(hit->chad);
01288       int vmm = ToVmm(hit->chad);
01289       
01290       if (chip!=lastchip) {
01291           lastchip = chip;
01292           int tstart = max(fVmmFreeTime[fDeadChipLastBuffer][crate][vmm],
01293                            (int)hit->timeStamp);
01294           tstart = max(fVmmFreeTime[fDeadChipBuffer][crate][vmm],
01295                            tstart);
01296           fChipFreeTime[fDeadChipBuffer][crate][chip] = tstart + DEADTIME;
01297           fVmmFreeTime[fDeadChipBuffer][crate][vmm] = tstart + DEADTIME;
01298       }
01299 
01300     }
01301     else {
01302       return n;
01303     }
01304   }
01305   return n;
01306 }
01307 
01308 int OltNewModule::ToVaTime(unsigned int qietime)
01309 {
01310   return (int)(qietime * 16 * 58.0/77.0 + fQieOffset);
01311 }
01312 
01313 int OltNewModule::SuckQieCrate (int crate, unsigned int &it, bool *hitplane, 
01314                                 OltNewModule::Trigbits&  trigbits , 
01315                                 int &teventend, int /* tf */)
01316 {
01317   //cout<<"Suck QIE "<<crate<<endl;
01318   MSG("Olt",Msg::kVerbose)<<"In Suck QIE: teventend is "<<teventend<<endl;
01319   //unused: int lastchip = -1;
01320   int n=0;
01321   for (;it<fSortedHits[crate].size();++it) {
01322     QieHit *hit = reinterpret_cast<QieHit *>(&fSortedHits[crate][it]);
01323     if (ToVaTime(hit->timeStamp) < fGap + teventend) {
01324       ++n;
01325       teventend = max(teventend, (int)(ToVaTime(hit->timeStamp)));
01326        MSG("Olt",Msg::kVerbose)<<"Suck QIE Hit at "<<ToVaTime(hit->timeStamp)<<" ts: "<<int(hit->timeStamp)<<" "<<int(hit->master)<<":"<<int(hit->minder)<<" "<<int(hit->adc)<<endl; 
01327        int chad = (hit->minder + (hit->master << 5) + (hit->geo << 8));
01328        hitplane[fQiePlane[crate][chad]] = true;
01329        MSG("Olt",Msg::kVerbose)<<"QIE hit in plane "<<fQiePlane[crate][chad]<<
01330          "  "<<crate<<"  "<<chad<<endl;
01331 
01332        int pmtmask = chad&0x1f80;
01333        fQieFreeTime[fDeadChipBuffer][crate][pmtmask] = ToVaTime(hit->timeStamp) + QIEDEADTIME;
01334 
01335        if (hit->type==4) trigbits.issgate = true;
01336     }
01337     else {
01338       return n;
01339     }
01340   }
01341   return n;
01342 }
01343 
01344 bool OltNewModule::OpenSpy(Detector::Detector_t det, Int_t run, Int_t subrun)
01345 {
01346   string fname = 
01347     Form("%c%8.8d_%4.4d",Detector::AsString(det)[0],run,subrun);
01348   string number = Form("_%d",fSpyVersion);
01349   string filename = fOutDir + "/" + fname + number + ".spy.root";
01350   bool ok = true;  
01351   ++fSpyVersion;
01352 
01353 // 3 streams in daq file
01354   for (int i = Per::kDaqSnarl;i<=Per::kLightInjection;i++) {
01355     Per::EStreamType stype = (Per::EStreamType) i;
01356     string treeName = Per::AsString(stype);
01357     string rotoStrmName = fname + "." + treeName;
01358     int compressionLevel = 1; // ROOT Default
01359     PerOutputStream* astream =
01360       fSpyStreamManager->OpenStream(rotoStrmName,treeName,
01361                                        "RawRecord","","",Per::kRecSplit,
01362                                        64000,compressionLevel);
01363     if (astream) {
01364       astream->SetAutoSave(0,0); // Turn off autosave
01365       bool openok = 
01366         fSpyStreamManager->SetFile(rotoStrmName,filename,Per::kRecreate);
01367       MSG("Olt",Msg::kInfo) << "Opened stream "<<rotoStrmName
01368                             << " on file "<<filename<<endl;
01369       // handle potential case where file already exists
01370       // and the rotorooter is in kNew not kRecreate mode
01371       Per::EErrorCode ecode = astream->GetErrorCode();
01372   
01373       
01374       if (Per::kErrSuccess != ecode) {
01375         MSG("Olt",Msg::kInfo) << "Open stream saw Per error: "
01376                               <<Per::AsString(ecode)<<endl;
01377       }
01378       ok = ok & openok;     
01379     } 
01380     else {
01381       ok = false;
01382     }
01383 
01384   } 
01385   return ok;
01386 }
01387 
01388 
01389 
01390 
01391 bool OltNewModule::CloseSpy(Detector::Detector_t det, Int_t run, Int_t subrun)
01392 {
01393   // Close output file. Name file *.tdaq.root for triggered data
01394   // Stolen from the Rotorooter...
01395   string fname = 
01396     Form("%c%8.8d_%4.4d",Detector::AsString(det)[0],run,subrun);
01397   
01398    // 3 streams in daq file
01399   for (int i = Per::kDaqSnarl;i<=Per::kLightInjection;i++) {
01400     Per::EStreamType stype = (Per::EStreamType) i;
01401     string treeName = Per::AsString(stype);
01402     string rotoStrmName = fname + "." + treeName;
01403     fSpyStreamManager->Write(rotoStrmName);
01404     fSpyStreamManager->CloseStream(rotoStrmName);
01405    }
01406   return true;
01407 }
01408 
01409 void OltNewModule::WriteConfig(string rotoStrmName)
01410 {
01411 
01412   VldTimeStamp now((const time_t)0,0); 
01413   VldContext vldc(fDetector,SimFlag::kData,now);
01414   RawDaqHeader *rawHead = new
01415     RawDaqHeader(vldc,fRun,fSubrun,fRunType,0);
01416   RawRecord *rawRec = new RawRecord(rawHead);
01417   RawDaqHeaderBlock *rawHeadBlk =
01418     new RawDaqHeaderBlock(vldc,fRun,fSubrun,fRunType,0);
01419   rawRec->AdoptRawBlock(rawHeadBlk);
01420   Registry &r = this->GetConfig();
01421   ostringstream text;
01422   r.PrintStream(text);
01423   char cvs[] = "$Id: OltNewModule.cxx,v 1.58 2006/12/03 02:15:30 gmieg Exp $\n";
01424   string blah(cvs);
01425   blah+=text.str();
01426   RawRunConfigBlock *rawRunConfigBlk =
01427      new RawRunConfigBlock(vldc,fRun,fSubrun,fRunType,blah.c_str());
01428   rawRec->AdoptRawBlock(rawRunConfigBlk);
01429 
01430   MomNavigator *mom = new MomNavigator;
01431   mom->AdoptFragment(rawRec);
01432   WriteMom(mom,rotoStrmName,0);
01433   delete mom;
01434 
01435 }
01436 
01437 void OltNewModule::WriteMom(MomNavigator *mom, string rotoStrmName, int trigword)
01438 {
01439   // MSG("Olt",Msg::kDebug)<<"Sent "<<bufpos<<" words to the rooter"<<endl;
01440   TIter iter = mom->FragmentIter();
01441   while (TObject *obj = iter.Next()) {
01442     RawRecord *rawrec = dynamic_cast<RawRecord *>(obj);
01443     MSG("Olt",Msg::kDebug)<<"RawRec: "<<rawrec<<endl;
01444     TIter recit = rawrec->GetRawBlockIter();
01445     while (TObject *obj = recit.Next()) {
01446       RawDataBlock *rawdata = dynamic_cast<RawDataBlock *>(obj);
01447       if (rawdata) {
01448         MSG("Olt",Msg::kDebug) <<rawdata->GetBlockId()<<endl;
01449       }
01450     }
01451     if (rawrec) {
01452       if (!fOutputStreamManager) {
01453         MSG("Olt",Msg::kError) << "No output stream manager"<<endl;
01454         return;
01455       }
01456       PerOutputStream* stream = 0;
01457       stream = dynamic_cast<PerOutputStream*>
01458         (fOutputStreamManager->GetOpenedStream(rotoStrmName));
01459       if (!stream) {
01460         MSG("Olt",Msg::kError) << "Can't find stream "<<rotoStrmName<<endl;
01461         return;
01462       }
01463       stream->SetObject(rawrec);
01464       stream->Store();
01465       //Spy...
01466       if (fSpyMode) {
01467         if ((trigword & (TRIG_CER2_MASK | TRIG_CER1_MASK | TRIG_TOF_MASK | TRIG_VARC0_MASK))
01468             && (trigword & TRIG_PLANE_MASK)){
01469           if (!fSpyStreamManager) { 
01470             MSG("Olt",Msg::kError) << "No output stream manager"<<endl;
01471             return;
01472           }
01473           PerOutputStream* spystream = 0;
01474           spystream = dynamic_cast<PerOutputStream*>
01475             (fSpyStreamManager->GetOpenedStream(rotoStrmName));
01476           if (!spystream) {
01477             MSG("Olt",Msg::kError) << "Can't find spy stream "<<rotoStrmName<<endl;
01478             return;
01479           }
01480           spystream->SetObject(rawrec);
01481           spystream->Store();
01482         }
01483       }
01484     }
01485     else {
01486       MSG("Olt",Msg::kError) <<"Didn't get a rawrec back from BufferInflate()"
01487                              <<endl;
01488     }
01489   }
01490   
01491 
01492 }

Generated on Fri Mar 28 15:37:10 2008 for loon by  doxygen 1.3.9.1