/* ErrorMsg */ void __cdecl ErrorMsg(const char* fmt, ...) { static FILE* pFile = NULL; DWORD dwWritten; char buf[5000]; char buf2[5000]; va_list va; va_start(va, fmt); vsprintf(buf, fmt, va); MessageBox(GetActiveWindow(), _Unicode(buf), TEXT_MAMEUINAME, MB_OK | MB_ICONERROR); strcpy(buf2, MAMEUINAME ": "); strcat(buf2,buf); strcat(buf2, "\n"); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), _Unicode(buf2), strlen(buf2), &dwWritten, NULL); if (pFile == NULL) pFile = fopen("debug.txt", "wt"); if (pFile != NULL) { fprintf(pFile, "%s", buf2); fflush(pFile); } va_end(va); }
double getAttrValueWithFallback(const DD4hep::XML::Component& node, const std::string& attrName, const double& defaultValue) { if (node.hasAttr(_Unicode(attrName.c_str()))) { return node.attr<double>(attrName.c_str()); } else { return defaultValue; } }
/** Simple cone using dimensions to be used to define cone composed of 1 single material @author Clement Helsens **/ static DD4hep::Geometry::Ref_t createSimpleCone(DD4hep::Geometry::LCDD& lcdd, xml_h e, DD4hep::Geometry::SensitiveDetector sensDet) { xml_det_t x_det = e; std::string name = x_det.nameStr(); DD4hep::Geometry::DetElement coneDet(name, x_det.id()); DD4hep::Geometry::Volume experimentalHall = lcdd.pickMotherVolume(coneDet); xml_comp_t coneDim(x_det.child(_U(dimensions))); DD4hep::Geometry::Cone cone(coneDim.dz(), coneDim.rmin1(), coneDim.rmax1(), coneDim.rmin2(), coneDim.rmax2()); DD4hep::Geometry::Volume coneVol(x_det.nameStr() + "_SimpleCone", cone, lcdd.material(coneDim.materialStr())); if (x_det.isSensitive()) { DD4hep::XML::Dimension sdType(x_det.child(_U(sensitive))); coneVol.setSensitiveDetector(sensDet); sensDet.setType(sdType.typeStr()); } DD4hep::Geometry::PlacedVolume conePhys; double zoff = coneDim.z_offset(); if (fabs(zoff) > 0.000000000001) { double reflectionAngle = 0.; if (coneDim.hasAttr(_Unicode(reflect))) { if (coneDim.reflect()) { reflectionAngle = M_PI; } } DD4hep::Geometry::Position trans(0., 0., zoff); conePhys = experimentalHall.placeVolume(coneVol, DD4hep::Geometry::Transform3D(DD4hep::Geometry::RotationX(reflectionAngle), trans)); } else conePhys = experimentalHall.placeVolume(coneVol); conePhys.addPhysVolID("system", x_det.id()); coneDet.setPlacement(conePhys); coneDet.setVisAttributes(lcdd, x_det.visStr(), coneVol); return coneDet; }
static DD4hep::Geometry::Ref_t createTkLayoutTrackerBarrel(DD4hep::Geometry::LCDD& lcdd, DD4hep::XML::Handle_t xmlElement, DD4hep::Geometry::SensitiveDetector sensDet) { // shorthands DD4hep::XML::DetElement xmlDet = static_cast<DD4hep::XML::DetElement>(xmlElement); Dimension dimensions(xmlDet.dimensions()); // get sensitive detector type from xml DD4hep::XML::Dimension sdTyp = xmlElement.child(_Unicode(sensitive)); // sensitive detector used for all sensitive parts of this detector sensDet.setType(sdTyp.typeStr()); // definition of top volume // has min/max dimensions of tracker for visualization etc. std::string detectorName = xmlDet.nameStr(); DetElement topDetElement(detectorName, xmlDet.id()); Acts::ActsExtension::Config barrelConfig; barrelConfig.isBarrel = true; // detElement owns extension Acts::ActsExtension* detWorldExt = new Acts::ActsExtension(barrelConfig); topDetElement.addExtension<Acts::IActsExtension>(detWorldExt); DD4hep::Geometry::Tube topVolumeShape( dimensions.rmin(), dimensions.rmax(), (dimensions.zmax() - dimensions.zmin()) * 0.5); Volume topVolume(detectorName, topVolumeShape, lcdd.air()); topVolume.setVisAttributes(lcdd.invisible()); // counts all layers - incremented in the inner loop over repeat - tags unsigned int layerCounter = 0; double integratedModuleComponentThickness = 0; double phi = 0; // loop over 'layer' nodes in xml DD4hep::XML::Component xLayers = xmlElement.child(_Unicode(layers)); for (DD4hep::XML::Collection_t xLayerColl(xLayers, _U(layer)); nullptr != xLayerColl; ++xLayerColl) { DD4hep::XML::Component xLayer = static_cast<DD4hep::XML::Component>(xLayerColl); DD4hep::XML::Component xRods = xLayer.child("rods"); DD4hep::XML::Component xRodEven = xRods.child("rodOdd"); DD4hep::XML::Component xRodOdd = xRods.child("rodEven"); DD4hep::XML::Component xModulesEven = xRodEven.child("modules"); DD4hep::XML::Component xModulePropertiesOdd = xRodOdd.child("moduleProperties"); DD4hep::XML::Component xModulesOdd = xRodOdd.child("modules"); DD4hep::Geometry::Tube layerShape(xLayer.rmin(), xLayer.rmax(), dimensions.zmax()); Volume layerVolume("layer", layerShape, lcdd.material("Air")); layerVolume.setVisAttributes(lcdd.invisible()); PlacedVolume placedLayerVolume = topVolume.placeVolume(layerVolume); placedLayerVolume.addPhysVolID("layer", layerCounter); DetElement lay_det(topDetElement, "layer" + std::to_string(layerCounter), layerCounter); Acts::ActsExtension::Config layConfig; layConfig.isLayer = true; // the local coordinate systems of modules in dd4hep and acts differ // see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html layConfig.axes = "XzY"; // correct translation of local x axis in dd4hep to local x axis in acts // detElement owns extension Acts::ActsExtension* layerExtension = new Acts::ActsExtension(layConfig); lay_det.addExtension<Acts::IActsExtension>(layerExtension); lay_det.setPlacement(placedLayerVolume); DD4hep::XML::Component xModuleComponentsOdd = xModulePropertiesOdd.child("components"); integratedModuleComponentThickness = 0; int moduleCounter = 0; Volume moduleVolume; for (DD4hep::XML::Collection_t xModuleComponentOddColl(xModuleComponentsOdd, _U(component)); nullptr != xModuleComponentOddColl; ++xModuleComponentOddColl) { DD4hep::XML::Component xModuleComponentOdd = static_cast<DD4hep::XML::Component>(xModuleComponentOddColl); moduleVolume = Volume("module", DD4hep::Geometry::Box(0.5 * xModulePropertiesOdd.attr<double>("modWidth"), 0.5 * xModuleComponentOdd.thickness(), 0.5 * xModulePropertiesOdd.attr<double>("modLength")), lcdd.material(xModuleComponentOdd.materialStr())); unsigned int nPhi = xRods.repeat(); DD4hep::XML::Handle_t currentComp; for (unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) { double lX = 0; double lY = 0; double lZ = 0; if (0 == phiIndex % 2) { phi = 2 * M_PI * static_cast<double>(phiIndex) / static_cast<double>(nPhi); currentComp = xModulesEven; } else { currentComp = xModulesOdd; } for (DD4hep::XML::Collection_t xModuleColl(currentComp, _U(module)); nullptr != xModuleColl; ++xModuleColl) { DD4hep::XML::Component xModule = static_cast<DD4hep::XML::Component>(xModuleColl); double currentPhi = atan2(xModule.Y(), xModule.X()); double componentOffset = integratedModuleComponentThickness - 0.5 * xModulePropertiesOdd.attr<double>("modThickness") + 0.5 * xModuleComponentOdd.thickness(); lX = xModule.X() + cos(currentPhi) * componentOffset; lY = xModule.Y() + sin(currentPhi) * componentOffset; lZ = xModule.Z(); DD4hep::Geometry::Translation3D moduleOffset(lX, lY, lZ); DD4hep::Geometry::Transform3D lTrafo(DD4hep::Geometry::RotationZ(atan2(lY, lX) + 0.5 * M_PI), moduleOffset); DD4hep::Geometry::RotationZ lRotation(phi); PlacedVolume placedModuleVolume = layerVolume.placeVolume(moduleVolume, lRotation * lTrafo); if (xModuleComponentOdd.isSensitive()) { placedModuleVolume.addPhysVolID("module", moduleCounter); moduleVolume.setSensitiveDetector(sensDet); DetElement mod_det(lay_det, "module" + std::to_string(moduleCounter), moduleCounter); mod_det.setPlacement(placedModuleVolume); ++moduleCounter; } } } integratedModuleComponentThickness += xModuleComponentOdd.thickness(); } ++layerCounter; } Volume motherVol = lcdd.pickMotherVolume(topDetElement); PlacedVolume placedGenericTrackerBarrel = motherVol.placeVolume(topVolume); placedGenericTrackerBarrel.addPhysVolID("system", topDetElement.id()); topDetElement.setPlacement(placedGenericTrackerBarrel); return topDetElement; }
void buildOneSide(MsgStream& lLog, DD4hep::Geometry::LCDD& aLcdd, DD4hep::Geometry::SensitiveDetector& aSensDet, DD4hep::Geometry::Volume& aEnvelope, DD4hep::XML::Handle_t& aXmlElement, int sign) { DD4hep::XML::Dimension dim(aXmlElement.child(_Unicode(dimensions))); DD4hep::XML::DetElement active = aXmlElement.child(_Unicode(active)); std::string activeMaterial = active.materialStr(); double activeThickness = active.thickness(); DD4hep::XML::DetElement readout = aXmlElement.child(_Unicode(readout)); std::string readoutMaterial = readout.materialStr(); double readoutThickness = readout.thickness(); DD4hep::XML::DetElement passive = aXmlElement.child(_Unicode(passive)); DD4hep::XML::DetElement passiveInner = passive.child(_Unicode(inner)); DD4hep::XML::DetElement passiveOuter = passive.child(_Unicode(outer)); DD4hep::XML::DetElement passiveGlue = passive.child(_Unicode(glue)); double passiveInnerThickness = passiveInner.thickness(); double passiveOuterThickness = passiveOuter.thickness(); double passiveGlueThickness = passiveGlue.thickness(); double passiveThickness = passiveInnerThickness + passiveOuterThickness + passiveGlueThickness; std::string passiveInnerMaterial = passiveInner.materialStr(); std::string passiveOuterMaterial = passiveOuter.materialStr(); std::string passiveGlueMaterial = passiveGlue.materialStr(); std::string passiveMaterial; if (passiveInnerThickness < passiveThickness) { passiveMaterial = "Air"; } else { passiveMaterial = passiveInnerMaterial; } DD4hep::Geometry::SensitiveDetector sensDet = aSensDet; DD4hep::XML::Dimension sensDetType = aXmlElement.child(_U(sensitive)); sensDet.setType(sensDetType.typeStr()); lLog << MSG::INFO << " rmin (cm) = " << dim.rmin1() << " rmin (cm) = " << dim.rmin2() << " rmax (cm) = " << dim.rmax() << " length (cm) = " << dim.dz() << " Sensitive volume of type: " << sensDetType.typeStr() << endmsg; double length = dim.dz() * 2; // First disc set is different: readout is first (HV), then half of active material, then absorber (GND) // Next disc sets have active material on both sides double lengthWithoutFirst = length - readoutThickness - activeThickness / 2. - passiveThickness; uint numDiscs = floor(lengthWithoutFirst / (activeThickness + readoutThickness + passiveThickness)); double marginOutside = (lengthWithoutFirst - numDiscs * (activeThickness + readoutThickness + passiveThickness)) / 2.; // add the first disc set to the number of all discs numDiscs += 1; lLog << MSG::INFO << "Thickness of active material in between absorbers (cm) = " << activeThickness << "\nThickness of absorber discs (cm) = " << passiveThickness << "\nThickness of readout disc placed in between absorber plates (cm) = " << readoutThickness << "\nNumber of absorber/readout discs: " << numDiscs << "\nMargin outside first readout disc and last absorber disc, filled with non-sensitive active medium (cm) = " << marginOutside << endmsg; lLog << MSG::INFO << "Detector length: (cm) " << length << endmsg; // Place components starting from closer to the collision-point double zOffset = (length / 2. - marginOutside) * -sign; double rMax = dim.rmax(); // First disc to place is readout zOffset += sign * (readoutThickness / 2.); double nonAbsorberRmin = std::min(dim.rmin1(), dim.rmin2()); double tanTheta = fabs(dim.rmin2() - dim.rmin1()) / (2 * dim.dz()); nonAbsorberRmin += (marginOutside + readoutThickness + activeThickness / 2.) * tanTheta; // for first readout position double dR1 = passiveThickness * tanTheta; // between readout and passive double dR2 = (activeThickness + readoutThickness + passiveThickness) * tanTheta; // between two readout discs DD4hep::Geometry::Tube readoutShapePre(nonAbsorberRmin, rMax, readoutThickness / 2.); DD4hep::Geometry::Tube activeShapePre(nonAbsorberRmin, rMax, activeThickness / 4.); DD4hep::Geometry::Volume readoutVolPre("readoutPre", readoutShapePre, aLcdd.material(readoutMaterial)); if (readout.isSensitive()) { lLog << MSG::INFO << "Readout volume set as sensitive" << endmsg; readoutVolPre.setSensitiveDetector(aSensDet); } DD4hep::Geometry::Volume activeVolPre("activePre", activeShapePre, aLcdd.material(activeMaterial)); activeVolPre.setSensitiveDetector(sensDet); DD4hep::Geometry::PlacedVolume readoutPhysVolPre = aEnvelope.placeVolume(readoutVolPre, DD4hep::Geometry::Position(0, 0, zOffset)); readoutPhysVolPre.addPhysVolID("layer", 0); readoutPhysVolPre.addPhysVolID("type", 2); // 0 = active, 1 = passive, 2 = readout std::vector<DD4hep::Geometry::PlacedVolume> activePhysVols; activePhysVols.reserve(numDiscs * 2); activePhysVols.push_back(aEnvelope.placeVolume( activeVolPre, DD4hep::Geometry::Position(0, 0, zOffset + sign * (readoutThickness / 2. + activeThickness / 4.)))); lLog << MSG::DEBUG << "Placing first readout at " << zOffset << " and active at z= " << zOffset + sign * (activeThickness / 4. + readoutThickness / 2.) << endmsg; // Now place complete sets of discs: absorber|active|readout|active zOffset += sign * (readoutThickness / 2. + activeThickness / 2. + passiveThickness / 2.); // Loop placing readout, active and passive discs for (uint iDiscs = 0; iDiscs < numDiscs - 1; iDiscs++) { nonAbsorberRmin += dR2; // readout and active discs have the same radius, but different thickness DD4hep::Geometry::Tube activeShapeBeforeSubtraction(nonAbsorberRmin, rMax, activeThickness / 2. + readoutThickness / 2.); DD4hep::Geometry::Tube readoutShape(nonAbsorberRmin, rMax, readoutThickness / 2.); DD4hep::Geometry::SubtractionSolid activeShape(activeShapeBeforeSubtraction, readoutShape); DD4hep::Geometry::Tube passiveShape(nonAbsorberRmin + dR1, rMax, passiveThickness / 2.); DD4hep::Geometry::Volume activeVol("active", activeShape, aLcdd.material(activeMaterial)); DD4hep::Geometry::Volume readoutVol("readout", readoutShape, aLcdd.material(readoutMaterial)); DD4hep::Geometry::Volume passiveVol("passive", passiveShape, aLcdd.material(passiveMaterial)); activeVol.setSensitiveDetector(sensDet); if (readout.isSensitive()) { lLog << MSG::DEBUG << "Passive inner volume set as sensitive" << endmsg; readoutVol.setSensitiveDetector(aSensDet); } if (passive.isSensitive()) { lLog << MSG::DEBUG << "Passive volume set as sensitive" << endmsg; passiveVol.setSensitiveDetector(aSensDet); } // absorber may consist of inner and outer material if (passiveInnerThickness < passiveThickness) { // create shapes DD4hep::Geometry::Tube passiveInnerShape(nonAbsorberRmin + dR1, rMax, passiveInnerThickness / 2.); DD4hep::Geometry::Tube passiveGlueShape(nonAbsorberRmin + dR1, rMax, passiveGlueThickness / 4.); DD4hep::Geometry::Tube passiveOuterShape(nonAbsorberRmin + dR1, rMax, passiveOuterThickness / 4.); // create volumes DD4hep::Geometry::Volume passiveInnerVol(passiveInnerMaterial + "_passive", passiveInnerShape, aLcdd.material(passiveInnerMaterial)); DD4hep::Geometry::Volume passiveOuterVol(passiveOuterMaterial + "_passive", passiveOuterShape, aLcdd.material(passiveOuterMaterial)); DD4hep::Geometry::Volume passiveGlueVol(passiveGlueMaterial + "_passive", passiveGlueShape, aLcdd.material(passiveGlueMaterial)); if (passive.isSensitive()) { lLog << MSG::INFO << "Passive volumes (inner, outer, glue) set as sensitive" << endmsg; passiveInnerVol.setSensitiveDetector(aSensDet); passiveOuterVol.setSensitiveDetector(aSensDet); passiveGlueVol.setSensitiveDetector(aSensDet); } // place volumes DD4hep::Geometry::PlacedVolume passiveInnerPhysVol = passiveVol.placeVolume(passiveInnerVol, DD4hep::Geometry::Position(0, 0, 0)); DD4hep::Geometry::PlacedVolume passiveOuterPhysVolBelow = passiveVol.placeVolume( passiveOuterVol, DD4hep::Geometry::Position(0, 0, passiveInnerThickness / 2. + passiveGlueThickness / 2. + passiveOuterThickness / 4.)); DD4hep::Geometry::PlacedVolume passiveOuterPhysVolAbove = passiveVol.placeVolume( passiveOuterVol, DD4hep::Geometry::Position(0, 0, -passiveInnerThickness / 2. - passiveGlueThickness / 2. - passiveOuterThickness / 4.)); DD4hep::Geometry::PlacedVolume passiveGluePhysVolBelow = passiveVol.placeVolume( passiveGlueVol, DD4hep::Geometry::Position(0, 0, -passiveInnerThickness / 2. - passiveGlueThickness / 4.)); DD4hep::Geometry::PlacedVolume passiveGluePhysVolAbove = passiveVol.placeVolume( passiveGlueVol, DD4hep::Geometry::Position(0, 0, passiveInnerThickness / 2. + passiveGlueThickness / 4.)); passiveInnerPhysVol.addPhysVolID("subtype", 0); passiveOuterPhysVolBelow.addPhysVolID("subtype", 1); passiveOuterPhysVolAbove.addPhysVolID("subtype", 2); passiveGluePhysVolBelow.addPhysVolID("subtype", 3); passiveGluePhysVolAbove.addPhysVolID("subtype", 4); } DD4hep::Geometry::PlacedVolume passivePhysVol = aEnvelope.placeVolume(passiveVol, DD4hep::Geometry::Position(0, 0, zOffset)); passivePhysVol.addPhysVolID("layer", iDiscs); passivePhysVol.addPhysVolID("type", 1); // 0 = active, 1 = passive, 2 = readout DD4hep::Geometry::PlacedVolume readoutPhysVol = aEnvelope.placeVolume( readoutVol, DD4hep::Geometry::Position(0, 0, zOffset + sign * (passiveThickness / 2. + activeThickness / 2. + readoutThickness / 2.))); readoutPhysVol.addPhysVolID("layer", iDiscs + 1); // +1 because first readout is placed before that loop readoutPhysVol.addPhysVolID("type", 2); // 0 = active, 1 = passive, 2 = readout activePhysVols.push_back(aEnvelope.placeVolume( activeVol, DD4hep::Geometry::Position(0, 0, zOffset + sign * (passiveThickness / 2. + activeThickness / 2. + readoutThickness / 2.)))); lLog << MSG::DEBUG << "Placing passive at z= " << zOffset << " readout at z= " << zOffset + sign * (passiveThickness / 2. + activeThickness / 2. + readoutThickness / 2.) << " active at " << zOffset + sign * (passiveThickness / 2. + activeThickness / 2. + readoutThickness / 2.) << endmsg; zOffset += sign * (readoutThickness + activeThickness + passiveThickness); if (iDiscs == numDiscs - 2) { // finish detector with the last disc of abosrber (for GND layer) DD4hep::Geometry::PlacedVolume passivePhysVolPost = aEnvelope.placeVolume(passiveVol, DD4hep::Geometry::Position(0, 0, zOffset)); passivePhysVolPost.addPhysVolID("layer", iDiscs + 1); passivePhysVolPost.addPhysVolID("type", 2); // 0 = active, 1 = passive, 2 = readout lLog << MSG::DEBUG << "Placing last passive disc at z= " << zOffset << endmsg; } for (uint iActive = 0; iActive < activePhysVols.size(); iActive++) { activePhysVols[iActive].addPhysVolID("layer", iActive + 1); // +1 because first active is placed before that loop activePhysVols[iActive].addPhysVolID("type", 0); // 0 = active, 1 = passive, 2 = readout } } return; }