Skip to content
Snippets Groups Projects

Resolve "Implement ce_MRICH"

Merged Chao Peng requested to merge 12-implement-ce_mrich into master
1 file
+ 132
8
Compare changes
  • Side-by-side
  • Inline
+ 132
8
@@ -16,6 +16,11 @@ using namespace dd4hep::rec;
@@ -16,6 +16,11 @@ using namespace dd4hep::rec;
typedef ROOT::Math::XYPoint Point;
typedef ROOT::Math::XYPoint Point;
 
std::vector<Point> fillSquares(Point ref, double lside, double rmin, double rmax,
 
double phmin = 0., double phmax = 2.*M_PI);
 
void addModules(Volume &mother, xml::DetElement &detElem, Detector &desc, SensitiveDetector &sens);
 
 
// create the detector
// create the detector
static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetector sens)
static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetector sens)
{
{
@@ -25,7 +30,6 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
@@ -25,7 +30,6 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
DetElement det(detName, detID);
DetElement det(detName, detID);
xml::Component dims = detElem.dimensions();
xml::Component dims = detElem.dimensions();
xml::Component mods = detElem.child(_Unicode(modules));
xml::Component rads = detElem.child(_Unicode(radiator));
xml::Component rads = detElem.child(_Unicode(radiator));
auto RIn = dims.attr<double>(_Unicode(r_in));
auto RIn = dims.attr<double>(_Unicode(r_in));
@@ -34,18 +38,15 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
@@ -34,18 +38,15 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
auto PosZ = dims.z();
auto PosZ = dims.z();
auto InnerR = dims.attr<double>(_Unicode(inner_r));
auto InnerR = dims.attr<double>(_Unicode(inner_r));
auto mThick = mods.attr<double>(_Unicode(thickness));
auto gasMat = desc.material(detElem.materialStr());
auto mWidth = mods.attr<double>(_Unicode(width));
auto mGap = mods.attr<double>(_Unicode(gap));
auto envMat = desc.material(detElem.materialStr());
// detector envelope
// detector envelope
auto envShape = Tube(RIn, ROut, SizeZ / 2., 0., 2*M_PI);
Tube envShape(RIn, ROut, SizeZ / 2., 0., 2*M_PI);
Volume envVol("ce_MRICH_GVol", envShape, envMat);
Volume envVol("ce_MRICH_GVol", envShape, gasMat);
envVol.setVisAttributes(desc.visAttributes(detElem.visStr()));
envVol.setVisAttributes(desc.visAttributes(detElem.visStr()));
// modules
// modules
 
addModules(envVol, detElem, desc, sens);
// place envelope
// place envelope
Volume motherVol = desc.pickMotherVolume(det);
Volume motherVol = desc.pickMotherVolume(det);
@@ -56,6 +57,129 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
@@ -56,6 +57,129 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
}
}
 
void addModules(Volume &mother, xml::DetElement &detElem, Detector &desc, SensitiveDetector &sens)
 
{
 
xml::Component dims = detElem.dimensions();
 
xml::Component mods = detElem.child(_Unicode(modules));
 
 
auto ROut = dims.attr<double>(_Unicode(r_out));
 
auto mThick = mods.attr<double>(_Unicode(thickness));
 
auto mWidth = mods.attr<double>(_Unicode(width));
 
auto mGap = mods.attr<double>(_Unicode(gap));
 
auto InnerR = dims.attr<double>(_Unicode(inner_r));
 
 
auto modMat = desc.material(mods.materialStr());
 
auto gasMat = desc.material(detElem.materialStr());
 
 
// single module
 
Box mShape(mWidth/2., mWidth/2., mThick/2. - 0.1*mm);
 
Volume mVol("ce_MRICH_mod_Solid", mShape, modMat);
 
 
// a thin gas layer to detect optical photons
 
Box modShape(mWidth/2., mWidth/2., mThick/2.);
 
Volume modVol("ce_MRICH_mod_Solid_v", modShape, gasMat);
 
// thin gas layer is on top (+z) of the material
 
modVol.placeVolume(mVol, Position(0., 0., -0.1*mm));
 
 
modVol.setVisAttributes(desc.visAttributes(mods.visStr()));
 
sens.setType("photoncounter");
 
modVol.setSensitiveDetector(sens);
 
 
double MRICH_R, x_mrich = 0., y_mrich = 0;
 
int kmrich = -1;
 
 
// place modules in the sectors (disk)
 
auto points = fillSquares(Point(0., 0.), mWidth + mGap, InnerR, ROut + mGap);
 
 
// determine module direction, always facing z = 0
 
double roty = dims.z() > 0. ? M_PI/2. : -M_PI/2.;
 
int imod = 1;
 
for (auto &p : points) {
 
// operations are inversely ordered
 
Transform3D tr = Translation3D(p.x(), p.y(), 0.) // move to position
 
* RotationY(roty); // facing z = 0.
 
auto modPV = mother.placeVolume(modVol, tr);
 
modPV.addPhysVolID("sector", 1).addPhysVolID("module", imod ++);
 
}
 
}
 
 
// check if a square in a ring
 
inline bool in_ring(const Point &pt, double side, double rmin, double rmax, double phmin, double phmax)
 
{
 
if (pt.r() > rmax || pt.r() < rmin) {
 
return false;
 
}
 
 
// check four corners
 
std::vector<Point> pts {
 
Point(pt.x() - side/2., pt.y() - side/2.),
 
Point(pt.x() - side/2., pt.y() + side/2.),
 
Point(pt.x() + side/2., pt.y() - side/2.),
 
Point(pt.x() + side/2., pt.y() + side/2.),
 
};
 
for (auto &p : pts) {
 
if (p.r() > rmax || p.r() < rmin || p.phi() > phmax || p.phi() < phmin) {
 
return false;
 
}
 
}
 
return true;
 
}
 
 
// check if a square is overlapped with the others
 
inline bool overlap(const Point &pt, double side, const std::vector<Point> &pts)
 
{
 
for (auto &p : pts) {
 
auto pn = (p - pt)/side;
 
if ((std::abs(pn.x()) < 1. - 1e-6) && (std::abs(pn.y()) < 1. - 1e-6)) {
 
return true;
 
}
 
}
 
return false;
 
}
 
 
// a helper function to recursively fill square in a ring
 
void add_square(Point p, std::vector<Point> &res, double lside, double rmin, double rmax,
 
double phmin, double phmax)
 
{
 
// outside of the ring or overlapping
 
if (!in_ring(p, lside, rmin, rmax, phmin, phmax) || overlap(p, lside, res)) {
 
return;
 
}
 
 
res.emplace_back(p);
 
 
// check adjacent squares
 
add_square(Point(p.x() + lside, p.y()), res, lside, rmin, rmax, phmin, phmax);
 
add_square(Point(p.x() - lside, p.y()), res, lside, rmin, rmax, phmin, phmax);
 
add_square(Point(p.x(), p.y() + lside), res, lside, rmin, rmax, phmin, phmax);
 
add_square(Point(p.x(), p.y() - lside), res, lside, rmin, rmax, phmin, phmax);
 
}
 
 
// fill squares
 
std::vector<Point> fillSquares(Point ref, double lside, double rmin, double rmax, double phmin, double phmax)
 
{
 
// start with a seed square and find one in the ring
 
// move to center
 
ref = ref - Point(int(ref.x()/lside)*lside, int(ref.y()/lside)*lside);
 
 
auto find_seed = [] (const Point &ref, int n, double side, double rmin, double rmax, double phmin, double phmax) {
 
for (int ix = -n; ix < n; ++ix) {
 
for (int iy = -n; iy < n; ++iy) {
 
Point pt(ref.x() + ix*side, ref.y() + iy*side);
 
if (in_ring(pt, side, rmin, rmax, phmin, phmax)) {
 
return pt;
 
}
 
}
 
}
 
return ref;
 
};
 
 
std::vector<Point> res;
 
ref = find_seed(ref, int(rmax/lside) + 2, lside, rmin, rmax, phmin, phmax);
 
add_square(ref, res, lside, rmin, rmax, phmin, phmax);
 
return res;
 
}
 
// clang-format off
// clang-format off
DECLARE_DETELEMENT(ce_MRICH, createDetector)
DECLARE_DETELEMENT(ce_MRICH, createDetector)
Loading