Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:19

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     FWTableViewManager
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:
0010 //         Created:  Sun Jan  6 22:01:27 EST 2008
0011 //
0012 
0013 // system include files
0014 #include <iostream>
0015 #include <functional>
0016 #include <algorithm>
0017 
0018 #include "TEveManager.h"
0019 #include "TClass.h"
0020 #include "FWCore/Reflection/interface/BaseWithDict.h"
0021 #include "FWCore/Reflection/interface/MemberWithDict.h"
0022 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0023 
0024 // user include files
0025 #include "Fireworks/Core/interface/FWConfiguration.h"
0026 #include "Fireworks/Core/interface/FWTableViewManager.h"
0027 #include "Fireworks/Core/interface/FWEventItem.h"
0028 #include "Fireworks/Core/interface/FWGUIManager.h"
0029 #include "Fireworks/Core/interface/FWColorManager.h"
0030 
0031 #include "Fireworks/Core/interface/FWTypeToRepresentations.h"
0032 #include "Fireworks/Core/interface/fwLog.h"
0033 
0034 //
0035 // constants, enums and typedefs
0036 //
0037 
0038 //
0039 // static data member definitions
0040 //
0041 
0042 //
0043 // constructors and destructor
0044 //
0045 FWTableViewManager::FWTableViewManager(FWGUIManager *iGUIMgr) : FWViewManagerBase() {
0046   FWGUIManager::ViewBuildFunctor f;
0047   f = std::bind(&FWTableViewManager::buildView, this, std::placeholders::_1, std::placeholders::_2);
0048   iGUIMgr->registerViewBuilder(FWViewType::idToName(FWViewType::kTable), f);
0049 
0050   // ---------- for some object types, we have default table contents ----------
0051   table("reco::GenParticle")
0052       .column("pT", 1, "pt")
0053       .column("eta", 3)
0054       .column("phi", 3)
0055       .column("status", TableEntry::INT)
0056       .column("pdgId", TableEntry::INT);
0057 
0058   table("reco::Muon")
0059       .column("q", TableEntry::INT, "charge")
0060       .column("pT", 1, "pt")
0061       .column("global", TableEntry::BOOL, "isGlobalMuon")
0062       .column("tracker", TableEntry::BOOL, "isTrackerMuon")
0063       .column("SA", TableEntry::BOOL, "isStandAloneMuon")
0064       .column("calo", TableEntry::BOOL, "isCaloMuon")
0065       .column("tr pt", 1, "track().pt()")
0066       .column("eta", 3)
0067       .column("phi", 3)
0068       .column("matches", TableEntry::INT, "numberOfMatches('SegmentArbitration')")
0069       .column("d0", 3, "track().d0()")
0070       .column("d0 / d0Err", 3, "track().d0() / track().d0Error()");
0071 
0072   table("reco::GsfElectron")
0073       .column("q", TableEntry::INT, "charge")
0074       .column("pT", 1, "pt")
0075       .column("eta", 3)
0076       .column("phi", 3)
0077       .column("E/p", 3, "eSuperClusterOverP")
0078       .column("H/E", 3, "hadronicOverEm")
0079       .column("fbrem", 3, "(trackMomentumAtVtx().R() - trackMomentumOut().R()) / trackMomentumAtVtx().R()")
0080       .column("dei", 3, "deltaEtaSuperClusterTrackAtVtx()")
0081       .column("dpi", 3, "deltaPhiSuperClusterTrackAtVtx()");
0082 
0083   table("reco::Photon").column("pT", 1, "pt").column("eta", 3).column("phi", 3).column("H/E", 3, "hadronicOverEm");
0084 
0085   table("reco::CaloJet")
0086       .column("pT", 1, "pt")
0087       .column("eta", 3)
0088       .column("phi", 3)
0089       .column("ECAL", 1, "p4().E() * emEnergyFraction()")
0090       .column("HCAL", 1, "p4().E() * energyFractionHadronic()")
0091       .column("emf", 3, "emEnergyFraction()");
0092 
0093   table("reco::Jet")
0094       .column("pT", 1, "pt")
0095       .column("eta", 3)
0096       .column("phi", 3)
0097       .column("electronEnergyFraction", 3, "electronEnergyFraction()")
0098       .column("muonEnergyFraction", 3, "muonEnergyFraction()")
0099       .column("photonEnergyFraction", 3, "photonEnergyFraction()");
0100 
0101   table("reco::MET").column("et", 1).column("phi", 3).column("sumEt", 1).column("mEtSig", 3);
0102 
0103   table("reco::Track")
0104       .column("q", TableEntry::INT, "charge")
0105       .column("pT", 1, "pt")
0106       .column("eta", 3)
0107       .column("phi", 3)
0108       .column("d0", 5)
0109       .column("d0Err", 5, "d0Error")
0110       .column("dz", 5)
0111       .column("dzErr", 5, "dzError")
0112       .column("vx", 5)
0113       .column("vy", 5)
0114       .column("vz", 5)
0115       .column("pixel hits", TableEntry::INT, "hitPattern().numberOfValidPixelHits()")
0116       .column("strip hits", TableEntry::INT, "hitPattern().numberOfValidStripHits()")
0117       .column("chi2", 3)
0118       .column("ndof", TableEntry::INT);
0119 
0120   table("DTRecSegment4D")
0121       .column("wheel", 0, "chamberId.wheel")
0122       .column("station", 0, "chamberId.station")
0123       .column("sector", 0, "chamberId.sector")
0124       .column("t0phi", 2, "phiSegment.t0")
0125       .column("t0theta", 2, "zSegment.t0")
0126       .column("hasPhi", -2, "hasPhi")
0127       .column("hasZed", -2, "hasZed")
0128       .column("chi2", 2, "chi2")
0129       .column("dof", 0, "degreesOfFreedom");
0130 
0131   table("DTRecHit1DPair")
0132       .column("wheel", 0, "wireId.wheel")
0133       .column("station", 0, "wireId.station")
0134       .column("sector", 0, "wireId.sector")
0135       .column("SL", 0, "wireId.superlayer")
0136       .column("layer", 0, "wireId.layer")
0137       .column("wire", 0, "wireId.wire")
0138       .column("digiTime", 2, "digiTime");
0139 
0140   table("CSCSegment")
0141       .column("endcap", 0, "cscDetId.endcap")
0142       .column("station", 0, "cscDetId.station")
0143       .column("ring", 0, "cscDetId.ring")
0144       .column("chamber", 0, "cscDetId.chamber");
0145 
0146   table("reco::Vertex")
0147       .column("x", 5)
0148       .column("xError", 5)
0149       .column("y", 5)
0150       .column("yError", 5)
0151       .column("z", 5)
0152       .column("zError", 5)
0153       .column("tracks", TableEntry::INT, "tracksSize")
0154       .column("chi2", 3)
0155       .column("ndof", 3);
0156 
0157   table("CaloTower").column("emEt", 1).column("hadEt", 1).column("et", 1, "Et").column("eta", 3).column("phi", 3);
0158 
0159   table("CaloRecHit")
0160       .column("id", TableEntry::INT, "detid.rawId")
0161       .column("energy", 3)
0162       .column("time", 3)
0163       .column("flags", TableEntry::INT, "flags");
0164 
0165   table("reco::PFCandidate")
0166       .column("et", 1, "Et")
0167       .column("eta", 3)
0168       .column("phi", 3)
0169       .column("ecalEnergy", 3, "ecalEnergy()")
0170       .column("hcalEnergy", 3, "hcalEnergy()")
0171       .column("track pt", 3, "trackRef().pt()");
0172 
0173   table("reco::Electron")
0174       .column("pT", 1, "pt")
0175       .column("eta", 3)
0176       .column("phi", 3)
0177       .column("E/p", 3, "eSuperClusterOverP")
0178       .column("H/E", 3, "hadronicOverEm")
0179       .column("fbrem", 3, "(trackMomentumAtVtx().R() - trackMomentumOut().R()) / trackMomentumAtVtx().R()")
0180       .column("dei", 3, "deltaEtaSuperClusterTrackAtVtx")
0181       .column("dpi", 3, "deltaPhiSuperClusterTrackAtVtx()")
0182       .column("charge", 0, "charge")
0183       .column("isPF", 0, "isPF()")
0184       .column("sieie", 3, "sigmaIetaIeta")
0185       .column("isNotConv", 1, "passConversionVeto");
0186 
0187   table("pat::PackedCandidate")
0188       .column("pT", 1, "pt")
0189       .column("eta", 3)
0190       .column("phi", 3)
0191       .column("pdgId", 0)
0192       .column("charge", 0)
0193       .column("dxy", 3)
0194       .column("dzAssociatedPV", 3, "dzAssociatedPV()");
0195 
0196   table("l1t::HGCalTriggerCell").column("pT", 1, "pt").column("eta", 3).column("phi", 3).column("detId", 0);
0197 
0198   table("CaloParticle").column("eta", 3).column("phi", 3).column("energy", 3);
0199 }
0200 
0201 FWTableViewManager::~FWTableViewManager() {}
0202 
0203 //
0204 // member functions
0205 //
0206 
0207 /** Define a new table for type @a name
0208  
0209     @a name the typename of the object contained in the table.
0210 
0211     @returns the TableHandle for this table, which can be
0212              used to create columns via the ::columns() method. 
0213     All subsequent calls for method column will be 
0214     relative to this table.
0215 
0216     If a table with the same name is already there, its entries
0217     are reset. 
0218   */
0219 FWTableViewManager::TableHandle FWTableViewManager::table(const char *name) {
0220   TableHandle handle(name, m_tableFormats);
0221   return handle;
0222 }
0223 
0224 /** Define a column in the current table. 
0225  
0226     @a name to be used as header of the column.
0227 
0228     @a precision specifying the number of significant digits in the fractional part.
0229 
0230     @a expression to be used to retrieve the value from the object.
0231   */
0232 FWTableViewManager::TableHandle &FWTableViewManager::TableHandle::column(const char *name,
0233                                                                          int precision,
0234                                                                          const char *expression) {
0235   TableEntry columnEntry;
0236   columnEntry.name = name;
0237   columnEntry.precision = precision;
0238   columnEntry.expression = expression;
0239 
0240   m_specs[m_name].push_back(columnEntry);
0241   return *this;
0242 }
0243 
0244 /** Helper function to do recursive lookup of specialized 
0245     table description for a given type @a key.
0246  */
0247 FWTableViewManager::TableSpecs::iterator FWTableViewManager::tableFormatsImpl(const edm::TypeWithDict &key) {
0248   TableSpecs::iterator ret = m_tableFormats.find(key.name());
0249   if (ret != m_tableFormats.end())
0250     return ret;
0251 
0252   // if there is no exact match for the type, try the base classes
0253   edm::TypeBases bases(key);
0254   for (auto const &base : bases) {
0255     ret = tableFormatsImpl(edm::BaseWithDict(base).typeOf());
0256     if (ret != m_tableFormats.end())
0257       return ret;
0258   }
0259 
0260   return m_tableFormats.end();
0261 }
0262 
0263 /** Find the entries for a given type @a key, possibly recursively
0264     searching recursively in the class hierarchy for a base class 
0265     that matches. 
0266 
0267     - If the recursion succeeds return the specific table.
0268     - Otherwise, create a dummy table with most common properties.
0269 
0270     @a key the edm::TypeWithDict of the collection for which we want
0271            to have the key definition.
0272 
0273     FIXME: how about actually inspecting the type and show all the int and floats 
0274            if no description is found??
0275   */
0276 FWTableViewManager::TableSpecs::iterator FWTableViewManager::tableFormats(const edm::TypeWithDict &key) {
0277   static const std::string isint("int");
0278   static const std::string isbool("bool");
0279   static const std::string isdouble("double");
0280   static const std::string isfloat("float");
0281 
0282   std::string keyType = key.name();
0283 
0284   TableSpecs::iterator ret = m_tableFormats.find(keyType);
0285 
0286   if (ret != m_tableFormats.end())
0287     return ret;
0288 
0289   ret = tableFormatsImpl(key);  // recursive search for base classes
0290 
0291   if (ret != m_tableFormats.end())
0292     return ret;
0293 
0294   TableHandle handle = table(keyType.c_str());
0295   edm::TypeFunctionMembers functionMembers(key);
0296   for (auto const &member : functionMembers) {
0297     edm::FunctionWithDict m(member);
0298     if (m.functionParameterSize())
0299       continue;
0300     if (!m.isPublic())
0301       continue;
0302     if (!m.isConst())
0303       continue;
0304     if (m.finalReturnType().name() == isint)
0305       handle.column(m.name().c_str(), TableEntry::INT);
0306     else if (m.finalReturnType().name() == isbool)
0307       handle.column(m.name().c_str(), TableEntry::BOOL);
0308     else if (m.finalReturnType().name() == isdouble)
0309       handle.column(m.name().c_str(), 5);
0310     else if (m.finalReturnType().name() == isfloat)
0311       handle.column(m.name().c_str(), 3);
0312   }
0313   edm::TypeDataMembers dataMembers(key);
0314   for (auto const &member : dataMembers) {
0315     edm::MemberWithDict m(member);
0316     if (!m.isPublic())
0317       continue;
0318     if (!m.isConst())
0319       continue;
0320     if (m.typeOf().name() == isint)
0321       handle.column(m.name().c_str(), TableEntry::INT);
0322     else if (m.typeOf().name() == isbool)
0323       handle.column(m.name().c_str(), TableEntry::BOOL);
0324     else if (m.typeOf().name() == isdouble)
0325       handle.column(m.name().c_str(), 5);
0326     else if (m.typeOf().name() == isfloat)
0327       handle.column(m.name().c_str(), 3);
0328   }
0329   return m_tableFormats.find(keyType);
0330 }
0331 
0332 /** Helper function which uses TClass rather than edm::TypeWithDict.
0333 
0334     Otherwise identical to FWTableViewManager::tableFormats(const TClass &key).
0335 
0336   */
0337 FWTableViewManager::TableSpecs::iterator FWTableViewManager::tableFormats(const TClass &key) {
0338   return tableFormats(edm::TypeWithDict::byName(key.GetName()));
0339 }
0340 
0341 class FWViewBase *FWTableViewManager::buildView(TEveWindowSlot *iParent, const std::string & /*type*/) {
0342   TEveManager::TRedrawDisabler disableRedraw(gEve);
0343   auto view = std::make_shared<FWTableView>(iParent, this);
0344   view->setBackgroundColor(colorManager().background());
0345   m_views.push_back(view);
0346   view->beingDestroyed_.connect(std::bind(&FWTableViewManager::beingDestroyed, this, std::placeholders::_1));
0347   return view.get();
0348 }
0349 
0350 void FWTableViewManager::beingDestroyed(const FWViewBase *iView) {
0351   for (Views::iterator it = m_views.begin(), itEnd = m_views.end(); it != itEnd; ++it) {
0352     if (it->get() == iView) {
0353       m_views.erase(it);
0354       return;
0355     }
0356   }
0357 }
0358 
0359 void FWTableViewManager::newItem(const FWEventItem *iItem) {
0360   m_items.push_back(iItem);
0361   iItem->goingToBeDestroyed_.connect(std::bind(&FWTableViewManager::destroyItem, this, std::placeholders::_1));
0362   notifyViews();
0363 }
0364 
0365 /** Tell the views to update their item list. */
0366 void FWTableViewManager::notifyViews(void) {
0367   for (size_t i = 0, e = m_views.size(); i != e; ++i) {
0368     FWTableView *view = m_views[i].get();
0369     view->updateItems();
0370     view->dataChanged();
0371   }
0372 }
0373 
0374 /** Remove @a iItem from the list 
0375     
0376     @a iItem the item to be removed.
0377 
0378  */
0379 void FWTableViewManager::destroyItem(const FWEventItem *iItem) {
0380   // remove the item from the list
0381   // FIXME: why doesn't it use erase?? Boh...
0382   for (size_t i = 0, e = m_items.size(); i != e; ++i) {
0383     if (m_items[i] != iItem)
0384       continue;
0385     m_items[i] = nullptr;
0386   }
0387 
0388   notifyViews();
0389 }
0390 
0391 /** Remove all items present in the view.
0392     
0393     This should watch the FWEventItemsManager::goingToClearItems_ signal.
0394   */
0395 void FWTableViewManager::removeAllItems(void) {
0396   m_items.clear();
0397   notifyViews();
0398 }
0399 
0400 void FWTableViewManager::modelChangesComing() { gEve->DisableRedraw(); }
0401 
0402 void FWTableViewManager::modelChangesDone() {
0403   gEve->EnableRedraw();
0404   // tell the views to update their item lists
0405   // FIXME: doesn't this need to call updateItems as well
0406   // and hence notifyViews would be more appropriate?? Boh...
0407   dataChanged();
0408 }
0409 
0410 /** Notify all the views that colors have changed */
0411 void FWTableViewManager::colorsChanged() {
0412   for (size_t i = 0, e = m_views.size(); i != e; ++i)
0413     m_views[i].get()->resetColors(colorManager());
0414 }
0415 
0416 void FWTableViewManager::dataChanged() {
0417   for (size_t i = 0, e = m_views.size(); i != e; ++i)
0418     m_views[i].get()->dataChanged();
0419 }
0420 
0421 FWTypeToRepresentations FWTableViewManager::supportedTypesAndRepresentations() const {
0422   FWTypeToRepresentations returnValue;
0423   return returnValue;
0424 }
0425 
0426 const std::string FWTableViewManager::kConfigTypeNames = "typeNames";
0427 
0428 void FWTableViewManager::addTo(FWConfiguration &iTo) const {
0429   // if there are views, it's the job of the first view to store
0430   // the configuration (this is to avoid ordering problems in the
0431   // case of multiple views)
0432   if (!m_views.empty())
0433     return;
0434   // if there are no views, then it's up to us to store the column
0435   // formats.  This is done in addToImpl, which can be called by
0436   // FWTableView as well
0437   addToImpl(iTo);
0438 }
0439 
0440 void FWTableViewManager::addToImpl(FWConfiguration &iTo) const {
0441   FWConfiguration typeNames(1);
0442   char prec[100];
0443 
0444   for (TableSpecs::const_iterator iType = m_tableFormats.begin(), iType_end = m_tableFormats.end(); iType != iType_end;
0445        ++iType) {
0446     const std::string &typeName = iType->first;
0447     typeNames.addValue(typeName);
0448     FWConfiguration columns(1);
0449     const TableEntries &entries = iType->second;
0450     for (size_t ei = 0, ee = entries.size(); ei != ee; ++ei) {
0451       const TableEntry &entry = entries[ei];
0452       columns.addValue(entry.name);
0453       columns.addValue(entry.expression);
0454       columns.addValue((snprintf(prec, 100, "%d", entry.precision), prec));
0455     }
0456     iTo.addKeyValue(typeName, columns);
0457   }
0458   iTo.addKeyValue(kConfigTypeNames, typeNames);
0459 }
0460 
0461 void FWTableViewManager::setFrom(const FWConfiguration &iFrom) {
0462   try {
0463     const FWConfiguration *typeNames = iFrom.valueForKey(kConfigTypeNames);
0464     if (typeNames == nullptr) {
0465       fwLog(fwlog::kWarning) << "no table column configuration stored, using defaults\n";
0466       return;
0467     }
0468 
0469     //NOTE: FWTableViewTableManagers hold pointers into m_tableFormats so if we
0470     // clear it those pointers would be invalid
0471     // instead we will just clear the lists and fill them with their new values
0472     //m_tableFormats.clear();
0473     for (FWConfiguration::StringValuesIt iType = typeNames->stringValues()->begin(),
0474                                          iTypeEnd = typeNames->stringValues()->end();
0475          iType != iTypeEnd;
0476          ++iType) {
0477       //std::cout << "reading type " << *iType << std::endl;
0478       const FWConfiguration *columns = iFrom.valueForKey(*iType);
0479       assert(columns != nullptr);
0480       TableHandle handle = table(iType->c_str());
0481       for (FWConfiguration::StringValuesIt it = columns->stringValues()->begin(),
0482                                            itEnd = columns->stringValues()->end();
0483            it != itEnd;
0484            ++it) {
0485         const std::string &name = *it++;
0486         const std::string &expr = *it++;
0487         int prec = atoi(it->c_str());
0488         handle.column(name.c_str(), prec, expr.c_str());
0489       }
0490     }
0491   } catch (...) {
0492     // No info about types in the configuration; this is not an
0493     // error, it merely means that the types are handled by the
0494     // first FWTableView.
0495   }
0496 }