| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

DataLoaderAlg.cc

Go to the documentation of this file.
00001 #include "DataLoaderAlg.h"
00002 
00003 #include "RawData/RawRecord.h"
00004 #include "RawData/RawData.h"
00005 #include "RawData/RawDataReader.h"
00006 #include "RawData/RawRecordFormat.h"
00007 #include "RawData/RawDataFormat.h"
00008 #include "Event/ReadoutPmtCrate.h"
00009 #include "Event/ReadoutRpcCrate.h"
00010 
00011 
00012 #include <sstream>
00013 
00014 DataLoaderAlg::DataLoaderAlg(const std::string& name, ISvcLocator* pSvcLocator)
00015   : DybAlgorithm<DayaBay::ReadoutHeader>(name,pSvcLocator)
00016   , m_inputFiles()
00017   , m_usePacked(true)
00018   , m_useUnpacked(true)
00019   , m_reader(0)
00020   , m_fileIndex(0)
00021   , m_fileYear(0)
00022   , m_fileMonth(0)
00023   , m_fileDay(0)
00024   , m_utcDay(0)
00025 {
00026   declareProperty("InputFiles",m_inputFiles,
00027                   "List of input data files");
00028   declareProperty("UsePacked",m_usePacked=true,"Load Packed Data");
00029   declareProperty("UseUnpacked",m_useUnpacked=true,"Load Unpacked Data");
00030 }
00031 
00032 DataLoaderAlg::~DataLoaderAlg()
00033 {
00034 }
00035 
00036 StatusCode DataLoaderAlg::initialize()
00037 {
00038   // Initialize the data loader
00039   m_fileIndex = 0;
00040   return StatusCode::SUCCESS;
00041 }
00042 
00043 StatusCode DataLoaderAlg::execute()
00044 {
00045   // Load one readout event
00046 
00047   // Get next event data
00048   DayaBay::RawEvent* event = 0;
00049   StatusCode sc = this->readNextEvent(event);
00050   if( !sc.isSuccess() ) return sc;
00051 
00052   // Create output header
00053   DayaBay::ReadoutHeader* readoutHeader = MakeHeaderObject();
00054 
00055   // Load data into header
00056   sc = this->loadEventData(event, readoutHeader);
00057 
00058   delete event;
00059   return sc;
00060 }
00061 
00062 StatusCode DataLoaderAlg::finalize()
00063 {
00064 
00065   // Delete old file reader
00066   if(m_reader){
00067     delete m_reader;
00068     m_reader=0;
00069   }
00070   m_fileIndex=0;
00071   return StatusCode::SUCCESS;
00072 }
00073 
00075 
00076 StatusCode DataLoaderAlg::openNextFile()
00077 {
00078   // Open the next input data file.
00079 
00080   // Delete old file reader
00081   if(m_reader){
00082     delete m_reader;
00083     m_reader=0;
00084   }
00085 
00086   // Check if there are more files
00087   if(m_fileIndex >= m_inputFiles.size()){
00088     warning() << "No more files to read" << endreq; 
00089     return StatusCode::FAILURE;
00090   }
00091 
00092   // Create new file reader
00093   m_reader = new DayaBay::RawDataReader;
00094   if(!m_reader){
00095     error() << "Failed to create new file reader" << endreq;
00096     return StatusCode::FAILURE;
00097   }
00098 
00099   // Open next file
00100   if(!m_reader->open( m_inputFiles[m_fileIndex].c_str() )){
00101     error() << "Failed to open input file: " << m_inputFiles[m_fileIndex] 
00102             << endreq;
00103     delete m_reader;
00104     m_reader=0;
00105     return StatusCode::FAILURE;
00106   }
00107 
00108   return StatusCode::SUCCESS;
00109 }
00110 
00111 StatusCode DataLoaderAlg::readNextEvent(DayaBay::RawEvent*& nextEvent)
00112 {
00113   // Read the next event record
00114 
00115   DayaBay::RawEvent* event = 0;
00116   while( !event ){
00117 
00118     // Check if reader is ready
00119     if(!m_reader){
00120       StatusCode sc = this->openNextFile();
00121       if(! sc.isSuccess() ){
00122         return sc;
00123       }
00124     }
00125 
00126     // Read the next record
00127     DayaBay::RawRecord* record = m_reader->nextRecord();
00128     if(!record){
00129       error() << "Failed to read next record from file: " 
00130               << m_inputFiles[m_fileIndex] << endreq;
00131       return StatusCode::FAILURE;
00132     }
00133 
00134     // Check the record type
00135     if( !record->isDataSeparator() ){
00136       // Not a data separator record.
00137       std::stringstream message;
00138       record->dump( message );
00139       info() << message.str() << endreq;
00140       if( record->isFileStart() ){
00141         DayaBay::RawFileStart* fileStart = dynamic_cast<DayaBay::RawFileStart*>(record);
00142         if(fileStart){
00143           this->m_fileYear = fileStart->date() % 10000;
00144           this->m_fileMonth = (fileStart->date() / 10000) % 100;
00145           this->m_fileDay = (fileStart->date() / 1000000) % 100;
00146           this->m_utcDay = 0;
00147         }
00148       }
00149       if( record->isFileEnd() ){
00150         // End of file.  Close and increment file index
00151         delete m_reader;
00152         m_reader = 0;
00153         m_fileIndex++;
00154       }
00155       delete record;
00156       continue;
00157     }
00158 
00159     // Process the data separator
00160     DayaBay::RawDataSeparator* dataSeparator = 
00161       dynamic_cast<DayaBay::RawDataSeparator*>(record);
00162     if( !dataSeparator ){
00163       error() << "Failed to process data separator" << endreq;
00164       std::stringstream message;
00165       record->dump( message );
00166       error() << message.str() << endreq;
00167       delete record;
00168       return StatusCode::FAILURE;
00169     }
00170     // Get Payload data
00171     DayaBay::RawData* data = dataSeparator->data();
00172     if( !data ){
00173       error() << "Failed to load payload data" << endreq;
00174       std::stringstream message;
00175       record->dump( message );
00176       error() << message.str() << endreq;
00177       delete record;
00178       return StatusCode::FAILURE;
00179     }
00180     // Check for event data
00181     if( !data->isEventType() ){
00182       // Not event data
00183       std::stringstream message;
00184       data->dump( message );
00185       info() << message.str() << endreq;
00186       delete data;
00187       delete record;
00188       continue;
00189     }
00190 
00191     // Found event data
00192     event = dynamic_cast<DayaBay::RawEvent*>(data);
00193     if( !event ){
00194       error() << "Failed to read event" << endreq;
00195       std::stringstream message;
00196       data->dump( message );
00197       error() << message.str() << endreq;
00198       delete data;
00199       delete record;
00200       return StatusCode::FAILURE;
00201     }
00202   }
00203 
00204   nextEvent = event;
00205   return StatusCode::SUCCESS;
00206 }
00207 
00208 
00209 StatusCode DataLoaderAlg::loadEventData(DayaBay::RawEvent* event, 
00210                                         DayaBay::ReadoutHeader* readoutHeader)
00211 {
00212   // Fill Readout 
00213 
00214   // Find the trigger time
00215   TimeStamp triggerTime;
00216   StatusCode sc = this->findTriggerTime(event,triggerTime);
00217   if(!sc.isSuccess()){
00218     warning() << "Failed to find trigger time for event: " << event->eventId()
00219               << endreq;
00220   }
00221 
00222   // Set the context
00223   Site::Site_t site = this->convertSite( event->siteId() );
00224   Context context(site,
00225                   SimFlag::kData,
00226                   triggerTime,
00227                   (DetectorId::DetectorId_t)(event->detectorId()));
00228 
00229   readoutHeader->setContext(context);
00230   readoutHeader->setEarliest(triggerTime);
00231   readoutHeader->setLatest(triggerTime);
00232 
00233   // Construct the readout
00234   DayaBay::Detector detector(this->convertSite(event->siteId()),
00235                              this->convertDetector(event->detectorId()));
00236 
00237   DayaBay::Readout* readout = 0;
00238   if( detector.isAD() || detector.isWaterShield() ){
00239     readout = new DayaBay::ReadoutPmtCrate();
00240   }else if( detector.detectorId() == DetectorId::kRPC){
00241     readout = new DayaBay::ReadoutRpcCrate();
00242   }else{
00243     error() << "Unknown detector: \"" << detector.detName() << "\","
00244             << " cannot make readout." << endreq;
00245     return StatusCode::FAILURE;
00246   }
00247 
00248   // Need to set detector for proper persistency
00249   readout->setDetector(detector);
00250   
00251   // Fill readout
00252   if(m_usePacked){
00253     // Packed data
00254     readout->setRawEvent( event->clone() );
00255   }
00256 
00257   if(m_useUnpacked){
00258     // Unpacked data
00259     sc = this->unpackEvent(event, readout);
00260     if( !sc.isSuccess() ){
00261       delete readout;
00262       return sc;
00263     }
00264   }
00265   // Add the readout to the header
00266   readoutHeader->setReadout( readout );
00267   readout->setHeader( readoutHeader );
00268 
00269   return StatusCode::SUCCESS;
00270 }
00271 
00272 
00273 StatusCode DataLoaderAlg::findTriggerTime(DayaBay::RawEvent* event, 
00274                                           TimeStamp& triggerTime)
00275 {
00276   // Find the trigger time for this event
00277   if(!event){
00278     error() << "Cannot find time of invalid event" << endreq;
00279     return StatusCode::FAILURE;
00280   }
00281   // Search raw data block for trigger time
00282   bool foundTriggerTime = false;
00283   while( DayaBay::RawModule* module = event->nextModule() ){
00284     if( module->isLocalTriggerModule() ){
00285       while( DayaBay::DataFragment* fragment = module->nextDataFragment() ){
00286         if( fragment->isLocalTriggerData() ){
00287           DayaBay::LocalTriggerData* ltbData = 
00288             dynamic_cast<DayaBay::LocalTriggerData*>(fragment);
00289           if(!ltbData){
00290             error() << "Failed to access local trigger data fragment" << endreq;
00291             return StatusCode::FAILURE;
00292           }
00293           triggerTime = this->convertTriggerTime(ltbData);
00294           foundTriggerTime = true;
00295           break;
00296         }
00297         delete fragment;
00298       }
00299       if( foundTriggerTime ) break;
00300     }
00301     delete module;
00302   }
00303   event->resetModule();
00304   if(!foundTriggerTime)   return StatusCode::FAILURE;
00305   return StatusCode::SUCCESS;
00306 }
00307 
00308 
00309 TimeStamp DataLoaderAlg::convertTriggerTime(DayaBay::LocalTriggerData* ltbData)
00310 {
00311   //Unpack Trigger time from raw LTB data block
00312   TimeStamp triggerTime;
00313   if(ltbData->isUnixTime()){
00314     triggerTime = TimeStamp(ltbData->unixtime(),
00315                             ltbData->nanosecond()+ltbData->accumulation());
00316   }else if(ltbData->isUtcTime()){
00317     // This data format provides no 'year'
00318     // Estimate the year from the file start time
00319     if(  ltbData->days()  <  this->m_utcDay ){
00320       // Catch case where file spans new year
00321       this->m_fileYear++;
00322     }
00323     triggerTime = TimeStamp(this->m_fileYear,
00324                             1 /*month*/,
00325                             ltbData->days()+1 /*day in year*/,
00326                             ltbData->hour(),
00327                             ltbData->minute(),
00328                             ltbData->second(),
00329                             ltbData->nanosecond()+ltbData->accumulation(),
00330                             true /*UTC*/);
00331     this->m_utcDay = ltbData->days();
00332   }else{
00333     // Date format from LTB Data version 0
00334     // The trigger times in this format have many issues; see DocDB-4635
00335     // Override using the file start time
00336     // Fix bug caused by 61s in a minute and 61m in an hour
00337     unsigned int seconds = ltbData->hour()*61*61 
00338       + ltbData->minute()*61 
00339       + ltbData->second();
00340     unsigned int hour = seconds / 3600;
00341     unsigned int minute = (seconds - hour*3600) / 60;
00342     unsigned int second = (seconds - (hour*3600 + minute*60));
00343     int timezoneOffset = -8*60*60; /* 8hr offset of PRC from UTC */
00344     triggerTime = TimeStamp(this->m_fileYear,  //ltbData->year(),
00345                             this->m_fileMonth, //ltbData->month(),
00346                             this->m_fileDay,   //ltbData->day(),
00347                             hour,
00348                             minute,
00349                             second,
00350                             (int)(ltbData->clock()*12.5) /* 80MHz clock */,
00351                             true /*use UTC with timezone offset*/,
00352                             timezoneOffset);
00353   }
00354   return triggerTime;
00355 }
00356 
00357 Site::Site_t DataLoaderAlg::convertSite(unsigned int daqSiteId)
00358 {
00359   // Convert site definition from DAQ to Offline convention 
00360   switch(daqSiteId){
00361   case 1:
00362     return Site::kDayaBay;
00363   case 2:
00364     return Site::kLingAo;
00365   case 3:
00366     return Site::kFar;
00367   case 4:
00368     return Site::kMid;
00369   case 6:
00370     return Site::kSAB;
00371   default:
00372     break;
00373   }
00374   return Site::kUnknown;
00375 }
00376 
00377 DetectorId::DetectorId_t DataLoaderAlg::convertDetector(
00378                                                   unsigned int daqDetectorId)
00379 {
00380   // Convert detector definition from DAQ to Offline convention 
00381   switch(daqDetectorId){
00382   case 1:
00383     return DetectorId::kAD1;
00384   case 2:
00385     return DetectorId::kAD2;
00386   case 3:
00387     return DetectorId::kAD3;
00388   case 4:
00389     return DetectorId::kAD4;
00390   case 5:
00391     return DetectorId::kIWS;
00392   case 6:
00393     return DetectorId::kOWS;
00394   case 7:
00395     return DetectorId::kRPC;
00396   default:
00397     break;
00398   }
00399   return DetectorId::kUnknown;
00400 }
00401 
00402 int DataLoaderAlg::convertBoard(unsigned int daqSlotId)
00403 {
00404   return daqSlotId;
00405 }
00406 
00407 int DataLoaderAlg::convertConnector(unsigned int daqChannelId)
00408 {
00409   return daqChannelId+1;
00410 }
00411 
00412 DayaBay::Trigger::TriggerType_t DataLoaderAlg::convertTriggerType(
00413                                             DayaBay::LocalTriggerData* ltbData,
00414                                             const DayaBay::Detector* detector)
00415 {
00416   // Convert Online trigger type to Offline convention
00417   unsigned int triggerType = DayaBay::Trigger::kUnknown;
00418   if(ltbData->isManualTrigger())
00419     triggerType |= DayaBay::Trigger::kManual;
00420   if(ltbData->isCrossTrigger())
00421     triggerType |= DayaBay::Trigger::kCross;
00422   if(ltbData->isPeriodicTrigger())
00423     triggerType |= DayaBay::Trigger::kPeriodic;
00424   if(ltbData->isMultiplicityTrigger())
00425     triggerType |= DayaBay::Trigger::kMult;
00426   // FIXME: Need to add all Esum trigger types to offline convention
00427   if(ltbData->isEsumAdcTrigger())
00428     triggerType |= DayaBay::Trigger::kESum;
00429   if(ltbData->isEsumCompHighTrigger())
00430     triggerType |= DayaBay::Trigger::kESum;
00431   if(ltbData->isEsumCompLowTrigger())
00432     triggerType |= DayaBay::Trigger::kESum;
00433   if(ltbData->isEsumCompAllTrigger())
00434     triggerType |= DayaBay::Trigger::kESum;
00435 
00436   switch(detector->detectorId()){
00437   case DetectorId::kAD1:
00438     triggerType |= DayaBay::Trigger::kAD1;
00439     break;
00440   case DetectorId::kAD2:
00441     triggerType |= DayaBay::Trigger::kAD2;
00442     break;
00443   case DetectorId::kAD3:
00444     triggerType |= DayaBay::Trigger::kAD3;
00445     break;
00446   case DetectorId::kAD4:
00447     triggerType |= DayaBay::Trigger::kAD4;
00448     break;
00449   case DetectorId::kIWS:
00450     triggerType |= DayaBay::Trigger::kIWS;
00451     break;
00452   case DetectorId::kOWS:
00453     triggerType |= DayaBay::Trigger::kOWS;
00454     break;
00455   default:
00456     break;
00457  }
00458 
00459   return static_cast<DayaBay::Trigger::TriggerType_t>(triggerType);
00460 }
00461 
00462 DayaBay::FeeGain::FeeGain_t DataLoaderAlg::convertAdcRange(
00463                                                       unsigned int daqAdcRange)
00464 {
00465   // Convert ADC Range definition from DAQ to Offline convention 
00466   switch(daqAdcRange){
00467   case 0:
00468     return DayaBay::FeeGain::kHigh;
00469   case 1:
00470     return DayaBay::FeeGain::kLow;
00471   default:
00472     break;
00473   }
00474   return DayaBay::FeeGain::kUnknown;
00475 }
00476 
00477 
00478 StatusCode DataLoaderAlg::unpackEvent(DayaBay::RawEvent* event, 
00479                                       DayaBay::Readout* readout)
00480 {
00481   // Unpack raw data into readout object
00482 
00483   // Loop over modules
00484   while( DayaBay::RawModule* module = event->nextModule() ){
00485     StatusCode sc;
00486     if( module->isLocalTriggerModule() ){
00487       sc = this->unpackLtbModule(module, readout);
00488     }else if( module->isPmtFeeModule() ){
00489       sc = this->unpackFeeModule(module, 
00490                      dynamic_cast<DayaBay::ReadoutPmtCrate*>(readout));
00491     }else if( module->isFlashAdcModule() ){
00492       //sc = this->unpackFlashAdcModule(module, readout);
00493     }else if( module->isRpcRomModule() ){
00494       //sc = this->unpackRpcRomModule(module, readout);
00495     }else if( module->isRpcRtmModule() ){
00496       //sc = this->unpackRpcRomModule(module, readout);
00497     }else{
00498       warning() << "Cannot unpack unknown module type: " 
00499                 << module->moduleType()<< endreq;
00500       sc = StatusCode::FAILURE;
00501     }
00502     if( !sc.isSuccess() ){
00503       // Gracefully continue even if there is trouble reading a module
00504       continue;
00505     }
00506     delete module;
00507   }
00508 
00509   return StatusCode::SUCCESS;
00510 }
00511 
00512 StatusCode DataLoaderAlg::unpackLtbModule(DayaBay::RawModule* module, 
00513                                           DayaBay::Readout* readout)
00514 {
00515   // Unpack the trigger data module
00516   bool firstTriggerFragment = true;
00517   TimeStamp triggerTime;
00518 
00519   while( DayaBay::DataFragment* fragment = module->nextDataFragment() ){
00520     if( fragment->isLocalTriggerData() ){
00521       // Process the trigger data fragment
00522       DayaBay::LocalTriggerData* ltbData = 
00523         dynamic_cast<DayaBay::LocalTriggerData*>(fragment);
00524       if(!ltbData){
00525         warning() << "Bad Local Trigger Data fragment" << endreq;
00526         continue;
00527       }
00528       triggerTime = this->convertTriggerTime(ltbData);
00529       if(firstTriggerFragment){
00530         // Set trigger time, type, number according to first trigger data block
00531         readout->setTriggerTime( triggerTime );
00532         readout->setTriggerType(this->convertTriggerType(ltbData, 
00533                                                       &(readout->detector())));
00534         // Get Trigger Number from head fragment
00535         DayaBay::HeadFragment* headFragment = module->headFragment();
00536         if( headFragment ){
00537           readout->setTriggerNumber( headFragment->triggerNumber() );
00538           delete headFragment;
00539         }else{
00540           warning() << "Missing head fragment!" << endreq;
00541         }
00542         firstTriggerFragment = false;
00543       }else{
00544         if(triggerTime != readout->triggerTime()){
00545           TimeStamp dtTrigger( triggerTime );
00546           dtTrigger.Subtract( readout->triggerTime() );
00547           debug() << "Additional trigger at dT = " <<  dtTrigger.GetSeconds()
00548                   << " [s]" << endreq;
00549         }
00550       }
00551     }else{
00552       warning() << "Unknown LTB data fragment type: " << fragment->dataType() 
00553                 << endreq;
00554     }
00555     delete fragment;
00556   }
00557   return StatusCode::SUCCESS;
00558 }
00559 
00560 StatusCode DataLoaderAlg::unpackFeeModule(DayaBay::RawModule* module, 
00561                                           DayaBay::ReadoutPmtCrate* readout)
00562 {
00563   // Unpack the front-end electronics data module
00564   if(!readout){
00565     warning() << "Trying to add FEE data to a non-PMT readout"
00566               << endreq;
00567     return StatusCode::FAILURE;
00568   }
00569 
00570   while( DayaBay::DataFragment* fragment = module->nextDataFragment() ){
00571     if( fragment->isFeePeakData() ){
00572       // Process the FEE peak-finding data fragment
00573       DayaBay::FeePeakData* feePeakData = 
00574         dynamic_cast<DayaBay::FeePeakData*>(fragment);
00575       if(!feePeakData){
00576         warning() << "Bad FEE Peak-finding Data fragment" << endreq;
00577         continue;
00578       }
00579       // Add channel data to readout
00580       DayaBay::FeeChannelId channelId(
00581                           this->convertBoard(module->slot()),
00582                           this->convertConnector(feePeakData->channel()),
00583                           readout->detector().site(),
00584                           readout->detector().detectorId()); 
00585 
00586       DayaBay::ReadoutPmtChannel& feeChannel = readout->channel(channelId);
00587       if(feeChannel.channelId() != channelId){
00588         // New channel, initialize
00589         feeChannel.setChannelId(channelId);
00590         feeChannel.setMode(0x1); // Peak-finding
00591         feeChannel.setReadout(readout);
00592       }
00593       // Add hit data
00594       feeChannel.tdc().push_back( feePeakData->tdc() );
00595       feeChannel.tdcHitCount().push_back( feePeakData->tdcHitCount() );
00596       feeChannel.adc().push_back( feePeakData->adc() );
00597       feeChannel.adcRange().push_back( 
00598                            this->convertAdcRange(feePeakData->adcRange()) );
00599       feeChannel.adcCycle().push_back( feePeakData->peakCycle() );
00600       if( feePeakData->hasAdcPedestal() )
00601         feeChannel.pedestal().push_back( feePeakData->adcPedestal() ); 
00602     }else{
00603       warning() << "Unknown FEE data fragment type: " << fragment->dataType() 
00604                 << endreq;
00605     }
00606     delete fragment;
00607   }
00608   return StatusCode::SUCCESS;
00609 }
00610 
00611 
00612 // Local Variables: **
00613 // c-basic-offset:2 **
00614 // indent-tabs-mode:nil **
00615 // End: **
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:41:09 2011 for DataDebug by doxygen 1.4.7