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

DetSim.cxx

Go to the documentation of this file.
00001 
00002 // $Id: DetSim.cxx,v 1.6 2007/11/10 16:22:40 schubert Exp $
00003 //
00004 // A JobControl Module for filling RawData from REROOT
00005 //
00006 // rhatcher@fnal.gov
00008 
00009 #include "DetSim/DetSim.h"
00010 #include "DetSim/SimDetector.h"
00011 #include "Digitization/DigiList.h"
00012 #include "Digitization/DigiPE.h"
00013 #include "Digitization/DigiSignal.h"
00014 
00015 #include "MinosObjectMap/MomNavigator.h"
00016 
00017 #include "MessageService/MsgService.h"
00018 #include "JobControl/JobCModuleRegistry.h"
00019 #include "JobControl/JobCommand.h"
00020 
00021 #include "Plex/PlexHandle.h"
00022 
00023 #include "Conventions/Munits.h"
00024 
00025 #include "Calibrator/Calibrator.h"
00026 
00027 #include "RawData/RawRecord.h"
00028 #include "RawData/RawDaqSnarlHeader.h"
00029 #include "RawData/RawDigitDataBlock.h"
00030 #include "RawData/RawBlockRegistry.h"
00031 #include "RawData/RawBlockId.h"
00032 #include "RawData/RawDigit.h"
00033 #include "RawData/RawDigiDigitMixIn.h"
00034 #include "RawData/RawQieDigit.h"
00035 #include "RawData/RawVaDigit.h"
00036 
00037 #include "Record/SimSnarlRecord.h"
00038 #include "Record/SimSnarlHeader.h"
00039 #include <TMath.h>
00040 #include <TObjArray.h>
00041 #include <TRandom3.h>
00042 
00043 ClassImp(DetSim)
00044 
00045 //......................................................................
00046 
00047 CVSID("$Id: DetSim.cxx,v 1.6 2007/11/10 16:22:40 schubert Exp $");
00048 JOBMODULE(DetSim, "DetSim",
00049          "Builds RawRecord with DigiPEs");
00050 
00051 //......................................................................
00052 
00053 DetSim::DetSim() 
00054    : fDetector(0),
00055      fRandomSeed(0),
00056      fRandom(0), 
00057      fRunStartSecs(-1),
00058      ncrates(0), workingcrates(0), cratesizeused(0), workingarray(0),
00059      fRemoveFalseDigits(1),
00060      fBiggestSnarlOnly(1),
00061      fContextSimFlag(SimFlag::kMC)
00062 {
00063    // construct a new "DetSim" JobControl module
00064 
00065    // we'll use a random # generator to set fake "trigbits"
00066    // the generator can live as long as the module
00067    fRandom = new TRandom3();
00068 
00069    ncrates = 128;
00070    cratesizeused  = new TArrayI(ncrates);
00071    workingcrates  = new TArrayI [ncrates];
00072 
00073    Int_t init_alloc = 5 + 100*3;
00074    for (Int_t i=0; i<ncrates; i++) {
00075       cratesizeused->AddAt(0,i);
00076       workingcrates[i].Set(init_alloc);
00077    }
00078 
00079    nwordsblock = 0;
00080    workingarray = new TArrayI(2);
00081 
00082    fDetectorConfiguration.UnLockValues();
00083    fDetectorConfiguration = SimDetector::DefaultConfig();
00084 
00085    fResultTree = 0;
00086    fResultTreeFile = 0;
00087 }
00088 
00089 //......................................................................
00090 
00091 DetSim::~DetSim() 
00092 {
00093   MSG("DetSim", Msg::kVerbose) << "DetSim::Destructor\n";
00094   
00095   if(fDetector) delete fDetector;
00096   if (fRandom) delete fRandom;
00097   fRandom = 0;
00098 
00099   if (ncrates) {
00100      delete [] workingcrates;
00101      workingcrates = 0;
00102 
00103      delete cratesizeused;
00104      cratesizeused = 0;
00105 
00106      ncrates = 0;
00107   }
00108 
00109   if (workingarray) delete workingarray;
00110   workingarray = 0;
00111 
00112   if(fResultTree) {
00113     MSG("DetSim",Msg::kInfo) << "Closing DetSim Ana file." << endl;
00114     fResultTreeFile->cd();
00115     fResultTree->Write();
00116     fResultTreeFile->Write();
00117     fResultTreeFile->Close();
00118     delete fResultTreeFile;
00119     fResultTreeFile = 0;
00120   }
00121 }
00122 
00123 //......................................................................
00124 
00125 JobCResult DetSim::Get(MomNavigator *mom)
00126 {
00127   // Simulate the PMTs and electronics and make a RawRecord.
00128 
00129   // Get the SimSnarl
00130   SimSnarlRecord* simsnarl = 0;
00131   TObject* tobj;
00132   TIter    fragiter = mom->FragmentIter();
00133   while( ( tobj = fragiter.Next() ) ) {
00134     simsnarl = dynamic_cast<SimSnarlRecord*>(tobj);
00135     if(simsnarl) break;
00136   }
00137 
00138   if(simsnarl ==0){
00139     MSG("DetSim",Msg::kError) << "Cannot find SimSnarl! Aborting this event!" << endl;
00140     return JobCResult::kWarning;
00141   }
00142 
00143    const TObjArray* peListObj = 0;
00144   peListObj = 
00145     dynamic_cast<const TObjArray*>(simsnarl->FindTemporary(0,"DigiListPe"));
00146 
00147   if(peListObj == 0) {
00148     // Not there? See if it's listed as a permanent object.
00149     MSG("DetSim",Msg::kInfo) << "DigiPE list is not marked as temporary. Try Permanent." << endl;
00150     peListObj = 
00151       dynamic_cast<const TObjArray*>(simsnarl->FindComponent(0,"DigiListPe"));
00152   }
00153 
00154   if(peListObj == 0) {
00155     MSG("DetSim",Msg::kError) << "Cannot find DigiPE list in the SimSnarl. Aborting." << endl;
00156     return JobCResult::kWarning;
00157   }
00158 
00159 
00160   const SimSnarlHeader* simHeader = simsnarl->GetSimSnarlHeader();
00161   if(simHeader ==0){
00162     MSG("DetSim",Msg::kError) << "Cannot find SimSnarlHeader. Aborting." << endl;
00163     return JobCResult::kWarning;
00164   }
00165 
00166   // For a PlexHandle we need a context
00167   fContext = simHeader->GetVldContext();
00168 
00169   // But we don't like this context.  We want it as an MC context,
00170   // not Reroot.
00171   fContext = VldContext(simHeader->GetVldContext().GetDetector(),
00172                         fContextSimFlag,
00173                         simHeader->GetVldContext().GetTimeStamp()
00174                         );
00175 
00176   // Reset the Calibrator.
00177   Calibrator::Instance().Reset(fContext);
00178 
00179   // Get a PlexHandle for PlexStripEndId to RawChannelId conversions
00180   PlexHandle ph(fContext);
00181   
00182   // Detector configuration. Make a new SimDetector,
00183   // or configure and reset the old one.
00184   if(fDetector==0){
00185     fDetector = new SimDetector(fContext,fRandom);
00186     fDetector->Config(fDetectorConfiguration);
00187   }
00188   fDetector->Reset(fContext);
00189 
00190   // Add all the PEs into the simulation.
00191   fDetector->AddDigiPEList(peListObj);
00192 
00193   // Set the random seed to match the event.
00194   // Also add some user-configurable randomness, in case they want to
00195   // generate the same event with a different outcome.
00196   fDetector->GetRandom()->SetSeed( simHeader->GetRun() 
00197                                    + simHeader->GetSnarl() 
00198                                    + fRandomSeed );
00199 
00200   // The money shot:
00201   fDetector->Simulate();
00202   
00203   // Debugging only:
00204   //if(MsgService::Instance()->GetStream("DetSim")->IsActive(Msg::kDebug))
00205   //  fDetector->Print();
00206 
00207   // An array to hold DigiSignals.
00208   TObjArray* signalArray = new TObjArray(fDetector->GetNumberOfDigits());
00209   signalArray->SetOwner(true);
00210   signalArray->SetName("DigiSignal");
00211 
00213   // Copy out all digiSignals.
00214   for(int i=0;i<fDetector->GetNumberOfDigits();i++) {
00215     // Get each digitization, whether it made it through a trigger or not.
00216     const SimDigit* digit = fDetector->GetSimDigit(i);
00217     if(digit) {
00218       // This makes a copy of the signal.
00219       if(digit->GetSignal()) 
00220         signalArray->AddLast(new DigiSignal(*(digit->GetSignal())));
00221     }
00222   }
00223   // Add the truth data to the simsnarl
00224   simsnarl->AdoptComponent(signalArray);
00225 
00227   // Make a new RawDigitDataBlock for each SimSnarl
00228 
00229   Int_t snarls_written = 0;
00230 
00231   for(UInt_t iSnarl=0; iSnarl<fDetector->GetNumberOfSnarls(); iSnarl++) { // each snarl
00232 
00233     // Check to see if this is the biggest one. 
00234     // This removes 'crap' events from the stream. This is a stopgap measure.
00235     if(fBiggestSnarlOnly) {
00236       if(iSnarl != fDetector->GetBiggestSnarl()) {
00237         MSG("DetSim",Msg::kInfo) << "Throwing out a snarl with "
00238                                  << fDetector->GetSnarl(iSnarl).Size() 
00239                                  << " digits." << endl;
00240         continue;
00241       }
00242     }
00243 
00244     const SimSnarl& snarl = fDetector->GetSnarl(iSnarl);
00245 
00246 
00247     // Prepare to start by getting current REROOT pointers
00248     // and clearing out the working array
00249     InitWorkingArray();
00250     
00251     
00252     // Reset context with a slightly different timestamp.
00253     // This should make no DB change, but correctly gets
00254     // the trigger time, making this consistent with later
00255     // analyses.
00256     
00257     // rwh: we would actually like to use the ns part of the
00258     // initial time stamp to offset within the 1 sec time
00259     // but currently the snarl creation doesn't use this
00260     // and introducing it here would just confuse things.
00261     VldTimeStamp trigTime(fContext.GetTimeStamp().GetSec(),
00262                           (int)(snarl.GetTriggerTime()/Munits::ns));
00263     VldContext trigContext(fContext.GetDetector(),
00264                            fContext.GetSimFlag(),
00265                            trigTime);
00266     
00267     Int_t outSnarlHits = 0;
00268     
00269     for(UInt_t i=0;i<(snarl.Size());i++) {
00270       // Get each hit...
00271       const SimDigit* digit = snarl.GetDigit(i);
00272       
00273       // And tack 'em on.
00274       if(digit) {
00275         // This test looks for bits that are bad in some way,
00276         // e.g. failed the 2/36 varc trigger. Some studies
00277         // may find it useful to keep them. If so, they are flagged
00278         // with error bits.
00279         if( (digit->GetErrors()==0) || (fRemoveFalseDigits==0) ) {
00280           outSnarlHits++;
00288           AddToCrate( trigContext,
00289                       digit->GetRawChannelId(),
00290                       digit->GetADC(),
00291                       digit->GetTDC(),
00292                       digit->GetErrors(),
00293                       digit->GetSignal()->GetId()
00294                       );
00295         }
00296       }
00297     }
00298     
00299     MSG("DetSim",Msg::kDebug) << "Snarl " << iSnarl << " added with " << outSnarlHits << " hits\n";
00300     
00301     
00302     
00304     // Add the raw data to to the raw record.
00305     
00306     // Finalize the working array, produce RawDigitDataBlock
00307     RawDataBlock *rawblk = FinalizeWorkingArray(trigContext);
00308     RawDigitDataBlock *rrdb = dynamic_cast<RawDigitDataBlock*>(rawblk);
00309     
00310     // produce a RawDaqSnarlHeader (specialized RawHeader)
00311     // which the RawRecord will adopt
00312     
00313     if(fRunStartSecs<0) fRunStartSecs = fContext.GetTimeStamp().GetSec();
00314     
00315     Int_t   run      = simHeader->GetRun();
00316     Short_t subrun   = simHeader->GetSubRun();
00317     Short_t runtype  = simHeader->GetRunType();
00318     Int_t   timeframe= simHeader->GetTimeFrame(); // fContext.GetTimeStamp().GetSec() - fRunStartSecs;
00319     // by using Snarl # stored in SimSnarlHeader we avoid getting out of
00320     // synch.  drawback is potential for duplicates when triggering
00321     // splits a SimSnarl's data into two separate triggers
00322     Int_t   snarlNo  = simHeader->GetSnarl();
00323     Int_t   trigbits = snarl.GetTriggerSource();
00324     Int_t   errcode  = simHeader->GetErrorCode();
00325     Int_t   nrawdigits = (rrdb) ? rrdb->GetNumberOfDigits() : -1;
00326     Int_t   spilltype  = -1;
00327     
00328     RawDaqSnarlHeader *head = 
00329       new RawDaqSnarlHeader(trigContext,run,subrun,runtype,timeframe,
00330                             snarlNo,trigbits,errcode,nrawdigits,spilltype);
00331     
00332     // produce a RawRecord, have it adopt the header  
00333     RawRecord *rawrec = new RawRecord(head);
00334 
00335     RecJobHistory& jobhist 
00336                   = const_cast<RecJobHistory&>(rawrec->GetJobHistory());
00337     jobhist.Append(simsnarl->GetJobHistory());
00338     jobhist.CreateJobRecord(RecJobHistory::kRaw);
00339     
00340     // give the block to the RawRecord
00341     rawrec->AdoptRawBlock(rawblk);
00342     
00343     // tag this RawRecord AS IF it had come from the DaqSnarl stream
00344     rawrec->GetTempTags().Set("stream","DaqSnarl");
00345     
00346     
00347     // massage the simsnarl so it has the same time.
00348     SimSnarlHeader* varSimHeader = const_cast<SimSnarlHeader*>(simHeader);
00349     varSimHeader->SetVldContext(trigContext);
00350     
00351     // give the RawRecord to MOM to hold as a "fragment"
00352     mom->AdoptFragment(rawrec);
00353     
00354       snarls_written += 1;
00355   }
00356 
00357   SimEventResult& eventResult = fDetector->GetEventResult();
00358   eventResult.run = simHeader->GetRun();
00359   eventResult.event = simHeader->GetSnarl();
00360 
00361   // Add a copy of the event result to the simsnarl for later bookkeeping.
00362   simsnarl->AdoptComponent(new SimEventResult(eventResult));
00363 
00364   // Return true if a snarl comes out.
00365   if(snarls_written==0) return JobCResult::kFailed;
00366   
00367   // Return trigger result.
00368   return JobCResult::kPassed;
00369 }
00370 
00371 
00372 //......................................................................
00373 
00374 JobCResult DetSim::Ana(const MomNavigator *mom)
00375 {
00376   // A test job for "reconstruction"
00377 
00378 
00379   SimSnarlRecord* simsnarl = 0;
00380   TObject* tobj;
00381   TIter    fragiter = mom->FragmentIter();
00382 
00383   // Get the simsnarl.
00384   while( ( tobj = fragiter.Next() ) ) {
00385     simsnarl = dynamic_cast<SimSnarlRecord*>(tobj);
00386     if(simsnarl) break;
00387   }
00388   const TObjArray* peListObj = 0;
00389   peListObj = 
00390     dynamic_cast<const TObjArray*>(simsnarl->FindTemporary(0,"DigiListPe"));
00391 
00392   if(peListObj == 0) {
00393     // Not there? See if it's listed as a permanent object.
00394     MSG("DetSim",Msg::kInfo) << "DigiPE list is not marked as temporary. Try Permanent." << endl;
00395     peListObj = 
00396       dynamic_cast<const TObjArray*>(simsnarl->FindComponent(0,"DigiListPe"));
00397   }
00398 
00399   if(peListObj == 0) {
00400     MSG("DetSim",Msg::kError) << "Cannot find DigiPE list in the SimSnarl. Aborting." << endl;
00401     return JobCResult::kWarning;
00402   }
00403 
00404   const DigiPE* digipe = NULL;
00405   Double_t earliest = 1e10;
00406 
00407   TObjArrayIter itr(peListObj);
00408   while( (digipe = dynamic_cast<DigiPE*>(itr.Next()))!=0 ) {
00409     if(digipe->GetTime() < earliest) earliest = digipe->GetTime();
00410     fDetector->GetEventResult().npe++;
00411   };
00412 
00414   // Fill a tree with some summary data.
00415   static SimEventResult* result_ptr;
00416   result_ptr = &(fDetector->GetEventResult());
00417   if( fResultTreeFile==0 ) {
00418     fResultTreeFile = new TFile("detsim_stats.root","RECREATE");
00419     fResultTree = new TTree("detsim","detsim");
00420     
00421     fResultTree->Branch("result","SimEventResult",&result_ptr,32000,1);
00422     fResultTree->Write("detsim");
00423     fResultTree->Print();
00424   }
00425   fResultTree->Fill();
00426   
00427                                                      
00428   // The following is example code for 
00429   // how to look at truth info.
00430   /*
00431     
00432 
00433   // Make a table of the DigiSignals if they exist.
00434   std::map<UInt_t,const DigiSignal*> signalMap;
00435 
00436   const TObjArray* signalArray = 
00437     dynamic_cast<const TObjArray*>(simsnarl->FindComponent(0,"DigiSignal"));
00438   if(signalArray) {
00439     TIter signalIter(signalArray);
00440     while( (tobj = signalIter.Next()) ) {
00441       const DigiSignal* signal = dynamic_cast<DigiSignal*>(tobj);
00442       if(signal) signalMap[signal->GetId()] = signal;
00443     }
00444   }  
00445   MSG("DetSim",Msg::kDebug) << "Got " << signalMap.size() << " signals." << endl;
00446   
00447   // Get the RawDigitDataBlock.
00448   const RawHeader* rawhead =0;
00449   const RawDigitDataBlock* rddb =0;
00450 
00451   fragiter.Reset();
00452   while( ( tobj = fragiter.Next() ) ) {
00453     RawRecord* rawRec = dynamic_cast<RawRecord*>(tobj);
00454     if(rawRec) {
00455       rawhead = rawRec->GetRawHeader();
00456       TIter itr = rawRec->GetRawBlockIter();
00457       RawDataBlock* rawBlk;
00458       while ( ( rawBlk = dynamic_cast<RawDataBlock*>(itr.Next()) ) ) {
00459         rddb = dynamic_cast<RawDigitDataBlock*>(rawBlk);
00460         if(rddb) break;
00461       }
00462     }
00463   }
00464 
00465   if(rddb) {
00466     TIter rditer = rddb->GetDatumIter();
00467     while( ( tobj = rditer.Next() ) ) {
00468       RawDigit*        rawDigit = dynamic_cast<RawDigit *>(tobj);
00469       RawDigiDigitMixIn* rawMCDigit = dynamic_cast<RawDigiDigitMixIn*>(tobj);
00470       
00471       if(rawDigit) 
00472         MSG("DetSim",Msg::kDebug) << "Digit: " << *rawDigit << endl;
00473       if(rawMCDigit) {
00474         UInt_t id = (UInt_t) rawMCDigit->GetDigiSignalIndex();
00475         if(signalMap.find(id)!=signalMap.end())
00476           MSG("DetSim",Msg::kDebug) << "  Signal: " 
00477                << "(Id: " << id << " ) "
00478                << "("       << signalMap[id]->GetCharge()/Munits::fC << " fC)\t"
00479                << "(truth=" << signalMap[id]->GetTruth() << ")\t"
00480                << "("       << signalMap[id]->GetNumberOfHits() << " hits)\t"
00481                << "("       << signalMap[id]->GetNumPes() << " PE)"
00482                << endl;
00483       }
00484     }
00485   }
00486   */
00487 
00488   return JobCResult::kAOK;
00489 }
00490 
00491 //......................................................................
00492 
00493 void DetSim::InitWorkingArray(void)
00494 {
00495    // Initialize for new "Get"
00496 
00497    // zero out used sizes ...
00498    for (Int_t i=0; i<ncrates; i++) {
00499       cratesizeused->AddAt(0,i);
00500    }
00501    nwordsblock = 0;
00502 }
00503 
00504 
00505 //......................................................................
00506 
00507 void DetSim::AddToCrate( VldContext& context,
00508                                          const RawChannelId&   rcid,
00509                                          Int_t adc, Int_t tdc,
00510                                          Bool_t error, 
00511                                          Int_t truth_info)
00512 {
00513    // Add this entry into the crate array
00514 
00515    Int_t crate = rcid.GetCrate();
00516    if (crate>=ncrates) {
00517       MSG("DetSim",Msg::kFatal) 
00518          << "DetSim::AddToCrate "
00519          << crate << " larger than allocated " << ncrates << endl;
00520       return;
00521    }
00522 
00523    TArrayI *wcrate = &workingcrates[crate];
00524 
00525    //  Crate block format is:
00526    //-------------------------
00527    //   0: Crate #
00528    //   1: # ndigits in crate (N)
00529    //   2: GPS T0 sec
00530    //   3: GPS T0 nsec
00531    //   4: readout 1 word 1
00532    //   5: readout 1 word 2
00533    //   6: PlexStripEndId.fEncoded truth
00534    //   7: readout 2 word 1
00535    //   8: readout 2 word 2
00536    //   9: PlexStripEndId.fEncoded truth
00537 
00538    const Int_t hsize        = 4; // header size
00539    const Int_t ndigits_indx = 1; // index for pair count
00540    const Int_t nw_digit     = 3; // 3 words per digit
00541 
00542    // if allocated size is too small make it bigger
00543    Int_t used = cratesizeused->At(crate);
00544    Int_t need = used + nw_digit;  // each new entry adds three words
00545    if (0 == used) need += hsize;
00546 
00547    const Int_t slop = 100; // min extra allocation
00548 
00549    if (wcrate->GetSize() < need) {
00550       wcrate->Set(need+slop);
00551    }
00552 
00553    // add in header stuff if necessary
00554    if (0 == used) {
00555       // crate # + ped/common modes + electronics flag
00556       const Int_t modes = 0x07;
00557       Int_t etype = rcid.GetElecType();
00558       Int_t packedCrate = (modes << 8) |
00559          (etype << 6) | (crate & 0x0000003f);
00560       wcrate->AddAt(packedCrate,used++);
00561       // # digits
00562       if (used != ndigits_indx) {
00563          // this should never happen
00564          MSG("DetSim",Msg::kFatal) 
00565             << "DetSim::AddToCrate ndigits_indx "
00566             << ndigits_indx << " != " << used << endl;
00567       }
00568       wcrate->AddAt(0,used++);
00569       // GPS T0 (sec,nsec)
00570       VldTimeStamp vts = context.GetTimeStamp();
00571       wcrate->AddAt(vts.GetSec(),used++);
00572       // The fine time stamp corresponds to the start of the timeframe, not the event.
00573       wcrate->AddAt(0,used++); 
00574       // Used to be: wcrate->AddAt(vts.GetNanoSec(),used++);
00575    }
00576 
00577    // Pack in data words.
00578    switch( rcid.GetElecType() ) {
00579    case ElecType::kVA:
00580      PackVaDigit(used, *wcrate, rcid, adc, tdc, error, truth_info);
00581      break;
00582    case ElecType::kQIE:
00583      PackQieDigit(used, *wcrate, rcid, adc, tdc, error, truth_info);
00584      break;
00585    default:
00586      // This shouldn't happen.
00587      MSG("DetSim",Msg::kError) << "DetSim: Unknown electronics type! Cannot pack digit!" << endl;
00588    }
00589 
00590    // update pair count
00591    Int_t npairs = (used-hsize)/nw_digit;
00592    wcrate->AddAt(npairs,ndigits_indx);
00593 
00594    // update used size
00595    cratesizeused->AddAt(used,crate);
00596 }
00597 
00598 
00599 void 
00600 DetSim::PackVaDigit(Int_t& cptr, 
00601                                     TArrayI& wcrate,
00602                                     const RawChannelId&   rcid,
00603                                     Int_t adc, Int_t tdc,
00604                                     Bool_t error,
00605                                     Int_t truth_info
00606                                     )
00607 {
00608    // From RawVaDigit:
00609    //       3         2         1         0
00610    //      10987654321098765432109876543210
00611    //  U:  1PWccccccccccccNsaaaaaaaaaaaaaa   X=common mode,c=chan, s=sign a=adc
00612    //  L:  0Pttttttttttttttttttttttttttttt   P=parity, t=tdc
00613    //  X:  PlexStripEndId::fEncoded
00614    // W = fifo or calinject warning condition (0=okay)
00615    // N = 1 for normal data taking (0=calinject or pedestal data)
00616 
00617   
00618   const int chaddmask  = 0x1fff;
00619   const int adcmask    = 0x00003fff;
00620   const int tdcmask    = 0x3fffffff;
00621   const int chaddshift = 16;
00622   const int adcsignbit  = 0x00004000;
00623   //const int adcsignext  = 0xffffc000;
00624   //const int adcsignshft = 14;
00625   const int wordbit    = 0x80000000;
00626   const int parityb    = 0x40000000;
00627   const int warnb      = 0x20000000;
00628   const int stddatab   = 0x00008000;
00629 
00630   // Pack channel address.
00631   Int_t chadd   = rcid.GetChAdd();
00632   if (chadd > chaddmask) {
00633     // this should never happen
00634     static int nmsg_chadd = 5;
00635     if (nmsg_chadd) {
00636          MSG("DetSim",Msg::kFatal) 
00637            << "DetSim::AddToCrate chadd "
00638            << hex << chadd << dec << " truncated from " 
00639            << hex << rcid.GetChAdd() << dec << endl;
00640          nmsg_chadd--;
00641          if (nmsg_chadd==0) 
00642            MSG("DetSim",Msg::kFatal) 
00643              << " ... last of these messages" << endl;
00644     }
00645   }
00646   chadd &= chaddmask;
00647   
00648   Int_t iadc = adc;
00649   // two's compliment.
00650   if(adc<0) iadc = (adcmask+1) - abs(adc);
00651 
00652   if (iadc > adcmask ) {
00653     // this shouldn't happen often.
00654     static int nmsg_adc = 5;
00655     if (nmsg_adc) {
00656       MSG("DetSim",Msg::kWarning) 
00657         << "DetSim::PackVaDigit() iadc "
00658         << iadc << " does not fit in field  (max " 
00659             << adcmask << ")" << endl;
00660       nmsg_adc--;
00661       if (nmsg_adc==0)
00662         MSG("DetSim",Msg::kWarning) 
00663           << " ... last of these messages" << endl;
00664     }     
00665       iadc = TMath::Max(0,TMath::Min(iadc,adcmask));
00666   }
00667   iadc &= adcmask;
00668   
00669   Int_t itdc = tdc;
00670   if (itdc < 0 ) { 
00671     // -ve times are a bugger.
00672     // Wrap the times around and hope that the reconstruction program can
00673     // fix it.
00674     itdc += 640000000; // Number of 16*40MHz ticks in a second.
00675   }
00676   else if (itdc > tdcmask ) {
00677     // this should never happen
00678     static int nmsg_tdc = 5;
00679     if (nmsg_tdc) {
00680       MSG("DetSim",Msg::kWarning) 
00681         << "DetSim::AddToCrate itdc "
00682         << itdc << " does not fit in field (max " 
00683         << tdcmask << ")" << endl;
00684       nmsg_tdc--;
00685       if (nmsg_tdc==0)
00686         MSG("DetSim",Msg::kWarning) 
00687           << " ... last of these messages" << endl;
00688     }     
00689     itdc = TMath::Max(0,TMath::Min(itdc,tdcmask));
00690   }
00691   itdc &= tdcmask;
00692   
00693   Int_t upper = stddatab | wordbit | (chadd<<chaddshift) | iadc;
00694   // Add sign bit.
00695   if(adc<0) upper |= adcsignbit;
00696   // Add error bit, if appropritate.
00697   if(error) upper |= warnb;
00698   
00699   Int_t lower = itdc;
00700   Int_t  extra = truth_info;
00701 
00702   // Compute parities.
00703   int sum1 = 0;
00704   int sum0 = 0;
00705   int v1 = upper; // upper word
00706   int v0 = lower; // lower word
00707   for (int j=0; j<32; j++) {
00708     sum1 += (v1&1);
00709     sum0 += (v0&1);
00710     v1 = v1 >> 1;
00711     v0 = v0 >> 1;
00712   }
00713   // If parities are odd, add a bit to make them even.
00714   
00715   if (sum1&1 !=0 ) upper |= parityb;
00716   if (sum0&1 !=0 ) lower |= parityb;
00717 
00718   // push the words in
00719   wcrate.AddAt(upper,cptr++);
00720   wcrate.AddAt(lower,cptr++);
00721   wcrate.AddAt(extra,cptr++);
00722 }
00723 
00724 
00725 void 
00726 DetSim::PackQieDigit(Int_t& cptr, 
00727                                      TArrayI& wcrate,
00728                                      const RawChannelId&   rcid,
00729                                      Int_t adc, Int_t tdc,
00730                                      Bool_t error,
00731                                      Int_t truth_info
00732                                      )
00733 {
00734    // From RawQieDigit:
00735    //       3         2         1         0
00736    //      10987654321098765432109876543210
00737    //  U:  eeecccccccccccccaaaaaaaaaaaaaaaa   e=err, c=chan, a=adc
00738    //  L:  dddxxttttttttttttttttttttttttttt   d=datatype x=unused, t=tdc
00739    //  X:  PlexStripEndId::fEncoded
00740 
00741   const int adcmask    = 0x0000ffff;
00742   const int tdcmask    = 0x07ffffff;     
00743   const int chaddmask  = 0x00001fff;
00744   const int errshift  = 29;
00745   const int errmask   = 0x00000007;
00746   const int chanshift = 16;
00747   const int dtshift   = 29;
00748   const int dtmask    = 0x00000007;
00749 
00750   Int_t chadd   = rcid.GetChAdd( );
00751    if (chadd > chaddmask) {
00752       // this should never happen
00753       static int nmsg_chadd = 5;
00754       if (nmsg_chadd) {
00755          MSG("DetSim",Msg::kFatal) 
00756             << "DetSim::PackQieDigit chadd "
00757             << hex << chadd << dec << " truncated from " 
00758             << hex << rcid.GetChAdd() << dec << endl;
00759          nmsg_chadd--;
00760          if (nmsg_chadd==0) 
00761             MSG("DetSim",Msg::kFatal) 
00762                << " ... last of these messages" << endl;
00763       }
00764    }
00765    chadd &= chaddmask;
00766 
00767    Int_t iadc = adc;
00768    if ( (iadc > adcmask) || (iadc<0) ) {
00769       // this shouldn't happen too often.
00770       static int nmsg_adc = 5;
00771       if (nmsg_adc) {
00772          MSG("DetSim",Msg::kWarning) 
00773             << "DetSim::PackQieDigit() iadc "
00774             << iadc << " does not fit in field  (max " 
00775             << adcmask << ")" << endl;
00776          nmsg_adc--;
00777          if (nmsg_adc==0)
00778             MSG("DetSim",Msg::kWarning) 
00779                << " ... last of these messages" << endl;
00780       }     
00781       iadc = TMath::Max(0,TMath::Min(iadc,adcmask));
00782    }
00783    iadc &= adcmask;
00784 
00785    Int_t itdc = tdc;
00786    if (itdc < 0) {
00787      // -ve times are a bugger. wrap them to the correct value and hope 
00788      // the reconstruction can sort it out.
00789      itdc += 53097844; // The number of QIE ticks in one second.
00790    }
00791    if (itdc > tdcmask ) {
00792       // this should never happen
00793       static int nmsg_tdc = 5;
00794       if (nmsg_tdc) {
00795          MSG("DetSim",Msg::kWarning) 
00796             << "DetSim::PackQieDigit itdc "
00797             << itdc << " does not fit in field (max " 
00798             << tdcmask << ")" << endl;
00799          nmsg_tdc--;
00800          if (nmsg_tdc==0)
00801             MSG("DetSim",Msg::kWarning) 
00802                << " ... last of these messages" << endl;
00803       }     
00804       itdc = TMath::Max(0,TMath::Min(itdc,tdcmask));
00805    }
00806    itdc &= tdcmask;
00807    
00808    // Pack it up.
00809    int ierr = 0;
00810    if(error) ierr =  (RawQieDigit::kParityError) & errmask;
00811    
00812    // We assume that all ND data is spill mode.
00813    // This is the current assumption in the QIE model.
00814    int dtype = (RawQieDigit::kSGate) & dtmask;
00815    
00816    Int_t upper = (ierr<<errshift) | (chadd<<chanshift) | iadc;
00817    Int_t lower = (dtype<<dtshift) | itdc; 
00818    Int_t  extra = truth_info;
00819    
00820    // push the words in
00821    wcrate.AddAt(upper,cptr++);
00822    wcrate.AddAt(lower,cptr++);
00823    wcrate.AddAt(extra,cptr++);
00824 }
00825 
00826 
00827 
00828 //......................................................................
00829 
00830 RawDataBlock* DetSim::FinalizeWorkingArray(VldContext& context)
00831 {
00832    // Build final array from crate arrays
00833 
00834    //  Block format is:
00835    //---------------------
00836    //  # words in block
00837    //  checksum
00838    //  Block Id
00839    //  Crate #
00840    //  GPS T0 sec
00841    //  GPS T0 nsec
00842    //  Crate status
00843    //  # pairs in crate (N)
00844    //  readout 1 word 1
00845    //  readout 1 word 2
00846    //   < truth PlexStripEndId if Reroot data>
00847    //  readout 2 word 1
00848    //  readout 2 word 2
00849    //  ...
00850    //  readout N word 1
00851    //  readout N word 2
00852    //  Crate #
00853    //  GPS T0 sec
00854    //  GPS T0 nsec
00855    //  Crate status
00856    //  # pairs in crate (N)
00857    //  readout 1 word 1
00858 
00859    Int_t need = 3;  // #words, checksum, blockid
00860    for (Int_t crate=0; crate < ncrates; crate++) {
00861       need += cratesizeused->At(crate);
00862    }
00863 
00864    // float to highwater mark without copying contents
00865    if (workingarray->GetSize() < need) {
00866       workingarray->Set(0);    // deletes old array
00867       workingarray->Set(need); // set to necessary size
00868    }
00869 
00870    RawBlockRegistry& rbr = RawBlockRegistry::Instance();
00871    RawBlockProxy*    rbp = rbr.LookUp("RawDigitDataBlock");
00872 
00873    Bool_t isDCS   = rbp->IsDCS();
00874    Int_t  majorId = rbp->GetMajorId();
00875 
00876    RawBlockProxy*    rbp2 = rbr.LookUp(isDCS,majorId);
00877    if ( rbp2 != rbp ) MSG("DetSim",Msg::kError) << "RawBlockProxy cross check failed" << endl;
00878 
00879    Int_t  minorId = 0;
00880    RawBlockId rbid(majorId,minorId,isDCS,context.GetDetector(),context.GetSimFlag());
00881    MSG("DetSim", Msg::kDebug)
00882       << " to be stored with RawBlockId " 
00883       << " 0x" << hex << rbid.GetEncoded() << dec
00884       << " == " << rbid.AsString() << endl
00885       << " majorId " << majorId << " minorId " << minorId
00886       << ((isDCS) ? " DCS " : " DAQ ")
00887       << " " << Detector::AsString(context.GetDetector()) << endl;
00888 
00889    Int_t checksum = 0xdeadbeef;
00890 
00891    Int_t& indx = nwordsblock;  // set "next" index to # words in block
00892    indx = 0;
00893    workingarray->AddAt(need,indx++);
00894    workingarray->AddAt(checksum,indx++);
00895    workingarray->AddAt(rbid.GetEncoded(),indx++);
00896    for (Int_t crate=0; crate<ncrates; crate++) {
00897       Int_t csize = cratesizeused->At(crate);
00898       TArrayI *wcrate = &workingcrates[crate];
00899       Int_t   *array  = wcrate->GetArray();  // gawd, it's guts are public
00900       for (Int_t i=0; i<csize; i++) {
00901          workingarray->AddAt(array[i],indx++);
00902       }
00903    }     
00904    
00905    // fill in the true checksum
00906    int xsum_version = 0;
00907    rdxsum_fill((long*)workingarray->GetArray(),xsum_version);
00908    
00909    // use the proxy to actually create a block
00910    return rbp->CreateRawDataBlock(workingarray->GetArray());
00911 
00912 }
00913 
00914 //......................................................................
00915 
00916 
00917 const Registry& DetSim::DefaultConfig() const
00918 {
00919   static Registry r;
00920 
00921   // Set name of config
00922   std::string name = this->GetName();
00923   name += ".config.default";
00924   r.SetName(name.c_str());
00925   
00926   // Set values in configuration
00927   r.UnLockValues();
00928   
00929   r.Set("removeFalseDigits",1);
00930   r.Set("biggestSnarlOnly",1);
00931   r.Set("contextSimFlag",SimFlag::AsString(SimFlag::kMC));
00932   r.Set("randomSeed",fRandomSeed);
00933 
00934   const Registry& r_simdet = SimDetector::DefaultConfig();
00935   r.Merge(r_simdet);
00936 
00937   return r;
00938 }
00939 
00940 void  DetSim::Config(const Registry& r)
00941 {
00942   fDetectorConfiguration.Merge(r);
00943   
00944   r.Get("removeFalseDigits",fRemoveFalseDigits);
00945   r.Get("biggestSnarlOnly",fBiggestSnarlOnly);
00946   r.Get("randomSeed",fRandomSeed);
00947   const char* tmps;
00948   if(r.Get("contextSimFlag",tmps)) { 
00949     SimFlag::SimFlag_t tsimflag = SimFlag::StringToEnum(tmps);
00950     if(tsimflag!=SimFlag::kUnknown) fContextSimFlag = tsimflag;
00951   }
00952 
00953   if(fDetector) fDetector->Config(fDetectorConfiguration);
00954 }
00955 
00956 void  DetSim::Report()
00957 {
00958   if(fDetector) fDetector->Print();
00959   else JobCModule::Report();
00960 }

Generated on Sat Nov 21 22:45:58 2009 for loon by  doxygen 1.3.9.1