9#include <beast/csi/geometry/CsiCreator.h>
10#include <beast/csi/simulation/SensitiveDetector.h>
11#include <beast/csi/geometry/CsiGeometryPar.h>
12#include <geometry/Materials.h>
13#include <geometry/CreatorFactory.h>
14#include <framework/gearbox/GearDir.h>
15#include <framework/logging/Logger.h>
18#include <boost/format.hpp>
19#include <G4AssemblyVolume.hh>
20#include <G4LogicalVolume.hh>
25#include <G4SubtractionSolid.hh>
28#include <G4VisAttributes.hh>
66 B2DEBUG(200,
"CsI Geometry Type: " << type);
74 G4Transform3D BrR = G4RotateZ3D(0.0);
76 int nEnc = content.getNumberNodes(
"/Enclosures/Enclosure");
78 G4AssemblyVolume* assemblyEnclosures =
new G4AssemblyVolume();
79 for (
int iEnc = 1; iEnc <= nEnc; iEnc++) {
84 assemblyEnclosures->MakeImprint(&topVolume, BrR);
87 B2INFO(
"Positions of the individual CsI crystals");
90 for (std::vector<G4VPhysicalVolume*>::iterator it = assemblyEnclosures->GetVolumesIterator();
91 i != assemblyEnclosures->TotalImprintedVolumes();
94 G4VPhysicalVolume* volume = *it;
95 string VolumeName = volume->GetName();
96 if (VolumeName.find(
"Crystal") < string::npos) {
98 " placed at (r[cm],[deg],z[cm]) = (" << setprecision(1) << fixed <<
99 volume->GetTranslation().perp() / CLHEP::cm <<
"," <<
100 volume->GetTranslation().phi() * 180.0 / M_PI <<
"," <<
101 volume->GetTranslation().z() / CLHEP::cm <<
")");
109 G4AssemblyVolume* assembly,
110 G4Transform3D position,
114 if (iCry <= 0)
return;
117 double foilthickness = counter.getLength(
"/Wrapping/Thickness") * CLHEP::cm;
121 int nCry = content.getNumberNodes(
"/EndCapCrystals/EndCapCrystal");
123 B2ERROR(
"CsiCreator: Crystal index too high");
127 counter.append((boost::format(
"/EndCapCrystals/EndCapCrystal[%1%]/") % (iCry)).str());
128 double h1 = counter.getLength(
"K_h1") * CLHEP::cm;
129 double h2 = counter.getLength(
"K_h2") * CLHEP::cm;
130 double bl1 = counter.getLength(
"K_bl1") * CLHEP::cm;
131 double bl2 = counter.getLength(
"K_bl2") * CLHEP::cm;
132 double tl1 = counter.getLength(
"K_tl1") * CLHEP::cm;
133 double tl2 = counter.getLength(
"K_tl2") * CLHEP::cm;
134 double alpha1 = counter.getAngle(
"K_alpha1");
135 double alpha2 = counter.getAngle(
"K_alpha2");
136 double halflength = counter.getLength(
"k_HalfLength") * CLHEP::cm;
139 string strMatCrystal = counter.getString(
"Material",
"Air");
143 G4VisAttributes* CrystalVisAtt =
new G4VisAttributes(G4Colour(1.0, 1.0, 0.0, 1.0));
145 if (strMatCrystal.compare(
"CsI") == 0) {
146 CrystalVisAtt->SetColour(18.0 / 256, 230.0 / 256, 3.0 / 256);
147 }
else if (strMatCrystal.compare(
"CsI-Tl") == 0) {
148 CrystalVisAtt->SetColour(0.0, 0.5, 1.0);
149 }
else if (strMatCrystal.compare(
"LYSO") == 0) {
150 CrystalVisAtt->SetColour(0.820, 0.148, 0.1875);
154 double fwtrapangle1 =
atan(2 * h1 / (bl1 - tl1));
155 double fwtrapangle2 =
atan(2 * h2 / (bl2 - tl2));
156 double foilh1 = h1 + foilthickness;
157 double foilh2 = h2 + foilthickness;
158 double foiltl1 = tl1 + foilthickness * tan(fwtrapangle1 / 2);
159 double foilbl1 = bl1 + foilthickness / tan(fwtrapangle1 / 2);
160 double foiltl2 = tl2 + foilthickness * tan(fwtrapangle2 / 2);
161 double foilbl2 = foiltl2 + (foilbl1 - foiltl1) * foilh2 / foilh1;
163 double foilhalflength = halflength + foilthickness;
166 string cryLogiVolName = (boost::format(
"Enclosure_%1%_Crystal_%2%") % iEnclosure % iCry).str();
167 G4Trap* CrystalShape =
new G4Trap((boost::format(
"sCrystal_%1%") % iCry).str().c_str(),
168 halflength, 0, 0, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2);
169 G4LogicalVolume* Crystal =
new G4LogicalVolume(CrystalShape, crystalMaterial,
170 cryLogiVolName.c_str(),
173 Crystal->SetVisAttributes(CrystalVisAtt);
180 G4Trap* Foilout =
new G4Trap((boost::format(
"Foilout_%1%") % iCry).str().c_str(),
181 foilhalflength, 0, 0, foilh1, foilbl1,
182 foiltl1, alpha1, foilh2, foilbl2,
185 G4Trap* Foilin =
new G4Trap((boost::format(
"solidEclCrystal_%1%") % iCry).str().c_str(),
189 G4SubtractionSolid* FoilShape =
new G4SubtractionSolid((boost::format(
"sFoil_%1%") % iCry).str().c_str(),
192 G4LogicalVolume* Foil =
new G4LogicalVolume(FoilShape, foilMaterial,
193 (boost::format(
"Foil_%1%") % iCry).str().c_str(),
196 G4VisAttributes* FoilVisAtt =
new G4VisAttributes(G4Colour(0.1, 0.1, 0.1, 0.5));
197 Foil->SetVisAttributes(FoilVisAtt);
200 Foil->SetVisAttributes(G4VisAttributes::GetInvisible());
202 assembly->AddPlacedVolume(Crystal, position);
203 assembly->AddPlacedVolume(Foil, position);
212 string gearPath =
"Enclosures/Enclosure";
213 int nEnclosures = content.getNumberNodes(gearPath);
215 if (iEnclosure > nEnclosures) {
216 B2ERROR(
"Enclosure index too high");
221 double width = content.getLength(
"Enclosures/Width") * CLHEP::cm;
222 double length = content.getLength(
"Enclosures/Length") * CLHEP::cm;
223 double depth = content.getLength(
"Enclosures/Depth") * CLHEP::cm;
224 double thk = content.getLength(
"Enclosures/Thickness") * CLHEP::cm;
225 double fold = content.getLength(
"Enclosures/Fold") * CLHEP::cm;
226 double lidthk = content.getLength(
"Enclosures/LidThickness") * CLHEP::cm;
227 double halflength = 15.0 * CLHEP::cm;
228 double zshift = 0.5 * length - thk - halflength;
230 string strMatEnclosure = content.getString(
"Enclosures/Material",
"5052-Alloy");
233 string strMatEncloLid = content.getString(
"Enclosures/LidMaterial",
"5052-Alloy");
236 G4Box* outer =
new G4Box(
"Outer", 0.5 * width, 0.5 * depth, 0.5 * length);
237 G4Box* inner =
new G4Box(
"Inner", 0.5 * width - thk, 0.5 * depth - thk, 0.5 * length - thk);
238 G4Box* opening =
new G4Box(
"Opening", 0.5 * width - fold, 0.5 * depth, 0.5 * length - fold);
239 G4Box* lid =
new G4Box(
"Lid", 0.5 * width, 0.5 * lidthk, 0.5 * length);
241 G4ThreeVector translation(0, thk, 0);
242 G4Translate3D transform(translation);
243 G4SubtractionSolid* enclosureShapeT =
new G4SubtractionSolid(
"EnclosureShapeT", outer, inner);
244 G4SubtractionSolid* enclosureShape =
new G4SubtractionSolid(
"EnclosureShape",
245 enclosureShapeT, opening, transform);
248 string enclosurePath = (boost::format(
"/%1%[%2%]") % gearPath % iEnclosure).str();
249 string logiVolName = (boost::format(
"%1%Enclosure_%2%") % side % iEnclosure).str();
250 string logiLidVolName = (boost::format(
"%1%EnclosureLid_%2%") % side % iEnclosure).str();
253 GearDir enclosureContent(content);
254 enclosureContent.
append(enclosurePath);
257 G4LogicalVolume* logiEnclosure =
new G4LogicalVolume(enclosureShape, EnclosureMat, logiVolName, 0, 0, 0);
258 G4LogicalVolume* logiEncloLid =
new G4LogicalVolume(lid, EncloLidMat, logiLidVolName, 0, 0, 0);
261 double PosZ = enclosureContent.
getLength(
"PosZ") * CLHEP::cm;
262 double PosR = enclosureContent.
getLength(
"PosR") * CLHEP::cm;
263 double PosT = enclosureContent.
getAngle(
"PosT") ;
266 double Phi1 = enclosureContent.
getAngle(
"AngPhi1") ;
267 double Theta = enclosureContent.
getAngle(
"AngTheta") ;
268 double Phi2 = enclosureContent.
getAngle(
"AngPhi2") ;
271 double AdjX = enclosureContent.
getLength(
"ShiftX") * CLHEP::cm;
272 double AdjY = enclosureContent.
getLength(
"ShiftY") * CLHEP::cm;
273 double AdjZ = enclosureContent.
getLength(
"ShiftZ") * CLHEP::cm;
275 G4Transform3D zsh = G4Translate3D(0, 0, zshift);
277 G4Transform3D m1 = G4RotateZ3D(Phi1);
278 G4Transform3D m2 = G4RotateY3D(Theta);
279 G4Transform3D m3 = G4RotateZ3D(Phi2);
280 G4Transform3D position = G4Translate3D(PosR * cos(PosT), PosR * sin(PosT), PosZ);
281 G4Transform3D adjust = G4Translate3D(AdjX, AdjY, AdjZ);
282 G4Transform3D lidpos = G4Translate3D(0, 0.5 * (depth + lidthk), 0);
284 G4Transform3D Tr = position * m3 * m2 * m1;
285 G4Transform3D ZshTr = Tr * zsh;
286 G4Transform3D ZshTrAdj = adjust * ZshTr;
287 G4Transform3D LidTr = ZshTr * lidpos;
288 G4Transform3D LidTrAdj = adjust * LidTr;
290 G4VisAttributes* VisAtt =
new G4VisAttributes(G4Colour(1.0, 0.5, 0.0, 0.5));
291 logiEnclosure->SetVisAttributes(VisAtt);
293 G4VisAttributes* LidVisAtt =
new G4VisAttributes(G4Colour(0.8, 1.0, 0.4, 0.5));
294 logiEncloLid->SetVisAttributes(LidVisAtt);
297 B2INFO(
"CsIBox No. " << iEnclosure <<
" Nominal pos. (mm): " << ZshTr.getTranslation());
298 B2INFO(
" Installed pos. (mm): " << ZshTrAdj.getTranslation());
299 B2INFO(
" Rotation matrix : " << ZshTrAdj.getRotation());
302 assembly->AddPlacedVolume(logiEnclosure, ZshTrAdj);
303 assembly->AddPlacedVolume(logiEncloLid, LidTrAdj);
308 for (
int iSlot = 1; iSlot <= nSlots; iSlot++) {
310 string slotPath = (boost::format(
"/Enclosures/Slot[%1%]") % iSlot).str();
313 slotContent.
append(slotPath);
315 double SlotX = slotContent.
getLength(
"PosX") * CLHEP::cm;
316 double SlotY = slotContent.
getLength(
"PosY") * CLHEP::cm;
317 double SlotZ = slotContent.
getLength(
"PosZ") * CLHEP::cm;
320 G4Transform3D Pos = G4Translate3D(SlotX, SlotY, SlotZ);
322 int CryID = enclosureContent.
getInt((boost::format(
"/CrystalInSlot[%1%]") % iSlot).str());
324 PutCrystal(content, assembly, adjust * Tr * Pos, iEnclosure, CryID);
GearDir is the basic class used for accessing the parameter store.
void append(const std::string &path)
Append something to the current path, modifying the GearDir in place.
virtual int getNumberNodes(const std::string &path="") const override
Return the number of nodes a given path will expand to.
virtual ~CsiCreator()
Destructor.
void BuildEnclosure(const GearDir &content, G4AssemblyVolume *assembly, std::string side, int iEnclosure)
Builds the crystals enclosures.
void PutCrystal(const GearDir &content, G4AssemblyVolume *assembly, G4Transform3D position, int iEnclosure, int iCry)
Builds the crystals and their wrapping (foil)
virtual void create(const GearDir &content, G4LogicalVolume &topVolume, geometry::GeometryTypes type)
Creation of the detector geometry from Gearbox (XML).
SensitiveDetector * m_sensitive
SensitiveDetector CSI.
The Class for CSI Geometry Parameters.
static CsiGeometryPar * Instance()
Static method to get a reference to the CsiGeometryPar instance.
int CsiVolNameToCellID(const G4String VolumeName)
Get Cell Id.
Sensitive Detector implementation of the CSI detector.
double getAngle(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard angle unit.
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
int getInt(const std::string &path="") const noexcept(false)
Get the parameter path as a int.
static G4Material * get(const std::string &name)
Find given material.
double atan(double a)
atan for double
const double avoidov
foil inside is a little bit lager than crystal to avoid overlap
geometry::CreatorFactory< CsiCreator > CsiFactory("CSICreator")
Creator creates the CSI geometry.
GeometryTypes
Flag indicating the type of geometry to be used.
Abstract base class for different kinds of events.
Very simple class to provide an easy way to register creators with the CreatorManager.