File indexing completed on 2024-04-06 12:20:42
0001 #include "L1Trigger/L1THGCal/interface/concentrator/HGCalConcentratorAutoEncoderImpl.h"
0002 #include "DataFormats/ForwardDetId/interface/HGCalTriggerDetId.h"
0003 #include <iomanip>
0004
0005
0006
0007
0008 HGCalConcentratorAutoEncoderImpl::HGCalConcentratorAutoEncoderImpl(const edm::ParameterSet& conf)
0009 : cellRemap_(conf.getParameter<std::vector<int>>("cellRemap")),
0010 cellRemapNoDuplicates_(conf.getParameter<std::vector<int>>("cellRemapNoDuplicates")),
0011 encoderShape_(conf.getParameter<std::vector<uint>>("encoderShape")),
0012 decoderShape_(conf.getParameter<std::vector<uint>>("decoderShape")),
0013 bitsPerInput_(conf.getParameter<int>("nBitsPerInput")),
0014 maxBitsPerOutput_(conf.getParameter<int>("maxBitsPerOutput")),
0015 outputBitsPerLink_(conf.getParameter<std::vector<int>>("bitsPerLink")),
0016 modelFilePaths_(conf.getParameter<std::vector<edm::ParameterSet>>("modelFiles")),
0017 linkToGraphMap_(conf.getParameter<std::vector<unsigned int>>("linkToGraphMap")),
0018 zeroSuppresionThreshold_(conf.getParameter<double>("zeroSuppresionThreshold")),
0019 bitShiftNormalization_(conf.getParameter<bool>("bitShiftNormalization")),
0020 saveEncodedValues_(conf.getParameter<bool>("saveEncodedValues")),
0021 preserveModuleSum_(conf.getParameter<bool>("preserveModuleSum")) {
0022
0023
0024 nInputs_ = 1;
0025 for (const auto& i : encoderShape_) {
0026 nInputs_ *= i;
0027 }
0028
0029
0030 if (encoderShape_.size() != encoderTensorDims_) {
0031 throw cms::Exception("BadInitialization")
0032 << "Encoder input shapes are currently expected to be " << encoderTensorDims_ << " values";
0033 }
0034
0035 if (decoderShape_.size() != decoderTensorDims_) {
0036 throw cms::Exception("BadInitialization")
0037 << "Encoder input shapes are currently expected to be " << decoderTensorDims_ << " values long";
0038 }
0039
0040 if (cellRemap_.size() != nInputs_) {
0041 throw cms::Exception("BadInitialization")
0042 << "Size of cellRemap (" << cellRemap_.size()
0043 << ") does not agree with the total size specified for the encoder inputs based on the encoderShape variable ("
0044 << nInputs_ << ")";
0045 }
0046
0047 if (cellRemap_.size() != cellRemapNoDuplicates_.size()) {
0048 throw cms::Exception("BadInitialization")
0049 << "Size of cellRemap (" << cellRemap_.size() << ") does not agree with size of cellRemapNoDuplicates ("
0050 << cellRemapNoDuplicates_.size() << ")";
0051 }
0052
0053 for (unsigned i = 0; i < cellRemap_.size(); i++) {
0054 if (cellRemap_[i] > nTriggerCells_ - 1) {
0055 throw cms::Exception("BadInitialization")
0056 << "cellRemap value " << cellRemap_[i] << " is larger than the number of trigger cells " << nTriggerCells_;
0057 }
0058 if (cellRemapNoDuplicates_[i] > nTriggerCells_ - 1) {
0059 throw cms::Exception("BadInitialization") << "cellRemapNoDuplicates value " << cellRemapNoDuplicates_[i]
0060 << " is larger than the number of trigger cells " << nTriggerCells_;
0061 }
0062 }
0063
0064 tensorflow::setLogging("0");
0065
0066 for (const auto& modelFilePset : modelFilePaths_) {
0067 std::string encoderPath = modelFilePset.getParameter<edm::FileInPath>("encoderModelFile").fullPath();
0068 std::string decoderPath = modelFilePset.getParameter<edm::FileInPath>("decoderModelFile").fullPath();
0069
0070 graphDef_encoder_ = std::unique_ptr<tensorflow::GraphDef>{tensorflow::loadGraphDef(encoderPath)};
0071
0072
0073 session_encoder_.push_back(
0074 std::unique_ptr<tensorflow::Session>{tensorflow::createSession(graphDef_encoder_.get())});
0075
0076 graphDef_decoder_ = std::unique_ptr<tensorflow::GraphDef>{tensorflow::loadGraphDef(decoderPath)};
0077
0078
0079 session_decoder_.push_back(
0080 std::unique_ptr<tensorflow::Session>{tensorflow::createSession(graphDef_decoder_.get())});
0081
0082
0083 if (modelFilePset == modelFilePaths_.front()) {
0084 inputTensorName_encoder_ = graphDef_encoder_.get()->node(0).name();
0085 outputTensorName_encoder_ = graphDef_encoder_.get()->node(graphDef_encoder_.get()->node_size() - 1).name();
0086 inputTensorName_decoder_ = graphDef_decoder_.get()->node(0).name();
0087 outputTensorName_decoder_ = graphDef_decoder_.get()->node(graphDef_decoder_.get()->node_size() - 1).name();
0088 } else {
0089 if (inputTensorName_encoder_ != graphDef_encoder_.get()->node(0).name()) {
0090 throw cms::Exception("BadInitialization") << "provided list of encoder graphs have different input nodes";
0091 }
0092 if (outputTensorName_encoder_ != graphDef_encoder_.get()->node(graphDef_encoder_.get()->node_size() - 1).name()) {
0093 throw cms::Exception("BadInitialization") << "provided list of encoder graphs have different output nodes";
0094 }
0095 if (inputTensorName_decoder_ != graphDef_decoder_.get()->node(0).name()) {
0096 throw cms::Exception("BadInitialization") << "provided list of decoder graphs have different input nodes";
0097 }
0098 if (outputTensorName_decoder_ != graphDef_decoder_.get()->node(graphDef_decoder_.get()->node_size() - 1).name()) {
0099 throw cms::Exception("BadInitialization") << "provided list of decoder graphs have different output nodes";
0100 }
0101 }
0102 }
0103
0104
0105 if (linkToGraphMap_.size() <= maxNumberOfLinks_) {
0106 throw cms::Exception("BadInitialization")
0107 << "Autoencoder graph number must be specified for all link allocation possibilities. Only "
0108 << linkToGraphMap_.size() << " values specified while " << maxNumberOfLinks_ << "links are possible";
0109 }
0110
0111
0112 for (const auto& graphNumber : linkToGraphMap_) {
0113 if (graphNumber >= modelFilePaths_.size()) {
0114 throw cms::Exception("BadInitialization")
0115 << "Autoencoder graph number " << graphNumber << " is larger than the size of the provided list of graphs "
0116 << modelFilePaths_.size();
0117 }
0118 }
0119 }
0120
0121 void HGCalConcentratorAutoEncoderImpl::select(unsigned nLinks,
0122 const std::vector<l1t::HGCalTriggerCell>& trigCellVecInput,
0123 std::vector<l1t::HGCalTriggerCell>& trigCellVecOutput,
0124 std::vector<l1t::HGCalConcentratorData>& ae_encodedLayer_Output) {
0125 std::array<double, nTriggerCells_> mipPt;
0126 std::array<double, nTriggerCells_> uncompressedCharge;
0127 std::array<double, nTriggerCells_> compressedCharge;
0128 std::array<double, maxAEInputSize_> ae_inputArray;
0129 std::array<double, nTriggerCells_> ae_outputArray;
0130
0131
0132 mipPt.fill(0);
0133 uncompressedCharge.fill(0);
0134 compressedCharge.fill(0);
0135 ae_inputArray.fill(0);
0136 ae_outputArray.fill(0);
0137
0138 double modSum = 0;
0139
0140 int bitsPerOutput = outputBitsPerLink_.at(nLinks);
0141
0142
0143
0144 double inputMaxIntSize = 1;
0145 if (bitsPerInput_ > 0)
0146 inputMaxIntSize = 1 << bitsPerInput_;
0147 double outputMaxIntSize = 1;
0148 if (bitsPerOutput > 0)
0149 outputMaxIntSize = 1 << bitsPerOutput;
0150 double outputMaxIntSizeGlobal = 1;
0151 if (maxBitsPerOutput_ > 0)
0152 outputMaxIntSizeGlobal = 1 << maxBitsPerOutput_;
0153
0154 for (const auto& trigCell : trigCellVecInput) {
0155 if (triggerTools_.isScintillator(trigCell.detId()))
0156 return;
0157
0158 HGCalTriggerDetId id(trigCell.detId());
0159 uint cellu = id.triggerCellU();
0160 uint cellv = id.triggerCellV();
0161 int inputIndex = cellUVremap_[cellu][cellv];
0162 if (inputIndex < 0) {
0163 throw cms::Exception("BadInitialization")
0164 << "Invalid index provided for trigger cell u=" << cellu << " v=" << cellv << " in cellUVRemap[" << cellu
0165 << "][" << cellv << "]";
0166 }
0167
0168 mipPt[inputIndex] = trigCell.mipPt();
0169 uncompressedCharge[inputIndex] = trigCell.uncompressedCharge();
0170 compressedCharge[inputIndex] = trigCell.compressedCharge();
0171
0172 modSum += trigCell.mipPt();
0173 }
0174
0175 double normalization = modSum;
0176 if (modSum > 0) {
0177
0178
0179 if (bitShiftNormalization_) {
0180 int msb = int(log2(modSum));
0181 normalization = pow(2, msb);
0182 }
0183
0184
0185 for (uint i = 0; i < nInputs_; i++) {
0186 int remapIndex = cellRemap_[i];
0187 if (remapIndex < 0)
0188 continue;
0189 ae_inputArray[i] = mipPt[remapIndex] / normalization;
0190
0191 if (bitsPerInput_ > 0) {
0192 ae_inputArray[i] = std::round(ae_inputArray[i] * inputMaxIntSize) / inputMaxIntSize;
0193 }
0194 }
0195 }
0196
0197 tensorflow::Tensor encoder_input(tensorflow::DT_FLOAT,
0198 {encoderShape_[0], encoderShape_[1], encoderShape_[2], encoderShape_[3]});
0199
0200 float* d = encoder_input.flat<float>().data();
0201 for (uint i = 0; i < nInputs_; i++, d++) {
0202 *d = ae_inputArray[i];
0203 }
0204
0205 int graphIndex = linkToGraphMap_.at(nLinks);
0206
0207 std::vector<tensorflow::Tensor> encoder_outputs;
0208 tensorflow::run(session_encoder_.at(graphIndex).get(),
0209 {{inputTensorName_encoder_, encoder_input}},
0210 {outputTensorName_encoder_},
0211 &encoder_outputs);
0212
0213 if (encoder_outputs.empty()) {
0214 throw cms::Exception("BadInitialization") << "Autoencoder graph returning empty output vector";
0215 }
0216
0217 d = encoder_outputs[0].flat<float>().data();
0218 for (int i = 0; i < encoder_outputs[0].NumElements(); i++, d++) {
0219 ae_encodedLayer_[i] = *d;
0220
0221 if (bitsPerOutput > 0 && maxBitsPerOutput_ > 0) {
0222 ae_encodedLayer_[i] = std::round(ae_encodedLayer_[i] * outputMaxIntSize) / outputMaxIntSize;
0223 }
0224 }
0225
0226 tensorflow::Tensor decoder_input(tensorflow::DT_FLOAT, {decoderShape_[0], decoderShape_[1]});
0227 d = decoder_input.flat<float>().data();
0228 for (int i = 0; i < nEncodedLayerNodes_; i++, d++) {
0229 *d = ae_encodedLayer_[i];
0230 }
0231
0232 std::vector<tensorflow::Tensor> decoder_outputs;
0233 tensorflow::run(session_decoder_.at(graphIndex).get(),
0234 {{inputTensorName_decoder_, decoder_input}},
0235 {outputTensorName_decoder_},
0236 &decoder_outputs);
0237
0238 double outputSum = 0.;
0239
0240 d = decoder_outputs[0].flat<float>().data();
0241 for (uint i = 0; i < nInputs_; i++, d++) {
0242 int remapIndex = cellRemapNoDuplicates_[i];
0243 if (remapIndex < 0)
0244 continue;
0245 outputSum += *d * normalization;
0246 ae_outputArray[remapIndex] = *d;
0247 }
0248
0249 double renormalizationFactor = 1.;
0250 if (preserveModuleSum_) {
0251 renormalizationFactor = modSum / outputSum;
0252 }
0253
0254
0255 if (modSum > 0) {
0256
0257 HGCalTriggerDetId id(trigCellVecInput.at(0).detId());
0258 int subdet = id.subdet();
0259 int zp = id.zside();
0260 int type = id.type();
0261 int layer = id.layer();
0262 int waferU = id.waferU();
0263 int waferV = id.waferV();
0264
0265
0266 float mipPtToEt_conv = trigCellVecInput[0].et() / trigCellVecInput[0].mipPt();
0267 float mipToADC_conv = trigCellVecInput[0].hwPt() / (trigCellVecInput[0].mipPt() * cosh(trigCellVecInput[0].eta()));
0268
0269 for (int i = 0; i < nTriggerCells_; i++) {
0270 if (ae_outputArray[i] > 0) {
0271 int cellU = ae_outputCellU_[i];
0272 int cellV = ae_outputCellV_[i];
0273
0274 HGCalTriggerDetId id(subdet, zp, type, layer, waferU, waferV, cellU, cellV);
0275
0276 if (!triggerTools_.getTriggerGeometry()->validTriggerCell(id))
0277 continue;
0278
0279 GlobalPoint point = triggerTools_.getTCPosition(id);
0280
0281 double mipPt = ae_outputArray[i] * normalization * renormalizationFactor;
0282 double adc = mipPt * cosh(point.eta()) * mipToADC_conv;
0283 double et = mipPt * mipPtToEt_conv;
0284
0285 if (mipPt < zeroSuppresionThreshold_)
0286 continue;
0287
0288 l1t::HGCalTriggerCell triggerCell(reco::LeafCandidate::LorentzVector(), adc, 0, 0, 0, id);
0289
0290 triggerCell.setUncompressedCharge(uncompressedCharge[i]);
0291 triggerCell.setCompressedCharge(compressedCharge[i]);
0292 triggerCell.setMipPt(mipPt);
0293
0294 math::PtEtaPhiMLorentzVector p4(et, point.eta(), point.phi(), 0.);
0295
0296 triggerCell.setP4(p4);
0297 triggerCell.setPosition(point);
0298
0299 trigCellVecOutput.push_back(triggerCell);
0300 }
0301 }
0302
0303 if (saveEncodedValues_) {
0304 id = HGCalTriggerDetId(subdet, zp, type, layer, waferU, waferV, 0, 0);
0305 for (int i = 0; i < nEncodedLayerNodes_; i++) {
0306 l1t::HGCalConcentratorData encodedLayerData(ae_encodedLayer_[i] * outputMaxIntSizeGlobal, i, id);
0307 ae_encodedLayer_Output.push_back(encodedLayerData);
0308 }
0309 }
0310 }
0311 }