CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/EventFilter/SiStripRawToDigi/src/SiStripRawToDigiUnpacker.cc

Go to the documentation of this file.
00001 #include "EventFilter/SiStripRawToDigi/interface/SiStripRawToDigiUnpacker.h"
00002 #include "CondFormats/SiStripObjects/interface/SiStripFedCabling.h"
00003 #include "DataFormats/Common/interface/DetSet.h"
00004 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
00005 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00006 #include "DataFormats/FEDRawData/src/fed_header.h"
00007 #include "DataFormats/FEDRawData/src/fed_trailer.h"
00008 #include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
00009 #include "DataFormats/SiStripCommon/interface/SiStripEventSummary.h"
00010 #include "DataFormats/SiStripDigi/interface/SiStripDigi.h"
00011 #include "DataFormats/SiStripDigi/interface/SiStripRawDigi.h"
00012 #include "EventFilter/SiStripRawToDigi/interface/TFHeaderDescription.h"
00013 #include "FWCore/Utilities/interface/Exception.h"
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 #include <iostream>
00016 #include <sstream>
00017 #include <iomanip>
00018 #include <ext/algorithm>
00019 
00020 namespace sistrip {
00021 
00022   RawToDigiUnpacker::RawToDigiUnpacker( int16_t appended_bytes, int16_t fed_buffer_dump_freq, int16_t fed_event_dump_freq, int16_t trigger_fed_id,
00023                                         bool using_fed_key, bool unpack_bad_channels, bool mark_missing_feds, const uint32_t errorThreshold ) :
00024     headerBytes_( appended_bytes ),
00025     fedBufferDumpFreq_( fed_buffer_dump_freq ),
00026     fedEventDumpFreq_( fed_event_dump_freq ),
00027     triggerFedId_( trigger_fed_id ),
00028     useFedKey_( using_fed_key ),
00029     unpackBadChannels_( unpack_bad_channels ),
00030     markMissingFeds_( mark_missing_feds ),
00031     event_(0),
00032     once_(true),
00033     first_(true),
00034     useDaqRegister_(false),
00035     quiet_(true),
00036     extractCm_(false),
00037     doFullCorruptBufferChecks_(false),
00038     doAPVEmulatorCheck_(true),
00039     errorThreshold_(errorThreshold)
00040   {
00041     if ( edm::isDebugEnabled() ) {
00042       LogTrace("SiStripRawToDigi")
00043         << "[sistrip::RawToDigiUnpacker::"<<__func__<<"]"
00044         <<" Constructing object...";
00045     }
00046     if (unpackBadChannels_) {
00047       edm::LogWarning("SiStripRawToDigi") << "Warning: Unpacking of bad channels enabled. Only enable this if you know what you are doing. " << std::endl;
00048     }
00049   }
00050 
00051   RawToDigiUnpacker::~RawToDigiUnpacker() {
00052     if ( edm::isDebugEnabled() ) {
00053       LogTrace("SiStripRawToDigi")
00054         << "[sistrip::RawToDigiUnpacker::"<<__func__<<"]"
00055         << " Destructing object...";
00056     }
00057   }
00058 
00059   void RawToDigiUnpacker::createDigis( const SiStripFedCabling& cabling, const FEDRawDataCollection& buffers, SiStripEventSummary& summary, RawDigis& scope_mode, RawDigis& virgin_raw, RawDigis& proc_raw, Digis& zero_suppr, DetIdCollection& detids, RawDigis& cm_values ) {
00060 
00061     // Clear working areas and registries
00062     cleanupWorkVectors();
00063     // Reserve space in bad module list
00064     detids.reserve(100);
00065   
00066     // Check if FEDs found in cabling map and event data
00067     if ( edm::isDebugEnabled() ) {
00068       if ( cabling.feds().empty() ) {
00069         edm::LogWarning(sistrip::mlRawToDigi_)
00070           << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00071           << " No FEDs found in cabling map!";
00072         // Check which FED ids have non-zero size buffers
00073         std::vector<uint16_t> feds;
00074         for ( uint16_t ifed = FEDNumbering::MINSiStripFEDID; ifed < FEDNumbering::MAXSiStripFEDID; ifed++ ) {
00075           if ( ifed != triggerFedId_ && 
00076                buffers.FEDData( static_cast<int>(ifed) ).size() ) {
00077             feds.push_back(ifed);
00078           }
00079         }
00080         LogTrace("SiStripRawToDigi")
00081           << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00082           << " Found " 
00083           << feds.size() 
00084           << " FED buffers with non-zero size!";
00085       }
00086     }
00087 
00088     // Flag for EventSummary update using DAQ register  
00089     bool first_fed = true;
00090   
00091     // Retrieve FED ids from cabling map and iterate through 
00092     std::vector<uint16_t>::const_iterator ifed = cabling.feds().begin();
00093     for ( ; ifed != cabling.feds().end(); ifed++ ) {
00094 
00095       // ignore trigger FED
00096       if ( *ifed == triggerFedId_ ) { continue;  }
00097     
00098       // Retrieve FED raw data for given FED 
00099       const FEDRawData& input = buffers.FEDData( static_cast<int>(*ifed) );
00100     
00101       // Some debug on FED buffer size
00102       if ( edm::isDebugEnabled() ) {
00103         if ( first_ && input.data() ) {
00104           std::stringstream ss;
00105           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00106              << " Found FED id " 
00107              << std::setw(4) << std::setfill(' ') << *ifed 
00108              << " in FEDRawDataCollection"
00109              << " with non-zero pointer 0x" 
00110              << std::hex
00111              << std::setw(8) << std::setfill('0') 
00112              << reinterpret_cast<uint32_t*>( const_cast<uint8_t*>(input.data()))
00113              << std::dec
00114              << " and size " 
00115              << std::setw(5) << std::setfill(' ') << input.size()
00116              << " chars";
00117           LogTrace("SiStripRawToDigi") << ss.str();
00118         }       
00119       }
00120     
00121       // Dump of FEDRawData to stdout
00122       if ( edm::isDebugEnabled() ) {
00123         if ( fedBufferDumpFreq_ && !(event_%fedBufferDumpFreq_) ) {
00124           std::stringstream ss;
00125           dumpRawData( *ifed, input, ss );
00126           edm::LogVerbatim(sistrip::mlRawToDigi_) << ss.str();
00127         }
00128       }
00129       
00130       // get the cabling connections for this FED
00131       const std::vector<FedChannelConnection>& conns = cabling.connections(*ifed);
00132     
00133       // Check on FEDRawData pointer
00134       if ( !input.data() ) {
00135         if ( edm::isDebugEnabled() ) {
00136           edm::LogWarning(sistrip::mlRawToDigi_)
00137             << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00138             << " NULL pointer to FEDRawData for FED id " 
00139             << *ifed;
00140         }
00141         // Mark FED modules as bad
00142         detids.reserve(detids.size()+conns.size());
00143         std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
00144         for ( ; iconn != conns.end(); iconn++ ) {
00145           if ( !iconn->detId() || iconn->detId() == sistrip::invalid32_ ) continue;
00146           detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
00147         }
00148         continue;
00149       } 
00150     
00151       // Check on FEDRawData size
00152       if ( !input.size() ) {
00153         if ( edm::isDebugEnabled() ) {
00154           edm::LogWarning(sistrip::mlRawToDigi_)
00155             << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00156             << " FEDRawData has zero size for FED id " 
00157             << *ifed;
00158         }
00159         // Mark FED modules as bad
00160         detids.reserve(detids.size()+conns.size());
00161         std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
00162         for ( ; iconn != conns.end(); iconn++ ) {
00163           if ( !iconn->detId() || iconn->detId() == sistrip::invalid32_ ) continue;
00164           detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
00165         }
00166         continue;
00167       }
00168       
00169       // construct FEDBuffer
00170       std::auto_ptr<sistrip::FEDBuffer> buffer;
00171       try {
00172         buffer.reset(new sistrip::FEDBuffer(input.data(),input.size()));
00173         if (!buffer->doChecks()) {
00174           if (!unpackBadChannels_ || !buffer->checkNoFEOverflows() )
00175             throw cms::Exception("FEDBuffer") << "FED Buffer check fails for FED ID " << *ifed << ".";
00176         }
00177         if (doFullCorruptBufferChecks_ && !buffer->doCorruptBufferChecks()) {
00178           throw cms::Exception("FEDBuffer") << "FED corrupt buffer check fails for FED ID " << *ifed << ".";
00179         }
00180       }
00181       catch (const cms::Exception& e) { 
00182         if ( edm::isDebugEnabled() ) {
00183           edm::LogWarning("sistrip::RawToDigiUnpacker") << "Exception caught when creating FEDBuffer object for FED " << *ifed << ": " << e.what();
00184         }
00185         // FED buffer is bad and should not be unpacked. Skip this FED and mark all modules as bad. 
00186         std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
00187         for ( ; iconn != conns.end(); iconn++ ) {
00188           if ( !iconn->detId() || iconn->detId() == sistrip::invalid32_ ) continue;
00189           detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
00190         }
00191         continue;
00192       }
00193 
00194       // Check if EventSummary ("trigger FED info") needs updating
00195       if ( first_fed && useDaqRegister_ ) { updateEventSummary( *buffer, summary ); first_fed = false; }
00196     
00197       // Check to see if EventSummary info is set
00198       if ( edm::isDebugEnabled() ) {
00199         if ( !quiet_ && !summary.isSet() ) {
00200           std::stringstream ss;
00201           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00202              << " EventSummary is not set correctly!"
00203              << " Missing information from both \"trigger FED\" and \"DAQ registers\"!";
00204           edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00205         }
00206       }
00207     
00208       // Check to see if event is to be analyzed according to EventSummary
00209       if ( !summary.valid() ) { 
00210         if ( edm::isDebugEnabled() ) {
00211           LogTrace("SiStripRawToDigi")
00212             << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00213             << " EventSummary is not valid: skipping...";
00214         }
00215         continue; 
00216       }
00217     
00219       sistrip::FEDReadoutMode mode = buffer->readoutMode(); 
00220 
00221       // Retrive run type
00222       sistrip::RunType runType_ = summary.runType();
00223       if( runType_ == sistrip::APV_LATENCY || runType_ == sistrip::FINE_DELAY ) { useFedKey_ = false; } 
00224      
00225       // Dump of FED buffer
00226       if ( edm::isDebugEnabled() ) {
00227         if ( fedEventDumpFreq_ && !(event_%fedEventDumpFreq_) ) {
00228           std::stringstream ss;
00229           buffer->dump( ss );
00230           edm::LogVerbatim(sistrip::mlRawToDigi_) << ss.str();
00231         }
00232       }
00233     
00234       // Iterate through FED channels, extract payload and create Digis
00235       std::vector<FedChannelConnection>::const_iterator iconn = conns.begin();
00236       for ( ; iconn != conns.end(); iconn++ ) {
00237 
00239         uint16_t chan = iconn->fedCh();
00240 
00241         // Check if fed connection is valid
00242         if ( !iconn->isConnected() ) { continue; }
00243         
00244         // Check DetId is valid (if to be used as key)
00245         if ( !useFedKey_ && ( !iconn->detId() || iconn->detId() == sistrip::invalid32_ ) ) { continue; }
00246       
00247         // Check FED channel
00248         if (!buffer->channelGood(iconn->fedCh(),doAPVEmulatorCheck_)) {
00249           if (!unpackBadChannels_ || !(buffer->fePresent(iconn->fedCh()/FEDCH_PER_FEUNIT) && buffer->feEnabled(iconn->fedCh()/FEDCH_PER_FEUNIT)) ) {
00250             detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
00251             continue;
00252           }
00253         }
00254 
00255         // Determine whether FED key is inferred from cabling or channel loop
00256         uint32_t fed_key = ( summary.runType() == sistrip::FED_CABLING ) ? ( ( *ifed & sistrip::invalid_ ) << 16 ) | ( chan & sistrip::invalid_ ) : ( ( iconn->fedId() & sistrip::invalid_ ) << 16 ) | ( iconn->fedCh() & sistrip::invalid_ );
00257 
00258         // Determine whether DetId or FED key should be used to index digi containers
00259         uint32_t key = ( useFedKey_ || mode == sistrip::READOUT_MODE_SCOPE ) ? fed_key : iconn->detId();
00260       
00261         // Determine APV std::pair number (needed only when using DetId)
00262         uint16_t ipair = ( useFedKey_ || mode == sistrip::READOUT_MODE_SCOPE ) ? 0 : iconn->apvPairNumber();
00263       
00264 
00265         if (mode == sistrip::READOUT_MODE_ZERO_SUPPRESSED ) { 
00266         
00267           Registry regItem(key, 0, zs_work_digis_.size(), 0);
00268         
00269           try {
00271             sistrip::FEDZSChannelUnpacker unpacker = sistrip::FEDZSChannelUnpacker::zeroSuppressedModeUnpacker(buffer->channel(iconn->fedCh()));
00272             
00274             
00275             while (unpacker.hasData()) {zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber()+ipair*256,unpacker.adc()));unpacker++;}
00276           } catch (const cms::Exception& e) {
00277             if ( edm::isDebugEnabled() ) {
00278               edm::LogWarning(sistrip::mlRawToDigi_)
00279                 << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00280                 << " Clusters are not ordered for FED "
00281                 << *ifed << " channel " << iconn->fedCh()
00282                 << ": " << e.what();
00283             }
00284             detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
00285             continue;
00286           }
00287           
00288           regItem.length = zs_work_digis_.size() - regItem.index;
00289           if (regItem.length > 0) {
00290             regItem.first = zs_work_digis_[regItem.index].strip();
00291             zs_work_registry_.push_back(regItem);
00292           }
00293 
00294             
00295           // Common mode values
00296           if ( extractCm_ ) {
00297             try {
00298               Registry regItem2( key, 2*ipair, cm_work_digis_.size(), 2 );
00299               cm_work_digis_.push_back( SiStripRawDigi( buffer->channel(iconn->fedCh()).cmMedian(0) ) );
00300               cm_work_digis_.push_back( SiStripRawDigi( buffer->channel(iconn->fedCh()).cmMedian(1) ) );
00301               cm_work_registry_.push_back( regItem2 );
00302             } catch (const cms::Exception& e) {
00303               if ( edm::isDebugEnabled() ) {
00304                 edm::LogWarning(sistrip::mlRawToDigi_)
00305                   << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00306                   << " Problem extracting common modes for FED id "
00307                   << *ifed << " and channel " << iconn->fedCh()
00308                   << ": " << std::endl << e.what();
00309               }
00310             }
00311           }
00312           
00313         }
00314 
00315         else if (mode == sistrip::READOUT_MODE_ZERO_SUPPRESSED_LITE ) { 
00316 
00317           Registry regItem(key, 0, zs_work_digis_.size(), 0);
00318         
00319           try {
00321             sistrip::FEDZSChannelUnpacker unpacker = sistrip::FEDZSChannelUnpacker::zeroSuppressedLiteModeUnpacker(buffer->channel(iconn->fedCh()));
00322             
00324             while (unpacker.hasData()) {zs_work_digis_.push_back(SiStripDigi(unpacker.sampleNumber()+ipair*256,unpacker.adc()));unpacker++;}
00325           } catch (const cms::Exception& e) {
00326             if ( edm::isDebugEnabled() ) {
00327               edm::LogWarning(sistrip::mlRawToDigi_)
00328                 << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00329                 << " Clusters are not ordered for FED "
00330                 << *ifed << " channel " << iconn->fedCh()
00331                 << ": " << e.what();
00332             }
00333             detids.push_back(iconn->detId()); //@@ Possible multiple entries (ok for Giovanni)
00334             continue;
00335           }  
00336 
00337           regItem.length = zs_work_digis_.size() - regItem.index;
00338           if (regItem.length > 0) {
00339             regItem.first = zs_work_digis_[regItem.index].strip();
00340             zs_work_registry_.push_back(regItem);
00341           }
00342           
00343 
00344         } 
00345      
00346         else if ( mode == sistrip::READOUT_MODE_VIRGIN_RAW ) {
00347 
00348           std::vector<uint16_t> samples; 
00349 
00351           sistrip::FEDRawChannelUnpacker unpacker = sistrip::FEDRawChannelUnpacker::virginRawModeUnpacker(buffer->channel(iconn->fedCh()));
00352 
00354           while (unpacker.hasData()) {samples.push_back(unpacker.adc());unpacker++;}
00355 
00356           if ( !samples.empty() ) { 
00357             Registry regItem(key, 256*ipair, virgin_work_digis_.size(), samples.size());
00358             uint16_t physical;
00359             uint16_t readout; 
00360             for ( uint16_t i = 0, n = samples.size(); i < n; i++ ) {
00361               physical = i%128;
00362               readoutOrder( physical, readout );                 // convert index from physical to readout order
00363               (i/128) ? readout=readout*2+1 : readout=readout*2; // un-multiplex data
00364               virgin_work_digis_.push_back(  SiStripRawDigi( samples[readout] ) );
00365             }
00366             virgin_work_registry_.push_back( regItem );
00367           }
00368         } 
00369     
00370         else if ( mode == sistrip::READOUT_MODE_PROC_RAW ) {
00371         
00372           std::vector<uint16_t> samples; 
00373         
00375           sistrip::FEDRawChannelUnpacker unpacker = sistrip::FEDRawChannelUnpacker::procRawModeUnpacker(buffer->channel(iconn->fedCh()));
00376         
00378           while (unpacker.hasData()) {samples.push_back(unpacker.adc());unpacker++;}
00379         
00380           if ( !samples.empty() ) { 
00381             Registry regItem(key, 256*ipair, proc_work_digis_.size(), samples.size());
00382             for ( uint16_t i = 0, n = samples.size(); i < n; i++ ) {
00383               proc_work_digis_.push_back(  SiStripRawDigi( samples[i] ) );
00384             }
00385             proc_work_registry_.push_back( regItem );
00386           }
00387         } 
00388 
00389         else if ( mode == sistrip::READOUT_MODE_SCOPE ) {
00390         
00391           std::vector<uint16_t> samples; 
00392         
00394           sistrip::FEDRawChannelUnpacker unpacker = sistrip::FEDRawChannelUnpacker::scopeModeUnpacker(buffer->channel(iconn->fedCh()));
00395 
00397           while (unpacker.hasData()) {samples.push_back(unpacker.adc());unpacker++;}
00398         
00399           if ( !samples.empty() ) { 
00400             Registry regItem(key, 0, scope_work_digis_.size(), samples.size());
00401             for ( uint16_t i = 0, n = samples.size(); i < n; i++ ) {
00402               scope_work_digis_.push_back(  SiStripRawDigi( samples[i] ) );
00403             }
00404             scope_work_registry_.push_back( regItem );
00405           }
00406         } 
00407         
00408         else { // Unknown readout mode! => assume scope mode
00409 
00410           if ( edm::isDebugEnabled() ) {
00411             std::stringstream ss;
00412             ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00413                << " Unknown FED readout mode (" << mode
00414                << ")! Assuming SCOPE MODE..."; 
00415             edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00416           }
00417         
00418           std::vector<uint16_t> samples; 
00419         
00421           sistrip::FEDRawChannelUnpacker unpacker = sistrip::FEDRawChannelUnpacker::scopeModeUnpacker(buffer->channel(iconn->fedCh()));
00422         
00424           while (unpacker.hasData()) {samples.push_back(unpacker.adc());unpacker++;}
00425         
00426           if ( !samples.empty() ) { 
00427             Registry regItem(key, 0, scope_work_digis_.size(), samples.size());
00428             for ( uint16_t i = 0, n = samples.size(); i < n; i++ ) {
00429               scope_work_digis_.push_back(  SiStripRawDigi( samples[i] ) );
00430             }
00431             scope_work_registry_.push_back( regItem );
00432           
00433             if ( edm::isDebugEnabled() ) {
00434               std::stringstream ss;
00435               ss << "Extracted " << samples.size() 
00436                  << " SCOPE MODE digis (samples[0] = " 
00437                  << samples[0] 
00438                  << ") from FED id/ch " 
00439                  << iconn->fedId() 
00440                  << "/" 
00441                  << iconn->fedCh();
00442               LogTrace("SiStripRawToDigi") << ss.str();
00443             }
00444           }
00445           else if ( edm::isDebugEnabled() ) {
00446             edm::LogWarning(sistrip::mlRawToDigi_)
00447               << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00448               << " No SM digis found!"; 
00449           }
00450         } 
00451       } // channel loop
00452     } // fed loop
00453 
00454     // bad channels warning
00455     unsigned int detIdsSize = detids.size();
00456     if ( edm::isDebugEnabled() && detIdsSize ) {
00457       std::ostringstream ss;
00458       ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00459          << " Problems were found in data and " << detIdsSize << " channels could not be unpacked. "
00460          << "See output of FED Hardware monitoring for more information. ";
00461       edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00462     }
00463     if( (errorThreshold_ != 0) && (detIdsSize > errorThreshold_) ) {
00464       edm::LogError("TooManyErrors") << "Total number of errors = " << detIdsSize;
00465     }
00466 
00467     // update DetSetVectors
00468     update(scope_mode, virgin_raw, proc_raw, zero_suppr, cm_values);
00469 
00470     // increment event counter
00471     event_++;
00472   
00473     // no longer first event!
00474     if ( first_ ) { first_ = false; }
00475   
00476     // final cleanup, just in case
00477     cleanupWorkVectors();
00478   }
00479 
00480   void RawToDigiUnpacker::update( RawDigis& scope_mode, RawDigis& virgin_raw, RawDigis& proc_raw, Digis& zero_suppr, RawDigis& common_mode ) {
00481   
00482     if ( ! zs_work_registry_.empty() ) {
00483       std::sort( zs_work_registry_.begin(), zs_work_registry_.end() );
00484       std::vector< edm::DetSet<SiStripDigi> > sorted_and_merged;
00485       sorted_and_merged.reserve(  std::min(zs_work_registry_.size(), size_t(17000)) );
00486     
00487       bool errorInData = false;
00488       std::vector<Registry>::iterator it = zs_work_registry_.begin(), it2 = it+1, end = zs_work_registry_.end();
00489       while (it < end) {
00490         sorted_and_merged.push_back( edm::DetSet<SiStripDigi>(it->detid) );
00491         std::vector<SiStripDigi> & digis = sorted_and_merged.back().data;
00492         // first count how many digis we have
00493         size_t len = it->length;
00494         for (it2 = it+1; (it2 != end) && (it2->detid == it->detid); ++it2) { len += it2->length; }
00495         // reserve memory 
00496         digis.reserve(len);
00497         // push them in
00498         for (it2 = it+0; (it2 != end) && (it2->detid == it->detid); ++it2) {
00499           digis.insert( digis.end(), & zs_work_digis_[it2->index], & zs_work_digis_[it2->index + it2->length] );
00500         }
00501         it = it2;
00502       }
00503     
00504       // check sorting
00505       if (!__gnu_cxx::is_sorted( sorted_and_merged.begin(), sorted_and_merged.end() )) {
00506         // this is an error in the code: i DID sort it already!
00507         throw cms::Exception("Bug Found") 
00508           << "Container must be already sorted!\nat " 
00509           << __FILE__ 
00510           << ", line " 
00511           << __LINE__ 
00512           <<"\n";
00513       }
00514     
00515       std::vector< edm::DetSet<SiStripDigi> >::iterator iii = sorted_and_merged.begin();
00516       std::vector< edm::DetSet<SiStripDigi> >::iterator jjj = sorted_and_merged.end();
00517       for ( ; iii != jjj; ++iii ) { 
00518         if ( ! __gnu_cxx::is_sorted( iii->begin(), iii->end() ) ) {
00519           // this might be an error in the data, if the raws from one FED are not sorted
00520           iii->clear(); 
00521           errorInData = true;
00522         }
00523       } 
00524     
00525       // output error
00526       if (errorInData) edm::LogWarning("CorruptData") << "Some modules contained corrupted ZS raw data, and have been skipped in unpacking\n";
00527     
00528       // make output DetSetVector
00529       edm::DetSetVector<SiStripDigi> zero_suppr_dsv( sorted_and_merged, true ); 
00530       zero_suppr.swap( zero_suppr_dsv );
00531     } 
00532   
00533     // Populate final DetSetVector container with VR data 
00534     if ( !virgin_work_registry_.empty() ) {
00535 
00536       std::sort( virgin_work_registry_.begin(), virgin_work_registry_.end() );
00537     
00538       std::vector< edm::DetSet<SiStripRawDigi> > sorted_and_merged;
00539       sorted_and_merged.reserve( std::min(virgin_work_registry_.size(), size_t(17000)) );
00540     
00541       bool errorInData = false;
00542       std::vector<Registry>::iterator it = virgin_work_registry_.begin(), it2, end = virgin_work_registry_.end();
00543       while (it < end) {
00544         sorted_and_merged.push_back( edm::DetSet<SiStripRawDigi>(it->detid) );
00545         std::vector<SiStripRawDigi> & digis = sorted_and_merged.back().data;
00546       
00547         bool isDetOk = true; 
00548         // first count how many digis we have
00549         int maxFirstStrip = it->first;
00550         for (it2 = it+1; (it2 != end) && (it2->detid == it->detid); ++it2) { 
00551           // duplicated APV or data corruption. DO NOT 'break' here!
00552           if (it2->first <= maxFirstStrip) { isDetOk = false; continue; } 
00553           maxFirstStrip = it2->first;                           
00554         }
00555         if (!isDetOk) { errorInData = true; it = it2; continue; } // skip whole det
00556       
00557         // make room for 256 * (max_apv_pair + 1) Raw Digis
00558         digis.resize(maxFirstStrip + 256);
00559         // push them in
00560         for (it2 = it+0; (it2 != end) && (it2->detid == it->detid); ++it2) {
00561           // data corruption. DO NOT 'break' here
00562           if (it->length != 256)  { isDetOk = false; continue; } 
00563           std::copy( & virgin_work_digis_[it2->index], & virgin_work_digis_[it2->index + it2->length], & digis[it2->first] );
00564         }
00565         if (!isDetOk) { errorInData = true; digis.clear(); it = it2; continue; } // skip whole det
00566         it = it2;
00567       }
00568     
00569       // output error
00570       if (errorInData) edm::LogWarning("CorruptData") << "Some modules contained corrupted virgin raw data, and have been skipped in unpacking\n"; 
00571     
00572       // check sorting
00573       if ( !__gnu_cxx::is_sorted( sorted_and_merged.begin(), sorted_and_merged.end()  ) ) {
00574         // this is an error in the code: i DID sort it already!
00575         throw cms::Exception("Bug Found") 
00576           << "Container must be already sorted!\nat " 
00577           << __FILE__ 
00578           << ", line " 
00579           << __LINE__ 
00580           <<"\n";
00581       }
00582     
00583       // make output DetSetVector
00584       edm::DetSetVector<SiStripRawDigi> virgin_raw_dsv( sorted_and_merged, true ); 
00585       virgin_raw.swap( virgin_raw_dsv );
00586     }
00587   
00588     // Populate final DetSetVector container with VR data 
00589     if ( !proc_work_registry_.empty() ) {
00590       std::sort( proc_work_registry_.begin(), proc_work_registry_.end() );
00591     
00592       std::vector< edm::DetSet<SiStripRawDigi> > sorted_and_merged;
00593       sorted_and_merged.reserve( std::min(proc_work_registry_.size(), size_t(17000)) );
00594     
00595       bool errorInData = false;
00596       std::vector<Registry>::iterator it = proc_work_registry_.begin(), it2, end = proc_work_registry_.end();
00597       while (it < end) {
00598         sorted_and_merged.push_back( edm::DetSet<SiStripRawDigi>(it->detid) );
00599         std::vector<SiStripRawDigi> & digis = sorted_and_merged.back().data;
00600       
00601         bool isDetOk = true; 
00602         // first count how many digis we have
00603         int maxFirstStrip = it->first;
00604         for (it2 = it+1; (it2 != end) && (it2->detid == it->detid); ++it2) { 
00605           // duplicated APV or data corruption. DO NOT 'break' here!
00606           if (it2->first <= maxFirstStrip) { isDetOk = false; continue; } 
00607           maxFirstStrip = it2->first;                           
00608         }
00609         // skip whole det
00610         if (!isDetOk) { errorInData = true; it = it2; continue; } 
00611       
00612         // make room for 256 * (max_apv_pair + 1) Raw Digis
00613         digis.resize(maxFirstStrip + 256);
00614         // push them in
00615         for (it2 = it+0; (it2 != end) && (it2->detid == it->detid); ++it2) {
00616           // data corruption. DO NOT 'break' here
00617           if (it->length != 256)  { isDetOk = false; continue; } 
00618           std::copy( & proc_work_digis_[it2->index], & proc_work_digis_[it2->index + it2->length], & digis[it2->first] );
00619         }
00620         // skip whole det
00621         if (!isDetOk) { errorInData = true; digis.clear(); it = it2; continue; } 
00622         it = it2;
00623       }
00624     
00625       // output error
00626       if (errorInData) edm::LogWarning("CorruptData") << "Some modules contained corrupted proc raw data, and have been skipped in unpacking\n";
00627     
00628       // check sorting
00629       if ( !__gnu_cxx::is_sorted( sorted_and_merged.begin(), sorted_and_merged.end()  ) ) {
00630         // this is an error in the code: i DID sort it already!
00631         throw cms::Exception("Bug Found") 
00632           << "Container must be already sorted!\nat " 
00633           << __FILE__ 
00634           << ", line " 
00635           << __LINE__ 
00636           <<"\n";
00637       }
00638     
00639       // make output DetSetVector
00640       edm::DetSetVector<SiStripRawDigi> proc_raw_dsv( sorted_and_merged, true ); 
00641       proc_raw.swap( proc_raw_dsv );
00642     }
00643   
00644     // Populate final DetSetVector container with SM data 
00645     if ( !scope_work_registry_.empty() ) {
00646       std::sort( scope_work_registry_.begin(), scope_work_registry_.end() );
00647     
00648       std::vector< edm::DetSet<SiStripRawDigi> > sorted_and_merged;
00649       sorted_and_merged.reserve( scope_work_registry_.size() );
00650     
00651       bool errorInData = false;
00652       std::vector<Registry>::iterator it, end;
00653       for (it = scope_work_registry_.begin(), end = scope_work_registry_.end() ; it != end; ++it) {
00654         sorted_and_merged.push_back( edm::DetSet<SiStripRawDigi>(it->detid) );
00655         std::vector<SiStripRawDigi> & digis = sorted_and_merged.back().data;
00656         digis.insert( digis.end(), & scope_work_digis_[it->index], & scope_work_digis_[it->index + it->length] );
00657       
00658         if ( (it +1 != end) && (it->detid == (it+1)->detid) ) {
00659           errorInData = true; 
00660           // let's skip *all* the detsets for that key, as we don't know which is the correct one!
00661           do { ++it; } while ( ( it+1 != end) && (it->detid == (it+1)->detid) );
00662         }
00663       }
00664 
00665       // output error
00666       if (errorInData) edm::LogWarning("CorruptData") << "Some fed keys contained corrupted scope mode data, and have been skipped in unpacking\n"; 
00667 
00668       // check sorting
00669       if ( !__gnu_cxx::is_sorted( sorted_and_merged.begin(), sorted_and_merged.end()  ) ) {
00670         // this is an error in the code: i DID sort it already!
00671         throw cms::Exception("Bug Found") 
00672           << "Container must be already sorted!\nat " 
00673           << __FILE__ 
00674           << ", line " 
00675           << __LINE__ 
00676           <<"\n";
00677       }
00678 
00679       // make output DetSetVector
00680       edm::DetSetVector<SiStripRawDigi> scope_mode_dsv( sorted_and_merged, true ); 
00681       scope_mode.swap( scope_mode_dsv );
00682     }
00683 
00684     // Populate DetSetVector with Common Mode values 
00685     if ( extractCm_ ) {
00686 
00687       // Populate final DetSetVector container with VR data 
00688       if ( !cm_work_registry_.empty() ) {
00689 
00690         std::sort( cm_work_registry_.begin(), cm_work_registry_.end() );
00691     
00692         std::vector< edm::DetSet<SiStripRawDigi> > sorted_and_merged;
00693         sorted_and_merged.reserve( std::min(cm_work_registry_.size(), size_t(17000)) );
00694     
00695         bool errorInData = false;
00696         std::vector<Registry>::iterator it = cm_work_registry_.begin(), it2, end = cm_work_registry_.end();
00697         while (it < end) {
00698           sorted_and_merged.push_back( edm::DetSet<SiStripRawDigi>(it->detid) );
00699           std::vector<SiStripRawDigi> & digis = sorted_and_merged.back().data;
00700       
00701           bool isDetOk = true; 
00702           // first count how many digis we have
00703           int maxFirstStrip = it->first;
00704           for (it2 = it+1; (it2 != end) && (it2->detid == it->detid); ++it2) { 
00705             // duplicated APV or data corruption. DO NOT 'break' here!
00706             if (it2->first <= maxFirstStrip) { isDetOk = false; continue; } 
00707             maxFirstStrip = it2->first;                           
00708           }
00709           if (!isDetOk) { errorInData = true; it = it2; continue; } // skip whole det
00710           
00711           // make room for 2 * (max_apv_pair + 1) Common mode values
00712           digis.resize(maxFirstStrip + 2);
00713           // push them in
00714           for (it2 = it+0; (it2 != end) && (it2->detid == it->detid); ++it2) {
00715             // data corruption. DO NOT 'break' here
00716             if (it->length != 2)  { isDetOk = false; continue; } 
00717             std::copy( & cm_work_digis_[it2->index], & cm_work_digis_[it2->index + it2->length], & digis[it2->first] );
00718           }
00719           if (!isDetOk) { errorInData = true; digis.clear(); it = it2; continue; } // skip whole det
00720           it = it2;
00721         }
00722     
00723         // output error
00724         if (errorInData) edm::LogWarning("CorruptData") << "Some modules contained corrupted common mode data, and have been skipped in unpacking\n"; 
00725     
00726         // check sorting
00727         if ( !__gnu_cxx::is_sorted( sorted_and_merged.begin(), sorted_and_merged.end()  ) ) {
00728           // this is an error in the code: i DID sort it already!
00729           throw cms::Exception("Bug Found") 
00730             << "Container must be already sorted!\nat " 
00731             << __FILE__ 
00732             << ", line " 
00733             << __LINE__ 
00734             <<"\n";
00735         }
00736     
00737         // make output DetSetVector
00738         edm::DetSetVector<SiStripRawDigi> common_mode_dsv( sorted_and_merged, true ); 
00739         common_mode.swap( common_mode_dsv );
00740       }
00741       
00742     }
00743     
00744   }
00745   
00746   void RawToDigiUnpacker::cleanupWorkVectors() {
00747     // Clear working areas and registries
00748     zs_work_registry_.clear();      zs_work_digis_.clear();
00749     virgin_work_registry_.clear();  virgin_work_digis_.clear();
00750     proc_work_registry_.clear();    proc_work_digis_.clear();
00751     scope_work_registry_.clear();   scope_work_digis_.clear();
00752     cm_work_registry_.clear();      cm_work_digis_.clear();
00753   }
00754 
00755   void RawToDigiUnpacker::triggerFed( const FEDRawDataCollection& buffers, SiStripEventSummary& summary, const uint32_t& event ) {
00756   
00757     // Pointer to data (recast as 32-bit words) and number of 32-bit words
00758     uint32_t* data_u32 = 0;
00759     uint32_t  size_u32 = 0;
00760   
00761     // Search mode
00762     if ( triggerFedId_ < 0 ) { 
00763     
00764       uint16_t ifed = 0;
00765       while ( triggerFedId_ < 0 && 
00766               ifed < 1 + FEDNumbering::lastFEDId() ) {
00767         const FEDRawData& trigger_fed = buffers.FEDData( ifed );
00768         if ( trigger_fed.data() && trigger_fed.size() ) {
00769           uint8_t*  temp = const_cast<uint8_t*>( trigger_fed.data() );
00770           data_u32 = reinterpret_cast<uint32_t*>( temp ) + sizeof(fedh_t)/sizeof(uint32_t) + 1;
00771           size_u32 = trigger_fed.size()/sizeof(uint32_t) - sizeof(fedh_t)/sizeof(uint32_t) - 1;
00772           fedt_t* fed_trailer = reinterpret_cast<fedt_t*>( temp + trigger_fed.size() - sizeof(fedt_t) );
00773           if ( fed_trailer->conscheck == 0xDEADFACE ) { 
00774             triggerFedId_ = ifed; 
00775             if ( edm::isDebugEnabled() ) {
00776               std::stringstream ss;
00777               ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00778                  << " Search mode for 'trigger FED' activated!"
00779                  << " Found 'trigger FED' info with id " << triggerFedId_;
00780               LogTrace("SiStripRawToDigi") << ss.str();
00781             }
00782           }
00783         }
00784         ifed++;
00785       }
00786       if ( triggerFedId_ < 0 ) {
00787         triggerFedId_ = 0;
00788         if ( edm::isDebugEnabled() ) {
00789           std::stringstream ss;
00790           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00791              << " Search mode for 'trigger FED' activated!"
00792              << " 'Trigger FED' info not found!";
00793           edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00794         }
00795       }  
00796     } 
00797 
00798     // "Trigger FED" id given in .cfg file
00799     else if ( triggerFedId_ > 0 ) { 
00800     
00801       const FEDRawData& trigger_fed = buffers.FEDData( triggerFedId_ );
00802       if ( trigger_fed.data() && trigger_fed.size() ) {
00803         uint8_t*  temp = const_cast<uint8_t*>( trigger_fed.data() );
00804         data_u32 = reinterpret_cast<uint32_t*>( temp ) + sizeof(fedh_t)/sizeof(uint32_t) + 1;
00805         size_u32 = trigger_fed.size()/sizeof(uint32_t) - sizeof(fedh_t)/sizeof(uint32_t) - 1;
00806         fedt_t* fed_trailer = reinterpret_cast<fedt_t*>( temp + trigger_fed.size() - sizeof(fedt_t) );
00807         if ( fed_trailer->conscheck != 0xDEADFACE ) { 
00808           if ( edm::isDebugEnabled() ) {
00809             edm::LogWarning(sistrip::mlRawToDigi_) 
00810               << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00811               << " Unexpected stamp found in DAQ trailer (ie, not 0xDEADFACE)!"
00812               << " Buffer appears not to contain 'trigger FED' data!";
00813           }
00814           triggerFedId_ = 0; 
00815         }
00816       }
00817       
00818     } else { 
00819       triggerFedId_ = 0; 
00820       data_u32 = 0;
00821       size_u32 = 0;
00822     }
00823   
00824     // Populate summary object with commissioning information
00825     if ( triggerFedId_ > 0 ) { 
00826 
00827       // Some checks
00828       if ( !data_u32 ) {
00829         if ( edm::isDebugEnabled() ) {
00830           std::stringstream ss;
00831           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00832              << " NULL pointer to 'trigger FED' data";
00833           edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00834         }
00835         return;
00836       } 
00837       if ( size_u32 < sizeof(TFHeaderDescription)/sizeof(uint32_t) ) {
00838         if ( edm::isDebugEnabled() ) {
00839           std::stringstream ss;
00840           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00841              << " Unexpected 'Trigger FED' data size [32-bit words]: " << size_u32;
00842           edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00843         }
00844         return;
00845       }
00846     
00847       // Write event-specific data to event
00848       TFHeaderDescription* header = (TFHeaderDescription*) data_u32;
00849       summary.event( static_cast<uint32_t>( header->getFedEventNumber()) );
00850       summary.bx( static_cast<uint32_t>( header->getBunchCrossing()) );
00851     
00852       // Write commissioning information to event 
00853       uint32_t hsize = sizeof(TFHeaderDescription)/sizeof(uint32_t);
00854       uint32_t* head = &data_u32[hsize];
00855       summary.commissioningInfo( head, event );
00856       summary.triggerFed( triggerFedId_ );
00857     
00858     }
00859 
00860     // Some debug
00861     if ( summary.isSet() && once_ ) {
00862       if ( edm::isDebugEnabled() ) {
00863         std::stringstream ss;
00864         ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00865            << " EventSummary built from \"trigger FED\":" 
00866            << std::endl << summary;
00867         LogTrace("SiStripRawToDigi") << ss.str();
00868       }
00869       once_ = false;
00870     }
00871   }
00872 
00873   void RawToDigiUnpacker::locateStartOfFedBuffer( const uint16_t& fed_id, const FEDRawData& input, FEDRawData& output ) {
00874   
00875     // Check size of input buffer
00876     if ( input.size() < 24 ) { 
00877       output.resize( input.size() ); // Return UNadjusted buffer start position and size
00878       memcpy( output.data(), input.data(), input.size() );
00879       if ( edm::isDebugEnabled() ) {
00880         std::stringstream ss; 
00881         ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "] "
00882            << "Input FEDRawData with FED id " << fed_id 
00883            << " has size " << input.size();
00884         edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
00885       }
00886       return;
00887     } 
00888   
00889     // Iterator through buffer to find DAQ header 
00890     bool found = false;
00891     uint16_t ichar = 0;
00892     while ( ichar < input.size()-16 && !found ) {
00893       uint16_t offset = headerBytes_ < 0 ? ichar : headerBytes_; // Negative value means use "search mode" to find DAQ header
00894       uint32_t* input_u32   = reinterpret_cast<uint32_t*>( const_cast<unsigned char*>( input.data() ) + offset );
00895       uint32_t* fed_trailer = reinterpret_cast<uint32_t*>( const_cast<unsigned char*>( input.data() ) + input.size() - 8 );
00896     
00897       // see info on FED 32-bit swapping at end-of-file
00898 
00899       bool old_vme_header = ( input_u32[0] & 0xF0000000 ) == 0x50000000 && ( fed_trailer[0]  & 0xF0000000 ) == 0xA0000000 && ( (fed_trailer[0] & 0x00FFFFFF)*0x8 ) == (input.size() - offset);
00900     
00901       bool old_slink_header = ( input_u32[1] & 0xF0000000 ) == 0x50000000 && ( fed_trailer[1]  & 0xF0000000 ) == 0xA0000000 && ( (fed_trailer[1] & 0x00FFFFFF)*0x8 ) == (input.size() - offset);
00902     
00903       bool old_slink_payload = ( input_u32[3] & 0xFF000000 ) == 0xED000000;
00904     
00905       bool new_buffer_format = ( input_u32[2] & 0xFF000000 ) == 0xC5000000;
00906     
00907       if ( old_vme_header )  {
00908       
00909         // Found DAQ header at byte position 'offset'
00910         found = true;
00911         output.resize( input.size()-offset );
00912         memcpy( output.data(),         // target
00913                 input.data()+offset,   // source
00914                 input.size()-offset ); // nbytes
00915         if ( headerBytes_ < 0 ) {
00916           if ( edm::isDebugEnabled() ) {
00917             std::stringstream ss;
00918             ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]" 
00919                << " Buffer for FED id " << fed_id 
00920                << " has been found at byte position " << offset
00921                << " with a size of " << input.size()-offset << " bytes."
00922                << " Adjust the configurable 'AppendedBytes' to " << offset;
00923             LogTrace("SiStripRawToDigi") << ss.str();
00924           }
00925         }
00926       
00927       } else if ( old_slink_header ) {
00928       
00929         if ( old_slink_payload ) {
00930       
00931           // Found DAQ header (with MSB and LSB 32-bit words swapped) at byte position 'offset' 
00932           found = true;
00933           output.resize( input.size()-offset );
00934           uint32_t* output_u32 = reinterpret_cast<uint32_t*>( const_cast<unsigned char*>( output.data() ) );
00935           uint16_t iter = offset; 
00936           while ( iter < output.size() / sizeof(uint32_t) ) {
00937             output_u32[iter] = input_u32[iter+1];
00938             output_u32[iter+1] = input_u32[iter];
00939             iter+=2;
00940           }
00941           if ( headerBytes_ < 0 ) {
00942             if ( edm::isDebugEnabled() ) {
00943               std::stringstream ss;
00944               ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]" 
00945                  << " Buffer (with MSB and LSB 32-bit words swapped) for FED id " << fed_id 
00946                  << " has been found at byte position " << offset
00947                  << " with a size of " << output.size() << " bytes."
00948                  << " Adjust the configurable 'AppendedBytes' to " << offset;
00949               LogTrace("SiStripRawToDigi") << ss.str();
00950             }
00951           }
00952 
00953         } else if ( new_buffer_format ) {
00954         
00955           // Found DAQ header at byte position 'offset'
00956           found = true;
00957           output.resize( input.size()-offset );
00958           memcpy( output.data(),         // target
00959                   input.data()+offset,   // source
00960                   input.size()-offset ); // nbytes
00961           if ( headerBytes_ < 0 ) {
00962             if ( edm::isDebugEnabled() ) {
00963               std::stringstream ss;
00964               ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]" 
00965                  << " Buffer for FED id " << fed_id 
00966                  << " has been found at byte position " << offset
00967                  << " with a size of " << input.size()-offset << " bytes."
00968                  << " Adjust the configurable 'AppendedBytes' to " << offset;
00969               LogTrace("SiStripRawToDigi") << ss.str();
00970             }
00971           }
00972         
00973         } else { headerBytes_ < 0 ? found = false : found = true; }
00974       } else { headerBytes_ < 0 ? found = false : found = true; }
00975       ichar++;
00976     }      
00977   
00978     // Check size of output buffer
00979     if ( output.size() == 0 ) { 
00980     
00981       // Did not find DAQ header after search => return buffer with null size
00982       output.resize( 0 ); //@@ NULL SIZE
00983       memcpy( output.data(), input.data(), 0 ); //@@ NULL SIZE
00984       if ( edm::isDebugEnabled() ) {
00985         std::stringstream ss;
00986         if ( headerBytes_ < 0 ) {
00987           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00988              << " DAQ header not found within buffer for FED id: " << fed_id;
00989         } else {
00990           uint32_t* input_u32 = reinterpret_cast<uint32_t*>( const_cast<unsigned char*>( input.data() ) );
00991           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
00992              << " DAQ header not found at expected location for FED id: " << fed_id << std::endl
00993              << " First 64-bit word of buffer is 0x"
00994              << std::hex 
00995              << std::setfill('0') << std::setw(8) << input_u32[0] 
00996              << std::setfill('0') << std::setw(8) << input_u32[1] 
00997              << std::dec << std::endl
00998              << " Adjust 'AppendedBytes' configurable to '-1' to activate 'search mode'";
00999         }
01000         edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
01001       }
01002     
01003     } else if ( output.size() < 24 ) { // Found DAQ header after search, but too few words
01004     
01005       if ( edm::isDebugEnabled() ) {
01006         std::stringstream ss; 
01007         ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
01008            << " Unexpected buffer size! FEDRawData with FED id " << fed_id 
01009            << " has size " << output.size();
01010         edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
01011       }
01012     }   
01013   }
01014 
01015   void RawToDigiUnpacker::updateEventSummary( const sistrip::FEDBuffer& fed, SiStripEventSummary& summary ) {
01016   
01017     // Retrieve contents of DAQ registers
01018 
01019     sistrip::FEDDAQEventType readout_mode = fed.daqEventType(); 
01020     uint32_t daq1 = sistrip::invalid32_;
01021     uint32_t daq2 = sistrip::invalid32_;
01022 
01023     if (fed.headerType() == sistrip::HEADER_TYPE_FULL_DEBUG) {
01024       const sistrip::FEDFullDebugHeader* header = 0;
01025       header = dynamic_cast<const sistrip::FEDFullDebugHeader*>(fed.feHeader());
01026       daq1 = static_cast<uint32_t>( header->daqRegister() ); 
01027       daq2 = static_cast<uint32_t>( header->daqRegister2() ); 
01028     }
01029 
01030   
01031     // If FED DAQ registers contain info, update (and possibly overwrite) EventSummary 
01032     if ( daq1 != 0 && daq1 != sistrip::invalid32_ ) {
01033     
01034       summary.triggerFed( triggerFedId_ );
01035       summary.fedReadoutMode( readout_mode );
01036       summary.commissioningInfo( daq1, daq2 );
01037     
01038       if ( summary.isSet() && once_ ) {
01039         if ( edm::isDebugEnabled() ) {
01040           std::stringstream ss;
01041           ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
01042              << " EventSummary built from FED DAQ registers:"
01043              << std::endl << summary;
01044           LogTrace("SiStripRawToDigi") << ss.str();
01045         }
01046         once_ = false;
01047       }
01048     }
01049   }
01050 
01051   void RawToDigiUnpacker::dumpRawData( uint16_t fed_id, const FEDRawData& buffer, std::stringstream& ss ) {
01052 
01053     ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
01054        << " Dump of buffer for FED id " <<  fed_id << std::endl
01055        << " Buffer contains " << buffer.size()
01056        << " bytes (NB: payload is byte-swapped)" << std::endl;
01057     uint32_t* buffer_u32 = reinterpret_cast<uint32_t*>( const_cast<unsigned char*>( buffer.data() ) );
01058     unsigned int empty = 0;
01059 
01060     if ( 0 ) { 
01061 
01062       ss << "Byte->   4 5 6 7 0 1 2 3\n";
01063       for ( uint32_t i = 0; i < buffer.size()/8; i++ ) {
01064         unsigned int temp0 = buffer_u32[i*2] & sistrip::invalid32_;
01065         unsigned int temp1 = buffer_u32[i*2+1] & sistrip::invalid32_;
01066         if ( !temp0 && !temp1 ) { empty++; }
01067         else { 
01068           if ( empty ) { 
01069             ss << "        [ empty  words ]" << std::endl; 
01070             empty = 0; 
01071           }
01072           ss << std::dec
01073              << std::setfill(' ')  << std::setw(6) << i*8 << ": " 
01074              << std::hex 
01075              << std::setfill('0') << std::setw(8) << temp0 
01076              << std::setfill('0') << std::setw(8) << temp1 
01077              << std::dec
01078              << std::endl;
01079         }
01080       }
01081 
01082     } else {
01083     
01084       ss << "  Byte |  <---- Byte order ----<  | Byte" << std::endl;
01085       ss << "  cntr |  7  6  5  4  3  2  1  0  | cntr" << std::endl;
01086       for ( uint32_t i = 0; i < buffer.size()/8; i++ ) {
01087         //if ( i>=20 && ((i+4)<(buffer.size()/8)) ) { continue; }
01088         uint16_t tmp0 = buffer.data()[i*8+0] & 0xFF;
01089         uint16_t tmp1 = buffer.data()[i*8+1] & 0xFF;
01090         uint16_t tmp2 = buffer.data()[i*8+2] & 0xFF;
01091         uint16_t tmp3 = buffer.data()[i*8+3] & 0xFF;
01092         uint16_t tmp4 = buffer.data()[i*8+4] & 0xFF;
01093         uint16_t tmp5 = buffer.data()[i*8+5] & 0xFF;
01094         uint16_t tmp6 = buffer.data()[i*8+6] & 0xFF;
01095         uint16_t tmp7 = buffer.data()[i*8+7] & 0xFF;
01096 //      if ( !tmp0 && !tmp1 && !tmp2 && !tmp3 &&
01097 //           !tmp4 && !tmp5 && !tmp6 && !tmp7 ) { empty++; }
01098 //      else { 
01099 //        if ( empty ) { 
01100 //          ss << "         [.." 
01101 //             << std::dec << std::setfill('.') << std::setw(4) << empty 
01102 //             << " null words....]" << std::endl; 
01103 //          empty = 0; 
01104 //        }
01105           ss << std::dec
01106              << std::setfill(' ')  << std::setw(6) << i*8+7 << " : " 
01107              << std::hex 
01108              << std::setfill('0') << std::setw(2) << tmp7 << " " 
01109              << std::setfill('0') << std::setw(2) << tmp6 << " " 
01110              << std::setfill('0') << std::setw(2) << tmp5 << " " 
01111              << std::setfill('0') << std::setw(2) << tmp4 << " " 
01112              << std::setfill('0') << std::setw(2) << tmp3 << " " 
01113              << std::setfill('0') << std::setw(2) << tmp2 << " " 
01114              << std::setfill('0') << std::setw(2) << tmp1 << " " 
01115              << std::setfill('0') << std::setw(2) << tmp0 
01116              << std::dec
01117              << " :" << std::setfill(' ')  << std::setw(6) << i*8 
01118              << std::endl;
01119 //      }
01120       }
01121 
01122     }
01123     ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
01124        << " End of FED buffer";
01125   }
01126 
01127   void RawToDigiUnpacker::handleException( std::string method_name, std::string extra_info ) { 
01128 
01129     method_name = "sistrip::RawToDigiUnpacker::" + method_name;
01130     try {
01131       throw; // rethrow caught exception to be dealt with below
01132     } 
01133     catch ( const cms::Exception& e ) { 
01134       //throw e; // rethrow cms::Exception to be caught by framework
01135     }
01136     catch ( const std::exception& e ) {
01137       if ( edm::isDebugEnabled() ) {
01138         std::stringstream ss;
01139         ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
01140            << " Caught std::exception!" << std::endl;
01141         if ( extra_info != "" ) { 
01142           ss << " Information: " << extra_info << std::endl;
01143         }
01144         ss << " Caught std::exception in ["
01145            << method_name << "] with message:" << std::endl 
01146            << e.what();
01147         edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
01148       }
01149       //throw cms::Exception(sistrip::mlRawToDigi_) << ss.str();
01150     }
01151     catch (...) {
01152       if ( edm::isDebugEnabled() ) {
01153         std::stringstream ss;
01154         ss << "[sistrip::RawToDigiUnpacker::" << __func__ << "]"
01155            << " Caught unknown exception!" << std::endl;
01156         if ( extra_info != "" ) { 
01157           ss << " Information: " << extra_info << std::endl;
01158         }
01159         ss << "Caught unknown exception in ["
01160            << method_name << "]" << std::endl;
01161         edm::LogWarning(sistrip::mlRawToDigi_) << ss.str();
01162       }
01163       //throw cms::Exception(sistrip::mlRawToDigi_) << ss.str();
01164     }
01165   }
01166 
01167 }
01168 
01169 /*
01170   
01171 Some info on FED buffer 32-bit word swapping. 
01172 
01173 Table below indicates if data are swapped relative to the "old"
01174 VME format (as originally expected by the Fed9UEvent class).
01175 
01176 -------------------------------------------
01177 | SWAPPED?    |         DATA FORMAT       |
01178 | (wrt "OLD") | OLD (0xED)  | NEW (0xC5)  |
01179 |             | VME | SLINK | VME | SLINK |
01180 -------------------------------------------
01181 | DAQ HEADER  |  N  |   Y   |  Y  |   Y   |
01182 | TRK HEADER  |  N  |   Y   |  N  |   N   |
01183 | PAYLOAD     |  N  |   Y   |  N  |   N   |
01184 | DAQ TRAILER |  N  |   Y   |  Y  |   Y   |
01185 -------------------------------------------
01186 
01187 So, in code, we check in code order of bytes in DAQ header/trailer only:
01188 -> if "old_vme_header",           then old format read out via vme, so do nothing.
01189 -> else if "old_slink_header",    then data may be wrapped, so check additionally the TRK header:
01190 ---> if "old_slink_payload",       then old format read out via slink, so swap all data;
01191 ---> else if "new_buffer_format",  then new format, handled internally by Fed9UEvent, so do nothing.
01192 
01193 Pattern matching to find DAQ and tracker headers, and DAQ trailer:
01194 DAQ header,  4 bits, in field  |BOE_1|      with value 0x5
01195 DAQ trailer, 4 bits, in field  |EOE_1|      with value 0xA
01196 TRK header,  8 bits, in field  |Hdr format| with value 0xED or 0xC5
01197 
01198 -------------------------------------------------------------------------------------------
01199 | SWAPPED?    |                                 DATA FORMAT                               |
01200 | (wrt "OLD") |               OLD (0xED)            |               NEW (0xC5)            |
01201 |             |       VME        |      SLINK       |       VME        |      SLINK       |
01202 -------------------------------------------------------------------------------------------
01203 | DAQ HEADER  | ........5....... | 5............... | 5............... | 5............... |
01204 | TRK HEADER  | ........ED...... | ED.............. | ........C5...... | ........C5...... |
01205 | PAYLOAD     | ..........EA.... | ..EA............ | ..EA............ | ............EA.. | 
01206 | DAQ TRAILER | ........A....... | A............... | A............... | A............... |
01207 -------------------------------------------------------------------------------------------
01208 
01209 */