diff --git a/Calorimeter/CaloTools/CaloTools/CaloAffectedTool.h b/Calorimeter/CaloTools/CaloTools/CaloAffectedTool.h new file mode 100755 index 0000000000000000000000000000000000000000..260e11efb79dde6f7cb14f1f5a613914d82d52f0 --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloAffectedTool.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + @class CaloAffectedTool + @brief Tool to check if object is in an affected region + @author G.Unal +*/ + +#ifndef CALOTOOLS_CaloAffectedTool_H +#define CALOTOOLS_CaloAffectedTool_H + + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "CaloInterface/ICaloAffectedTool.h" +#include "CaloConditions/CaloAffectedRegionInfoVec.h" +#include "AthenaKernel/IOVSvcDefs.h" + +namespace xAOD { + class IParticle; +} + +class StoreGateSvc; + +class CaloAffectedTool: public AthAlgTool, + virtual public ICaloAffectedTool, virtual public IIncidentListener +{ +private: + + CaloAffectedRegionInfoVec* m_affectedRegions; + + StatusCode updateAffectedRegionsFromDB(IOVSVC_CALLBACK_ARGS); + + StatusCode readDB(); + + void handle(const Incident& inc); + + bool m_read; + + bool m_readRaw; + +public: + + CaloAffectedTool(const std::string& type, + const std::string& name, + const IInterface* parent); + virtual ~CaloAffectedTool(); + + virtual bool isAffected(const xAOD::IParticle *p, float deta=0., float dphi=0., int layer_min=0, int layer_max=-1, int problemType=-1); + + virtual bool listAffected(const xAOD::IParticle* p, std::vector<int>& layer_list, std::vector<int>& problem_list, float deta=0, float dphi=0, int problemType=-1); + + StatusCode initialize(); + + +}; + +#endif diff --git a/Calorimeter/CaloTools/CaloTools/CaloCellPackerUtils.h b/Calorimeter/CaloTools/CaloTools/CaloCellPackerUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..d612a3c3d3702d28a1dfb3db068866175059031e --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloCellPackerUtils.h @@ -0,0 +1,176 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCellPackerUtils.h,v 1.1 2007-11-08 18:14:20 ssnyder Exp $ + +/** + * @file CaloTools/CaloCellPackerUtils.h + * @author scott snyder + * @date Nov 2007 + * @brief Utilities for compacting calorimeter cells. + */ + + +#ifndef CALOCELLPACKERUTILS_H +#define CALOCELLPACKERUTILS_H + + +#include "GaudiKernel/Kernel.h" // For LIKELY + + +namespace CaloCellPackerUtils { + + +/** + * @brief Helper for packing into/out of a bit field. + * + * The bitfield is identified by a bitmask, which should + * contain a contiguous string of 1's. The @c in function + * will then take a value and shift and mask it appropriately + * for the bitfield. The @c out function will extract a value + * from the bitfield. + */ +class Bitfield +{ +public: + /** + * @brief Constructor. + * @param The bit mask. Should contain a single contiguous string of 1's. + */ + Bitfield (unsigned int mask = 1); + + + /** + * @brief Shift and mask a value into the bitfield. + * @param x The input value. + * @return The value shifted and masked to go into the bitfield. + */ + unsigned int in (unsigned int x) const; + + + /** + * @brief Extract a value from the bitfield. + * @param x The input bitfield. + * @return The value extracted from the bitfield. + */ + unsigned int out (unsigned int x) const; + + +protected: + /// Bitmask. Lower bit should be 1. + unsigned int m_mask; + + /// Shift count. + unsigned int m_shift; +}; + + +/** + * @brief Helper for packing a float into/out of a bit field. + * + * This works like the bitfield class above, except that the + * @c in/@c out methods take floating-point values. + * The field takes a min/max range of values; the input value is converted + * to a fraction within the range, and that fraction is stored. + */ +class Floatfield + : public Bitfield +{ +public: + /** + * @brief Constructor. + * @param The bit mask. Should contain a single contiguous string of 1's. + * @param xmin The smallest storable value. + * @param xmax The largest storable value. + */ + Floatfield (unsigned int mask=1, double xmin=1, double xmax=0); + + + /** + * @brief Shift and mask a value into the bitfield. + * @param x The input value. + * @return The converted value shifted and masked to go into the bitfield. + */ + unsigned int in (double x) const; + + + /** + * @brief Extract a value from the bitfield. + * @param x The input bitfield. + * @param underflag[out] Set to 1 if the value was the lowest possible. + * @return The value extracted from the bitfield. + */ + double out (unsigned int x, int& underflow) const; + + +private: + /// Smallest representable value. + double m_xmin; + + /// Largest representable value. + double m_xmax; + + /// Cached factor for int->float conversions. + double m_fact; + + /// Cached factor for float->int conversions. + double m_ifact; +}; + + +/** + * @brief Helper for packing a float into/out of a bit field, with + * a minimum of 0. + * + * This is just like @c Floatfield, specialized for the case where @c xmin==0. + */ +class Floatfield2 + : public Bitfield +{ +public: + /** + * @brief Constructor. + * @param The bit mask. Should contain a single contiguous string of 1's. + * @param xmax The largest storable value. + */ + Floatfield2 (unsigned int mask=1, double xmax=1); + + + /** + * @brief Shift and mask a value into the bitfield. + * @param x The input value. + * @return The converted value shifted and masked to go into the bitfield. + */ + unsigned int in (double x) const; + + + /** + * @brief Extract a value from the bitfield. + * @param x The input bitfield. + * @return The value extracted from the bitfield. + */ + double out (unsigned int x) const; + + +private: + /// Largest representable value. + double m_xmax; + + /// Cached factor for int->float conversions. + double m_fact; + + /// Cached factor for float->int conversions. + double m_ifact; +}; + + +} // namespace CaloCellPackerUtils + + +#include "CaloTools/CaloCellPackerUtils.icc" + + +#endif // not CALOCELLPACKERUTILS_H diff --git a/Calorimeter/CaloTools/CaloTools/CaloCellPackerUtils.icc b/Calorimeter/CaloTools/CaloTools/CaloCellPackerUtils.icc new file mode 100644 index 0000000000000000000000000000000000000000..d61d3d5a1965423b57fb8593a685a80d3c2ba632 --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloCellPackerUtils.icc @@ -0,0 +1,127 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCellPackerUtils.icc,v 1.1 2007-11-08 18:14:20 ssnyder Exp $ +/** + * @file CaloTools/CaloCellPackerUtils.icc + * @author scott snyder + * @date Nov 2007 + * @brief Utilities for compacting calorimeter cells. + */ + + +namespace CaloCellPackerUtils { + + +/** + * @brief Shift and mask a value into the bitfield. + * @param x The input value. + * @return The value shifted and masked to go into the bitfield. + */ +inline +unsigned int Bitfield::in (unsigned int x) const +{ + return (x&m_mask)<<m_shift; +} + + +/** + * @brief Extract a value from the bitfield. + * @param x The input bitfield. + * @return The value extracted from the bitfield. + */ +inline +unsigned int Bitfield::out (unsigned int x) const +{ + return (x>>m_shift)&m_mask; +} + + +/** + * @brief Shift and mask a value into the bitfield. + * @param x The input value. + * @return The converted value shifted and masked to go into the bitfield. + */ +inline +unsigned int Floatfield::in (double x) const +{ + // Handle over/underflow. + if (UNLIKELY(x >= m_xmax)) + return Bitfield::in (m_mask); + else if (UNLIKELY(x <= m_xmin)) + return 0; + + // Convert to an int, and pack. + return Bitfield::in (static_cast<unsigned int> ((x - m_xmin) * m_ifact)); +} + + +/** + * @brief Extract a value from the bitfield. + * @param x The input bitfield. + * @param underflag[out] Set to 1 if the value was the lowest possible. + * @return The value extracted from the bitfield. + */ +inline +double Floatfield::out (unsigned int x, int& underflow) const +{ + // Unpack the value. + unsigned int xx = Bitfield::out(x); + + // Did we underflow? + if (UNLIKELY(!xx)) { + underflow = 1; + return m_xmin; + } + + // Convert back to a float. + // Note: the cast to int here is important for performance: converting + // an unsigned to a double takes much longer than converting an int. + underflow = 0; + return m_xmin + ((int)xx+0.5) * m_fact; +} + + +/** + * @brief Shift and mask a value into the bitfield. + * @param x The input value. + * @return The converted value shifted and masked to go into the bitfield. + */ +inline +unsigned int Floatfield2::in (double x) const +{ + // Handle over/underflow. + if (UNLIKELY(x >= m_xmax)) + return Bitfield::in (m_mask); + else if (UNLIKELY(x <= 0)) + return 0; + + // Convert to an int, and pack. + return Bitfield::in (static_cast<unsigned int> (x * m_ifact)); +} + + +/** + * @brief Extract a value from the bitfield. + * @param x The input bitfield. + * @return The value extracted from the bitfield. + */ +inline +double Floatfield2::out (unsigned int x) const +{ + // Unpack the value. + unsigned int xx = Bitfield::out(x); + + // Did we underflow? + // (The branch hint here gives a small but measureable improvement.) + if (UNLIKELY(xx == 0)) return 0; + + // Convert back to a float. + // Note: the cast to int here is important for performance: converting + // an unsigned to a double takes much longer than converting an int. + return ((int)xx+0.5) * m_fact; +} + + +} // namespace CaloCellPackerUtils diff --git a/Calorimeter/CaloTools/CaloTools/CaloCellPacker_400_500.h b/Calorimeter/CaloTools/CaloTools/CaloCellPacker_400_500.h new file mode 100644 index 0000000000000000000000000000000000000000..a17b6bb783189b5b6bafa76fa7caf23caf9b94bc --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloCellPacker_400_500.h @@ -0,0 +1,483 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCellPacker_400_500.h,v 1.3 2009-03-19 01:42:14 ssnyder Exp $ + +/** + * @file CaloTools/CaloCellPacker_400_500.h + * @author scott snyder, from earlier code by Ilija Vukotic and Sven Menke + * @date Jan 2009 + * @brief Calo cell packer/unpacker v400/500. + * + * This class handles both versions 400 and 500. + */ + + +#ifndef CALOCELLPACKER_400_500_H +#define CALOCELLPACKER_400_500_H + + +#include "CaloTools/CaloCellPackerUtils.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "LArRecEvent/LArCell.h" +#include "TileEvent/TileCell.h" +#include "DataModel/DataPool.h" +#include "CaloEvent/CaloCompactCellContainer.h" +#include "CaloInterface/ICaloCompactCellTool.h" +class CaloCellContainer; +class CaloCell; +struct CaloCellPacker_400_500_test; + +/** + * @brief 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 @c 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 @c header400 + * or @c 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 @c int. + * + * Following the header is a set of @e 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 + * @e 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 + */ +class CaloCellPacker_400_500 +{ +public: + /** + * @brief Pack cells. + * @param cells The input cell container. + * @param packed The output packed cell container. + * @param version The version of the header to initialize. + */ + void pack (const CaloCellContainer& cells, + CaloCompactCellContainer& packed, + int version) const; + + + /** + * @brief Unpack cells. + * @param packed The input packed cell container. + * @param vheader The header part of the packed data. + * @param cells The output cell container. + * @param larpool Pool for allocating LAr cells. + * @param tilepool Pool for allocating Tile cells. + * + * Note that allocations will be done from the provided pools, + * and the pools retain ownership of the cells. + * The @a cells container will be changed to a view container. + */ + void unpack (const CaloCompactCellContainer& packed, + const std::vector<CaloCompactCellContainer::value_type>&vheader, + CaloCellContainer& cells, + DataPool<LArCell>& larpool, + DataPool<TileCell>& tilepool) const; + +private: + + //========================================================================== + /** @name Header and parameter definitions. */ + //@{ + + /** + * @brief Packing parameters header (v400). + * + * This structure is written at the beginning of the packed data. + * It contains both the basic packing constants as well as counters + * for the number of cells and sequences. + * + * These values are initialized in @c init_header. + * + * Since this is written directly to the persistent data, + * don't rearrange fields! + */ + struct header400 { + int m_length; // Header length, in units of int. + + int m_version; // Version code (ICaloCompactCellTool). + + /// Counters of number of cells in each subcalo. + int m_ncells_larem; + int m_ncells_larhec; + int m_ncells_larfcal; + int m_ncells_tile; + + /// Masks defining the bit positions used for various quantities. + /// These should all contain a single consecutive string of 1'.s + unsigned int m_qualy_mask; // Quality. + unsigned int m_egain_mask; // LAr gain. + unsigned int m_esign_mask; // LAr energy sign bit. + unsigned int m_crtae_mask; // LAr cbrt(energy). + unsigned int m_egain_tile_mask; // Tile gain. + unsigned int m_esign_tile_mask; // Tile energy sign bit. + unsigned int m_crtae_tile_mask; // Tile cbrt(energy). + unsigned int m_tsign_mask; // Time sign bit. + unsigned int m_logat_mask; // log(time). + + /// Various enumeration constants. + int m_qabad; // Bad quality flag. + int m_enlow; // LAr low gain. + int m_enmed; // LAr medium gain. + int m_enhig; // LAr high gain. + int m_ehhig; // LAr high gain with 50 GeV range. + int m_glow; // Tile low range. + int m_ghigh; // Tile high range. + + /// Counts of number of sequences in each subcalo. + /// Note: in early versions of the v400 packer, these words would + /// be left uninitialized if there were no cells. + int m_seq_larem; + int m_seq_larhec; + int m_seq_larfcal; + int m_seq_tile; + + /// Packing ranges for floats. + float m_e1_norm_res; // Normal LAr energy range. + float m_e1_high_res; // High gain LAr energy range. + float m_high_tile; // High gain tile energy range. + float m_low_tile; // Low gain tile energy range. + float m_t0; // Lower time range. + float m_t1; // Upper time range. + }; + + + /** + * @brief Packing parameters header (v500). + * + * This adds a count of the number of provenance entries. + */ + struct header500 + : public header400 + { + // The number of provenance entries (in 16-bit units). + // In order to know from where to start reading provenance. + unsigned int m_lengthProvenance; + }; + + + /** + * @brief Packing parameters header (v501). + * + * Also for 502. + * + * This adds a status flag. + */ + struct header501 + : public header500 + { + // A bitmask for additional status information. + // Added for version 501. + unsigned int m_status; + + enum { + // Set if the cells are not in subcalo order. + STATUS_UNORDERED = (1 << 0), + // Set if the cells are SuperCell + STATUS_IS_SUPERCELL = (1 << 1) + }; + }; + + + /// The most recent header version. + typedef header501 header; + + + /** + * @brief Derived packing parmeters. + * + * This structure contains parameters derived from those in @c header. + * It is filled in by @c init_derived. + * + * It derives from @c header, so that we just need to pass one of these + * around to access all parameters. + */ + struct pars500 + : public header + { + /// Good quality flag. + int m_qgood; + + /// Maximum number of cells in a sequence. + unsigned int m_nseq_max; + unsigned int m_prov_max; + unsigned int m_prov_max_tile; + + /// Transformed packing ranges for floats. + double m_cbrt_e1_norm_res; // cbrt(e1_norm_res) + double m_cbrt_e1_high_res; // cbrt(e1_high_res) + double m_cbrt_low_tile; // cbrt(low_tile) + double m_cbrt_high_tile; // cbrt(high_tile) + double m_log_t0; // log(t0) + double m_log_t1; // log(t1) + + /// Bitfields for various quantities. + CaloCellPackerUtils::Bitfield m_hash_field; + CaloCellPackerUtils::Bitfield m_nseq_field; + CaloCellPackerUtils::Bitfield m_prov_field; + + CaloCellPackerUtils::Bitfield m_egain_field; + CaloCellPackerUtils::Bitfield m_qualy_field; + CaloCellPackerUtils::Floatfield m_logat_field; + CaloCellPackerUtils::Floatfield2 m_crtae_norm_field; + CaloCellPackerUtils::Floatfield2 m_crtae_high_field; + CaloCellPackerUtils::Floatfield2 m_crtae_tile_low_field; + CaloCellPackerUtils::Floatfield2 m_crtae_tile_high_field; + CaloCellPackerUtils::Bitfield m_egain_tile_field; + + CaloCellPackerUtils::Bitfield m_tile_qual1_field; + CaloCellPackerUtils::Bitfield m_tile_qual2_field; + + // Some errors are flagged by setting all bits on; the resulting packed + // values are stored in @c m_lar_dummy and @c m_tile_dummy. + // These are, however, still valid encodings. If we would legitimately + // pack a value that gives the dummy word, we replace it with @c subst, + // which has the low bit of the energy cleared. This effectively reduces + // the range on the low side slightly. + CaloCompactCell::value_type m_lar_dummy; + CaloCompactCell::value_type m_lar_dummy_subst; + CaloCompactCell::value_type m_tile_dummy; + CaloCompactCell::value_type m_tile_dummy_subst; + }; + + + /** + * @brief Initialize header with the current version of the packing + * parameters. (Almost) all the constants are defined here. + * @param header The header to initialize. + * @param version The version of the header to initialize. + */ + void init_header (header& header, int version) const; + + + /** + * @brief Clear the counters in the event header. + * @param header The header to clear. + */ + void clear_header (header& header) const; + + + /** + * @brief Initialize the derived packing parameters from the constants + * in the header. + * @param pars The packing parameters. + */ + void init_derived (pars500& pars) const; + + + //@} + //========================================================================== + /** @name Packing. */ + //@{ + + + /** + * @brief Pack a time value. + * @param time The time to pack. + * @param it The iterator into which to pack. + * @param pars The packing parameters. + */ + void pack_time (float time, + CaloCompactCellContainer::compact_output_iterator& it, + const pars500& pars) const; + + + /** + * @brief Pack one LAr cell. + * @param cell The cell to pack. + * @param subcalo The cell's subcalorimeter code. + * @param it The iterator into which to pack. + * @param pars The packing parameters. + */ + void pack_lar (const CaloCell* cell, + CaloCell_ID::SUBCALO subcalo, + CaloCompactCellContainer::compact_output_iterator& it, + const pars500& pars) const; + + + /** + * @brief Pack one tile cell. + * @param cell The cell to pack. + * @param it The iterator into which to pack. + * @param pars The packing parameters. + */ + void pack_tile (const TileCell* cell, + CaloCompactCellContainer::compact_output_iterator& it, + const pars500& pars) const; + + + /** + * @brief Finish up one cell sequence. + * @param hash The hash of the first cell in the sequence. + * @param nseq The number of cells in the sequence. + * @param it Iterator pointing at the beginning of the sequence. + * @param subcalo Subcalorimeter code for the sequence. + * @param pars The packing parameters. + */ + void finish_seq (unsigned int hash, + unsigned int nseq, + CaloCompactCellContainer::compact_output_iterator& it, + CaloCell_ID::SUBCALO subcalo, + pars500& pars) const; + + + /** + * @brief Write the header to the output container. + * @param header The header to write. + * @param packed The container to which to write. + */ + void write_header (const header& header, + CaloCompactCellContainer& packed) const; + + + //@} + //========================================================================== + /** @name Unpacking. */ + //@{ + + + /** + * @brief Unpack the time word. + * @param it Input iterator. + * @param pars Unpacking parameters. + * @return The unpacked time. + */ + double unpack_time (CaloCompactCellContainer::compact_input_iterator& it, + const pars500& pars) const; + + + /** + * @brief Unpack a LAr cell. + * @param it Input iterator. + * @param subcalo Subcalorimeter code for the cell. + * @param cell Pointer to the cell in which to write. + * @param pars Unpacking parameters. + * @param provenance The provenance word for this cell. + * @return @a cell, as a @c CaloCell*. + * + * The DDE and ID will be set in the cell separately; here, we need only + * fill in the cell data. + */ + CaloCell* unpack_lar (CaloCompactCellContainer::compact_input_iterator& it, + CaloCell_ID::SUBCALO subcalo, + LArCell* cell, + const pars500& pars, + uint16_t provenance) const; + + + /** + * @brief Unpack a tile cell. + * @param it Input iterator. + * @param dde Descriptor element for the cell. + * @param pars Unpacking parameters. + * @param provenance The provenance word for this cell. + * @return The new cell. + */ + TileCell unpack_tile (CaloCompactCellContainer::compact_input_iterator& it, + const CaloDetDescrElement* dde, + const pars500& pars, + uint16_t provenance) const; + //@} + + friend struct CaloCellPacker_400_500_test; +}; + + +#endif // not CALOCELLPACKER_400_500_H diff --git a/Calorimeter/CaloTools/CaloTools/CaloCompactCellTool.h b/Calorimeter/CaloTools/CaloTools/CaloCompactCellTool.h new file mode 100755 index 0000000000000000000000000000000000000000..73db569f8ba1ad617b9ab2cb0b97061fbcda2960 --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloCompactCellTool.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef CALOTOOLS_CALOCOMPACTCELLTOOL_H +#define CALOTOOLS_CALOCOMPACTCELLTOOL_H + +/** + @class CaloCompactCellTool + @brief Tool to convert from CaloCellContainer to CaloCompactCellContainer and back + @author Sven Menke +*/ + +#include "AthenaBaseComps/AthAlgTool.h" +#include "CaloEvent/CaloCellContainer.h" +#include "CaloEvent/CaloCompactCellContainer.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CLHEP/Units/SystemOfUnits.h" + +#include <math.h> + +#include "CaloInterface/ICaloCompactCellTool.h" + +class IChronoStatSvc; + +class CaloCompactCellTool: public AthAlgTool, + virtual public ICaloCompactCellTool +{ + + public: + + CaloCompactCellTool(const std::string& type, const std::string& name, + const IInterface* parent); + + virtual ~CaloCompactCellTool(); + virtual StatusCode initialize(); + virtual StatusCode finalize(); + + StatusCode getTransient(const CaloCompactCellContainer & theCompactContainer, + CaloCellContainer * theCellContainer); + // fills a CaloCellContainer ; caller has the responsibility + // of creating and deleting the object again + + StatusCode getPersistent(const CaloCellContainer & theCellContainer, + CaloCompactCellContainer * theCompactContainer, + int theVersion = ICaloCompactCellTool::VERSION_LATEST); + // fills a CaloCompactCellContainer ; caller has the responsibility + // of creating and deleting the object again + + private: + + int getLogCompact(const double & x, const double & log_x0, const double & log_x1, const int & n); + + double unpackLog(const int & log_x, const double & log_x0, const double & log_x1, const int & n); + + int getCubRootCompact(const double & x, const double & cbrt_x1, const int & n); + + double unpackCubRoot(const int & cbrt_x, const double & cbrt_x1, const int & n); + +}; + +inline int CaloCompactCellTool::getLogCompact(const double & x, + const double & log_x0, + const double & log_x1, + const int & n) +{ + int result = 0; + if ( x > 0 ) { + double log_x = log(x); + if ( log_x >= log_x1 ) { + result = (1<<n)-1; + } + else if ( log_x > log_x0 ) { + int nmax=1<<n; + result = (int)((log_x - log_x0)/(log_x1 - log_x0)*nmax); + } + } + return result; +} + +inline int CaloCompactCellTool::getCubRootCompact(const double & x, + const double & cbrt_x1, + const int & n){ + int result = 0; + double cbrt_x=cbrt(x); + if ( cbrt_x >= cbrt_x1 ) { + result = (1<<n)-1; + } else { + int nmax=1<<n; + result = (int)(cbrt_x/cbrt_x1*nmax); + } + return result; +} + +inline double CaloCompactCellTool::unpackLog(const int & log_x, + const double & log_x0, + const double & log_x1, + const int & n){ + double result = 0; + if ( log_x > 0 ) { + int nmax=1<<n; + result = exp((log_x+0.5)*(log_x1-log_x0)/nmax+log_x0); + } + return result; +} + +inline double CaloCompactCellTool::unpackCubRoot(const int & cbrt_x, + const double & cbrt_x1, + const int & n){ + double result = 0; + if ( cbrt_x > 0 ) { + int nmax=1<<n; + double r = (cbrt_x+0.5)*cbrt_x1/nmax; + result =r*r*r; + } + return result; +} + + +#endif + diff --git a/Calorimeter/CaloTools/CaloTools/CaloLumiBCIDTool.h b/Calorimeter/CaloTools/CaloTools/CaloLumiBCIDTool.h new file mode 100755 index 0000000000000000000000000000000000000000..de006bf824295f9bfd4d3b0c8a8ca31c8826513a --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloLumiBCIDTool.h @@ -0,0 +1,108 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//Dear emacs, this is -*-c++-*- + +/** + @class CaloLumiBCIDTool + @brief Tool to provide expected pedestal shift for Pileup from first principle computation (relevant for non 25ns bunch spacing) + @author G.Unal +*/ + +#ifndef CALOTOOLS_CaloLumiBCIDTool_H +#define CALOTOOLS_CaloLumiBCIDTool_H + +class Identifier; +class StoreGateSvc; +class CaloIdManager; +class CaloCell_ID; +class CaloDetDescrElement; + +#include "LArElecCalib/ILArShape.h" +#include "LArElecCalib/ILArMinBiasAverage.h" +#include "LArElecCalib/ILArOFC.h" +#include "LArElecCalib/ILArOFCTool.h" +#include "LArElecCalib/ILArMCSymTool.h" +#include "LArIdentifier/LArOnlineID.h" +#include "LArTools/LArCablingService.h" + +#include "LumiBlockComps/ILuminosityTool.h" +#include "TrigAnalysisInterfaces/IBunchCrossingTool.h" + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "StoreGate/DataHandle.h" +#include "CaloInterface/ICaloLumiBCIDTool.h" +#include "AthenaKernel/IOVSvcDefs.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" + + +class CaloLumiBCIDTool: public AthAlgTool, + virtual public ICaloLumiBCIDTool, virtual public IIncidentListener +{ +private: + +//Database + + const DataHandle<ILArShape> m_dd_shape; + const DataHandle<ILArMinBiasAverage> m_dd_minbiasAverage; + const DataHandle<ILArOFC> m_dd_ofc; + ToolHandle<LArCablingService> m_cablingService; + ToolHandle<ILArMCSymTool> m_larmcsym; + ToolHandle<ILArOFCTool> m_OFCTool; + ToolHandle<ILuminosityTool> m_lumiTool; + ToolHandle<Trig::IBunchCrossingTool> m_bunchCrossingTool; + + const LArOnlineID* m_lar_on_id; + const CaloIdManager* m_caloIdMgr; + const CaloCell_ID* m_calocell_id; + + + bool m_isMC; + std::string m_keyShape, m_keyMinBiasAverage, m_keyOFC; + + unsigned int m_bcidMax; + int m_ncell; + + mutable bool m_cacheValid; + + //Internal cache: + std::vector<HWIdentifier> m_hwid_sym; + std::vector<float> m_eshift_sym; + std::vector<int> m_symCellIndex; + unsigned int m_bcid; + + +//Functions + StatusCode initialize(); + + virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS); + + void handle(const Incident& inc); + + void getListOfCells(); + + + /** Callback added to handle Data-driven GeoModel initialisation + */ + virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS); + + StatusCode computeValues(unsigned int bcid); + +public: + + CaloLumiBCIDTool(const std::string& type, + const std::string& name, + const IInterface* parent); + virtual ~CaloLumiBCIDTool(); + + float average(const CaloCell* caloCell, unsigned int bcid); + + float average(const CaloDetDescrElement* caloDDE,unsigned int bcid); + + +}; + +#endif diff --git a/Calorimeter/CaloTools/CaloTools/CaloMBAverageTool.h b/Calorimeter/CaloTools/CaloTools/CaloMBAverageTool.h new file mode 100755 index 0000000000000000000000000000000000000000..be0b9904d383a7a0d5f2481239879b0496f58973 --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloMBAverageTool.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + @class CaloMBAverageTool + @brief Tool to provide expected pedestal shift for Pileup from first principle computation (relevant for non 25ns bunch spacing) + @author G.Unal +*/ + +#ifndef CALOTOOLS_CaloMBAverageTool_H +#define CALOTOOLS_CaloMBAverageTool_H + +class Identifier; +class StoreGateSvc; +class CaloIdManager; +class CaloCell_ID; +class CaloDetDescrElement; + +#include "CaloIdentifier/CaloGain.h" +#include "LArElecCalib/ILArShape.h" +#include "LArElecCalib/ILArfSampl.h" +#include "LArElecCalib/ILArMinBiasAverage.h" +#include "LArElecCalib/ILArOFCTool.h" + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "StoreGate/DataHandle.h" +#include "CaloInterface/ICaloMBAverageTool.h" +#include "AthenaKernel/IOVSvcDefs.h" + + +class CaloMBAverageTool: public AthAlgTool, + virtual public ICaloMBAverageTool +{ +private: +//Database + + const DataHandle<ILArShape> m_dd_shape; + const DataHandle<ILArfSampl> m_dd_fsampl; + const DataHandle<ILArMinBiasAverage> m_dd_minbiasAverage; + ToolHandle<ILArOFCTool> m_OFCTool; + + const DataHandle<CaloIdManager> m_caloIdMgr; + const CaloCell_ID* m_calo_id; + + + float m_Nminbias; + int m_deltaBunch; + std::string m_keyShape, m_keyfSampl, m_keyMinBiasAverage; + + unsigned int m_ncell; + std::vector<float> m_shift; + +//Functions + StatusCode initialize(); + + virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS); + + /** Callback added to handle Data-driven GeoModel initialisation + */ + virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS); + +public: + + CaloMBAverageTool(const std::string& type, + const std::string& name, + const IInterface* parent); + virtual ~CaloMBAverageTool(); + + float average(const CaloCell* caloCell); + + float average(const CaloDetDescrElement* caloDDE,const CaloGain::CaloGain gain); + + +}; + +#endif diff --git a/Calorimeter/CaloTools/CaloTools/CaloNoiseTool.h b/Calorimeter/CaloTools/CaloTools/CaloNoiseTool.h new file mode 100755 index 0000000000000000000000000000000000000000..1a42bef454e68d75dd20381c629eb0f8855740bb --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloNoiseTool.h @@ -0,0 +1,482 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + @class CaloNoiseTool + @brief Tool to provide electronic and pile up noise in MeV + @author David Rousseau + @author Mathieu Lechowski +*/ + +#ifndef CALOTOOLS_CALONOISETOOL_H +#define CALOTOOLS_CALONOISETOOL_H + +class Identifier; +class StoreGateSvc; + +#include "AtlasDetDescr/AtlasDetectorID.h" +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloIdentifier/LArID.h" + +#include "CaloIdentifier/TileID.h" +#include "CaloIdentifier/CaloIdManager.h" +#include "LArTools/LArCablingService.h" +#include "CaloIdentifier/LArID_Exception.h" + +#include "CaloIdentifier/CaloGain.h" + +#include "StoreGate/DataHandle.h" +#include "LArElecCalib/ILArOFC_Shape.h" +#include "LArElecCalib/ILArAutoCorr.h" +#include "LArElecCalib/ILArNoise.h" +#include "LArElecCalib/ILArPedestal.h" +#include "LArElecCalib/ILArAdc2GeV.h" +#include "LArElecCalib/ILArShape.h" +#include "LArElecCalib/ILArfSampl.h" +#include "LArElecCalib/ILArMinBias.h" + +#include "LArElecCalib/ILArOFCTool.h" +#include "LArElecCalib/ILArADC2MeVTool.h" + +#include "TileConditions/TileInfo.h" + +#include "CaloEvent/CaloCell.h" +#include "LArRecEvent/LArCell.h" +#include "TileEvent/TileCell.h" +#include "AthenaBaseComps/AthAlgTool.h" + +#include "GaudiKernel/ToolHandle.h" +#include "CaloInterface/ICaloNoiseTool.h" +#include "AthenaKernel/IOVSvcDefs.h" + +#include "GaudiKernel/IIncidentListener.h" + + +typedef std::vector< std::vector<float> > VectorContainer; +typedef std::vector< float > SingleContainer; + +enum VALUE_ENUM{BADVALUE=-999,BADVALUE_TO_RETURN=-1}; +enum DATABASE_ENUM{iADC2MEV,iSIGMANOISE,iAUTOCORR,iOFC,iSHAPE, + iMINBIASRMS,iFSAMPL,nDATABASE}; + +class CaloNoiseTool: public AthAlgTool, + virtual public ICaloNoiseTool, + public IIncidentListener +{ +private: + typedef float (CaloNoiseTool::*GETNOISE_CDDE)(const CaloDetDescrElement*, + const CaloGain::CaloGain, + const float, + const int); + typedef float (CaloNoiseTool::*GETNOISE_CELL)(const CaloCell*, + const CaloGain::CaloGain, + const float, + const int); + + float elecNoiseRMS(const CaloCell* caloCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float pileupNoiseRMS(const CaloCell* caloCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float totalNoiseRMS(const CaloCell* caloCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + GETNOISE_CDDE m_CachedGetNoiseCDDE; + GETNOISE_CELL m_CachedGetNoiseCELL; + + std::string m_ReturnNoiseName; + int m_gain_from_joboption; + + +//Constants + static const int m_nCalos=4;// number of calorimeters + + float m_LowGainThresh[m_nCalos]; + float m_HighGainThresh[m_nCalos]; + CaloGain::CaloGain m_highestGain[m_nCalos]; + +//Switches + bool m_WithOF; + +//Identifiers + const AtlasDetectorID* m_atlas_id; + + const CaloIdManager* m_calo_id_man; + + // const LArDetDescrManager* m_lar_dd_man; + const LArEM_ID* m_lar_em_id; + const LArHEC_ID* m_lar_hec_id; + const LArFCAL_ID* m_lar_fcal_id; + + //const TileDetDescrManager* m_tile_dd_man; + const TileID* m_tile_id; + + const CaloDetDescrManager* m_calo_dd_man; + const CaloCell_ID* m_calocell_id; + + IdentifierHash m_LArHashMax; + IdentifierHash m_TileHashMax; + IdentifierHash m_CaloHashMax; + IdentifierHash m_CaloHashMin; + + ToolHandle<LArCablingService> m_cablingService; + + std::string m_tileInfoName; + const TileInfo* m_tileInfo; + +//Database + + bool m_retrieve[15]; + + float Adc2MeVFactor; + const DataHandle<ILArAdc2GeV> m_dd_adc2gev; + double AdcPerMev; + ToolHandle<ILArADC2MeVTool> m_adc2mevTool; + + const DataHandle<ILArNoise> m_dd_noise; + float SigmaNoise; + double CNoise; + + bool m_useRMSpedestal; + const DataHandle<ILArPedestal> m_dd_pedestal; + float RMSpedestal; + + const DataHandle<ILArAutoCorr> m_dd_acorr; + ILArAutoCorr::AutoCorrRef_t AutoCorr; + float c[32][32]; + + const DataHandle<ILArOFC_Shape> m_detDHOFC ; + ToolHandle<ILArOFCTool> m_OFCTool; + ILArOFCTool::OFCRef_t OFC; + + const DataHandle<ILArShape> m_dd_shape; + ILArShape::ShapeRef_t Shape; + int m_nsamples; + + const DataHandle<ILArfSampl> m_dd_fsampl; + float fSampl; + + const DataHandle<ILArMinBias> m_dd_minbias; + float MinBiasRMS; + float m_Nminbias; + float m_Nminbias_usedForCache; +// + int m_WorkMode; + bool m_NormalizeAutoCorr; + //bool m_Geant3; + bool m_UseLAr; + bool m_UseTile; + bool m_UseSymmetry; + bool m_DumpDatabase[3]; + bool m_DumpDatabaseHG,m_DumpDatabaseMG,m_DumpDatabaseLG; + bool m_isMC; + bool m_loadAtBegin; // load constant at BeginRun time. + + std::string m_keyNoise, m_keyPedestal, m_keyADC2GeV, m_keyOFShape, m_keyAutoCorr; + std::string m_keyShape, m_keyfSampl, m_keyMinBias; + + unsigned int m_Nmessages_forTilePileUp; + +//DIAGNOSTIC (for TESTBEAM, since limited to 5000 cells) + bool m_noiseOK; + bool m_DiagnosticHG,m_DiagnosticMG,m_DiagnosticLG; + bool m_diagnostic[3]; + int m_nCellsWithProblem[3]; + int m_nReason[5000][3]; + int m_itReason[10][3]; + int m_idHash[5000][3]; + int m_reason[5000][10][3]; + std::string m_reasonName[10]; + + // state of the Cache + bool m_cacheValid ; + + int m_deltaBunch; + unsigned int m_firstSample; + +//Containers + std::vector<IdentifierHash> m_indexContainer; + // = vector indexed with all the hashids, + //containing which index (of container) should be used with a hashid + std::vector<IdentifierHash> m_idSymmCaloHashContainer; + //used only to initialize m_indexOfContainer + + // experimental + // typedef std::map<IdentifierHash, unsigned int> CaloHashIdMap; + // CaloHashIdMap m_idSymmCaloHashMap ; + + VectorContainer m_elecNoiseRAWContainer; + VectorContainer m_elecNoiseCELLContainer; + SingleContainer m_pileupNoiseContainer; + //SingleContainer m_scaleContainer; + VectorContainer m_adc2mevContainer; + + +//Functions + StatusCode initialize(); + StatusCode retrieveDatabase(); + StatusCode initContainers(); + StatusCode initData(); + StatusCode initAdc2MeV(); + StatusCode initElecNoise(); + StatusCode initPileUpNoise(); + + virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS); + + /** Callback added to handle Data-driven GeoModel initialisation + */ + virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS); + + bool checkIfConnected(const Identifier &id); + void commonCalculations(float & OFC_AC_OFC,float & OFC_OFC, int icase, unsigned int firstSample=0); + StatusCode retrieveCellDatabase(const IdentifierHash & idCaloHash, + const Identifier & id,int igain, + const float &Nminbias, + std::string function_name); + StatusCode checkCellDatabase(const Identifier & id, int igain, + std::string function_name); + void updateDiagnostic(int reason,std::string reason_name,int igain); + + std::vector<float> + calculateElecNoiseForLAR(const IdentifierHash &idCaloHash, + const CaloCell_ID::SUBCALO iCalo, + const float &Nminbias); + std::vector<float> + calculateElecNoiseForTILE(const IdentifierHash &idCaloHash); + + float + calculatePileUpNoise(const IdentifierHash &idCaloHash, + const float &Nminbias); + + void initIndex(); + int index(const IdentifierHash &idCaloHash); + CaloCell_ID::SUBCALO caloNum(const IdentifierHash idCaloHash); + bool isBadValue(float tested_value); + + CaloGain::CaloGain estimatedLArGain(const CaloCell_ID::SUBCALO &iCalo, + const CaloDetDescrElement* caloDDE, + const float &energy, + const int &step); + CaloGain::CaloGain estimatedTileGain(const CaloCell* caloCell, + const CaloDetDescrElement* caloDDE, + const int &step); + + +public: + + CaloNoiseTool(const std::string& type, + const std::string& name, + const IInterface* parent); + //virtual ~CaloNoiseTool(); + + +//-------------- user interfaces ------------------------------------------ + +// Note on NMinBias : if you use the interface without it or if you take -1, +// the returned data will be the one calculated at the +// initialization with the default value (0) or the +// specified one (with the property m_Nminbias). +// In all cases, the NMinBias used to calculate the OFCs +// is NOT known by CaloNoiseTool (CaloNoiseTool always +// recomputes OFCs for its own needs) + + + +//== just one function for the interface to the CaloNoiseTool == + // which noise to return is defined via jobOptions or via the + // optional parameter CalorimeterNoiseType + + float getNoise(const CaloCell* caloCell, + CalorimeterNoiseType type=JOBOPTION ); + float getNoise(const CaloDetDescrElement* caloDDE, + CalorimeterNoiseType type=JOBOPTION ); + + bool isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + float getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type=JOBOPTION); + + float getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + + + +//== ELECTRONIC NOISE == + + //''''''''' functions to use currently + + float elecNoiseRMS(const CaloCell* caloCell, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise, finding itself the right gain + //from the energy of the given caloCell. + //Can also return the sigma without the scale applied in LArG3Escale + //(meaning at the level of the RawChannels) specifying the step (use ENUM) + + float elecNoiseRMS(const CaloCell* caloCell, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //same as above, but must specify the number of minimum bias events + //per bunch crossing + // (slower since do not use stored data -> calculate again) + + float elecNoiseRMSHighestGain(const CaloCell* caloCell, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the caloDDE of the given + //caloCELL and for the highest gain of the considered calorimeter + //(eg: HG for LAr, MG for HEC, ...). + //Can also return the sigma without the scale applied in LArG3Escale + //(meaning at the level of the RawChannels) specifying the step (use ENUM) + + float elecNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //same as above, but must specify the number of minimum bias events + //per bunch crossing + // (slower since do not use stored data -> calculate again) + + //''''''''' functions more specialized + + float elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the given caloDDE and + //for the highest gain of the considered calorimeter (eg: MG for HEC). + //Can also return the sigma without the scale applied in LArG3Escale + //(meaning at the level of the RawChannels) specifying the step (use ENUM) + + float elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //same as above, but must specify the number of minimum bias events + //per bunch crossing + // (slower since do not use stored data -> calculate again) + + float elecNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the given caloDDE, gain and + //the number of minimum bias events per bunch crossing. + //Can also return the sigma without the scale applied in LArG3Escale + //(meaning at the level of the RawChannels) specifying the step (use ENUM) + + std::vector<float> + elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const int step=ICaloNoiseToolStep::CELLS); + //Returns a vector containing the sigma of the electronic noise for the + //given caloDDE, for each gain of the considered calorimeter + //(eg: vector of 3 sigma3 gains for LAr) + //Can also return the sigma without the scale applied in LArG3Escale + //(meaning at the level of the RawChannels) specifying the step (use ENUM) + + std::vector<float> + elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //same as above, but must specify the number of minimum bias events + //per bunch crossing + // (slower since do not use stored data -> calculate again) + + VectorContainer* elecNoiseRMSContainer(const int &iCalo); + //TO BE USED ONLY FOR SPECIAL CASES + //Returns a vector containing, for each Hash Identifier of the calorimeter + //iCalo, a vector containing the sigma of the electronic noise for all + //gains. + //So it's a vector (indexed by hashID) of vectors (sigma for each gain) + //(see typedef VectorContainer). + + +//== PILEUP NOISE == + + float pileupNoiseRMS(const CaloCell* caloCell, + const float Nminbias=-1); + float pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const float Nminbias=-1); + //Nminbias is the number of minimum-bias events per bunch-crossing + // (default is 0 (set in the constructor) ) + +//== TOTAL NOISE == (only at the "Cells" step) + + float totalNoiseRMS(const CaloCell* caloCell, + const float Nminbias=-1); + float totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias=-1); + float totalNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias=-1); + float totalNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias=-1); + + + +//== GAIN == + CaloGain::CaloGain estimatedGain(const CaloCell* caloCell, + const int &step); + CaloGain::CaloGain estimatedGain(const CaloCell* caloCell, + const CaloDetDescrElement* caloDDE, + const int &step); + CaloGain::CaloGain estimatedGain(const CaloDetDescrElement* caloDDE, + const float &energy, + const int &step); + +//== ADDITIONNAL STUFF == + // these functions will be replaced soon by dedicated tools, + // so please AVOID TO USING THEM + + //float eScale(const CaloDetDescrElement* caloDDE); + //Returns the scale between RawChannels and Cells, i.e + //what returns LArG3Escale + + float adc2mev(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain); + //Returns adc2mev factor for the given caloDDE and gain + + float adc2mev(const Identifier& id,const CaloGain::CaloGain gain); + //Returns adc2mev factor for the given ID and gain + //SHOULD NOT BE USED ANYMORE, prefer the one above with caloDDE + + + /** + implement IIncidentListener interface + */ + virtual void handle(const Incident&); + + +}; + +//------------------------------------------------------------ + +inline bool +CaloNoiseTool::isBadValue(float tested_value) +{ + if(tested_value<BADVALUE+1) return true; + return false; +} + +////////////////////////////////////////////////// + +inline CaloCell_ID::SUBCALO +CaloNoiseTool::caloNum(const IdentifierHash idCaloHash) +{ + return + static_cast<CaloCell_ID::SUBCALO>(m_calocell_id->sub_calo(idCaloHash)); +} + +#endif + diff --git a/Calorimeter/CaloTools/CaloTools/CaloNoiseToolDB.h b/Calorimeter/CaloTools/CaloTools/CaloNoiseToolDB.h new file mode 100755 index 0000000000000000000000000000000000000000..f7c9bb72f1463375070c9299d83b16391bf34a24 --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/CaloNoiseToolDB.h @@ -0,0 +1,321 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + @class CaloNoiseToolDB + @brief Tool to provide electronic and pile up noise in MeV from reading values stored in DB + @brief Implementing ICaloNoiseTool interface + @author G.Unal +*/ + +#ifndef CALOTOOLS_CaloNoiseToolDB_H +#define CALOTOOLS_CaloNoiseToolDB_H + + +//#include "GaudiKernel/AlgTool.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "CaloInterface/ICaloNoiseTool.h" + +#include "AtlasDetDescr/AtlasDetectorID.h" +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloIdentifier/CaloIdManager.h" +#include "CaloIdentifier/CaloGain.h" +#include "CaloEvent/CaloCell.h" +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "AthenaKernel/IOVSvcDefs.h" +#include "StoreGate/DataHandle.h" +#include <string> +#include <boost/multi_array.hpp> + +#define sqrt2 1.4142135623730950 +#define invsqrt2 0.707106781186547524 + + +class CaloCondBlobFlt; + + +class CaloNoiseToolDB: public AthAlgTool, + virtual public ICaloNoiseTool +{ +public: + + typedef std::vector< std::vector<float> > VectorContainer; + + CaloNoiseToolDB(const std::string& type, + const std::string& name, + const IInterface* parent); + + enum SYSTEM{EMECZNEG = 0, + EMBZNEG = 1, + EMBZPOS = 2, + EMECZPOS = 3, + HEC =16, + FCAL =32, + TILE =48}; + + + +//-------------- user interfaces ------------------------------------------ + +// Note on NMinBias : if you use the interface without it or if you take -1, +// the returned data will be the one calculated at the +// initialization with the default value (0) or the +// specified one (with the property m_Nminbias). +// FIXME : to be updated using the proper luminosity information from lumi block +// (and then should also register a call back on the lumi block for cached data) + + +//== just one function for the interface to the CaloNoiseToolDB == + // which noise to return is defined via jobOptions or via the + // optional parameter CalorimeterNoiseType + + float getNoise(const CaloCell* caloCell, + CalorimeterNoiseType type=JOBOPTION ); + float getNoise(const CaloDetDescrElement* caloDDE, + CalorimeterNoiseType type=JOBOPTION ); + float getNoise(const CaloCell* caloCell, float energy, + CalorimeterNoiseType type=JOBOPTION ); + + bool isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + float calcSig(double e, double sigma1, double ratio, double sigma2); + + float getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type=JOBOPTION); + + float getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + + +//== ELECTRONIC NOISE == + + //''''''''' functions to use currently + + float elecNoiseRMS(const CaloCell* caloCell, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise, finding itself the right gain + //from the energy of the given caloCell. + + float elecNoiseRMS(const CaloCell* caloCell, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + // returns the same as above (Nminbias ignored in this implementation from database) + + float elecNoiseRMSHighestGain(const CaloCell* caloCell, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the caloDDE of the given + //caloCELL and for the highest gain of the considered calorimeter + //(eg: HG for LAr, MG for HEC, ...). + + float elecNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + // same as above + + //''''''''' functions more specialized + + float elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the given caloDDE and + //for the highest gain of the considered calorimeter (eg: MG for HEC). + + float elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //same as above + + float elecNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the given caloDDE, gain + // Nminbias is ignored + + float elecNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const float energy, + const int step=ICaloNoiseToolStep::CELLS); + //Returns the sigma of the electronic noise for the given caloDDE in + //case of 2-gaussian noise, gain + // Nminbias is ignored + + std::vector<float> + elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const int step=ICaloNoiseToolStep::CELLS); + //Returns a vector containing the sigma of the electronic noise for the + //given caloDDE, for each gain of the considered calorimeter + //(eg: vector of 3 sigma3 gains for LAr) + + std::vector<float> + elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const float Nminbias, + const int step=ICaloNoiseToolStep::CELLS); + //same as above, Nminbias ignored + + VectorContainer* elecNoiseRMSContainer(const int &iCalo); + //TO BE USED ONLY FOR SPECIAL CASES + //Returns a vector containing, for each Hash Identifier of the calorimeter + //iCalo, a vector containing the sigma of the electronic noise for all + //gains. + //So it's a vector (indexed by hashID) of vectors (sigma for each gain) + //(see typedef VectorContainer). + // empty for the time being + + +//== PILEUP NOISE == + + float pileupNoiseRMS(const CaloCell* caloCell, + const float Nminbias=-1); + float pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const float Nminbias=-1); + //Nminbias is the number of minimum-bias events per bunch-crossing + // (default is 0 (set in the constructor) ) + +//== TOTAL NOISE == (only at the "Cells" step) + + float totalNoiseRMS(const CaloCell* caloCell, + const float Nminbias=-1); + float totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias=-1); + float totalNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias=-1); + float totalNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias=-1); + + + +//== GAIN == Only there to fulfill the interface, returns INVALID values... + CaloGain::CaloGain estimatedGain(const CaloCell* caloCell, + const int &step); + CaloGain::CaloGain estimatedGain(const CaloCell* caloCell, + const CaloDetDescrElement* caloDDE, + const int &step); + CaloGain::CaloGain estimatedGain(const CaloDetDescrElement* caloDDE, + const float &energy, + const int &step); + + StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS); + + + /** Callback added to handle Data-driven GeoModel initialisation + ( even needed to retrieve Identifiers ) + */ + virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS); + +private: + + + ICalorimeterNoiseTool::CalorimeterNoiseType m_cached; + + // cached noise per cell + boost::multi_array<float, 2> m_noise; // float[MaxGains][MaxCells] + + typedef float (CaloNoiseToolDB::*GETNOISE_CDDE)(const CaloDetDescrElement*, + const CaloGain::CaloGain, + const float, + const int); + typedef float (CaloNoiseToolDB::*GETNOISE_CELL)(const CaloCell*, + const CaloGain::CaloGain, + const float, + const int); + + float elecNoiseRMS(const CaloCell* caloCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float pileupNoiseRMS(const CaloCell* caloCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float totalNoiseRMS(const CaloCell* caloCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step); + float totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const float energy, + const int step); + GETNOISE_CDDE m_CachedGetNoiseCDDE; + GETNOISE_CELL m_CachedGetNoiseCELL; + + int m_gain_from_joboption; + bool m_speedTwoGauss; + +//Constants + static const int m_nCalos=4;// number of calorimeters + int m_ncell; // total number of calo cells + + CaloGain::CaloGain m_highestGain[m_nCalos]; + + float m_Nminbias; + float m_lumi0; + +//Functions + StatusCode initialize(); + StatusCode finalize(); + +// provate methods to access database + float getA(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const; + float getB(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getC(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getD(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getE(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getDBNoise(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain, float lumi) const; + + float getA(unsigned int cellHash, CaloGain::CaloGain caloGain) const; + float getB(unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getC(unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getD(unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getE(unsigned int cellHash, CaloGain::CaloGain caloGain) const ; + float getDBNoise(unsigned int cellHash, CaloGain::CaloGain caloGain, float lumi) const; + + int checkObjLength(unsigned int cellHash) const; + + SYSTEM caloSystem(unsigned int cellHash, unsigned int& subHash) const; + + //=== callback function to update noise map + virtual StatusCode updateMap(IOVSVC_CALLBACK_ARGS); + void updateCache(); + + //=== callback function for luminosity storate + virtual StatusCode updateLumi(IOVSVC_CALLBACK_ARGS); + + + //=== blob storage + std::vector<DataHandle<CondAttrListCollection> > m_noiseAttrListColl; + std::map<SYSTEM, const CaloCondBlobFlt*> m_noiseBlobMap; + + bool m_cacheValid; + + std::string m_ReturnNoiseName; + + const DataHandle<CaloIdManager> m_caloIdMgr; + const DataHandle<CaloDetDescrManager> m_calodetdescrmgr; + const CaloCell_ID* m_calo_id; + + // number of EM systems in SYSTEM enum + enum { NUM_EM_SYS = 4 }; + + // First IdHash for each system in EM Barrel and EndCap (indexed by SYSTEM, only first NUM_EM_SYS SYSTEMs) + IdentifierHash m_firstSysHash[NUM_EM_SYS]; + + std::vector<std::string> m_folderNames;//jobOption + std::string m_lumiFolderName; +}; + +#endif diff --git a/Calorimeter/CaloTools/CaloTools/SimpleNoiseTool.h b/Calorimeter/CaloTools/CaloTools/SimpleNoiseTool.h new file mode 100755 index 0000000000000000000000000000000000000000..d46ade69d705743a850ff285d4edddf38a4e765c --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/SimpleNoiseTool.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + @class SimpleNoiseTool + @brief Tool to provide noise from hardcoded numbers + @author Rolf Seuster +*/ + +#ifndef CALOTOOLS_SIMPLENOISETOOL_H +#define CALOTOOLS_SIMPLENOISETOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IIncidentListener.h" + +#include "CaloGeoHelpers/CaloSampling.h" + +#include "CaloIdentifier/CaloGain.h" +#include "CaloDetDescr/CaloDetDescrElement.h" + +#include "CaloInterface/ICalorimeterNoiseTool.h" + +#include <map> +#include <string> + +class CaloCell; + +class StoreGateSvc; + +class SimpleNoiseTool : public AthAlgTool, + virtual public ICalorimeterNoiseTool +{ + public: + + typedef std::pair<CaloSampling::CaloSample,CaloGain::CaloGain> index_t; + typedef std::map<index_t,double> store_t; + + SimpleNoiseTool(const std::string& type, const std::string& name, + const IInterface* parent); + + virtual ~SimpleNoiseTool(); + + StatusCode initialize(); + + float getNoise(const CaloCell* aCell, CalorimeterNoiseType type=JOBOPTION); + float getNoise(const CaloDetDescrElement *caloCell, CalorimeterNoiseType type=JOBOPTION); + + bool isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + float getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type=JOBOPTION); + + float getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + + +}; +#endif diff --git a/Calorimeter/CaloTools/CaloTools/SimpleNoiseToolFromTextFile.h b/Calorimeter/CaloTools/CaloTools/SimpleNoiseToolFromTextFile.h new file mode 100755 index 0000000000000000000000000000000000000000..15df6f21ec83af78d2300936adcdf3d7ac5e170f --- /dev/null +++ b/Calorimeter/CaloTools/CaloTools/SimpleNoiseToolFromTextFile.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + @class SimpleNoiseToolFromTextFile + @brief Tool to provide noise from numbers read in a text file + @author Rolf Seuster +*/ + +#ifndef CALOTOOLS_SIMPLENOISETOOLFROMTEXTFILE_H +#define CALOTOOLS_SIMPLENOISETOOLFROMTEXTFILE_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IIncidentListener.h" + +#include "CaloIdentifier/CaloGain.h" +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloInterface/ICalorimeterNoiseTool.h" +#include "Identifier/Identifier.h" +#include "AthenaKernel/IOVSvcDefs.h" + +#include <map> + +class CaloCell; +class CaloDetDescrElement; + +class StoreGateSvc; + +class SimpleNoiseToolFromTextFile : public AthAlgTool, + virtual public ICalorimeterNoiseTool +{ + public: + + SimpleNoiseToolFromTextFile(const std::string& type, const std::string& name, + const IInterface* parent); + + virtual ~SimpleNoiseToolFromTextFile(); + + StatusCode initialize(); + + /** Callback added to handle Data-driven GeoModel initialisation + */ + virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS); + + float getNoise(const CaloCell* aCell, CalorimeterNoiseType type=JOBOPTION); + float getNoise(const CaloDetDescrElement* caloDDE, CalorimeterNoiseType type=JOBOPTION); + + bool isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + float getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type=JOBOPTION); + + float getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling symmetryHandling=ONLYRIGHTSIDEINTEGRATION, + CalorimeterNoiseType type=JOBOPTION ); + + + + private: + // access calo detector managers and calo identifier helper + // only needed for debug printout + const CaloDetDescrManager* m_caloDDM; + const CaloCell_ID* m_caloIDH; + + // Identifier keyed map of calo cell noise + std::map<Identifier, float> m_cellNoise; + + // Properties + std::string m_cellNoiseFileName; + double m_cellNoiseUnits; // CLHEP units of cell noise in noise file + float m_cellNoiseDefault; // noise value to return if cell noise not in noise file + bool m_cellNoiseDefaultWarning; // if true, print a MSG::WARNING if noise default is used + + float getNoiseHelper(Identifier id); +}; +#endif diff --git a/Calorimeter/CaloTools/cmt/requirements b/Calorimeter/CaloTools/cmt/requirements new file mode 100755 index 0000000000000000000000000000000000000000..5252137f70f3ca954cf00063704ee9734a60937b --- /dev/null +++ b/Calorimeter/CaloTools/cmt/requirements @@ -0,0 +1,58 @@ +package CaloTools + +use AtlasPolicy AtlasPolicy-* +use AtlasDetDescr AtlasDetDescr-* DetectorDescription +use AthenaKernel AthenaKernel-* Control +use AthenaPoolUtilities AthenaPoolUtilities-* Database/AthenaPOOL +use Identifier Identifier-* DetectorDescription +use CaloDetDescr CaloDetDescr-* Calorimeter +use CaloInterface CaloInterface-* Calorimeter +use CaloEvent CaloEvent-* Calorimeter +use CaloGeoHelpers CaloGeoHelpers-* Calorimeter +use CaloIdentifier CaloIdentifier-* Calorimeter +use CaloConditions CaloConditions-* Calorimeter +use DataModel DataModel-* Control +use GaudiInterface GaudiInterface-* External +use LArElecCalib LArElecCalib-* LArCalorimeter +use LArRecEvent LArRecEvent-* LArCalorimeter +use LArTools LArTools-* LArCalorimeter +use StoreGate StoreGate-* Control +use TileConditions TileConditions-* TileCalorimeter +use TileEvent TileEvent-* TileCalorimeter +use LumiBlockComps LumiBlockComps-* LumiBlock +use TrigAnalysisInterfaces TrigAnalysisInterfaces-* Trigger/TrigAnalysis +use LArIdentifier LArIdentifier-* LArCalorimeter +use AthenaBaseComps AthenaBaseComps-* Control + +use AtlasCLHEP AtlasCLHEP-* External +use AtlasBoost AtlasBoost-* External +use AthenaPoolUtilities AthenaPoolUtilities-* Database/AthenaPOOL + +private +use xAODBase xAODBase-* Event/xAOD +use AthAllocators AthAllocators-* Control +use CaloTriggerTool CaloTriggerTool-* Calorimeter +end_private + +library CaloTools *.cxx components/*.cxx +apply_pattern component_library + +apply_pattern declare_joboptions files="*.txt *.py" + +apply_pattern declare_python_modules files="*.py" + +private +use AtlasCORAL AtlasCORAL-* External +use AtlasROOT AtlasROOT-* External +use TestTools TestTools-* AtlasTest +use xAODEventInfo xAODEventInfo-* Event/xAOD +use IdDictParser IdDictParser-* DetectorDescription +use GeoModelInterfaces GeoModelInterfaces-* DetectorDescription/GeoModel +use CaloCondBlobObjs CaloCondBlobObjs-* Calorimeter +use TileIdentifier TileIdentifier-* TileCalorimeter + +apply_pattern UnitTest_run unit_test=CaloCellPackerUtils + +apply_pattern UnitTest_run unit_test=CaloCompactCellTool \ + extrapatterns="SGAudSvc +INFO|^lar decode|^HistogramPersis.* INFO|initialize_from_dict|mask/zero|^JobOptionsSvc +INFO|^AtlasDetectorID::" + diff --git a/Calorimeter/CaloTools/doc/mainpage.h b/Calorimeter/CaloTools/doc/mainpage.h new file mode 100644 index 0000000000000000000000000000000000000000..9e53fca440116d96b0b66a9ab8b6b755b9215448 --- /dev/null +++ b/Calorimeter/CaloTools/doc/mainpage.h @@ -0,0 +1,15 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + +@mainpage CaloTols Package + +This package provides some tools used in the calorimeter reconstruction. + +@author David Rousseau rousseau@lal.in2p3.fr +@authour Sven Menke Sven.Menke@cern.ch + + +*/ diff --git a/Calorimeter/CaloTools/python/CaloAffectedToolDefault.py b/Calorimeter/CaloTools/python/CaloAffectedToolDefault.py new file mode 100644 index 0000000000000000000000000000000000000000..5756483e242c453b08f2b5d070522a2b5288a312 --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloAffectedToolDefault.py @@ -0,0 +1,28 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.Logging import logging + +def CaloAffectedToolDefault(name='CaloAffectedToolDefault'): + + # check if tool already exists + from AthenaCommon.AppMgr import ServiceMgr as svcMgr + if hasattr(svcMgr.ToolSvc, name): + # re-use previously configured (public) tool + return getattr(svcMgr.ToolSvc, name) + + mlog = logging.getLogger( 'CaloAffectedToolDefault' ) + + from CaloTools.CaloToolsConf import CaloAffectedTool + + + theTool = CaloAffectedTool(name) + + from RecExConfig.RecFlags import rec + if rec.readRDO(): + theTool.readRaw = True + else: + theTool.readRaw = False + from IOVDbSvc.CondDB import conddb + conddb.addFolder ('', '/LAR/LArAffectedRegionInfo<metaOnly/>') + + return theTool diff --git a/Calorimeter/CaloTools/python/CaloLumiBCIDToolDefault.py b/Calorimeter/CaloTools/python/CaloLumiBCIDToolDefault.py new file mode 100644 index 0000000000000000000000000000000000000000..6424531cb506bac896aceebdba7a65149e091a28 --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloLumiBCIDToolDefault.py @@ -0,0 +1,37 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.Logging import logging +from AthenaCommon.SystemOfUnits import * + +def CaloLumiBCIDToolDefault(name='CaloLumiBCIDToolDefault'): + mlog = logging.getLogger( 'CaloLumiBCIDToolDefault' ) + + from CaloTools.CaloToolsConf import CaloLumiBCIDTool + + from AthenaCommon.GlobalFlags import globalflags + if globalflags.DataSource()=='data': + from LumiBlockComps.LuminosityToolDefault import LuminosityToolDefault + theLumiTool = LuminosityToolDefault() + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += theLumiTool + from IOVDbSvc.CondDB import conddb + #conddb.addFolder("","/LAR/ElecCalibOfl/LArPileupShape<db>sqlite://;schema=/afs/cern.ch/user/g/gunal/public/DB/bcid/shape.db;dbname=COMP200</db><key>LArShape32</key><tag>LARElecCalibOflLArPileupShape-mc</tag>") + #conddb.addFolder("","/LAR/ElecCalibOfl/LArPileupAverage<db>sqlite://;schema=/afs/cern.ch/user/g/gunal/public/DB/bcid/LArPileupAverage-data.db;dbname=COMP200</db><tag>LARElecCalibOflLArPileupAverage-data11-00</tag>") + conddb.addFolder("LAR_OFL","/LAR/ElecCalibOfl/LArPileupShape<key>LArShape32</key>") + conddb.addFolder("LAR_OFL","/LAR/ElecCalibOfl/LArPileupAverage") + theTool = CaloLumiBCIDTool(name,isMC=False,LumiTool=theLumiTool,keyShape="LArShape32") + else: + from LArRecUtils.LArOFCToolDefault import LArOFCToolDefault + theOFCTool = LArOFCToolDefault() + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += theOFCTool + from TrigBunchCrossingTool.BunchCrossingTool import BunchCrossingTool + theBunchCrossingTool = BunchCrossingTool() + from IOVDbSvc.CondDB import conddb + conddb.addFolder("LAR_OFL","/LAR/ElecCalibMC/Shape") + #conddb.addFolder("","/LAR/ElecCalibMC/LArPileupAverage<db>sqlite://;schema=/afs/cern.ch/user/g/gunal/public/DB/bcid/LArPileupAverage-mc.db;dbname=OFLP200</db><tag>LARElecCalibMCLArPileupAverage-mc11b-00</tag>") + conddb.addFolder("LAR_OFL","/LAR/ElecCalibMC/LArPileupAverage") + theTool = CaloLumiBCIDTool(name, + isMC=True, + LArOFCTool = theOFCTool,BunchCrossingTool = theBunchCrossingTool) + return theTool diff --git a/Calorimeter/CaloTools/python/CaloMBAverageToolDefault.py b/Calorimeter/CaloTools/python/CaloMBAverageToolDefault.py new file mode 100644 index 0000000000000000000000000000000000000000..fb395da59be38509655175d603f83836df9b1d31 --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloMBAverageToolDefault.py @@ -0,0 +1,27 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.Logging import logging +from AthenaCommon.SystemOfUnits import * + +def CaloMBAverageToolDefault(name='CaloMBAverageToolDefault'): + mlog = logging.getLogger( 'CaloMBAverageToolDefault' ) + + from CaloTools.CaloToolsConf import CaloMBAverageTool + # get public tool LArOFCTool + from LArRecUtils.LArOFCToolDefault import LArOFCToolDefault + theOFCTool = LArOFCToolDefault() + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += theOFCTool + from AthenaCommon.BeamFlags import jobproperties + if jobproperties.Beam.zeroLuminosity(): + NMinBias=0 + deltaBunch=1 + else: + NMinBias=jobproperties.Beam.numberOfCollisions() + deltaBunch=int(jobproperties.Beam.bunchSpacing()/( 25.*ns)+0.5) + + theTool = CaloMBAverageTool(name, + LArOFCTool = theOFCTool, + NMinBias = NMinBias, + deltaBunch = deltaBunch) + return theTool diff --git a/Calorimeter/CaloTools/python/CaloNoiseFlags.py b/Calorimeter/CaloTools/python/CaloNoiseFlags.py new file mode 100644 index 0000000000000000000000000000000000000000..6f7d09b94c14ebfcdd8704f2f4eaed79e9610f03 --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloNoiseFlags.py @@ -0,0 +1,51 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +""" Flags for define calo noise tool configuration +""" +# +# +__author__ = 'G.Unal' + + +#======================================================================= +# imports +#======================================================================= +from AthenaCommon.JobProperties import JobProperty, JobPropertyContainer +from AthenaCommon.JobProperties import jobproperties + +class FixedLuminosity(JobProperty): + """ Flag to force luminosity (10**33 units) to a given value corresponding to a given mu + Lumi is related to mu by Lumi = (mu/2.3) * 25ns/BunchSpacing(ns) + BunchSpacing should be consistent with what is used from DB, as noise/sqrt(Lumi) depends on BunchSpacing + if -1 uses lumi from database (Data) or Beam properties (MC) to perform the sqrt(Lumi) pileup noise scaling + """ + statusOn = True + allowedType=['float'] + StoredValue = -1. + +class UseCaloLuminosity(JobProperty): + """ Flag to tell to use the luminosity normalization for pileup noise from dedicated calo folder + instead of online per LumiBlock + Only active if FixedLuminosity is not >0 + """ + statusOn = True + allowedType=['bool'] + StoredValue = True + +class CaloNoiseFlags(JobPropertyContainer): + """ The CaloNoiseFlag container + """ + pass + + +# add container to jobProperties +jobproperties.add_Container(CaloNoiseFlags) + +list_jobproperties = [ + FixedLuminosity,UseCaloLuminosity + ] + +for i in list_jobproperties: + jobproperties.CaloNoiseFlags.add_JobProperty(i) + +del list_jobproperties diff --git a/Calorimeter/CaloTools/python/CaloNoiseToolDBData.py b/Calorimeter/CaloTools/python/CaloNoiseToolDBData.py new file mode 100644 index 0000000000000000000000000000000000000000..c01d1ccf48a708aa1583a6e895c60b06d11802a7 --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloNoiseToolDBData.py @@ -0,0 +1,71 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# example of use of CaloNoiseToolDB returning cell noise from Cool DB + +from AthenaCommon.Logging import logging +from AthenaCommon.SystemOfUnits import * +from AthenaCommon.Constants import * + +# import the base class +from CaloTools.CaloToolsConf import CaloNoiseToolDB + +class CaloNoiseToolDBData(CaloNoiseToolDB) : + + def __init__(self, name="CaloNoiseToolDBData"): + # call base class constructor + CaloNoiseToolDB.__init__( self, name) + + mlog = logging.getLogger( 'CaloNoiseToolDBData::__init__ ' ) + mlog.info("entering") + + from IOVDbSvc.CondDB import conddb + + from CaloTools.CaloNoiseFlags import jobproperties + fixedLumi = jobproperties.CaloNoiseFlags.FixedLuminosity() + caloLumi = jobproperties.CaloNoiseFlags.UseCaloLuminosity() + + if conddb.isOnline: + folder = "/CALO/Noise/CellNoise" + conddb.addFolder('CALO_ONL',folder) + CaloNoiseToolDB.FolderNames=[folder,] + if fixedLumi >= 0 : + CaloNoiseToolDB.Luminosity = fixedLumi + mlog.info("online mode: use fixed luminosity for scaling pileup noise: %f"%fixedLumi) + else: + if caloLumi: + lumiFolder='/CALO/Noise/PileUpNoiseLumi' + conddb.addFolder('CALO',lumiFolder) + CaloNoiseToolDB.LumiFolderName = lumiFolder + CaloNoiseToolDB.Luminosity = -1. + mlog.info("online mode: use luminosity from /CALO/Noise/PileUpNoiseLumi to scale pileup noise") + else: + CaloNoiseToolDB.Luminosity = 0. + mlog.info("online mode: ignore pileup noise") + else: + folders=[("LAR_OFL","/LAR/NoiseOfl/CellNoise"), + ("TILE_OFL","/TILE/OFL02/NOISE/CELL") + ] + #The noise for runs before 2012 is a different folder: + if conddb.dbdata=="COMP200": + folders.append(("CALO_OFL","/CALO/Ofl/Noise/CellNoise")), + + for (db,fldr) in folders: + conddb.addFolder(db,fldr) + CaloNoiseToolDB.FolderNames=[f[1] for f in folders] + + # for luminosity + if fixedLumi >= 0 : + CaloNoiseToolDB.Luminosity = fixedLumi + mlog.info("offline mode: use fixed luminosity for scaling pileup noise: %f"%fixedLumi) + else : + CaloNoiseToolDB.Luminosity = -1 + if caloLumi: + lumiFolder='/CALO/Ofl/Noise/PileUpNoiseLumi' + conddb.addFolder('CALO_OFL',lumiFolder) + mlog.info("offline mode: use luminosity from /CALO/Ofl/Noise/PileUpNoiseLumi to scale pileup noise") + else: + lumiFolder = '/TRIGGER/LUMI/LBLESTONL' + conddb.addFolder('TRIGGER_ONL',lumiFolder); + mlog.info("offline mode: use luminosity = f(Lumiblock) to scale pileup noise") + CaloNoiseToolDB.LumiFolderName = lumiFolder + diff --git a/Calorimeter/CaloTools/python/CaloNoiseToolDBMC.py b/Calorimeter/CaloTools/python/CaloNoiseToolDBMC.py new file mode 100644 index 0000000000000000000000000000000000000000..d8892ad4d255fd93d0dd2e08edb025458e53ab9e --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloNoiseToolDBMC.py @@ -0,0 +1,46 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# example of use of CaloNoiseToolDB returning cell noise from Cool DB + +from AthenaCommon.Logging import logging +from AthenaCommon.SystemOfUnits import * +from AthenaCommon.Constants import * + +# import the base class +from CaloTools.CaloToolsConf import CaloNoiseToolDB + +class CaloNoiseToolDBMC(CaloNoiseToolDB) : + + def __init__(self, name="CaloNoiseToolDBMC"): + # call base class constructor + CaloNoiseToolDB.__init__( self, name) + + mlog = logging.getLogger( 'CaloNoiseToolDBMC::__init__ ' ) + mlog.info("entering") + + from IOVDbSvc.CondDB import conddb + + # do the configuration + from CaloTools.CaloNoiseFlags import jobproperties + if jobproperties.CaloNoiseFlags.FixedLuminosity() >= 0 : + self.Luminosity=jobproperties.CaloNoiseFlags.FixedLuminosity() + mlog.info(" Luminosity (in 10**33) units used for pileup noise from CaloNoiseFlags : %f"%self.Luminosity) + else: + if jobproperties.CaloNoiseFlags.UseCaloLuminosity(): + lumiFolder='/CALO/Ofl/Noise/PileUpNoiseLumi' + conddb.addFolder('CALO_OFL',lumiFolder) + mlog.info("offline mode: use luminosity from /CALO/Ofl/Noise/PileuUpNoiseLumi to scale pileup noise") + self.LumiFolderName = lumiFolder + self.Luminosity=-1. + else: + from AthenaCommon.BeamFlags import jobproperties + self.Luminosity=jobproperties.Beam.estimatedLuminosity()/1e+33 + mlog.info(" Luminosity (in 10**33) units used for pileup noise from BeamFlags : %f"%self.Luminosity) + + folders = (("CALO_OFL","/CALO/Ofl/Noise/CellNoise"), + ("LAR_OFL","/LAR/NoiseOfl/CellNoise"), + ("TILE_OFL","/TILE/OFL02/NOISE/CELL") + ) + for (db,fldr) in folders: + conddb.addFolder(db,fldr) + CaloNoiseToolDB.FolderNames=[f[1] for f in folders] diff --git a/Calorimeter/CaloTools/python/CaloNoiseToolDefault.py b/Calorimeter/CaloTools/python/CaloNoiseToolDefault.py new file mode 100644 index 0000000000000000000000000000000000000000..9af276d7929e7f8e06146d7373f0866271193ba7 --- /dev/null +++ b/Calorimeter/CaloTools/python/CaloNoiseToolDefault.py @@ -0,0 +1,94 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.Logging import logging +from AthenaCommon.SystemOfUnits import * + +def CaloNoiseToolDefault(flag='',name='CaloNoiseToolDefault'): + + # check if tool already exists + from AthenaCommon.AppMgr import ServiceMgr as svcMgr + if hasattr(svcMgr.ToolSvc, name): + # re-use previously configured (public) tool + return getattr(svcMgr.ToolSvc, name) + + mlog = logging.getLogger( 'CaloNoiseToolDefault' ) + + if flag=='db' : + _useDB = True + elif flag=='tool' : + _useDB = False + else : + # will put here logic to select according to global flag + from AthenaCommon.GlobalFlags import globalflags + from AthenaCommon.BeamFlags import jobproperties + if globalflags.DataSource()=='data' and globalflags.DetGeo()!='ctbh6' and globalflags.DetGeo()!='ctbh8': + _useDB = True + elif globalflags.DataSource()=='geant4' and jobproperties.Beam.zeroLuminosity(): + _useDB = True + else: + # now uses also calonoisetoolDB for MC with pileup.. requires a new global tag for pileup reco to have the noise properly read + _useDB = True + + if _useDB : + mlog.info(" Using CaloNoiseToolDB" ) + from AthenaCommon.GlobalFlags import globalflags + if globalflags.DataSource()=='data': + from CaloTools.CaloNoiseToolDBData import CaloNoiseToolDBData + theTool = CaloNoiseToolDBData(name) + else: + from CaloTools.CaloNoiseToolDBMC import CaloNoiseToolDBMC + theTool = CaloNoiseToolDBMC(name) + return theTool + else : + mlog.info("Using CaloNoiseTool") + from CaloTools.CaloToolsConf import CaloNoiseTool + # Tile configuration + from TileConditions.TileInfoConfigurator import TileInfoConfigurator + tileInfoConfigurator = TileInfoConfigurator() + tileInfoConfigurator.setupCOOL() + + # CaloNoiseTool configuration + WorkMode=1 + WithOF=True + TileInfoName="TileInfo" + # get public tool LArADC2MeVTool + from LArRecUtils.LArADC2MeVToolDefault import LArADC2MeVToolDefault + theADC2MeVTool = LArADC2MeVToolDefault() + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += theADC2MeVTool + # get public tool LArOFCTool + from LArRecUtils.LArOFCToolDefault import LArOFCToolDefault + theOFCTool = LArOFCToolDefault() + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += theOFCTool + from AthenaCommon.BeamFlags import jobproperties + if jobproperties.Beam.zeroLuminosity(): + ReturnNoise="electronicNoise" + NMinBias=0 + deltaBunch=1 + else: + ReturnNoise="totalNoise" + NMinBias=jobproperties.Beam.numberOfCollisions() + deltaBunch=int(jobproperties.Beam.bunchSpacing()/( 25.*ns)+0.5) + from AthenaCommon.GlobalFlags import globalflags + if globalflags.DataSource()=='data': + IsMC = False + UseSymmetry= False + else: + IsMC = True + UseSymmetry= True + + from LArROD.LArRODFlags import larRODFlags + theTool = CaloNoiseTool(name, + WorkMode = WorkMode, + WithOF = WithOF, + TileInfoName = TileInfoName, + LArADC2MeVTool = theADC2MeVTool, + LArOFCTool = theOFCTool, + ReturnNoise = ReturnNoise, + NMinBias = NMinBias, + deltaBunch = deltaBunch, + IsMC = IsMC, + UseSymmetry = UseSymmetry, + firstSample=larRODFlags.firstSample()) + return theTool diff --git a/Calorimeter/CaloTools/python/__init__.py b/Calorimeter/CaloTools/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..74583d364ec2ca794156596c7254d9b234a940c6 --- /dev/null +++ b/Calorimeter/CaloTools/python/__init__.py @@ -0,0 +1,2 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + diff --git a/Calorimeter/CaloTools/share/CaloBadChannelTool_jobOptions.py b/Calorimeter/CaloTools/share/CaloBadChannelTool_jobOptions.py new file mode 100755 index 0000000000000000000000000000000000000000..abf4bb9b06afd5e1f1dc3a6683d7a31539066356 --- /dev/null +++ b/Calorimeter/CaloTools/share/CaloBadChannelTool_jobOptions.py @@ -0,0 +1,15 @@ +# +# jobOptions for the instance CaloBadChannelTool of ICaloBadChannelTool +# +theApp.Dlls += [ "CaloTools" ] + +ToolSvc = Service( "ToolSvc" ) + +if 'GlobalFlags.DetGeo' in dir(): + if( GlobalFlags.DetGeo.is_ctbh8() ) : + ToolSvc.CaloBadChannelTool.geometry='H8' + else : + ToolSvc.CaloBadChannelTool.geometry='Atlas' + +else : + ToolSvc.CaloBadChannelTool.geometry='Atlas' diff --git a/Calorimeter/CaloTools/share/CaloCellPackerUtils_test.ref b/Calorimeter/CaloTools/share/CaloCellPackerUtils_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Calorimeter/CaloTools/share/CaloCompactCellTool_test.txt b/Calorimeter/CaloTools/share/CaloCompactCellTool_test.txt new file mode 100644 index 0000000000000000000000000000000000000000..0dc9dec0ecec08f4dd40a8450ee42ed712681d19 --- /dev/null +++ b/Calorimeter/CaloTools/share/CaloCompactCellTool_test.txt @@ -0,0 +1,2 @@ +ApplicationMgr.DLLs += { "StoreGate", "CLIDComps", "CaloTriggerTool" }; +ApplicationMgr.ExtSvc += { "StoreGateSvc", "StoreGateSvc/DetectorStore" }; diff --git a/Calorimeter/CaloTools/share/CaloNoiseTool_TB_jobOptions.py b/Calorimeter/CaloTools/share/CaloNoiseTool_TB_jobOptions.py new file mode 100644 index 0000000000000000000000000000000000000000..68ba7964907c8d6a541280bb091f061cb4867af8 --- /dev/null +++ b/Calorimeter/CaloTools/share/CaloNoiseTool_TB_jobOptions.py @@ -0,0 +1,81 @@ + +#jobOptions for Tile part +include( "TileConditions/TileConditions_jobOptions.py" ) + +from AthenaCommon.AppMgr import ToolSvc +#from AthenaCommon.GlobalFlags import globalflags +from AthenaCommon.GlobalFlags import jobproperties + +include("LArRecUtils/LArOFCTool_jobOptions.py") +include("LArRecUtils/LArAutoCorrTotalTool_jobOptions.py") +include("LArRecUtils/LArADC2MeVTool_jobOptions.py") + +from CaloTools.CaloToolsConf import CaloNoiseTool +theCaloNoiseTool=CaloNoiseTool("calonoisetool") + + +# Properties +theCaloNoiseTool.WorkMode=1 +theCaloNoiseTool.WithOF= True +theCaloNoiseTool.TileInfoName="TileInfo" + +# Luminosity +from AthenaCommon.BeamFlags import jobproperties + +if jobproperties.Beam.zeroLuminosity(): + theCaloNoiseTool.ReturnNoise="electronicNoise" + theCaloNoiseTool.NMinBias=0 + ToolSvc.LArAutoCorrTotalTool.NMinBias=0 +else: + theCaloNoiseTool.ReturnNoise="totalNoise" + theCaloNoiseTool.NMinBias=jobproperties.Beam.numberOfCollisions() + ToolSvc.LArAutoCorrTotalTool.NMinBias=jobproperties.Beam.numberOfCollisions() + +_deltaBunch=int(jobproperties.Beam.bunchSpacing()/( 25.*ns)+0.5) +theCaloNoiseTool.deltaBunch = _deltaBunch +ToolSvc.LArAutoCorrTotalTool.deltaBunch = _deltaBunch +del _deltaBunch + + # Concerning CaloNoiseTool and luminosity: + # It will take AutoCorr and OFC calculated at the initialization + # according to the NMinBias set above (in LArAutoCorrTotalTool). + # However if you want/need the expected noise at another luminosity + # you can specify another value, then it will take AutoCorr and OFC + # accordingly recomputed on-fly + # (without affecting the cache of LArAutoCorrTotalTool and LArOFCTool, + # so without affecting the reconstruction) + # Same thing if you specify the luminosity in the calling functions of + # CaloNoiseTool + + +# AutoCorrelation +#(if the matrix is not normalized (default cse for the moment), normalize it +# REMOVED +#if globalflags.DetGeo()=='ctbh8' and globalflags.DataSource()=='data': +# theCaloNoiseTool.NormalizeAutoCorr=True +# ToolSvc.LArOFCTool.NormalizeAutoCorr=True + +# Set data type (needed to decide wether to retrieve LArNoise or LArPedestal for the noise) +if jobproperties.Global.DataSource()=='data': + theCaloNoiseTool.IsMC=False + +# No symmetry for testbeam +if( jobproperties.Global.DetGeo()=='ctbh8' or jobproperties.Global.DetGeo()=='ctbh6' ) : + theCaloNoiseTool.UseSymmetry=False + ToolSvc.LArAutoCorrTotalTool.MCSym = False + ToolSvc.LArADC2MeVTool.MCSym = False + ToolSvc.LArOFCTool.MCSym = False +else: + theCaloNoiseTool.UseSymmetry= True + ToolSvc.LArAutoCorrTotalTool.MCSym = True + ToolSvc.LArADC2MeVTool.MCSym = True + ToolSvc.LArOFCTool.MCSym = True + + + +# Dump the database (ADC2MEV, OFC, AC, ...) used for each cell (long dump !) +#theCaloNoiseTool.DumpDatabaseHG=TRUE +#theCaloNoiseTool.DumpDatabaseMG=TRUE +#theCaloNoiseTool.DumpDatabaseLG=TRUE + +ToolSvc+=theCaloNoiseTool diff --git a/Calorimeter/CaloTools/share/CaloNoiseTool_jobOptions.py b/Calorimeter/CaloTools/share/CaloNoiseTool_jobOptions.py new file mode 100755 index 0000000000000000000000000000000000000000..ff440166ff189680ab0bbf8e6e121cc8620bb6ed --- /dev/null +++ b/Calorimeter/CaloTools/share/CaloNoiseTool_jobOptions.py @@ -0,0 +1,80 @@ + +#jobOptions for Tile part +include( "TileConditions/TileConditions_jobOptions.py" ) + +from AthenaCommon.AppMgr import ToolSvc +from AthenaCommon.GlobalFlags import globalflags + +include("LArRecUtils/LArOFCTool_jobOptions.py") +include("LArRecUtils/LArAutoCorrTotalTool_jobOptions.py") +include("LArRecUtils/LArADC2MeVTool_jobOptions.py") + +from CaloTools.CaloToolsConf import CaloNoiseTool +theCaloNoiseTool=CaloNoiseTool("calonoisetool") + + +# Properties +theCaloNoiseTool.WorkMode=1 +theCaloNoiseTool.WithOF= True +theCaloNoiseTool.TileInfoName="TileInfo" + +# Luminosity +from AthenaCommon.BeamFlags import jobproperties + +if jobproperties.Beam.zeroLuminosity(): + theCaloNoiseTool.ReturnNoise="electronicNoise" + theCaloNoiseTool.NMinBias=0 + ToolSvc.LArAutoCorrTotalTool.NMinBias=0 +else: + theCaloNoiseTool.ReturnNoise="totalNoise" + theCaloNoiseTool.NMinBias=jobproperties.Beam.numberOfCollisions() + ToolSvc.LArAutoCorrTotalTool.NMinBias=jobproperties.Beam.numberOfCollisions() + +_deltaBunch=int(jobproperties.Beam.bunchSpacing()/( 25.*ns)+0.5) +theCaloNoiseTool.deltaBunch = _deltaBunch +ToolSvc.LArAutoCorrTotalTool.deltaBunch = _deltaBunch +del _deltaBunch + + # Concerning CaloNoiseTool and luminosity: + # It will take AutoCorr and OFC calculated at the initialization + # according to the NMinBias set above (in LArAutoCorrTotalTool). + # However if you want/need the expected noise at another luminosity + # you can specify another value, then it will take AutoCorr and OFC + # accordingly recomputed on-fly + # (without affecting the cache of LArAutoCorrTotalTool and LArOFCTool, + # so without affecting the reconstruction) + # Same thing if you specify the luminosity in the calling functions of + # CaloNoiseTool + + +# AutoCorrelation +#(if the matrix is not normalized (default cse for the moment), normalize it +# REMOVED +#if globalflags.DetGeo()=='ctbh8' and globalflags.DataSource()=='data': +# theCaloNoiseTool.NormalizeAutoCorr=True +# ToolSvc.LArOFCTool.NormalizeAutoCorr=True + +# Set data type (needed to decide wether to retrieve LArNoise or LArPedestal for the noise) +if GlobalFlags.DataSource()=='data': + theCaloNoiseTool.IsMC=False + +# No symmetry for testbeam +if( GlobalFlags.DetGeo()=='ctbh8' or GlobalFlags.DetGeo()=='ctbh6' ) : + theCaloNoiseTool.UseSymmetry=False + ToolSvc.LArAutoCorrTotalTool.MCSym = False + ToolSvc.LArADC2MeVTool.MCSym = False + ToolSvc.LArOFCTool.MCSym = False +else: + theCaloNoiseTool.UseSymmetry= True + ToolSvc.LArAutoCorrTotalTool.MCSym = True + ToolSvc.LArADC2MeVTool.MCSym = True + ToolSvc.LArOFCTool.MCSym = True + + + +# Dump the database (ADC2MEV, OFC, AC, ...) used for each cell (long dump !) +#theCaloNoiseTool.DumpDatabaseHG=TRUE +#theCaloNoiseTool.DumpDatabaseMG=TRUE +#theCaloNoiseTool.DumpDatabaseLG=TRUE + +ToolSvc+=theCaloNoiseTool diff --git a/Calorimeter/CaloTools/share/SimpleNoiseToolFromTextFile_jobOptions.py b/Calorimeter/CaloTools/share/SimpleNoiseToolFromTextFile_jobOptions.py new file mode 100755 index 0000000000000000000000000000000000000000..529cafc37979f0dd2edcb864e6be6d0f1b7638b2 --- /dev/null +++ b/Calorimeter/CaloTools/share/SimpleNoiseToolFromTextFile_jobOptions.py @@ -0,0 +1,9 @@ +# +# jobOptions for the instance simplenoisetool of SimpleNoiseToolFromTextFile +# +ToolSvc = Service( "ToolSvc" ) +ToolSvc.simplenoisetool.CellNoiseFileName = "/afs/cern.ch/user/h/hectbmon/public/tb/aug02/noise/H6_2002NoiseMuons.dat" +ToolSvc.simplenoisetool.CellNoiseUnits = MeV +ToolSvc.simplenoisetool.CellNoiseDefault = 100.*MeV +ToolSvc.simplenoisetool.CellNoiseDefaultWarning = TRUE +ToolSvc.simplenoisetool.OutputLevel = INFO diff --git a/Calorimeter/CaloTools/src/CaloAffectedTool.cxx b/Calorimeter/CaloTools/src/CaloAffectedTool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..ea20542449df4fba2f375a72cd25bb49e7e5962f --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloAffectedTool.cxx @@ -0,0 +1,265 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloTools/CaloAffectedTool.h" +//#include "EventKernel/I4Momentum.h" +#include "xAODBase/IParticle.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGateSvc.h" +#include "CaloConditions/CaloAffectedRegionInfoVec.h" +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "CaloGeoHelpers/CaloPhiRange.h" + + +CaloAffectedTool::CaloAffectedTool (const std::string& type, + const std::string& name, + const IInterface* parent) : + AthAlgTool(type, name, parent), + m_readRaw(true) +{ + m_affectedRegions=0; + declareInterface<ICaloAffectedTool>(this); + declareProperty("readRaw",m_readRaw); +} + +//----------------------------------------------------------------- + +CaloAffectedTool::~CaloAffectedTool() { + if (m_affectedRegions && !m_readRaw) delete m_affectedRegions; +} + + +//------------------------------------------------------------------- + +StatusCode CaloAffectedTool::initialize() { + + MsgStream log( msgSvc(), name() ); + + if (!m_readRaw) { + if (detStore()->contains<CondAttrListCollection>("/LAR/LArAffectedRegionInfo")) { + const DataHandle<CondAttrListCollection> affectedRegionH; + if (detStore()->regFcn(&CaloAffectedTool::updateAffectedRegionsFromDB, + this, + affectedRegionH, + "/LAR/LArAffectedRegionInfo").isSuccess()) { + if (log.level() <= MSG::DEBUG) + log << MSG::DEBUG << "Registered callback for LArAffectedRegion " << endreq; + } + else { + log << MSG::WARNING << "Cannot register callback for LArAffectedRegion " << endreq; + } + } + else { + log << MSG::WARNING << " no LArAffectedRegion information available from metadata " << endreq; + } + } + else { + // register incident handler for begin event + IIncidentSvc* incSvc; + if (service( "IncidentSvc", incSvc ).isFailure()) { + log << MSG::ERROR << "Unable to get the IncidentSvc" << endreq; + return StatusCode::FAILURE; + } + long int priority=100; + incSvc->addListener(this,"BeginEvent",priority); + + } + + m_read=false; + return StatusCode::SUCCESS; +} + +//--------------------------------------------------------- + +void CaloAffectedTool::handle(const Incident& inc) { + + MsgStream log(msgSvc(), name()); + + if (inc.type()!="BeginEvent") + return; + + if (detStore()->contains<CaloAffectedRegionInfoVec>("LArAffectedRegion")) { + if (detStore()->retrieve(m_affectedRegions,"LArAffectedRegion").isFailure()) { + log << MSG::WARNING << " cannot read LArAffectedRegion at begin of event " << endreq; + return; + } + m_read=true; + //std::cout << " got affected regions at beginning of event " << std::endl; + return; + } + return; + +} + + +//-------------------------------------------------- + +StatusCode CaloAffectedTool::updateAffectedRegionsFromDB(IOVSVC_CALLBACK_ARGS) { + + return this->readDB(); +} + +StatusCode CaloAffectedTool::readDB() { + + MsgStream log(msgSvc(), name()); // Part 1: Get the messaging service, print where you are + log << MSG::INFO << "updateAffectedRegionsFromDB()" << endreq; + + // retrieve from detStore + const CondAttrListCollection* attrListColl = 0; + StatusCode sc = detStore()->retrieve(attrListColl, "/LAR/LArAffectedRegionInfo"); + if (sc.isFailure()) { + log << MSG::WARNING << "attrrListColl not found for /LAR/CaloAffectedRegionInfo " << endreq; + return StatusCode::SUCCESS; + } + + if (m_affectedRegions) { + m_affectedRegions->clear(); + } + else { + m_affectedRegions = new CaloAffectedRegionInfoVec(); + } + + // Loop over collection + CondAttrListCollection::const_iterator first = attrListColl->begin(); + CondAttrListCollection::const_iterator last = attrListColl->end(); + for (; first != last; ++first) { + std::ostringstream attrStr1; + (*first).second.toOutputStream( attrStr1 ); + log << MSG::DEBUG << "ChanNum " << (*first).first << + " Attribute list " << attrStr1.str() << endreq; + // const AttributeList& attrList = (*first).second; + const coral::AttributeList& attrList = (*first).second; + CaloAffectedRegionInfo info; + float eta_min = attrList["eta_min"].data<float>(); + float eta_max = attrList["eta_max"].data<float>(); + float phi_min = attrList["phi_min"].data<float>(); + float phi_max = attrList["phi_max"].data<float>(); + int layer_min = attrList["layer_min"].data<int>(); + int layer_max = attrList["layer_max"].data<int>(); + //std::cout << " affected region found " << eta_min << " " << eta_max << " " << phi_min << " " << phi_max << " " << layer_min << " " << layer_max << " " << attrList["problem"].data<int>() << std::endl; + CaloAffectedRegionInfo::type_problem problem = (CaloAffectedRegionInfo::type_problem)(attrList["problem"].data<int>()); + + info.FillCaloAffectedRegionInfo(eta_min,eta_max,phi_min,phi_max,layer_min,layer_max,problem); + m_affectedRegions->push_back(info); + } + + m_read = true; + return StatusCode::SUCCESS; + +} + +//------------------------------------------------- + +bool CaloAffectedTool::isAffected(const xAOD::IParticle *p, float deta, float dphi, int layer_min, int layer_max, int problemType) +{ + + static CaloPhiRange _range; + static float epsilon=1e-6; + + //std::cout << " in isAffected " << p->eta() << " " << p->phi() << std::endl; + if (!m_read && !m_readRaw) { + if (this->readDB().isFailure()) return false; + } + if (!m_read) return false; + if (!m_affectedRegions) return false; + + std::vector<CaloAffectedRegionInfo>::const_iterator reg1 = m_affectedRegions->begin(); + std::vector<CaloAffectedRegionInfo>::const_iterator reg2 = m_affectedRegions->end(); + for (;reg1 != reg2; ++reg1) { + const CaloAffectedRegionInfo* region = &(*reg1); + + int problem=region->get_problem(); + //std::cout << " problem,problemType " << problem << " " << problemType << std::endl; + if (problemType>=0 && (problem != problemType)) continue; + + int layermin=region->get_layer_min(); + int layermax=region->get_layer_max(); + //std::cout << " layermin, layermax " << layermin << " " << layermax << std::endl; + if ((layer_max>=layer_min) && (layermax < layer_min || layermin > layer_max)) continue; + + + float etamin=region->get_eta_min(); + float etamax=region->get_eta_max(); + float eta = p->eta(); + //std::cout << " eta region " << etamin << " " << etamax << std::endl; + if ((eta+deta)<etamin || (eta-deta)>etamax) continue; + + float phimin=region->get_phi_min(); + float phimax=region->get_phi_max(); + float phi = p->phi(); + //std::cout << " phi region " << phimin << " " << phimax << std::endl; + float phi2 =_range.fix(phi+dphi+epsilon); + float phi1 =_range.fix(phi-dphi-epsilon); + + if ((phimax >= phimin) && (phi2 >= phi1) && (phi2<phimin || phi1>phimax)) continue; + if ((phimax >= phimin) && (phi2 <= phi1) && (phi1>phimax && phi2<phimin)) continue; + if ((phimax <= phimin) && (phi2 >= phi1) && (phi1>phimax && phi2<phimin)) continue; + + //std::cout << " in region " << std::endl; + + return true; + + } + + return false; + +} +//------------------------------------------------- + +bool CaloAffectedTool::listAffected(const xAOD::IParticle*p, std::vector<int>& layer_list, std::vector<int>& problem_list, float deta, float dphi, int problemType) +{ + + bool found = false; + + static CaloPhiRange _range; + static float epsilon=1e-6; + + layer_list.clear(); + problem_list.clear(); + + if (!m_read && !m_readRaw ) { + if (this->readDB().isFailure()) return false; + } + if (!m_read) return false; + if (!m_affectedRegions) return false; + + std::vector<CaloAffectedRegionInfo>::const_iterator reg1 = m_affectedRegions->begin(); + std::vector<CaloAffectedRegionInfo>::const_iterator reg2 = m_affectedRegions->end(); + for (;reg1 != reg2; ++reg1) { + const CaloAffectedRegionInfo* region = &(*reg1); + + int problem=region->get_problem(); + if (problemType>=0 && (problem != problemType)) continue; + + int layermin=region->get_layer_min(); + int layermax=region->get_layer_max(); + + float etamin=region->get_eta_min(); + float etamax=region->get_eta_max(); + float eta = p->eta(); + if ((eta+deta)<etamin || (eta-deta)>etamax) continue; + + float phimin=region->get_phi_min(); + float phimax=region->get_phi_max(); + float phi = p->phi(); + float phi2 =_range.fix(phi+dphi+epsilon); + float phi1 =_range.fix(phi-dphi-epsilon); + + if ((phimax >= phimin) && (phi2 >= phi1) && (phi2<phimin || phi1>phimax)) continue; + if ((phimax >= phimin) && (phi2 <= phi1) && (phi1>phimax && phi2<phimin)) continue; + if ((phimax <= phimin) && (phi2 >= phi1) && (phi1>phimax && phi2<phimin)) continue; + + found = true; + + for (int ilayer=layermin;ilayer<=layermax;ilayer++) { + layer_list.push_back(ilayer); + problem_list.push_back(problem); + } + + + } + + return found; + +} diff --git a/Calorimeter/CaloTools/src/CaloCellPackerUtils.cxx b/Calorimeter/CaloTools/src/CaloCellPackerUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..5d290cebb8de21bca49e645f6dbbe7a200c2aaad --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloCellPackerUtils.cxx @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCellPackerUtils.cxx,v 1.1 2007-11-08 18:14:22 ssnyder Exp $ +/** + * @file CaloTools/src/CaloCellPackerUtils.cxx + * @author scott snyder + * @date Nov 2007 + * @brief Utilities for compacting calorimeter cells. + */ + + +#include "CaloTools/CaloCellPackerUtils.h" +#include <cassert> + + +namespace CaloCellPackerUtils { + + +/** + * @brief Constructor. + * @param The bit mask. Should contain a single contiguous string of 1's. + */ +Bitfield::Bitfield (unsigned int mask /*= 1*/) +{ + // Shift the mask until the rightmost bit is non-zero. + assert (mask != 0); + m_shift = 0; + while ((mask & 1) == 0) { + mask >>= 1; + ++m_shift; + } + m_mask = mask; +} + + +/** + * @brief Constructor. + * @param The bit mask. Should contain a single contiguous string of 1's. + * @param xmin The smallest storable value. + * @param xmax The largest storable value. + */ +Floatfield::Floatfield (unsigned int mask/*=1*/, + double xmin/*=1*/, + double xmax/*=0*/) + : Bitfield (mask), + m_xmin (xmin), + m_xmax (xmax), + m_fact ((xmax-xmin) / (m_mask + 1)), + m_ifact (1/m_fact) +{ +} + + +/** + * @brief Constructor. + * @param The bit mask. Should contain a single contiguous string of 1's. + * @param xmax The largest storable value. + */ +Floatfield2::Floatfield2 (unsigned int mask/*=1*/, + double xmax/*=1*/) + : Bitfield (mask), + m_xmax (xmax), + m_fact (xmax / (m_mask + 1)), + m_ifact (1/m_fact) +{ +} + + +} // namespace CaloCellPackerUtils diff --git a/Calorimeter/CaloTools/src/CaloCellPacker_400_500.cxx b/Calorimeter/CaloTools/src/CaloCellPacker_400_500.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1cb8a06280183c1d407d330da9eb2e4ecc9fb332 --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloCellPacker_400_500.cxx @@ -0,0 +1,1147 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCellPacker_400_500.cxx,v 1.5 2009-03-31 19:04:04 ssnyder Exp $ +/** + * @file CaloTools/src/CaloCellPacker_400_500.cxx + * @author scott snyder, from earlier code by Ilija Vukotic and Sven Menke + * @date Jan 2009 + * @brief Calo cell packer/unpacker v400/500. + */ + + +#include "CaloTools/CaloCellPacker_400_500.h" +#include "CaloEvent/CaloCellContainer.h" +#include "CaloEvent/CaloCompactCellContainer.h" +#include "CaloEvent/CaloCell.h" +#include "TileEvent/TileCell.h" +#include "CaloInterface/ICaloCompactCellTool.h" +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "AthenaKernel/errorcheck.h" +#include "GaudiKernel/SystemOfUnits.h" + + +//============================================================================ +// Common methods. +// + + +/** + * @brief Initialize header with the current version of the packing + * parameters. (Almost) all the constants are defined here. + * @param header The header to initialize. + * @param version The version of the header to initialize. + */ +void CaloCellPacker_400_500::init_header (header& header, + int version) const +{ + header.m_version = version; + switch (version) { + case ICaloCompactCellTool::VERSION_501: + case ICaloCompactCellTool::VERSION_502: + case ICaloCompactCellTool::VERSION_503: + case ICaloCompactCellTool::VERSION_504: + header.m_length = sizeof(header501)/sizeof(int); + break; + + case ICaloCompactCellTool::VERSION_500: + header.m_length = sizeof(header500)/sizeof(int); + break; + case ICaloCompactCellTool::VERSION_400: + header.m_length = sizeof(header400)/sizeof(int); + break; + default: + std::abort(); + } + + header.m_qualy_mask = 0x8000; + header.m_egain_mask = 0x6000; + header.m_esign_mask = 0x1000; + // 12 bits for cbrt(|E|) and 2 ranges, one normal + // resolution range with upper limit 3.2 TeV and precision loss + // sigma_E'/E < 1.4%/sqrt(E/GeV) and one high-resolution range used + // whenever E < 50 GeV and the hardware gain is HIGH (HEC: MEDIUM) + // resulting in a precision loss of sigma_E'/E < 0.15%/sqrt(E/GeV) + header.m_crtae_mask = 0x0fff; + header.m_egain_tile_mask = 0x4000; + header.m_esign_tile_mask = 0x2000; + // 13 bits cbrt(|E|) and 2 ranges + // upper limit for low gain is 3.2 TeV, + // upper limit for high gain is 50 GeV (safety factor of ~3) + header.m_crtae_tile_mask = 0x1fff; + header.m_tsign_mask = 0x8000; + header.m_logat_mask = 0x7fff; + + header.m_qabad = 0; + header.m_enlow = 0; // normal resolution LOW gain + header.m_enmed = 1; // normal resolution MEDIUM gain + header.m_enhig = 2; // normal resolution HIGH gain + header.m_ehhig = 3; // high resolution HIGH (HEC: MEDIUM) gain + header.m_glow = TileID::LOWGAIN; + header.m_ghigh = TileID::HIGHGAIN; + + header.m_e1_norm_res = 3.2*Gaudi::Units::TeV; + header.m_e1_high_res = 50*Gaudi::Units::GeV; + header.m_high_tile = 50*Gaudi::Units::GeV; + header.m_low_tile = 3.2*Gaudi::Units::TeV; + header.m_t0 = 0.001*Gaudi::Units::ns; + header.m_t1 = 1250.0*Gaudi::Units::ns; + + clear_header(header); +} + + +/** + * @brief Clear the counters in the event header. + * @param header The header to clear. + */ +void CaloCellPacker_400_500::clear_header (header& header) const +{ + header.m_ncells_larem = 0; + header.m_ncells_larhec = 0; + header.m_ncells_larfcal = 0; + header.m_ncells_tile = 0; + header.m_seq_larem = 0; + header.m_seq_larhec = 0; + header.m_seq_larfcal = 0; + header.m_seq_tile = 0; + header.m_lengthProvenance = 0; + header.m_status = 0; +} + + +/** + * @brief Initialize the derived packing parameters from the constants + * in the header. + * @param pars The packing parameters. + */ +void CaloCellPacker_400_500::init_derived (pars500& pars) const +{ + // Good quality flag. + pars.m_qgood = 1; + + // Set up parameters for packing/unpacking the sequence header. + pars.m_hash_field = CaloCellPackerUtils::Bitfield (0x0003ffff); + pars.m_nseq_field = CaloCellPackerUtils::Bitfield (0xfffc0000); + pars.m_nseq_max = 0x3fff; + + // Set up parameters for packing/unpacking the provenance list. + pars.m_prov_field = CaloCellPackerUtils::Bitfield (0xfff80000); + pars.m_prov_max = 0x1fff; + pars.m_prov_max_tile = 0x1f1f; + + // Cube roots of energy ranges. + pars.m_cbrt_e1_norm_res = cbrt(pars.m_e1_norm_res); + pars.m_cbrt_e1_high_res = cbrt(pars.m_e1_high_res); + pars.m_cbrt_low_tile = cbrt(pars.m_low_tile); + pars.m_cbrt_high_tile = cbrt(pars.m_high_tile); + + // Logarithms of time ranges. + pars.m_log_t0 = log(pars.m_t0); + pars.m_log_t1 = log(pars.m_t1); + + // Fill in remaining bit fields. + pars.m_qualy_field = CaloCellPackerUtils::Bitfield (pars.m_qualy_mask); + pars.m_egain_field = CaloCellPackerUtils::Bitfield (pars.m_egain_mask); + pars.m_crtae_norm_field = + CaloCellPackerUtils::Floatfield2 (pars.m_crtae_mask, + pars.m_cbrt_e1_norm_res); + pars.m_crtae_high_field = + CaloCellPackerUtils::Floatfield2 (pars.m_crtae_mask, + pars.m_cbrt_e1_high_res); + pars.m_logat_field = + CaloCellPackerUtils::Floatfield (pars.m_logat_mask, + pars.m_log_t0, pars.m_log_t1); + pars.m_egain_tile_field = + CaloCellPackerUtils::Bitfield (pars.m_egain_tile_mask); + pars.m_crtae_tile_high_field = + CaloCellPackerUtils::Floatfield2 (pars.m_crtae_tile_mask, + pars.m_cbrt_high_tile); + pars.m_crtae_tile_low_field = + CaloCellPackerUtils::Floatfield2 (pars.m_crtae_tile_mask, + pars.m_cbrt_low_tile); + + pars.m_tile_qual1_field = CaloCellPackerUtils::Bitfield (0x00ff); + pars.m_tile_qual2_field = CaloCellPackerUtils::Bitfield (0xff00); + + // Dummy flags. + pars.m_lar_dummy = + pars.m_egain_field.in (pars.m_enhig) | + pars.m_qualy_field.in (pars.m_qabad) | + pars.m_crtae_norm_field.in (cbrt (pars.m_e1_norm_res)) | + pars.m_esign_mask; + + pars.m_tile_dummy = + pars.m_egain_tile_field.in (pars.m_glow) | + pars.m_qualy_field.in (pars.m_qabad) | + pars.m_crtae_tile_high_field.in (pars.m_cbrt_high_tile) | + pars.m_esign_tile_mask; + + + { + CaloCellPackerUtils::Bitfield& elar = pars.m_crtae_norm_field; + pars.m_lar_dummy_subst = (pars.m_lar_dummy & ~pars.m_crtae_mask) | + elar.in (elar.out (pars.m_lar_dummy)-1); + + CaloCellPackerUtils::Bitfield& etile = pars.m_crtae_tile_high_field; + pars.m_tile_dummy_subst = (pars.m_tile_dummy & ~pars.m_crtae_tile_mask) | + etile.in (etile.out (pars.m_tile_dummy)-1); + } +} + + +//============================================================================ +// Packing. +// To ensure full inlining, don't reorder these. +// + + +/** + * @brief Pack a time value. + * @param time The time to pack. + * @param it The iterator into which to pack. + * @param pars The packing parameters. + */ +inline +void CaloCellPacker_400_500::pack_time + (float time, + CaloCompactCellContainer::compact_output_iterator& it, + const pars500& pars) const +{ + // We want to pack log(abs(time)). + float ltime = pars.m_log_t0; + if (time != 0) + ltime = log(fabs(time)); + + // Pack it into the bitfield. + CaloCompactCell::value_type data = pars.m_logat_field.in (ltime); + + // Set the sign bit. + if ( time < 0 ) + data |= pars.m_tsign_mask; + + // Fill output. + it.set (data); +} + + +/** + * @brief Pack one LAr cell. + * @param cell The cell to pack. + * @param subcalo The cell's subcalorimeter code. + * @param it The iterator into which to pack. + * @param pars The packing parameters. + */ +inline +void CaloCellPacker_400_500::pack_lar + (const CaloCell* cell, + CaloCell_ID::SUBCALO subcalo, + CaloCompactCellContainer::compact_output_iterator& it, + const pars500& pars) const +{ + // Get values from the cell. + double energy = cell->energy(); + double time = cell->time(); + int qualflag; + if( (cell->provenance() & 0x2000) == 0x2000 ) + qualflag=pars.m_qgood; + else + qualflag=pars.m_qabad; + + int gain = cell->gain(); + + // Figure out which gain to use. + // cbrt_flag is set to 1 for the high gain range (50 GeV) and 0 for + // the low gain range (3.2 TeV). + int gainflag = -999; + int cbrt_flag = 0; + switch ( gain ) { + case CaloGain::LARLOWGAIN: + gainflag = pars.m_enlow; + break; + case CaloGain::LARMEDIUMGAIN: + if ( subcalo == CaloCell_ID::LARHEC && + fabs(energy) < pars.m_e1_high_res ) + { + gainflag = pars.m_ehhig; + cbrt_flag = 1; + } + else + gainflag = pars.m_enmed; + break; + case CaloGain::LARHIGHGAIN: + if ( fabs(energy) < pars.m_e1_high_res && + subcalo != CaloCell_ID::LARHEC ) + { + gainflag = pars.m_ehhig; + cbrt_flag = 1; + } + else + gainflag = pars.m_enhig; + break; + + default: + // Some invalid gain. Mark as an error. + gainflag = -999; + } + + if (gainflag == -999) { + it.set (pars.m_lar_dummy); + } + else { + // Pack the energy, gain, and quality into the output word. + double crtae = cbrt(fabs(energy)); + CaloCompactCell::value_type data = + pars.m_egain_field.in (gainflag) | + pars.m_qualy_field.in (qualflag) | + (cbrt_flag ? pars.m_crtae_high_field.in (crtae) + : pars.m_crtae_norm_field.in (crtae)); + + // Set the sign bit. + if (energy < 0) + data |= pars.m_esign_mask; + + if (data == pars.m_lar_dummy) + data = pars.m_lar_dummy_subst; + + // Fill the output container. + it.set (data); + + // If quality is not bad there are time and quality (chi^2) measurements. + if ( qualflag != pars.m_qabad){ + pack_time (time, it, pars); + if (pars.m_version >= 500) + it.set(cell->quality()); + } + } +} + + +/** + * @brief Pack one tile cell. + * @param cell The cell to pack. + * @param it The iterator into which to pack. + * @param pars The packing parameters. + */ +inline +void CaloCellPacker_400_500::pack_tile + (const TileCell* cell, + CaloCompactCellContainer::compact_output_iterator& it, + const pars500& pars) const +{ + // Tile cells have two separate measurements to pack. + // Retrieve them both: + double ene[2] = {cell->ene1(), cell->ene2()}; + double time[2] = {cell->time1(), cell->time2()}; + int qbit[2] = {cell->qbit1(), cell->qbit2()}; + int gain[2] = {cell->gain1(), cell->gain2()}; + + // Loop over the two measurements (PMTs). + // If no cell both gains are bad; + // if only one pmt per cell, second gain is bad. + bool write_qual = false; + for (int ipmt=0; ipmt<2; ++ipmt) { + // We'll set this to true if we want to write time information. + bool write_time = false; + + // The data word we're building. + CaloCompactCell::value_type data; + + // Does this measurement exist? + if (gain[ipmt] == CaloGain::INVALIDGAIN) { + // No --- make a dummy. + data = pars.m_tile_dummy; + } + else { + // Yes --- we have a measurement. See if the quality's good. + // If so, then we'll want to write the time too. + int qualflag = pars.m_qabad; + if (qbit[ipmt] >= TileCell::KEEP_TIME) { + qualflag = pars.m_qgood; + write_time = true; + write_qual = true; + } + + // Pack the energy, with the proper range, depending on the gain. + double crtae = cbrt(fabs(ene[ipmt])); + if (gain[ipmt] != pars.m_glow) + data = pars.m_crtae_tile_high_field.in (crtae); + else + data = pars.m_crtae_tile_low_field.in (crtae); + + // Add in the gain and quality. + data |= + pars.m_egain_tile_field.in (gain[ipmt]) | + pars.m_qualy_field.in (qualflag); + + // Add the sign bit. + if (ene[ipmt] < 0) + data |= pars.m_esign_tile_mask; + + if (data == pars.m_tile_dummy) + data = pars.m_tile_dummy_subst; + } + + // Fill to the output container. + it.set (data); + + // Fill the time and quality, if needed. + if (write_time) + pack_time (time[ipmt], it, pars); + } + + if (pars.m_version >= 502 && write_qual) { + it.set (cell->quality()); + } +} + + +/** + * @brief Finish up one cell sequence. + * @param hash The hash of the first cell in the sequence. + * @param nseq The number of cells in the sequence. + * @param it Iterator pointing at the beginning of the sequence. + * @param subcalo Subcalorimeter code for the sequence. + * @param pars The packing parameters. + */ +inline +void CaloCellPacker_400_500::finish_seq + (unsigned int hash, + unsigned int nseq, + CaloCompactCellContainer::compact_output_iterator& it, + CaloCell_ID::SUBCALO subcalo, + pars500& pars) const +{ + // Pack the hash code and number of cells into a bitfield. + CaloCompactCellContainer::value_type data = + pars.m_hash_field.in(hash) | pars.m_nseq_field.in(nseq); + + // Write it into the output container. + it.set ((data>>16) & 0xffff); + it.set (data & 0xffff); + + // Update counters. + switch (subcalo) { + case CaloCell_ID::LAREM: + pars.m_ncells_larem += nseq; + ++pars.m_seq_larem; + break; + case CaloCell_ID::LARHEC: + pars.m_ncells_larhec += nseq; + ++pars.m_seq_larhec; + break; + case CaloCell_ID::LARFCAL: + pars.m_ncells_larfcal += nseq; + ++pars.m_seq_larfcal; + break; + case CaloCell_ID::TILE: + pars.m_ncells_tile += nseq; + ++pars.m_seq_tile; + break; + default: + std::abort(); + } +} + + +/** + * @brief Pack cells. + * @param cells The input cell container. + * @param packed The output packed cell container. + * @param version The version of the header to initialize. + */ +void CaloCellPacker_400_500::pack (const CaloCellContainer& cells, + CaloCompactCellContainer& packed, + int version) const +{ + // Set up the header and derived parameters. + pars500 pars; + init_header (pars, version); + init_derived (pars); + + std::vector<short unsigned int> vProvenance; + + // Figure out an upper limit for the container size. + // Header, plus one word/cell for sequence, two words/cell for data, + // and another word/cell for provenance. + // Tile cells have two additional words/cell - energy and time for second PMT. + // Add one more to account for possible padding before the provenance info. + // We'll resize this down correctly when we're done. + unsigned int maxsize = + pars.m_length + 4 * cells.size() + 2 * cells.nCellsCalo (CaloCell_ID::TILE)+1; + packed.resize (maxsize); + + // Set up for loop over cells. + + // This is the output iterator, to which we write. + CaloCompactCellContainer::compact_output_iterator outit + (packed.compact_begin_output (pars.m_length)); + + // Here we save the output iterator at the beginning of each sequence. + // We'll use that to go back and plug in the count when we're done. + CaloCompactCellContainer::compact_output_iterator seqit + (packed.compact_begin_output (pars.m_length)); + + // The hash of the first cell in the current sequence. + unsigned int seqhash = static_cast<unsigned int> (-1); + + // Number of cells so far in the current sequence. + // 0 if not in a sequence. + unsigned int nseq = 0; + + // The subcalorimeter code of the previous cell we looked at. + CaloCell_ID::SUBCALO prevcalo = CaloCell_ID::NOT_VALID; + + // If all the cells have provenance 0, there is nothing in the vector. + short unsigned int prevCellProvenance=0; + + // check if it is a SuperCell + bool is_SC=false; + if (cells.size()>0){ + // assuming no mixed SC and Cells. + const CaloDetDescrElement* dde = cells[0]->caloDDE(); + const CaloCell_Base_ID* idhelper = + dde->descriptor()->get_calo_helper(); + is_SC = idhelper->is_supercell(cells[0]->ID()); + } + + if (is_SC) + pars.m_status |= header::STATUS_IS_SUPERCELL; + + // Loop over input cells. + for (CaloCellContainer::const_iterator it = cells.begin(); + it != cells.end(); + ++it) + { + // Pick up values from the cell. + const CaloCell* cell = *it; + const CaloDetDescrElement* dde = cell->caloDDE(); + unsigned int hash = dde->calo_hash(); + CaloCell_ID::SUBCALO subcalo = dde->getSubCalo(); + + // Test to see if we need to start a new sequence. + if (// Not in a sequence now? + nseq == 0 || + // We're at the maximum sequence length? + nseq >= pars.m_nseq_max || + // A skip in the cell hash codes? + seqhash + nseq != hash || + // Moving to a new subcalorimeter? + subcalo != prevcalo) + { + // Mark if cells aren't ordered. + if (prevcalo != CaloCell_ID::NOT_VALID && + subcalo < prevcalo) + pars.m_status |= header::STATUS_UNORDERED; + + // If we're already in a sequence, need to finish it. + if (nseq > 0) + finish_seq (seqhash, nseq, seqit, prevcalo, pars); + + // Start a new sequence. + nseq = 0; + seqhash = hash; + prevcalo = subcalo; + // Leave space to fill in the hash/count later. + seqit = outit; + ++outit; + ++outit; + } + + // Add the current cell on to sequence. + if (!is_SC && subcalo == CaloCell_ID::TILE) { + pack_tile (static_cast<const TileCell*>(cell), outit, pars); + + // Check to see if the provenance changed. + if (version >= 502 && + (cell->provenance() & pars.m_prov_max_tile) != prevCellProvenance) + { + prevCellProvenance = cell->provenance() & pars.m_prov_max_tile; + CaloCompactCellContainer::value_type data = + pars.m_hash_field.in(hash) | + pars.m_prov_field.in(prevCellProvenance); + vProvenance.push_back ((data>>16) & 0xffff); + vProvenance.push_back (data & 0xffff); + } + } + else { + pack_lar (cell, subcalo, outit, pars); + + // Check to see if the provenance changed. + if (version >= 500 && + (cell->provenance() & pars.m_prov_max) != prevCellProvenance) + { + prevCellProvenance = cell->provenance() & pars.m_prov_max; + CaloCompactCellContainer::value_type data = + pars.m_hash_field.in(hash) | + pars.m_prov_field.in(prevCellProvenance); + vProvenance.push_back ((data>>16) & 0xffff); + vProvenance.push_back (data & 0xffff); + } + } + ++nseq; + } + + // Finish the last sequence. + if (nseq != 0) + finish_seq (seqhash, nseq, seqit, prevcalo, pars); + + pars.m_lengthProvenance = vProvenance.size(); + + assert (outit.used() + pars.m_length + vProvenance.size()/2 + 1 <= maxsize); + + if (pars.m_lengthProvenance > 0) { + // this part is making existing vector to have full number of 32 bit words. + int x=outit.used(); + // dummy value of 0 is inserted + outit.set(0); + int y=outit.used(); + // if size changed it means that vector was flat at the end and that we spoiled it. + // so we have to fix it. + if (x!=y) outit.set(0); + // now its surely flat. + + // add provenance stuff at the end. + for (std::vector<short unsigned int>::iterator iter = vProvenance.begin(); + iter != vProvenance.end(); + ++iter) + { + outit.set (*iter); + } + } + + // Now resize the container to the final size. + packed.resize (outit.used() + pars.m_length); + + // And copy the header to the front. + write_header (pars, packed); +} + + +/** + * @brief Write the header to the output container. + * @param header The header to write. + * @param packed The container to which to write. + */ +void +CaloCellPacker_400_500::write_header (const header& header, + CaloCompactCellContainer& packed) const +{ + const int * phead = &(header.m_length); + std::vector<CaloCompactCellContainer::value_type> + vhead (phead, phead + header.m_length); + packed.setHeader(vhead); +} + + + +//============================================================================ +// Unpacking. +// To ensure full inlining, don't reorder these. +// + + +/** + * @brief Unpack the time word. + * @param it Input iterator. + * @param pars Unpacking parameters. + * @return The unpacked time. + */ +inline +double CaloCellPacker_400_500::unpack_time + (CaloCompactCellContainer::compact_input_iterator& it, + const pars500& pars) const +{ + // Get the word from the input container. + CaloCompactCell::value_type data = it.next(); + + // Unpack to a float. + int underflow; + double time = pars.m_logat_field.out (data, underflow); + if (UNLIKELY(underflow)) + return 0; + + // Exponentiate, and restore the sign. + // (nb. introducing `ee' helps the gcc optimizer avoid a redundant + // test on the underflow flag.) + double ee = std::exp (time); + if (data & pars.m_tsign_mask) + return -ee; + return ee; +} + + +/** + * @brief Unpack a LAr cell. + * @param it Input iterator. + * @param subcalo Subcalorimeter code for the cell. + * @param cell Pointer to the cell in which to write. + * @param pars Unpacking parameters. + * @param provenance The provenance word for this cell. + * @return @a cell, as a @c CaloCell*. + * + * The DDE and ID will be set in the cell separately; here, we need only + * fill in the cell data. + */ +inline +CaloCell* +CaloCellPacker_400_500::unpack_lar + (CaloCompactCellContainer::compact_input_iterator& it, + CaloCell_ID::SUBCALO subcalo, + LArCell* cell, + const pars500& pars, + uint16_t provenance) const +{ + // Get the data word from the input. + CaloCompactCell::value_type data = it.next(); + + // Recognize cells filled with dummy values. + if (data == pars.m_lar_dummy) + { + cell->set (0, 0, 0, provenance, CaloGain::INVALIDGAIN); + return cell; + } + + // Unpack the gain flag. + int gainflag = pars.m_egain_field.out (data); + int qualflag = pars.m_qualy_field.out (data); + + CaloGain::CaloGain gain = CaloGain::UNKNOWNGAIN; + + // Convert to the CaloCell gain, and convert the energy back to a float + // using the proper range. + double energy; + if ( gainflag == pars.m_ehhig ) { + if ( subcalo == CaloCell_ID::LARHEC ) + gain = CaloGain::LARMEDIUMGAIN; + else + gain = CaloGain::LARHIGHGAIN; + energy = pars.m_crtae_high_field.out (data); + } + else { + if ( gainflag == pars.m_enhig ) { + gain = CaloGain::LARHIGHGAIN; + } + else if ( gainflag == pars.m_enmed ) { + gain = CaloGain::LARMEDIUMGAIN; + } + else if ( gainflag == pars.m_enlow) { + gain = CaloGain::LARLOWGAIN; + } + energy = pars.m_crtae_norm_field.out (data); + } + + // Now undo the cube root and apply the sign bit. + energy = energy*energy*energy; + if (data & pars.m_esign_mask) + energy = -energy; + + // If the quality's good, then we need to unpack the time/chi2 too. + double time = 0; + uint16_t quality=0; + if ( qualflag != pars.m_qabad ) { + time = unpack_time (it, pars); + if (pars.m_version >= 500) + quality=it.next(); + provenance = provenance | 0x2000; + } + + // Fill the data into the cell. + cell->set (energy, time, quality, provenance, gain); + + // Return it. + return cell; +} + + +/** + * @brief Unpack a tile cell. + * @param it Input iterator. + * @param dde Descriptor element for the cell. + * @param pars Unpacking parameters. + * @return The new cell. + */ +inline +TileCell CaloCellPacker_400_500::unpack_tile + (CaloCompactCellContainer::compact_input_iterator& it, + const CaloDetDescrElement* dde, + const pars500& pars, + uint16_t provenance) const +{ + // Loop over the two elements for the cell. + double ene[2]; + double time[2]; + int gain[2]; + int qbit[2]; + + bool read_qual = false; + + for (int ipmt = 0; ipmt < 2; ++ipmt) { + // Unpack the data word. + CaloCompactCell::value_type data = it.next(); + + // Is this measurement a dummy? + if (data == pars.m_tile_dummy) + { + // Yeah --- fill in dummy values and skip the rest. + ene[ipmt] = 0; + gain[ipmt] = CaloGain::INVALIDGAIN; + qbit[ipmt] = 0; + if (ipmt == 1) + time[ipmt] = time[0]; + else + time[ipmt] = 0; + continue; + } + + // Get the quality and gain. + int qualflag = pars.m_qualy_field.out (data); + int gainflag = pars.m_egain_tile_field.out (data); + + gain[ipmt] = gainflag; + + // Unpack the energy, using the range appropriate to the gain. + double e; + if (gainflag != pars.m_glow) + e = pars.m_crtae_tile_high_field.out (data); + else + e = pars.m_crtae_tile_low_field.out (data); + ene[ipmt] = e*e*e; + if (data & pars.m_esign_tile_mask) + ene[ipmt] = -ene[ipmt]; + + // If the quality is good, we need to unpack the time too. + if (qualflag != pars.m_qabad) { + read_qual = true; + time[ipmt] = unpack_time (it, pars); + qbit[ipmt] = TileCell::MASK_CMPC | TileCell::MASK_TIME; + } + else { + time[ipmt] = 0; + qbit[ipmt] = TileCell::MASK_CMPC; + } + } + + uint8_t qual[2]; + if (pars.m_version >= 502) { + qbit[0] |= pars.m_tile_qual1_field.out (provenance); + qbit[1] |= pars.m_tile_qual2_field.out (provenance); + if (read_qual) { + uint16_t qualp = it.next(); + qual[0] = pars.m_tile_qual1_field.out (qualp); + qual[1] = pars.m_tile_qual2_field.out (qualp); + } else { + qual[0] = ((qbit[0] & TileCell::MASK_BADCH) != 0) ? 255 : 0; + qual[1] = ((qbit[1] & TileCell::MASK_BADCH) != 0) ? 255 : 0; + } + } + else { + qual[0] = qual[1] = 0; + } + + // Make the cell. + return TileCell (dde, ene[0], ene[1], time[0], time[1], + qual[0], qual[1], qbit[0], qbit[1], gain[0], gain[1]); +} + + +/** + * @brief Unpack cells. + * @param packed The input packed cell container. + * @param vheader The header part of the packed data. + * @param cells The output cell container. + * @param larpool Pool for allocating LAr cells. + * @param tilepool Pool for allocating Tile cells. + * + * Note that allocations will be done from the provided pools, + * and the pools retain ownership of the cells. + * The @a cells container will be changed to a view container. + */ +void CaloCellPacker_400_500::unpack + (const CaloCompactCellContainer& packed, + const std::vector<int>& vheader, + CaloCellContainer& cells, + DataPool<LArCell>& larpool, + DataPool<TileCell>& tilepool) const +{ + // Convert the header. + pars500 pars; + + { + const int* headerbeg = &*vheader.begin(); + const int* headerend = headerbeg + vheader.size(); + size_t nheader = headerend - headerbeg; + size_t parsize = sizeof(header) / sizeof(int); + size_t ncopy = std::min (nheader, parsize); + int* parsbeg = &pars.m_length; + std::copy (headerbeg, headerbeg+ncopy, parsbeg); + if (nheader > parsize) { + // Header was longer than we expected --- there's something + // wrong with the data. Issue a warning. + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: Compact cell header is " + << nheader << " words long, longer than the largest expected value of " + << parsize << "."; + } + else if (ncopy < parsize) { + // Header was shorter than we expected. + // It may be a previous version --- clear out the remainder of pars. + // TODO: Cross-check the size we got with what we expect based + // on the version number in the header. + std::fill (parsbeg + ncopy, parsbeg + parsize, 0); + } + } + + // Initialize derived parameters from the header. + init_derived (pars); + + // Bounds check on size of provenance. + unsigned nprov = pars.m_lengthProvenance/2; + if (nprov + vheader.size() > packed.getData().size()) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: Provenance count too large " + << pars.m_lengthProvenance << "."; + pars.m_lengthProvenance = 0; + nprov = 0; + } + + // need to make a new iterator and use it for provenance. + CaloCompactCellContainer::compact_input_iterator provIt = + packed.compact_begin_input_from(pars.m_lengthProvenance/2); + unsigned iprov=0; + + // getting starting values + short unsigned int currProvValue=0; + int nextProvHash=-1; + short unsigned int nextProvValue=0; + if (pars.m_lengthProvenance) { + unsigned int provhash = provIt.next(); + provhash = (provhash<<16) | provIt.next(); + nextProvValue = pars.m_prov_field.out (provhash); + nextProvHash = pars.m_hash_field.out (provhash); + iprov++; + } + + bool is_SC = (pars.m_status & header::STATUS_IS_SUPERCELL); + + // We need the detector description. + const CaloDetDescrManager_Base *ddmgr = 0; + if (is_SC){ + ddmgr = CaloSuperCellDetDescrManager::instance(); + }else + { + ddmgr = CaloDetDescrManager::instance(); + } + const CaloCell_Base_ID *calo_id = ddmgr->getCaloCell_ID(); + + // Clear the output container and reserve the right number of elements. + cells.clear(SG::VIEW_ELEMENTS); + CaloCell_ID::size_type totcells = + pars.m_ncells_larem + pars.m_ncells_larhec + + pars.m_ncells_larfcal + pars.m_ncells_tile; + if (totcells > calo_id->calo_cell_hash_max()) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: Too many cells " << totcells << "."; + totcells = calo_id->calo_cell_hash_max(); + } + cells.reserve (totcells); + + // To speed things up, we'll use the underlying vector from the cell + // container. + std::vector<CaloCell*>& cellsv = + const_cast<std::vector<CaloCell*>&>(cells.stdcont()); + + // Iterator for scanning the input. + CaloCompactCellContainer::compact_input_iterator it = + packed.compact_begin_input(); + + // To test for falling off the end. + std::vector<CaloCompactCellContainer::value_type>::const_iterator pend = + packed.getData().end() - (pars.m_lengthProvenance+1)/2; + + // Sum up the total number of cells/sequences over all subcalos. + unsigned int ncells = + pars.m_ncells_larem + + pars.m_ncells_larhec + + pars.m_ncells_larfcal + + pars.m_ncells_tile; + unsigned int nseqs = + pars.m_seq_larem + + pars.m_seq_larhec + + pars.m_seq_larfcal + + pars.m_seq_tile; + + // Note: In the first version of the v400 packer, the sequence counts + // would be left uninitialized if ncells==0. + if (ncells == 0) + nseqs = 0; + + // Warn if there are too many cells/sequences. + IdentifierHash hashmax = calo_id->calo_cell_hash_max(); + if (ncells > hashmax || nseqs > hashmax || nseqs > ncells) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: Bad counts" + << ": ncells " << ncells << " nseqs " << nseqs << " hashmax " << hashmax; + } + + CaloCell_ID::SUBCALO prevcalo = CaloCell_ID::NOT_VALID; + + // Loop over sequences. + while (nseqs--) { + + // Check for overrun. + if (it.base() >= pend) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: cell vector overrun."; + break; + } + + // Get the starting hash code and count. + CaloCompactCell::value_type data = it.next(); + unsigned int hashlength = data << 16; + hashlength |= it.next(); + + unsigned int hash = pars.m_hash_field.out (hashlength); + unsigned int nseq = pars.m_nseq_field.out (hashlength); + + if (nseq > ncells || hash+nseq > hashmax) + { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: bad sequence. " + << "nseq " << nseq << " hash " << hash << " ncells " << ncells + << " hashmax " << hashmax; + break; + } + + // Subcalo code for this cell. + CaloCell_ID::SUBCALO subcalo = + static_cast<CaloCell_ID::SUBCALO> (calo_id->sub_calo (hash)); + + // Maintain the cell container's pointers --- only if cells were ordered! + if (subcalo != prevcalo) { + if ((pars.m_status & header::STATUS_UNORDERED) == 0) { + if (prevcalo != CaloCell_ID::NOT_VALID) { + cells.updateCaloEndIterators (prevcalo, cells.size()); + if (subcalo < prevcalo) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Cells not in subcalo order; iterators will be wrong."; + } + } + cells.updateCaloBeginIterators (subcalo, cells.size()); + } + cells.setHasCalo (subcalo); + prevcalo = subcalo; + } + + // Loop over cells in the sequence. + while (nseq--) { + // Find the descriptor element for this cell. + const CaloDetDescrElement *dde = ddmgr->get_element(hash); + + if (dde == 0) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: can't find DDE for cell with hash " << hash; + } + + // Unpack the cell. + // + // One point here that needs explaining. + // The pack_tile method returns a TileCell by value. + // Normally, this would involve a copy; however, we're careful + // to allow the compiler to use the `return value optimization' + // to avoid this copy. That way, we can use the TileCell constructor + // directly, without having to add extra set methods (or violate + // encapsulation, as the previous version of this code did). + // We get a pointer to a TileCell from the data pool and + // use this in a placement new to initialize a TileCell + // using the value returned from unpack_tile. Due to the RVO, + // the copy is avoided, and the constructor in unpack_tile + // will run its constructor directly on the pointer gotten + // from the pool. For this to work correctly, we rely + // on the fact that TileCell has only a trivial destructor --- + // thus it's safe to rerun the constructor on an object that + // has already been constructed. + // + // You'll notice, however, that CaloCell is done differently. + // CaloCell is not a simple class; it has a complicated inheritance + // structure. It was found that setting up all the vtable pointers + // in CaloCell was taking a considerable amount of time + // (comparable to filling in the cell data). So, for CaloCell, + // we instead add a couple new (inlined) set methods to fill + // in the data directly, without having to redo the vtable pointers. + // We split it in two, one for dde/id and the other for the cell data, + // to reduce the amount of data we need to pass to unpack_lar. + // + // Why wasn't the same thing done for TileCell, then? + // - I don't have TC rights for TileEvent, so changing that + // is more of a hassle. + // - There are many fewer tile cells than LAr cells. + // - The TileCell constructor we use is significantly + // more complicated than LArCell. We'd have to duplicate + // this code. Further, this, together with the previous + // point, implies that the performance implications + // of rebuilding the vtable pointers is much less + // for tile cells than for LAr cells. + + // New provenance? + if (hash==static_cast<unsigned int>(nextProvHash)){ + currProvValue = nextProvValue; + if (iprov<nprov) { + unsigned int provhash = provIt.next(); + provhash = (provhash<<16) | provIt.next(); + nextProvValue = pars.m_prov_field.out (provhash); + nextProvHash = pars.m_hash_field.out (provhash); + iprov++; + } else { + nextProvHash = -1; + } + } + + CaloCell* cell; + if (!is_SC && subcalo == CaloCell_ID::TILE) + cell = new (tilepool.nextElementPtr()) + TileCell (unpack_tile (it, + dde, + pars, currProvValue)); + else { + cell = unpack_lar (it, + subcalo, + larpool.nextElementPtr(), + pars, + currProvValue); + cell->set (dde, calo_id->cell_id(hash)); + } + + // Add the cell to the container. + if (dde) + cellsv.push_back (cell); + + // Move to next cell. + ++hash; + } + } + + // Finish off the last iterator. + if (prevcalo != CaloCell_ID::NOT_VALID) + cells.updateCaloEndIterators (prevcalo, cells.size()); + + // Check that we've consumed all the data. + // Note that there may be a padding word before the provenance word. + if (it.base() < pend-2) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING, + "CaloCellPacker_400_500 ") + << "Corrupted data: didn't consume all packed data."; + } +} + + +//============================================================================ diff --git a/Calorimeter/CaloTools/src/CaloCompactCellTool.cxx b/Calorimeter/CaloTools/src/CaloCompactCellTool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..b07fc7e5361004bc3dcfd9478a588ff0f4542954 --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloCompactCellTool.cxx @@ -0,0 +1,125 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//----------------------------------------------------------------------- +// File and Version Information: +// $Id: CaloCompactCellTool.cxx,v 1.35 2009-03-19 01:42:15 ssnyder Exp $ +// +// Description: see CaloCompactCellTool.h +// +// Environment: +// Software developed for the ATLAS Detector at the CERN LHC +// +// All compactor versions before version 400 are removed and can be found only in +// old versions in CVS +//----------------------------------------------------------------------- + +#define private public +#define protected public +#include "LArRecEvent/LArCell.h" +#include "TileEvent/TileCell.h" +#undef private +#undef protected + +#include "DataModel/DataPool.h" +#include "CaloTools/CaloCompactCellTool.h" +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloTools/CaloCellPacker_400_500.h" +#include "GaudiKernel/MsgStream.h" + +CaloCompactCellTool::CaloCompactCellTool(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool(type,name,parent) +{ +declareInterface< ICaloCompactCellTool >( this ); +} + +CaloCompactCellTool::~CaloCompactCellTool() +{ } + +StatusCode CaloCompactCellTool::initialize() +{ + declareInterface<ICaloCompactCellTool>(this); + return StatusCode::SUCCESS; +} + +StatusCode CaloCompactCellTool::finalize() +{ + return StatusCode::SUCCESS; +} + +StatusCode CaloCompactCellTool::getTransient +(const CaloCompactCellContainer & theCompactContainer, + CaloCellContainer * theCellContainer) +{ + MsgStream logStream(msgSvc(), name()); + + const std::vector<CaloCompactCellContainer::value_type> theHeader = theCompactContainer.getHeader(); + logStream << MSG::DEBUG << " getTransient: using version: "<<theHeader[1] << endreq; + + static DataPool<LArCell> larCellsP(220000);//initialize for the default value will resize latter to full size + static DataPool<TileCell> tileCellsP(13000); + + switch (theHeader[1]) { + + case ICaloCompactCellTool::VERSION_400: + case ICaloCompactCellTool::VERSION_500: + case ICaloCompactCellTool::VERSION_501: + case ICaloCompactCellTool::VERSION_502: + case ICaloCompactCellTool::VERSION_503: + case ICaloCompactCellTool::VERSION_504: + { + CaloCellPacker_400_500 packer; + packer.unpack (theCompactContainer, theHeader, *theCellContainer, + larCellsP, tileCellsP); + } + break; + + default: + logStream << MSG::FATAL << " unknown version " << theHeader[1] + << " requested for unpacking the CaloCompactCellContainer" + << endreq; + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +StatusCode CaloCompactCellTool::getPersistent //fill the CaloCompactCellContainer +(const CaloCellContainer & theCellContainer, + CaloCompactCellContainer * theCompactContainer, + int theVersion ) +{ + MsgStream logStream(msgSvc(), name()); + + logStream << MSG::DEBUG << "CaloCell container contains " << theCellContainer.size() << " cells. Write compact Ver: " << theVersion <<endreq; + + if (theVersion == ICaloCompactCellTool::VERSION_LATEST) + theVersion = ICaloCompactCellTool::VERSION_504; + + switch (theVersion ) { + + case ICaloCompactCellTool::VERSION_400: + case ICaloCompactCellTool::VERSION_500: + case ICaloCompactCellTool::VERSION_501: + case ICaloCompactCellTool::VERSION_502: + case ICaloCompactCellTool::VERSION_503: + case ICaloCompactCellTool::VERSION_504: + { + CaloCellPacker_400_500 packer; + + packer.pack (theCellContainer, *theCompactContainer, theVersion); + } + break; + + default: + logStream << MSG::FATAL << " unknown version " << theVersion + << " requested for packing the CaloCellContainer" << endreq; + return StatusCode::FAILURE; + } + return StatusCode::SUCCESS; +} diff --git a/Calorimeter/CaloTools/src/CaloLumiBCIDTool.cxx b/Calorimeter/CaloTools/src/CaloLumiBCIDTool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..0ec79df58bc7c6cbcd61062dd8bb4fd18eb2ae49 --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloLumiBCIDTool.cxx @@ -0,0 +1,418 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloTools/CaloLumiBCIDTool.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGateSvc.h" +#include "CaloEvent/CaloCell.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloIdentifier/CaloIdManager.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" +//#include "xAODEventInfo/EventID.h" +#include "xAODEventInfo/EventInfo.h" + + +CaloLumiBCIDTool::CaloLumiBCIDTool (const std::string& type, + const std::string& name, + const IInterface* parent) : + AthAlgTool(type, name, parent), + m_larmcsym("LArMCSymTool"), + m_OFCTool("LArOFCTool"), + m_lumiTool("LuminosityTool"), + m_bunchCrossingTool("BunchCrossingTool"), + m_isMC(false), + m_keyShape("LArShape"), m_keyMinBiasAverage("LArPileupAverage"),m_keyOFC("LArOFC"), + m_bcidMax(3564), + m_ncell(0), + m_bcid(0xFFFF) //Larger than m_bcidmax +{ + declareInterface<ICaloLumiBCIDTool>(this); + declareProperty("LArOFCTool",m_OFCTool,"Tool handle for OFC"); + declareProperty("LumiTool",m_lumiTool,"Tool handle for Luminosity"); + declareProperty("BunchCrossingTool",m_bunchCrossingTool,"Tool handle for bunch crossing tool"); + declareProperty("isMC",m_isMC); + declareProperty("keyShape",m_keyShape); + declareProperty("keyMinBiasAverge",m_keyMinBiasAverage); + declareProperty("keyOFC",m_keyOFC); +} + +//----------------------------------------------------------------- + +CaloLumiBCIDTool::~CaloLumiBCIDTool() {} + + +//------------------------------------------------------------------- + +StatusCode CaloLumiBCIDTool::initialize() { + + msg(MSG::INFO) << " initialize " << endreq; + + IIncidentSvc* incSvc; + if (service( "IncidentSvc", incSvc ).isFailure()) { + msg(MSG::ERROR) << "Unable to get the IncidentSvc" << endreq; + return StatusCode::FAILURE; + } + long int priority=100; + incSvc->addListener(this,"BeginEvent",priority); + + + const IGeoModelSvc *geoModel=0; + StatusCode sc = service("GeoModelSvc", geoModel); + if(sc.isFailure()) + { + msg(MSG::ERROR) << "Could not locate GeoModelSvc" << endreq; + return sc; + } + + // dummy parameters for the callback: + int dummyInt=0; + std::list<std::string> dummyList; + + if (geoModel->geoInitialized()) + { + return geoInit(dummyInt,dummyList); + } + else + { + sc = detStore()->regFcn(&IGeoModelSvc::geoInit, + geoModel, + &CaloLumiBCIDTool::geoInit,this); + if(sc.isFailure()) + { + msg(MSG::ERROR) << "Could not register geoInit callback" << endreq; + return sc; + } + } + return sc; + +} + +// ------------------------------------------------------------------------------ + +StatusCode CaloLumiBCIDTool::geoInit(IOVSVC_CALLBACK_ARGS) { + + msg(MSG::INFO) << " geoInit " << endreq; + +// callback for Shape + + StatusCode sc=detStore()->regFcn(&ICaloLumiBCIDTool::LoadCalibration, + dynamic_cast<ICaloLumiBCIDTool*>(this), + m_dd_shape,m_keyShape,true); + if(sc.isSuccess()){ + msg(MSG::INFO) << "Registered callback for key: " + << m_keyShape << endreq; + } else { + msg(MSG::ERROR) << "Cannot register callback function for key " + << m_keyShape << endreq; + return sc; + } + +// callback for MinBiasAverage + + sc=detStore()->regFcn(&ICaloLumiBCIDTool::LoadCalibration, + dynamic_cast<ICaloLumiBCIDTool*>(this), + m_dd_minbiasAverage,m_keyMinBiasAverage,true); + if(sc.isSuccess()){ + msg(MSG::INFO) << "Registered callback for key: " + << m_keyMinBiasAverage << endreq; + } else { + msg(MSG::ERROR) << "Cannot register callback function for key " + << m_keyMinBiasAverage << endreq; + return sc; + } + + sc=m_cablingService.retrieve(); + if (sc.isFailure()){ + msg(MSG::ERROR) << "Unable to get CablingService" << endreq; + return sc; + } + + +// get OFC tool and register callback + + if (m_isMC) { + sc=m_OFCTool.retrieve(); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Unable to retrieve LArOFCTool" << endreq; + return sc; + } else { + msg(MSG::DEBUG) << " -- LArOFCTool retrieved" << endreq; + } + + + sc=detStore()->regFcn(&ILArOFCTool::LoadCalibration,&(*m_OFCTool), + &ICaloLumiBCIDTool::LoadCalibration,dynamic_cast<ICaloLumiBCIDTool*>(this),true); + if (sc.isSuccess()) { + msg(MSG::INFO) << "Registered callbacks for LArOFCTool -> CaloLumiBCIDTool" + << endreq; + } else { + msg(MSG::ERROR) << "Cannot register callbacks for LArOFCTool -> CaloLumiBCIDTool" + << endreq; + return sc; + } + + } else { + sc=detStore()->regFcn(&ICaloLumiBCIDTool::LoadCalibration, + dynamic_cast<ICaloLumiBCIDTool*>(this), + m_dd_ofc,m_keyOFC,true); + if(sc.isSuccess()){ + msg(MSG::INFO) << "Registered callback for key: " + << m_keyOFC << endreq; + } else { + msg(MSG::ERROR) << "Cannot register callback function for key " + << m_keyOFC << endreq; + return sc; + } + + } + +// get LumiTool + if (m_isMC) { + sc=m_bunchCrossingTool.retrieve(); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Unable to retrieve bunch crossing Tool" << endreq; + return sc; + } else { + ATH_MSG_DEBUG(" -- bunch crossing Tool retrieved"); + } + + } else { + sc=m_lumiTool.retrieve(); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Unable to retrieve Lumi Tool" << endreq; + return sc; + } else { + ATH_MSG_DEBUG(" -- Lumi Tool retrieved"); + } + + } + + // + sc = m_larmcsym.retrieve(); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Unable to retrieve LArMCSym tool " << endreq; + return sc; + } + else { + ATH_MSG_DEBUG(" -- LArMCSmy tool retrieved "); + } + + sc = detStore()->retrieve(m_lar_on_id,"LArOnlineID"); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Cannot retrieve LArOnlineID from detector store " << endreq; + return sc; + } + + sc = detStore()->retrieve( m_caloIdMgr ); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Unable to retrieve CaloIdMgr in " << endreq; + return StatusCode::FAILURE; + } + m_calocell_id = m_caloIdMgr->getCaloCell_ID(); + + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------ + +void CaloLumiBCIDTool::getListOfCells() +{ + m_ncell = m_calocell_id->calo_cell_hash_max(); + + m_symCellIndex.resize(m_ncell,-1); + m_hwid_sym.reserve(2000); + m_eshift_sym.reserve(2000); + std::vector<int> m_doneCell; + m_doneCell.resize(m_ncell,-1); + + int nsym=0; + for (int i=0;i<m_ncell;i++) { + IdentifierHash idHash=i; + Identifier id=m_calocell_id->cell_id(idHash); + if (m_calocell_id->is_tile(id)) continue; + // convert cell id to symetric identifier + HWIdentifier hwid2=m_larmcsym->symOnline(id); + Identifier id2 = m_cablingService->cnvToIdentifier(hwid2); + int i2 = (int) (m_calocell_id->calo_cell_hash(id2)); + // we have already processed this hash => just need to associate cell i to the same symetric cell + if (m_doneCell[i2]>=0) { + m_symCellIndex[i]=m_doneCell[i2]; + } + // we have not already processed this hash, add an entry for this new symmetric cell + else { + m_doneCell[i2]=nsym; + m_symCellIndex[i] = nsym; + m_hwid_sym.push_back(hwid2); + m_eshift_sym.push_back(0.); + nsym++; + } + } + + //std::cout << " --- number of symmetric cells found " << nsym << std::endl; + + //for (int i=0;i<m_ncell;i++) { + // IdentifierHash idHash=i; + // Identifier id=m_calocell_id->cell_id(idHash); + // std::cout << " Calo cell " << m_calocell_id->show_to_string(id) << " sym index " << m_symCellIndex[i] << " symmetric hwid " << m_lar_on_id->show_to_string(m_hwid_sym[m_symCellIndex[i]]) << std::endl; + //} + + + + return; +} + +//------------------------------------------------------------------------------------- + +StatusCode CaloLumiBCIDTool::LoadCalibration(IOVSVC_CALLBACK_ARGS_K(keys)) { + + msg(MSG::INFO) << "Callback invoked for " << keys.size() << " keys " << endreq; + + m_cacheValid=false; + return StatusCode::SUCCESS; +} + +//--------------------------------------------------------- + +void CaloLumiBCIDTool::handle(const Incident& inc) { + + if (inc.type()!="BeginEvent") return; + + //std::cout << " in CaloLumiBCIDTool event handle " << std::endl; + m_cacheValid=false; + return; + +} + + +//---------------------------------------------------------------------------------------- + +StatusCode CaloLumiBCIDTool::computeValues(unsigned int bcid) +{ + //std::cout << " in CaloLumiBCIDTool::computeValues() " << m_isMC << std::endl; + + if (m_ncell==0) getListOfCells(); + +// get mu value and convert to luminosity for MC + float xlumiMC=0.; + if (m_isMC) { + const xAOD::EventInfo* eventInfo; + if (! evtStore()->retrieve(eventInfo).isSuccess() ) { + msg(MSG::WARNING) << " Event info not found in event store . Pileup offsets computed for 0 lumi " << endreq; + } + else { + xlumiMC = eventInfo->averageInteractionsPerCrossing()/6.31; // convert from mu/bunch to lumi in 10**30 units per bunch + // 25ns*Nbcid*71mb*10**30 = 25e-9*3564*71e-27*1e30 = 6.31 + //std::cout << " mu and xlumiMC for this bcid " << eventInfo->averageInteractionsPerCrossing() << " " << xlumiMC << std::endl; + } + } + + if (bcid==0) { + const xAOD::EventInfo* eventInfo; + if (! evtStore()->retrieve(eventInfo).isSuccess() ) { + msg(MSG::WARNING) << " Event info not found in event store . Pileup offsets computed for bcid=1 " << endreq; + bcid=1; + } + else { + //const EventID* myEventID=eventInfo->event_ID(); + bcid = eventInfo->bcid(); + } + } + //std::cout << " start loop over cells bcid= " << bcid << std::endl; + //if (!m_isMC) std::cout << " lumi for this bcid " << m_lumiTool->lbLuminosityPerBCID(bcid) << std::endl; + std::vector<HWIdentifier>::iterator it = m_hwid_sym.begin(); + std::vector<HWIdentifier>::iterator it_end = m_hwid_sym.end(); + int index=0; + for(;it!=it_end;++it) { + const HWIdentifier id = *it; + //std::cout << " Identifier " << m_lar_on_id->show_to_string(id) << std::endl; + float eOFC=0.; + if(m_cablingService->isOnlineConnected(id)) { + + // get MinBiasAverage + float MinBiasAverage = m_dd_minbiasAverage->minBiasAverage(id); + //float MinBiasAverage=1.; + + if (MinBiasAverage<0.) MinBiasAverage=0.; + + // get Shape + ILArShape::ShapeRef_t Shape = m_dd_shape->Shape(id,0); + + // get OFC + ILArOFCTool::OFCRef_t OFC; + if (m_isMC) OFC = m_OFCTool->OFC_a(id,0) ; + else OFC = m_dd_ofc->OFC_a(id,0,0); + + unsigned int nsamples = OFC.size(); + + unsigned int nshapes = Shape.size(); + if (nshapes < nsamples) { + msg(MSG::ERROR) << " Not enough samples in Shape " << nshapes << " less than in OFC " << nsamples << endreq; + return StatusCode::FAILURE; + } + + //std::cout << " loop over bcid "; + for (unsigned int i=0;i<nsamples;i++) { + float sumShape=0.; + for (unsigned int j=0;j<nshapes;j++) { + unsigned int k; + if ((bcid+i)<j) k = m_bcidMax+bcid+i-j; + else if ((bcid+i)>=(m_bcidMax+j)) k = i-j+bcid-m_bcidMax; + else k = bcid+i-j; + + float lumi; + if (m_isMC) lumi= m_bunchCrossingTool->bcIntensity(k)*xlumiMC; // convert to luminosity per bunch in 10**30 units + else lumi = m_lumiTool->lbLuminosityPerBCID(k); // luminosity in 10**30 units + //std::cout << "k:lumi " << k << " " << lumi << " "; + + sumShape += Shape[j]*lumi; + } + eOFC += sumShape * (OFC[i] ); + } + //std::cout << std::endl; + eOFC = eOFC * MinBiasAverage; + } // connected cell + else { + //std::cout << " disconnected cell ? " << std::endl; + eOFC=0.; + } + + //std::cout << " index, eOFC " << index << " " << eOFC << std::endl; + m_eshift_sym[index]=eOFC; + index++; + + } // loop over cells + + + m_cacheValid=true; + m_bcid = bcid; + return StatusCode::SUCCESS; +} + +//------------------------------------------------- + +float CaloLumiBCIDTool::average(const CaloCell* caloCell,unsigned int bcid) +{ + return this->average(caloCell->caloDDE(),bcid); + +} + +//------------------------------------------------- + +float CaloLumiBCIDTool::average(const CaloDetDescrElement* caloDDE,unsigned int bcid) +{ + if (bcid != m_bcid && bcid !=0 ) m_cacheValid=false; + if (!m_cacheValid) { + StatusCode sc = this->computeValues(bcid); + if (sc.isFailure()) return 0.; + } + const Identifier CellID = caloDDE->identify(); + + if (m_calocell_id->is_tile(CellID)) return 0.; + + int i2 = (int) (m_calocell_id->calo_cell_hash(CellID)); + if (i2>=m_ncell) return 0.; + unsigned int index = m_symCellIndex[i2]; + if (index>=m_eshift_sym.size()) return 0.; + return m_eshift_sym[index]; +} diff --git a/Calorimeter/CaloTools/src/CaloMBAverageTool.cxx b/Calorimeter/CaloTools/src/CaloMBAverageTool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..f2c6a3938cebc2bc82f5ac3715f0bb46f3e66b9f --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloMBAverageTool.cxx @@ -0,0 +1,257 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloTools/CaloMBAverageTool.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGateSvc.h" +#include "CaloEvent/CaloCell.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloIdentifier/CaloIdManager.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + + +CaloMBAverageTool::CaloMBAverageTool (const std::string& type, + const std::string& name, + const IInterface* parent) : + AthAlgTool(type, name, parent), + m_OFCTool("LArOFCTool"), + m_Nminbias(-1),m_deltaBunch(1),m_keyShape("LArShape"), m_keyfSampl("LArfSampl"), m_keyMinBiasAverage("LArMinBiasAverage") +{ + declareInterface<ICaloMBAverageTool>(this); + declareProperty("NMinBias",m_Nminbias); + declareProperty("deltaBunch",m_deltaBunch); + declareProperty("keyShape",m_keyShape); + declareProperty("keyfSampl",m_keyfSampl); + declareProperty("keyMinBiasAverge",m_keyMinBiasAverage); + declareProperty("LArOFCTool",m_OFCTool,"Tool handle for OFC"); + +} + +//----------------------------------------------------------------- + +CaloMBAverageTool::~CaloMBAverageTool() {} + + +//------------------------------------------------------------------- + +StatusCode CaloMBAverageTool::initialize() { + + MsgStream log( msgSvc(), name() ); + + log << MSG::INFO << " initialize " << endreq; + + m_ncell = 0; + + const IGeoModelSvc *geoModel=0; + StatusCode sc = service("GeoModelSvc", geoModel); + if(sc.isFailure()) + { + log << MSG::ERROR << "Could not locate GeoModelSvc" << endreq; + return sc; + } + + // dummy parameters for the callback: + int dummyInt=0; + std::list<std::string> dummyList; + + if (geoModel->geoInitialized()) + { + return geoInit(dummyInt,dummyList); + } + else + { + sc = detStore()->regFcn(&IGeoModelSvc::geoInit, + geoModel, + &CaloMBAverageTool::geoInit,this); + if(sc.isFailure()) + { + log << MSG::ERROR << "Could not register geoInit callback" << endreq; + return sc; + } + } + return sc; + +} + +// ------------------------------------------------------------------------------ + +StatusCode CaloMBAverageTool::geoInit(IOVSVC_CALLBACK_ARGS) { + + MsgStream log(msgSvc(), name()); + log << MSG::INFO << " geoInit " << endreq; + + StatusCode sc = detStore()->retrieve( m_caloIdMgr ); + if (sc.isFailure()) { + log << MSG::ERROR << "Unable to retrieve CaloIdMgr in " << endreq; + return StatusCode::FAILURE; + } + m_calo_id = m_caloIdMgr->getCaloCell_ID(); + + + + +// callback for Shape + + sc=detStore()->regFcn(&ICaloMBAverageTool::LoadCalibration, + dynamic_cast<ICaloMBAverageTool*>(this), + m_dd_shape,m_keyShape,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyShape << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyShape << endreq; + return sc; + } + +// callback for fSampl + + sc=detStore()->regFcn(&ICaloMBAverageTool::LoadCalibration, + dynamic_cast<ICaloMBAverageTool*>(this), + m_dd_fsampl,m_keyfSampl,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyfSampl << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyfSampl << endreq; + return sc; + } + +// callback for MinBiasAverage + + sc=detStore()->regFcn(&ICaloMBAverageTool::LoadCalibration, + dynamic_cast<ICaloMBAverageTool*>(this), + m_dd_minbiasAverage,m_keyMinBiasAverage,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyMinBiasAverage << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyMinBiasAverage << endreq; + return sc; + } + + + +// get OFC tool and register callback + + sc=m_OFCTool.retrieve(); + if (sc.isFailure()) { + log << MSG::ERROR << "Unable to retrieve LArOFCTool" << endreq; + return sc; + } else { + log << MSG::DEBUG << " -- LArOFCTool retrieved" << endreq; + } + + + sc=detStore()->regFcn(&ILArOFCTool::LoadCalibration,&(*m_OFCTool), + &ICaloMBAverageTool::LoadCalibration,dynamic_cast<ICaloMBAverageTool*>(this),true); + if (sc.isSuccess()) { + log << MSG::INFO + << "Registered callbacks for LArOFCTool -> CaloMBAverageTool" + << endreq; + } else { + log << MSG::ERROR + << "Cannot register callbacks for LArOFCTool -> CaloMBAverageTool" + << endreq; + return sc; + } + + + return StatusCode::SUCCESS; +} + +//------------------------------------------------------------------------------------- + +StatusCode CaloMBAverageTool::LoadCalibration(IOVSVC_CALLBACK_ARGS_K(keys)) +{ + + MsgStream log(msgSvc(), name()); + + log << MSG::INFO << "Callback invoked for " << keys.size() << " keys " << endreq; + + m_ncell = m_calo_id->calo_cell_hash_max(); + m_shift.resize(3*m_ncell,0.); + + for (unsigned int icell=0;icell<m_ncell;icell++) { + IdentifierHash cellHash = icell; + Identifier id = m_calo_id->cell_id(cellHash); + + if (m_calo_id->is_em(cellHash) || m_calo_id->is_hec(cellHash) || m_calo_id->is_fcal(cellHash)) { + + // get MinBiasAverage + float MinBiasAverage = m_dd_minbiasAverage->minBiasAverage(id); + + if (MinBiasAverage<0.) MinBiasAverage=0.; + + // get fSampl + float fSampl = m_dd_fsampl->FSAMPL(id); + + for (int igain=0;igain<3;igain++) { + + // get Shape + ILArShape::ShapeRef_t Shape = m_dd_shape->Shape(id,igain); + + // get OFC + ILArOFCTool::OFCRef_t OFC = m_OFCTool->OFC_a(id, igain, m_Nminbias) ; + + int nsamples = OFC.size(); + + int nshapes = Shape.size(); + if (nshapes < nsamples) { + log << MSG::ERROR << " Not enough samples in Shape " << nshapes << " less than in OFC " << nsamples << endreq; + return StatusCode::FAILURE; + } + + float e = MinBiasAverage/fSampl*m_Nminbias; + + float eOFC=0.; + + for (int i=0;i<nsamples;i++) { + float sumShape = 0.; + for (int j=0;j<nshapes;j++) { + int k=i-j; + if (k%m_deltaBunch == 0 ) sumShape += Shape[j]; + } + float energySample = sumShape*e; + eOFC += energySample * ( OFC[i] ); + } + + + unsigned int index = igain*m_ncell + icell; + m_shift[index] = eOFC; + + } + + + } + + } + + + return StatusCode::SUCCESS; +} + +//------------------------------------------------- + +float CaloMBAverageTool::average(const CaloCell* caloCell) +{ + CaloGain::CaloGain igain = caloCell->gain(); + return this->average(caloCell->caloDDE(),igain); + +} + +//------------------------------------------------- + +float CaloMBAverageTool::average(const CaloDetDescrElement* caloDDE,CaloGain::CaloGain gain) +{ + const IdentifierHash idCaloHash = caloDDE->calo_hash(); + int igain=static_cast<int>(gain); + unsigned int index = igain*m_ncell + ((int)(idCaloHash)); + if (index < m_shift.size()) + return m_shift[index]; + else + return 0.; +} diff --git a/Calorimeter/CaloTools/src/CaloNoiseTool.cxx b/Calorimeter/CaloTools/src/CaloNoiseTool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..e67ba962dbfc6017de80ae874ea56ee8b28a15d0 --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloNoiseTool.cxx @@ -0,0 +1,2256 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloTools/CaloNoiseTool.h" + +#include "CLHEP/Units/SystemOfUnits.h" +#include "TileIdentifier/TileHWID.h" +#include "TileConditions/TileCablingService.h" + +// For Gaudi +#include "GaudiKernel/MsgStream.h" +//#include "GaudiKernel/IService.h" +//#include "GaudiKernel/IToolSvc.h" +//#include "GaudiKernel/ListItem.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "TileIdentifier/TileRawChannelUnit.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" +#include "CLHEP/Random/RandomEngine.h" +#include "CLHEP/Random/RandGauss.h" + +// Exceptions +#include "LArElecCalib/LArConditionsException.h" + +using CLHEP::GeV; +using CLHEP::RandGauss; + +////////////////////////////////////////////////// + +CaloNoiseTool::CaloNoiseTool(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool(type, name, parent), + m_WithOF(true), m_cablingService("LArCablingService"), + m_tileInfoName("TileInfo"), + m_adc2mevTool("LArADC2MeVTool"),m_OFCTool("LArOFCTool"), + m_Nminbias(-1), m_WorkMode(1), + m_UseLAr(true),m_UseTile(true),m_UseSymmetry(true), + m_DumpDatabaseHG(false),m_DumpDatabaseMG(false),m_DumpDatabaseLG(false), + m_isMC(true), + m_keyNoise("LArNoise"), m_keyPedestal("LArPedestal"), m_keyADC2GeV("LArADC2MeV"), + m_keyOFShape("LArOFC_Shape"), m_keyAutoCorr("LArAutoCorr"), + m_keyShape("LArShape"), m_keyfSampl("LArfSampl"), m_keyMinBias("LArMinBias"), + m_DiagnosticHG(true),m_DiagnosticMG(true),m_DiagnosticLG(true), + m_cacheValid(false),m_deltaBunch(1),m_firstSample(0) + +{ + declareInterface<ICaloNoiseTool>(this); + declareInterface<ICalorimeterNoiseTool>(this); + + //switch on Optimal Filtering (applied or not) + declareProperty("WithOF",m_WithOF); + //name of TileInfo + declareProperty("TileInfoName",m_tileInfoName); + declareProperty("LArADC2MeVTool",m_adc2mevTool,"Tool handle for ADC2MeV"); + declareProperty("LArOFCTool",m_OFCTool,"Tool handle for OFC"); + declareProperty("NMinBias",m_Nminbias); + declareProperty("WorkMode",m_WorkMode); + //declareProperty("Geant3",m_Geant3); + declareProperty("UseLAr",m_UseLAr); + declareProperty("UseTile",m_UseTile); + declareProperty("UseSymmetry",m_UseSymmetry); + declareProperty("DumpDatabaseHG",m_DumpDatabaseHG); + declareProperty("DumpDatabaseMG",m_DumpDatabaseMG); + declareProperty("DumpDatabaseLG",m_DumpDatabaseLG); + declareProperty("DiagnosticHG",m_DiagnosticHG); + declareProperty("DiagnosticMG",m_DiagnosticMG); + declareProperty("DiagnosticLG",m_DiagnosticLG); + declareProperty("ReturnNoise",m_ReturnNoiseName="electronicNoise"); + declareProperty("FixGain",m_gain_from_joboption=-1); + declareProperty("IsMC",m_isMC); + declareProperty("keyAutoCorr",m_keyAutoCorr); + declareProperty("keyPedestal",m_keyPedestal); + declareProperty("keyOFC",m_keyOFShape); + declareProperty("keyShape",m_keyShape); + declareProperty("keyfSampl",m_keyfSampl); + declareProperty("keyMinBias",m_keyMinBias); + declareProperty("keyNoise",m_keyNoise); + declareProperty("keyADC2GeV",m_keyADC2GeV); + declareProperty("LoadAtBegin",m_loadAtBegin=true); + declareProperty("deltaBunch",m_deltaBunch); + declareProperty("firstSample",m_firstSample); +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::initialize() +{ + + MsgStream log( msgSvc(), name() ); + + StoreGateSvc* detStore; + if (service("DetectorStore", detStore).isFailure()) { + log << MSG::ERROR << "Unable to access DetectoreStore" << endreq ; + return StatusCode::FAILURE; + } + + const IGeoModelSvc *geoModel=0; + StatusCode sc = service("GeoModelSvc", geoModel); + if(sc.isFailure()) + { + log << MSG::ERROR << "Could not locate GeoModelSvc" << endreq; + return sc; + } + + // dummy parameters for the callback: + int dummyInt=0; + std::list<std::string> dummyList; + + if (geoModel->geoInitialized()) + { + return geoInit(dummyInt,dummyList); + } + else + { + sc = detStore->regFcn(&IGeoModelSvc::geoInit, + geoModel, + &CaloNoiseTool::geoInit,this); + if(sc.isFailure()) + { + log << MSG::ERROR << "Could not register geoInit callback" << endreq; + return sc; + } + } + return sc; +} + +StatusCode +CaloNoiseTool::geoInit(IOVSVC_CALLBACK_ARGS) +{ + MsgStream log( msgSvc(), name() ); + + log << MSG::INFO + << "CaloNoiseTool called " << this->name() << " initialize() begin" + << endreq; + + if ((std::string)this->name()=="ToolSvc.calonoisetool") + log << MSG::WARNING << "calonoisetool is obsolete. Please use CaloNoiseToolDefault.py" <<endreq; + + //diagnostic + m_diagnostic[CaloGain::LARHIGHGAIN] =m_DiagnosticHG; + m_diagnostic[CaloGain::LARMEDIUMGAIN]=m_DiagnosticMG; + m_diagnostic[CaloGain::LARLOWGAIN] =m_DiagnosticLG; + + //dumps + m_DumpDatabase[CaloGain::LARHIGHGAIN] =m_DumpDatabaseHG; + m_DumpDatabase[CaloGain::LARMEDIUMGAIN]=m_DumpDatabaseMG; + m_DumpDatabase[CaloGain::LARLOWGAIN] =m_DumpDatabaseLG; + + m_Nmessages_forTilePileUp=0; + + if (m_cablingService.retrieve().isFailure()) { + log << MSG::ERROR << "Unable to get CablingService " << endreq; + return StatusCode::FAILURE; + } + else log << MSG::DEBUG << "CablingService retrieved" << endreq; + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //retrieves helpers for LArCalorimeter + + m_calo_dd_man = CaloDetDescrManager::instance(); + m_calo_id_man = m_calo_dd_man->getCalo_Mgr(); + + m_lar_em_id = m_calo_id_man->getEM_ID(); + m_lar_hec_id = m_calo_id_man->getHEC_ID(); + m_lar_fcal_id = m_calo_id_man->getFCAL_ID(); + + //FIXME + m_tile_id = m_calo_id_man->getTileID(); + + if (m_tile_id==0) + { + m_UseTile=false; + log << MSG::WARNING + <<" no tile_id -> noise unavailable for Tiles !" + << endreq; + } + + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //retrieves helpers for Calorimeter + m_calocell_id = m_calo_dd_man->getCaloCell_ID(); + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //set calohash maximums + m_LArHashMax =0; + m_TileHashMax=0; + if(m_UseLAr) + m_LArHashMax = m_lar_em_id->channel_hash_max() + + m_lar_hec_id->channel_hash_max() + + m_lar_fcal_id->channel_hash_max(); + if(m_UseTile) + m_TileHashMax = m_tile_id->cell_hash_max(); + m_CaloHashMax = m_LArHashMax + m_TileHashMax; + + //set calohash minimum + if(m_UseLAr) m_CaloHashMin = 0; + if(m_UseTile && m_UseLAr==false) m_CaloHashMin = m_LArHashMax; + + log << MSG::DEBUG + << " UseLAr: " <<m_UseLAr<< " UseTile: " <<m_UseTile + << " => CaloHashMin= " <<m_CaloHashMin + << " CaloHashMax= " <<m_CaloHashMax + << endreq; + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //gain-thresholds + m_LowGainThresh[CaloCell_ID::LAREM] = 3900;//ADC counts in MediumGain + m_HighGainThresh[CaloCell_ID::LAREM] = 1300;//ADC counts in MediumGain + m_LowGainThresh[CaloCell_ID::LARHEC] = 2500;//ADC counts in MediumGain + m_HighGainThresh[CaloCell_ID::LARHEC] = 0;//-> high-gain never used for HEC + if(m_WorkMode==0) + { + m_LowGainThresh[CaloCell_ID::LARFCAL] = 60.*GeV;//MeV + m_HighGainThresh[CaloCell_ID::LARFCAL] = 6.*GeV; //MeV + } + else + { + m_LowGainThresh[CaloCell_ID::LARFCAL] = 2000.;//ADC counts + m_HighGainThresh[CaloCell_ID::LARFCAL] = 1100.;//ADC counts + } + m_LowGainThresh[CaloCell_ID::TILE] = 0.;// unit ? + m_HighGainThresh[CaloCell_ID::TILE] = 0.;// + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + m_highestGain[CaloCell_ID::LAREM] = CaloGain::LARHIGHGAIN; + m_highestGain[CaloCell_ID::LARHEC] = CaloGain::LARMEDIUMGAIN; + m_highestGain[CaloCell_ID::LARFCAL] = CaloGain::LARHIGHGAIN; + m_highestGain[CaloCell_ID::TILE] = CaloGain::TILEHIGHHIGH; + + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //retrieves TileInfo + if(m_UseTile) + { + StatusCode sc = detStore()->retrieve(m_tileInfo, m_tileInfoName); + if (sc.isFailure()) { + log << MSG::WARNING + << "Unable to retrieve TileInfo from DetectorStore" + <<" -> noise unavailable for Tiles !" << endreq; + m_UseTile=false; + } + } + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //retrieve the LAr tools + if(m_WorkMode==1 && m_UseLAr) + { + //---- retrieve the ADC2MeV tool ---------------- + if (m_adc2mevTool.retrieve().isFailure()) { + log << MSG::ERROR << "Unable to retrieve tool 'LArADC2MeVTool'" << endreq; + return StatusCode::FAILURE; + } + else + log << MSG::DEBUG << " --ILArADC2MeVTool retrieved" << endreq; + + if(m_WithOF) { + //---- retrieve the OFC Tool ---------------- + StatusCode sc=m_OFCTool.retrieve(); + //sc = p_toolSvc->retrieveTool("LArOFCTool", algtool2); + if (sc.isFailure()) + log << MSG::ERROR << "Unable to retrieve LArOFCTool" << endreq; + else + log << MSG::DEBUG << " -- LArOFCTool retrieved" << endreq; + } + } + + // Cache, what noise to return + m_CachedGetNoiseCDDE=NULL; + m_CachedGetNoiseCELL=NULL; + if(m_ReturnNoiseName=="electronicNoise") { + log << MSG::INFO << "Will cache electronic noise" << endreq; + m_CachedGetNoiseCDDE=&CaloNoiseTool::elecNoiseRMS; + m_CachedGetNoiseCELL=&CaloNoiseTool::elecNoiseRMS; + } + if(m_ReturnNoiseName=="pileupNoise") { + log << MSG::INFO << "Will cache pileupNoise noise" << endreq; + m_CachedGetNoiseCDDE=&CaloNoiseTool::pileupNoiseRMS; + m_CachedGetNoiseCELL=&CaloNoiseTool::pileupNoiseRMS; + } + if(m_ReturnNoiseName=="totalNoise") { + log << MSG::INFO << "Will cache totalNoise noise" << endreq; + m_CachedGetNoiseCDDE=&CaloNoiseTool::totalNoiseRMS; + m_CachedGetNoiseCELL=&CaloNoiseTool::totalNoiseRMS; + } + if(m_CachedGetNoiseCELL==NULL || + m_CachedGetNoiseCELL==NULL) { + log << MSG::ERROR << "Unknown noise !" << endreq; + return StatusCode::FAILURE; + } + + + // callback functions + if(m_UseLAr) + { + + if(m_isMC){ + StatusCode sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_noise,m_keyNoise,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyNoise << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyNoise << endreq; + } + }else{ + StatusCode sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_pedestal,m_keyPedestal,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyPedestal << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyPedestal << endreq; + } + } + + if(m_WorkMode==0) + { + + StatusCode sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_adc2gev,m_keyADC2GeV,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyADC2GeV << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyADC2GeV << endreq; + } + + sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_detDHOFC,m_keyOFShape,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyOFShape << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyOFShape << endreq; + } + } + + StatusCode sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_acorr,m_keyAutoCorr,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyAutoCorr << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyAutoCorr << endreq; + } + + if(m_WorkMode==1) + { + +// get pulse shape, fSampl and minBiasRMS to compute pileup noise (MC only) + if(m_isMC){ + + StatusCode sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_shape,m_keyShape,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyShape << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyShape << endreq; + } + + sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_fsampl,m_keyfSampl,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyfSampl << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyfSampl << endreq; + } + + sc=detStore()->regFcn(&ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this), + m_dd_minbias,m_keyMinBias,true); + if(sc.isSuccess()){ + log << MSG::INFO << "Registered callback for key: " + << m_keyMinBias << endreq; + } else { + log << MSG::ERROR << "Cannot register callback function for key " + << m_keyMinBias << endreq; + } + } + + + if (StatusCode::SUCCESS== + detStore()->regFcn(&ILArADC2MeVTool::LoadCalibration,&(*m_adc2mevTool), + &ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this),true) ) { + log << MSG::INFO + << "Registered callbacks for LArADC2MeVTool -> CaloNoiseTool" + << endreq; + } else { + log << MSG::ERROR + << "Cannot register callbacks for LArADC2MeVTool -> CaloNoiseTool" + << endreq; + } + + if(m_WithOF){ + if (StatusCode::SUCCESS== + detStore()->regFcn(&ILArOFCTool::LoadCalibration,&(*m_OFCTool), + &ICaloNoiseTool::LoadCalibration, + dynamic_cast<ICaloNoiseTool*>(this),true) ) { + log << MSG::INFO + << "Registered callbacks for LArOFCTool -> CaloNoiseTool" + << endreq; + } else { + log << MSG::ERROR + << "Cannot register callbacks for LArOFCTool -> CaloNoiseTool" + << endreq; + } + } + + } + + }//UseLAr + + if(m_UseTile) + { + //currently no database for Tile + } + + CNoise = 0.456E-3; + AdcPerMev = 5.*GeV; + + + + if (m_loadAtBegin) { + log << MSG::DEBUG << "Setting callback function to load calibration at begin of run" << endreq; + // Incident Service: + IIncidentSvc* incSvc; + StatusCode sc = service("IncidentSvc", incSvc); + if (sc.isFailure()) { + log << MSG::ERROR << "Unable to retrieve pointer to IncidentSvc " + << endreq; + return sc; + } + + //start listening to "BeginRun". The incident should be fired AFTER the IOV callbacks and only once. + const long priority=std::numeric_limits<long>::min(); //Very low priority + incSvc->addListener(this, "BeginRun", priority ,false,true); //single-shot incident + } + + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + log << MSG::INFO << "CaloNoiseTool initialize() end" << endreq; + + return StatusCode::SUCCESS; +} + + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::initContainers() +{ + //initialize the maps m_ElecNoiseContainer and m_ScaleContainer + //(assuming type of elements of the containers is the same for Tile and LAr) + + MsgStream log( msgSvc(), name() ); + log << MSG::INFO << "initContainers() begin " << endreq; + + // intialise indices + this->initIndex(); + + //:::::::::::::::::::::::::::::::::::::: + m_elecNoiseRAWContainer.resize(m_idSymmCaloHashContainer.size()); + m_elecNoiseCELLContainer.resize(m_idSymmCaloHashContainer.size()); + if(m_WorkMode==1) + m_pileupNoiseContainer.resize(m_idSymmCaloHashContainer.size()); + m_adc2mevContainer.resize(m_idSymmCaloHashContainer.size()); + //:::::::::::::::::::::::::::::::::::::: + log << MSG::INFO << "initContainers() end : " + <<" size of containers = " + <<m_idSymmCaloHashContainer.size() + << endreq; + return StatusCode::SUCCESS; +} + +////////////////////////////////////////////////// + +void +CaloNoiseTool::initIndex() + +{ + //:::::::::::::::::::::::::::::::::::::: + m_indexContainer.clear(); + m_indexContainer.resize(m_CaloHashMax, + static_cast<unsigned int> (-1)); + + //maybe the other container sould be reset + m_idSymmCaloHashContainer.clear(); + m_idSymmCaloHashContainer.reserve(5000); + + + + for (unsigned int intIdCaloHash=m_CaloHashMin; intIdCaloHash<m_CaloHashMax; + ++intIdCaloHash) + { + + + IdentifierHash idCaloHash=static_cast<IdentifierHash>(intIdCaloHash); + + // std::cout << "DRDEBUG in initIndex loop " << intIdCaloHash << std::endl ; + + + // initialize the vector of indexes (big vector without symmetry) + + + + + // o idCaloHash -> id -> idSymm (symmetry phi->0 and z->|z|) + // o idSymm -> idSymmCaloHash + // o idSymmCaloHash stored in m_idSymmCaloHashContainer + // o an index is associated to an idSymmCaloHash + // o index stored in m_indexContainer + + CaloCell_ID::SUBCALO iCalo = this->caloNum(idCaloHash); + Identifier id = m_calocell_id->cell_id(idCaloHash); + Identifier regId; + Identifier idSymm; + IdentifierHash idSymmCaloHash; + + if(m_UseSymmetry) + { + if(iCalo==CaloCell_ID::LAREM) + { + int barrel_ec = m_lar_em_id->barrel_ec(id); + int sampling = m_lar_em_id->sampling(id); + int region = m_lar_em_id->region(id); + int eta = m_lar_em_id->eta(id); + regId = m_lar_em_id->region_id(abs(barrel_ec),sampling,region); + idSymm = m_lar_em_id->channel_id(regId, + eta, + m_calocell_id->phi_min(regId)); + idSymmCaloHash= m_calocell_id->calo_cell_hash(idSymm); + } + else if(iCalo==CaloCell_ID::LARHEC) + { + int pos_neg = m_lar_hec_id->pos_neg(id); + int sampling = m_lar_hec_id->sampling(id); + int region = m_lar_hec_id->region(id); + int eta = m_lar_hec_id->eta(id); + regId = m_lar_hec_id->region_id(abs(pos_neg),sampling,region); + idSymm = m_lar_hec_id->channel_id(regId, + eta, + m_calocell_id->phi_min(regId)); + idSymmCaloHash= m_calocell_id->calo_cell_hash(idSymm); + } + else if(iCalo==CaloCell_ID::LARFCAL) + { + int pos_neg = m_lar_fcal_id->pos_neg(id); + int module = m_lar_fcal_id->module(id); + int eta = m_lar_fcal_id->eta(id); + int phi = m_lar_fcal_id->phi(id); + if(phi>7) phi = phi-8; //as in LArMCSymTool + regId = m_lar_fcal_id->module_id(abs(pos_neg),module); + idSymm = m_lar_fcal_id->channel_id(regId, + eta, + phi); + idSymmCaloHash= m_calocell_id->calo_cell_hash(idSymm); + } + else if(iCalo==CaloCell_ID::TILE) + { + idSymm = id; + idSymmCaloHash = m_calocell_id->calo_cell_hash(idSymm); + } + else + { + MsgStream log( msgSvc(), name() ); + log << MSG::WARNING + <<"CaloNoiseTool::chooseIndex wrong id ! " + << m_lar_em_id->show_to_string(id) << endreq ; + continue ; + } + + assert (idSymmCaloHash < m_CaloHashMax); + if (m_indexContainer[idSymmCaloHash] != static_cast<unsigned int>(-1)) { + m_indexContainer[idCaloHash] = m_indexContainer[idSymmCaloHash]; + continue; + } + } + else idSymmCaloHash=idCaloHash;// no symmetry + + + if(iCalo!=CaloCell_ID::TILE) { + if(this->checkIfConnected(id)==false) { + std::cout << "DRDEBUG ... NOT connected " << std::endl ; + continue; + } + // else { std::cout << "DRDEBUG ... connected " << std::endl ;} + } + + // std::cout << "DRDEBUG ... check connected OK " << intIdCaloHash << std::endl ; + + /* cabling eta= 0 -> 0.8 (for private debug) + int samp = m_lar_em_id->sampling(id); + int region= m_lar_em_id->region(id); + int eta = m_lar_em_id->eta(id); + int phi = m_lar_em_id->phi(id); + if(samp==1 && eta>=256) return; + if(samp==1 && eta==0) return; + if(samp==2 && eta>=32) return; + if(samp==3 && eta>=16) return; + if(region>0) return; + */ + + // std::cout << "DRDEBUG ... register under " << m_new_index << std::endl ; + + //we come here if idSymmHash is not yet indexed (and is connected) + m_indexContainer[idCaloHash] = + m_indexContainer[idSymmCaloHash] = + m_idSymmCaloHashContainer.size(); + + m_idSymmCaloHashContainer.push_back(idSymmCaloHash); + }// loop on all cells +} + +////////////////////////////////////////////////// + +bool +CaloNoiseTool::checkIfConnected(const Identifier &id) +{ + try + { + HWIdentifier hwid = m_cablingService->createSignalChannelID(id); + if(!m_cablingService->isOnlineConnected(hwid)) + { + //std::cout<<m_lar_em_id->show_to_string(id) + // <<" not connected !!"<<std::endl; + return false; + } + } + catch(LArID_Exception & except) + {return false;} + //std::cout<<m_lar_em_id->show_to_string(id) + // <<" connected !!"<<std::endl; + return true; +} + +////////////////////////////////////////////////// + +int +CaloNoiseTool::index(const IdentifierHash &idCaloHash) +{ + return m_indexContainer[idCaloHash]; +} + +////////////////////////////////////////////////// + +StatusCode CaloNoiseTool::LoadCalibration(IOVSVC_CALLBACK_ARGS_K(keys)) +{ + + MsgStream log(msgSvc(), name()); + + log << MSG::INFO << "Callback invoked for " << keys.size() << " keys " << endreq; + + // invalidates the cache + m_cacheValid = false; + + return StatusCode::SUCCESS; +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::initData() +{ + MsgStream log( msgSvc(), name() ); + + StatusCode sc ; + sc = this->initContainers(); + if (sc.isFailure()) { + log << MSG::WARNING + << "initContainers failed" << endreq ; + return sc; + } + + // reset diagnostics + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + { + m_nCellsWithProblem[igain]=0; + for(int i=0;i<5000;++i) m_nReason[i][igain]=0; + for(int i=0;i<10;++i) m_itReason[i][igain]=0; + } + + + if(m_UseLAr) + { + //stores the Adc2MeV factors + sc = this->initAdc2MeV(); + if (!sc.isSuccess()) + log << MSG::ERROR << "initData(): error with initAdc2MeV() " << endreq; + } + + //calculates and stores the electronic noise + sc = this->initElecNoise(); + if (!sc.isSuccess()) + log << MSG::ERROR << "initData(): error with initElecNoise() " << endreq; + + //calculates and stores the pileup noise + if(m_WorkMode==1) { + sc = this->initPileUpNoise(); + if (!sc.isSuccess()) + log << MSG::ERROR << "initData(): error with initPileUpNoise() "<<endreq; + } + + + m_cacheValid=true; + return StatusCode::SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::initAdc2MeV() +{ + MsgStream log( msgSvc(), name() ); + log << MSG::INFO << "initAdc2MeV() begin " << endreq; + for (unsigned int it=0; it<m_adc2mevContainer.size(); ++it) + { + CaloCell_ID::SUBCALO iCalo = this->caloNum(m_idSymmCaloHashContainer[it]); + Identifier id=m_calocell_id->cell_id(m_idSymmCaloHashContainer[it]); + //:::::::::::::::::::::::::::::::::::::: + if(m_WorkMode==0) + { + if(iCalo==CaloCell_ID::LAREM || iCalo==CaloCell_ID::LARHEC) + { //only for EM and HEC + m_adc2mevContainer[it]=m_dd_adc2gev->AllFactors(id); + for(unsigned int i=0;i<(m_adc2mevContainer[it]).size();++i) + (m_adc2mevContainer[it])[i] *= GeV; + } + } + //:::::::::::::::::::::::::::::::::::::: + else if(m_WorkMode==1) + { + if(iCalo!=CaloCell_ID::TILE) + { + std::vector<float>& adc2mevVector = m_adc2mevContainer[it]; + adc2mevVector.reserve (CaloGain::LARNGAIN); + for(unsigned int igain=0;igain<CaloGain::LARNGAIN;++igain) + { + const std::vector<float> * + polynom_adc2mev = &(m_adc2mevTool->ADC2MEV(id,igain)); + if(polynom_adc2mev->size()==0) + adc2mevVector.push_back(0.); + else + adc2mevVector.push_back((*polynom_adc2mev)[1]); + } + } + } + //:::::::::::::::::::::::::::::::::::::: + } + log << MSG::INFO << "initAdc2MeV() end " << endreq; + return StatusCode::SUCCESS; +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::initElecNoise() +{ + // initialize the parameters (the same for each event for each Identifier) + // for the calculation of the electronic noise + + + MsgStream log( msgSvc(), name() ); + log << MSG::DEBUG << "initElecNoise() begin " << endreq; + + for (unsigned int it=0; it<m_elecNoiseRAWContainer.size(); ++it) + { + CaloCell_ID::SUBCALO iCalo = this->caloNum(m_idSymmCaloHashContainer[it]); + //:::::::::::::::::::::::::::::::::::::: + if(iCalo==CaloCell_ID::TILE) + m_elecNoiseRAWContainer[it] = + this->calculateElecNoiseForTILE(m_idSymmCaloHashContainer[it]); + //:::::::::::::::::::::::::::::::::::::: + else + m_elecNoiseRAWContainer[it] = + this->calculateElecNoiseForLAR(m_idSymmCaloHashContainer[it],iCalo, + m_Nminbias); + //:::::::::::::::::::::::::::::::::::::: + m_elecNoiseCELLContainer[it] = m_elecNoiseRAWContainer[it]; + } + + //print diagnostic + if(m_UseLAr) + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + if(m_diagnostic[igain]) + { + log<<MSG::INFO<<endreq; + log<<MSG::INFO<<"===== Diagnostic for gain "<<igain<<" ====="<<endreq; + log<<MSG::INFO<<endreq; + for(int i=0;i<m_nCellsWithProblem[igain];++i) + { + Identifier id = m_calocell_id->cell_id(m_idHash[i][igain]); + log<<MSG::DEBUG<<m_idHash[i][igain]<<" " + <<m_lar_em_id->show_to_string(id) + <<" "<<m_nReason[i][igain]<<" : "; + for(int j=0;j<m_nReason[i][igain];++j) + log<<MSG::DEBUG<<m_reasonName[m_reason[i][j][igain]]<<" "; + log << MSG::DEBUG<<endreq; + } + log<<MSG::DEBUG<<endreq; + log<<MSG::INFO<<"N cells with problem(s) = " + <<m_nCellsWithProblem[igain]<<endreq; + for(int i=0;i<10;++i) + if(m_itReason[i][igain]>0) + log<<MSG::INFO<<i<<" "<<m_reasonName[i] + <<": for "<<m_itReason[i][igain]<<" cells"<<endreq; + } + + log << MSG::DEBUG << "initElecNoise() end " << endreq; + return StatusCode::SUCCESS; +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::initPileUpNoise() +{ + // initialize the parameters (the same for each event for each Identifier) + // for the calculation of the PileUp noise + + MsgStream log( msgSvc(), name() ); + log << MSG::DEBUG << "initPileUpNoise() begin " << endreq; + log << MSG::INFO << "N events of Minimum Bias per bunch crossing = " + << m_Nminbias<< endreq; + //:::::::::::::::::::::::::::::::::::::: + for (unsigned int it=0; it<m_pileupNoiseContainer.size(); ++it) + m_pileupNoiseContainer[it] + =this->calculatePileUpNoise(m_idSymmCaloHashContainer[it],m_Nminbias); + //:::::::::::::::::::::::::::::::::::::: + m_Nminbias_usedForCache=m_Nminbias; + log << MSG::DEBUG << "initPileUpNoise() end " << endreq; + return StatusCode::SUCCESS; +} + +////////////////////////////////////////////////// + +std::vector<float> +CaloNoiseTool::calculateElecNoiseForLAR(const IdentifierHash & idCaloHash, + const CaloCell_ID::SUBCALO iCalo, + const float &Nminbias) +{ + /* + +E=SUMi { OFCi * (short[ (PulseShapei*Ehit/Adc2MeV(gain) + Noisei(gain) + + pedestal) ] + - pedestal) * Adc2Mev(gain) ] } + with Noisei =SUMj { cij*Rndm } * SigmaNoise + + NB: without short and with cij=identity (no autocorrelation) + E=SUMi { NOISEi(gain)*Rndm } + with NOISEi(gain) = Adc2MeV(gain) * OFCi * SigmaNoise(gain) + + => Sigma^2=SUMi{NOISEi(gain)*NOISEj(gain)*cij} + quantification part + = NOISE(gain) + REST + Sigma = sqrt( NOISE(gain) + REST) + + +========= for FCAL on WorkMode=0 (NOVA DB) ==================== + +E=SUMi { OFCi * (short[ ( (PulseShapei*Ehit+Noisei)*gain + CNoisei ) + * AdcPerGev + pedestal] + - pedestal) } / gain + with Noisei =SUMj { cij*Rndm } * SigmaNoise + CNoisei=SUMj { cij*Rndm } * CNoise + + NB: without short and with cij=identity (no autocorrelation) + E=SUMi { Ai*Rndm + Bi*Rndm } + with Ai=(AdcPerGev) *OFCi*SigmaNoise + Bi=(AdcPerGev/gain)*OFCi*CNoise + + => Sigma^2=SUMi{Ai*Aj*cij + Bi*Bj*cij } + quantification part + = A + ( B + C) / gain^2 + +*/ + + std::vector<float> sigmaVector (CaloGain::LARNGAIN,BADVALUE); + float sigma; + + Identifier id = m_calocell_id->cell_id(idCaloHash); + + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + { + m_noiseOK=true; + //:::::::::::::::::::::::::::::::::::::::::::::::::: + //==== retrieve the database ==== + //:::::::::::::::::::::::::::::::::::::::::::::::::: + + for(int i=0;i<nDATABASE;++i) m_retrieve[i]=false; + m_retrieve[iADC2MEV]=true; + m_retrieve[iSIGMANOISE]=true; + m_retrieve[iAUTOCORR]=true; + if(m_WithOF) m_retrieve[iOFC]=true; + //m_retrieve[iSHAPE]=true; + StatusCode sc=this->retrieveCellDatabase(idCaloHash,id,igain,Nminbias, + "calculateElecNoiseForLAR"); + //if(sc.isFailure()) continue; + //NOTE: if an element of the database is empty, + // leave the iteration (on gains) => value will be BADVALUE + //the interfaces take care of that ! + + //:::::::::::::::::::::::::::::::::::::::::::::::::: + //==== calculations ==== + //:::::::::::::::::::::::::::::::::::::::::::::::::: + + if(sc.isFailure()) { + sigma=float(BADVALUE_TO_RETURN); + } + else + { + float OFC_AC_OFC,OFC_OFC; + this->commonCalculations(OFC_AC_OFC,OFC_OFC,1); + //:::::::::::::::::::::::::::::::::::::: + if(iCalo==CaloCell_ID::LARFCAL && m_WorkMode==0) + { + float A=OFC_AC_OFC*SigmaNoise*SigmaNoise*AdcPerMev*AdcPerMev; + // A is the part with SigmaNoise + float B=OFC_AC_OFC*CNoise*CNoise*AdcPerMev*AdcPerMev; + // B is the part with the constant noise (CNoise) + float C=OFC_OFC/(12.); + // C is the quantification part (effect of the truncation short(..) ) + // 12.=sqrt(12)*sqrt(12) + float gain[3]={1.,10.,100.}; + sigma=A + (B+C)/(gain[igain]*gain[igain]) ; + } + else// USUAL CASE + { + float NOISE= OFC_AC_OFC*SigmaNoise*SigmaNoise ; + float REST = OFC_OFC/12.;// 12.=sqrt(12)*sqrt(12) + sigma=(NOISE+REST) * Adc2MeVFactor*Adc2MeVFactor; + } + //:::::::::::::::::::::::::::::::::::::: + if(sigma>0) sigma=sqrt(sigma); + else + { + sigma=-sqrt(-sigma); + //::::::::::::::::: + // MsgStream log(msgSvc(), name()); + // if(igain==0) log << MSG::ERROR + // <<m_lar_em_id->show_to_string(id)<<" gain "<<igain + // <<" : negative root square => WRONG noise " + // <<"(please check if OFC or AutoCorr are correct for this cell)" + // <<endreq; + } + + //diagnostic + if(m_diagnostic[igain]) + { + if(m_noiseOK && sigma<0) + this->updateDiagnostic(9,"sigma<0",igain); + if(m_noiseOK==false) + { + m_idHash[m_nCellsWithProblem[igain]][igain]=idCaloHash; + ++m_nCellsWithProblem[igain]; + m_nReason[m_nCellsWithProblem[igain]][igain]=0; + } + } + //:::::::::::::::::::::::::::::::::::::: + if(m_noiseOK==false || sigma<0) sigma=float(BADVALUE_TO_RETURN); + } + sigmaVector[igain]=sigma; + + }//loop on gains + + return sigmaVector; +} + +////////////////////////////////////////////////// + +std::vector<float> +CaloNoiseTool::calculateElecNoiseForTILE(const IdentifierHash & idCaloHash) +{ + std::vector<float> sigmaVector (CaloGain::LARNGAIN,BADVALUE); + + Identifier id = m_calocell_id->cell_id(idCaloHash); + //std::cout<<"TILE elecnoise " <<m_lar_em_id->show_to_string(id); + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + { + CaloGain::CaloGain gain = static_cast<CaloGain::CaloGain>(igain); + float sigma = m_tileInfo->CellNoiseSigma(id,gain); + //the LAr gain is internally (in CellNoiseSigma) converted into Tile gain + sigmaVector[igain]= sigma; + //:::::::::::::::::::::::::::::::::::::: + //std::cout<<" "<<sigma; + } + //std::cout<<" "<<std::endl; + + return sigmaVector; +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::calculatePileUpNoise(const IdentifierHash & idCaloHash, + const float &Nminbias) +{ + if(Nminbias<=0.000001) return 0.; + //only on WorkMode==1 + if(this->caloNum(idCaloHash)==CaloCell_ID::TILE) return 0.; + //no pile-up for tiles, for the moment ... + + /* + SigmaPileUp^2 = ( SigmaE * sqrt(Nmb) )^2 * Ipileup/Tc + where: + - Ipileup = Tc * SUM(k=1->Nb) g(tk)^2 + - Tc is the time between bunch crossings + - Nb is the number of bunch crossings + (over which the response function is non-zero) + - g is the shape + - SigmaE is the RMS of the energy in 1 minimum bias event + - Nmb is the number of minimum bias events (depending on the luminosity) + */ + + Identifier id = m_calocell_id->cell_id(idCaloHash); + + //:::::::::::::::::::::::::::::::::::::: + + for(int i=0;i<nDATABASE;++i) m_retrieve[i]=false; + m_retrieve[iAUTOCORR]=true; + if(m_WithOF) m_retrieve[iOFC]=true; + m_retrieve[iSHAPE]=true; + m_retrieve[iMINBIASRMS]=true; + m_retrieve[iFSAMPL]=true; + StatusCode sc=this->retrieveCellDatabase(idCaloHash,id, + CaloGain::LARHIGHGAIN,Nminbias, + "calculatePileUpNoise"); + if(sc.isFailure()) return 0.; + + //:::::::::::::::::::::::::::::::::::::: + + //in the database, RMS is at the scale of the Hits, + // so we need to scale it at the e.m scale using the sampling fraction ... + MinBiasRMS /= fSampl; + + //:::::::::::::::::::::::::::::::::::::: + +// overall normalization factor + float PileUp=MinBiasRMS*sqrt(Nminbias); + + //:::::::::::::::::::::::::::::::::::::: + + float OFC_AC_OFC,OFC_OFC; + unsigned int firstSample=m_firstSample; + // for HEC, always use firstSample=1 when the number of samples is 4 + if (m_lar_hec_id->is_lar_hec(id) && m_nsamples==4 && m_firstSample==0) firstSample=1; + this->commonCalculations(OFC_AC_OFC,OFC_OFC,2,firstSample); + + //:::::::::::::::::::::::::::::::::::::: + + PileUp*=sqrt(OFC_AC_OFC); + + //std::cout<<"PILEUP "<<m_lar_em_id->show_to_string(id)<<" " + // <<MinBiasRMS<<" "<<OFC_AC_OFC<<" "<<PileUp<<std::endl; + + return PileUp; +} + +////////////////////////////////////////////////// + +void +CaloNoiseTool::commonCalculations(float & OFC_AC_OFC,float & OFC_OFC,int icase, unsigned int firstSample) +{ + + // case 1 electronic noise + if (icase==1) { + //calculate the matrix of autocorrelation + for(int i=0;i<m_nsamples;++i) + for(int j=0;j<m_nsamples;++j) + { + if(i==j) c[i][j] = 1.; + for(int k=1;k<m_nsamples;++k) + if(i==j-k || i==j+k) + c[i][j] = AutoCorr[k-1]; + } + } +// other case: pileup noise + else { + for (int i=0;i<m_nsamples;i++) { + for (int j=0;j<m_nsamples;j++) + { + c[i][j]=0.; + int nsize = Shape.size(); + for (int k=0;k<nsize;k++) { + if ((j-i+k)>=0 && (j-i+k)<nsize) { + int ibunch=0; + if ((i+firstSample-k)%m_deltaBunch == 0 ) ibunch=1; + c[i][j] += ((double) (ibunch)) * (Shape[k]) * (Shape[j-i+k]); + } + } + } + } + } + + //:::::::::::::::::::::::::::::::::::::: + OFC_AC_OFC=0; + OFC_OFC=0; + + if(m_WithOF) + { + float tmp; + for(int i=0;i<m_nsamples;++i) + { + tmp=0.; + for(int j=0;j<m_nsamples;++j) + tmp+=c[i][j]*OFC[j]; + tmp*=OFC[i]; + OFC_AC_OFC+=tmp; + OFC_OFC+= OFC[i] * OFC[i]; + //std::cout<<" "<<i<<" "<<OFC_AC_OFC<<" "<<OFC_OFC<<std::endl; + } + } + else //equivalent to have only the third sample (peak) + { + // <=> (*OFC)[2]==1, others are null + OFC_AC_OFC=c[2][2]; + OFC_OFC=1; + } + //:::::::::::::::::::::::::::::::::::::: +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::retrieveCellDatabase(const IdentifierHash & idCaloHash, + const Identifier & id, + int igain, + const float &Nminbias, + std::string function_name) +{ + bool PRINT=false; + if(m_DumpDatabase[igain]) PRINT=true; + + if(PRINT) std::cout<<"============ "<<m_lar_em_id->show_to_string(id) + <<" hash="<<idCaloHash + <<" gain="<<igain + <<" (HG="<<CaloGain::LARHIGHGAIN + << ",MG="<<CaloGain::LARMEDIUMGAIN + << ",LG="<<CaloGain::LARLOWGAIN<<")"<<std::endl; + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //ADC2MEV + if(m_retrieve[iADC2MEV]) + { + if(m_WorkMode==0) + { + const std::vector<float>& vAdc2MeVFactor = m_dd_adc2gev->AllFactors(id); + Adc2MeVFactor = vAdc2MeVFactor[igain]*GeV; + } + else + { + int index=this->index(idCaloHash); + Adc2MeVFactor = (m_adc2mevContainer[index])[igain]; + } + if(PRINT) std::cout<<"Adc2MeVFactor="<<Adc2MeVFactor<<std::endl; + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //SIGMANOISE + if(m_retrieve[iSIGMANOISE]) + { + if(m_isMC) + SigmaNoise = m_dd_noise->noise(id,igain); + else + { + RMSpedestal = m_dd_pedestal->pedestalRMS(id,igain); + if(RMSpedestal>(1.0+LArElecCalib::ERRORCODE)) + SigmaNoise = RMSpedestal; + else + { + // MsgStream log(msgSvc(), name()); + // log << MSG::WARNING << function_name + // <<" PedestalRMS vector empty for " + // <<m_lar_em_id->show_to_string(id)<<" at gain "<<igain<<endreq; + SigmaNoise = 0.; + } + } + if(PRINT) std::cout<<"SigmaNoise(inADC)="<<SigmaNoise<<std::endl; + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //AUTOCORR + if(m_retrieve[iAUTOCORR]) + { + AutoCorr = m_dd_acorr->autoCorr(id,igain); + ////////// + if(PRINT) { + std::cout<<"AutoCorr= "; + for(unsigned int i=0;i<AutoCorr.size();++i) + std::cout<<AutoCorr[i]<<" "; + std::cout<<std::endl; + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //OFC + if(m_retrieve[iOFC]) + { + if(m_WorkMode==0) OFC = m_detDHOFC->OFC_a(id, igain, 0) ; + else OFC = m_OFCTool->OFC_a(id, igain) ; + ///////// + if(PRINT) { + std::cout<<"OFC= "; + for(unsigned int i=0;i<OFC.size();++i) + std::cout<<OFC[i]<<" "; + std::cout<<" Nminbias="<<Nminbias<<std::endl; + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //SHAPE + if(m_retrieve[iSHAPE]) + { + Shape = m_dd_shape->Shape(id,0); + ////////// + if(PRINT) { + std::cout<<"Shape= "; + for(unsigned int i=0;i<Shape.size();++i) + std::cout<<Shape[i]<<" "; + std::cout<<std::endl; + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //MinimumBias RMS + if(m_retrieve[iMINBIASRMS]) + { + MinBiasRMS = m_dd_minbias->minBiasRMS(id); + if(PRINT) std::cout<<"MinBiasRMS="<<MinBiasRMS<<std::endl; + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //SAMPLING FRACTION + if(m_retrieve[iFSAMPL]) + { + fSampl = m_dd_fsampl->FSAMPL(id); + if(PRINT) std::cout<<"fSampl="<<fSampl<<std::endl; + } + + return this->checkCellDatabase(id,igain,function_name); +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseTool::checkCellDatabase(const Identifier & id, int igain, + std::string function_name) +{ + StatusCode StatusDatabase=StatusCode::SUCCESS; + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //ADC2MEV + if(m_retrieve[iADC2MEV]) { + if(fabs(Adc2MeVFactor)<0.000001) { + StatusDatabase=StatusCode::FAILURE; + if(m_diagnostic[igain]) + this->updateDiagnostic(0,"Adc2MeVFactor=0",igain); + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //SIGMANOISE + if(m_retrieve[iSIGMANOISE]) { + if(fabs(SigmaNoise)<0.000001) { + StatusDatabase=StatusCode::FAILURE; + if(m_diagnostic[igain]) + this->updateDiagnostic(1,"SigmaNoise=0",igain); + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //AUTOCORR + if(m_retrieve[iAUTOCORR]) + { + if (!AutoCorr.valid()) + { + MsgStream log(msgSvc(), name()); + log << MSG::WARNING << function_name + <<" AutoCorr invalid for " + <<m_lar_em_id->show_to_string(id)<<" at gain "<<igain<<endreq; + StatusDatabase=StatusCode::FAILURE; + } + if (AutoCorr.size()==0) + { + // MsgStream log(msgSvc(), name()); + // log << MSG::WARNING << function_name + // <<" AutoCorr vector empty for " + // <<m_lar_em_id->show_to_string(id)<<" at gain "<<igain<<endreq; + StatusDatabase=StatusCode::FAILURE; + if(m_diagnostic[igain]) this->updateDiagnostic(2,"AC empty",igain); + } + /* // autocorr can be null (and it is for low-gain !), so allow it ! + else + if(m_diagnostic[igain]) + { + unsigned int n_ACnull=0; + for(unsigned int i=0;i<(*AutoCorr).size();++i) + if(fabs((*AutoCorr)[i])<0.000001) ++n_ACnull; + if(n_ACnull==(*AutoCorr).size()) + this->updateDiagnostic(3,"AC=0",igain); + } + */ + m_nsamples=AutoCorr.size()+1; + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //OFC + if(m_retrieve[iOFC]) + { + if (!OFC.valid()) + { + MsgStream log(msgSvc(), name()); + log<<MSG::WARNING<< function_name + <<" OFC pointer null for " + <<m_lar_em_id->show_to_string(id)<<" at gain "<<igain<<endreq; + StatusDatabase=StatusCode::FAILURE; + } + if (OFC.size()==0) + { + // MsgStream log(msgSvc(), name()); + // log<<MSG::WARNING<< function_name + // <<" OFC vector empty for " + // <<m_lar_em_id->show_to_string(id)<<" at gain "<<igain<<endreq; + StatusDatabase=StatusCode::FAILURE; + if(m_diagnostic[igain]) this->updateDiagnostic(4,"OFC empty",igain); + } + else + if(m_diagnostic[igain]) + { + unsigned int n_OFCnull=0; + for(unsigned int i=0;i<OFC.size();++i) + if(fabs(OFC[i])<0.000001) ++n_OFCnull; + if(n_OFCnull==OFC.size()) this->updateDiagnostic(5,"OFC=0",igain); + } + m_nsamples=OFC.size(); + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //SHAPE + if(m_retrieve[iSHAPE]) + { + if (!Shape.valid()) + { + MsgStream log(msgSvc(), name()); + log<<MSG::WARNING<< function_name + <<" Shape pointer null -> PileUp will be 0 for " + <<m_lar_em_id->show_to_string(id)<<endreq; + StatusDatabase=StatusCode::FAILURE; + } + if (Shape.size()==0) + { + // MsgStream log(msgSvc(), name()); + // log<<MSG::WARNING<< function_name + // <<" Shape vector empty -> PileUp will be 0 for " + // <<m_lar_em_id->show_to_string(id)<<endreq; + StatusDatabase=StatusCode::FAILURE; + if(m_diagnostic[igain]) this->updateDiagnostic(6,"Shape empty",igain); + } + else + if(m_diagnostic[igain]) + { + unsigned int n_SHAPEnull=0; + for(unsigned int i=0;i<Shape.size();++i) + if(fabs(Shape[i])<0.000001) ++n_SHAPEnull; + if(n_SHAPEnull==Shape.size()) + this->updateDiagnostic(7,"Shape=0",igain); + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //NSAMPLES + if(m_retrieve[iOFC] && m_retrieve[iAUTOCORR] + && OFC.size()!=AutoCorr.size()+1) + { + m_nsamples=std::min(OFC.size(),AutoCorr.size()+1); + MsgStream log( msgSvc(), name() ); + log<<MSG::DEBUG + <<"AutoCorr and OFC vectors have not the same " + <<"number of elements" + <<" ("<<AutoCorr.size()<<"/"<<OFC.size() + <<" ) => will take into account only " << m_nsamples << " samples !" + <<endreq; + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + if(m_retrieve[iOFC] && m_retrieve[iSHAPE] && OFC.size()==Shape.size()) + { + float scalar=0; + for(unsigned int i=0;i<Shape.size();++i) + scalar+=Shape[i]*OFC[i]; + if((scalar-1)>0.05) + this->updateDiagnostic(8,"[Shape].[OFC] not 1",igain); + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //SAMPLING FRACTION + if(m_retrieve[iFSAMPL]) + { + if (fSampl<0.000001) + { + MsgStream log(msgSvc(), name()); + log<<MSG::WARNING<< function_name + <<" fSampl null -> PileUp will be 0 for " + <<m_lar_em_id->show_to_string(id)<<endreq; + StatusDatabase=StatusCode::FAILURE; + } + } + + //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + return StatusDatabase; +} + +////////////////////////////////////////////////// +// functions for the getNoise interface +float +CaloNoiseTool::getNoise(const CaloDetDescrElement* caloDDE, CalorimeterNoiseType type) +{ + float Nminbias=-1; + if( m_Nminbias>0 ) + Nminbias=m_Nminbias; + + CaloGain::CaloGain igain = m_highestGain[caloDDE->getSubCalo()]; + if( m_gain_from_joboption>=0 && + (type == ICalorimeterNoiseTool::ELECTRONICNOISE || + type == ICalorimeterNoiseTool::PILEUPNOISE || + type == ICalorimeterNoiseTool::TOTALNOISE )) + igain = static_cast<CaloGain::CaloGain>(m_gain_from_joboption); + + switch(type) { + case ICalorimeterNoiseTool::JOBOPTION: + return (this->*m_CachedGetNoiseCDDE)(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::ELECTRONICNOISE_HIGHESTGAIN: + case ICalorimeterNoiseTool::ELECTRONICNOISE: + return elecNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::PILEUPNOISE_HIGHESTGAIN: + case ICalorimeterNoiseTool::PILEUPNOISE: + return pileupNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::TOTALNOISE_HIGHESTGAIN: + case ICalorimeterNoiseTool::TOTALNOISE: + return totalNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + default: + return 0.; + break; + } +} + +float +CaloNoiseTool::getNoise(const CaloCell* caloCell, CalorimeterNoiseType type) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + float Nminbias=-1; + if( m_Nminbias>0 ) + Nminbias=m_Nminbias; + + CaloGain::CaloGain igain = caloCell->gain(); + + if( m_gain_from_joboption>=0 && + (type == ICalorimeterNoiseTool::ELECTRONICNOISE || + type == ICalorimeterNoiseTool::PILEUPNOISE || + type == ICalorimeterNoiseTool::TOTALNOISE )) + igain = static_cast<CaloGain::CaloGain>(m_gain_from_joboption); + + switch(type) { + case ICalorimeterNoiseTool::JOBOPTION: + return (this->*m_CachedGetNoiseCELL)(caloCell,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::ELECTRONICNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + case ICalorimeterNoiseTool::ELECTRONICNOISE: + return elecNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + case ICalorimeterNoiseTool::PILEUPNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + // NOTE: igain is not used at the moment for pileupnoise + case ICalorimeterNoiseTool::PILEUPNOISE: + return pileupNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + case ICalorimeterNoiseTool::TOTALNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + // NOTE: igain is only used for the electronics noise at the moment + case ICalorimeterNoiseTool::TOTALNOISE: + return totalNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + default: + return 0.; + break; + } +} + +////////////////////////////////////////////////// + +void +CaloNoiseTool::updateDiagnostic(int ireason,std::string nameReason,int igain) +{ + int nTmp=m_nCellsWithProblem[igain]; + if (nTmp >= 5000) return; + int nr = m_nReason[nTmp][igain]; + if (nr >= 10) return; + m_reason[nTmp][nr][igain]=ireason; + m_reasonName[ireason]=nameReason; + ++m_nReason[nTmp][igain]; + ++m_itReason[ireason][igain]; + m_noiseOK=false; + //std::cout<<nTmp<<" "<<n_reason[nTmp][igain]<<" " + // <<it_reason[ireason][igain]<<std::endl; +} + +////////////////////////////////////////////////// + + +//======================== USER INTERFACES =================================== + + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMS(const CaloCell* caloCell, + const int step) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + //CaloGain::CaloGain igain = this->estimatedGain(caloCell,caloDDE,step); + CaloGain::CaloGain igain = caloCell->gain(); + return this->elecNoiseRMS(caloDDE,igain,-1,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMS(const CaloCell* caloCell, + const float Nminbias, const int step) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + //CaloGain::CaloGain igain = this->estimatedGain(caloCell,caloDDE,step); + CaloGain::CaloGain igain = caloCell->gain(); + return this->elecNoiseRMS(caloDDE,igain,Nminbias,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMSHighestGain(const CaloCell* caloCell, + const int step) +{ + return this->elecNoiseRMSHighestGain(caloCell->caloDDE(),step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias, const int step) +{ + //WARNING: this function is almost 200 times slower than the previous one + return this->elecNoiseRMSHighestGain(caloCell->caloDDE(),Nminbias,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const int step) +{ + CaloCell_ID::SUBCALO iCalo = caloDDE->getSubCalo(); + CaloGain::CaloGain highestGain=m_highestGain[iCalo]; + return this->elecNoiseRMS(caloDDE,highestGain,-1,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias, const int step) +{ + //CaloCell_ID::SUBCALO iCalo = this->caloNum(caloDDE->calo_hash()); + CaloCell_ID::SUBCALO iCalo = caloDDE->getSubCalo(); + CaloGain::CaloGain highestGain=m_highestGain[iCalo]; + return this->elecNoiseRMS(caloDDE,highestGain,Nminbias,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::elecNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step) +// << base class >> +{ + + if(!m_cacheValid){ + MsgStream log( msgSvc(), name() ); + log<<MSG::DEBUG<< " in elecNoiseRMS, cache not valid yet"<<endreq; + StatusCode sc = this->initData(); + if (sc.isFailure()) { + throw LArConditionsException("Could not compute elecNoiseRMS "); + } + } + + + float sigma=0.; + + const IdentifierHash idCaloHash = caloDDE->calo_hash(); + //CaloCell_ID::SUBCALO iCalo = this->caloNum(idCaloHash); + CaloCell_ID::SUBCALO iCalo = caloDDE->getSubCalo(); + int index=this->index(idCaloHash); + + + int igain=static_cast<int>(gain);//for LAr + if(iCalo==CaloCell_ID::TILE) //for Tile + { + CaloGain::CaloGain convertedGain; + switch(gain) + { + //convert Tile gain into LAr gain (the one used to store the noise in arrays) + case CaloGain::TILEHIGHHIGH : convertedGain=CaloGain::LARHIGHGAIN; break; + case CaloGain::TILEHIGHLOW : convertedGain=CaloGain::LARMEDIUMGAIN; break; + case CaloGain::TILELOWHIGH : convertedGain=CaloGain::LARMEDIUMGAIN; break; + case CaloGain::TILELOWLOW : convertedGain=CaloGain::LARLOWGAIN; break; + case CaloGain::TILEONEHIGH : convertedGain=CaloGain::LARHIGHGAIN; break; + case CaloGain::TILEONELOW : convertedGain=CaloGain::LARLOWGAIN; break; + default: convertedGain = CaloGain::INVALIDGAIN; + } + igain=static_cast<int>(convertedGain); + } + + if (gain==CaloGain::INVALIDGAIN || gain==CaloGain::UNKNOWNGAIN) { + MsgStream log( msgSvc(), name() ); + log << MSG::WARNING << " ask noise for invalid/unknown gain, will return noise for high gain " << endreq; + igain=static_cast<int>(CaloGain::LARHIGHGAIN); + } + + if (iCalo<0 || index<0) + { + MsgStream log(msgSvc(), name()); + log<<MSG::WARNING + << "CaloNoiseTool::elecNoiseRMS wrong id ! " + << "iCalo="<<iCalo + << "index="<<index + << "id:" << m_lar_em_id->show_to_string(caloDDE->identify()) + << endreq; + return 0.; + } + else + { + const std::vector<float>* sigmaVector = 0; + if(step==ICaloNoiseToolStep::CELLS) + sigmaVector = &m_elecNoiseCELLContainer[index]; + else if(step==ICaloNoiseToolStep::RAWCHANNELS) + sigmaVector = &m_elecNoiseRAWContainer[index]; + else + { + MsgStream log(msgSvc(), name()); + log<<MSG::WARNING<< "CaloNoiseTool::elecNoiseRMS wrong step !!! " + <<step + <<endreq; + return 0.; + } + + bool retry=true; + int shift_gain=0; + int gain_wanted=igain; + if(m_WorkMode==0) gain_wanted=2-igain; + int gain_shifted=gain_wanted; + + while(retry) + { + //::::::::::::::::: + retry=false; + //::::::::::::::::: + if(m_WorkMode==0) gain_shifted=gain_wanted+shift_gain; + else if(m_WorkMode==1) gain_shifted=gain_wanted-shift_gain; + //::::::::::::::::: + sigma = (*sigmaVector)[gain_shifted]; + //::::::::::::::::: + if(m_WorkMode==1 && Nminbias>=0 && Nminbias!=m_Nminbias_usedForCache && + iCalo != CaloCell_ID::TILE ) + { + sigma = this->calculateElecNoiseForLAR(idCaloHash, + this->caloNum(idCaloHash), + Nminbias) [gain_shifted]; +// if(m_Geant3 && step==ICaloNoiseToolStep::CELLS) +// sigma = sigma*m_scaleContainer[index]; + } + //::::::::::::::::: + if(this->isBadValue(sigma)) + { + ++shift_gain; + if(shift_gain<=igain) retry=true; + MsgStream log(msgSvc(), name()); + log<<MSG::WARNING<< "noise is missing for this cell " << m_lar_em_id->show_to_string(caloDDE->identify()) + << " at this gain (" + <<gain_wanted<<"), return the noise at next gain (" + <<gain_shifted<<")" + <<endreq; + } + //::::::::::::::::: + } + return sigma; + } +} + +////////////////////////////////////////////////// + +std::vector<float> +CaloNoiseTool::elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const int step) +{ + std::vector<float> sigma; + sigma.reserve (CaloGain::LARNGAIN); + + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + sigma.push_back(this->elecNoiseRMS(caloDDE, + static_cast<CaloGain::CaloGain>(igain), + -1, + step)); + return sigma; +} + +////////////////////////////////////////////////// + +std::vector<float> +CaloNoiseTool::elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const float NMinBias,const int step) +{ + std::vector<float> sigma; + sigma.reserve (CaloGain::LARNGAIN); + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + sigma.push_back(this->elecNoiseRMS(caloDDE, + static_cast<CaloGain::CaloGain>(igain), + NMinBias, + step)); + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + if(this->isBadValue(sigma[igain]) && + igain!=CaloGain::LARHIGHGAIN) + sigma[igain]=sigma[igain-1];//take the next gain (low->medium->high) + return sigma; +} + +////////////////////////////////////////////////// + +VectorContainer* +CaloNoiseTool::elecNoiseRMSContainer(const int &iCalo) +{ + MsgStream log( msgSvc(), name() ); + log << MSG::WARNING << " elecNoiseRMSContainer not implemented " << iCalo << endreq ; + //return &m_elecNoiseContainer_old[iCalo]; + return 0; +} + +////////////////////////////////////////////////// +// new interfaces to enable caching of the pointer to member + +float +CaloNoiseTool::elecNoiseRMS(const CaloCell* theCell, + const CaloGain::CaloGain /*gain*/, + const float Nminbias, + const int step) { + return this->elecNoiseRMS(theCell,Nminbias,step); +} + +float +CaloNoiseTool::pileupNoiseRMS(const CaloCell* theCell, + const CaloGain::CaloGain /*gain*/, + const float Nminbias, + const int /*step*/) { + return this->pileupNoiseRMS(theCell,Nminbias); +} + +float +CaloNoiseTool::totalNoiseRMS(const CaloCell* theCell, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step) { + float elecNoiseRMS_tmp = this->elecNoiseRMS(theCell,gain,Nminbias,step); + float pileupNoiseRMS_tmp = this->pileupNoiseRMS(theCell,gain,Nminbias,step); + + if(elecNoiseRMS_tmp>=0) + return sqrt((elecNoiseRMS_tmp*elecNoiseRMS_tmp) + (pileupNoiseRMS_tmp*pileupNoiseRMS_tmp)); + return(-1); +} + +float +CaloNoiseTool::pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain /*gain*/, + const float Nminbias, + const int /*step*/) { + return this->pileupNoiseRMS(caloDDE,Nminbias); +} + +float +CaloNoiseTool::totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int step) { + float elecNoiseRMS_tmp = this->elecNoiseRMS(caloDDE,gain,Nminbias,step); + float pileupNoiseRMS_tmp = this->pileupNoiseRMS(caloDDE,gain,Nminbias,step); + + return sqrt((elecNoiseRMS_tmp*elecNoiseRMS_tmp) + (pileupNoiseRMS_tmp*pileupNoiseRMS_tmp) ); +} +////////////////////////////////////////////////// + +float +CaloNoiseTool::pileupNoiseRMS(const CaloCell* caloCell, const float Nminbias) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + return this->pileupNoiseRMS(caloDDE,Nminbias); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const float Nminbias) +// << base class >> +{ + + + if(!m_cacheValid){ + StatusCode sc = this->initData(); + if (sc.isFailure()) { + throw LArConditionsException("Could not compute pileupNoiseRMS "); + } + } + + const IdentifierHash idCaloHash = caloDDE->calo_hash(); + CaloCell_ID::SUBCALO iCalo = this->caloNum(idCaloHash); + + if(iCalo!=CaloCell_ID::TILE) + { + int index=this->index(idCaloHash); + float PileUp; + // check if noise stored in container was calcualted with this Nminbias + if ((Nminbias==m_Nminbias_usedForCache) || (Nminbias<=0)) //default + PileUp=m_pileupNoiseContainer[index]; + else + PileUp=this->calculatePileUpNoise(idCaloHash,Nminbias);//slower !! + return PileUp; + } + else//TILE + { + if(m_Nmessages_forTilePileUp<10)// to not have thousands of messages + { + MsgStream log( msgSvc(), name() ); + log<<MSG::INFO + <<"CaloNoiseTool::pileupNoiseRMS : NOT IMPLEMENTED " + <<"for TILEs ! (-> returns 0. for the moment)" + <<endreq; + ++m_Nmessages_forTilePileUp; + } + return 0.; + } +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::totalNoiseRMS(const CaloCell* caloCell, const float Nminbias) +{ + CaloGain::CaloGain igain = caloCell->gain(); + return this->totalNoiseRMS(caloCell->caloDDE(),igain,Nminbias); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias) +{ + float elecNoiseRMS_tmp = this->elecNoiseRMS(caloDDE,gain,Nminbias, + ICaloNoiseToolStep::CELLS); + float pileupNoiseRMS_tmp = this->pileupNoiseRMS(caloDDE,Nminbias); + + float totalNoiseRMS = -1; + + // checks that elecNoise is valid + if(elecNoiseRMS_tmp>0) + totalNoiseRMS= sqrt((elecNoiseRMS_tmp*elecNoiseRMS_tmp) + (pileupNoiseRMS_tmp*pileupNoiseRMS_tmp) ); + + return totalNoiseRMS; +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::totalNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias) +{ + return this->totalNoiseRMSHighestGain(caloCell->caloDDE(),Nminbias); +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::totalNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias) +{ + //CaloCell_ID::SUBCALO iCalo = caloNum(caloDDE->calo_hash()); + CaloCell_ID::SUBCALO iCalo = caloDDE->getSubCalo(); + CaloGain::CaloGain highestGain=m_highestGain[iCalo]; + return this->totalNoiseRMS(caloDDE,highestGain,Nminbias); +} + + +////////////////////////////////////////////////// +////////////////////////////////////////////////// + +CaloGain::CaloGain +CaloNoiseTool::estimatedGain(const CaloCell* caloCell, + const int &step) +{ + return this->estimatedGain(caloCell,caloCell->caloDDE(),step); +} + +////////////////////////////////////////////////// + +CaloGain::CaloGain +CaloNoiseTool::estimatedGain(const CaloCell* caloCell, + const CaloDetDescrElement* caloDDE, + const int &step) +{ + //CaloCell_ID::SUBCALO iCalo = caloNum(caloDDE->calo_hash()); + CaloCell_ID::SUBCALO iCalo = caloDDE->getSubCalo(); + + if(iCalo==CaloCell_ID::LAREM || + iCalo==CaloCell_ID::LARHEC || + iCalo==CaloCell_ID::LARFCAL) + return this->estimatedLArGain(iCalo,caloDDE,caloCell->energy(),step); + else if(iCalo==CaloCell_ID::TILE) + return this->estimatedTileGain(caloCell,caloDDE,step); + else + { + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING + <<"CaloNoiseTool::estimatedGain wrong id ! " + <<m_lar_em_id->show_to_string(caloDDE->identify()) + <<endreq; + return CaloGain::INVALIDGAIN; + } +} + +////////////////////////////////////////////////// + +CaloGain::CaloGain +CaloNoiseTool::estimatedGain(const CaloDetDescrElement* caloDDE, + const float &energy, + const int &step) +{ + //CaloCell_ID::SUBCALO iCalo = caloNum(caloDDE->calo_hash()); + CaloCell_ID::SUBCALO iCalo = caloDDE->getSubCalo(); + + if(iCalo==CaloCell_ID::LAREM || + iCalo==CaloCell_ID::LARHEC || + iCalo==CaloCell_ID::LARFCAL) + return this->estimatedLArGain(iCalo,caloDDE,energy,step); + else if(iCalo==CaloCell_ID::TILE) + { + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING + <<"CaloNoiseTool::estimatedGain NOT IMPLEMENTED FOR TILE " + <<"with these arguments! " + << m_lar_em_id->show_to_string(caloDDE->identify()) + <<endreq; + return CaloGain::INVALIDGAIN; + } + else + { + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING + <<"CaloNoiseTool::estimatedGain wrong id ! " + << m_lar_em_id->show_to_string(caloDDE->identify()) + <<endreq; + return CaloGain::INVALIDGAIN; + } +} + +////////////////////////////////////////////////// + +CaloGain::CaloGain +CaloNoiseTool::estimatedLArGain(const CaloCell_ID::SUBCALO &iCalo, + const CaloDetDescrElement* caloDDE, + const float &energy, + const int &step) +{ + //returns the gain of a cell according to the energy + //(converts in ADC counts in MediumGain and uses thresholds in ADC counts + //to determine the gain) + + // the function could be called before (step=0, RawChannels) + // or after (step=1, Cells) LArG3Escale + + CaloGain::CaloGain igain=CaloGain::INVALIDGAIN; + + //--EM/HEC-- + if( iCalo==CaloCell_ID::LAREM || iCalo==CaloCell_ID::LARHEC || + (iCalo==CaloCell_ID::LARFCAL && m_WorkMode==1) ) + { + //We choose the gain in applying thresholds on the energy + //converted in ADC counts in MediumGain (index "1" of adc2mev(id,1)). + //Indeed, thresholds in ADC counts are defined with respect + //to the MediumGain. + // + // 1300 3900 + // ---------------|----------------|-------------> ADC counts in MediumGain + // HighGain <--- MediumGain ---> LowGain + + float adc=0.; + + //Cells (with E scale and weights from LArG3Escale) + if(step==ICaloNoiseToolStep::CELLS) + adc=energy/(this->adc2mev(caloDDE,CaloGain::LARMEDIUMGAIN)) + 1000 ; + //RawChannels + else if(step==ICaloNoiseToolStep::RAWCHANNELS) + adc=energy/(this->adc2mev(caloDDE,CaloGain::LARMEDIUMGAIN)) + 1000 ; + else + { + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING<< "CaloNoiseTool::estimatedGain wrong step"<<endreq; + } + if(adc<m_HighGainThresh[iCalo]) igain=CaloGain::LARHIGHGAIN; + else if(adc>m_LowGainThresh[iCalo]) igain=CaloGain::LARLOWGAIN; + else igain=CaloGain::LARMEDIUMGAIN; + } + //--FCAL-- + else if(iCalo==CaloCell_ID::LARFCAL && m_WorkMode==0) + { + if(energy<m_HighGainThresh[iCalo]) igain=CaloGain::LARHIGHGAIN; + else if(energy>m_LowGainThresh[iCalo]) igain=CaloGain::LARLOWGAIN; + else igain=CaloGain::LARMEDIUMGAIN; + } + + return igain; +} + +////////////////////////////////////////////////// + +CaloGain::CaloGain +CaloNoiseTool::estimatedTileGain(const CaloCell* caloCell, + const CaloDetDescrElement* caloDDE, + const int &/*step*/) +{ + const TileCell * tileCell = (TileCell *)caloCell; + //double eneTot = tileCell->energy(); + + // threshold (1023 counts) is the same for all channels + double thr = m_tileInfo->ADCmax(); + + static const TileHWID * tileHWID = TileCablingService::getInstance()->getTileHWID(); + static const IdContext chContext = tileHWID->channel_context(); + HWIdentifier hwid; + + tileHWID->get_id(caloDDE->onl1(), hwid, &chContext ); // pmt id + hwid = tileHWID->adc_id(hwid,TileHWID::HIGHGAIN); // high gain ADC id + + // first PMT, convert energy to ADC counts + double amp = tileCell->ene1(); + amp /= m_tileInfo->ChannelCalib(hwid,TileRawChannelUnit::ADCcounts,TileRawChannelUnit::MegaElectronVolts); + double ped = m_tileInfo->DigitsPedLevel(hwid); + + int igain1; + + if (amp + ped < thr ) + igain1 = TileID::HIGHGAIN; + else + igain1 = TileID::LOWGAIN; + + // second PMT, if it exists + if (caloDDE->onl2() != TileID::NOT_VALID_HASH ) + { + tileHWID->get_id(caloDDE->onl2(), hwid, &chContext ); // pmt id + hwid = tileHWID->adc_id(hwid,TileHWID::HIGHGAIN); // high gain ADC id + + amp = tileCell->ene2(); + amp /= m_tileInfo->ChannelCalib(hwid,TileRawChannelUnit::ADCcounts,TileRawChannelUnit::MegaElectronVolts); + ped = m_tileInfo->DigitsPedLevel(hwid); + + if (amp + ped < thr ) { + // igain2 high + return igain1 == TileID::LOWGAIN ? CaloGain::TILEHIGHLOW : CaloGain::TILEHIGHHIGH; + } + else { + // igain2 low + return igain1 == TileID::LOWGAIN ? CaloGain::TILELOWLOW : CaloGain::TILEHIGHLOW; + } + // nb. Having HIGHLOW in two places seems wrong, but that's what the + // original code was doing. + } + + // igain2 doesn't exist. + return igain1 == TileID::LOWGAIN ? CaloGain::TILEONELOW : CaloGain::TILEONEHIGH; +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::adc2mev(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain) +{ + + if(!m_cacheValid){ + StatusCode sc = this->initData(); + if (sc.isFailure()) { + throw LArConditionsException("Could not compute adc2mev "); + } + } + + + float factor=1.; + IdentifierHash idCaloHash = caloDDE->calo_hash(); + CaloCell_ID::SUBCALO iCalo = this->caloNum(idCaloHash); + + if(iCalo==CaloCell_ID::LAREM || iCalo==CaloCell_ID::LARHEC) + { + int index=this->index(idCaloHash); + if(m_WorkMode==0) + factor=(m_adc2mevContainer[index])[2-gain]; + else if(m_WorkMode==1) + factor=(m_adc2mevContainer[index])[gain]; + } + else if(iCalo==CaloCell_ID::LARFCAL) + { + if(m_WorkMode==0) + { + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING + <<"CaloNoiseTool::adc2mev(id,gain) : NOT IMPLEMENTED !" + <<"for FCAL (-> returns 5000. for the moment)" + <<endreq; + //NOT CLEAR what we should return + //(for the moment, returns AdcPerGev from LArDigitMaker) + factor=AdcPerMev; + } + else if(m_WorkMode==1) + { + int index=this->index(idCaloHash); + factor=(m_adc2mevContainer[index])[gain]; + } + } + else if(iCalo==CaloCell_ID::TILE) + { + //TILE_PART + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING + <<"CaloNoiseTool::adc2mev(id,gain) : NOT IMPLEMENTED !" + <<"for TILE (-> returns 1. for the moment)" + <<endreq; + factor=1.; + } + else + { + MsgStream log( msgSvc(), name() ); + log<<MSG::WARNING + <<"CaloNoiseTool::adc2mev(id,gain) wrong id ! " + <<m_lar_em_id->show_to_string(caloDDE->identify()) + <<endreq; + factor=0.; + } + return factor; +} + +////////////////////////////////////////////////// + +float +CaloNoiseTool::adc2mev(const Identifier& id,const CaloGain::CaloGain gain) +{ + return adc2mev(m_calo_dd_man->get_element(id),gain); +} + + + +void CaloNoiseTool::handle(const Incident&) { + MsgStream log( msgSvc(), name() ); + log << MSG::DEBUG << "In Incident-handle" << endreq; + if (m_cacheValid) { + log << MSG::DEBUG << "Cached data already computed." << endreq; + return; + } + + StatusCode sc = this->initData(); + + if (sc.isFailure()) { + log << MSG::ERROR << "handle: error with initData() " << endreq; + log << MSG::ERROR << "Failed to update CaloNoiseTool Cache at the begin of run." << endreq; + m_cacheValid=false; + } +} + +///////////////////////////////////////////////////////////////////////// + +bool CaloNoiseTool::isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling, + CalorimeterNoiseType type ) +{ + float noise_cut = fabs(sigmaCut*this->getEffectiveSigma(caloCell, symmetryHandling, type)); + float energy = fabs(caloCell->e()); + return (energy>noise_cut); + +} + +//////////////////////////////////////////////////////////////////// + +float CaloNoiseTool::getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type) +{ + double rms = this->getNoise(caloCell,type); + return RandGauss::shoot(engine,0.,rms); +} + +/////////////////////////////////////////////////////////////////////////// + +float CaloNoiseTool::getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling /*symmetryHandling*/, + CalorimeterNoiseType type ) +{ + // simple implementation for gaussian noise + return this->getNoise(caloCell,type); +} + + diff --git a/Calorimeter/CaloTools/src/CaloNoiseToolDB.cxx b/Calorimeter/CaloTools/src/CaloNoiseToolDB.cxx new file mode 100755 index 0000000000000000000000000000000000000000..135458b2805fce3199d67a4f1caeb029f616617e --- /dev/null +++ b/Calorimeter/CaloTools/src/CaloNoiseToolDB.cxx @@ -0,0 +1,1178 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CaloTools/CaloNoiseToolDB.h" + + +//=== AttributeList +#include "CoralBase/Blob.h" +#include "AthenaPoolUtilities/CondAttrListCollection.h" +//=== TileCalibBlobObjs +#include "CaloCondBlobObjs/CaloCondBlobFlt.h" +#include "CaloCondBlobObjs/CaloCondUtils.h" + +#include "CLHEP/Random/RandomEngine.h" +#include "CLHEP/Random/RandGauss.h" + +#include "GeoModelInterfaces/IGeoModelSvc.h" + +#include "TMath.h" + +using CLHEP::RandGauss; + +////////////////////////////////////////////////// + +CaloNoiseToolDB::CaloNoiseToolDB(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool(type, name, parent), + m_cacheValid(false) + +{ + declareInterface<ICaloNoiseTool>(this); + declareInterface<ICalorimeterNoiseTool>(this); + + declareProperty("Luminosity",m_lumi0=0,"Luminosity in 10**33 units"); + declareProperty("CachedNoise",m_ReturnNoiseName="totalNoise","Cached Noise"); + declareProperty("FixGain",m_gain_from_joboption=-1); + declareProperty("SpeedTwoGauss",m_speedTwoGauss=true); + declareProperty("FolderNames",m_folderNames); + declareProperty("LumiFolderName",m_lumiFolderName="/TRIGGER/LUMI/LBLESTONL"); +} + +////////////////////////////////////////////////// + +StatusCode +CaloNoiseToolDB::initialize() +{ + + m_cached = ICalorimeterNoiseTool::TOTALNOISE; + + if (m_folderNames.size()==0) { + msg(MSG::ERROR) << "No database folder name give to read noise! Please set " << name() << ".FolderNames=[...]" << endreq; + return StatusCode::FAILURE; + } + + + const IGeoModelSvc *geoModel=0; + StatusCode sc = service("GeoModelSvc", geoModel); + if(sc.isFailure()) + { + msg(MSG::ERROR) << "Could not locate GeoModelSvc" << endreq; + return sc; + } + + // dummy parameters for the callback: + int dummyInt=0; + std::list<std::string> dummyList; + + if (geoModel->geoInitialized()) + { + return geoInit(dummyInt,dummyList); + } + else + { + sc = detStore()->regFcn(&IGeoModelSvc::geoInit, + geoModel, + &CaloNoiseToolDB::geoInit,this); + if(sc.isFailure()) + { + msg(MSG::ERROR) << "Could not register geoInit callback" << endreq; + return sc; + } + } + + + return sc; +} + + +StatusCode +CaloNoiseToolDB::finalize() +{ + msg(MSG::INFO) + << "CaloNoiseToolDB final(), cleaning m_noiseBlobMap, size = " <<m_noiseBlobMap.size() <<endreq; + + //=== delete old CaloCondBlobFlt (which does not own the blob) + std::map<SYSTEM, const CaloCondBlobFlt*>::iterator it = m_noiseBlobMap.begin(); + std::map<SYSTEM, const CaloCondBlobFlt*>::iterator it_e = m_noiseBlobMap.end(); + for (; it!=it_e; ++it ){ + delete it->second; + } + + return StatusCode::SUCCESS; + +} +StatusCode +CaloNoiseToolDB::geoInit(IOVSVC_CALLBACK_ARGS) +{ + StatusCode sc; + + msg(MSG::INFO) + << "CaloNoiseToolDB initialize() begin" + << endreq; + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + //retrieves helpers for Identifier + + //retrieve ID helpers + sc = detStore()->retrieve( m_caloIdMgr ); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Unable to retrieve CaloIdMgr in LArHitEMap " << endreq; + return StatusCode::FAILURE; + } + m_calo_id = m_caloIdMgr->getCaloCell_ID(); + + m_Nminbias = m_lumi0*2.3; + + m_highestGain[CaloCell_ID::LAREM] = CaloGain::LARHIGHGAIN; + m_highestGain[CaloCell_ID::LARHEC] = CaloGain::LARMEDIUMGAIN; + m_highestGain[CaloCell_ID::LARFCAL] = CaloGain::LARHIGHGAIN; + m_highestGain[CaloCell_ID::TILE] = CaloGain::TILEHIGHHIGH; + + // register callback for luminosity (only if not hardcoded from jobOptions) + + if (m_lumi0<0) { + m_lumi0=0; + if (detStore()->contains<CondAttrListCollection>(m_lumiFolderName)) { + const DataHandle<CondAttrListCollection> lumiData; + sc = detStore()->regFcn(&CaloNoiseToolDB::updateLumi, this , lumiData, m_lumiFolderName, true); + if (sc.isFailure()) { + msg(MSG::ERROR) << " cannot register callback for luminosity " << endreq; + return StatusCode::FAILURE; + } + msg(MSG::INFO) << " Registered a callback for " << m_lumiFolderName << " Cool folder " << endreq; + } + } + + + m_noiseAttrListColl.resize(m_folderNames.size()); + std::vector<std::string>::const_iterator fldr_it=m_folderNames.begin(); + std::vector<std::string>::const_iterator fldr_it_e=m_folderNames.end(); + unsigned i=0; + for(;fldr_it!=fldr_it_e;++fldr_it) { + const std::string& folderName=*fldr_it; + + msg(MSG::INFO) << "Registering callback on folder " << folderName << endreq; + sc=detStore()->regFcn(&CaloNoiseToolDB::updateMap, this, const_cast<const DataHandle<CondAttrListCollection>&>(m_noiseAttrListColl[i++]), folderName, true); + if (sc.isFailure()) { + msg(MSG::ERROR) << " cannot register callback to folder " << folderName << endreq; + return StatusCode::FAILURE; + } + } + + msg(MSG::INFO) << "CaloNoiseToolDB initialize() end" << endreq; + + return StatusCode::SUCCESS; +} + +//______________________________________________________________________________________ +StatusCode +CaloNoiseToolDB::updateLumi( IOVSVC_CALLBACK_ARGS ) +{ + + msg(MSG::INFO) << " in updateLumi() " << endreq; + + const CondAttrListCollection* attrListColl = 0; + StatusCode sc = detStore()->retrieve(attrListColl, m_lumiFolderName); + if (sc.isFailure() || !attrListColl) { + msg(MSG::WARNING) << "attrrListColl not found for " << m_lumiFolderName << endreq; + return StatusCode::SUCCESS; + } + // Loop over collection + CondAttrListCollection::const_iterator first = attrListColl->begin(); + CondAttrListCollection::const_iterator last = attrListColl->end(); + for (; first != last; ++first) { + if ((*first).first == 0) { + std::ostringstream attrStr1; + (*first).second.toOutputStream( attrStr1 ); + ATH_MSG_DEBUG("ChanNum " << (*first).first << " Attribute list " << attrStr1.str()); + const coral::AttributeList& attrList = (*first).second; + if (attrList["LBAvInstLumi"].isNull()) { + msg(MSG::WARNING) << " NULL Luminosity information in database ... set it to 0 " << endreq; + m_lumi0 = 0.; + } else { + m_lumi0 = attrList["LBAvInstLumi"].data<float>() *1e-3; // luminosity (from 10**30 units in db to 10*33 units) + } + if ( !(m_lumi0 == m_lumi0) ) { + msg(MSG::WARNING) << " Luminosity is not a number.. " << m_lumi0 << " ... set it to 0 " << endreq; + m_lumi0=0.; + } + m_Nminbias = m_lumi0*2.3; + m_cacheValid = false; + break; + } + } + return StatusCode::SUCCESS; +} + +//_______________________________________________________________________________________ +StatusCode +CaloNoiseToolDB::updateMap( IOVSVC_CALLBACK_ARGS_K(keys) ) +{ + std::set<unsigned> channelsFound; + std::list<std::string>::const_iterator itr; + for (itr=keys.begin(); itr!=keys.end(); ++itr) { + msg(MSG::INFO) << " updateMap callback for kye " << *itr << endreq; + const CondAttrListCollection* noiseAttrListColl; + StatusCode sc=detStore()->retrieve(noiseAttrListColl,*itr); + if (sc.isFailure()) { + msg(MSG::ERROR) << "Failed to retrieve CondAttrListCollection with key " << *itr << endreq; + return sc; + } + + //=== loop over collection (all cool channels) + CondAttrListCollection::const_iterator iColl = noiseAttrListColl->begin(); + CondAttrListCollection::const_iterator last = noiseAttrListColl->end(); + for (; iColl != last; ++iColl) { + ATH_MSG_DEBUG("Working on folder " << *itr << " Channel " << iColl->first); + const coral::Blob& blob = (iColl->second)["CaloCondBlob16M"].data<coral::Blob>(); + if (blob.size()<1) { + ATH_MSG_DEBUG("Empty blob in folder " << *itr << ", channel " << iColl->first << ". Ignored."); + continue; + } + + if (channelsFound.insert(iColl->first).second==false) { + msg(MSG::ERROR) << "Channel " << iColl->first << " encountered twice during this callback! Don't know what to do." << endreq; + return StatusCode::FAILURE; + } + //=== COOL channel number is system id + SYSTEM sysId = static_cast<SYSTEM>(iColl->first); + + //=== delete old CaloCondBlobFlt (which does not own the blob) + std::map<SYSTEM, const CaloCondBlobFlt*>::iterator iOld = m_noiseBlobMap.find(sysId); + if(iOld != m_noiseBlobMap.end()){ + delete iOld->second; + } + + //=== Get new CaloCondBlobFlt instance, interpreting current BLOB + + const CaloCondBlobFlt* flt = CaloCondBlobFlt::getInstance(blob); + + //=== store new pointer in map + m_noiseBlobMap[sysId] = flt; + + }//end iColl + } + + if (m_noiseBlobMap.size()==7) { + this->updateCache(); + } + return StatusCode::SUCCESS; +} +//_______________________________________________________________________________________ +void +CaloNoiseToolDB::updateCache() + // + // This function is called when /CALO/Noise/CellNoise goes out of IOV. + // It ensures that the pointers to the CaloCondBlobFlt objects stored in + // the different COOL channels are also up to date. + // +{ + msg(MSG::INFO) << " in update Cache " << endreq; + + // Cache, what noise to return + m_CachedGetNoiseCDDE=NULL; + if(m_ReturnNoiseName=="electronicNoise") { + msg(MSG::INFO) << "Will cache electronic noise" << endreq; + m_CachedGetNoiseCDDE=&CaloNoiseToolDB::elecNoiseRMS; + m_CachedGetNoiseCELL=&CaloNoiseToolDB::elecNoiseRMS; + m_cached = ICalorimeterNoiseTool::ELECTRONICNOISE; + } + if(m_ReturnNoiseName=="pileupNoise") { + msg(MSG::INFO) << "Will cache pileupNoise noise" << endreq; + m_CachedGetNoiseCDDE=&CaloNoiseToolDB::pileupNoiseRMS; + m_CachedGetNoiseCELL=&CaloNoiseToolDB::pileupNoiseRMS; + m_cached = ICalorimeterNoiseTool::PILEUPNOISE; + } + if(m_ReturnNoiseName=="totalNoise") { + msg(MSG::INFO) << "Will cache totalNoise noise" << endreq; + m_CachedGetNoiseCDDE=&CaloNoiseToolDB::totalNoiseRMS; + m_CachedGetNoiseCELL=&CaloNoiseToolDB::totalNoiseRMS; + m_cached = ICalorimeterNoiseTool::TOTALNOISE; + } + if(m_CachedGetNoiseCDDE==NULL || + m_CachedGetNoiseCELL==NULL) { + msg(MSG::ERROR) << "Unknown noise !" << endreq; + } + + + // total number of cells in calorimeter + m_ncell=m_calo_id->calo_cell_hash_max(); + + // Number of cells per system in EM Barrel and EndCap (indexed by SYSTEM, only first NUM_EM_SYS SYSTEMs) + // This is not used later, only for printing + int ncellEM[NUM_EM_SYS]; + + std::fill_n(ncellEM, NUM_EM_SYS, 0); + std::fill_n(m_firstSysHash, NUM_EM_SYS, IdentifierHash()); + + IdentifierHash cellHash, cellHashEnd; + m_calo_id->calo_cell_hash_range(CaloCell_ID::LAREM, cellHash, cellHashEnd); + for (; cellHash != cellHashEnd; cellHash += 1) { + Identifier id = m_calo_id->cell_id(cellHash); + int sys = 0; + if (m_calo_id->is_em_barrel(id)) { + sys = (m_calo_id->pos_neg(id) > 0) ? EMBZPOS : EMBZNEG; + } else if (m_calo_id->is_em_endcap(id)) { + sys = (m_calo_id->pos_neg(id) > 0) ? EMECZPOS : EMECZNEG; + } + if (not m_firstSysHash[sys].is_valid()) m_firstSysHash[sys] = cellHash; + ++ ncellEM[sys]; + } + + msg(MSG::INFO) << " starting cell hash in EM calo " << m_firstSysHash[EMECZNEG] << " " << m_firstSysHash[EMBZNEG] << " " << m_firstSysHash[EMBZPOS] << " " << m_firstSysHash[EMECZPOS] << endreq; + msg(MSG::INFO) << " number of cells in EM calo " << ncellEM[EMECZNEG] << " " << ncellEM[EMBZNEG] << " " << ncellEM[EMBZPOS] << " " << ncellEM[EMECZPOS] << endreq; + msg(MSG::INFO) << " number from Cools " << m_noiseBlobMap[EMECZNEG]->getNChans() << " " << m_noiseBlobMap[EMBZNEG]->getNChans() << " " + << m_noiseBlobMap[EMBZPOS]->getNChans() << " " << m_noiseBlobMap[EMECZPOS]->getNChans() << endreq; + + const int MaxGains = 4; // make sure that code below does not exceed this size + // m_noise is quite large and memory layout is important; profiling shows that + // [MaxGains][m_ncell] ordering makes fewer cache misses than opposite order. + m_noise.resize(boost::extents[MaxGains][m_ncell]); + + bool tile_not_found = true; + + msg(MSG::INFO) << " m_lumi0 " << m_lumi0 << endreq; + float lumi = m_lumi0; + for (int i=0;i<m_ncell;i++) { + IdentifierHash idHash = i; + int ngain=3; + if (m_calo_id->is_tile(idHash)) { + ngain=4; + if (tile_not_found) { + tile_not_found = false; + if (this->checkObjLength(i) < 5) { + msg(MSG::WARNING) + << "Old CALO DB detected, double gaussian noise option has no effect" << endreq; + } else { + msg(MSG::INFO) + << "New CALO DB detected, double gaussian noise option can be used" << endreq; + } + } + } + for (int igain=0;igain<ngain;igain++) { + CaloGain::CaloGain caloGain=CaloGain::INVALIDGAIN;; + if (!m_calo_id->is_tile(idHash)) caloGain = static_cast<CaloGain::CaloGain> (igain); + else { + if (igain==0) caloGain=CaloGain::TILELOWLOW; + if (igain==1) caloGain=CaloGain::TILELOWHIGH; + if (igain==2) caloGain=CaloGain::TILEHIGHLOW; + if (igain==3) caloGain=CaloGain::TILEHIGHHIGH; + } + if (m_cached==ICalorimeterNoiseTool::TOTALNOISE) { + float noise = this->getDBNoise(i,caloGain,lumi); + m_noise[igain][i] = noise; + if (i==0) { + msg(MSG::INFO) << " NoiseDB parameters for first cell at gain " << igain << endreq; + msg(MSG::INFO) << " a " << this->getA(i,caloGain) << endreq; + msg(MSG::INFO) << " b " << this->getB(i,caloGain) << endreq; + msg(MSG::INFO) << " lumi " << lumi << endreq; + msg(MSG::INFO) << " noise " << noise << endreq; + } + } + if (m_cached==ICalorimeterNoiseTool::ELECTRONICNOISE) { + float noise = this->getA(i,caloGain); + m_noise[igain][i] = noise; + } + if (m_cached==ICalorimeterNoiseTool::PILEUPNOISE) { + float noise = this->getB(i,caloGain)*sqrt(lumi); + m_noise[igain][i] = noise; + } + } + } + m_cacheValid = true; +} + +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getDBNoise(unsigned int cellHash, + CaloGain::CaloGain caloGain, + float lumi) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + return this->getDBNoise(sysId, subHash, caloGain, lumi); +} + + +// +float +CaloNoiseToolDB::getA(unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + return this->getA(sysId,subHash,caloGain); +} + +// +float +CaloNoiseToolDB::getB(unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + return this->getB(sysId,subHash,caloGain); +} + +// +float +CaloNoiseToolDB::getC(unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + return this->getC(sysId,subHash,caloGain); +} + +// +float +CaloNoiseToolDB::getD(unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + return this->getD(sysId,subHash,caloGain); +} + +// +float +CaloNoiseToolDB::getE(unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + return this->getE(sysId,subHash,caloGain); +} + +CaloNoiseToolDB::SYSTEM CaloNoiseToolDB::caloSystem(unsigned int cellHash, unsigned int& subHash) const +{ + int subCalo; + subHash = m_calo_id->subcalo_cell_hash (cellHash, subCalo); + if (subCalo == CaloCell_ID::LAREM) { // EM calo + for (int i = 0; i != NUM_EM_SYS-1; ++ i) { + if (cellHash < m_firstSysHash[i+1].value()) { + subHash = cellHash - m_firstSysHash[i].value(); + return SYSTEM(i); + } + } + subHash = cellHash - m_firstSysHash[NUM_EM_SYS-1].value(); + return SYSTEM(NUM_EM_SYS-1); + } else if (subCalo == CaloCell_ID::LARHEC) { // HEC + return HEC; + } else if (subCalo == CaloCell_ID::LARFCAL) { // Fcal + return FCAL; + } else { + if (subCalo != CaloCell_ID::TILE) { + std::cout << " something wrong. either LAr not tile..." << std::endl; + } + return TILE; + } +} + + + +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getA(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(caloGain); + return flt->getData(cellHash,dbGain,0); +} + +// +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getB(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(caloGain); + return flt->getData(cellHash,dbGain,1); +} + +// +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getC(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(caloGain); + return flt->getData(cellHash,dbGain,2); +} + +// +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getD(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(caloGain); + return flt->getData(cellHash,dbGain,3); +} + +// +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getE(SYSTEM sysId, unsigned int cellHash, CaloGain::CaloGain caloGain) const +{ + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(caloGain); + return flt->getData(cellHash,dbGain,4); +} + +// +int +CaloNoiseToolDB::checkObjLength(unsigned int cellHash) const +{ + unsigned int subHash; + SYSTEM sysId = this->caloSystem(cellHash,subHash); + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + return flt->getObjSizeUint32(); +} + +//_______________________________________________________________________________________ +float +CaloNoiseToolDB::getDBNoise(SYSTEM sysId, + unsigned int cellHash, + CaloGain::CaloGain caloGain, + float lumi) const +{ + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(caloGain); + return flt->getCalib(cellHash, dbGain, lumi); +} + + + + + +////////////////////////////////////////////////// +// functions for the getNoise interface +float +CaloNoiseToolDB::getNoise(const CaloDetDescrElement* caloDDE, CalorimeterNoiseType type) +{ + float Nminbias=-1; + if( m_Nminbias>0 ) + Nminbias=m_Nminbias; + + CaloGain::CaloGain igain = m_highestGain[caloDDE->getSubCalo()]; + if( m_gain_from_joboption>=0 && + (type == ICalorimeterNoiseTool::ELECTRONICNOISE || + type == ICalorimeterNoiseTool::PILEUPNOISE || + type == ICalorimeterNoiseTool::TOTALNOISE )) + igain = static_cast<CaloGain::CaloGain>(m_gain_from_joboption); + + switch(type) { + case ICalorimeterNoiseTool::JOBOPTION: + return (this->*m_CachedGetNoiseCDDE)(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::ELECTRONICNOISE_HIGHESTGAIN: + case ICalorimeterNoiseTool::ELECTRONICNOISE: + return elecNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::PILEUPNOISE_HIGHESTGAIN: + case ICalorimeterNoiseTool::PILEUPNOISE: + return pileupNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::TOTALNOISE_HIGHESTGAIN: + case ICalorimeterNoiseTool::TOTALNOISE: + return totalNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + default: + return 0.; + break; + } +} + +float +CaloNoiseToolDB::getNoise(const CaloCell* caloCell, CalorimeterNoiseType type) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + float Nminbias=-1; + if( m_Nminbias>0 ) + Nminbias=m_Nminbias; + + CaloGain::CaloGain igain = caloCell->gain(); + + if( m_gain_from_joboption>=0 && + (type == ICalorimeterNoiseTool::ELECTRONICNOISE || + type == ICalorimeterNoiseTool::PILEUPNOISE || + type == ICalorimeterNoiseTool::TOTALNOISE )) + igain = static_cast<CaloGain::CaloGain>(m_gain_from_joboption); + + switch(type) { + case ICalorimeterNoiseTool::JOBOPTION: + return (this->*m_CachedGetNoiseCELL)(caloCell,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::ELECTRONICNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + case ICalorimeterNoiseTool::ELECTRONICNOISE: + return elecNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + case ICalorimeterNoiseTool::PILEUPNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + // NOTE: igain is not used at the moment for pileupnoise + case ICalorimeterNoiseTool::PILEUPNOISE: + return pileupNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + case ICalorimeterNoiseTool::TOTALNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + // NOTE: igain is only used for the electronics noise at the moment + case ICalorimeterNoiseTool::TOTALNOISE: + return totalNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + default: + return 0.; + break; + } +} + +float +CaloNoiseToolDB::getNoise(const CaloCell* caloCell, float energy, CalorimeterNoiseType type) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + float Nminbias=-1; + if( m_Nminbias>0 ) + Nminbias=m_Nminbias; + + CaloGain::CaloGain igain = caloCell->gain(); + + if( m_gain_from_joboption>=0 && + (type == ICalorimeterNoiseTool::ELECTRONICNOISE || + type == ICalorimeterNoiseTool::PILEUPNOISE || + type == ICalorimeterNoiseTool::TOTALNOISE )) + igain = static_cast<CaloGain::CaloGain>(m_gain_from_joboption); + + switch(type) { + case ICalorimeterNoiseTool::JOBOPTION: + return (this->*m_CachedGetNoiseCELL)(caloCell,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + case ICalorimeterNoiseTool::ELECTRONICNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + case ICalorimeterNoiseTool::ELECTRONICNOISE: + return elecNoiseRMS(caloDDE,igain,Nminbias,energy, + ICaloNoiseToolStep::CELLS); + break; + + case ICalorimeterNoiseTool::PILEUPNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + // NOTE: igain is not used at the moment for pileupnoise + case ICalorimeterNoiseTool::PILEUPNOISE: + return pileupNoiseRMS(caloDDE,igain,Nminbias, + ICaloNoiseToolStep::CELLS); + break; + + case ICalorimeterNoiseTool::TOTALNOISE_HIGHESTGAIN: + // overwrite iGain with highest gain for that detector and + // continue into normal code (NO break !!) + igain=m_highestGain[caloDDE->getSubCalo()]; + // NOTE: igain is only used for the electronics noise at the moment + case ICalorimeterNoiseTool::TOTALNOISE: + return totalNoiseRMS(caloDDE,igain,Nminbias,energy, + ICaloNoiseToolStep::CELLS); + break; + + default: + return 0.; + break; + } +} + +float +CaloNoiseToolDB::calcSig(double e, double sigma1, double ratio, double sigma2) { +//Luca: code to return the C.L. of the double gaussian with +//3 parameters. +//sigma1, sigma2 and ratio are the 3 noise parameters +// e is the input energy of which you want to calculated the +//significance + float valid_range[2]={0.9,7.5}; + + if((sigma1 == 0. && sigma2 == 0.) || e == 0.) return 0.; + if(sigma1 == 0.) return e/sigma2; + if((ratio == 0.) || sigma2 == 0.) return e/sigma1; + double x1 = e/sigma1; + double x2 = e/sigma2; + + if (m_speedTwoGauss) { + float wide_gauss_sigma = std::min(fabs(x1),fabs(x2)); + if(wide_gauss_sigma > valid_range[1]) return wide_gauss_sigma; + float narrow_gauss_sigma= std::max(fabs(x1),fabs(x2)); + if(narrow_gauss_sigma < valid_range[0]) return narrow_gauss_sigma; + } + + double y1= TMath::Erf(invsqrt2*x1); + double y2= TMath::Erf(invsqrt2*x2); + + double z = ( y1*sigma1 + ratio*y2*sigma2 )/( sigma1 + ratio*sigma2); + + //return the C.L. probability (with sign!) + // return z; + + // if instead you want to return the sigma-equivalent C.L. + // (with sign!) use the following line + return sqrt2*TMath::ErfInverse(z); + +} + +//======================== USER INTERFACES =================================== + + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMS(const CaloCell* caloCell, + const int /* step */) +{ + if (!m_cacheValid) this->updateCache(); + Identifier id = caloCell->ID(); + int i = (int)(m_calo_id->calo_cell_hash(id)); + if (i>m_ncell) return -1; + CaloGain::CaloGain calogain = caloCell->gain(); + if (m_cached==ICalorimeterNoiseTool::ELECTRONICNOISE && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(calogain); + return m_noise[igain][i]; + } + else + return this->getA(i,calogain); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMS(const CaloCell* caloCell, + const float /* Nminbias */, const int step) +{ + return this->elecNoiseRMS(caloCell,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMSHighestGain(const CaloCell* caloCell, + const int /* step */) +{ + Identifier id = caloCell->ID(); + int i = (int)(m_calo_id->calo_cell_hash(id)); + if (i>m_ncell) return -1; + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + CaloGain::CaloGain highestgain=m_highestGain[caloDDE->getSubCalo()]; + return this->getA(i,highestgain); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMSHighestGain(const CaloCell* caloCell, + const float /* Nminbias */, const int step) +{ + return this->elecNoiseRMSHighestGain(caloCell,step); + +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const int step) +{ + CaloGain::CaloGain highestGain=m_highestGain[caloDDE->getSubCalo()]; + return this->elecNoiseRMS(caloDDE,highestGain,-1,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias, const int step) +{ + CaloGain::CaloGain highestGain=m_highestGain[caloDDE->getSubCalo()]; + return this->elecNoiseRMS(caloDDE,highestGain,Nminbias,step); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float /* Nminbias */, + const int /* step */) +{ + if (!m_cacheValid) this->updateCache(); + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + if (m_cached==ICalorimeterNoiseTool::ELECTRONICNOISE && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(gain); + return m_noise[igain][i]; + } + else + return this->getA(i,gain); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::elecNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float /* Nminbias */, + const float energy, + const int /* step */) +{ + if (!m_cacheValid) this->updateCache(); + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + unsigned int subHash; + SYSTEM sysId = this->caloSystem(i,subHash); + const CaloCondBlobFlt* const flt = m_noiseBlobMap.find(sysId)->second; + unsigned int dbGain = CaloCondUtils::getDbCaloGain(gain); + if (flt->getObjSizeUint32() > 4) { // need at least 5 elements in a vector for 2G noise + double sigma1 = flt->getData(subHash,dbGain,2); + double sigma2 = flt->getData(subHash,dbGain,3); + double ratio = flt->getData(subHash,dbGain,4); + float n_sigma = this->calcSig(energy, sigma1, ratio, sigma2); + float equiv_noise = (n_sigma != 0.) ? fabs(energy/n_sigma) : 0.0; + return equiv_noise; + } else { + if (m_cached==ICalorimeterNoiseTool::ELECTRONICNOISE && m_cacheValid) { + return m_noise[dbGain][i]; + } + else { + return flt->getData(subHash,dbGain,0); + } + } +} + +////////////////////////////////////////////////// + +std::vector<float> +CaloNoiseToolDB::elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const int step) +{ + std::vector<float> sigma; + for(int igain=0;igain<CaloGain::LARNGAIN;++igain) + sigma.push_back(this->elecNoiseRMS(caloDDE,static_cast<CaloGain::CaloGain>(igain),-1,step)); + return sigma; + +} + +////////////////////////////////////////////////// + +std::vector<float> +CaloNoiseToolDB::elecNoiseRMS3gains(const CaloDetDescrElement* caloDDE, + const float /* NMinBias */,const int step) +{ + return this->elecNoiseRMS3gains(caloDDE,step); +} + +////////////////////////////////////////////////// + +VectorContainer* +CaloNoiseToolDB::elecNoiseRMSContainer(const int &iCalo) +{ + msg(MSG::WARNING) << " elecNoiseRMSContainer not implemented " << iCalo << endreq ; + return 0; +} + +////////////////////////////////////////////////// +// new interfaces to enable caching of the pointer to member + +float +CaloNoiseToolDB::elecNoiseRMS(const CaloCell* theCell, + const CaloGain::CaloGain /*gain*/, + const float Nminbias, + const int step) { + return this->elecNoiseRMS(theCell,Nminbias,step); +} + +float +CaloNoiseToolDB::pileupNoiseRMS(const CaloCell* theCell, + const CaloGain::CaloGain /*gain*/, + const float Nminbias, + const int /*step*/) { + return this->pileupNoiseRMS(theCell,Nminbias); +} + +float +CaloNoiseToolDB::totalNoiseRMS(const CaloCell* theCell, + const CaloGain::CaloGain /*gain*/, + const float Nminbias, + const int /* step */) { + return this->totalNoiseRMS(theCell,Nminbias); +} + +float +CaloNoiseToolDB::pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int /*step*/) { + if (!m_cacheValid) this->updateCache(); + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + if (m_cached==ICalorimeterNoiseTool::PILEUPNOISE && (Nminbias == m_Nminbias || Nminbias<0) && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(gain); + return m_noise[igain][i]; + } + else { + float lumi; + if (Nminbias>0) { + lumi=Nminbias/2.3; + } + else { + lumi=m_lumi0; + } + return (this->getB(i,gain)*sqrt(lumi)); + } + +} + +float +CaloNoiseToolDB::totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const int /*step*/) { + if (!m_cacheValid) this->updateCache(); + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + if (m_cached==ICalorimeterNoiseTool::TOTALNOISE && (Nminbias == m_Nminbias || Nminbias<0) && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(gain); + return m_noise[igain][i]; + } else { + float lumi = (Nminbias>0) ? Nminbias/2.3 : m_lumi0; + return this->getDBNoise(i,gain,lumi); + } +} + +float +CaloNoiseToolDB::totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias, + const float energy, + const int /*step*/) { + // std::cout << "totalNoiseRMS e " << energy << " gain " << gain << std::endl; + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + float lumi = (Nminbias>0) ? Nminbias/2.3 : m_lumi0; + float x; + float a = elecNoiseRMS(caloDDE,gain,Nminbias,energy, + ICaloNoiseToolStep::CELLS); + float b = this->getB(i,gain); + + int objver = m_noiseBlobMap[TILE]->getObjVersion(); + if(objver==1){ + //=== Total noise parameterized as + //=== Sigma**2 = a**2 + b**2 * Lumi + x = std::sqrt( a*a + b*b*lumi ); + } + else if (objver==2) { + //== parameterization for pedestal = a + b*Lumi + x = a+b*lumi; + } + else{ + throw CaloCond::VersionConflict("CaloNoiseToolDB::totalNoiseRMS ",objver); + } + return x; +} +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::pileupNoiseRMS(const CaloCell* caloCell, const float Nminbias) +{ + if (!m_cacheValid) this->updateCache(); + Identifier id = caloCell->ID(); + int i = (int)(m_calo_id->calo_cell_hash(id)); + if (i>m_ncell) return -1; + CaloGain::CaloGain calogain = caloCell->gain(); + if (m_cached==ICalorimeterNoiseTool::PILEUPNOISE && (Nminbias == m_Nminbias || Nminbias<0) && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(calogain); + return m_noise[igain][i]; + } + else { + float lumi; + if (Nminbias>0) { + lumi=Nminbias/2.3; + } + else { + lumi=m_lumi0; + } + return (this->getB(i,calogain)*sqrt(lumi)); + } +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::pileupNoiseRMS(const CaloDetDescrElement* caloDDE, + const float Nminbias) +{ + if (!m_cacheValid) this->updateCache(); + int subcalo = caloDDE->getSubCalo(); + if (subcalo < 0 || subcalo >= m_nCalos) return -1; + CaloGain::CaloGain highestGain=m_highestGain[subcalo]; + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + if (m_cached==ICalorimeterNoiseTool::PILEUPNOISE && (Nminbias == m_Nminbias || Nminbias<0) && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(highestGain); + return m_noise[igain][i]; + } + else { + float lumi; + if (Nminbias>0) { + lumi=Nminbias/2.3; + } + else { + lumi=m_lumi0; + } + return (this->getB(i,highestGain)*sqrt(lumi)); + } + +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::totalNoiseRMS(const CaloCell* caloCell, const float Nminbias) +{ + if (!m_cacheValid) this->updateCache(); + Identifier id = caloCell->ID(); + int i = (int)(m_calo_id->calo_cell_hash(id)); + if (i>m_ncell) return -1; + CaloGain::CaloGain calogain = caloCell->gain(); + if (m_cached==ICalorimeterNoiseTool::TOTALNOISE && (Nminbias == m_Nminbias || Nminbias<0) && m_cacheValid) { + int igain=CaloCondUtils::getDbCaloGain(calogain); + return m_noise[igain][i]; + } else { + float lumi = (Nminbias>0) ? Nminbias/2.3 : m_lumi0; + return this->getDBNoise(i,calogain,lumi); + } + + +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::totalNoiseRMS(const CaloDetDescrElement* caloDDE, + const CaloGain::CaloGain gain, + const float Nminbias) +{ + if (!m_cacheValid) this->updateCache(); + int i = (int)(caloDDE->calo_hash()); + if (i>m_ncell) return -1; + if (m_cached==ICalorimeterNoiseTool::TOTALNOISE && (Nminbias == m_Nminbias || Nminbias<0) && m_cacheValid) { + int igain = CaloCondUtils::getDbCaloGain(gain); + return m_noise[igain][i]; + } else { + float lumi = (Nminbias>0) ? Nminbias/2.3 : m_lumi0; + return this->getDBNoise(i,gain,lumi); + } + +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::totalNoiseRMSHighestGain(const CaloCell* caloCell, + const float Nminbias) +{ + return this->totalNoiseRMSHighestGain(caloCell->caloDDE(),Nminbias); +} + +////////////////////////////////////////////////// + +float +CaloNoiseToolDB::totalNoiseRMSHighestGain(const CaloDetDescrElement* caloDDE, + const float Nminbias) +{ + CaloGain::CaloGain highestGain=m_highestGain[caloDDE->getSubCalo()]; + return this->totalNoiseRMS(caloDDE,highestGain,Nminbias); +} + + +CaloGain::CaloGain CaloNoiseToolDB::estimatedGain(const CaloCell* /* caloCell */, + const int & /*step */) { + msg(MSG::WARNING) << " CaloNoiseToolDB::estimatedGain returns INVALIDGAIN " << endreq; + return CaloGain::INVALIDGAIN; +} +CaloGain::CaloGain CaloNoiseToolDB::estimatedGain(const CaloCell* /* caloCell */, + const CaloDetDescrElement* /* caloDDE */, + const int & /*step */){ + msg(MSG::WARNING) << " CaloNoiseToolDB::estimatedGain returns INVALIDGAIN " << endreq; + return CaloGain::INVALIDGAIN; +} +CaloGain::CaloGain CaloNoiseToolDB::estimatedGain(const CaloDetDescrElement* /* caloDDE */, + const float& /* energy */, + const int & /* step */) { + msg(MSG::WARNING) << " CaloNoiseToolDB::estimatedGain returns INVALIDGAIN " << endreq; + return CaloGain::INVALIDGAIN; +} + +StatusCode CaloNoiseToolDB::LoadCalibration(IOVSVC_CALLBACK_ARGS) { + msg(MSG::WARNING) << " CaloNoiseToolDB::LoadCalibration dummy method " << endreq; + return StatusCode::SUCCESS; +} + + +// GU: below are temporary implementations, waiting for non-gaussian noise description in DB (at least for Tiles) + +///////////////////////////////////////////////////////////////////////// + +bool CaloNoiseToolDB::isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling /* symmetryHandling */, + CalorimeterNoiseType type) +{ + float noise_cut; + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + if(caloDDE->getSubCalo()==CaloCell_ID::TILE) { + noise_cut = fabs(sigmaCut*this->getNoise(caloCell, (float) caloCell->e(), type)); + } else { + noise_cut = fabs(sigmaCut*this->getNoise(caloCell, type)); + } + float energy = fabs(caloCell->e()); + return (energy>noise_cut); +} + +//////////////////////////////////////////////////////////////////// + +float CaloNoiseToolDB::getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type) +{ + double rms = this->getNoise(caloCell,type); + return RandGauss::shoot(engine,0.,rms); +} + +////////////////////////////////////////////////////////////////////////////////////// + +float CaloNoiseToolDB::getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling /*symmetryHandling*/, + CalorimeterNoiseType type ) +{ + const CaloDetDescrElement* caloDDE = caloCell->caloDDE(); + float eqnoise; + if(caloDDE->getSubCalo()==CaloCell_ID::TILE) { + eqnoise = this->getNoise(caloCell, (float) caloCell->e(), type); + } else { + eqnoise = this->getNoise(caloCell, type); + } + return eqnoise; + // simple implementation for gaussian noise + // return this->getNoise(caloCell,type); +} diff --git a/Calorimeter/CaloTools/src/SimpleNoiseTool.cxx b/Calorimeter/CaloTools/src/SimpleNoiseTool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..c0ed4d62b76a570d39d424ff0414c1202ef5203f --- /dev/null +++ b/Calorimeter/CaloTools/src/SimpleNoiseTool.cxx @@ -0,0 +1,94 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "GaudiKernel/Service.h" +#include "GaudiKernel/MsgStream.h" + +#include "StoreGate/StoreGateSvc.h" + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Random/RandomEngine.h" +#include "CLHEP/Random/RandGauss.h" + + +#include "CaloTools/SimpleNoiseTool.h" + +#include "CaloEvent/CaloCell.h" + +std::map<float, CaloDetDescrElement> NoiseMap; + +SimpleNoiseTool::SimpleNoiseTool(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool(type,name,parent) +{ + + declareInterface<ICalorimeterNoiseTool>(this); + + MsgStream report(msgSvc(),name); + report << MSG::INFO << " SimpleNoiseTool start" << endreq; +} + +SimpleNoiseTool::~SimpleNoiseTool() +{ } + +StatusCode SimpleNoiseTool::initialize() +{ + MsgStream report(msgSvc(),name()); + report << MSG::INFO << " SimpleNoiseTool initialize()" << endreq; + + + return StatusCode::SUCCESS; +} + +float SimpleNoiseTool::getNoise(const CaloCell* /*aCell*/, CalorimeterNoiseType /*type*/) +{ + float noise=10.0; + + MsgStream report(msgSvc(),name()); + // report << MSG::INFO + // << "::getNoise::" << aCell->caloDDE() << " : " << noise << "\n"; + return noise; +} + +float SimpleNoiseTool::getNoise(const CaloDetDescrElement* /*caloDDE*/, CalorimeterNoiseType /*type*/) +{ + float noise=10.0; + + MsgStream report(msgSvc(),name()); + // report << MSG::INFO + // << "::getNoise::" << caloDDE << " : " << noise << "\n"; + return noise; +} + +///////////////////////////////////////////////////////////////////////// + +bool SimpleNoiseTool::isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling, + CalorimeterNoiseType type) +{ + float noise_cut = fabs(sigmaCut*this->getEffectiveSigma(caloCell, symmetryHandling, type)); + float energy = fabs(caloCell->e()); + return (energy>noise_cut); + +} + +//////////////////////////////////////////////////////////////////// + +float SimpleNoiseTool::getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type) +{ + double rms = this->getNoise(caloCell,type); + return CLHEP::RandGauss::shoot(engine,0.,rms); +} + +////////////////////////////////////////////////////////////////////////////////////// + +float SimpleNoiseTool::getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling /*symmetryHandling*/, + CalorimeterNoiseType type ) +{ + // simple implementation for gaussian noise + return this->getNoise(caloCell,type); +} diff --git a/Calorimeter/CaloTools/src/SimpleNoiseToolFromTextFile.cxx b/Calorimeter/CaloTools/src/SimpleNoiseToolFromTextFile.cxx new file mode 100755 index 0000000000000000000000000000000000000000..e648ea90032c58f3f2f4b760fe2c708fc380fda2 --- /dev/null +++ b/Calorimeter/CaloTools/src/SimpleNoiseToolFromTextFile.cxx @@ -0,0 +1,223 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "GaudiKernel/Service.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGateSvc.h" +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Random/RandomEngine.h" +#include "CLHEP/Random/RandGauss.h" +#include "CaloTools/SimpleNoiseToolFromTextFile.h" +#include "CaloEvent/CaloCell.h" +#include "CaloDetDescr/CaloDetDescrElement.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + +#include <iomanip> +#include <iostream> +#include <fstream> +#include <string> + +using CLHEP::MeV; +using CLHEP::RandGauss; + +SimpleNoiseToolFromTextFile::SimpleNoiseToolFromTextFile(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool(type,name,parent) + , m_cellNoiseFileName("") + , m_cellNoiseUnits(MeV) + , m_cellNoiseDefault(100.*MeV) + , m_cellNoiseDefaultWarning(true) +{ + declareInterface<ICalorimeterNoiseTool>(this); + + declareProperty("CellNoiseFileName", m_cellNoiseFileName="/afs/cern.ch/user/h/hectbmon/public/tb/aug02/noise/H6_2002NoiseMuons.dat"); + declareProperty("CellNoiseUnits", m_cellNoiseUnits=MeV); + declareProperty("CellNoiseDefault", m_cellNoiseDefault=100*MeV); + declareProperty("CellNoiseDefaultWarning", m_cellNoiseDefaultWarning=true); +} + +SimpleNoiseToolFromTextFile::~SimpleNoiseToolFromTextFile() +{ } + +StatusCode SimpleNoiseToolFromTextFile::initialize() +{ + MsgStream report(msgSvc(),name()); + + StoreGateSvc* detStore; + if (service("DetectorStore", detStore).isFailure()) { + report << MSG::ERROR << "Unable to access DetectoreStore" << endreq ; + return StatusCode::FAILURE; + } + + const IGeoModelSvc *geoModel=0; + StatusCode sc = service("GeoModelSvc", geoModel); + if(sc.isFailure()) + { + report << MSG::ERROR << "Could not locate GeoModelSvc" << endreq; + return sc; + } + + // dummy parameters for the callback: + int dummyInt=0; + std::list<std::string> dummyList; + + if (geoModel->geoInitialized()) + { + return geoInit(dummyInt,dummyList); + } + else + { + sc = detStore->regFcn(&IGeoModelSvc::geoInit, + geoModel, + &SimpleNoiseToolFromTextFile::geoInit,this); + if(sc.isFailure()) + { + report << MSG::ERROR << "Could not register geoInit callback" << endreq; + return sc; + } + } + return sc; +} + +StatusCode +SimpleNoiseToolFromTextFile::geoInit(IOVSVC_CALLBACK_ARGS) +{ + MsgStream report(msgSvc(),name()); + + report << MSG::INFO + << "SimpleNoiseToolFromTextFile initialize()" + << endreq; + + // access calo detector managers + m_caloDDM = CaloDetDescrManager::instance(); + + // access calo identifier helper + m_caloIDH = m_caloDDM->getCaloCell_ID(); + + // open noise file + std::ifstream fStream(m_cellNoiseFileName.c_str()); + + // exit if the file cannot be opened + if (!fStream.is_open()) { + report << MSG::ERROR + << "Failed to open file: " << m_cellNoiseFileName + << endreq; + return StatusCode::FAILURE; + } + + // read the cell noise from file + std::string line; + std::istringstream inStream; + while (getline(fStream, line)) { // read line into line + if (line[0] != '#') { // skip line if starting with # + inStream.clear(); + inStream.str(line); // use line as input stream + int offlineID; // this is theID.get_compact() + float cellNoise; // noise units are specified by a the jobOption CellNoiseUnits + if (inStream >> offlineID >> cellNoise) { // read in offlineID and cellNoise + // sync noise units + cellNoise *= m_cellNoiseUnits; + // make the Identifier + Identifier theID(offlineID); + // fill the noise map + m_cellNoise[theID] = cellNoise; + + report << MSG::DEBUG + << "Cell " << theID.get_compact() + << std::setbase(16) << std::setiosflags(std::ios_base::showbase) + << " : " << theID.get_compact() << std::setbase(10) + << " : " << std::setw(17) << m_caloIDH->show_to_string(theID) + << " : noise = " << cellNoise/MeV << " MeV" + << endreq; + } else { + report << MSG::ERROR + << "bad format in cell noise file " << m_cellNoiseFileName + << endreq; + return StatusCode::FAILURE; + } + } + } + + fStream.close(); + + report << MSG::INFO + << "SimpleNoiseToolFromTextFile: cell noise values read from file " + << m_cellNoiseFileName + << endreq; + + return StatusCode::SUCCESS; +} + +float SimpleNoiseToolFromTextFile::getNoise(const CaloCell* aCell, CalorimeterNoiseType /*type*/) +{ + Identifier tmp=aCell->ID(); + return getNoiseHelper(tmp); +} + +float SimpleNoiseToolFromTextFile::getNoise(const CaloDetDescrElement* caloDDE, CalorimeterNoiseType /*type*/) +{ + Identifier tmp=caloDDE->identify(); + return getNoiseHelper(tmp); +} + +float SimpleNoiseToolFromTextFile::getNoiseHelper(Identifier id) +{ + MsgStream report( msgSvc(), name() ); + + std::map<Identifier, float>::iterator itr = m_cellNoise.find(id); + if (itr != m_cellNoise.end()) { + // cell is in the map + // return the noise + return itr->second; + } else { + // cell not in the map + // report this if requested + if (m_cellNoiseDefaultWarning) + report << MSG::WARNING + << "SimpleNoiseToolFromTextFile: default noise " + << m_cellNoiseDefault/MeV + << " MeV for cell " + << id.get_compact() + << std::setbase(16) << std::setiosflags(std::ios_base::showbase) + << " : " << id.get_compact() << std::setbase(10) + << " : " << std::setw(17) << m_caloIDH->show_to_string(id) + << endreq; + // return the default noise value set by jobOption + return m_cellNoiseDefault; + } +} + + +///////////////////////////////////////////////////////////////////////// + +bool SimpleNoiseToolFromTextFile::isEOverNSigma(const CaloCell* caloCell, float sigmaCut , + CalorimeterNoiseSymmetryHandling symmetryHandling, + CalorimeterNoiseType type) +{ + float noise_cut = fabs(sigmaCut*this->getEffectiveSigma(caloCell, symmetryHandling,type)); + float energy = fabs(caloCell->e()); + return (energy>noise_cut); + +} + +//////////////////////////////////////////////////////////////////// + +float SimpleNoiseToolFromTextFile::getRandomisedE(const CaloCell* caloCell , CLHEP::HepRandomEngine* engine, CalorimeterNoiseType type) +{ + double rms = this->getNoise(caloCell,type); + return RandGauss::shoot(engine,0.,rms); +} + +//////////////////////////////////////////////////////////////////// + +float SimpleNoiseToolFromTextFile::getEffectiveSigma(const CaloCell* caloCell, + CalorimeterNoiseSymmetryHandling /*symmetryHandling*/, + CalorimeterNoiseType type ) +{ + // simple implementation for gaussian noise + return this->getNoise(caloCell,type); +} + diff --git a/Calorimeter/CaloTools/src/components/CaloTools_entries.cxx b/Calorimeter/CaloTools/src/components/CaloTools_entries.cxx new file mode 100755 index 0000000000000000000000000000000000000000..9b1b3ce0ff23c4406fd8c6813243a644a5f95536 --- /dev/null +++ b/Calorimeter/CaloTools/src/components/CaloTools_entries.cxx @@ -0,0 +1,29 @@ +#include "CaloTools/CaloCompactCellTool.h" +#include "CaloTools/CaloNoiseTool.h" +#include "CaloTools/CaloMBAverageTool.h" +#include "CaloTools/CaloNoiseToolDB.h" +#include "CaloTools/SimpleNoiseTool.h" +#include "CaloTools/SimpleNoiseToolFromTextFile.h" +#include "CaloTools/CaloAffectedTool.h" +#include "CaloTools/CaloLumiBCIDTool.h" +#include "GaudiKernel/DeclareFactoryEntries.h" + +DECLARE_TOOL_FACTORY( CaloCompactCellTool ) +DECLARE_TOOL_FACTORY( CaloNoiseTool ) +DECLARE_TOOL_FACTORY( CaloMBAverageTool ) +DECLARE_TOOL_FACTORY( CaloNoiseToolDB ) +DECLARE_TOOL_FACTORY( SimpleNoiseTool ) +DECLARE_TOOL_FACTORY( SimpleNoiseToolFromTextFile ) +DECLARE_TOOL_FACTORY( CaloAffectedTool ) +DECLARE_TOOL_FACTORY( CaloLumiBCIDTool ) + +DECLARE_FACTORY_ENTRIES(CaloTools) { + DECLARE_TOOL( CaloCompactCellTool ) + DECLARE_TOOL( CaloNoiseTool ) + DECLARE_TOOL( CaloMBAverageTool ) + DECLARE_TOOL( CaloNoiseToolDB ) + DECLARE_TOOL( SimpleNoiseTool ) + DECLARE_TOOL( SimpleNoiseToolFromTextFile ) + DECLARE_TOOL( CaloAffectedTool ) + DECLARE_TOOL( CaloLumiBCIDTool ) +} diff --git a/Calorimeter/CaloTools/src/components/CaloTools_load.cxx b/Calorimeter/CaloTools/src/components/CaloTools_load.cxx new file mode 100755 index 0000000000000000000000000000000000000000..6daa57fe1e8c1036d6c99f329c5b1de02b0c8101 --- /dev/null +++ b/Calorimeter/CaloTools/src/components/CaloTools_load.cxx @@ -0,0 +1,3 @@ +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES(CaloTools) diff --git a/Calorimeter/CaloTools/test/CaloCellPackerUtils_test.cxx b/Calorimeter/CaloTools/test/CaloCellPackerUtils_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1b5d3fc4e28f1d81441f9a2a71ae9f4f06a79ded --- /dev/null +++ b/Calorimeter/CaloTools/test/CaloCellPackerUtils_test.cxx @@ -0,0 +1,72 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCellPackerUtils_test.cxx,v 1.1 2007-11-08 18:14:23 ssnyder Exp $ +/** + * @file CaloCellPackerUtils_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2007 + * @brief Component test for CaloCellPackerUtils. + */ + +#undef NDEBUG + + +#include "CaloTools/CaloCellPackerUtils.h" +#include <cassert> +#include <cmath> +#include <cstdio> +#include <cstdlib> + + +void compare_float (float x1, float x2, float thresh=1e-9) +{ + float den = std::abs(x1) + std::abs(x2); + if (den == 0) den = 1; + if (std::abs(x1-x2) / den > thresh) { + printf ("Float miscompare: %f %f\n", x1, x2); + std::abort(); + } +} + + +void test1() +{ + CaloCellPackerUtils::Bitfield bf (0x00f0); + assert (bf.in (5) == 0x0050); + assert (bf.in (0x123) == 0x0030); + assert (bf.out (0x1234) == 3); + + int underflow; + CaloCellPackerUtils::Floatfield ff (0x00f0, 2, 4); + assert (ff.in (2.5) == 0x0040); + compare_float (ff.out (0x0040, underflow), 2.5625); + assert (underflow == 0); + assert (ff.in (0) == 0); + compare_float (ff.out (0, underflow), 2); + assert (underflow == 1); + assert (ff.in (10) == 0x00f0); + compare_float (ff.out (0x00f0, underflow), 3.9375); + assert (underflow == 0); + + CaloCellPackerUtils::Floatfield2 ff2 (0x00f0, 4); + assert (ff2.in (2.5) == 0x00a0); + compare_float (ff2.out (0x00a0), 2.625); + assert (ff2.in (0) == 0); + compare_float (ff2.out (0), 0); + assert (ff2.in (10) == 0x00f0); + compare_float (ff2.out (0x00f0), 3.875); +} + + +int main() +{ + test1(); + return 0; +} + + +// This package builds a component library, so we don't normally +// link against the library. So just include this here. +#include "../src/CaloCellPackerUtils.cxx" diff --git a/Calorimeter/CaloTools/test/CaloCompactCellTool_test.cxx b/Calorimeter/CaloTools/test/CaloCompactCellTool_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..eec816dae89e0133ec13156245f11d5908791bb5 --- /dev/null +++ b/Calorimeter/CaloTools/test/CaloCompactCellTool_test.cxx @@ -0,0 +1,1274 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: CaloCompactCellTool_test.cxx,v 1.12 2009-03-31 19:04:04 ssnyder Exp $ +/** + * @file CaloCompactCellTool_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2007 + * @brief Component test for CaloCompactCellTool. + */ + +#undef NDEBUG + +#include "CaloTools/CaloCompactCellTool.h" +#include "CaloTools/CaloCellPacker_400_500.h" +#include "CaloTriggerTool/ICaloSuperCellIDTool.h" +#include "CaloEvent/CaloCellContainer.h" +#include "CaloEvent/CaloCell.h" +#include "TileEvent/TileCell.h" +#include "LArRecEvent/LArCell.h" +#include "CaloDetDescr/CaloDetectorElements.h" +#include "CaloDetDescr/CaloDetDescriptor.h" +#include "CaloDetDescr/CaloDetDescrManager.h" +#include "CaloIdentifier/CaloCell_ID.h" +#include "CaloIdentifier/CaloCell_SuperCell_ID.h" +#include "CaloIdentifier/LArEM_ID.h" +#include "CaloIdentifier/LArHEC_ID.h" +#include "CaloIdentifier/LArFCAL_ID.h" +#include "CaloIdentifier/LArMiniFCAL_ID.h" +#include "CaloIdentifier/TileID.h" +#include "CaloIdentifier/CaloIdManager.h" +#include "StoreGate/StoreGateSvc.h" +#include "AthAllocators/Arena.h" +#include "AthAllocators/ArenaHeaderGaudiClear.h" +#include "IdDictParser/IdDictParser.h" +#include "GaudiKernel/Bootstrap.h" +#include "TestTools/initGaudi.h" +#include "AthenaKernel/errorcheck.h" +#include "boost/foreach.hpp" +#include <vector> +#include <map> +#include <algorithm> +#include <sstream> +#include <iostream> +#include <cmath> +#include <sys/resource.h> +#include <sys/time.h> + +using CLHEP::MeV; +using CLHEP::GeV; +using CLHEP::TeV; + + +typedef long double efloat_t; + + +SG::Arena* arena = 0; + +CaloDetDescrManager* g_mgr = 0; +IToolSvc* g_toolsvc = 0; +ISvcLocator* g_svcloc = 0; + + +#undef CHECK +#define CHECK(s) do { if (!(s).isSuccess()) {printf("error: %s\n", #s);exit(1);}} while(0) + + +// Dufus-quality RNG, using LCG. Constants from numerical recipies. +// I don't particularly care about RNG quality here, just about +// getting something that's reproducible. + +#include <stdint.h> +uint32_t seed = 1; +uint32_t rngmax = static_cast<uint32_t> (-1); +uint32_t rng() +{ + seed = (1664525*seed + 1013904223); + return seed; +} + +efloat_t randf (float rmax) +{ + return static_cast<efloat_t>(rng()) / rngmax * rmax; +} +int randi (int rmax) +{ + return static_cast<int> (randf(rmax)); +} + + + + +CaloCell_ID* make_helper () +{ + TileID* tile_id = new TileID; + LArEM_ID* em_id = new LArEM_ID; + LArHEC_ID* hec_id = new LArHEC_ID; + LArFCAL_ID* fcal_id = new LArFCAL_ID; + LArMiniFCAL_ID* minifcal_id = new LArMiniFCAL_ID; + + IdDictParser* parser = new IdDictParser; + parser->register_external_entity ("LArCalorimeter", + "IdDictLArCalorimeter.xml"); + IdDictMgr& idd = parser->parse ("IdDictParser/ATLAS_IDS.xml"); + em_id->set_do_neighbours (false); + em_id->initialize_from_dictionary (idd); + hec_id->initialize_from_dictionary (idd); + fcal_id->set_do_neighbours (false); + fcal_id->initialize_from_dictionary (idd); + minifcal_id->set_do_neighbours (false); + minifcal_id->initialize_from_dictionary (idd); + tile_id->set_do_neighbours (false); + tile_id->initialize_from_dictionary (idd); + + CaloCell_ID* calo_helper = new CaloCell_ID (em_id, + hec_id, + fcal_id, + minifcal_id, + tile_id); + calo_helper->initialize_from_dictionary (idd); + return calo_helper; +} + + +CaloCell_SuperCell_ID* make_sc_helper () +{ + Tile_SuperCell_ID* tile_id = new Tile_SuperCell_ID; + LArEM_SuperCell_ID* em_id = new LArEM_SuperCell_ID; + LArHEC_SuperCell_ID* hec_id = new LArHEC_SuperCell_ID; + LArFCAL_SuperCell_ID* fcal_id = new LArFCAL_SuperCell_ID; + LArMiniFCAL_ID* minifcal_id = new LArMiniFCAL_ID; + + IdDictParser* parser = new IdDictParser; + parser->register_external_entity ("LArCalorimeter", + "IdDictLArCalorimeter.xml"); + IdDictMgr& idd = parser->parse ("IdDictParser/ATLAS_IDS.xml"); + em_id->set_do_neighbours (false); + em_id->initialize_from_dictionary (idd); + hec_id->initialize_from_dictionary (idd); + fcal_id->set_do_neighbours (false); + fcal_id->initialize_from_dictionary (idd); + minifcal_id->set_do_neighbours (false); + minifcal_id->initialize_from_dictionary (idd); + tile_id->set_do_neighbours (false); + tile_id->initialize_from_dictionary (idd); + + CaloCell_SuperCell_ID* calo_helper = + new CaloCell_SuperCell_ID (em_id, + hec_id, + fcal_id, + minifcal_id, + tile_id); + calo_helper->initialize_from_dictionary (idd); + return calo_helper; +} + + +CaloIdManager* make_idmgr (const CaloCell_ID* cellhelper, + const CaloCell_SuperCell_ID* schelper) +{ + CaloIdManager* idmgr = new CaloIdManager; + idmgr->set_helper (cellhelper); + idmgr->set_helper (cellhelper->em_idHelper()); + idmgr->set_helper (cellhelper->hec_idHelper()); + idmgr->set_helper (cellhelper->fcal_idHelper()); + idmgr->set_helper (cellhelper->tile_idHelper()); + + idmgr->set_helper (schelper); + idmgr->set_helper (schelper->em_idHelper()); + idmgr->set_helper (schelper->hec_idHelper()); + idmgr->set_helper (schelper->fcal_idHelper()); + idmgr->set_helper (schelper->tile_idHelper()); + + return idmgr; +} + + +typedef std::map<Identifier, CaloDetDescriptor*> ddmap_t; +ddmap_t ddmap_ol; +ddmap_t ddmap_sc; +CaloDetDescriptor* find_dd (int hashid, + const CaloDetDescrManager_Base* mgr) +{ + const CaloCell_Base_ID* helper = mgr->getCaloCell_ID(); + Identifier id = helper->cell_id (hashid); + Identifier reg_id; + int subcalo = helper->sub_calo (id); + if (subcalo == CaloCell_ID::TILE) { + int section = helper->section (id); + int side = helper->side (id); + reg_id = helper->region_id (subcalo, section, side, 0); + } + else { + int sampling = helper->sampling (id); + int posneg = helper->pos_neg (id); + int region = helper->region (id); + reg_id = helper->region_id (subcalo, posneg, sampling, region); + } + ddmap_t& ddmap = helper->is_supercell(id) ? ddmap_sc : ddmap_ol; + CaloDetDescriptor* dd = ddmap[reg_id]; + if (!dd) { + dd = new CaloDetDescriptor (reg_id, helper->tile_idHelper(), helper); + ddmap[reg_id] = dd; + } + return dd; +} + + +CaloCell* make_cell (int hashid, + CaloDetDescrManager* mgr) +{ + CaloDetDescriptor* descr = find_dd (hashid, mgr); + CaloDetDescrElement* dde = new DummyDetDescrElement (hashid - + descr->caloCellMin(), + 0, + 0, + descr); + mgr->add (dde); + + if (descr->is_tile()) { + int gain1; + efloat_t ene1; + switch (randi(2)) { + case 0: + gain1 = TileID::LOWGAIN; + ene1 = randf(3200*GeV)-20*GeV; + break; + case 1: + default: + gain1 = TileID::HIGHGAIN; + ene1 = randf(50*GeV)-20*GeV; + break; + } + int qbit1 = randi(32); + int qual1 = ((qbit1 & TileCell::MASK_BADCH) != 0) ? 255 : randi(256); + int time1 = 0; + if (randi(2)>0) { + qbit1 |= TileCell::KEEP_TIME; + time1 = (randi(2000)-1000); + } + + int gain2; + efloat_t ene2; + switch (randi(3)) { + case 0: + gain2 = TileID::LOWGAIN; + ene2 = randf(3200*GeV)-20*GeV; + break; + case 1: + gain2 = TileID::HIGHGAIN; + ene2 = randf(50*GeV)-20*GeV; + break; + default: + gain2 = CaloGain::INVALIDGAIN; + ene2 = 0; + break; + } + int qbit2 = randi(32); + int qual2 = ((qbit2 & TileCell::MASK_BADCH) != 0) ? 255 : randi(256); + int time2 = 0; + if (randi(2)>0) { + qbit2 |= TileCell::KEEP_TIME; + time2 = (randi(2000)-1000); + } + + if (((gain1 == TileID::LOWGAIN && gain2 == TileID::HIGHGAIN) || + (gain1 == TileID::HIGHGAIN && gain2 == TileID::LOWGAIN)) && + ene1 + ene2 > 400*GeV) + { + float scale = 399*GeV / (ene1 + ene2); + ene1 *= scale; + ene2 *= scale; + } + + if (gain1 == TileID::HIGHGAIN && gain2 == TileID::HIGHGAIN && + ene1 + ene2 > 50*GeV) + { + efloat_t scale = 49*GeV / (ene1 + ene2); + ene1 *= scale; + ene2 *= scale; + } + + if ( ((qbit1 & qbit2) & TileCell::MASK_BADCH) != 0 ) { // both channels masked + time1 = time2 = 0; + ene1 = ene2 = 0.512932 * MeV; + gain1 = gain2 = TileID::LOWGAIN; + } + + return new TileCell (dde, + ene1, ene2, + time1, time2, + qual1, qual2, + qbit1, qbit2, + gain1, gain2); + } + else { + CaloGain::CaloGain gain = CaloGain::INVALIDGAIN; + efloat_t energy = 0; + int quality = randi(65536); + int provenance = randi(0x2000); + float time = 0; + // Good quality? Take 10% to be bad. + if (randi(10) != 0) { + provenance |= 0x2000; + switch (randi(3)) { + case 0: + gain = CaloGain::LARHIGHGAIN; + energy = randf(60*GeV) - 16*GeV; + break; + case 1: + gain = CaloGain::LARMEDIUMGAIN; + energy = randf(360*GeV) + 40*GeV; + break; + case 2: + default: + gain = CaloGain::LARLOWGAIN; + energy = randf(3000*GeV) + 40*GeV; + break; + } + time = randf(2000) - 1000; + } + return new CaloCell (dde, energy, time, quality, provenance, gain); + } +} + + +std::vector<CaloCell*> make_cells (CaloDetDescrManager* mgr) +{ + size_t hashmax = mgr->getCaloCell_ID()->calo_cell_hash_max(); + std::vector<CaloCell*> v; + v.reserve (hashmax); + for (size_t i = 0; i < hashmax; i++) + v.push_back (make_cell (i, mgr)); + + // Give a few cells off-scale energies, to test saturation. + IdentifierHash tilemin, tilemax; + mgr->getCaloCell_ID()->calo_cell_hash_range (CaloCell_ID::TILE, + tilemin, tilemax); + assert (tilemax <= v.size()); + assert (tilemin <= tilemax); + for (size_t i = 0; i < 10; i++) { + CaloCell* cell = v[randi(tilemin)]; + assert ( ! cell->caloDDE()->is_tile()); + cell->setGain ((i&2) ? CaloGain::LARLOWGAIN : CaloGain::LARHIGHGAIN); + cell->setEnergy ((((int)i&1)*2-1) * 4000*GeV); + } + for (size_t i = 0; i < 8; i++) { + TileCell* cell = + dynamic_cast<TileCell*>(v[tilemin + randi(tilemax-tilemin)]); + assert (cell != 0); + assert (cell->caloDDE()->is_tile()); + int pmt = (i&2)>>1; + cell->addEnergy ((((int)i&1)*2-1) * 8000*GeV, pmt, + (i&4) ? TileID::LOWGAIN : TileID::HIGHGAIN); + } + return v; +} + + +void fill_cells_rand (int n, + const std::vector<CaloCell*>& cells, + CaloCellContainer& cont) +{ + std::vector<CaloCell*> tmp = cells; + std::random_shuffle (tmp.begin(), tmp.end(), randi); + for (int i = 0; i < n; i++) + cont.push_back (tmp[i]); +} + + +void fill_cells_clustery (int n, + const std::vector<CaloCell*>& cells, + CaloCellContainer& cont) +{ + std::vector<CaloCell*> tmp = cells; + while (n > 0) { + int idx = randi (tmp.size()); + int nmax = std::min ((unsigned int)n, (unsigned int)tmp.size() - idx); + assert (nmax > 0); + int thisn = randi (nmax) + 1; + for (int i = idx; i < idx + thisn; i++) + cont.push_back (tmp[i]); + tmp.erase (tmp.begin()+idx, tmp.begin()+idx+thisn); + n -= thisn; + } +} + + +CaloCellContainer* fill_cells (int n, + const std::vector<CaloCell*>& cells, + bool clustery, + bool ordered) +{ + CaloCellContainer* cont = new CaloCellContainer (SG::VIEW_ELEMENTS); + if (clustery) + fill_cells_clustery (n, cells, *cont); + else + fill_cells_rand (n, cells, *cont); + + if (ordered) { + cont->order(); + cont->updateCaloIterators(); + } + return cont; +} + + +CaloCellContainer* fill_supercells (const std::vector<CaloCell*>& cells) +{ + CaloCellContainer* cont = new CaloCellContainer; + + ICaloSuperCellIDTool* sctool = 0; + CHECK( g_toolsvc->retrieveTool ("CaloSuperCellIDTool", sctool) ); + + StoreGateSvc* detstore = 0; + CHECK( g_svcloc->service ("DetectorStore", detstore) ); + const CaloIdManager* idmgr = 0; + CHECK( detstore->retrieve (idmgr, "CaloIdManager") ); + const CaloCell_SuperCell_ID* schelper = + idmgr->getCaloCell_SuperCell_ID(); + + CaloSuperCellDetDescrManager* scmgr = 0; + CHECK( detstore->retrieve (scmgr, "CaloSuperCellMgr") ); + + std::vector<CaloCell*> scells (schelper->calo_cell_hash_max()); + BOOST_FOREACH (const CaloCell* cell, cells) { + Identifier scid = sctool->offlineToSuperCellID (cell->ID()); + if (!scid.is_valid()) continue; + IdentifierHash hash = schelper->calo_cell_hash (scid); + assert (hash < scells.size()); + if (scells[hash] == 0) { + const CaloDetDescrElement* dde = scmgr->get_element (hash); + if (!dde) { + CaloDetDescriptor* descr = find_dd (hash, scmgr); + CaloDetDescrElement* dde_nc = + new DummyDetDescrElement (hash - + descr->caloCellMin(), + 0, + 0, + descr); + scmgr->add (dde_nc); + dde = dde_nc; + } + CaloGain::CaloGain gain = cell->gain(); + switch (gain) + { + case CaloGain::TILELOWLOW: + case CaloGain::TILELOWHIGH: + case CaloGain::TILEONELOW: + gain = CaloGain::LARLOWGAIN; + break; + case CaloGain::TILEHIGHHIGH: + case CaloGain::TILEHIGHLOW: + case CaloGain::TILEONEHIGH: + gain = CaloGain::LARHIGHGAIN; + break; + default: + break; + } + scells[hash] = new CaloCell (dde, + cell->energy(), + cell->provenance() & 0x2000 ? + cell->time() : 0, + cell->quality(), + cell->provenance() & 0x3fff, + gain); + } + else if (scells[hash]->gain() != CaloGain::INVALIDGAIN) { + scells[hash]->setEnergy (scells[hash]->energy() + cell->energy()); + } + } + + BOOST_FOREACH (CaloCell* cell, scells) { + cont->push_back (cell); + } + + cont->order(); + cont->updateCaloIterators(); + return cont; +} + + +void compare_float (float x1, float x2, + const std::string& what, + float thresh=0.01) +{ + float den = std::abs(x1) + std::abs(x2); + if (den == 0) den = 1; + if (den < 1e-3) den = 1e-3; + if (std::abs(x1-x2) / den > thresh) { + printf ("Float %s miscompare: %f %f\n", what.c_str(), x1, x2); + std::abort(); + } +} + + +void compare_lar_energy (int hash, float e1, float e2, float prec) +{ + std::ostringstream ss; + ss << "energy " << hash; + if (e1 > 3.2*TeV) + compare_float (3.2*TeV, e2, ss.str(), prec); + else if (e1 < -3.2*TeV) + compare_float (-3.2*TeV, e2, ss.str(), prec); + else + compare_float (e1, e2, ss.str(), prec); +} + + +float tile_ele (const TileCell* c, int pmt) +{ + if (pmt) + return c->ene2(); + return c->ene1(); +} + + +int tile_gain (const TileCell* c, int pmt) +{ + if (pmt) + return c->gain2(); + return c->gain1(); +} + + +void compare_tile_energy (const TileCell* c1, const TileCell* c2, + int pmt, + const char* what) +{ + float max = 3.2*TeV; + if (tile_gain (c2, pmt) == TileID::HIGHGAIN) + max = 50*GeV; + + float prec = 0.01; + if (fabs (c2->ene1() - c2->ene2()) > 30*GeV) prec = 0.02; + + float e1 = tile_ele (c1, pmt); + float e2 = tile_ele (c2, pmt); + + if (e1 > max) + compare_float (max, e2, what, prec); + else if (e1 < -max) + compare_float (-max, e2, what, prec); + else + compare_float (e1, e2, what, prec); +} + + +void compare_lar (const CaloCell* cell1, const CaloCell* cell2, + int version) +{ + const CaloDetDescrElement* dde = cell1->caloDDE(); + + float prec = 0.01; + if (fabs(cell1->energy()) < 0.1) + prec = 0.1; + else if (fabs(cell1->energy()) < 10) { + if (dde->getSubCalo() == CaloCell_ID::LARHEC) + prec = 0.02; + else + prec = 0.015; + } + + if (dde->getSubCalo() == CaloCell_ID::TILE) + prec = 0.03; // supercell + + compare_lar_energy (dde->calo_hash(), + cell1->energy(), cell2->energy(), prec); + + std::ostringstream twhat; + twhat << "time " << dde->calo_hash(); + compare_float (cell1->time(), cell2->time(), twhat.str()); + assert (cell1->gain() == cell2->gain()); + + // Test quality flag. + assert ((cell1->provenance()&0x2000) == (cell2->provenance()&0x2000)); + + if (version <= ICaloCompactCellTool::VERSION_400) { + // Quality not saved. + assert (cell2->quality() == 0); + } + else { + assert (cell1->provenance() == cell2->provenance()); + + // Quality saved if good flag is set. + if ((cell1->provenance() & 0x2000) != 0) { + assert (cell1->quality() == cell2->quality()); + } + else { + assert (cell2->quality() == 0); + } + } +} + + +void compare_tile (const TileCell* cell1, const TileCell* cell2, + int version) +{ + assert (cell1->gain1() == cell2->gain1()); + assert (cell1->gain2() == cell2->gain2()); + compare_tile_energy (cell1, cell2, 0, "ene1"); + compare_float (cell1->time1(), cell2->time1(), "time1", 0.1); + + assert ((cell1->qbit1() >= TileCell::KEEP_TIME) == + (cell2->qbit1() >= TileCell::KEEP_TIME)); + + if (version < ICaloCompactCellTool::VERSION_502 ) { + assert ((cell2->qbit1() & 0x1F) == 0); // Provenance not saved. + } + else { + assert ((cell1->qbit1() & 0x1F) == (cell2->qbit1() & 0x1F)); + } + + if (version < ICaloCompactCellTool::VERSION_502 ) { + assert (cell2->qual1() == 0); // Quality not saved. + } else { + if (cell1->qbit1() < TileCell::KEEP_TIME && + (cell1->qbit2() < TileCell::KEEP_TIME || cell1->gain2() == CaloGain::INVALIDGAIN)) { + if ((cell1->qbit1() & TileCell::MASK_BADCH) != 0) + assert (cell2->qual1() == 255); // Quality is bad. + else + assert (cell2->qual1() == 0); // Quality is good. + } else { + assert (cell1->qual1() == cell2->qual1()); + } + } + + if (cell1->gain2() != CaloGain::INVALIDGAIN) { + compare_tile_energy (cell1, cell2, 1, "ene2"); + compare_float (cell1->time2(), cell2->time2(), "time2", 0.1); + assert ((cell1->qbit2() >= TileCell::KEEP_TIME) == + (cell2->qbit2() >= TileCell::KEEP_TIME)); + + if (version < ICaloCompactCellTool::VERSION_502 ) { + assert ((cell2->qbit2() & 0x1F) == 0); // Provenance not saved. + } + else { + assert ((cell1->qbit2() & 0x1F) == (cell2->qbit2() & 0x1F)); + } + + if (version < ICaloCompactCellTool::VERSION_502 ) { + assert (cell2->qual2() == 0); // Quality not saved. + } else { + if (cell1->qbit1() < TileCell::KEEP_TIME && cell1->qbit2() < TileCell::KEEP_TIME) { + if ((cell1->qbit2() & TileCell::MASK_BADCH) != 0) + assert (cell2->qual2() == 255); // Quality is bad. + else + assert (cell2->qual2() == 0); // Quality is good. + } else { + assert (cell1->qual2() == cell2->qual2()); + } + } + } +} + + +void dump_packed (const CaloCompactCellContainer& packed) +{ + const std::vector<CaloCompactCellContainer::value_type>& data = + packed.getData(); + + int ccount = 0; + for (size_t i = 0; i < data.size(); i++) { + if (ccount == 0) + printf ("\n%08x ", (unsigned int)i*4); + printf (" %08x", data[i]); + ++ccount; + if (ccount == 4) ccount = 0; + } + printf ("\n"); +} + + +void dump_e (double e) +{ + if (e > 1000*GeV) + e = round (e / 20) * 20; + else + e = round (e / 10) * 10; + printf ("%8.0f ", e); +} + + +void dump_cells (const CaloCellContainer& cont) +{ + for (size_t i = 0; i < cont.size(); i++) { + const CaloCell* cell = cont[i]; + printf ("%8d ", (unsigned int)cell->caloDDE()->calo_hash()); + if (const TileCell* tcell = dynamic_cast<const TileCell*> (cell)) { + dump_e (tcell->ene1()); + dump_e (tcell->ene2()); + printf ("%8.2f %8.2f %d %d 0x%02x 0x%02x %d %d\n", + tcell->time1(), tcell->time2(), + tcell->qual1(), tcell->qual2(), + tcell->qbit1(), tcell->qbit2(), + (int)tcell->gain1(), (int)tcell->gain2()); + } + else { + printf ("%8.1f %8.2f %d %d %d\n", + cell->energy(), cell->time(), + cell->quality(), cell->provenance(), + (int)cell->gain()); + } + } +} + + +void compare_containers (const CaloCellContainer* cont, + const CaloCellContainer* cont2, + bool ordered, + int version) +{ + assert (cont->size() == cont2->size()); + + CaloCell_ID::SUBCALO subcalos[4] = {CaloCell_ID::LAREM, + CaloCell_ID::LARHEC, + CaloCell_ID::LARFCAL, + CaloCell_ID::TILE}; + for (int i = 0; i < 4; i++) { + assert (cont->hasCalo(subcalos[i]) == + cont2->hasCalo(subcalos[i])); + if (ordered) { + assert (cont->indexFirstCellCalo(subcalos[i]) == + cont2->indexFirstCellCalo(subcalos[i])); + assert (cont->indexLastCellCalo(subcalos[i]) == + cont2->indexLastCellCalo(subcalos[i])); + assert (cont->nCellsCalo(subcalos[i]) == + cont2->nCellsCalo(subcalos[i])); + } + } + + for (size_t i = 0; i < cont->size(); i++) { + const CaloCell* cell1 = (*cont)[i]; + const CaloCell* cell2 = (*cont2)[i]; + assert (cell1->caloDDE() == cell2->caloDDE()); + if (dynamic_cast<const LArCell*> (cell2) != 0) { + assert (dynamic_cast<const TileCell*> (cell1) == 0); + compare_lar (cell1, cell2, version); + } + else if (const TileCell* tcell2 = + dynamic_cast<const TileCell*> (cell2)) { + const TileCell* tcell1 = dynamic_cast<const TileCell*> (cell1); + assert (tcell1 != 0); + compare_tile (tcell1, tcell2, version); + } + else + std::abort(); + } +} + + +void test_one (int n, + int version, + const std::vector<CaloCell*>& cells, + ICaloCompactCellTool* tool, + bool clustery = false, + bool dump = false, + bool ordered = true) +{ + printf ("*** test %d %d %d %d\n", version, n, clustery, ordered); + CaloCellContainer* cont = fill_cells (n, cells, clustery, ordered); + + if (dump) + dump_cells (*cont); + + CaloCompactCellContainer ccc; + tool->getPersistent (*cont, &ccc, version); + + if (dump) + dump_packed (ccc); + + CaloCellContainer* cont2 = new CaloCellContainer (SG::VIEW_ELEMENTS); + SG::Arena::Push push (*arena); + tool->getTransient (ccc, cont2); + + if (dump) + dump_cells (*cont2); + + compare_containers (cont, cont2, ordered, version); + + delete cont; + delete cont2; + + arena->reset(); +} + + +void test_supercells (int version, + const std::vector<CaloCell*>& cells, + ICaloCompactCellTool* tool) +{ + printf ("*** test SC %d\n", version); + CaloCellContainer* cont = fill_supercells (cells); + //dump_cells (*cont); + + CaloCompactCellContainer ccc; + tool->getPersistent (*cont, &ccc, version); + + CaloCellContainer* cont2 = new CaloCellContainer (SG::VIEW_ELEMENTS); + SG::Arena::Push push (*arena); + tool->getTransient (ccc, cont2); + //dump_cells (*cont2); + + compare_containers (cont, cont2, true, version); + + delete cont; + delete cont2; + arena->reset(); +} + + +//============================================================================ + + +struct CaloCellPacker_400_500_test +{ + typedef CaloCellPacker_400_500::header500 header_t; + typedef CaloCompactCellContainer::value_type value_type; + typedef std::vector<value_type> vec_t; + + static + void test_fin (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err1 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + static + void test_err2 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err3 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err4 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err5 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err6 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err7 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err8 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err9 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err10 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); + + static + void test_err11 (const CaloCompactCellContainer& ccc, + ICaloCompactCellTool* tool); +}; + + +void +CaloCellPacker_400_500_test::test_fin (const CaloCompactCellContainer& + ccc2, + ICaloCompactCellTool* tool) +{ + CaloCellContainer cont2 (SG::VIEW_ELEMENTS); + SG::Arena::Push push (*arena); + tool->getTransient (ccc2, &cont2); +} + + +void +CaloCellPacker_400_500_test::test_err1 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err1\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + header.m_ncells_larhec = 1000000; + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err2 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err2\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + header.m_seq_larem = 1000000; + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err3 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err3\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + header.m_seq_larem = 10000; + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err4 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err4\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + vec.resize (vec.size() + 100); + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err5 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err5\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + vec.resize (vec.size() - 100); + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err6 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err6\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + vec.resize (vec.size() - 100); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + value_type val = vec[header.m_length]; + vec[header.m_length] = (10000<<2) | (val & 0xffff0003); + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err7 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err7\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + vec.resize (vec.size() - 100); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + value_type val = vec[header.m_length]; + int newhash = 200000; + vec[header.m_length] = (newhash>>16) | ((newhash&0xffff)<<16) | (val&0xfffc); + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err8 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err8\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t* header = reinterpret_cast<header_t*> (&*vec.begin()); + vec.insert (vec.begin() + header->m_length, 10, 0); + header = reinterpret_cast<header_t*> (&*vec.begin()); + header->m_length += 10; + test_fin (ccc2, tool); +} + + +// Deletes the last word of the header. +void +CaloCellPacker_400_500_test::test_err9 (const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err9\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t* header = reinterpret_cast<header_t*> (&*vec.begin()); + vec.erase (vec.begin() + header->m_length-1); + header = reinterpret_cast<header_t*> (&*vec.begin()); + --header->m_length; + test_fin (ccc2, tool); +} + + +void +CaloCellPacker_400_500_test::test_err10(const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err10\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + value_type val = vec[header.m_length]; + int nseq = (val & 0xfffc) >> 2; + int hash = (val & 3) << 16 | ((val & 0xffff0000)>>16); + int target = hash + std::min (10, nseq); + + CaloDetDescrManager::calo_element_const_iterator cbeg = + g_mgr->element_begin(); + CaloDetDescrElement * const & rcbeg = *cbeg; + CaloDetDescrElement** beg = const_cast<CaloDetDescrElement**> (&rcbeg); + CaloDetDescrElement* dde = beg[target]; + beg[target] = 0; + test_fin (ccc2, tool); + beg[target] = dde; +} + + +void +CaloCellPacker_400_500_test::test_err11(const CaloCompactCellContainer& + ccc, + ICaloCompactCellTool* tool) +{ + printf (" --- err11\n"); + CaloCompactCellContainer ccc2 = ccc; + vec_t& vec = const_cast<vec_t&>(ccc2.getData()); + header_t& header = *reinterpret_cast<header_t*> (&*vec.begin()); + header.m_lengthProvenance = 9999999; + test_fin (ccc2, tool); +} + + +// Test handling of corrupt data. +void test_errs (const std::vector<CaloCell*>& cells, + ICaloCompactCellTool* tool) +{ + printf ("*** test_errs\n"); + CaloCellContainer* cont = fill_cells (10000, cells, true, true); + CaloCompactCellContainer ccc; + tool->getPersistent (*cont, &ccc, ICaloCompactCellTool::VERSION_501); + + typedef CaloCellPacker_400_500_test T; + + T::test_err1 (ccc, tool); + T::test_err2 (ccc, tool); + T::test_err3 (ccc, tool); + T::test_err4 (ccc, tool); + T::test_err5 (ccc, tool); + T::test_err6 (ccc, tool); + T::test_err7 (ccc, tool); + T::test_err8 (ccc, tool); + T::test_err9 (ccc, tool); + T::test_err10 (ccc, tool); + T::test_err11 (ccc, tool); + + // Unordered + printf (" --- err unordered\n"); + seed = 101; + CaloCellContainer* cont2 = fill_cells (10000, cells, true, false); + CaloCompactCellContainer ccc2; + tool->getPersistent (*cont2, &ccc2, ICaloCompactCellTool::VERSION_500); + T::test_fin (ccc2, tool); + + delete cont; +} + + +//============================================================================ + + +std::vector<CaloCell*> init (ICaloCompactCellTool* & tool) +{ + ISvcLocator* svcloc; + if (!Athena_test::initGaudi("CaloCompactCellTool_test.txt", svcloc)) { + std::cerr << "This test can not be run" << std::endl; + exit(0); + } + g_svcloc = svcloc; + + CaloCell_ID* helper = make_helper (); + CaloCell_SuperCell_ID* schelper = make_sc_helper (); + CaloIdManager* idmgr = make_idmgr (helper, schelper); + CaloDetDescrManager* mgr = new CaloDetDescrManager; + mgr->set_helper (helper); + mgr->initialize(); + + CaloSuperCellDetDescrManager* scmgr = new CaloSuperCellDetDescrManager; + scmgr->set_helper (schelper); + scmgr->initialize(); + + std::vector<CaloCell*> cells = make_cells (mgr); + + IToolSvc* toolsvc = 0; + CHECK( svcloc->service ("ToolSvc", toolsvc, true) ); + g_toolsvc = toolsvc; + + tool = 0; + CHECK( toolsvc->retrieveTool ("CaloCompactCellTool", tool) ); + + StoreGateSvc* detstore = 0; + CHECK( svcloc->service ("DetectorStore", detstore) ); + + CHECK( detstore->record (mgr, "CaloMgr") ); + CHECK( detstore->record (scmgr, "CaloSuperCellMgr") ); + CHECK( detstore->record (idmgr, "CaloIdManager") ); + + arena = new SG::Arena ("arena"); + SG::ArenaHeaderGaudiClear::disable(); + + g_mgr = mgr; + + return cells; +} + + +void runtests () +{ + ICaloCompactCellTool* tool = 0; + std::vector<CaloCell*> cells = init (tool); + + seed = 10; + test_one (400, ICaloCompactCellTool::VERSION_400, cells, tool, false, true); + test_one (400, ICaloCompactCellTool::VERSION_400, cells, tool, true, true); + test_one (10000, ICaloCompactCellTool::VERSION_400, cells, tool); + test_one (10000, ICaloCompactCellTool::VERSION_400, cells, tool, true); + + test_one (100000, ICaloCompactCellTool::VERSION_400, cells, tool); + test_one (100000, ICaloCompactCellTool::VERSION_400, cells, tool, true); + + test_one (cells.size(), ICaloCompactCellTool::VERSION_400, cells, tool); + + seed = 20; + test_one (400, ICaloCompactCellTool::VERSION_500, cells, tool, false, true); + test_one (400, ICaloCompactCellTool::VERSION_500, cells, tool, true, true); + + test_one (10000, ICaloCompactCellTool::VERSION_500, cells, tool); + test_one (10000, ICaloCompactCellTool::VERSION_500, cells, tool, true); + + test_one (100000, ICaloCompactCellTool::VERSION_500, cells, tool); + test_one (100000, ICaloCompactCellTool::VERSION_500, cells, tool, true); + + test_one (cells.size(), ICaloCompactCellTool::VERSION_500, cells, tool); + + seed = 40; + test_one (400, ICaloCompactCellTool::VERSION_501, cells, tool, false); + test_one (400, ICaloCompactCellTool::VERSION_501, cells, tool, true); + + test_one (10000, ICaloCompactCellTool::VERSION_501, cells, tool); + test_one (10000, ICaloCompactCellTool::VERSION_501, cells, tool, true); + + test_one (100000, ICaloCompactCellTool::VERSION_501, cells, tool); + test_one (100000, ICaloCompactCellTool::VERSION_501, cells, tool, true); + + test_one (cells.size(), ICaloCompactCellTool::VERSION_501, cells, tool); + + // Unordered + test_one (400, ICaloCompactCellTool::VERSION_501, cells, tool, false, + true, false); + + seed = 50; + test_one (400, ICaloCompactCellTool::VERSION_502, cells, tool, false); + test_one (400, ICaloCompactCellTool::VERSION_502, cells, tool, true); + + test_one (10000, ICaloCompactCellTool::VERSION_502, cells, tool); + test_one (10000, ICaloCompactCellTool::VERSION_502, cells, tool, true); + + test_one (100000, ICaloCompactCellTool::VERSION_502, cells, tool); + test_one (100000, ICaloCompactCellTool::VERSION_502, cells, tool, true); + + test_one (cells.size(), ICaloCompactCellTool::VERSION_502, cells, tool); + + seed = 60; + test_one (400, ICaloCompactCellTool::VERSION_503, cells, tool, false); + test_one (400, ICaloCompactCellTool::VERSION_503, cells, tool, true); + + test_one (10000, ICaloCompactCellTool::VERSION_503, cells, tool); + test_one (10000, ICaloCompactCellTool::VERSION_503, cells, tool, true); + + test_one (100000, ICaloCompactCellTool::VERSION_503, cells, tool); + test_one (100000, ICaloCompactCellTool::VERSION_503, cells, tool, true); + + test_one (cells.size(), ICaloCompactCellTool::VERSION_503, cells, tool); + + seed = 70; + test_one (400, ICaloCompactCellTool::VERSION_504, cells, tool, false); + test_one (400, ICaloCompactCellTool::VERSION_504, cells, tool, true); + + test_one (10000, ICaloCompactCellTool::VERSION_504, cells, tool); + test_one (10000, ICaloCompactCellTool::VERSION_504, cells, tool, true); + + test_one (100000, ICaloCompactCellTool::VERSION_504, cells, tool); + test_one (100000, ICaloCompactCellTool::VERSION_504, cells, tool, true); + + test_one (cells.size(), ICaloCompactCellTool::VERSION_504, cells, tool); + + seed = 80; + test_supercells (ICaloCompactCellTool::VERSION_504, cells, tool); + + seed = 30; + test_errs (cells, tool); +} + + +float tv_diff (const timeval& tv1, const timeval& tv2) +{ + return tv2.tv_sec - tv1.tv_sec + (tv2.tv_usec - tv1.tv_usec) / 1000000.; +} + + +void timetests (int nrep) +{ + ICaloCompactCellTool* tool = 0; + std::vector<CaloCell*> cells = init (tool); + + CaloCellContainer* cont = fill_cells (10000, cells, true, true); + + rusage ru0, ru1, ru2, ru3; + + CaloCompactCellContainer ccc; + getrusage (RUSAGE_SELF, &ru0); + for (int i=0; i < nrep; i++) + tool->getPersistent (*cont, &ccc); + getrusage (RUSAGE_SELF, &ru1); + + SG::Arena::Push push (*arena); + CaloCellContainer* cont2 = new CaloCellContainer (SG::VIEW_ELEMENTS); + getrusage (RUSAGE_SELF, &ru2); + for (int i = 0; i < nrep; i++) { + tool->getTransient (ccc, cont2); + cont2->clear(); + arena->reset(); + } + getrusage (RUSAGE_SELF, &ru3); + + printf ("pack: %f ", tv_diff (ru0.ru_utime, ru1.ru_utime)); + printf ("unpack: %f\n", tv_diff (ru2.ru_utime, ru3.ru_utime)); +} + + +int main (int argc, char** argv) +{ + errorcheck::ReportMessage::hideErrorLocus (true); + + if (argc >= 3 && strcmp (argv[1], "-t") == 0) { + timetests (atoi (argv[2])); + return 0; + } + + runtests (); + + return 0; +} diff --git a/Calorimeter/CaloTools/test/CaloTools.xml b/Calorimeter/CaloTools/test/CaloTools.xml new file mode 100755 index 0000000000000000000000000000000000000000..bb9ddb7422141b6de7f1f2726a0dd46023d3fd34 --- /dev/null +++ b/Calorimeter/CaloTools/test/CaloTools.xml @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<atn> + <TEST name="CaloToolsTests" type="makecheck"> + <package>Calorimeter/CaloTools</package> + <author> scott snyder </author> + <mailto> snyder@bnl.gov </mailto> + <expectations> + <errorMessage>Athena exited abnormally</errorMessage> + <errorMessage>differ</errorMessage> + <warningMessage> # WARNING_MESSAGE : post.sh> ERROR</warningMessage> + <successMessage>check ok</successMessage> + <returnValue>0</returnValue> + </expectations> + </TEST> +</atn>