diff --git a/CaloCluster/CMakeLists.txt b/CaloCluster/CMakeLists.txt index 6a7c9d112b..9af4a67d76 100644 --- a/CaloCluster/CMakeLists.txt +++ b/CaloCluster/CMakeLists.txt @@ -28,6 +28,7 @@ cet_build_plugin(CaloClusterMaker art::module Offline::CalorimeterGeom Offline::GeometryService + Offline::ProditionsService Offline::RecoDataProducts ) diff --git a/CaloCluster/src/CaloClusterMaker_module.cc b/CaloCluster/src/CaloClusterMaker_module.cc index 62fc985036..2e54a0cf01 100644 --- a/CaloCluster/src/CaloClusterMaker_module.cc +++ b/CaloCluster/src/CaloClusterMaker_module.cc @@ -21,6 +21,7 @@ #include "Offline/RecoDataProducts/inc/CaloHit.hh" #include "Offline/RecoDataProducts/inc/CaloCluster.hh" #include "Offline/RecoDataProducts/inc/CaloProtoCluster.hh" +#include "Offline/ProditionsService/inc/ProditionsHandle.hh" #include #include @@ -66,6 +67,7 @@ namespace mu2e { private: art::ProductToken mainToken_; art::ProductToken splitToken_; + ProditionsHandle alignedCal_h; double deltaTime_; double maxDistSplit_; double maxDistMain_; @@ -73,30 +75,33 @@ namespace mu2e { int diagLevel_; std::vector clusterTimeEnergy(const std::vector>& hits); - void makeCaloClusters(CaloClusterCollection&, const CaloProtoClusterCollection&, const CaloProtoClusterCollection&); + void makeCaloClusters(const Calorimeter& cal, CaloClusterCollection&, + const CaloProtoClusterCollection&, + const CaloProtoClusterCollection&); }; //--------------------------------------------------------------------------------------------------------------- void CaloClusterMaker::produce(art::Event& event) { + const Calorimeter& alignedCal = alignedCal_h.get(event.id()); + const auto& caloClustersMain = *event.getValidHandle(mainToken_); const auto& caloClustersSplit = *event.getValidHandle(splitToken_); auto caloClusters = std::make_unique(); - makeCaloClusters(*caloClusters, caloClustersMain, caloClustersSplit); + makeCaloClusters(alignedCal, *caloClusters, caloClustersMain, caloClustersSplit); event.put(std::move(caloClusters)); } //--------------------------------------------------------------------------------------------------------------- - void CaloClusterMaker::makeCaloClusters(CaloClusterCollection& caloClusters, const CaloProtoClusterCollection& caloClustersMain, + void CaloClusterMaker::makeCaloClusters(const Calorimeter& cal, + CaloClusterCollection& caloClusters, + const CaloProtoClusterCollection& caloClustersMain, const CaloProtoClusterCollection& caloClustersSplit) { - const Calorimeter& cal = *(GeomHandle()); - - ClusterAssociator associator(cal); associator.associateSplitOff(caloClustersMain, caloClustersSplit, deltaTime_,maxDistSplit_); @@ -116,8 +121,8 @@ namespace mu2e { isSplit = true; caloHitsPtrVector.insert(caloHitsPtrVector.end(), - caloClustersSplit.at(isplit).caloHitsPtrVector().begin(), - caloClustersSplit.at(isplit).caloHitsPtrVector().end()); + caloClustersSplit.at(isplit).caloHitsPtrVector().begin(), + caloClustersSplit.at(isplit).caloHitsPtrVector().end()); if (diagLevel_ > 1) std::cout<<"Associated main cluster "<>(); + } + } + + set_t makeSet(art::EventID const& eid) { + // get the tables up to date + ProditionsEntity::set_t cids; + if (_useDb) { + _tadisk_p->get(eid); + cids.insert(_tadisk_p->cid()); + } + return cids; + } + + DbIoV makeIov(art::EventID const& eid) { + DbIoV iov; + iov.setMax(); // start with full IOV range + if (_useDb) { + iov.overlap(_tadisk_p->iov()); + } + return iov; + } + + ProditionsEntity::ptr makeEntity(art::EventID const& eid) { + if(_useDb) { + return _maker.fromDb(_tadisk_p->getPtr(eid)); + } else { + return _maker.fromFcl(); + } + } + + + private: + bool _useDb; + AlignedCalorimeterMaker _maker; + std::unique_ptr> _tadisk_p; + }; +} +#endif diff --git a/CaloConditions/inc/AlignedCalorimeterMaker.hh b/CaloConditions/inc/AlignedCalorimeterMaker.hh new file mode 100644 index 0000000000..388ff46a68 --- /dev/null +++ b/CaloConditions/inc/AlignedCalorimeterMaker.hh @@ -0,0 +1,33 @@ +#ifndef CaloConditions_AlignedCalorimeterMaker_hh +#define CaloConditions_AlignedCalorimeterMaker_hh +// +// Make AlignedCalorimeter from fcl or (eventually) database +// +#include "Offline/CalorimeterGeom/inc/DiskCalorimeter.hh" +#include "Offline/CaloConfig/inc/AlignedCalConfig.hh" +#include "Offline/DbTables/inc/CalAlignElement.hh" +#include "Offline/DbTables/inc/CalAlignParams.hh" + +namespace mu2e { + + class AlignedCalorimeterMaker { + typedef std::shared_ptr ptr_t; + + public: + AlignedCalorimeterMaker(const AlignedCalConfig& config):_config(config) {} + void alignCalorimeter(ptr_t ptr, + const std::vector& disk_align_params); + ptr_t fromFcl(); + ptr_t fromDb(CalAlignDisk::cptr_t cad_p); + + private: + std::vector readFile(const std::string& fileName, uint16_t nRowMax); + std::vector readDb(CalAlignElement::cptr_t cptr, uint16_t nRowMax); + + // this object needs to be thread safe, + // _config should only be initialized once + const AlignedCalConfig _config; + }; +} + +#endif diff --git a/CaloConditions/src/AlignedCalorimeterMaker.cc b/CaloConditions/src/AlignedCalorimeterMaker.cc new file mode 100644 index 0000000000..e48b9b2b6c --- /dev/null +++ b/CaloConditions/src/AlignedCalorimeterMaker.cc @@ -0,0 +1,158 @@ +#include "cetlib_except/exception.h" +#include "Offline/CaloConditions/inc/AlignedCalorimeterMaker.hh" +#include "Offline/CalorimeterGeom/inc/DiskCalorimeter.hh" +#include "Offline/ConfigTools/inc/ConfigFileLookupPolicy.hh" +#include "Offline/GeometryService/inc/GeomHandle.hh" + +#include "CLHEP/Vector/ThreeVector.h" +#include "CLHEP/Vector/Rotation.h" + +#include +#include +#include +#include + + +namespace mu2e { + + //----------------------------------------------------------------------------------------- + void AlignedCalorimeterMaker::alignCalorimeter(AlignedCalorimeterMaker::ptr_t ptr, + const std::vector& disk_align_params) + { + DiskCalorimeter& cal = *ptr; + + for (auto& disk : cal.disks()) { + // Use the const_cast bazooka here - this is the only place where + // Disk parameters should be modified by an external agent + auto& diskcc = const_cast(disk); + const auto& disk_align = disk_align_params.at(diskcc.id()); + + CLHEP::Hep3Vector shift(disk_align.dx(),disk_align.dy(),disk_align.dz()); + CLHEP::HepRotation rotation(CLHEP::HepRotation::IDENTITY); + rotation.rotateX(disk_align.rx()); + rotation.rotateY(disk_align.ry()); + rotation.rotateZ(disk_align.rz()); + + diskcc.moveDisk(shift,rotation); + } + } + + + + //----------------------------------------------------------------------------------------- + std::vector AlignedCalorimeterMaker::readFile(const std::string& fileName, uint16_t nRowMax) + { + ConfigFileLookupPolicy configFile; + std::string fullFileName = configFile(fileName); + if (_config.verbose()>0) { + std::cout << "AlignedCalorimeterMaker::fromFcl reading from " << fullFileName << "\n"; + } + + std::ifstream ordFile; + ordFile.open(fullFileName); + if (!ordFile.is_open()) { + throw cet::exception("ALIGNEDCAL_OPEN_FAILED") + << " failed to open file " << fullFileName << "\n"; + } + + std::vector align_params; + uint16_t nRead(0); + std::string line; + while (std::getline(ordFile, line)) { + uint16_t index; + float dx,dy,dz,rx,ry,rz; + + std::istringstream iss(line); + if (!(iss >> index >> dx >> dy >> dz >> rx >> ry >> rz)) { + throw cet::exception("ALIGNEDCAL_FORMAT") + << "invalid format at line "<> std::ws; + if (!iss.eof()) { + throw cet::exception("ALIGNEDCAL_FORMAT") + << "invalid format at line "<= nRowMax) { + throw cet::exception("ALIGNEDCAL_RANGE") << "AlignedCalorimeterMaker read invalid offlineId " + << index << "\n"; + } + align_params.push_back(CalAlignParams(index,dx,dy,dz,rx,ry,rz)); + ++nRead; + } + + if(nRead != nRowMax) { + throw cet::exception("ALIGNEDCAL_COUNT") + << "AlignedCalorimeterMaker read the wrong number of id's " + << nRead << ", expected " << nRowMax << "\n"; + } + + return align_params; + } + + + + //----------------------------------------------------------------------------------------- + std::vector AlignedCalorimeterMaker::readDb(CalAlignElement::cptr_t cptr, uint16_t nRowMax) + { + std::vector align_params; + uint16_t nRead(0); + + for (auto const& row : cptr->rows()) { + auto index = row.index(); + auto dx = row.dx(); + auto dy = row.dy(); + auto dz = row.dz(); + auto rx = row.rx(); + auto ry = row.ry(); + auto rz = row.rz(); + + if (index >= nRowMax) { + throw cet::exception("AlignedCalorimeterMAKER_RANGE") << "AlignedCalorimeterMaker read invalid offlineId " << index << "\n"; + } + align_params.push_back(CalAlignParams(index,dx,dy,dz,rx,ry,rz)); + ++nRead; + } + + if(nRead != nRowMax) { + throw cet::exception("AlignedCalorimeterMAKER_COUNT") + << "AlignedCalorimeterMaker read the wrong number of id's " + << nRead << ", expected " << nRowMax << "\n"; + } + return align_params; + } + + + //----------------------------------------------------------------------------------------- + AlignedCalorimeterMaker::ptr_t AlignedCalorimeterMaker::fromFcl() + { + //Deep copy of the calorimeter to keep the original untouched + GeomHandle cal_h; + auto ptr = std::make_shared(*cal_h); + + if ( _config.verbose() > 0 ) + std::cout << "AlignedCalorimeterMaker::fromFcl now zero aligning Calorimeter\n"; + + auto disk_align_params = readFile(_config.filenameDisk(), CaloConst::_nDisk); + alignCalorimeter(ptr, disk_align_params); + + return ptr; + } + + //----------------------------------------------------------------------------------------- + AlignedCalorimeterMaker::ptr_t AlignedCalorimeterMaker::fromDb(CalAlignDisk::cptr_t cad_p) + { + GeomHandle cal_h; + auto ptr = std::make_shared(*cal_h); + + if ( _config.verbose() > 0 ) + std::cout << "AlignedCalorimeterMaker::fromDb now aligning Calorimeter \n"; + + auto disk_align_params = readDb(cad_p, CaloConst::_nDisk); + alignCalorimeter(ptr, disk_align_params); + + return ptr; + } +} diff --git a/CaloConditions/src/SConscript b/CaloConditions/src/SConscript index dcd48fe7c1..1bf8c601a4 100644 --- a/CaloConditions/src/SConscript +++ b/CaloConditions/src/SConscript @@ -26,7 +26,7 @@ mainlib = helper.make_mainlib ( [ 'fhiclcpp_types', 'cetlib', 'cetlib_except', - #'CLHEP', + 'CLHEP', 'MathCore', 'boost_system' #rootlibs diff --git a/CaloConfig/CMakeLists.txt b/CaloConfig/CMakeLists.txt index cd9647682a..84146faece 100644 --- a/CaloConfig/CMakeLists.txt +++ b/CaloConfig/CMakeLists.txt @@ -3,6 +3,7 @@ cet_make_library(INTERFACE INSTALLED_PATH_BASE Offline inc/CalCalibConfig.hh inc/CalDAQMapConfig.hh inc/CalSimParamsConfig.hh + inc/AlignedCalConfig.hh LIBRARIES INTERFACE ) diff --git a/CaloConfig/inc/AlignedCalConfig.hh b/CaloConfig/inc/AlignedCalConfig.hh new file mode 100644 index 0000000000..93a9eb45ee --- /dev/null +++ b/CaloConfig/inc/AlignedCalConfig.hh @@ -0,0 +1,24 @@ +#ifndef CaloConfig_AlignedCalConfig_hh +#define CaloConfig_AlignedCalConfig_hh +// +// Initialize AlignedCal from fcl +// +#include "fhiclcpp/types/Atom.h" +#include "fhiclcpp/types/Sequence.h" +#include + +namespace mu2e { + + struct AlignedCalConfig { + using Name=fhicl::Name; + using Comment=fhicl::Comment; + fhicl::Atom filenameDisk { + Name("filenameDisk"), Comment("Filename for disk alignment file")}; + fhicl::Atom verbose{ + Name("verbose"), Comment("verbosity")}; + fhicl::Atom useDb{ + Name("useDb"), Comment("use database or fcl")}; + }; +} + +#endif diff --git a/DbTables/inc/CalAlignElement.hh b/DbTables/inc/CalAlignElement.hh new file mode 100644 index 0000000000..a7c981fba4 --- /dev/null +++ b/DbTables/inc/CalAlignElement.hh @@ -0,0 +1,85 @@ +#ifndef DbTables_CalAlignElement_hh +#define DbTables_CalAlignElement_hh +// +// Alignment tables for calorimeter elements +// +#include "Offline/DataProducts/inc/CaloConst.hh" +#include "Offline/DbTables/inc/DbTable.hh" +#include "Offline/DbTables/inc/CalAlignParams.hh" +#include +#include +#include + +namespace mu2e { + + class CalAlignElement : public DbTable { + public: + typedef std::shared_ptr ptr_t; + typedef std::shared_ptr cptr_t; + + CalAlignElement(const char* Name, const char* DbName, size_t nrows) : + DbTable(Name, DbName, "index,dx,dy,dz,rx,ry,rz"), _nrows(nrows) + {} + + const CalAlignParams& rowAt(const std::size_t index) const { + return _rows.at(index); + } + const std::vector& rows() const {return _rows;} + std::size_t nrow() const override {return _rows.size();}; + std::size_t nrowFix() const override {return _nrows;}; + std::size_t size() const override { + return baseSize() + nrow() * sizeof(CalAlignParams); + }; + const std::string orderBy() const {return std::string("index");} + + void addRow(const std::vector& columns) override { + unsigned index = std::stoul(columns[0]); + // enforce a strict sequential order + if (index >= _nrows || index != _rows.size()) { + throw cet::exception("CALALIGNELEMENT_BAD_INDEX") + << "CalAlignElement::addRow found index out of order: " << index + << " != " << _rows.size() << "\n"; + } + _rows.emplace_back(index,std::stof(columns[1]),std::stof(columns[2]), + std::stof(columns[3]),std::stof(columns[4]), + std::stof(columns[5]),std::stof(columns[6])); + } + + void rowToCsv(std::ostringstream& sstream, std::size_t irow) const override { + CalAlignParams const& r = _rows.at(irow); + sstream << r.index() << ","; + sstream << std::fixed + << std::setprecision(3); + sstream << r.dx() << ","; + sstream << r.dy() << ","; + sstream << r.dz() << ","; + sstream << std::fixed << std::setprecision(3); + sstream << r.rx() << ","; + sstream << r.ry() << ","; + sstream << r.rz() << ","; + } + + void clear() override { + baseClear(); + _rows.clear(); + } + + private: + std::vector _rows; + size_t _nrows; + }; + + + class CalAlignDisk : public CalAlignElement { + public: + constexpr static const char* cxname = "CalAlignDisk"; + CalAlignDisk() : + CalAlignElement(cxname, "cal.aligndisk", CaloConst::_nDisk) + {} + CalAlignDisk(const char* name, const char* dbname) : + CalAlignElement(name, dbname, CaloConst::_nDisk) + {} + }; + +} +#endif diff --git a/DbTables/inc/CalAlignParams.hh b/DbTables/inc/CalAlignParams.hh new file mode 100644 index 0000000000..30270b7ff9 --- /dev/null +++ b/DbTables/inc/CalAlignParams.hh @@ -0,0 +1,36 @@ +#ifndef DbTables_CalAlignParams_hh +#define DbTables_CalAlignParams_hh +// +// Rigid body alignment parameters for calorimeter +// dx,dy,dz = displacement of the disk in mm +// rx,ry,rz are rotations along the x,y,z axes w.r.t disk center in radians +// Order of operation is irrelevant since rotation is perfomed around disk center +// +namespace mu2e { + class CalAlignParams { + public: + CalAlignParams(int index, float dx, float dy, float dz, + float rx, float ry, float rz) : + _index(index), _dx(dx), _dy(dy), _dz(dz), + _rx(rx), _ry(ry), _rz(rz) + {} + + unsigned index() const { return _index; } + float dx() const { return _dx; } + float dy() const { return _dy; } + float dz() const { return _dz; } + float rx() const { return _rx; } + float ry() const { return _ry; } + float rz() const { return _rz; } + + private: + unsigned _index; + float _dx; + float _dy; + float _dz; + float _rx; + float _ry; + float _rz; + }; +} +#endif diff --git a/DbTables/src/DbTableFactory.cc b/DbTables/src/DbTableFactory.cc index e799ac2297..1a91708fff 100644 --- a/DbTables/src/DbTableFactory.cc +++ b/DbTables/src/DbTableFactory.cc @@ -25,6 +25,7 @@ #include "Offline/DbTables/inc/CalTimeCalib.hh" #include "Offline/DbTables/inc/CalCosmicT0Align.hh" #include "Offline/DbTables/inc/CalSimCrystals.hh" +#include "Offline/DbTables/inc/CalAlignElement.hh" #include "Offline/DbTables/inc/TrkAlignElement.hh" #include "Offline/DbTables/inc/TrkAlignElementSim.hh" @@ -129,6 +130,8 @@ mu2e::DbTable::ptr_t mu2e::DbTableFactory::newTable(std::string const& name) { return std::shared_ptr(new mu2e::CalEnergyCalibInfo()); } else if (name=="CalTimeCalib") { return std::shared_ptr(new mu2e::CalTimeCalib()); + } else if (name=="CalAlignDisk") { + return std::shared_ptr(new mu2e::CalAlignDisk()); } else if (name=="CalCosmicT0Align") { return std::shared_ptr(new mu2e::CalCosmicT0Align()); } else if (name=="CalSimCrystals") { diff --git a/ProditionsService/fcl/prolog.fcl b/ProditionsService/fcl/prolog.fcl index 72945cd68d..45aa8c784c 100644 --- a/ProditionsService/fcl/prolog.fcl +++ b/ProditionsService/fcl/prolog.fcl @@ -29,6 +29,7 @@ Proditions : { calDAQConditions : @local::CalDAQConditions calCalib : @local::CalCalib calSimParams : @local::CalSimParams + alignedCalorimeter : @local::alignedCalorimeter verbose : 0 } diff --git a/ProditionsService/inc/ProditionsService.hh b/ProditionsService/inc/ProditionsService.hh index 1f6711fe43..f8d9662a89 100644 --- a/ProditionsService/inc/ProditionsService.hh +++ b/ProditionsService/inc/ProditionsService.hh @@ -30,6 +30,7 @@ #include "Offline/AnalysisConfig/inc/MVACatalogConfig.hh" #include "Offline/SimulationConfig/inc/SimBookkeeperConfig.hh" +#include "Offline/CaloConfig/inc/AlignedCalConfig.hh" #include "Offline/CaloConfig/inc/CalCalibConfig.hh" #include "Offline/CaloConfig/inc/CalSimParamsConfig.hh" @@ -98,6 +99,8 @@ class ProditionsService { Name("calCalib"),Comment("calorimeter energy calib") }; fhicl::Table calSimParams{ Name("calSimParams"),Comment("calorimeter sim parameters for crystals") }; + fhicl::Table alignedCalorimeter{ + Name("alignedCalorimeter"), Comment("Calorimeter alignment in reco code")}; }; // this line is required by art to allow the command line help print diff --git a/ProditionsService/src/ProditionsService.cc b/ProditionsService/src/ProditionsService.cc index 7ec721dc8a..53190f43dd 100644 --- a/ProditionsService/src/ProditionsService.cc +++ b/ProditionsService/src/ProditionsService.cc @@ -3,21 +3,21 @@ // //#include "Offline/AnalysisConditions/inc/TrkQualCatalogCache.hh" #include "Offline/DbService/inc/DbHandle.hh" +#include "Offline/DbService/inc/DbService.hh" +#include "Offline/GeometryService/inc/GeometryService.hh" +#include "Offline/ProditionsService/inc/ProditionsService.hh" + #include "Offline/CRVConditions/inc/CRVCalibCache.hh" #include "Offline/CRVConditions/inc/CRVOrdinalCache.hh" #include "Offline/CRVConditions/inc/CRVPhotonYieldCache.hh" #include "Offline/CRVConditions/inc/CRVStatusCache.hh" -#include "Offline/CaloConditions/inc/CalDAQMapCache.hh" #include "Offline/DAQConditions/inc/EventTimingCache.hh" -#include "Offline/DbService/inc/DbService.hh" -#include "Offline/GeometryService/inc/GeometryService.hh" -#include "Offline/ProditionsService/inc/ProditionsService.hh" #include "Offline/CaloConditions/inc/CalSimParamsCache.hh" #include "Offline/CaloConditions/inc/CalDAQMapCache.hh" +#include "Offline/CaloConditions/inc/AlignedCalorimeterCache.hh" #include "Offline/CaloConditions/inc/CalCalibCache.hh" -#include "Offline/DAQConditions/inc/EventTimingCache.hh" #include "Offline/STMConditions/inc/STMEnergyCalibCache.hh" #include "Offline/SimulationConditions/inc/SimBookkeeperCache.hh" @@ -101,6 +101,10 @@ ProditionsService::ProditionsService(Parameters const& sTable, auto cmc = std::make_shared(_config.calSimParams()); _caches[cmc->name()] = cmc; + auto acc = + std::make_shared(_config.alignedCalorimeter()); + _caches[acc->name()] = acc; + if (_config.verbose() > 0) { cout << "Proditions built caches:" << endl; for (auto const& cc : _caches) {