ATLAS Offline Software
Loading...
Searching...
No Matches
CaloCellPacker_400_500 Class Reference

Calo cell packer/unpacker v400/500. More...

#include <CaloCellPacker_400_500.h>

Collaboration diagram for CaloCellPacker_400_500:

Classes

struct  header400
 Packing parameters header (v400). More...
struct  header500
 Packing parameters header (v500). More...
struct  header501
 Packing parameters header (v501). More...
struct  pars500
 Derived packing parmeters. More...

Public Member Functions

void pack (const CaloCellContainer &cells, CaloCompactCellContainer &packed, const SG::ThinningDecisionBase *dec, int version) const
 Pack cells.
void unpack (const CaloCompactCellContainer &packed, const std::vector< CaloCompactCellContainer::value_type > &vheader, CaloCellContainer &cells, DataPool< LArCell > &larpool, DataPool< TileCell > &tilepool) const
 Unpack cells.

Private Member Functions

Packing.
void pack_time (float time, CaloCompactCellContainer::compact_output_iterator &it, const pars500 &pars) const
 Pack a time value.
void pack_lar (const CaloCell *cell, CaloCell_ID::SUBCALO subcalo, CaloCompactCellContainer::compact_output_iterator &it, const pars500 &pars) const
 Pack one LAr cell.
void pack_tile (const TileCell *cell, CaloCompactCellContainer::compact_output_iterator &it, const pars500 &pars) const
 Pack one tile cell.
void finish_seq (unsigned int hash, unsigned int nseq, CaloCompactCellContainer::compact_output_iterator &it, CaloCell_ID::SUBCALO subcalo, pars500 &pars) const
 Finish up one cell sequence.
void write_header (const headerheader &headerheader, CaloCompactCellContainer &packed) const
 Write the header to the output container.

Header and parameter definitions.

typedef header501 header
 The most recent header version.
void init_header (headerheader &headerheader, int version) const
 Initialize header with the current version of the packing parameters.
void clear_header (headerheader &headerheader) const
 Clear the counters in the event header.
void init_derived (pars500 &pars) const
 Initialize the derived packing parameters from the constants in the header.

Unpacking.

class CaloCellPacker_400_500_test
double unpack_time (CaloCompactCellContainer::compact_input_iterator &it, const pars500 &pars) const
 Unpack the time word.
CaloCellunpack_lar (CaloCompactCellContainer::compact_input_iterator &it, CaloCell_ID::SUBCALO subcalo, LArCell *cell, const pars500 &pars, uint16_t provenance) const
 Unpack a LAr cell.
TileCell unpack_tile (CaloCompactCellContainer::compact_input_iterator &it, const CaloDetDescrElement *dde, const pars500 &pars, uint16_t provenance) const
 Unpack a tile cell.

Detailed Description

Calo cell packer/unpacker v400/500.

This class handles packing and unpacking of calorimeter cells into a CaloCompactCellContainer. This holds data as a vector of integers, but for our purposes, we treat it as an array of 16-bit values. We use the special iterator-like objects that that class defines for access.

A summary of the format is given here. Most constants and bit assignments are specified within the method init_header(). Though some of them are spelled out here, the possibility is left open that they can change. The constants are stored in a header along with the data; for reading, those stored constants are the ones used to interpret the data.

The difference between versions 400 and 500 is the inclusion of quality and provenance data. Quality is like a chi**2 comparing the observed pulse shape (with 5 samples) to the expected one. It is different cell by cell, event by event (it is like energy and time from this point of view)

The idea to store provenance is to know when reading back the ESD how the energy was estimated. For instance, when doing the OFC iteration method on the cosmics on high energy cell there is one bit which tells if the iteration converges or not and this is useful when analyzing back the event (and this bit can vary from event to event for the same cell).

The packed data start with an instance of either header400 or header500, containing the packing constants as well as cell/sequence counts. Note that the first word is the length of the header, in units of int.

Following the header is a set of sequences, each containing a range of cells with consecutive hash IDs. The cells are stored in hash order, which implies that the subcalorimeters are strictly in the order LAREM, LARHEC, LARFCAL, TILE. A single sequence contains cells from only a single subcalorimeter.

Each sequence starts with a 32-bit value; where the high word is stored first, and the low word second. (Note that this is opposite from the order in which the x86 would naturally store the data.) The lower 18 bits of this give the hash value of the first cell in the sequence (others follow sequentially), and the upper 14 bits give the number of cells in the sequence. (Note: if the number of cells in a sequence is more than can be represented in 14 bits, the sequence is simply split into several.) Following this is the information for the cells themselves.

For LAr cells, there is a 16-bit word, containing, starting from the low bit, 12 bits of energy, one sign bit for energy, two bits for the gain, and one bit for the quality. The quality bit is 1 for good quality and 0 for bad quality. The gain bits are one of: 0 ENLOW for LARLOWGAIN 1 ENMED for LARMEDIUMGAIN, unless cell is in the HEC with e < e1_high 2 ENHIG for LARHIGHGAIN, unless cell is not in the HEC with e< e1_high 3 EHHIG for LARMEDIUMGAIN if cell is in the HEC with e < e1_high or for LARHIGHGAIN if cell is not in the HEC with e < e1_high

The maximum energy is taken to be 50 GeV (e1_high) for EHHIG and 3.2 TeV otherwise. We take the cube root of the absolute value of the energy, convert it into a fraction of fullscale (as a cube root), and store that fraction as a fixed-point number.

If the quality is good, this is followed by two additional 16-bit words. The first gives the time information. This has 15 bits of time information and one sign bit. We take the natural log of the time, and then encode this as a fraction of the range from 0.001ns to 1250ns. This is then followed by the quality word.

For tile cells, information for each of the two PMTs is stored separately. First is a 16-bit word containing 13 bits of energy information, one sign bit, one gain bit, and one quality bit. The quality bit is 1 for good quality and 0 for bad. The gain bit is 0 for low gain and 1 for high gain. The energy is again stored as a scaled cube root, where the upper limit is 50 GeV for high gain and 3.2 TeV for low gain. If the quality is good, this is followed by 16 bits of time information, encoded as before. Following both cells is a 16-bit quality word; the lower 8 bits are for the first PMT, and the upper eight bits are for the second PMT. If the quality flags for both PMTs are bad, then this word is omitted.

Following the cell information is the provenance information. Each provenance entry consists of a cell hash code (19 bits) plus a provenance word (13 bits) packed into two 16-bit words. The high 13 bits of the first word are the provenance; the low three bits of the first word plus the second word give the hash code. Each provenance entry says that cells starting at the given hash code have the given provenance value (until the hash code of the next provenance entry). Cells with a hash code less than that of the first provenance entry have a provenance word of 0.

Version 501 adds a status bitmask to the header, with the flag STATUS_UNORDERED. This is set if the packer finds that the cells are not in subcalo order. (This is the case for cell collections produced by the HLT, which are concatenations of per-ROI cell collections.)

Version 502 adds quality words and provenance for tile.

Version 503 reduces slightly the range for negative energies, to avoid confusion with error flags.

Version 504 introduces a flag for SuperCell

Definition at line 144 of file CaloCellPacker_400_500.h.

Member Typedef Documentation

◆ header

The most recent header version.

Definition at line 284 of file CaloCellPacker_400_500.h.

Member Function Documentation

◆ clear_header()

void CaloCellPacker_400_500::clear_header ( header & header) const
private

Clear the counters in the event header.

Parameters
headerThe header to clear.

Definition at line 102 of file CaloCellPacker_400_500.cxx.

103{
104 header.m_ncells_larem = 0;
105 header.m_ncells_larhec = 0;
106 header.m_ncells_larfcal = 0;
107 header.m_ncells_tile = 0;
108 header.m_seq_larem = 0;
109 header.m_seq_larhec = 0;
110 header.m_seq_larfcal = 0;
111 header.m_seq_tile = 0;
112 header.m_lengthProvenance = 0;
113 header.m_status = 0;
114}
header501 header
The most recent header version.

◆ finish_seq()

void CaloCellPacker_400_500::finish_seq ( unsigned int hash,
unsigned int nseq,
CaloCompactCellContainer::compact_output_iterator & it,
CaloCell_ID::SUBCALO subcalo,
pars500 & pars ) const
inlineprivate

Finish up one cell sequence.

Parameters
hashThe hash of the first cell in the sequence.
nseqThe number of cells in the sequence.
itIterator pointing at the beginning of the sequence.
subcaloSubcalorimeter code for the sequence.
parsThe packing parameters.

Definition at line 422 of file CaloCellPacker_400_500.cxx.

428{
429 // Pack the hash code and number of cells into a bitfield.
431 pars.m_hash_field.in(hash) | pars.m_nseq_field.in(nseq);
432
433 // Write it into the output container.
434 it.set ((data>>16) & 0xffff);
435 it.set (data & 0xffff);
436
437 // Update counters.
438 switch (subcalo) {
440 pars.m_ncells_larem += nseq;
441 ++pars.m_seq_larem;
442 break;
444 pars.m_ncells_larhec += nseq;
445 ++pars.m_seq_larhec;
446 break;
448 pars.m_ncells_larfcal += nseq;
449 ++pars.m_seq_larfcal;
450 break;
452 pars.m_ncells_tile += nseq;
453 ++pars.m_seq_tile;
454 break;
455 default:
456 std::abort();
457 }
458}
int value_type
value type for the internal data

◆ init_derived()

void CaloCellPacker_400_500::init_derived ( pars500 & pars) const
private

Initialize the derived packing parameters from the constants in the header.

Parameters
parsThe packing parameters.

Definition at line 122 of file CaloCellPacker_400_500.cxx.

123{
124 // Good quality flag.
125 pars.m_qgood = 1;
126
127 // Set up parameters for packing/unpacking the sequence header.
128 pars.m_hash_field = CaloCellPackerUtils::Bitfield (0x0003ffff);
129 pars.m_nseq_field = CaloCellPackerUtils::Bitfield (0xfffc0000);
130 pars.m_nseq_max = 0x3fff;
131
132 // Set up parameters for packing/unpacking the provenance list.
133 pars.m_prov_field = CaloCellPackerUtils::Bitfield (0xfff80000);
134 pars.m_prov_max = 0x1fff;
135 pars.m_prov_max_tile = 0x1f1f;
136
137 // Cube roots of energy ranges.
138 pars.m_cbrt_e1_norm_res = cbrt(static_cast<double>(pars.m_e1_norm_res));
139 pars.m_cbrt_e1_high_res = cbrt(static_cast<double>(pars.m_e1_high_res));
140 pars.m_cbrt_low_tile = cbrt(static_cast<double>(pars.m_low_tile));
141 pars.m_cbrt_high_tile = cbrt(static_cast<double>(pars.m_high_tile));
142
143 // Logarithms of time ranges.
144 pars.m_log_t0 = log(static_cast<double>(pars.m_t0));
145 pars.m_log_t1 = log(static_cast<double>(pars.m_t1));
146
147 // Fill in remaining bit fields.
148 pars.m_qualy_field = CaloCellPackerUtils::Bitfield (pars.m_qualy_mask);
149 pars.m_egain_field = CaloCellPackerUtils::Bitfield (pars.m_egain_mask);
150 pars.m_crtae_norm_field =
151 CaloCellPackerUtils::Floatfield2 (pars.m_crtae_mask,
152 pars.m_cbrt_e1_norm_res);
153 pars.m_crtae_high_field =
154 CaloCellPackerUtils::Floatfield2 (pars.m_crtae_mask,
155 pars.m_cbrt_e1_high_res);
156 pars.m_logat_field =
157 CaloCellPackerUtils::Floatfield (pars.m_logat_mask,
158 pars.m_log_t0, pars.m_log_t1);
159 pars.m_egain_tile_field =
160 CaloCellPackerUtils::Bitfield (pars.m_egain_tile_mask);
161 pars.m_crtae_tile_high_field =
162 CaloCellPackerUtils::Floatfield2 (pars.m_crtae_tile_mask,
163 pars.m_cbrt_high_tile);
164 pars.m_crtae_tile_low_field =
165 CaloCellPackerUtils::Floatfield2 (pars.m_crtae_tile_mask,
166 pars.m_cbrt_low_tile);
167
168 pars.m_tile_qual1_field = CaloCellPackerUtils::Bitfield (0x00ff);
169 pars.m_tile_qual2_field = CaloCellPackerUtils::Bitfield (0xff00);
170
171 // Dummy flags.
172 pars.m_lar_dummy =
173 pars.m_egain_field.in (pars.m_enhig) |
174 pars.m_qualy_field.in (pars.m_qabad) |
175 pars.m_crtae_norm_field.in (cbrt (pars.m_e1_norm_res)) |
176 pars.m_esign_mask;
177
178 pars.m_tile_dummy =
179 pars.m_egain_tile_field.in (pars.m_glow) |
180 pars.m_qualy_field.in (pars.m_qabad) |
181 pars.m_crtae_tile_high_field.in (pars.m_cbrt_high_tile) |
182 pars.m_esign_tile_mask;
183
184
185 {
186 CaloCellPackerUtils::Bitfield& elar = pars.m_crtae_norm_field;
187 pars.m_lar_dummy_subst = (pars.m_lar_dummy & ~pars.m_crtae_mask) |
188 elar.in (elar.out (pars.m_lar_dummy)-1);
189
190 CaloCellPackerUtils::Bitfield& etile = pars.m_crtae_tile_high_field;
191 pars.m_tile_dummy_subst = (pars.m_tile_dummy & ~pars.m_crtae_tile_mask) |
192 etile.in (etile.out (pars.m_tile_dummy)-1);
193 }
194}
unsigned int out(unsigned int x) const
Extract a value from the bitfield.
unsigned int in(unsigned int x) const
Shift and mask a value into the bitfield.

◆ init_header()

void CaloCellPacker_400_500::init_header ( header & header,
int version ) const
private

Initialize header with the current version of the packing parameters.

(Almost) all the constants are defined here.

Parameters
headerThe header to initialize.
versionThe version of the header to initialize.

Definition at line 39 of file CaloCellPacker_400_500.cxx.

41{
42 header.m_version = version;
43 switch (version) {
48 header.m_length = sizeof(header501)/sizeof(int);
49 break;
50
52 header.m_length = sizeof(header500)/sizeof(int);
53 break;
55 header.m_length = sizeof(header400)/sizeof(int);
56 break;
57 default:
58 std::abort();
59 }
60
61 header.m_qualy_mask = 0x8000;
62 header.m_egain_mask = 0x6000;
63 header.m_esign_mask = 0x1000;
64 // 12 bits for cbrt(|E|) and 2 ranges, one normal
65 // resolution range with upper limit 3.2 TeV and precision loss
66 // sigma_E'/E < 1.4%/sqrt(E/GeV) and one high-resolution range used
67 // whenever E < 50 GeV and the hardware gain is HIGH (HEC: MEDIUM)
68 // resulting in a precision loss of sigma_E'/E < 0.15%/sqrt(E/GeV)
69 header.m_crtae_mask = 0x0fff;
70 header.m_egain_tile_mask = 0x4000;
71 header.m_esign_tile_mask = 0x2000;
72 // 13 bits cbrt(|E|) and 2 ranges
73 // upper limit for low gain is 3.2 TeV,
74 // upper limit for high gain is 50 GeV (safety factor of ~3)
75 header.m_crtae_tile_mask = 0x1fff;
76 header.m_tsign_mask = 0x8000;
77 header.m_logat_mask = 0x7fff;
78
79 header.m_qabad = 0;
80 header.m_enlow = 0; // normal resolution LOW gain
81 header.m_enmed = 1; // normal resolution MEDIUM gain
82 header.m_enhig = 2; // normal resolution HIGH gain
83 header.m_ehhig = 3; // high resolution HIGH (HEC: MEDIUM) gain
84 header.m_glow = TileID::LOWGAIN;
85 header.m_ghigh = TileID::HIGHGAIN;
86
87 header.m_e1_norm_res = 3.2*Gaudi::Units::TeV;
88 header.m_e1_high_res = 50*Gaudi::Units::GeV;
89 header.m_high_tile = 50*Gaudi::Units::GeV;
90 header.m_low_tile = 3.2*Gaudi::Units::TeV;
91 header.m_t0 = 0.001*Gaudi::Units::ns;
92 header.m_t1 = 1250.0*Gaudi::Units::ns;
93
95}
void clear_header(header &header) const
Clear the counters in the event header.
Packing parameters header (v400).
Packing parameters header (v500).
Packing parameters header (v501).

◆ pack()

void CaloCellPacker_400_500::pack ( const CaloCellContainer & cells,
CaloCompactCellContainer & packed,
const SG::ThinningDecisionBase * dec,
int version ) const

Pack cells.

Parameters
cellsThe input cell container.
packedThe output packed cell container.
decIf non-null, specification of elements to be thinned.
versionThe version of the header to initialize.

Definition at line 468 of file CaloCellPacker_400_500.cxx.

472{
473 // Set up the header and derived parameters.
474 pars500 pars;
475 init_header (pars, version);
476 init_derived (pars);
477
478 std::vector<short unsigned int> vProvenance;
479
480 // Figure out an upper limit for the container size.
481 // Header, plus one word/cell for sequence, two words/cell for data,
482 // and another word/cell for provenance.
483 // Tile cells have two additional words/cell - energy and time for second PMT.
484 // Add one more to account for possible padding before the provenance info.
485 // We'll resize this down correctly when we're done.
486 unsigned int maxsize =
487 pars.m_length + 4 * cells.size() + 2 * cells.nCellsCalo (CaloCell_ID::TILE)+1;
488 packed.resize (maxsize);
489
490 // Set up for loop over cells.
491
492 // This is the output iterator, to which we write.
493 CaloCompactCellContainer::compact_output_iterator outit
494 (packed.compact_begin_output (pars.m_length));
495
496 // Here we save the output iterator at the beginning of each sequence.
497 // We'll use that to go back and plug in the count when we're done.
498 CaloCompactCellContainer::compact_output_iterator seqit
499 (packed.compact_begin_output (pars.m_length));
500
501 // The hash of the first cell in the current sequence.
502 unsigned int seqhash = static_cast<unsigned int> (-1);
503
504 // Number of cells so far in the current sequence.
505 // 0 if not in a sequence.
506 unsigned int nseq = 0;
507
508 // The subcalorimeter code of the previous cell we looked at.
510
511 // If all the cells have provenance 0, there is nothing in the vector.
512 short unsigned int prevCellProvenance=0;
513
514 // check if it is a SuperCell
515 bool is_SC=false;
516 if (cells.size()>0){
517 // assuming no mixed SC and Cells.
518 const CaloDetDescrElement* dde = cells[0]->caloDDE();
519 const CaloCell_Base_ID* idhelper =
520 dde->descriptor()->get_calo_helper();
521 is_SC = idhelper->is_supercell(cells[0]->ID());
522 }
523
524 if (is_SC)
525 pars.m_status |= header::STATUS_IS_SUPERCELL;
526
527 // Loop over input cells.
528 for (size_t icell = 0; const CaloCell* cell : cells)
529 {
530 // Check for thinning.
531 if (dec && dec->thinned (icell++)) {
532 continue;
533 }
534
535 // Pick up values from the cell.
536 const CaloDetDescrElement* dde = cell->caloDDE();
537 unsigned int hash = dde->calo_hash();
538 CaloCell_ID::SUBCALO subcalo = dde->getSubCalo();
539
540 // Test to see if we need to start a new sequence.
541 if (// Not in a sequence now?
542 nseq == 0 ||
543 // We're at the maximum sequence length?
544 nseq >= pars.m_nseq_max ||
545 // A skip in the cell hash codes?
546 seqhash + nseq != hash ||
547 // Moving to a new subcalorimeter?
548 subcalo != prevcalo)
549 {
550 // Mark if cells aren't ordered.
551 if (prevcalo != CaloCell_ID::NOT_VALID &&
552 subcalo < prevcalo)
553 pars.m_status |= header::STATUS_UNORDERED;
554
555 // If we're already in a sequence, need to finish it.
556 if (nseq > 0)
557 finish_seq (seqhash, nseq, seqit, prevcalo, pars);
558
559 // Start a new sequence.
560 nseq = 0;
561 seqhash = hash;
562 prevcalo = subcalo;
563 // Leave space to fill in the hash/count later.
564 seqit = outit;
565 ++outit;
566 ++outit;
567 }
568
569 // Add the current cell on to sequence.
570 if (!is_SC && subcalo == CaloCell_ID::TILE) {
571 pack_tile (static_cast<const TileCell*>(cell), outit, pars);
572
573 // Check to see if the provenance changed.
574 if (version >= 502 &&
575 (cell->provenance() & pars.m_prov_max_tile) != prevCellProvenance)
576 {
577 prevCellProvenance = cell->provenance() & pars.m_prov_max_tile;
579 pars.m_hash_field.in(hash) |
580 pars.m_prov_field.in(prevCellProvenance);
581 vProvenance.push_back ((data>>16) & 0xffff);
582 vProvenance.push_back (data & 0xffff);
583 }
584 }
585 else {
586 pack_lar (cell, subcalo, outit, pars);
587
588 // Check to see if the provenance changed.
589 if (version >= 500 &&
590 (cell->provenance() & pars.m_prov_max) != prevCellProvenance)
591 {
592 prevCellProvenance = cell->provenance() & pars.m_prov_max;
594 pars.m_hash_field.in(hash) |
595 pars.m_prov_field.in(prevCellProvenance);
596 vProvenance.push_back ((data>>16) & 0xffff);
597 vProvenance.push_back (data & 0xffff);
598 }
599 }
600 ++nseq;
601 }
602
603 // Finish the last sequence.
604 if (nseq != 0)
605 finish_seq (seqhash, nseq, seqit, prevcalo, pars);
606
607 pars.m_lengthProvenance = vProvenance.size();
608
609 assert (outit.used() + pars.m_length + vProvenance.size()/2 + 1 <= maxsize);
610
611 if (pars.m_lengthProvenance > 0) {
612 // this part is making existing vector to have full number of 32 bit words.
613 int x=outit.used();
614 // dummy value of 0 is inserted
615 outit.set(0);
616 int y=outit.used();
617 // if size changed it means that vector was flat at the end and that we spoiled it.
618 // so we have to fix it.
619 if (x!=y) outit.set(0);
620 // now its surely flat.
621
622 // add provenance stuff at the end.
623 for (unsigned short & iter : vProvenance)
624 {
625 outit.set (iter);
626 }
627 }
628
629 // Now resize the container to the final size.
630 packed.resize (outit.used() + pars.m_length);
631
632 // And copy the header to the front.
633 write_header (pars, packed);
634}
#define y
#define x
void finish_seq(unsigned int hash, unsigned int nseq, CaloCompactCellContainer::compact_output_iterator &it, CaloCell_ID::SUBCALO subcalo, pars500 &pars) const
Finish up one cell sequence.
void write_header(const header &header, CaloCompactCellContainer &packed) const
Write the header to the output container.
void pack_tile(const TileCell *cell, CaloCompactCellContainer::compact_output_iterator &it, const pars500 &pars) const
Pack one tile cell.
void pack_lar(const CaloCell *cell, CaloCell_ID::SUBCALO subcalo, CaloCompactCellContainer::compact_output_iterator &it, const pars500 &pars) const
Pack one LAr cell.
void init_derived(pars500 &pars) const
Initialize the derived packing parameters from the constants in the header.
void init_header(header &header, int version) const
Initialize header with the current version of the packing parameters.
bool is_supercell(const Identifier id) const
Test if the identifier represents a supercell.
CaloCell_Base_ID::SUBCALO SUBCALO
Definition CaloCell_ID.h:50
const CaloDetDescriptor * descriptor() const
cell descriptor
const CaloCell_Base_ID * get_calo_helper() const
get Calo Cell ID helper
bool thinned(size_t ndx) const
Return true if element ndx should be thinned.
H5::CompType packed(H5::CompType in)
ID
//////////////////////////////////////// JetAlgorithmType::ID defines most common physics jet finding...

◆ pack_lar()

void CaloCellPacker_400_500::pack_lar ( const CaloCell * cell,
CaloCell_ID::SUBCALO subcalo,
CaloCompactCellContainer::compact_output_iterator & it,
const pars500 & pars ) const
inlineprivate

Pack one LAr cell.

Parameters
cellThe cell to pack.
subcaloThe cell's subcalorimeter code.
itThe iterator into which to pack.
parsThe packing parameters.

Definition at line 243 of file CaloCellPacker_400_500.cxx.

248{
249 // Get values from the cell.
250 double energy = cell->energy();
251 double time = cell->time();
252 int qualflag;
253 if( (cell->provenance() & 0x2000) == 0x2000 )
254 qualflag=pars.m_qgood;
255 else
256 qualflag=pars.m_qabad;
257
258 int gain = cell->gain();
259
260 // Figure out which gain to use.
261 // cbrt_flag is set to 1 for the high gain range (50 GeV) and 0 for
262 // the low gain range (3.2 TeV).
263 int gainflag = -999;
264 int cbrt_flag = 0;
265 switch ( gain ) {
267 gainflag = pars.m_enlow;
268 break;
270 if ( subcalo == CaloCell_ID::LARHEC &&
271 fabs(energy) < pars.m_e1_high_res )
272 {
273 gainflag = pars.m_ehhig;
274 cbrt_flag = 1;
275 }
276 else
277 gainflag = pars.m_enmed;
278 break;
280 if ( fabs(energy) < pars.m_e1_high_res &&
281 subcalo != CaloCell_ID::LARHEC )
282 {
283 gainflag = pars.m_ehhig;
284 cbrt_flag = 1;
285 }
286 else
287 gainflag = pars.m_enhig;
288 break;
289
290 default:
291 // Some invalid gain. Mark as an error.
292 gainflag = -999;
293 }
294
295 if (gainflag == -999) {
296 it.set (pars.m_lar_dummy);
297 }
298 else {
299 // Pack the energy, gain, and quality into the output word.
300 double crtae = cbrt(fabs(energy));
302 (cbrt_flag ? pars.m_crtae_high_field.in (crtae)
303 : pars.m_crtae_norm_field.in (crtae));
304
305 // Set the sign bit.
306 // Only set the sign bit if saved value is non-zero.
307 // Otherwise, it'll be read as zero regardless, and if we write
308 // again, the sign bit'll be different.
309 if (energy < 0 && data != 0)
310 data |= pars.m_esign_mask;
311
312 data |= pars.m_egain_field.in (gainflag) |
313 pars.m_qualy_field.in (qualflag);
314
315 if (data == pars.m_lar_dummy)
316 data = pars.m_lar_dummy_subst;
317
318 // Fill the output container.
319 it.set (data);
320
321 // If quality is not bad there are time and quality (chi^2) measurements.
322 if ( qualflag != pars.m_qabad){
323 pack_time (time, it, pars);
324 if (pars.m_version >= 500)
325 it.set(cell->quality());
326 }
327 }
328}
void pack_time(float time, CaloCompactCellContainer::compact_output_iterator &it, const pars500 &pars) const
Pack a time value.
unsigned short value_type
value type for the compact CaloCell data
@ LARMEDIUMGAIN
Definition CaloGain.h:18
@ LARLOWGAIN
Definition CaloGain.h:18
@ LARHIGHGAIN
Definition CaloGain.h:18
time(flags, cells_name, *args, **kw)

◆ pack_tile()

void CaloCellPacker_400_500::pack_tile ( const TileCell * cell,
CaloCompactCellContainer::compact_output_iterator & it,
const pars500 & pars ) const
inlineprivate

Pack one tile cell.

Parameters
cellThe cell to pack.
itThe iterator into which to pack.
parsThe packing parameters.

Definition at line 338 of file CaloCellPacker_400_500.cxx.

342{
343 // Tile cells have two separate measurements to pack.
344 // Retrieve them both:
345 double ene[2] = {cell->ene1(), cell->ene2()};
346 double time[2] = {cell->time1(), cell->time2()};
347 int qbit[2] = {cell->qbit1(), cell->qbit2()};
348 int gain[2] = {cell->gain1(), cell->gain2()};
349
350 // Loop over the two measurements (PMTs).
351 // If no cell both gains are bad;
352 // if only one pmt per cell, second gain is bad.
353 bool write_qual = false;
354 for (int ipmt=0; ipmt<2; ++ipmt) {
355 // We'll set this to true if we want to write time information.
356 bool write_time = false;
357
358 // The data word we're building.
360
361 // Does this measurement exist?
362 if (gain[ipmt] == CaloGain::INVALIDGAIN) {
363 // No --- make a dummy.
364 data = pars.m_tile_dummy;
365 }
366 else {
367 // Yes --- we have a measurement. See if the quality's good.
368 // If so, then we'll want to write the time too.
369 int qualflag = pars.m_qabad;
370 if (qbit[ipmt] >= TileCell::KEEP_TIME) {
371 qualflag = pars.m_qgood;
372 write_time = true;
373 write_qual = true;
374 }
375
376 // Pack the energy, with the proper range, depending on the gain.
377 double crtae = cbrt(fabs(ene[ipmt]));
378 if (gain[ipmt] != pars.m_glow)
379 data = pars.m_crtae_tile_high_field.in (crtae);
380 else
381 data = pars.m_crtae_tile_low_field.in (crtae);
382
383 // Add the sign bit.
384 // Only set the sign bit if saved value is non-zero.
385 // Otherwise, it'll be read as zero regardless, and if we write
386 // again, the sign bit'll be different.
387 if (ene[ipmt] < 0 && data != 0)
388 data |= pars.m_esign_tile_mask;
389
390 // Add in the gain and quality.
391 data |=
392 pars.m_egain_tile_field.in (gain[ipmt]) |
393 pars.m_qualy_field.in (qualflag);
394
395 if (data == pars.m_tile_dummy)
396 data = pars.m_tile_dummy_subst;
397 }
398
399 // Fill to the output container.
400 it.set (data);
401
402 // Fill the time and quality, if needed.
403 if (write_time)
404 pack_time (time[ipmt], it, pars);
405 }
406
407 if (pars.m_version >= 502 && write_qual) {
408 it.set (cell->quality());
409 }
410}
@ KEEP_TIME
Definition TileCell.h:83
@ INVALIDGAIN
Definition CaloGain.h:18

◆ pack_time()

void CaloCellPacker_400_500::pack_time ( float time,
CaloCompactCellContainer::compact_output_iterator & it,
const pars500 & pars ) const
inlineprivate

Pack a time value.

Parameters
timeThe time to pack.
itThe iterator into which to pack.
parsThe packing parameters.

Definition at line 210 of file CaloCellPacker_400_500.cxx.

214{
215 // We want to pack log(abs(time)).
216 float ltime = pars.m_log_t0;
217 if (time != 0)
218 ltime = log(fabs(time));
219
220 // Pack it into the bitfield.
221 CaloCompactCell::value_type data = pars.m_logat_field.in (ltime);
222
223 // Set the sign bit.
224 // Only set the sign bit if saved value is non-zero.
225 // Otherwise, it'll be read as zero regardless, and if we write
226 // again, the sign bit'll be different.
227 if ( time < 0 && data != 0 )
228 data |= pars.m_tsign_mask;
229
230 // Fill output.
231 it.set (data);
232}

◆ unpack()

void CaloCellPacker_400_500::unpack ( const CaloCompactCellContainer & packed,
const std::vector< CaloCompactCellContainer::value_type > & vheader,
CaloCellContainer & cells,
DataPool< LArCell > & larpool,
DataPool< TileCell > & tilepool ) const

Unpack cells.

Parameters
packedThe input packed cell container.
vheaderThe header part of the packed data.
cellsThe output cell container.
larpoolPool for allocating LAr cells.
tilepoolPool for allocating Tile cells.

Note that allocations will be done from the provided pools, and the pools retain ownership of the cells. The cells container will be changed to a view container.

Definition at line 876 of file CaloCellPacker_400_500.cxx.

882{
883 // Convert the header.
884 pars500 pars;
885 pars.m_status = 0;
886 pars.m_seq_tile = 0;
887 pars.m_seq_larem = 0;
888 pars.m_seq_larhec = 0;
889 pars.m_seq_larfcal = 0;
890 pars.m_lengthProvenance = 0;
891 pars.m_ncells_tile = 0;
892 pars.m_ncells_larhec = 0;
893 pars.m_ncells_larfcal = 0;
894 pars.m_ncells_larem = 0;
895
896 {
897 const int* headerbeg = &*vheader.begin();
898 const int* headerend = headerbeg + vheader.size();
899 size_t nheader = headerend - headerbeg;
900 size_t parsize = sizeof(header) / sizeof(int);
901 size_t ncopy = std::min (nheader, parsize);
902 int* parsbeg = reinterpret_cast<int*>(&pars);
903 std::copy (headerbeg, headerbeg+ncopy, parsbeg);
904 if (nheader > parsize) {
905 // Header was longer than we expected --- there's something
906 // wrong with the data. Issue a warning.
907 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
908 "CaloCellPacker_400_500 ")
909 << "Corrupted data: Compact cell header is "
910 << nheader << " words long, longer than the largest expected value of "
911 << parsize << ".";
912 }
913 else if (ncopy < parsize) {
914 // Header was shorter than we expected.
915 // It may be a previous version --- clear out the remainder of pars.
916 // TODO: Cross-check the size we got with what we expect based
917 // on the version number in the header.
918 std::fill (parsbeg + ncopy, parsbeg + parsize, 0);
919 }
920 }
921
922 // Initialize derived parameters from the header.
923 init_derived (pars);
924
925 // Bounds check on size of provenance.
926 unsigned nprov = pars.m_lengthProvenance/2;
927 if (nprov + vheader.size() > packed.getData().size()) {
928 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
929 "CaloCellPacker_400_500 ")
930 << "Corrupted data: Provenance count too large "
931 << pars.m_lengthProvenance << ".";
932 pars.m_lengthProvenance = 0;
933 nprov = 0;
934 }
935
936 // need to make a new iterator and use it for provenance.
937 CaloCompactCellContainer::compact_input_iterator provIt =
938 packed.compact_begin_input_from(pars.m_lengthProvenance/2);
939 unsigned iprov=0;
940
941 // getting starting values
942 short unsigned int currProvValue=0;
943 int nextProvHash=-1;
944 short unsigned int nextProvValue=0;
945 if (pars.m_lengthProvenance) {
946 unsigned int provhash = provIt.next();
947 provhash = (provhash<<16) | provIt.next();
948 nextProvValue = pars.m_prov_field.out (provhash);
949 nextProvHash = pars.m_hash_field.out (provhash);
950 iprov++;
951 }
952
953 bool is_SC = (pars.m_status & header::STATUS_IS_SUPERCELL);
954
955 // We need the detector description.
956 const CaloDetDescrManager_Base *ddmgr = nullptr;
957 if (is_SC){
958 SG::ReadCondHandleKey<CaloSuperCellDetDescrManager> caloSuperCellMgrKey {"CaloSuperCellDetDescrManager"};
959 StatusCode sc = caloSuperCellMgrKey.initialize();
960 if(sc.isFailure()) {
961 throw std::runtime_error("Failed to initialize ReadCondHandleKey for CaloSuperCellDetDescrManager");
962 }
963 SG::ReadCondHandle<CaloSuperCellDetDescrManager> caloSuperCellMgrHandle{caloSuperCellMgrKey};
964 ddmgr = *caloSuperCellMgrHandle;
965 }
966 else {
967 SG::ReadCondHandleKey<CaloDetDescrManager> caloMgrKey {"CaloDetDescrManager"};
968 StatusCode sc = caloMgrKey.initialize();
969 if(sc.isFailure()) {
970 throw std::runtime_error("Failed to initialize ReadCondHandleKey for CaloDetDescrManager");
971 }
972 SG::ReadCondHandle<CaloDetDescrManager> caloMgrHandle{caloMgrKey};
973 ddmgr = *caloMgrHandle;
974 }
975 const CaloCell_Base_ID *calo_id = ddmgr->getCaloCell_ID();
976
977 // Clear the output container and reserve the right number of elements.
979 CaloCell_ID::size_type totcells =
980 pars.m_ncells_larem + pars.m_ncells_larhec +
981 pars.m_ncells_larfcal + pars.m_ncells_tile;
982 if (totcells > calo_id->calo_cell_hash_max()) {
983 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
984 "CaloCellPacker_400_500 ")
985 << "Corrupted data: Too many cells " << totcells << ".";
986 totcells = calo_id->calo_cell_hash_max();
987 }
988 cells.reserve (totcells);
989
990 // Iterator for scanning the input.
991 CaloCompactCellContainer::compact_input_iterator it =
992 packed.compact_begin_input();
993
994 // To test for falling off the end.
995 std::vector<CaloCompactCellContainer::value_type>::const_iterator pend =
996 packed.getData().end() - (pars.m_lengthProvenance+1)/2;
997
998 // Sum up the total number of cells/sequences over all subcalos.
999 unsigned int ncells =
1000 pars.m_ncells_larem +
1001 pars.m_ncells_larhec +
1002 pars.m_ncells_larfcal +
1003 pars.m_ncells_tile;
1004 unsigned int nseqs =
1005 pars.m_seq_larem +
1006 pars.m_seq_larhec +
1007 pars.m_seq_larfcal +
1008 pars.m_seq_tile;
1009
1010 // Note: In the first version of the v400 packer, the sequence counts
1011 // would be left uninitialized if ncells==0.
1012 if (ncells == 0)
1013 nseqs = 0;
1014
1015 // Warn if there are too many cells/sequences.
1016 IdentifierHash hashmax = calo_id->calo_cell_hash_max();
1017 if (ncells > hashmax || nseqs > hashmax || nseqs > ncells) {
1018 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
1019 "CaloCellPacker_400_500 ")
1020 << "Corrupted data: Bad counts"
1021 << ": ncells " << ncells << " nseqs " << nseqs << " hashmax " << hashmax;
1022 }
1023
1025
1026 // Loop over sequences.
1027 for (; nseqs > 0; --nseqs) {
1028
1029 // Check for overrun.
1030 if (it.base() >= pend) {
1031 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
1032 "CaloCellPacker_400_500 ")
1033 << "Corrupted data: cell vector overrun.";
1034 break;
1035 }
1036
1037 // Get the starting hash code and count.
1039 unsigned int hashlength = data << 16;
1040 hashlength |= it.next();
1041
1042 unsigned int hash = pars.m_hash_field.out (hashlength);
1043 unsigned int nseq = pars.m_nseq_field.out (hashlength);
1044
1045 if (nseq > ncells || hash+nseq > hashmax)
1046 {
1047 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
1048 "CaloCellPacker_400_500 ")
1049 << "Corrupted data: bad sequence. "
1050 << "nseq " << nseq << " hash " << hash << " ncells " << ncells
1051 << " hashmax " << hashmax;
1052 break;
1053 }
1054
1055 // Subcalo code for this cell.
1056 CaloCell_ID::SUBCALO subcalo =
1057 static_cast<CaloCell_ID::SUBCALO> (calo_id->sub_calo (hash));
1058
1059 // Maintain the cell container's pointers --- only if cells were ordered!
1060 if (subcalo != prevcalo) {
1061 if ((pars.m_status & header::STATUS_UNORDERED) == 0) {
1062 if (prevcalo != CaloCell_ID::NOT_VALID) {
1063 cells.updateCaloEndIterators (prevcalo, cells.size());
1064 if (subcalo < prevcalo) {
1065 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
1066 "CaloCellPacker_400_500 ")
1067 << "Cells not in subcalo order; iterators will be wrong.";
1068 }
1069 }
1070 cells.updateCaloBeginIterators (subcalo, cells.size());
1071 }
1072 cells.setHasCalo (subcalo);
1073 prevcalo = subcalo;
1074 }
1075
1076 // Loop over cells in the sequence.
1077 while (nseq--) {
1078 // Find the descriptor element for this cell.
1079 const CaloDetDescrElement *dde = ddmgr->get_element(hash);
1080
1081 if (dde == nullptr) {
1082 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
1083 "CaloCellPacker_400_500 ")
1084 << "Corrupted data: can't find DDE for cell with hash " << hash;
1085 }
1086
1087 // Unpack the cell.
1088 //
1089 // One point here that needs explaining.
1090 // The pack_tile method returns a TileCell by value.
1091 // Normally, this would involve a copy; however, we're careful
1092 // to allow the compiler to use the `return value optimization'
1093 // to avoid this copy. That way, we can use the TileCell constructor
1094 // directly, without having to add extra set methods (or violate
1095 // encapsulation, as the previous version of this code did).
1096 // We get a pointer to a TileCell from the data pool and
1097 // use this in a placement new to initialize a TileCell
1098 // using the value returned from unpack_tile. Due to the RVO,
1099 // the copy is avoided, and the constructor in unpack_tile
1100 // will run its constructor directly on the pointer gotten
1101 // from the pool. For this to work correctly, we rely
1102 // on the fact that TileCell has only a trivial destructor ---
1103 // thus it's safe to rerun the constructor on an object that
1104 // has already been constructed.
1105 //
1106 // You'll notice, however, that CaloCell is done differently.
1107 // CaloCell is not a simple class; it has a complicated inheritance
1108 // structure. It was found that setting up all the vtable pointers
1109 // in CaloCell was taking a considerable amount of time
1110 // (comparable to filling in the cell data). So, for CaloCell,
1111 // we instead add a couple new (inlined) set methods to fill
1112 // in the data directly, without having to redo the vtable pointers.
1113 // We split it in two, one for dde/id and the other for the cell data,
1114 // to reduce the amount of data we need to pass to unpack_lar.
1115 //
1116 // Why wasn't the same thing done for TileCell, then?
1117 // - I don't have TC rights for TileEvent, so changing that
1118 // is more of a hassle.
1119 // - There are many fewer tile cells than LAr cells.
1120 // - The TileCell constructor we use is significantly
1121 // more complicated than LArCell. We'd have to duplicate
1122 // this code. Further, this, together with the previous
1123 // point, implies that the performance implications
1124 // of rebuilding the vtable pointers is much less
1125 // for tile cells than for LAr cells.
1126
1127 // New provenance?
1128 if (hash==static_cast<unsigned int>(nextProvHash)){
1129 currProvValue = nextProvValue;
1130 if (iprov<nprov) {
1131 unsigned int provhash = provIt.next();
1132 provhash = (provhash<<16) | provIt.next();
1133 nextProvValue = pars.m_prov_field.out (provhash);
1134 nextProvHash = pars.m_hash_field.out (provhash);
1135 iprov++;
1136 } else {
1137 nextProvHash = -1;
1138 }
1139 }
1140
1141 CaloCell* cell;
1142 if (!is_SC && subcalo == CaloCell_ID::TILE)
1143 cell = new (tilepool.nextElementPtr())
1144 TileCell (unpack_tile (it,
1145 dde,
1146 pars, currProvValue));
1147 else {
1148 cell = unpack_lar (it,
1149 subcalo,
1150 larpool.nextElementPtr(),
1151 pars,
1152 currProvValue);
1153 cell->set (dde, calo_id->cell_id(hash));
1154 }
1155
1156 // Add the cell to the container.
1157 if (dde)
1158 cells.push_back (cell);
1159
1160 // Move to next cell.
1161 ++hash;
1162 }
1163 }
1164
1165 // Finish off the last iterator.
1166 if (prevcalo != CaloCell_ID::NOT_VALID)
1167 cells.updateCaloEndIterators (prevcalo, cells.size());
1168
1169 // Check that we've consumed all the data.
1170 // Note that there may be a padding word before the provenance word.
1171 if (it.base() < pend-2) {
1172 REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,
1173 "CaloCellPacker_400_500 ")
1174 << "Corrupted data: didn't consume all packed data.";
1175 }
1176}
#define REPORT_MESSAGE_WITH_CONTEXT(LVL, CONTEXT_NAME)
Report a message, with an explicitly specified context name.
static Double_t sc
CaloCell * unpack_lar(CaloCompactCellContainer::compact_input_iterator &it, CaloCell_ID::SUBCALO subcalo, LArCell *cell, const pars500 &pars, uint16_t provenance) const
Unpack a LAr cell.
TileCell unpack_tile(CaloCompactCellContainer::compact_input_iterator &it, const CaloDetDescrElement *dde, const pars500 &pars, uint16_t provenance) const
Unpack a tile cell.
int sub_calo(const Identifier id) const
returns an int taken from SUBCALO enum and describing the subCalo to which the Id belongs.
size_type calo_cell_hash_max() const
cell 'global' hash table max size
Identifier cell_id(const int subCalo, const int barec_or_posneg, const int sampling_or_fcalmodule, const int region_or_dummy, const int eta, const int phi) const
Make a cell (== channel) ID from constituting fields and subCalo index; for (Mini)FCAL,...
CaloCell_Base_ID::size_type size_type
Definition CaloCell_ID.h:38
CaloCompactCell::value_type next()
Return the current value and advance to the next one.
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
const CaloCell_Base_ID * getCaloCell_ID() const
get calo cell ID helper
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
StatusCode initialize(bool used=true)
::StatusCode StatusCode
StatusCode definition for legacy code.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts

◆ unpack_lar()

CaloCell * CaloCellPacker_400_500::unpack_lar ( CaloCompactCellContainer::compact_input_iterator & it,
CaloCell_ID::SUBCALO subcalo,
LArCell * cell,
const pars500 & pars,
uint16_t provenance ) const
inlineprivate

Unpack a LAr cell.

Parameters
itInput iterator.
subcaloSubcalorimeter code for the cell.
cellPointer to the cell in which to write.
parsUnpacking parameters.
provenanceThe provenance word for this cell.
Returns
cell, as a CaloCell*.

The DDE and ID will be set in the cell separately; here, we need only fill in the cell data.

Definition at line 704 of file CaloCellPacker_400_500.cxx.

710{
711 // Get the data word from the input.
713
714 // Recognize cells filled with dummy values.
715 if (data == pars.m_lar_dummy)
716 {
717 cell->set (0, 0, 0, provenance, CaloGain::INVALIDGAIN);
718 return cell;
719 }
720
721 // Unpack the gain flag.
722 int gainflag = pars.m_egain_field.out (data);
723 int qualflag = pars.m_qualy_field.out (data);
724
726
727 // Convert to the CaloCell gain, and convert the energy back to a float
728 // using the proper range.
729 double energy;
730 if ( gainflag == pars.m_ehhig ) {
731 if ( subcalo == CaloCell_ID::LARHEC )
733 else
735 energy = pars.m_crtae_high_field.out (data);
736 }
737 else {
738 if ( gainflag == pars.m_enhig ) {
740 }
741 else if ( gainflag == pars.m_enmed ) {
743 }
744 else if ( gainflag == pars.m_enlow) {
746 }
747 energy = pars.m_crtae_norm_field.out (data);
748 }
749
750 // Now undo the cube root and apply the sign bit.
752 if (data & pars.m_esign_mask)
753 energy = -energy;
754
755 // If the quality's good, then we need to unpack the time/chi2 too.
756 double time = 0;
757 uint16_t quality=0;
758 if ( qualflag != pars.m_qabad ) {
759 time = unpack_time (it, pars);
760 if (pars.m_version >= 500)
761 quality=it.next();
762 provenance = provenance | 0x2000;
763 }
764
765 // Fill the data into the cell.
766 cell->set (energy, time, quality, provenance, gain);
767
768 // Return it.
769 return cell;
770}
double unpack_time(CaloCompactCellContainer::compact_input_iterator &it, const pars500 &pars) const
Unpack the time word.
@ UNKNOWNGAIN
Definition CaloGain.h:21
setWord1 uint16_t

◆ unpack_tile()

TileCell CaloCellPacker_400_500::unpack_tile ( CaloCompactCellContainer::compact_input_iterator & it,
const CaloDetDescrElement * dde,
const pars500 & pars,
uint16_t provenance ) const
inlineprivate

Unpack a tile cell.

Parameters
itInput iterator.
ddeDescriptor element for the cell.
parsUnpacking parameters.
provenanceThe provenance word for this cell.
Returns
The new cell.
Parameters
itInput iterator.
ddeDescriptor element for the cell.
parsUnpacking parameters.
Returns
The new cell.

Definition at line 781 of file CaloCellPacker_400_500.cxx.

786{
787 // Loop over the two elements for the cell.
788 double ene[2];
789 double time[2];
790 int gain[2];
791 int qbit[2];
792
793 bool read_qual = false;
794
795 for (int ipmt = 0; ipmt < 2; ++ipmt) {
796 // Unpack the data word.
798
799 // Is this measurement a dummy?
800 if (data == pars.m_tile_dummy)
801 {
802 // Yeah --- fill in dummy values and skip the rest.
803 ene[ipmt] = 0;
805 qbit[ipmt] = 0;
806 if (ipmt == 1)
807 time[ipmt] = time[0];
808 else
809 time[ipmt] = 0;
810 continue;
811 }
812
813 // Get the quality and gain.
814 int qualflag = pars.m_qualy_field.out (data);
815 int gainflag = pars.m_egain_tile_field.out (data);
816
817 gain[ipmt] = gainflag;
818
819 // Unpack the energy, using the range appropriate to the gain.
820 double e;
821 if (gainflag != pars.m_glow)
822 e = pars.m_crtae_tile_high_field.out (data);
823 else
824 e = pars.m_crtae_tile_low_field.out (data);
825 ene[ipmt] = e*e*e;
826 if (data & pars.m_esign_tile_mask)
827 ene[ipmt] = -ene[ipmt];
828
829 // If the quality is good, we need to unpack the time too.
830 if (qualflag != pars.m_qabad) {
831 read_qual = true;
832 time[ipmt] = unpack_time (it, pars);
834 }
835 else {
836 time[ipmt] = 0;
837 qbit[ipmt] = TileCell::MASK_CMPC;
838 }
839 }
840
841 uint8_t qual[2];
842 if (pars.m_version >= 502) {
843 qbit[0] |= pars.m_tile_qual1_field.out (provenance);
844 qbit[1] |= pars.m_tile_qual2_field.out (provenance);
845 if (read_qual) {
846 uint16_t qualp = it.next();
847 qual[0] = pars.m_tile_qual1_field.out (qualp);
848 qual[1] = pars.m_tile_qual2_field.out (qualp);
849 } else {
850 qual[0] = ((qbit[0] & TileCell::MASK_BADCH) != 0) ? 255 : 0;
851 qual[1] = ((qbit[1] & TileCell::MASK_BADCH) != 0) ? 255 : 0;
852 }
853 }
854 else {
855 qual[0] = qual[1] = 0;
856 }
857
858 // Make the cell.
859 return TileCell (dde, ene[0], ene[1], time[0], time[1],
860 qual[0], qual[1], qbit[0], qbit[1], gain[0], gain[1]);
861}
@ MASK_TIME
Definition TileCell.h:67
@ MASK_CMPC
Definition TileCell.h:66
@ MASK_BADCH
Definition TileCell.h:63

◆ unpack_time()

double CaloCellPacker_400_500::unpack_time ( CaloCompactCellContainer::compact_input_iterator & it,
const pars500 & pars ) const
inlineprivate

Unpack the time word.

Parameters
itInput iterator.
parsUnpacking parameters.
Returns
The unpacked time.

Definition at line 667 of file CaloCellPacker_400_500.cxx.

670{
671 // Get the word from the input container.
673
674 // Unpack to a float.
675 int underflow;
676 double time = pars.m_logat_field.out (data, underflow);
677 if (underflow) [[unlikely]]
678 return 0;
679
680 // Exponentiate, and restore the sign.
681 // (nb. introducing `ee' helps the gcc optimizer avoid a redundant
682 // test on the underflow flag.)
683 double ee = std::exp (time);
684 if (data & pars.m_tsign_mask)
685 return -ee;
686 return ee;
687}
#define unlikely(x)

◆ write_header()

void CaloCellPacker_400_500::write_header ( const header & header,
CaloCompactCellContainer & packed ) const
private

Write the header to the output container.

Parameters
headerThe header to write.
packedThe container to which to write.

Definition at line 643 of file CaloCellPacker_400_500.cxx.

645{
646 const int * phead = &(header.m_length);
647 std::vector<CaloCompactCellContainer::value_type>
648 vhead (phead, phead + header.m_length);
649 packed.setHeader(vhead);
650}

◆ CaloCellPacker_400_500_test

friend class CaloCellPacker_400_500_test
friend

Definition at line 483 of file CaloCellPacker_400_500.h.


The documentation for this class was generated from the following files: