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 header &header, 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 (header &header, int version) const
 Initialize header with the current version of the packing parameters.
void clear_header (header &header) 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 103 of file CaloCellPacker_400_500.cxx.

104{
105 header.m_ncells_larem = 0;
106 header.m_ncells_larhec = 0;
107 header.m_ncells_larfcal = 0;
108 header.m_ncells_tile = 0;
109 header.m_seq_larem = 0;
110 header.m_seq_larhec = 0;
111 header.m_seq_larfcal = 0;
112 header.m_seq_tile = 0;
113 header.m_lengthProvenance = 0;
114 header.m_status = 0;
115}
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 423 of file CaloCellPacker_400_500.cxx.

429{
430 // Pack the hash code and number of cells into a bitfield.
432 pars.m_hash_field.in(hash) | pars.m_nseq_field.in(nseq);
433
434 // Write it into the output container.
435 it.set ((data>>16) & 0xffff);
436 it.set (data & 0xffff);
437
438 // Update counters.
439 switch (subcalo) {
441 pars.m_ncells_larem += nseq;
442 ++pars.m_seq_larem;
443 break;
445 pars.m_ncells_larhec += nseq;
446 ++pars.m_seq_larhec;
447 break;
449 pars.m_ncells_larfcal += nseq;
450 ++pars.m_seq_larfcal;
451 break;
453 pars.m_ncells_tile += nseq;
454 ++pars.m_seq_tile;
455 break;
456 default:
457 std::abort();
458 }
459}
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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 123 of file CaloCellPacker_400_500.cxx.

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

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

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

◆ 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 244 of file CaloCellPacker_400_500.cxx.

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

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

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

◆ 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 877 of file CaloCellPacker_400_500.cxx.

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

711{
712 // Get the data word from the input.
714
715 // Recognize cells filled with dummy values.
716 if (data == pars.m_lar_dummy)
717 {
718 cell->set (0, 0, 0, provenance, CaloGain::INVALIDGAIN);
719 return cell;
720 }
721
722 // Unpack the gain flag.
723 int gainflag = pars.m_egain_field.out (data);
724 int qualflag = pars.m_qualy_field.out (data);
725
727
728 // Convert to the CaloCell gain, and convert the energy back to a float
729 // using the proper range.
730 double energy;
731 if ( gainflag == pars.m_ehhig ) {
732 if ( subcalo == CaloCell_ID::LARHEC )
734 else
736 energy = pars.m_crtae_high_field.out (data);
737 }
738 else {
739 if ( gainflag == pars.m_enhig ) {
741 }
742 else if ( gainflag == pars.m_enmed ) {
744 }
745 else if ( gainflag == pars.m_enlow) {
747 }
748 energy = pars.m_crtae_norm_field.out (data);
749 }
750
751 // Now undo the cube root and apply the sign bit.
753 if (data & pars.m_esign_mask)
754 energy = -energy;
755
756 // If the quality's good, then we need to unpack the time/chi2 too.
757 double time = 0;
758 uint16_t quality=0;
759 if ( qualflag != pars.m_qabad ) {
760 time = unpack_time (it, pars);
761 if (pars.m_version >= 500)
762 quality=it.next();
763 provenance = provenance | 0x2000;
764 }
765
766 // Fill the data into the cell.
767 cell->set (energy, time, quality, provenance, gain);
768
769 // Return it.
770 return cell;
771}
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 782 of file CaloCellPacker_400_500.cxx.

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

671{
672 // Get the word from the input container.
674
675 // Unpack to a float.
676 int underflow;
677 double time = pars.m_logat_field.out (data, underflow);
678 if (ATH_UNLIKELY(underflow))
679 return 0;
680
681 // Exponentiate, and restore the sign.
682 // (nb. introducing `ee' helps the gcc optimizer avoid a redundant
683 // test on the underflow flag.)
684 double ee = std::exp (time);
685 if (data & pars.m_tsign_mask)
686 return -ee;
687 return ee;
688}
#define ATH_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 644 of file CaloCellPacker_400_500.cxx.

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

◆ 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: