diff --git a/CMakeLists.txt b/CMakeLists.txt index 83cdee5db2b2452993934c7a785a4176d86fae41..aa896f49c2aca7891785cd07a7d8c1c3b0e16fc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ dd4hep_add_plugin(${a_lib_name} src/IP6BeamPipe.cpp src/magnetVacuumFF.cpp src/OffMomentumTracker_geo.cpp + src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp src/ZeroDegreeCalorimeterEcal_geo.cpp src/ZeroDegreeCalorimeterSampling_geo.cpp USES ActsCore ActsPluginDD4hep ROOT::Core ROOT::Gdml diff --git a/ip6/far_forward_ZDC_Ecal_WSciFi.xml b/ip6/far_forward_ZDC_Ecal_WSciFi.xml new file mode 100644 index 0000000000000000000000000000000000000000..301a67209763baca8ea50c7cac8b89b0ca385701 --- /dev/null +++ b/ip6/far_forward_ZDC_Ecal_WSciFi.xml @@ -0,0 +1,42 @@ +<lccdd> + <comment> + ////////////////////////////////////////////////// + // Far Forward Ion Zero Degree Calorimeter + // W power + SciFi for Ecal + ////////////////////////////////////////////////// + </comment> + + <define> + <constant name="ffi_ZDC_ECAL_FiberRadius" value="0.235*mm"/> + <constant name="ffi_ZDC_ECAL_FiberOffset" value="0.5*mm"/> + <constant name="ffi_ZDC_ECAL_FiberSpaceX" value="0.265*mm"/> + <constant name="ffi_ZDC_ECAL_FiberSpaceY" value="0.425*mm"/> + </define> + + <detectors> + <detector id="ffi_ZDC_ECAL_ID" + name="ffi_ZDC_ECAL" + type="ZDCEcalScFiCalorimeter" + vis="ffi_ZDC_ECAL_Vis" + readout="ffi_ZDC_ECAL_Hits"> + <position x="ffi_ZDC_ECAL_x_pos" y="ffi_ZDC_ECAL_y_pos" z="ffi_ZDC_ECAL_z_pos"/> + <rotation x="ffi_ZDC_ECAL_rotateX_angle" y="ffi_ZDC_ECAL_rotateY_angle" z="ffi_ZDC_ECAL_rotateZ_angle"/> + <dimensions x="ffi_ZDC_ECAL_width" z="ffi_ZDC_ECAL_length"/> + <module sizex="25*mm" sizey="25*mm" sizez="170*mm" material="WSciFi_UCLA_Abs" vis="ffi_ZDC_ECAL_module_Vis"> + <fiber material="PlasticScint" + radius="ffi_ZDC_ECAL_FiberRadius" + offset="ffi_ZDC_ECAL_FiberOffset" + spacex="ffi_ZDC_ECAL_FiberSpaceX" + spacey="ffi_ZDC_ECAL_FiberSpaceY"/> + </module> + </detector> + </detectors> + + <readouts> + <readout name="ffi_ZDC_ECAL_Hits"> + <segmentation type="NoSegmentation"/> + <id>system:8,module:28,fiber_x:8,fiber_y:8</id> + </readout> + </readouts> + +</lccdd> diff --git a/ip6/far_forward_ZDC_Hcal.xml b/ip6/far_forward_ZDC_Hcal.xml index 871826fabde3e942ff36ef3a1218f9a752c8cc8b..aabac9ea3af8dd59b0b7f565e4589f70762242d1 100644 --- a/ip6/far_forward_ZDC_Hcal.xml +++ b/ip6/far_forward_ZDC_Hcal.xml @@ -11,55 +11,26 @@ <position x="ffi_ZDC_HCAL_x_pos" y="ffi_ZDC_HCAL_y_pos" z="ffi_ZDC_HCAL_z_pos"/> <rotation x="ffi_ZDC_HCAL_rotateX_angle" y="ffi_ZDC_HCAL_rotateY_angle" z="ffi_ZDC_HCAL_rotateZ_angle"/> <dimensions x="ffi_ZDC_HCAL_width" z="ffi_ZDC_HCAL_length"/> - - <layer repeat="ffi_ZDC_Gap_NRepeat"> - <slice name="Gap_slice" material="Air" thickness="ffi_ZDC_Gap_Thickness" vis="InvisibleNoDaughters"/> - </layer> - <layer repeat="ffi_ZDC_PbScint_NRepeat"> - <slice name="Lead_slice" material="Pb" thickness="ffi_ZDC_Lead_Thickness" vis="BlueGreenVis"/> - <slice name="Scint_slice" material="ZDC_Scintillator" thickness="ffi_ZDC_Scint_Thickness" vis="AnlOrange" sensitive="true"/> - <slice name="Air_4_slice" material="Air" thickness="ffi_ZDC_Air_4_Thickness" vis="InvisibleNoDaughters"/> - </layer> - <layer repeat="ffi_ZDC_SiPb_NRepeat"> - <slice name="Lead_slice" material="Pb" thickness="ffi_ZDC_Lead_Thickness" vis="BlueGreenVis"/> - <slice name="Glue_1_slice" material="ZDC_EpoxyGlue" thickness="ffi_ZDC_Glue_1_Thickness" vis="AnlGold"/> - <slice name="Silicon_2_slice" material="Silicon" thickness="ffi_ZDC_Silicon_2_Thickness" vis="RedVis" sensitive="true"/> - <slice name="Glue_2_slice" material="ZDC_EpoxyGlue" thickness="ffi_ZDC_Glue_2_Thickness" vis="AnlGold"/> - <slice name="FPC_slice" material="ZDC_EpoxyGlue" thickness="ffi_ZDC_FPC_Thickness" vis="AnlGold"/> - <slice name="Air_3_slice" material="Air" thickness="ffi_ZDC_Air_3_Thickness" vis="InvisibleNoDaughters"/> - </layer> - - <layer repeat="ffi_ZDC_Gap_NRepeat"> - <slice name="Gap_slice" material="Air" thickness="ffi_ZDC_Gap_Thickness" vis="InvisibleNoDaughters"/> - </layer> <layer repeat="ffi_ZDC_PbScint_NRepeat"> - <slice name="Lead_slice" material="Pb" thickness="ffi_ZDC_Lead_Thickness" vis="BlueGreenVis"/> + <slice name="Lead_slice" material="Pb" thickness="ffi_ZDC_Lead_Thickness" vis="AnlGray"/> <slice name="Scint_slice" material="ZDC_Scintillator" thickness="ffi_ZDC_Scint_Thickness" vis="AnlOrange" sensitive="true"/> - <slice name="Air_4_slice" material="Air" thickness="ffi_ZDC_Air_4_Thickness" vis="InvisibleNoDaughters"/> + <slice name="Air_4_slice" material="Air" thickness="ffi_ZDC_Air_4_Thickness" vis="InvisibleNoDaughters"/> </layer> </detector> </detectors> <define> - <constant name="ZDC_HCAL_PbScint1Min_index" value="1 + ffi_ZDC_Gap_NRepeat" /> - <constant name="ZDC_HCAL_PbScint1Max_index" value="ZDC_HCAL_PbScint1Min_index + ffi_ZDC_PbScint_NRepeat - 1" /> - <constant name="ZDC_HCAL_SiPbMin_index" value="ZDC_HCAL_PbScint1Max_index + 1" /> - <constant name="ZDC_HCAL_SiPbMax_index" value="ZDC_HCAL_SiPbMin_index + ffi_ZDC_SiPb_NRepeat - 1" /> - <constant name="ZDC_HCAL_PbScint2Min_index" value="1 + ZDC_HCAL_SiPbMin_index + ffi_ZDC_Gap_NRepeat" /> - <constant name="ZDC_HCAL_PbScint2Max_index" value="ZDC_HCAL_PbScint2Min_index + ffi_ZDC_PbScint_NRepeat - 1" /> + <constant name="ZDC_HCAL_PbScintMin_index" value="1" /> + <constant name="ZDC_HCAL_PbScintMax_index" value="ZDC_HCAL_PbScintMin_index + ffi_ZDC_PbScint_NRepeat - 1" /> </define> <readouts> <readout name="ffi_ZDC_HCAL_Hits"> <segmentation type="MultiSegmentation" key="layer"> - <segmentation name="Si_LG_grid" type="CartesianGridXY" key_min="ZDC_HCAL_SiPbMin_index" key_max="ZDC_HCAL_SiPbMax_index" grid_size_x="1.0*cm" grid_size_y="1.0*cm"/> - <segmentation name="Scint_grid" type="CartesianGridXY" key_min="ZDC_HCAL_PbScint1Min_index" key_max="ZDC_HCAL_PbScint1Max_index" grid_size_x="10.0*cm" grid_size_y="10.0*cm"/> - <segmentation name="Scint_grid" type="CartesianGridXY" key_min="ZDC_HCAL_PbScint2Min_index" key_max="ZDC_HCAL_PbScint2Max_index" grid_size_x="10.0*cm" grid_size_y="10.0*cm"/> + <segmentation name="Scint_grid" type="CartesianGridXY" key_min="ZDC_HCAL_PbScintMin_index" key_max="ZDC_HCAL_PbScintMax_index" grid_size_x="10.0*cm" grid_size_y="10.0*cm"/> </segmentation> <hits_collections> - <hits_collection name="ffiZDCScintHits" key="layer" key_min="ZDC_HCAL_PbScint1Min_index" key_max="ZDC_HCAL_PbScint1Max_index"/> - <hits_collection name="ffiZDCSiPbHits" key="layer" key_min="ZDC_HCAL_SiPbMin_index" key_max="ZDC_HCAL_SiPbMax_index"/> - <hits_collection name="ffiZDCScintHits" key="layer" key_min="ZDC_HCAL_PbScint2Min_index" key_max="ZDC_HCAL_PbScint2Max_index"/> + <hits_collection name="ffiZDCPbScintHits" key="layer" key_min="ZDC_HCAL_PbScintMin_index" key_max="ZDC_HCAL_PbScintMax_index"/> </hits_collections> <id>system:8,layer:12,slice:12,x:32:-16,y:-16</id> </readout> diff --git a/ip6/far_forward_detectors.xml b/ip6/far_forward_detectors.xml index ecc61d66aefa41c71214d9a861d6df7d9f1b4158..ca5790f673eca2e8c8113cb8eb060b70935320fa 100644 --- a/ip6/far_forward_detectors.xml +++ b/ip6/far_forward_detectors.xml @@ -40,7 +40,8 @@ <constant name="ffi_ZDC_Air_2_Thickness" value="3.0 * cm"/> <constant name="ffi_ZDC_ECAL_layer_thickness" value="ffi_ZDC_Silicon_1_Thickness + ffi_ZDC_Glue_1_Thickness + ffi_ZDC_FPC_Thickness + ffi_ZDC_Air_1_Thickness + ffi_ZDC_WSciFi_Thickness + ffi_ZDC_Air_2_Thickness"/> - <constant name="ffi_ZDC_ECAL_length" value="ffi_ZDC_SiWSciFi_NRepeat * ffi_ZDC_ECAL_layer_thickness"/> + <!--<constant name="ffi_ZDC_ECAL_length" value="ffi_ZDC_SiWSciFi_NRepeat * ffi_ZDC_ECAL_layer_thickness"/>--> + <constant name="ffi_ZDC_ECAL_length" value="170.0 * mm"/> <comment> ------------------------------- @@ -56,9 +57,9 @@ <constant name="ffi_ZDC_HCAL_width" value="ffi_ZDC_width"/> <constant name="ffi_ZDC_HCAL_length" value="ffi_ZDC_length"/> - <constant name="ffi_ZDC_SiPb_NRepeat" value="2"/> <!-- changed from 12 --> - <constant name="ffi_ZDC_PbScint_NRepeat" value="19"/> - <constant name="ffi_ZDC_Gap_NRepeat" value="1"/> + <constant name="ffi_ZDC_SiPb_NRepeat" value="0"/> <!-- changed from 12 --> + <constant name="ffi_ZDC_PbScint_NRepeat" value="35"/> + <constant name="ffi_ZDC_Gap_NRepeat" value="0"/> <constant name="ffi_ZDC_Silicon_2_Thickness" value="320.0 * um"/> <constant name="ffi_ZDC_Tungsten_Thickness" value="3.5 * mm"/> @@ -79,7 +80,7 @@ <display> </display> - <include ref="far_forward_ZDC_Ecal.xml"/> + <include ref="far_forward_ZDC_Ecal_WSciFi.xml"/> <include ref="far_forward_ZDC_Hcal.xml"/> <detectors> diff --git a/ip6/ip6_display.xml b/ip6/ip6_display.xml index 813f4a82eedae163c3147af8b00f7d9194daeb21..ddfb250a7ad65c73336a82b5b45c093796f771ba 100644 --- a/ip6/ip6_display.xml +++ b/ip6/ip6_display.xml @@ -44,12 +44,12 @@ <comment> - Old visualization code that should be integrated in the new color scheme + ZDC visualization </comment> - <vis name="ffi_ZDC_ECAL_Vis" alpha="0.1" r= "0.1" g="0.0" b="1.0" showDaughters="true" visible="true"/> - <vis name="ffi_ZDC_ECAL_module_Vis" alpha="1.0" r= "0.1" g="1.0" b="0.9" showDaughters="true" visible="true"/> - <vis name="ffi_ZDC_HCAL_Vis" alpha="0.1" r= "0.1" g="0.0" b="1.0" showDaughters="true" visible="true"/> + <vis name="ffi_ZDC_ECAL_Vis" ref="AnlGreen" showDaughters="true" visible="true"/> + <vis name="ffi_ZDC_ECAL_module_Vis" ref="AnlRed" showDaughters="false" visible="true"/> + <vis name="ffi_ZDC_HCAL_Vis" ref="AnlBlue" showDaughters="true" visible="true"/> <comment> Deprecated color scheme diff --git a/ip6/materials.xml b/ip6/materials.xml index e28b2ddef5745f88f3426b7c8328fc8f4e38b610..72961aa1898ef3eaa94cf1ae8b8e80ed911e2f09 100644 --- a/ip6/materials.xml +++ b/ip6/materials.xml @@ -214,4 +214,9 @@ <composite n="0.009" ref="H"/> <composite n="0.041" ref="C"/> </material> + <material name="WSciFi_UCLA_Abs"> + <D type="density" value="12.4" unit="g / cm3"/> + <fraction n="0.96" ref="W"/> + <fraction n="0.04" ref="Polystyrene"/> + </material> </materials> diff --git a/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp b/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..82d93de86d5ab57da2f25db4672b55fe42576402 --- /dev/null +++ b/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp @@ -0,0 +1,132 @@ +#include "DDRec/Surface.h" +#include "DDRec/DetectorData.h" +#include "DD4hep/OpticalSurfaces.h" +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Printout.h" +#include <XML/Helper.h> +#include <iostream> +#include <algorithm> +#include <tuple> +#include <math.h> +////////////////////////////////////////////////// +// Far Forward Ion Zero Degree Calorimeter - Ecal +// Reference from ATHENA ScFiCalorimeter_geo.cpp +////////////////////////////////////////////////// + +using namespace std; +using namespace dd4hep; + +// main +static Ref_t create_detector(Detector& desc, xml::Handle_t handle, SensitiveDetector sens) +{ + xml::DetElement detElem = handle; + std::string detName = detElem.nameStr(); + int detID = detElem.id(); + DetElement det(detName, detID); + sens.setType("calorimeter"); + auto dim = detElem.dimensions(); + auto width = dim.x(); + auto length = dim.z(); + xml_dim_t pos = detElem.position(); + xml_dim_t rot = detElem.rotation(); + + // envelope + Box envShape(width * 0.5, width * 0.5, length * 0.5); + Volume env(detName + "_envelope", envShape, desc.material("Air")); + env.setVisAttributes(desc.visAttributes(detElem.visStr())); + + // build module + xml_comp_t mod_x = detElem.child(_Unicode(module)); + auto sx = mod_x.attr<double>(_Unicode(sizex)); + auto sy = mod_x.attr<double>(_Unicode(sizey)); + auto sz = mod_x.attr<double>(_Unicode(sizez)); + + Box modShape(sx/2., sy/2., sz/2.); + auto modMat = desc.material(mod_x.attr<std::string>(_Unicode(material))); + Volume modVol("module_vol", modShape, modMat); + modVol.setVisAttributes(desc.visAttributes(mod_x.visStr())); + //modVol.setSensitiveDetector(sens); + + if (mod_x.hasChild("fiber")) { + auto fiber_x = mod_x.child(_Unicode(fiber)); + auto fr = fiber_x.attr<double>(_Unicode(radius)); + auto fsx = fiber_x.attr<double>(_Unicode(spacex)); + auto fsy = fiber_x.attr<double>(_Unicode(spacey)); + auto foff = dd4hep::getAttrOrDefault<double>(fiber_x, _Unicode(offset), 0.5*mm); + auto fiberMat = desc.material(fiber_x.attr<std::string>(_Unicode(material))); + Tube fiberShape(0., fr, sz/2. - 1.*mm); + Volume fiberVol("fiber_vol", fiberShape, fiberMat); + fiberVol.setSensitiveDetector(sens); + + // Fibers are placed in a honeycomb with the radius = sqrt(3)/2. * hexagon side length + // So each fiber is fully contained in a regular hexagon, which are placed as + // the parameters space x and space y are used to add additional spaces between the hexagons + double fside = 2. / std::sqrt(3.) * fr; + double fdistx = 2. * fside + fsx; + double fdisty = 2. * fr + fsy; + + // maximum numbers of the fibers, help narrow the loop range + int nx = int(sx / (2.*fr)) + 1; + int ny = int(sy / (2.*fr)) + 1; + + // place the fibers + double y0 = (foff + fside); + int nfibers = 0; + for (int iy = 0; iy < ny; ++iy) { + double y = y0 + fdisty * iy; + // about to touch the boundary + if ((sy - y) < y0) { break; } + double x0 = (iy % 2) ? (foff + fside) : (foff + fside + fdistx / 2.); + for (int ix = 0; ix < nx; ++ix) { + double x = x0 + fdistx * ix; + // about to touch the boundary + if ((sx - x) < x0) { break; } + auto fiberPV = modVol.placeVolume(fiberVol, nfibers++, Position{x - sx/2., y - sy/2., 0}); + fiberPV.addPhysVolID("fiber_x", ix + 1).addPhysVolID("fiber_y", iy + 1); + } + } + // if no fibers we make the module itself sensitive + } else { + modVol.setSensitiveDetector(sens); + } + + // Module Position + double mod_x_pos = 0.0; + double mod_y_pos = 0.0; + double mod_z_pos = 0.0 * mm; + double mgap = sx/100.; // 0.000001 * mm; + int mNTowers = floor(width / (sx+mgap)); + //std::cout << "mNTowers: " << mNTowers << std::endl; + + int k = 0; + // Place Modules + for (int j=0; j < mNTowers; j++) + { + if (j == 0) + mod_y_pos = width * 0.5 - (sy + mgap) * 0.5; + else + mod_y_pos -= (sy + mgap); + + for (int i=0; i < mNTowers; i++) + { + if (i == 0) + mod_x_pos = width * 0.5 - (sx + mgap) * 0.5; + else + mod_x_pos -= (sx + mgap); + + PlacedVolume pv_mod = env.placeVolume(modVol, Position(mod_x_pos,mod_y_pos,mod_z_pos)); + pv_mod.addPhysVolID("module",k++); + //std::cout << "j: " << j << "i: " << i << " Position: " << mod_x_pos << " " << mod_y_pos << " " << mod_z_pos << std::endl; + } + } + + // detector position and rotation + Volume motherVol = desc.pickMotherVolume(det); + Transform3D tr(RotationZYX(rot.z(), -rot.y(), rot.x()), Position(pos.x(), pos.y(), pos.z())); + PlacedVolume envPV = motherVol.placeVolume(env, tr); + envPV.addPhysVolID("system", detID); + det.setPlacement(envPV); + return det; +} + +DECLARE_DETELEMENT(ZDCEcalScFiCalorimeter, create_detector)