diff --git a/compact/tracking/definitions_craterlake.xml b/compact/tracking/definitions_craterlake.xml
index 3963c0ec5..79c5aa6fc 100644
--- a/compact/tracking/definitions_craterlake.xml
+++ b/compact/tracking/definitions_craterlake.xml
@@ -14,7 +14,7 @@
Main parameters for the vertex tracker
-
+
Main parameters for the SiBarrel layer geometry
diff --git a/compact/tracking/vertex_barrel.xml b/compact/tracking/vertex_barrel.xml
index f2fc4ad20..639eabc54 100644
--- a/compact/tracking/vertex_barrel.xml
+++ b/compact/tracking/vertex_barrel.xml
@@ -1,5 +1,5 @@
-
+
@@ -7,151 +7,223 @@
Main parameters
-
-
-
-
+
+
+
+
+
+
+ 1 RSU = 2x6 tiles with inactive areas == 2x2 sections
+ 1 section (module) = 3-tiles along z
+ 1 "stave" = 1 row of 12 RSU
+
+
+
+
+ # of RSU in phi: 12, 16, 40 RSUs = 24, 32, 80 sections
+
+
+
+
-
-
-
+
+
+
- ensure we are within the vertex envelope with some margin.
-
+
+
+
- - Currently there are 3 sensor layers. Each is composed of 2 half-cylinders modules with only 40um of silicon thickness.
- - Both support shells are 300um thick, implemented as the integrated tracker support/service setup
-
+ for the segmentation. Assume sensors are placed at the inner most surface for each layer
+
+
+
+
+ - Currently there are 3 sensor layers: Layer 1,2,3 = L0, L1, L2.
+ - assume they are of the same length and aligned.
+
-
-
-
-
-
- Layer 3 already set as main parameter
-
-
-
-
-
-
-
-
-
- Extra parameters to approximate a cylinder as a set of skinny staves
- due to ACTS limitations.
- FIXME: this shouldn't be needed anymore, need to update the cylindrical plugin.
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
- ### Actual detectors
+ ### Actual detectors
-
-
- Vertex Barrel Modules
-
-
+
+
+ - Vertex Barrel Modules.
+ - For RSU (1 module = 1 upper/lower section of three tiles):
+ --Use [mod_name]_upper and [mod_name]_lower here, and [mod_name] in corresponding layer
+ to allow the geo plugin find both modules.
+ -- also need to specify type="upper" or "lower" in components.
+ - for other modules and components:
+ no need to specify upper and lower anywhere.
+ - one RSU ("|" = backbone. Length alone z.):
+ | ------readout-------- | -------readout--------
+ | tilex3 | tilex3
+ | ------biasing-------- | -------biasing--------
+ | ------biasing-------- | -------biasing--------
+ | tilex3 | tilex3
+ | ------readout-------- | -------readout--------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
+
+
- Layers composed of many arrayed modules
+
+ Layers composed of many arrayed modules
+ L0
+
+
+
+
+
+ phi0 : Starting phi of first module.
+ nphi : Number of modules in phi.
+ z0 : Z position of first module's center.
+ nz : Number of modules to place in z.
+
+
+
+
+
+ L1
-
-
-
- phi0 : Starting phi of first module.
- phi_tilt : Phi tilt of a module.
- rc : Radius of the module center.
- nphi : Number of modules in phi.
- rphi_dr : The delta radius of every other module.
- z0 : Z position of first module in phi.
- nz : Number of modules to place in z.
- dr : Radial displacement parameter, of every other module.
-
-
-
+
+
+
+
+
+ L2
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
-
- system:8,layer:4,module:12,sensor:2,x:32:-16,y:-16
+
+
+
+
+
+ system:8,layer:4,module:12,sensor:2,phi:32:-16,z:-16
diff --git a/compact/tracking/vertex_barrel_flat_stave.xml b/compact/tracking/vertex_barrel_flat_stave.xml
new file mode 100644
index 000000000..f2fc4ad20
--- /dev/null
+++ b/compact/tracking/vertex_barrel_flat_stave.xml
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+ Main parameters
+
+
+
+
+
+
+
+
+
+
+
+
+ ensure we are within the vertex envelope with some margin.
+
+
+
+ - Currently there are 3 sensor layers. Each is composed of 2 half-cylinders modules with only 40um of silicon thickness.
+ - Both support shells are 300um thick, implemented as the integrated tracker support/service setup
+
+
+
+
+
+
+
+
+
+ Layer 3 already set as main parameter
+
+
+
+
+
+
+
+
+
+ Extra parameters to approximate a cylinder as a set of skinny staves
+ due to ACTS limitations.
+ FIXME: this shouldn't be needed anymore, need to update the cylindrical plugin.
+
+
+
+
+
+
+
+
+
+
+
+ ### Actual detectors
+
+
+
+
+ Vertex Barrel Modules
+
+
+
+
+
+
+
+
+
+ Layers composed of many arrayed modules
+
+
+
+
+
+ phi0 : Starting phi of first module.
+ phi_tilt : Phi tilt of a module.
+ rc : Radius of the module center.
+ nphi : Number of modules in phi.
+ rphi_dr : The delta radius of every other module.
+ z0 : Z position of first module in phi.
+ nz : Number of modules to place in z.
+ dr : Radial displacement parameter, of every other module.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ system:8,layer:4,module:12,sensor:2,x:32:-16,y:-16
+
+
+
+
diff --git a/src/CurvedBarrelTracker_geo.cpp b/src/CurvedBarrelTracker_geo.cpp
new file mode 100644
index 000000000..10f2940a4
--- /dev/null
+++ b/src/CurvedBarrelTracker_geo.cpp
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright (C) 2022-2024 Whitney Armstrong, Jonathan Witte, Shujie Li
+
+/** Curved Barrel tracker
+ * - Derived from "BarrelTrackerWithFrame_geo.cpp".
+ *
+ * - Designed to process "vertex_barrel.xml":
+ * - When the upper and lower modules are provided, will use the
+ * Build-in EIC-LAS RSU structure with four sections and inactive areas
+ *
+ *
+ * \code
+ * \endcode
+ *
+ *
+ * @author Whitney Armstrong, Jonathan Witte, Shujie Li
+ */
+
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/Shapes.h"
+#include "DDRec/DetectorData.h"
+#include "DDRec/Surface.h"
+#include "XML/Layering.h"
+#include "XML/Utilities.h"
+#include
+#include "DD4hepDetectorHelper.h"
+
+using namespace std;
+using namespace dd4hep;
+using namespace dd4hep::rec;
+using namespace dd4hep::detail;
+
+static Ref_t create_CurvedBarrelTracker(Detector& description, xml_h e, SensitiveDetector sens) {
+
+ xml_det_t x_det = e;
+ Material air = description.air();
+ int det_id = x_det.id();
+ string det_name = x_det.nameStr();
+ DetElement sdet(det_name, det_id);
+
+ typedef vector Placements;
+ map volumes;
+ map sensitives;
+ map> volplane_surfaces;
+ map> module_length;
+
+ PlacedVolume pv, pv_frame;
+
+ // Set detector type flag
+ dd4hep::xml::setDetectorTypeFlag(x_det, sdet);
+ auto& params = DD4hepDetectorHelper::ensureExtension(sdet);
+
+ // Add the volume boundary material if configured
+ for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
+ xml_comp_t x_boundary_material = bmat;
+ DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_boundary_material, params,
+ "boundary_material");
+ }
+
+ Assembly assembly(det_name);
+
+ sens.setType("tracker");
+
+ // loop over the modules
+ for (xml_coll_t mi(x_det, _U(module)); mi; ++mi) {
+ xml_comp_t x_mod = mi;
+ string m_nam = x_mod.nameStr();
+ double m_rmin = x_mod.rmin();
+ double m_length = x_mod.length();
+ double m_width = x_mod.width();
+ module_length[m_nam].push_back(m_length);
+
+ if (volumes.find(m_nam) != volumes.end()) {
+ printout(ERROR, "CurvedBarrelTracker",
+ string((string("Module with named ") + m_nam + string(" already exists."))).c_str());
+ throw runtime_error("Logics error in building modules.");
+ }
+ int ncomponents = 0;
+ int sensor_number = 1;
+ double total_thickness = 0;
+
+ // Compute module total thickness from components
+ xml_coll_t ci(x_mod, _U(module_component));
+ for (ci.reset(), total_thickness = 0.0; ci; ++ci) {
+ total_thickness += xml_comp_t(ci).thickness();
+ }
+ // the module assembly volume
+ Assembly m_vol(m_nam);
+ volumes[m_nam] = m_vol;
+ m_vol.setVisAttributes(description.visAttributes(x_mod.visStr()));
+
+ double thickness_so_far = 0.0;
+ for (xml_coll_t mci(x_mod, _U(module_component)); mci; ++mci, ++ncomponents) {
+ Volume c_vol;
+ xml_comp_t x_comp = mci;
+ const string c_nam = x_comp.nameStr(); // _toString(ncomponents, "component%d");
+ const string c_mat = x_comp.materialStr();
+ double c_thickness = x_comp.thickness();
+ double c_width = getAttrOrDefault(x_comp, _U(width), m_width);
+ double c_length = getAttrOrDefault(x_comp, _U(length), m_length);
+ double c_rmin = m_rmin + thickness_so_far;
+ double c_dphi = c_width / c_rmin;
+
+ if (c_nam == "RSU") { // for RSU, create ONE upper or lower 3-tile sections.
+ // **** hard-coded RSU design with 12 tiles, plus backbones, readout pads, biasing
+ // Having issue including multiple sensitive surfaces in one Tube module (worked with box).
+ // Therefore use type "upper" and "lower" to create two mirrored tile sections. (left right is identical)
+ //
+ // "|" = backbone. Length alone z.
+ //
+ // | ------readout-------- | -------readout--------
+ // | tilex3 | tilex3
+ // | ------biasing-------- | -------biasing--------
+ // | ------biasing-------- | -------biasing--------
+ // | tilex3 | tilex3
+ // | ------readout-------- | -------readout--------
+ const string frame_vis = "VertexSupportLayerVis";
+ const string c_type = x_comp.typeStr();
+ const double BiasingWidth = 0.06 * mm; // need to x2 for two sets
+ const double ReadoutPadsWidth = m_width - BiasingWidth - c_width;
+ const double BackboneLength = m_length - c_length; //0.06*mm;
+
+ double px = 0, py = 0, pz = 0;
+ double c_z0 = -m_length / 2;
+ double c_z1 = c_z0 + BackboneLength;
+ double c_z2 = m_length / 2;
+ pz = (c_z1 + c_z2) / 2; // section central z
+
+ double c_phi0 = 0;
+ double c_phi1, c_phi2;
+ double c_phi3 = m_width / m_rmin;
+ string c_nam1, c_nam2;
+ if (c_type == "upper") {
+ c_phi1 = BiasingWidth / c_rmin;
+ c_phi2 = c_phi1 + c_dphi;
+ c_nam1 = "biasing";
+ c_nam2 = "readout";
+ } else if (c_type == "lower") {
+ c_phi1 = ReadoutPadsWidth / c_rmin;
+ c_phi2 = c_phi1 + c_dphi;
+ c_nam1 = "readout";
+ c_nam2 = "biasing";
+ } else {
+ printout(ERROR, "CurvedBarrelTracker",
+ string((string("Module ") + m_nam + string(": invalid RSU component type [") +
+ c_type + string("], should be upper or lower")))
+ .c_str());
+ throw runtime_error("Logics error in building modules.");
+ }
+
+ // *** inactive areas
+ // biasing and readout (horizontal)
+ Tube f_tube1(c_rmin, c_rmin + c_thickness, c_length / 2, c_phi0, c_phi1);
+ Volume f_vol1(c_nam1, f_tube1, description.material(c_mat));
+ pv_frame = m_vol.placeVolume(f_vol1, Position(px, py, pz));
+ f_vol1.setVisAttributes(description, frame_vis);
+
+ Tube f_tube2(c_rmin, c_rmin + c_thickness, c_length / 2, c_phi2, c_phi3);
+ Volume f_vol2(c_nam2, f_tube2, description.material(c_mat));
+ pv_frame = m_vol.placeVolume(f_vol2, Position(px, py, pz));
+ f_vol2.setVisAttributes(description, frame_vis);
+
+ // backbone (vertical)
+ Tube f_tube3(c_rmin, c_rmin + c_thickness, BackboneLength / 2, c_phi0, c_phi3);
+ Volume f_vol3("backbone", f_tube3, description.material(c_mat));
+ pv_frame = m_vol.placeVolume(f_vol3, Position(px, py, (c_z0 + c_z1) / 2));
+ f_vol3.setVisAttributes(description, frame_vis);
+
+ // *** sensitive tile
+ Tube c_tube(c_rmin, c_rmin + c_thickness, c_length / 2, c_phi1, c_phi2);
+ c_vol = Volume(c_nam + "_" + c_type, c_tube, description.material(c_mat));
+ pv = m_vol.placeVolume(c_vol, Position(px, py, pz));
+ } else { // for regular component, no difference b/w upper/lower
+ Tube c_tube(c_rmin, c_rmin + c_thickness, c_length / 2, 0, c_dphi);
+ c_vol = Volume(c_nam, c_tube, description.material(c_mat));
+ pv = m_vol.placeVolume(c_vol, Position(0, 0, 0));
+ }
+ c_vol.setRegion(description, x_comp.regionStr());
+ c_vol.setLimitSet(description, x_comp.limitsStr());
+ c_vol.setVisAttributes(description, x_comp.visStr());
+ if (x_comp.isSensitive()) {
+ pv.addPhysVolID("sensor", sensor_number++);
+ c_vol.setSensitiveDetector(sens);
+ sensitives[m_nam].push_back(pv);
+ // -------- create a measurement plane for the tracking surface attched to the sensitive volume -----
+ Vector3D u(-1., 0., 0.);
+ Vector3D v(0., -1., 0.);
+ Vector3D n(0., 0., 1.);
+ // compute the inner and outer thicknesses that need to be assigned to the tracking surface
+ // depending on wether the support is above or below the sensor
+ double inner_thickness = thickness_so_far + c_thickness / 2.0;
+ double outer_thickness = total_thickness - inner_thickness;
+
+ SurfaceType type(SurfaceType::Sensitive);
+ VolPlane surf(c_vol, type, inner_thickness, outer_thickness, u, v, n); //,o ) ;
+ volplane_surfaces[m_nam].push_back(surf);
+ }
+ thickness_so_far += c_thickness;
+ }
+ }
+
+ // now build the layers by alternating upper and lower modules.
+ for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
+ xml_comp_t x_layer = li;
+ xml_comp_t x_barrel = x_layer.child(_U(barrel_envelope));
+ xml_comp_t x_layout = x_layer.child(_U(rphi_layout));
+ xml_comp_t z_layout = x_layer.child(_U(z_layout)); // Get the element.
+ int lay_id = x_layer.id();
+ string m_nam = x_layer.moduleStr();
+ string lay_nam = det_name + _toString(x_layer.id(), "_layer%d");
+ Tube lay_tub(x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.z_length() / 2.0);
+
+ Volume lay_vol(lay_nam, lay_tub, air); // Create the layer envelope volume.
+ Position lay_pos(0, 0, getAttrOrDefault(x_barrel, _U(z0), 0.));
+ lay_vol.setVisAttributes(description.visAttributes(x_layer.visStr()));
+
+ double phi0 = x_layout.phi0(); // Starting phi of first module.
+ int l_nphi = x_layout.nphi(); // Number of modules in phi.
+ int nphi[2] = {int((l_nphi + 1) / 2),
+ int(l_nphi / 2)}; // number of modules in uppper and lower modules.
+ double phi_incr = (M_PI * 2) / l_nphi; // Phi increment for one module.
+ double z0 = z_layout.z0(); // Z position of first module in phi.
+ double nz = z_layout.nz(); // Number of modules to place in z.
+
+ Volume module_env[2];
+ Placements sensVols[2];
+ string m_nams[2] = {m_nam + "_upper", m_nam + "_lower"};
+ // if both upper and lower modules are provided (for RSU tiles)
+ if ((volumes.find(m_nams[0]) != volumes.end()) && (volumes.find(m_nams[1]) != volumes.end())) {
+ if (nphi[0] != nphi[1]) {
+ printout(ERROR, "CurvedBarrelTracker",
+ string((string("Layer ") + lay_nam +
+ string(": nphi must be even number to allow upper and lower modules"))
+ .c_str()));
+ throw runtime_error("Logics error in building modules.");
+ }
+ module_env[0] = volumes[m_nams[0]];
+ module_env[1] = volumes[m_nams[1]];
+ sensVols[0] = sensitives[m_nams[0]];
+ sensVols[1] = sensitives[m_nams[1]];
+ }
+ // for other regular modules
+ else if (volumes.find(m_nam) != volumes.end()) {
+ module_env[0] = volumes[m_nam];
+ module_env[1] = volumes[m_nam];
+ sensVols[0] = sensitives[m_nam];
+ sensVols[1] = sensitives[m_nam];
+ m_nams[0] = m_nam;
+ m_nams[1] = m_nam;
+ }
+ DetElement lay_elt(sdet, lay_nam, lay_id);
+
+ // the local coordinate systems of modules in dd4hep and acts differ
+ // see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html
+ auto& layerParams =
+ DD4hepDetectorHelper::ensureExtension(lay_elt);
+
+ for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
+ xml_comp_t x_layer_material = lmat;
+ DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_layer_material, layerParams,
+ "layer_material");
+ }
+
+ // Z increment for module placement along Z axis.
+ // Adjust for z0 at center of module rather than
+ // the end of cylindrical envelope.
+ // double z_incr = nz > 1 ? (2.0 * abs(z0)) / (nz - 1) : 0.0;
+ // Starting z for module placement along Z axis.
+ int module = 1;
+
+ // Loop over the number of modules in phi.
+ for (int kk = 0; kk < 2; kk++) {
+ int iphi = nphi[kk];
+ double z_incr = module_length[m_nams[kk]][0];
+
+ for (int ii = 0; ii < iphi; ii++) {
+ // Loop over the number of modules in z.
+ double module_z = z0;
+ for (int j = 0; j < nz; j++, module_z += z_incr) {
+ string module_name = _toString(module, "module%d");
+ DetElement mod_elt(lay_elt, module_name, module);
+ Transform3D tr(
+ RotationZYX(phi0 + phi_incr * ii * 2, 0, 0),
+ Position(0, 0, module_z)); // altering upper and lower module to fill every other row
+ pv = lay_vol.placeVolume(module_env[kk], tr);
+ pv.addPhysVolID("module", module);
+ mod_elt.setPlacement(pv);
+ for (size_t ic = 0; ic < sensVols[kk].size(); ++ic) {
+ PlacedVolume sens_pv = sensVols[kk][ic];
+ DetElement comp_de(mod_elt, std::string("de_") + sens_pv.volume().name(), module);
+ comp_de.setPlacement(sens_pv);
+ auto& comp_de_params =
+ DD4hepDetectorHelper::ensureExtension(comp_de);
+ comp_de_params.set("axis_definitions", "XYZ");
+ // comp_de.setAttributes(description, sens_pv.volume(), x_layer.regionStr(), x_layer.limitsStr(),
+ // xml_det_t(xmleles[m_nam]).visStr());
+ //
+ volSurfaceList(comp_de)->push_back(volplane_surfaces[m_nams[kk]][ic]);
+ }
+
+ /// Increase counters etc.
+ module++;
+ }
+ }
+ phi0 += phi_incr; // switch from upper to lower modules
+ }
+ // Create the PhysicalVolume for the layer.
+ pv = assembly.placeVolume(lay_vol, lay_pos); // Place layer in mother
+ pv.addPhysVolID("layer", lay_id); // Set the layer ID.
+ lay_elt.setAttributes(description, lay_vol, x_layer.regionStr(), x_layer.limitsStr(),
+ x_layer.visStr());
+ lay_elt.setPlacement(pv);
+ }
+ sdet.setAttributes(description, assembly, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
+ assembly.setVisAttributes(description.invisible());
+ pv = description.pickMotherVolume(sdet).placeVolume(assembly);
+ pv.addPhysVolID("system", det_id); // Set the subdetector system ID.
+ sdet.setPlacement(pv);
+ return sdet;
+}
+
+//@}
+// clang-format off
+DECLARE_DETELEMENT(epic_CylinderSVTBarrel,create_CurvedBarrelTracker)