Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-06 07:38:10

0001 /*
0002  */
0003 
0004 #ifndef EVENT_SELECT_H
0005 #define EVENT_SELECT_H
0006 
0007 #include <cinttypes>
0008 #include <ctime>
0009 #include <fstream>
0010 #include <iostream>
0011 #include <list>
0012 #include <map>
0013 #include <memory>
0014 #include <sys/time.h>
0015 #include <vector>
0016 
0017 #include "FWCore/Framework/interface/Frameworkfwd.h"
0018 #include "FWCore/Framework/interface/one/EDAnalyzer.h"
0019 #include "FWCore/Utilities/interface/InputTag.h"
0020 
0021 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0022 #include "DataFormats/Provenance/interface/LuminosityBlockID.h"
0023 #include "DataFormats/Provenance/interface/RunID.h"
0024 
0025 /**
0026  * This module is used to classify events of laser sequence acquired in 
0027  * a global run. 
0028  * Sorting: Events are grouped by bunch of consecutive events from the same 
0029  * FED. A file of such a bunch of events is identified by the FED or ECAL
0030  * sector and the luminosity block id of the first event.
0031  * 
0032  * Sorting strategy:
0033  * It is assumes that:
0034  * - one sequence FED does not overlap more than
0035  *   two lumi blocks. 
0036  * - lumi blocks are read in order
0037  * A FED file will be closed as soon as one event 2 lumi block ahead
0038  * from the first event feed in the file is read.
0039  *
0040  * File completion: while being feeding, .part is appended at the end of 
0041  * the each output file.Once a file is completed (see above), it is renamed
0042  * without the enclosing .part suffix.
0043  */
0044 class LaserSorter : public edm::one::EDAnalyzer<edm::one::WatchRuns> {
0045   //inner classes
0046 private:
0047   struct IndexRecord {
0048     uint32_t orbit;
0049     uint32_t filePos;
0050     bool operator<(const IndexRecord& i) const { return orbit < i.orbit; }
0051   };
0052 
0053   class OutStreamRecord {
0054   public:
0055     //default ctor
0056     OutStreamRecord(int fedId__,
0057                     edm::LuminosityBlockNumber_t startingLumiBlock__,
0058                     std::ofstream* out__,
0059                     std::string& tmpFileName__,
0060                     std::string& finalFileName__)
0061         : fedId_(fedId__),
0062           startingLumiBlock_(startingLumiBlock__),
0063           out_(out__),
0064           tmpFileName_(tmpFileName__),
0065           finalFileName_(finalFileName__),
0066           indexError_(false) {
0067       indices_.reserve(indexReserve_);
0068     }
0069 
0070     int fedId() const { return fedId_; }
0071     edm::LuminosityBlockNumber_t startingLumiBlock() const { return startingLumiBlock_; }
0072     std::ofstream* out() const { return out_.get(); }
0073     std::string finalFileName() const { return finalFileName_; }
0074     std::string tmpFileName() const { return tmpFileName_; }
0075     std::vector<IndexRecord>* indices() { return &indices_; }
0076 
0077     /** Gets the list of orbits to skip. Used to update an existing file:
0078      * orbits of events already present in the file are excluded.
0079      * @return the list of orbits to skip.
0080      */
0081     std::set<uint32_t>& excludedOrbit() { return excludedOrbit_; }
0082 
0083   private:
0084     int fedId_;
0085     edm::LuminosityBlockNumber_t startingLumiBlock_;
0086     std::unique_ptr<std::ofstream> out_;
0087     std::string tmpFileName_;
0088     std::string finalFileName_;
0089     const static std::string emptyString_;
0090 
0091     /** Index table. This map is used to index the events in the file
0092      * according to their orbit id. An index table is stored at the end
0093      * of the output files.
0094      */
0095     std::vector<IndexRecord> indices_;
0096 
0097     /** List of orbits to skip. Used to update an existing file: orbits
0098      * of events already present in the file are excluded. 
0099      */
0100     std::set<uint32_t> excludedOrbit_;
0101 
0102     /** Used to invalidate index table in case a problem preventing
0103      * indexing is encountered: in principle non unicity of the orbit id.
0104      */
0105     bool indexError_;
0106 
0107     /** Initial memory allocation for index table (see vector::reserve()).
0108      */
0109     static const size_t indexReserve_;
0110   };
0111 
0112   //typedefs:
0113 private:
0114   typedef std::list<std::unique_ptr<OutStreamRecord>> OutStreamList;
0115 
0116   //ctors/dtors
0117 public:
0118   LaserSorter(const edm::ParameterSet&);
0119   ~LaserSorter() override;
0120 
0121   //methods
0122 public:
0123   void analyze(const edm::Event&, const edm::EventSetup&) override;
0124   void endJob() override;
0125   void beginJob() override;
0126   void beginRun(edm::Run const&, edm::EventSetup const&) override;
0127   void endRun(edm::Run const&, edm::EventSetup const&) override;
0128 
0129 private:
0130   int dcc2Lme(int dccNum, int dccSide);
0131 
0132   /** Retrieves the orbit ID from DCC headers. The first header found is used.
0133    * @rawdata the raw data where to read the orbit id.
0134    * @return the event orbit ID or -1 if it was not found
0135    */
0136   int getOrbitFromDcc(const edm::Handle<FEDRawDataCollection>& rawdata) const;
0137 
0138   /** Retrieve detailed trigger type (trigger type, DCC, side) from raw event
0139    * @param rawdata FED data collection
0140    * @param proba if not null used to store the maximum of occurence frequency
0141    * of the detailed trigger types (DTT) appearing in each DCC block. In normal
0142    * condition every DCC indicated the same DTT and this value is 1.
0143    * @return detailed trigger type. In case of descripancy between the DCCs, the
0144    * most frequent value is returned if it covers more than 80% of the present DCC
0145    * blocks, -1 is returned otherwise. If event does not contain any ECAL data
0146    * -2 is returned.
0147    */
0148   int getDetailedTriggerType(const edm::Handle<FEDRawDataCollection>& rawdata, double* proba = nullptr);
0149 
0150   /** Closes output stream 2 lumi block older than the input 'lumiBlock' ID.
0151    * @param lumiBlock ID of the reference luminosity block.
0152    */
0153   void closeOldStreams(edm::LuminosityBlockNumber_t lumiBlock);
0154 
0155   /** Closes all opened output streams.
0156    */
0157   void closeAllStreams();
0158 
0159   /** Gets and eventually creates the output stream for writing the events 
0160    * of a given FED and luminosity block.
0161    * @param fedId ID of the FED the event is issued from
0162    * @param lumiBlock luminositu block of the event
0163    * @return pointer of the output stream record or null if not found.
0164    */
0165   const std::unique_ptr<OutStreamRecord>& getStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock);
0166 
0167   /** Writes a monitoring events to an output stream.
0168    * @param out stream to write the event out
0169    * @param event EDM event, used to retrieve meta information like timestamp
0170    * and ID.
0171    * @param ID of the unique FED block of the event
0172    * @param data DCC data
0173    * @return true on success, false on failure
0174    * @see getStream(int, edm::LuminosityBlockNumber_t)
0175    */
0176   bool writeEvent(OutStreamRecord& out,
0177                   const edm::Event& event,
0178                   int detailedTriggerType,
0179                   const FEDRawDataCollection& data);
0180 
0181   /** Writes out data of a FED
0182    * @param out stream to write the event out
0183    * @param data FED data
0184    * @return true on success, false on failure
0185    */
0186   bool writeFedBlock(std::ofstream& out, const FEDRawData& data);
0187 
0188   /** Closes an output stream and removed it from opened stream records.
0189    * Beware: this methode modifies outStreamList_.
0190    * @param streamRecord record of the output stream to close.
0191    * @return iterator to element next to the deleted one.
0192    */
0193   OutStreamList::iterator closeOutStream(OutStreamList::iterator streamRecord);
0194 
0195   /** Creates an output stream. It must be ensured before calling this method
0196    * that the output stream is not already opened (See outStreamList_).
0197    * @param fedId FED ID of the event to stream out.
0198    * @param lumiBlock starting lumi block of the event group to write to the
0199    * stream.
0200    * @return iterator to the new stream record. outStreamList_.end() in case
0201    * of failure.
0202    */
0203   OutStreamList::iterator createOutStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock);
0204 
0205   /** Writing file header for an LMF binary file
0206    * @param out stream of the output file
0207    */
0208   void writeFileHeader(std::ofstream& out);
0209 
0210   /** Write event header with event identification and timestamp.
0211    * @param out output stream to write to
0212    * @param evt event
0213    * @return false in case of write failure
0214    */
0215   bool writeEventHeader(std::ofstream& out, const edm::Event& evt, int fedId, unsigned nFeds);
0216 
0217   /** Builds the file names for the group of event corresponding
0218    * to a FED and a starting lumi block.
0219    * @param fedId FED ID of the event set
0220    * @param lumiBlock starting luminoisty block of the event set
0221    * @param [out] tmpName name of the file to use when filling it.
0222    * @param [out] finalName name of the file once completed.
0223    */
0224   void streamFileName(int fedId, edm::LuminosityBlockNumber_t lumiBlock, std::string& tmpName, std::string& finalName);
0225 
0226   /** Checks if an ECAL DCC event is empty. It is considered as
0227    * empty if it does not contains FE data ("tower" block). So
0228    * an event containing SRP or TCC data can be tagged as empty by
0229    * this method.
0230    * @dccLen, if not null filled with the event length read from the
0231    * DCC header.
0232    * @nTowerBlocks if not null, filled with number of tower blocks
0233    * @return true if event is empty, false otherwise
0234    */
0235   bool isDccEventEmpty(const FEDRawData& data, size_t* dccLen = nullptr, int* nTowerBlocks = nullptr) const;
0236 
0237   /** Computes the list of FEDs which data must be written out.
0238    * @param data CMS raw event
0239    * @param fedIds [out] list of FEDs to keep
0240    */
0241   void getOutputFedList(const edm::Event& event, const FEDRawDataCollection& data, std::vector<unsigned>& fedIds) const;
0242 
0243   /** Read index table of an LMF file.
0244    * @param in LMF file whose index table must be read.
0245    * @param inName name of the in file
0246    * @param outRcd record of the output file. whose the index table must be
0247    * copied to.
0248    * @param err if not nul, in case of failure filled with the error message.
0249    * @return true in case of success, false otherwise
0250    */
0251   bool readIndexTable(std::ifstream& in, std::string& inName, OutStreamRecord& outRcd, std::string* err);
0252 
0253   /** Writes index table in LMF output file. stream must be positionned
0254    * to the place for the index table (end of file).
0255    * @param out stream of output file.
0256    * @param indices index table
0257    */
0258   bool writeIndexTable(std::ofstream& out, std::vector<IndexRecord>& indices);
0259 
0260   bool renameAsBackup(const std::string& fileName, std::string& newFileName);
0261 
0262   /** Gets format version of an LMF file. Position of file is preserved.
0263    * @param in stream to read the file
0264    * @param fileName name of the file. Used in error message.
0265    * @return version or -1 in case of error.
0266    */
0267   int readFormatVersion(std::ifstream& in, const std::string& fileName);
0268 
0269   /** Help function to format a date
0270    */
0271   static std::string toString(uint64_t t);
0272 
0273   /** Opens output streams associated to a lumi block according to
0274    * already existing files. To be used when previously processed luminosity
0275    * block is not
0276    * @param lumiBlock ID of the luminosity block whose output streams
0277    * must be reopened.
0278    */
0279   void restoreStreamsOfLumiBlock(int lumiBlock);
0280 
0281   /** Retrieves DCCs which were fully read out (>=68 readout channels).
0282    * @param data DCC data collection
0283    * @return FED ids.
0284    */
0285   std::vector<int> getFullyReadoutDccs(const FEDRawDataCollection& data) const;
0286 
0287   //fields
0288 private:
0289   /** Lower bound of ECAL DCC FED ID
0290    */
0291   static const int ecalDccFedIdMin_;
0292 
0293   /** Lower bound of ECAL DCC FED ID
0294    */
0295   static const int ecalDccFedIdMax_;
0296 
0297   /** Trigger type of calibration event. -1 if unkown.
0298    */
0299   int detailedTrigType_;
0300 
0301   /** File for logging
0302    */
0303   std::ofstream logFile_;
0304 
0305   /** Luminosity block of event under processing
0306    */
0307   edm::LuminosityBlockNumber_t lumiBlock_;
0308 
0309   /** Luminosity block of previous processed event
0310    */
0311   edm::LuminosityBlockNumber_t lumiBlockPrev_;
0312 
0313   /** List of output stream to write sorted
0314    * data
0315    */
0316   OutStreamList outStreamList_;
0317 
0318   /** Data format version of lmf output file
0319    */
0320   unsigned char formatVersion_;
0321 
0322   /** Top directory for output files
0323    */
0324   std::string outputDir_;
0325 
0326   /** Subdirectories for output file of each FED
0327    */
0328   std::vector<std::string> fedSubDirs_;
0329 
0330   /** Name of the file to log the processing time
0331    */
0332   std::string timeLogFile_;
0333 
0334   /** Switch to disable writing output file (for test purpose).
0335    */
0336   bool disableOutput_;
0337 
0338   /** Run number of event under process
0339    */
0340   edm::RunNumber_t runNumber_;
0341 
0342   /** Buffer for timing
0343    */
0344   timeval timer_;
0345 
0346   /** Output stream to log code timing
0347    */
0348   std::ofstream timeLog_;
0349 
0350   /** Switch for code timing.
0351    */
0352   bool timing_;
0353 
0354   /** name of file where list of output file is listed to
0355    */
0356   std::string outputListFile_;
0357 
0358   /**Switch for logging paths of the output files
0359    */
0360   bool doOutputList_;
0361 
0362   /** Debugging message verbosity level
0363    */
0364   int verbosity_;
0365 
0366   /** stream where list of output file is listed to
0367    */
0368   std::ofstream outputList_;
0369 
0370 #if 0
0371   /**Switch for logging Orbit Id of first calibration event
0372    */
0373   bool storeFirstOrbitId_;
0374 
0375   /** stream where to store orbit ID of first calibration event
0376    */
0377   std::ofstream firstOrbitOut_;
0378 
0379   /** Path to the file to store orbit ID of first calibration event
0380    */
0381   std::string firstOrbitOutputFile_;
0382 
0383   /** Buffer to compute minimal orbit ID of process events
0384    */
0385   uint32_t minOrbitId_;
0386 
0387 #endif
0388 
0389   /** Number of "No fully readout DCC error"
0390    */
0391   int iNoFullReadoutDccError_;
0392 
0393   /** Maximum number of "No fully readout DCC error" message in a run
0394    */
0395   int maxFullReadoutDccError_;
0396 
0397   /** number of "ECAL DCC data" message in a run
0398    */
0399   int iNoEcalDataMess_;
0400 
0401   /** Maximum number of "ECAL DCC data" message in a run
0402    */
0403   int maxNoEcalDataMess_;
0404 
0405   /** Tolerance on lumi block spanning of a FED sequence. Subsequent events
0406    * of a same FED must span at most on 2*lumiBlockSpan_+1 luminosity blocks.
0407    *
0408    * <ul><li>It is important that the laser sequence scane does not pass twice on the same FED
0409    * within the 2*lumiBlockSpan_+1. Failing this requirement will result mixing event of
0410    * different passes in the same output file.
0411    *    <li>The number of input files opened simultinuously is proportional to 2*lumiBlockSpan_+1.
0412    * So increasing lumiBlockSpan_ will also increase the number of opened files and may have
0413    * some impact of sorting time performances.
0414    * </ul>
0415    */
0416   int lumiBlockSpan_;
0417 
0418   edm::InputTag fedRawDataCollectionTag_;
0419   edm::EDGetTokenT<FEDRawDataCollection> fedRawDataCollectionToken_;
0420 
0421   /** FED ID associated to Matacq data
0422    */
0423   static const int matacqFedId_ = 655;
0424 
0425   /**
0426    */
0427   static const int indexOffset32_;
0428 
0429   /** Limit of number of events to prevent exhausting memory
0430    * with indexTable_ in case of file corruption.
0431    */
0432   static const unsigned maxEvents_ = 1 << 20;
0433 
0434   /** Statistics on event processing
0435    */
0436   struct stats_t {
0437     /// number of events read out
0438     double nRead;
0439     /// number of events written out
0440     double nWritten;
0441     ///number of events with at least one DCC with an invalid Detailed trigger
0442     ///type value
0443     double nInvalidDccStrict;
0444     ///number of events whose DCC ID determination from DCC headers fails because
0445     ///of a large descrepancy between the different DCCs of because of invalid values
0446     double nInvalidDccWeak;
0447     ///number of events whose DCC ID was restored based on FED block sizes
0448     double nRestoredDcc;
0449   } stats_;
0450   static const stats_t stats_init;
0451 
0452   /** Switch to recompute and overwrite the lumi block ID
0453    */
0454   bool overWriteLumiBlockId_;
0455 
0456   /** Length of a lumi block in number of orbits used when
0457    * overWriteLumiBlockId is set to true;
0458    * LB = orbit_id / orbitCountInALumiBlock_
0459    */
0460   int orbitCountInALumiBlock_;
0461 
0462   int orbit_;
0463 
0464   /** Time stamp offset to use to calculate
0465    * calibration time from the orbit id. It is obtained
0466    * from the matacq block (time originates from the PC hosting the laser supervisor).
0467    * and used in case the event is missing timestamp, in principle for data
0468    * acquired with the minidaq
0469    * Calibration event time = orbitZeroTime_ + orbit_ * (89.1 microsec).
0470    */
0471   struct timeval orbitZeroTime_;
0472 };
0473 
0474 #endif  //EVENT_SELECT_H not defined