9#include <arich/geometry/ARICHGeometryPar.h>
11#include <framework/logging/Logger.h>
12#include <framework/gearbox/GearDir.h>
13#include <framework/gearbox/Unit.h>
14#include <framework/geometry/VectorUtil.h>
16#include <Math/VectorUtil.h>
19#include <boost/format.hpp>
20#include <boost/foreach.hpp>
54 string Type = content.getString(
"@type",
"");
55 if (Type ==
"beamtest") {
100 for (
int i = 0; i < MAX_N_ALAYERS; i++) {
112 for (
int i = 0; i < MAXPTS_QE; i++) {
m_QE[i] = 0.;}
118 for (
int i = 0; i < 5; i++)
m_tileNphi[i] = 0;
128 GearDir detParams(content,
"Detector");
140 string Type = content.getString(
"@type",
"");
141 if (Type ==
"beamtest")
return;
145 GearDir mirrParams(content,
"Mirrors");
154 GearDir qeParams(content,
"QE");
159 for (
int i = 0; i < MAXPTS_QE; i++) {
161 stringstream ss;
string cc;
163 string path =
"Qeffi[@component='point-" + cc +
"']/";
170 GearDir aerogel(content,
"Aerogel");
187 GearDir mapping(content,
"FrontEndMapping");
190 unsigned mergerID = (unsigned) merger.getInt(
"@id");
194 B2ERROR(mapping.
getPath() <<
"/MergerID " << mergerID <<
195 " ***input already used");
200 std::vector<unsigned> boardIDs;
201 for (
const GearDir& board : merger.getNodes(
"FEboards/FEboard")) {
202 unsigned boardID = board.getInt();
205 B2ERROR(mapping.
getPath() <<
"/FEboardID " << boardID <<
206 " ***input already used");
208 boardIDs.push_back(boardID);
211 m_merger2feb.insert(std::pair<
int, std::vector<unsigned>>(mergerID, boardIDs));
212 unsigned copperID = (unsigned) merger.getInt(
"COPPERid");
213 string finesseSlot = merger.getString(
"FinesseSlot");
215 if (finesseSlot ==
"A") {finesse = 0;}
216 else if (finesseSlot ==
"B") {finesse = 1;}
217 else if (finesseSlot ==
"C") {finesse = 2;}
218 else if (finesseSlot ==
"D") {finesse = 3;}
220 B2ERROR(merger.getPath() <<
"/FinesseSlot " << finesseSlot <<
221 " ***invalid slot (valid are A, B, C, D)");
227 std::pair<unsigned, int> copfin(copperID, finesse);
228 m_copper2merger.insert(std::pair<std::pair<unsigned, int>,
unsigned>(copfin, mergerID));
236 auto merger =
m_copper2merger.find(std::pair<unsigned, int>(copperID, finesse));
243 return merger->second;
250 B2ERROR(
"getBoardFromMerger: " <<
" merger " << mergerID <<
" is not mapped");
253 if ((boards->second).size() <=
unsigned(slot)) {
254 B2ERROR(
"getBoardFromMerger: " <<
" merger " << mergerID <<
" slot " << slot <<
" is not assigned to FE board.");
257 return (boards->second).at(slot);
264 B2ERROR(
"getNBoardsOnMerger: " <<
" merger " << mergerID <<
" is not mapped");
266 return (boards->second).size();
271 istringstream chstream;
273 GearDir modParams(content,
"ModuleInfo");
274 uint8_t defqe = uint8_t(modParams.
getDouble(
"DefaultQE") * 100);
277 int modid = atoi(module.getString(
"@id",
"").c_str());
278 chstream.str(module.getString(
"ChannelsQE"));
279 while (chstream >> ch >> qq) {
280 int chid = (modid - 1) *
m_nPads + ch;
284 chstream.str(module.getString(
"DeadChannels"));
285 while (chstream >> ch) {
294 if (e < 0.001)
return 0;
296 if (dlam < 0)
return 0;
309 int id = (moduleID - 1) *
m_nPads + channelID;
318 ROOT::Math::XYVector locloc = position - chipPos;
321 if (locloc.X() < 0 || locloc.Y() < 0)
return -1;
322 if (ix > Npad - 1 || iy > Npad - 1)
return -1;
323 int chID = ChipID * Npad * Npad + iy + ix * Npad;
330 GearDir detParams(content,
"Detector/Plane/Rings");
339 B2WARNING(
m_ncol.size() + 1 <<
"th ring of ARICH photon detectors will not be placed (out of detector tube).");
343 int nSeg = ring.
getInt(
"nSegments") ;
346 double f = 2.*atan2((
m_modXSize + dFi) / 2., r);
347 int blaa = int(2.*M_PI / f / nSeg) * nSeg;
349 f = 2.*M_PI / double(blaa);
351 B2INFO(blaa <<
" modules of " <<
m_ncol.size() <<
"th ring of ARICH photon detectors will be placed at r = " << rcenter <<
"cm. ");
352 for (
int nv = 0; nv < blaa; ++nv) {
353 m_fR.push_back(rcenter);
354 double fi = f * (nv + 0.5);
360 B2INFO(
"Altogether " <<
m_fR.size() <<
" ARICH photon detector modules will be placed.");
365 BOOST_FOREACH(
const GearDir & module, content.getNodes(
"Detector/Plane/Modules/Module")) {
366 ROOT::Math::XYVector position(module.getLength(
"xPos"), module.getLength(
"yPos"));
367 double angle = module.getAngle(
"angle") /
Unit::rad;
368 m_fFi.push_back(position.Phi());
369 m_fR.push_back(position.R());
372 B2INFO(
"Altogether " <<
m_fR.size() <<
" ARICH photon detector modules will be placed.");
379 double r =
sqrt(x * x + y * y);
380 double fi = atan2(y, x);
381 if (fi < 0) fi += 2 * M_PI;
383 for (
int i = 0; i <
m_nrow; i++) {
384 int nfi = int(fi /
m_fDFi[i]);
385 int copyno = ntot + nfi;
394 const double amag = std::abs(
m_fR[copyNo - 1]);
395 const double phi =
m_fFi[copyNo - 1];
396 return ROOT::Math::XYZVector(amag * std::cos(phi), amag * std::sin(phi),
m_detZpos +
m_modZSize / 2.);
401 ROOT::Math::XYZVector origin =
getOrigin(copyNo);
422 if (locpos.X() > 0) {
423 if (locpos.Y() > 0)
return 0;
426 if (locpos.Y() > 0)
return 2;
433 int id = (modID - 1) *
m_nPads + chanID;
447 for (
int chipID = 0; chipID < 4; chipID++) {
449 for (
int ix = 0; ix < Npad; ix++) {
450 for (
int iy = 0; iy < Npad; iy++) {
451 int chanID = chipID * Npad * Npad + ix * Npad + iy;
453 center = center + chipPos;
459 const double magnitude = std::abs(
m_fR[iMod]);
460 const double phi =
m_fFi[iMod];
461 const double phiMod =
m_fFiMod[iMod];
462 const double iModCenterX = magnitude * std::cos(phi);
463 const double iModCenterY = magnitude * std::sin(phi);
467 const double cosPhiMod = std::cos(phiMod);
468 const double sinPhiMod = std::sin(phiMod);
469 const double iChanCenterRotatedX = iChanCenter.X() * cosPhiMod - iChanCenter.Y() * sinPhiMod;
470 const double iChanCenterRotatedY = iChanCenter.X() * sinPhiMod + iChanCenter.Y() * cosPhiMod;
471 ROOT::Math::XYVector iWorld(iModCenterX + iChanCenterRotatedX, iModCenterY + iChanCenterRotatedY);
491 double thick = content.getLength(
"Mirrors/thickness");
492 BOOST_FOREACH(
const GearDir & mirror, content.getNodes(
"Mirrors/Mirror")) {
493 double angle = mirror.
getAngle(
"angle");
494 ROOT::Math::XYZVector point(mirror.
getLength(
"xPos") - cos(angle)*thick / 2., mirror.
getLength(
"yPos") - sin(angle)*thick / 2., 0);
495 ROOT::Math::XYZVector norm(cos(angle), sin(angle), 0);
541 int m_DetectorMaskSize =
m_nPads * nmodules / 32 + 1;
542 for (
int i = 0; i < m_DetectorMaskSize; i++) {
545 B2INFO(
"DetectorMask initialized size=" <<
m_nPads <<
" * " << nmodules <<
" +1 =" << m_DetectorMaskSize);
551 int ch = (module - 1) *
m_nPads + channel;
553 unsigned int idx = ch / 32;
555 B2WARNING(idx <<
" Wrong detector mask size >= " <<
m_DetectorMask.size());
563 int ch = (module - 1) *
m_nPads + channel;
571 GearDir modParams(content,
"Mirrors/Alignment");
574 int id = atoi(plate.
getString(
"@id").c_str());
576 double dphi = plate.
getAngle(
"dphi");
577 double dtheta = plate.
getAngle(
"dtheta");
589 double r = locpos.R();
590 double phi = ROOT::Math::VectorUtil::Phi_0_2pi(locpos.Phi());
593 if (r < m_aeroRin + nr * size + m_tileGap / 2. || r >
m_aeroRin + (nr + 1)*size -
m_tileGap / 2.)
return 0;
595 double dphi = 2.*M_PI / double(
m_tileNphi[nr]);
598 int nphi = int(phi / dphi);
599 if (phi < nphi * dphi + gapPhi / 2. || phi > (nphi + 1)*dphi - gapPhi / 2.)
return 0;
602 for (
int i = 0; i < nr; i++) tileID +=
m_tileNphi[i];
The Class for ARICH Geometry Parameters.
double m_modXSize
Detector module length.
double m_tileGap
Gap size between two aerogel tiles.
double m_winThick
Thickness of detector module window.
double m_padSize
Detector pad size.
double m_chipGap
Gap between chips in detector module.
double m_LambdaFirst
wavelength [nm]: first QE data point
std::vector< ROOT::Math::XYZVector > m_mirrornorm
vector holding normal vectors of mirror plates
std::vector< ROOT::Math::XYVector > m_chipLocPos
vector holding chip positions (in detector module local coordinates)
double m_aeroRout
Outer radius of aerogel tube.
double m_detZpos
Z position of detector plane.
double m_detInnerRadius
Inner radius of detector tube.
double m_aeroRin
Inner radius of aerogel tube.
double m_mirrorOuterRad
Radius of circle outscribed to mirrors polygon.
double m_aeroZPosition[MAX_N_ALAYERS]
Array of aerogel Z positions.
double m_qeScale
QE scale factor for photons internally reflected in HAPD window.
double m_detOuterRadius
Outer radius of detector tube.
std::vector< double > m_fDR
minimal distance between detector modules in radial direction
int m_nrow
number of detector rings
double m_modZSize
Detector module height.
double m_aeroTrLength[MAX_N_ALAYERS]
Array of aerogel transmission lenths.
int m_NpointsQE
number of QE data points
std::unordered_set< unsigned int > m_boardIDs
FEB ID's.
std::unordered_set< unsigned int > m_mergerIDs
Merger ID's.
std::vector< double > m_fR
radial coordinate of detector modules
double m_LambdaStep
wavelength [nm]: step
int m_tileNphi[5]
Number of aerogel tiles in phi direction of each "radial" ring.
double m_winRefInd
Detector window refractive index.
std::vector< uint32_t > m_DetectorMask
Detector Mask of inactive channels.
double m_ColEffi
collection efficiency
bool m_simple
True if parametrization initialized with simple geometry (beamtest)
int m_nRad
Number of aerogel layers.
double m_mirrorZPos
Z position of mirror plates (starting z)
std::vector< double > m_fDFi
angle covered by one detector module in ring
double m_chipNegativeCrosstalk
to simulate opposite polarity crosstalk among channels on chip
double m_QE[MAXPTS_QE]
quantum efficiency curve
std::unordered_set< unsigned int > m_copperIDs
COPPER ID's.
double m_aeroRefIndex[MAX_N_ALAYERS]
Array of aerogel refracive indices.
std::vector< double > m_fFi
angular coordinate of detector modules
std::map< int, ROOT::Math::XYVector > m_padLocPositions
map holding channel local positions (in detector module local coordinates)
double m_windowAbsorbtion
absorbtion probability for photons internally reflected in HAPD window
std::map< std::pair< unsigned, int >, unsigned > m_copper2merger
mapping of merger boards to cooper boards
bool m_init
True if parametrization is already initialized.
int m_nPadX
Number of detector module pads in one direction.
int m_nPads
total number of pads in a sensor
std::vector< ROOT::Math::XYZVector > m_mirrorpoint
vector holding one point of each mirror plate
std::vector< ROOT::Math::XYVector > m_padWorldPositions
map holding channel global positions
std::vector< uint8_t > m_ChannelQE
Channel QE at 400nm.
std::vector< double > m_fFiMod
angle of detector module
double m_mirrorStartAng
The angle of first corner of mirror plates polygon.
double m_aeroThickness[MAX_N_ALAYERS]
Array of aerogel thickness.
int m_nMirrors
Number of mirrors segments.
std::map< int, std::vector< unsigned > > m_merger2feb
mapping of front-end boards to mergers
std::vector< int > m_ncol
m_ncol[i] gives number of detector modules in i-th detector ring (first one is the outer most)
int m_tileNr
Number of aerogel tiles in radial direction.
double m_mirrorThickness
Thickness of mirror plates.
GearDir is the basic class used for accessing the parameter store.
virtual std::string getString(const std::string &path="") const noexcept(false) override
Get the parameter path as a string.
static const double mm
[millimeters]
static const double rad
Standard of [angle].
static const double nm
[nanometers]
static const double cm
Standard units with the value = 1.
double getAngle(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard angle unit.
double getDouble(const std::string &path="") const noexcept(false)
Get the parameter path as a double.
std::string getPath() const
Return path of the current interface.
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
std::vector< GearDir > getNodes(const std::string &path="") const
Get vector of GearDirs which point to all the nodes the given path evaluates to.
int getInt(const std::string &path="") const noexcept(false)
Get the parameter path as a int.
ROOT::Math::XYVector getChipLocPos(int chipID)
get center position of chipID-th chip of detector module (in detector module local coordinates)
int getMergerFromCooper(int cooperID, int finesse)
returns merger board ID from cooperID and finesse
void setAeroTransLength(int ilayer, double trlen)
set transmission length of "ilayer" aerogel layer
int getBoardFromMerger(int mergerID, int slot)
returns front-end board ID from merger ID and slot
ROOT::Math::XYZVector getOrigin(int copyno)
get the position of copyno-th HAPD module origin
ARICHGeometryPar()
Constructor.
void mirrorPositions(const GearDir &content)
calculates parameters of all mirror planes (normal vector and point on plane)
int getChannelID(ROOT::Math::XYVector hit)
get ID number of channel containing point "hit" (hit is in detector module local coordinates)
void setAerogelThickness(int ilayer, double thick)
set thickness of "ilayer" aerogel layer
void modulesPositionSimple(const GearDir &content)
gets modules positions directly from xml file (for simple "beamtest" geometry).
void frontEndMapping(const GearDir &content)
reads front-end board to merger to cooper mapping from an xml file
void padPositions()
calculates the centers of channels in local (detector module) and global coordinates
int getNBoardsOnMerger(int mergerID)
returns number of front-end boards connected to the merger
void Initialize(const GearDir &content)
calculates detector parameters needed for geometry build and reconstruction.
void setAerogelZPosition(int ilayer, double zPos)
set z position of "ilayer" aerogel layer
void read(const GearDir &content)
gets geometry parameters from gearbox.
void Print(void) const
Print some debug information.
void mirrorPositionSimple(const GearDir &content)
Gets mirrors positions directly from xml file (in case of simple "beamtest" geometry).
static ARICHGeometryPar * Instance()
Static method to get a reference to the ARICHGeometryPar instance.
void setAeroRefIndex(int ilayer, double n)
set refractive index of "ilayer" aerogel layer
virtual ~ARICHGeometryPar()
Destructor.
double getModAngle(int copyno)
get the angle of copyno-th HAPD rotation
static ARICHGeometryPar * p_B4ARICHGeometryParDB
Pointer that saves the instance of this class.
G4ThreeVector getOriginG4(int copyNo)
get the position of copyNo-th HAPD module origin (returns G4ThreeVector)
void readMirrorAlignment(const GearDir &content)
Reads mirror plates alignment parameters.
int getNMCopies() const
get the total number of HAPD modules
ROOT::Math::XYZVector getMirrorNormal(int mirID)
get normal vector of mirID-th mirror plate
void setActive(int module, int channel, bool val)
set the channel on/off
void initDetectorMask(int nmodules)
initialize detector mask
int getChipID(ROOT::Math::XYVector locpos)
get ID number of chip containing point "locpos"
void setWindowRefIndex(double refInd)
set detector module window refractive index
void chipLocPosition()
calculates the centers of chips in detector module local coordinates
void readModuleInfo(const GearDir &content)
read parameters of each module from gearbox.
bool isActive(int module, int channel)
check the activity of the channel
double getChannelQE(int moduleID, int channelID)
get channel quantum efficiency
double QE(double e) const
get photocathode quantum efficiency at energy e.
int getAerogelTileID(ROOT::Math::XYVector locpos)
returns ID number of aerogel tile containing locpos (x-y) point.
int getCopyNo(const ROOT::Math::XYZVector &hit)
get the copy number of HAPD module containing point "hit"
ROOT::Math::XYZVector getChannelCenterGlob(int modID, int chanID)
get center of chanID channel of modID detector module (in global coordinates)
void modulesPosition(const GearDir &content)
calculates the positions of HAPD modules, with the parameters from xml.
ROOT::Math::XYVector getChannelCenterLoc(int chID)
get center position of chID channel (in detector module local coordinates)
ROOT::Math::XYZVector getMirrorPoint(int mirID)
get one point lying on mirID-th mirror plate
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.