20 #include "messagefacility/MessageLogger/MessageLogger.h"
33 ,
fGeom(lar::providerFrom<geo::Geometry>())
38 assert(fNOpDetChannels > 0U);
39 unsigned int nCryoChannels =
fGeom->Cryostat(0U).NOpDet();
40 libraryIndices.resize(nCryoChannels);
41 std::iota(libraryIndices.begin(), libraryIndices.end(), 0U);
43 prepareMappings(libraryIndices);
53 return onCryo? location + fTranslations[onCryo.
Cryostat]: location;
59 (
geo::Point_t const& location)
const -> OpDetToLibraryIndexMap
const&
63 ? fOpDetToLibraryIndexMaps[onCryo.
Cryostat]: fInvalidOpDetToLibraryIndexMap;
73 ? fLibraryIndexToOpDetMaps[onCryo.
Cryostat]: fInvalidLibraryIndexToOpDetMap;
93 if (C0endX > C1startX) {
94 throw std::runtime_error(
95 "phot::ICARUSPhotonMappingTransformations::prepareGeometryMapping(): "
98 +
"... this algorithm does not understand this geometry."
102 MF_LOG_DEBUG(
"ICARUSPhotonMappingTransformations")
103 <<
"Switching from cryostat 0 to 1 when x > " <<
fSwitchPoint <<
" cm";
108 fTranslations.push_back(refPoint - cryo.BoundingBox().Min());
139 std::vector<lar::util::MinMaxCollector<OpDetID_t>> opDetChannelRangeByCryostat
140 (
fGeom->Ncryostats());
143 unsigned int const maxOpChannel =
fGeom->MaxOpChannel();
144 for (
unsigned int channel = 0; channel < maxOpChannel; ++channel) {
147 auto const& opDetID = opDet.
ID();
149 if (opDetID.isValid) {
150 opDetChannelRange.add(
OpDetID_t(channel));
151 opDetChannelRangeByCryostat[opDetID.Cryostat].add(
OpDetID_t(channel));
157 fChannelShifts.clear();
163 auto const& channelRange = opDetChannelRangeByCryostat[cid.
Cryostat];
164 if (!channelRange.has_data()) {
165 throw std::runtime_error(
166 "phot::ICARUSPhotonMappingTransformations::prepareLibraryMappings(): "
167 + cid.
toString() +
" ends up with no optical channels??"
171 auto const nChannels = channelRange.max() + 1 - channelRange.min();
172 if ((
unsigned int) nChannels != cryo.NOpDet()) {
173 throw std::runtime_error(
174 "phot::ICARUSPhotonMappingTransformations::prepareLibraryMappings(): "
175 + cid.
toString() +
" expected to have "
176 +
std::to_string(cryo.NOpDet()) +
" optical channels, we end up with "
184 fChannelShifts.push_back
185 (channelRange.min() - opDetChannelRangeByCryostat.front().min());
200 fLibraryIndexToOpDetMaps.clear();
208 auto const nChannels = cryo.NOpDet();
209 if (libraryIndices.size() != nChannels) {
210 throw std::runtime_error(
211 "phot::ICARUSPhotonMappingTransformations::prepareLibraryMappings(): "
213 +
" channels but it covers " +
std::to_string(libraryIndices.size())
218 auto const nFirst = fChannelShifts[cryo.ID().Cryostat];
220 for (
auto& c: libraryIndexToOpDetMap) c += nFirst;
222 fLibraryIndexToOpDetMaps.push_back(std::move(libraryIndexToOpDetMap));
229 fInvalidLibraryIndexToOpDetMap.clear();
230 fInvalidLibraryIndexToOpDetMap.resize
231 (fLibraryIndexToOpDetMaps.front().size(), InvalidOpDetID);
244 fOpDetToLibraryIndexMaps.clear();
245 for (
auto const& libToOpDetMap: fLibraryIndexToOpDetMaps) {
247 fOpDetToLibraryIndexMaps.push_back
248 (invertMapping(libToOpDetMap, maxOpChannel, InvalidLibraryIndex));
252 fInvalidOpDetToLibraryIndexMap.clear();
253 fInvalidOpDetToLibraryIndexMap.resize(maxOpChannel, InvalidLibraryIndex);
273 mf::LogInfo(
"ICARUSPhotonMappingTransformations")
274 <<
"Photon visibility mapping tool: 'ICARUSPhotonMappingTransformations'";
279 prepareGeometryMapping();
284 prepareLibraryMappings(libraryIndices);
287 if (fDumpMapping) dumpMapping();
295 std::string channelIndex
303 std::string libraryIndex
316 mf::LogInfo log(
"ICARUSPhotonMappingTransformations");
318 log <<
"ICARUSPhotonMappingTransformations mapping";
320 log <<
"\nMapping of geometry: '" <<
fGeom->DetectorName() <<
"':"
321 <<
"\n - " <<
fGeom->Ncryostats() <<
" cryostats"
322 <<
"\n - optical channels: " << fNOpDetChannels
323 <<
"\n - maximum optical detector channel number: " <<
fGeom->MaxOpChannel()
327 log <<
"\nThe switch point is at x=" << fSwitchPoint <<
" cm.";
329 constexpr
unsigned int PageBreak = 12;
331 for (
auto const& cryo:
fGeom->IterateCryostats()) {
333 auto const c = cryo.ID().Cryostat;
335 log <<
"\n" << cryo.ID() <<
":"
336 <<
"\n * optical detectors: " << cryo.NOpDet()
337 <<
"\n * channel -> library shift: " << fChannelShifts[c]
338 <<
"\n * translation: " << fTranslations[c];
343 auto const& libOpDetIDmap = fLibraryIndexToOpDetMaps[c];
345 <<
"\n * mapping [library index @" << cryo.ID()
346 <<
"] => [optical detector] (" << libOpDetIDmap.size()
351 if (++pager >= PageBreak) {
355 log <<
" [" << i <<
"] => [" << channelIndex(opDetID) <<
"];";
359 auto const& opDetLibMap = fOpDetToLibraryIndexMaps[c];
362 <<
"\n * mapping [optical detector] => [library index @"
363 << cryo.ID() <<
"] (" << opDetLibMap.size() <<
" entries):";
366 for (std::size_t i = 0; i < opDetLibMap.size(); ++i) {
367 if (++pager >= PageBreak) {
371 log <<
" [" << i <<
"] => [" << libraryIndex(opDetLibMap[i]) <<
"];";
378 <<
"\nMapping [library index] => [no optical detector] ("
379 << fInvalidLibraryIndexToOpDetMap.size() <<
" entries):";
380 unsigned int pager = PageBreak;
381 for (std::size_t i = 0; i < fInvalidLibraryIndexToOpDetMap.size(); ++i) {
382 if (++pager >= PageBreak) {
386 log <<
" [" << i <<
"] => ["
387 << libraryIndex(fInvalidLibraryIndexToOpDetMap[i]) <<
"];";
394 <<
"\nMapping [optical detector] => [no library] ("
395 << fInvalidOpDetToLibraryIndexMap.size() <<
" entries):";
396 unsigned int pager = PageBreak;
397 for (std::size_t i = 0; i < fInvalidOpDetToLibraryIndexMap.size(); ++i) {
398 if (++pager >= PageBreak) {
402 log <<
" [" << i <<
"] => ["
403 << channelIndex(fInvalidOpDetToLibraryIndexMap[i]) <<
"];";
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition of util::enumerate().
double MinX() const
Returns the world x coordinate of the start of the box.
CryostatID_t Cryostat
Index of cryostat.
double MaxX() const
Returns the world x coordinate of the end of the box.
Geometry information for a single cryostat.
geo::BoxBoundedGeo const & BoundingBox() const
Returns the bounding box of this cryostat.
Classes gathering simple statistics.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Keeps track of the minimum and maximum value we observed.
std::string toString() const
Human-readable representation of the cryostat ID.
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
phot::IPhotonMappingTransformations::OpDetID_t OpDetID_t
Type of (global) optical detector ID.
geo::Point_t Min() const
Returns the corner point with the smallest coordinates.
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
std::string to_string(WindowPattern const &pattern)
geo::OpDetID const & ID() const
Returns the geometry ID of this optical detector.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
The data type to uniquely identify a cryostat.