CMS 3D CMS Logo

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