File indexing completed on 2024-04-06 12:27:40
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "FWCore/Framework/interface/stream/EDProducer.h"
0010 #include "FWCore/Framework/interface/ESWatcher.h"
0011 #include "FWCore/Framework/interface/Event.h"
0012 #include "FWCore/Framework/interface/EventSetup.h"
0013 #include "FWCore/Framework/interface/ESHandle.h"
0014 #include "FWCore/Framework/interface/MakerMacros.h"
0015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0016 #include "FWCore/Utilities/interface/ESGetToken.h"
0017
0018 #include "DataFormats/Common/interface/DetSetVector.h"
0019 #include "DataFormats/Common/interface/DetSet.h"
0020 #include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
0021 #include "DataFormats/CTPPSReco/interface/TotemRPRecHit.h"
0022 #include "DataFormats/CTPPSReco/interface/TotemRPUVPattern.h"
0023
0024 #include "Geometry/Records/interface/VeryForwardRealGeometryRecord.h"
0025 #include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h"
0026
0027 #include "RecoPPS/Local/interface/FastLineRecognition.h"
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 class TotemRPUVPatternFinder : public edm::stream::EDProducer<> {
0038 public:
0039 TotemRPUVPatternFinder(const edm::ParameterSet &conf);
0040
0041 ~TotemRPUVPatternFinder() override;
0042
0043 void produce(edm::Event &e, const edm::EventSetup &c) override;
0044 static void fillDescriptions(edm::ConfigurationDescriptions &);
0045
0046 private:
0047 edm::InputTag tagRecHit;
0048 edm::EDGetTokenT<edm::DetSetVector<TotemRPRecHit>> detSetVectorTotemRPRecHitToken;
0049
0050 edm::ESGetToken<CTPPSGeometry, VeryForwardRealGeometryRecord> ctppsGeometryToken;
0051 edm::ESWatcher<VeryForwardRealGeometryRecord> geometryWatcher;
0052
0053 unsigned int verbosity;
0054
0055
0056 unsigned char minPlanesPerProjectionToSearch;
0057
0058
0059 unsigned char minPlanesPerProjectionToFit;
0060
0061
0062 unsigned int maxHitsPerPlaneToSearch;
0063
0064
0065 FastLineRecognition *lrcgn;
0066
0067
0068 double threshold;
0069
0070
0071 double max_a_toFit;
0072
0073
0074 struct RPSettings {
0075 unsigned char minPlanesPerProjectionToFit_U, minPlanesPerProjectionToFit_V;
0076 double threshold_U, threshold_V;
0077 };
0078
0079
0080 std::map<unsigned int, RPSettings> exceptionalSettings;
0081
0082
0083 void recognizeAndSelect(TotemRPUVPattern::ProjectionType proj,
0084 double z0,
0085 double threshold,
0086 unsigned int planes_required,
0087 const edm::DetSetVector<TotemRPRecHit> &hits,
0088 edm::DetSet<TotemRPUVPattern> &patterns);
0089 };
0090
0091
0092
0093 using namespace std;
0094 using namespace edm;
0095
0096
0097
0098 TotemRPUVPatternFinder::TotemRPUVPatternFinder(const edm::ParameterSet &conf)
0099 : tagRecHit(conf.getParameter<edm::InputTag>("tagRecHit")),
0100 ctppsGeometryToken(esConsumes()),
0101 verbosity(conf.getUntrackedParameter<unsigned int>("verbosity", 0)),
0102 minPlanesPerProjectionToSearch(conf.getParameter<unsigned int>("minPlanesPerProjectionToSearch")),
0103 minPlanesPerProjectionToFit(conf.getParameter<unsigned int>("minPlanesPerProjectionToFit")),
0104 maxHitsPerPlaneToSearch(conf.getParameter<unsigned int>("maxHitsPerPlaneToSearch")),
0105 lrcgn(new FastLineRecognition(conf.getParameter<double>("clusterSize_a"),
0106 conf.getParameter<double>("clusterSize_b"))),
0107 threshold(conf.getParameter<double>("threshold")),
0108 max_a_toFit(conf.getParameter<double>("max_a_toFit")) {
0109 for (const auto &ps : conf.getParameter<vector<ParameterSet>>("exceptionalSettings")) {
0110 unsigned int rpId = ps.getParameter<unsigned int>("rpId");
0111
0112 RPSettings settings;
0113 settings.minPlanesPerProjectionToFit_U = ps.getParameter<unsigned int>("minPlanesPerProjectionToFit_U");
0114 settings.minPlanesPerProjectionToFit_V = ps.getParameter<unsigned int>("minPlanesPerProjectionToFit_V");
0115 settings.threshold_U = ps.getParameter<double>("threshold_U");
0116 settings.threshold_V = ps.getParameter<double>("threshold_V");
0117
0118 exceptionalSettings[rpId] = settings;
0119 }
0120
0121 detSetVectorTotemRPRecHitToken = consumes<edm::DetSetVector<TotemRPRecHit>>(tagRecHit);
0122
0123 produces<DetSetVector<TotemRPUVPattern>>();
0124 }
0125
0126
0127
0128 TotemRPUVPatternFinder::~TotemRPUVPatternFinder() { delete lrcgn; }
0129
0130
0131
0132 void TotemRPUVPatternFinder::recognizeAndSelect(TotemRPUVPattern::ProjectionType proj,
0133 double z0,
0134 double threshold_loc,
0135 unsigned int planes_required,
0136 const DetSetVector<TotemRPRecHit> &hits,
0137 DetSet<TotemRPUVPattern> &patterns) {
0138
0139 DetSet<TotemRPUVPattern> newPatterns;
0140 lrcgn->getPatterns(hits, z0, threshold_loc, newPatterns);
0141
0142
0143 for (auto &p : newPatterns) {
0144 p.setProjection(proj);
0145
0146 p.setFittable(true);
0147
0148 set<unsigned int> planes;
0149 for (const auto &ds : p.hits())
0150 planes.insert(TotemRPDetId(ds.detId()).plane());
0151
0152 if (planes.size() < planes_required)
0153 p.setFittable(false);
0154
0155 if (fabs(p.a()) > max_a_toFit)
0156 p.setFittable(false);
0157
0158 patterns.push_back(p);
0159 }
0160 }
0161
0162
0163
0164 void TotemRPUVPatternFinder::produce(edm::Event &event, const edm::EventSetup &es) {
0165 if (verbosity > 5)
0166 LogVerbatim("TotemRPUVPatternFinder")
0167 << ">> TotemRPUVPatternFinder::produce " << event.id().run() << ":" << event.id().event();
0168
0169
0170 const auto &geometry = es.getData(ctppsGeometryToken);
0171 if (geometryWatcher.check(es))
0172 lrcgn->resetGeometry(&geometry);
0173
0174
0175 edm::Handle<edm::DetSetVector<TotemRPRecHit>> input;
0176 event.getByToken(detSetVectorTotemRPRecHitToken, input);
0177
0178
0179 DetSetVector<TotemRPUVPattern> patternsVector;
0180
0181
0182 struct RPData {
0183 DetSetVector<TotemRPRecHit> hits_U, hits_V;
0184 map<uint8_t, uint16_t> planeOccupancy_U, planeOccupancy_V;
0185 };
0186 map<unsigned int, RPData> rpData;
0187
0188 for (auto &ids : *input) {
0189 TotemRPDetId detId(ids.detId());
0190 unsigned int plane = detId.plane();
0191 bool uDir = detId.isStripsCoordinateUDirection();
0192
0193 CTPPSDetId rpId = detId.rpId();
0194
0195 RPData &data = rpData[rpId];
0196
0197 for (auto &h : ids) {
0198 if (uDir) {
0199 auto &ods = data.hits_U.find_or_insert(ids.detId());
0200 ods.push_back(h);
0201 data.planeOccupancy_U[plane]++;
0202 } else {
0203 auto &ods = data.hits_V.find_or_insert(ids.detId());
0204 ods.push_back(h);
0205 data.planeOccupancy_V[plane]++;
0206 }
0207 }
0208 }
0209
0210
0211 for (auto const &it : rpData) {
0212 CTPPSDetId rpId(it.first);
0213 RPData const &data = it.second;
0214
0215
0216 unsigned int minPlanesPerProjectionToFit_U = minPlanesPerProjectionToFit;
0217 unsigned int minPlanesPerProjectionToFit_V = minPlanesPerProjectionToFit;
0218 double threshold_U = threshold;
0219 double threshold_V = threshold;
0220
0221 auto setIt = exceptionalSettings.find(rpId);
0222 if (setIt != exceptionalSettings.end()) {
0223 minPlanesPerProjectionToFit_U = setIt->second.minPlanesPerProjectionToFit_U;
0224 minPlanesPerProjectionToFit_V = setIt->second.minPlanesPerProjectionToFit_V;
0225 threshold_U = setIt->second.threshold_U;
0226 threshold_V = setIt->second.threshold_V;
0227 }
0228
0229 auto &uColl = data.planeOccupancy_U;
0230 auto &vColl = data.planeOccupancy_V;
0231
0232 if (verbosity > 5) {
0233 LogVerbatim("TotemRPUVPatternFinder")
0234 << "\tRP " << rpId << "\n\t\tall planes: u = " << uColl.size() << ", v = " << vColl.size();
0235 }
0236
0237
0238 unsigned int uPlanes = 0, vPlanes = 0;
0239 for (auto pit : uColl)
0240 if (pit.second <= maxHitsPerPlaneToSearch)
0241 uPlanes++;
0242
0243 for (auto pit : vColl)
0244 if (pit.second <= maxHitsPerPlaneToSearch)
0245 vPlanes++;
0246
0247 if (verbosity > 5)
0248 LogVerbatim("TotemRPUVPatternFinder") << "\t\tplanes with clean data: u = " << uPlanes << ", v = " << vPlanes;
0249
0250
0251 if (uPlanes < minPlanesPerProjectionToSearch || vPlanes < minPlanesPerProjectionToSearch)
0252 continue;
0253
0254
0255 DetSet<TotemRPUVPattern> &patterns = patternsVector.find_or_insert(rpId);
0256
0257
0258 double z0 = geometry.rp(rpId)->translation().z();
0259
0260
0261 recognizeAndSelect(TotemRPUVPattern::projU, z0, threshold_U, minPlanesPerProjectionToFit_U, data.hits_U, patterns);
0262
0263 recognizeAndSelect(TotemRPUVPattern::projV, z0, threshold_V, minPlanesPerProjectionToFit_V, data.hits_V, patterns);
0264
0265 if (verbosity > 5) {
0266 LogVerbatim("TotemRPUVPatternFinder") << "\t\tpatterns:";
0267 for (const auto &p : patterns) {
0268 unsigned int n_hits = 0;
0269 for (auto &hds : p.hits())
0270 n_hits += hds.size();
0271
0272 LogVerbatim("TotemRPUVPatternFinder")
0273 << "\t\t\tproj = " << ((p.projection() == TotemRPUVPattern::projU) ? "U" : "V") << ", a = " << p.a()
0274 << ", b = " << p.b() << ", w = " << p.w() << ", fittable = " << p.fittable() << ", hits = " << n_hits;
0275 }
0276 }
0277 }
0278
0279
0280 event.put(make_unique<DetSetVector<TotemRPUVPattern>>(patternsVector));
0281 }
0282
0283
0284
0285 void TotemRPUVPatternFinder::fillDescriptions(edm::ConfigurationDescriptions &descr) {
0286 edm::ParameterSetDescription desc;
0287
0288 desc.add<edm::InputTag>("tagRecHit", edm::InputTag("totemRPRecHitProducer"))
0289 ->setComment("input rechits collection to retrieve");
0290 desc.addUntracked<unsigned int>("verbosity", 0);
0291 desc.add<unsigned int>("maxHitsPerPlaneToSearch", 5)
0292 ->setComment("minimum threshold of hits multiplicity to flag the pattern as dirty");
0293 desc.add<unsigned int>("minPlanesPerProjectionToSearch", 3)
0294 ->setComment(
0295 "minimal number of reasonable (= not empty and not dirty) planes per projection and per RP, to start the "
0296 "pattern search");
0297 desc.add<double>("clusterSize_a", 0.02 )
0298 ->setComment("(full) cluster size (in rad) in slope-intercept space");
0299 desc.add<double>("clusterSize_b", 0.3 );
0300
0301 desc.add<double>("threshold", 2.99)
0302 ->setComment(
0303 "minimal weight of (Hough) cluster to accept it as candidate\n"
0304 " weight of cluster = sum of weights of contributing points\n"
0305 " weight of point = sigma0 / sigma_of_point\n"
0306 "most often: weight of point ~ 1, thus cluster weight is roughly number of contributing points");
0307
0308 desc.add<unsigned int>("minPlanesPerProjectionToFit", 3)
0309 ->setComment(
0310 "minimal number of planes (in the recognised patterns) per projection and per RP, to tag the candidate as "
0311 "fittable");
0312
0313 desc.add<bool>("allowAmbiguousCombination", false)
0314 ->setComment(
0315 "whether to allow combination of most significant U and V pattern, in case there several of them.\n"
0316 "don't set it to True, unless you have reason");
0317
0318 desc.add<double>("max_a_toFit", 10.0)
0319 ->setComment(
0320 "maximal angle (in any projection) to mark the candidate as fittable -> controls track parallelity with "
0321 "beam\n"
0322 "huge value -> no constraint");
0323
0324 edm::ParameterSetDescription exceptions_validator;
0325 exceptions_validator.add<unsigned int>("rpId")->setComment("RP id according to CTPPSDetId");
0326 exceptions_validator.add<unsigned int>("minPlanesPerProjectionToFit_U");
0327 exceptions_validator.add<unsigned int>("minPlanesPerProjectionToFit_V");
0328 exceptions_validator.add<double>("threshold_U");
0329 exceptions_validator.add<double>("threshold_V");
0330
0331 std::vector<edm::ParameterSet> exceptions_default;
0332 desc.addVPSet("exceptionalSettings", exceptions_validator, exceptions_default);
0333
0334 descr.add("totemRPUVPatternFinder", desc);
0335 }
0336
0337
0338
0339 DEFINE_FWK_MODULE(TotemRPUVPatternFinder);