1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
|
/*
*/
#ifndef EVENT_SELECT_H
#define EVENT_SELECT_H
#include <cinttypes>
#include <ctime>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <sys/time.h>
#include <vector>
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/one/EDAnalyzer.h"
#include "FWCore/Utilities/interface/InputTag.h"
#include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
#include "DataFormats/Provenance/interface/LuminosityBlockID.h"
#include "DataFormats/Provenance/interface/RunID.h"
/**
* This module is used to classify events of laser sequence acquired in
* a global run.
* Sorting: Events are grouped by bunch of consecutive events from the same
* FED. A file of such a bunch of events is identified by the FED or ECAL
* sector and the luminosity block id of the first event.
*
* Sorting strategy:
* It is assumes that:
* - one sequence FED does not overlap more than
* two lumi blocks.
* - lumi blocks are read in order
* A FED file will be closed as soon as one event 2 lumi block ahead
* from the first event feed in the file is read.
*
* File completion: while being feeding, .part is appended at the end of
* the each output file.Once a file is completed (see above), it is renamed
* without the enclosing .part suffix.
*/
class LaserSorter : public edm::one::EDAnalyzer<edm::one::WatchRuns> {
//inner classes
private:
struct IndexRecord {
uint32_t orbit;
uint32_t filePos;
bool operator<(const IndexRecord& i) const { return orbit < i.orbit; }
};
class OutStreamRecord {
public:
//default ctor
OutStreamRecord(int fedId__,
edm::LuminosityBlockNumber_t startingLumiBlock__,
std::ofstream* out__,
std::string& tmpFileName__,
std::string& finalFileName__)
: fedId_(fedId__),
startingLumiBlock_(startingLumiBlock__),
out_(out__),
tmpFileName_(tmpFileName__),
finalFileName_(finalFileName__),
indexError_(false) {
indices_.reserve(indexReserve_);
}
int fedId() const { return fedId_; }
edm::LuminosityBlockNumber_t startingLumiBlock() const { return startingLumiBlock_; }
std::ofstream* out() const { return out_.get(); }
std::string finalFileName() const { return finalFileName_; }
std::string tmpFileName() const { return tmpFileName_; }
std::vector<IndexRecord>* indices() { return &indices_; }
/** Gets the list of orbits to skip. Used to update an existing file:
* orbits of events already present in the file are excluded.
* @return the list of orbits to skip.
*/
std::set<uint32_t>& excludedOrbit() { return excludedOrbit_; }
private:
int fedId_;
edm::LuminosityBlockNumber_t startingLumiBlock_;
std::unique_ptr<std::ofstream> out_;
std::string tmpFileName_;
std::string finalFileName_;
const static std::string emptyString_;
/** Index table. This map is used to index the events in the file
* according to their orbit id. An index table is stored at the end
* of the output files.
*/
std::vector<IndexRecord> indices_;
/** List of orbits to skip. Used to update an existing file: orbits
* of events already present in the file are excluded.
*/
std::set<uint32_t> excludedOrbit_;
/** Used to invalidate index table in case a problem preventing
* indexing is encountered: in principle non unicity of the orbit id.
*/
bool indexError_;
/** Initial memory allocation for index table (see vector::reserve()).
*/
static const size_t indexReserve_;
};
//typedefs:
private:
typedef std::list<std::unique_ptr<OutStreamRecord>> OutStreamList;
//ctors/dtors
public:
LaserSorter(const edm::ParameterSet&);
~LaserSorter() override;
//methods
public:
void analyze(const edm::Event&, const edm::EventSetup&) override;
void endJob() override;
void beginJob() override;
void beginRun(edm::Run const&, edm::EventSetup const&) override;
void endRun(edm::Run const&, edm::EventSetup const&) override;
private:
int dcc2Lme(int dccNum, int dccSide);
/** Retrieves the orbit ID from DCC headers. The first header found is used.
* @rawdata the raw data where to read the orbit id.
* @return the event orbit ID or -1 if it was not found
*/
int getOrbitFromDcc(const edm::Handle<FEDRawDataCollection>& rawdata) const;
/** Retrieve detailed trigger type (trigger type, DCC, side) from raw event
* @param rawdata FED data collection
* @param proba if not null used to store the maximum of occurence frequency
* of the detailed trigger types (DTT) appearing in each DCC block. In normal
* condition every DCC indicated the same DTT and this value is 1.
* @return detailed trigger type. In case of descripancy between the DCCs, the
* most frequent value is returned if it covers more than 80% of the present DCC
* blocks, -1 is returned otherwise. If event does not contain any ECAL data
* -2 is returned.
*/
int getDetailedTriggerType(const edm::Handle<FEDRawDataCollection>& rawdata, double* proba = nullptr);
/** Closes output stream 2 lumi block older than the input 'lumiBlock' ID.
* @param lumiBlock ID of the reference luminosity block.
*/
void closeOldStreams(edm::LuminosityBlockNumber_t lumiBlock);
/** Closes all opened output streams.
*/
void closeAllStreams();
/** Gets and eventually creates the output stream for writing the events
* of a given FED and luminosity block.
* @param fedId ID of the FED the event is issued from
* @param lumiBlock luminositu block of the event
* @return pointer of the output stream record or null if not found.
*/
const std::unique_ptr<OutStreamRecord>& getStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock);
/** Writes a monitoring events to an output stream.
* @param out stream to write the event out
* @param event EDM event, used to retrieve meta information like timestamp
* and ID.
* @param ID of the unique FED block of the event
* @param data DCC data
* @return true on success, false on failure
* @see getStream(int, edm::LuminosityBlockNumber_t)
*/
bool writeEvent(OutStreamRecord& out,
const edm::Event& event,
int detailedTriggerType,
const FEDRawDataCollection& data);
/** Writes out data of a FED
* @param out stream to write the event out
* @param data FED data
* @return true on success, false on failure
*/
bool writeFedBlock(std::ofstream& out, const FEDRawData& data);
/** Closes an output stream and removed it from opened stream records.
* Beware: this methode modifies outStreamList_.
* @param streamRecord record of the output stream to close.
* @return iterator to element next to the deleted one.
*/
OutStreamList::iterator closeOutStream(OutStreamList::iterator streamRecord);
/** Creates an output stream. It must be ensured before calling this method
* that the output stream is not already opened (See outStreamList_).
* @param fedId FED ID of the event to stream out.
* @param lumiBlock starting lumi block of the event group to write to the
* stream.
* @return iterator to the new stream record. outStreamList_.end() in case
* of failure.
*/
OutStreamList::iterator createOutStream(int fedId, edm::LuminosityBlockNumber_t lumiBlock);
/** Writing file header for an LMF binary file
* @param out stream of the output file
*/
void writeFileHeader(std::ofstream& out);
/** Write event header with event identification and timestamp.
* @param out output stream to write to
* @param evt event
* @return false in case of write failure
*/
bool writeEventHeader(std::ofstream& out, const edm::Event& evt, int fedId, unsigned nFeds);
/** Builds the file names for the group of event corresponding
* to a FED and a starting lumi block.
* @param fedId FED ID of the event set
* @param lumiBlock starting luminoisty block of the event set
* @param [out] tmpName name of the file to use when filling it.
* @param [out] finalName name of the file once completed.
*/
void streamFileName(int fedId, edm::LuminosityBlockNumber_t lumiBlock, std::string& tmpName, std::string& finalName);
/** Checks if an ECAL DCC event is empty. It is considered as
* empty if it does not contains FE data ("tower" block). So
* an event containing SRP or TCC data can be tagged as empty by
* this method.
* @dccLen, if not null filled with the event length read from the
* DCC header.
* @nTowerBlocks if not null, filled with number of tower blocks
* @return true if event is empty, false otherwise
*/
bool isDccEventEmpty(const FEDRawData& data, size_t* dccLen = nullptr, int* nTowerBlocks = nullptr) const;
/** Computes the list of FEDs which data must be written out.
* @param data CMS raw event
* @param fedIds [out] list of FEDs to keep
*/
void getOutputFedList(const edm::Event& event, const FEDRawDataCollection& data, std::vector<unsigned>& fedIds) const;
/** Read index table of an LMF file.
* @param in LMF file whose index table must be read.
* @param inName name of the in file
* @param outRcd record of the output file. whose the index table must be
* copied to.
* @param err if not nul, in case of failure filled with the error message.
* @return true in case of success, false otherwise
*/
bool readIndexTable(std::ifstream& in, std::string& inName, OutStreamRecord& outRcd, std::string* err);
/** Writes index table in LMF output file. stream must be positionned
* to the place for the index table (end of file).
* @param out stream of output file.
* @param indices index table
*/
bool writeIndexTable(std::ofstream& out, std::vector<IndexRecord>& indices);
bool renameAsBackup(const std::string& fileName, std::string& newFileName);
/** Gets format version of an LMF file. Position of file is preserved.
* @param in stream to read the file
* @param fileName name of the file. Used in error message.
* @return version or -1 in case of error.
*/
int readFormatVersion(std::ifstream& in, const std::string& fileName);
/** Help function to format a date
*/
static std::string toString(uint64_t t);
/** Opens output streams associated to a lumi block according to
* already existing files. To be used when previously processed luminosity
* block is not
* @param lumiBlock ID of the luminosity block whose output streams
* must be reopened.
*/
void restoreStreamsOfLumiBlock(int lumiBlock);
/** Retrieves DCCs which were fully read out (>=68 readout channels).
* @param data DCC data collection
* @return FED ids.
*/
std::vector<int> getFullyReadoutDccs(const FEDRawDataCollection& data) const;
//fields
private:
/** Lower bound of ECAL DCC FED ID
*/
static const int ecalDccFedIdMin_;
/** Lower bound of ECAL DCC FED ID
*/
static const int ecalDccFedIdMax_;
/** Trigger type of calibration event. -1 if unkown.
*/
int detailedTrigType_;
/** File for logging
*/
std::ofstream logFile_;
/** Luminosity block of event under processing
*/
edm::LuminosityBlockNumber_t lumiBlock_;
/** Luminosity block of previous processed event
*/
edm::LuminosityBlockNumber_t lumiBlockPrev_;
/** List of output stream to write sorted
* data
*/
OutStreamList outStreamList_;
/** Data format version of lmf output file
*/
unsigned char formatVersion_;
/** Top directory for output files
*/
std::string outputDir_;
/** Subdirectories for output file of each FED
*/
std::vector<std::string> fedSubDirs_;
/** Name of the file to log the processing time
*/
std::string timeLogFile_;
/** Switch to disable writing output file (for test purpose).
*/
bool disableOutput_;
/** Run number of event under process
*/
edm::RunNumber_t runNumber_;
/** Buffer for timing
*/
timeval timer_;
/** Output stream to log code timing
*/
std::ofstream timeLog_;
/** Switch for code timing.
*/
bool timing_;
/** name of file where list of output file is listed to
*/
std::string outputListFile_;
/**Switch for logging paths of the output files
*/
bool doOutputList_;
/** Debugging message verbosity level
*/
int verbosity_;
/** stream where list of output file is listed to
*/
std::ofstream outputList_;
#if 0
/**Switch for logging Orbit Id of first calibration event
*/
bool storeFirstOrbitId_;
/** stream where to store orbit ID of first calibration event
*/
std::ofstream firstOrbitOut_;
/** Path to the file to store orbit ID of first calibration event
*/
std::string firstOrbitOutputFile_;
/** Buffer to compute minimal orbit ID of process events
*/
uint32_t minOrbitId_;
#endif
/** Number of "No fully readout DCC error"
*/
int iNoFullReadoutDccError_;
/** Maximum number of "No fully readout DCC error" message in a run
*/
int maxFullReadoutDccError_;
/** number of "ECAL DCC data" message in a run
*/
int iNoEcalDataMess_;
/** Maximum number of "ECAL DCC data" message in a run
*/
int maxNoEcalDataMess_;
/** Tolerance on lumi block spanning of a FED sequence. Subsequent events
* of a same FED must span at most on 2*lumiBlockSpan_+1 luminosity blocks.
*
* <ul><li>It is important that the laser sequence scane does not pass twice on the same FED
* within the 2*lumiBlockSpan_+1. Failing this requirement will result mixing event of
* different passes in the same output file.
* <li>The number of input files opened simultinuously is proportional to 2*lumiBlockSpan_+1.
* So increasing lumiBlockSpan_ will also increase the number of opened files and may have
* some impact of sorting time performances.
* </ul>
*/
int lumiBlockSpan_;
edm::InputTag fedRawDataCollectionTag_;
edm::EDGetTokenT<FEDRawDataCollection> fedRawDataCollectionToken_;
/** FED ID associated to Matacq data
*/
static const int matacqFedId_ = 655;
/**
*/
static const int indexOffset32_;
/** Limit of number of events to prevent exhausting memory
* with indexTable_ in case of file corruption.
*/
static const unsigned maxEvents_ = 1 << 20;
/** Statistics on event processing
*/
struct stats_t {
/// number of events read out
double nRead;
/// number of events written out
double nWritten;
///number of events with at least one DCC with an invalid Detailed trigger
///type value
double nInvalidDccStrict;
///number of events whose DCC ID determination from DCC headers fails because
///of a large descrepancy between the different DCCs of because of invalid values
double nInvalidDccWeak;
///number of events whose DCC ID was restored based on FED block sizes
double nRestoredDcc;
} stats_;
static const stats_t stats_init;
/** Switch to recompute and overwrite the lumi block ID
*/
bool overWriteLumiBlockId_;
/** Length of a lumi block in number of orbits used when
* overWriteLumiBlockId is set to true;
* LB = orbit_id / orbitCountInALumiBlock_
*/
int orbitCountInALumiBlock_;
int orbit_;
/** Time stamp offset to use to calculate
* calibration time from the orbit id. It is obtained
* from the matacq block (time originates from the PC hosting the laser supervisor).
* and used in case the event is missing timestamp, in principle for data
* acquired with the minidaq
* Calibration event time = orbitZeroTime_ + orbit_ * (89.1 microsec).
*/
struct timeval orbitZeroTime_;
};
#endif //EVENT_SELECT_H not defined
|