Back to home page

EIC code displayed by LXR

 
 

    


Warning, /tutorial-geometry-development-using-dd4hep/_episodes/03-modifying-geometry.md is written in an unsupported language. File is not indexed.

0001 ---
0002 title: "Modifying geometry"
0003 teaching: 20
0004 exercises: 40
0005 questions:
0006 - "How do we modify or add geometry defined in DD4hep?"
0007 objectives:
0008 - "Understand the structure of a geometry plugin source file."
0009 keypoints:
0010 - "To add or modify geometry, we add geometry plugins written in C++."
0011 ---
0012 Until now we have interacted with the read-only geometry that is stored inside the container. We will now move on to modifying this geometry. That requires that we work in a local copy of the geometry.
0013 
0014 ## Checking out your local copy of the geometry
0015 
0016 We will start with a local copy of the `epic` repository:
0017 ```console
0018 $ cd ~/eic/
0019 $ git clone https://github.com/eic/epic
0020 $ cd epic
0021 $ ls
0022 bin    calibrations    compact         macro      reports           scripts  templates
0023 build  CMakeLists.txt  configurations  README.md  requirements.txt  src      views
0024 ```
0025 
0026 As you can tell, the content of the repository itself is quite different from the installed version (as is often the case for other software as well). You will recognize, however, the `compact` directory with the subsystem xml files.
0027 
0028 In order to compile and install the local geometry repository into a local directory, we can use the following commands:
0029 ```console
0030 $ cd ~/eic/epic
0031 $ cmake -B build -S . -DCMAKE_INSTALL_PREFIX=install
0032 $ cmake --build build -- install
0033 ```
0034 
0035 > Note: To speed up compilation, you may add the options `-j4` to the last command, where `4` corresponds to the number of cores you can use.
0036 {: .callout}
0037 
0038 This will install the geometry into the directory `~/eic/epic/install/` (and subdirectories). You will notice that `~/eic/epic/install/share/epic` contains the same files that we explored earlier inside the `/opt/detector` directory.
0039 
0040 As before, we now need to load the environment for this geometry. We can again use the `bin/thisepic.sh` script for this, though now we must use the one installed in our local installation directory:
0041 ```console
0042 $ source install/bin/thisepic.sh
0043 ```
0044 
0045 When we run `dd_web_display --export $DETECTOR_PATH/$DETECTOR_CONFIG.xml` now, we will use the local geometry parametrization and the local geometry plugins. (Note: As before, downloads of fieldmaps and calibration files will be necessary.)
0046 
0047 > Quick Exercise:
0048 > - Ensure that you have a local copy of the geometry repository which you can compile and install in a local directory.
0049 > - Verify that, after sourcing the `bin/thisepic.sh` script, the `DETECTOR_PATH` points to the correct local install directory.
0050 > - Verify that `dd_web_display` can indeed export the geometry for the detector subsystem configuration you used before.
0051 {: .challenge}
0052 
0053 ## Anatomy of a detector plugin
0054 
0055 ### Introduction
0056 
0057 It may be clear at this point how to make modifications to the parametrization, commit them to a branch in the local repository, and submit a pull request on GitHub to include them in the main branch.
0058 
0059 For the remainder of this lesson we will focus on the vertex barrel detector using the much reduced geometry configuration `epic_vertex_only.xml` so that any change made are more evident.
0060 
0061 What we have not covered yet is the discussion of what goes into a detector plugin. Let's look at the `epic_VertexBarrel` plugin we encountered earlier. The names of the plugins may not agree with the source files in the `src/` directory. This allows us to support multiple detector types with the same source files. In this case, `epic_VertexBarrel` is defined in the file `src/BarrelTrackerWithFrame_geo.cpp`.
0062 
0063 If you are not sure what fine in the `src` directory builds the plugin you are looking for, find the `type` in the xml detector definition and use the `grep` shell command.
0064 
0065 ```console
0066 $ grep -r epic_VertexBarrel src/
0067 src/BarrelTrackerWithFrame_geo.cpp:DECLARE_DETELEMENT(epic_VertexBarrel,    create_BarrelTrackerWithFrame)
0068 ```
0069 
0070 The DECLARE_DETELEMENT line, at the bottom of the `src/BarrelTrackerWithFrame_geo.cpp` file provides dd4hep with the link which tells it to call the `create_BarrelTrackerWithFrame` function when an xml detector definition is given the `epic_VertexBarrel` type.
0071 
0072 We now know that changing the content of the `create_BarrelTrackerWithFrame` function should be called when the `epic_vertex_only.xml` is used when dd4hep loads a geometry.
0073 
0074 ### Passing parameters from xml
0075 
0076 Next we will take a deeper dive into the `create_BarrelTrackerWithFrame` function to pick out the key components and how it is configured by the xml file `compact/tracking/vertex_barrel.xml`
0077 
0078 ```shell
0079 static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, SensitiveDetector sens)
0080 ```
0081 
0082 here `description` contains access to the full tree defined from the main detector xml file. `e` contains the specific information contained within the xml tree within the `<detector>` blocks.
0083 
0084 There are a few ways to access these xml configuration parameters. Some xml elements have methods provided by dd4hep which allow direct access to the values, such as:
0085 
0086 ```shell
0087 51  Material                     air      = description.air();
0088 52  int                          det_id   = x_det.id();
0089 53  string                       det_name = x_det.nameStr();
0090 ```
0091 
0092 A list of tags dd4hep provides a conventient conversion method for can be found [here](https://dd4hep.web.cern.ch/dd4hep/reference/UnicodeValues_8h_source.html), (**There is almost certainly a better link**).
0093 
0094 More often you may be wanting to define a parameter by a tag of your choice or if you're wanting to be certain how it's being handled. The following (abridged) code is an example of how to access parameters of any name.
0095 
0096 ```shell
0097   for (xml_coll_t su(x_det, _U(support)); su; ++su) {
0098     xml_comp_t  x_support         = su;
0099     double      support_thickness = getAttrOrDefault(x_support, _U(thickness), 2.0 * mm);
0100     double      support_length    = getAttrOrDefault(x_support, _U(length), 2.0 * mm);
0101     double      support_rmin      = getAttrOrDefault(x_support, _U(rmin), 2.0 * mm);
0102     double      support_zstart    = getAttrOrDefault(x_support, _U(zstart), 2.0 * mm);
0103     std::string support_name      = getAttrOrDefault<std::string>(x_support, _Unicode(name), "support_tube");
0104     std::string support_vis       = getAttrOrDefault<std::string>(x_support, _Unicode(vis), "AnlRed");
0105   }
0106 ```
0107 
0108 The code loops over all `<support>` elements inside the `<detector>` block, located using `_U(support)` which interprets content as unicode. Inside each support node the `getAttrOrDefault` method sets the variables to the values given by the unicode `thickness` etc, or if they are not present in the support node sets a default value. If you want to require the parameter be defined in the xml file you could simply use `x_support.child(thickness)`.
0109 
0110 > Note:
0111 > - No support blocks actually currently appear in the `compact/tracking/vertex_barrel.xml` file so this block of code won't be run.
0112 > - In the xml file, there must be no white space between the parameter, = sign and the value.
0113 {: .callout}
0114 
0115 A fuller description of how to access and use the xml parameters is given in section [2.4 of the dd4hep manual](https://dd4hep.web.cern.ch/dd4hep/usermanuals/DD4hepManual/DD4hepManualch2.html#x3-210002.4)
0116 
0117 
0118 > Exercise:
0119 > - Create and chackout a new branch forked from the main branch.
0120 > - Add a new configuration parameter into `compact/tracking/vertex_barrel.xml` 
0121 > - Add code to `src/BarrelTrackerWithFrame_geo.cpp` which will read the new parameter and a print statement to display its value to the terminal.
0122 > - Recompile and rerun the `dd_web_display` step using `epic_vertex_only.xml` to verify that the printout statement has been added.
0123 > - Change the values in the xml and rerun to verify the value is being read properly.
0124 {: .challenge}
0125 
0126 > Note: Changes to the xml files in `install/share/epic/`... can made without recompiling the code, however they will be overwritten when the code is recompiled. In order to test temporary changes a top level configuration file can be copied to a path outside of `install`. This then needs to be edited to internally point to the compact file you are editing rather than the path given by the install, `${DETECTOR_PATH}`.
0127 {: .callout}
0128 
0129 ### Building new components
0130 
0131 DD4hep geometries are built in a similar hierarchical way to Geant4 geometries.
0132 
0133 > - Shape - 3D shape of the component. Can be a simple shape, made from boolean combinations of simple shapes or imported from CAD.
0134 > - Volume - Adds physical properties to the shape such as its material and if its sensitive.
0135 > - Placement - Position(s) that the volume is located within your detector geometry, this can be a position nested within another volume, containing unique identifier.
0136 
0137 We will start by looking at the shapes anv volumes. The most common shapes you are likely to find yourself using are `Box` and `Tube`. In `src/BarrelTrackerWithFrame_geo.cpp` both are used, `module_component` is defined as `Box`, the volume of which takes its material from the xml description:
0138 
0139 ```shell
0140 172      Box          c_box(x_comp.width() / 2, x_comp.length() / 2, x_comp.thickness() / 2);
0141 173      Volume       c_vol(c_nam, c_box, description.material(x_comp.materialStr()));
0142 ```
0143 
0144 `layer` volumes into which `module_component`s are later placed are described as a `Tube` but this time the volume is directly given the air material:
0145 
0146 ```shell
0147 239    Tube       lay_tub(x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.z_length() / 2.0);
0148 240    Volume     lay_vol(lay_nam, lay_tub, air); // Create the layer envelope volume.
0149 ```
0150 
0151 In DD4hep there is a type of volume called an Assembly which contains volumes placed within itself but doesn't have a shape of its own. This is very useful for arranging volumes without needing a container volume defined with might have overlaps of their own where none are really present.
0152 
0153 > Notes: 
0154 > - The [DD4hep shapes](https://dd4hep.web.cern.ch/dd4hep/usermanuals/DD4hepManual/DD4hepManualch2.html#x3-290002.9) are based directly off the [ROOT geometry shapes](https://root.cern.ch/root/htmldoc/guides/users-guide/Geometry.html#shapes). An useful, probably out of date table comparing the ROOT, DD4hep and Geant4 shape names can be found here:  [https://github.com/AIDASoft/DD4hep/issues/588](https://github.com/AIDASoft/DD4hep/issues/588)
0155 > - DD4hep provides some shape plugins directly, so very basic geometries can be described directly in the xml with no additional code.
0156 {: .callout}
0157 
0158 > Exercise:
0159 > - Create a new simple volume within the hierachy in `src/BarrelTrackerWithFrame_geo.cpp`.
0160 > - Recompile and rerun the `dd_web_display` step using `epic_vertex_only.xml` locating the new shape(s) you have added in the ROOTJS viewer.
0161 > - Build a new tube volume which contains tracking layers.
0162 {: .challenge}
0163 
0164 ### Testing overlaps
0165 
0166 It is important for running the Geant4 simulation that geometries do not overlap. When stepping through the geometry a particle cannot know which volume it is in. An overlap check is run by GitHub when you request that your changes are merged into the main branch of the epic code.
0167 
0168 ```shell
0169 python scripts/checkOverlaps.py -c ${DETECTOR_PATH}/epic_vertex_only.xml
0170 ```
0171 
0172 > Exercise:
0173 > - Run the overlap check on your geometry with the added component.
0174 > - Change some parameters to add/remove the overlap and compare the output.
0175 {: .challenge}
0176 
0177 ### Readout 
0178 
0179 Placed volumes can be made sensitive by setting e.g.
0180 
0181 ```shell
0182 194  c_vol.setSensitiveDetector(sens);
0183 ```
0184 
0185 The type of information that will be saved to the output is defined usually as either:
0186 
0187 ```shell
0188   sens.setType("tracker");
0189   sens.setType("calorimeter");
0190 ```
0191 
0192 In the xml file the readout for the detector is passed in the `readout` field of the `detector` definition
0193 
0194 ```shell
0195     <detector
0196       id="VertexBarrel_0_ID"
0197       name="VertexBarrel"
0198       type="epic_VertexBarrel"
0199       readout="VertexBarrelHits"
0200       insideTrackingVolume="true">
0201 ```
0202 
0203 Where the readout name references a `readout` block also defined in the xml description
0204 
0205 ```shell
0206   <readouts>
0207     <readout name="VertexBarrelHits">
0208       <segmentation type="CartesianGridXY" grid_size_x="0.020*mm" grid_size_y="0.020*mm" />
0209       <id>system:8,layer:4,module:12,sensor:2,x:32:-16,y:-16</id>
0210     </readout>
0211   </readouts>
0212 ```
0213 
0214 Here the name given will appear as the name of the branch containing the hits in the output edm4hep file. dd4hep provides very convenient segmentation to the readout which allows hits in a readout volume to be divided up to locations beyond its natural boundaries, this is configures by the `x` and `y` parameters as well as the `grid_size`.
0215 
0216 The readout branch contains the information on the hit energy deposited, time of arival etc. which is usually found in a simulation output but in addition it contains `CellID` which is a 64 bit field which uniquely identifies the detector segmentation. 
0217 
0218 In the case of `VertexBarrelHits`, 8 bits always required by the system, 4 bits locate a specific layer, 12 a module, 2 a sensor and 32 the remaining x-y segmentation. In the code, dd4hep requires a separate hierachy of the geometry detector elements which are given tags and numbers so they can be uniquely identified. This hieracy doesn't have to strictly follow the way the volumes are themselves constructed.
0219 
0220 ```shell
0221   DetElement mod_elt(lay_elt, module_name, module);
0222   pv = lay_vol.placeVolume(module_env, tr);
0223   pv.addPhysVolID("module", module);
0224   mod_elt.setPlacement(pv);
0225 ```
0226 
0227 Here `mod_elt` is give the parent element `layer_elt`, the name and module number. Then the element is attached to a placed volume which has been given the physical volume id `module`.
0228 
0229 To run the simulation and produce an output file containing the detector hits you can use `npsim`. I would suggest only using a small sample of events given by the `--numberOfEvents` flag.
0230 
0231 ```shell
0232 $ npsim --runType run --compactFile $DETECTOR_PATH/epic_vertex_only.xml --inputFiles root://dtn-eic.jlab.org//work/eic2/EPIC/EVGEN/SIDIS/pythia6-eic/1.0.0/18x275/q2_0to1/pythia_ep_noradcor_18x275_q2_0.000000001_1.0_run9.ab.hepmc3.tree.root --numberOfEvents 100 --outputFile test.edm4hep.root
0233 ```
0234 
0235 Inside the output file `test.edm4hep.root` there should be 4 trees:
0236 
0237 ```shell
0238 events
0239 runs
0240 metadata
0241 podio_metadata
0242 ```
0243 
0244 The events tree contains the readout of your detectors, in this example it should contain only 7 branches,
0245 
0246 ```shell
0247 MCHeader
0248 MCParticles
0249 _MCParticles_parents
0250 _MCParticles_daughters
0251 VertexBarrelHits
0252 _VertexBarrelHits_MCParticle
0253 ```
0254 
0255 The `MCParticles` branch contains information on all of the particles described by your generator and any secondaries produced in the simulation. `VertexBarrelHits` contains the hit information of the vertex barrel and has the association branch `_VertexBarrelHits_MCParticle` which references the particle in the `MCParticles` branch which caused the hit.
0256 
0257 > Exercise:
0258 > - Run the simulation with a small dataset using
0259 > - Look at the output datafiles usig your favorate ROOT browser.
0260 > - Change the sensitive type of the `BarrelTrackerWithFrame_geo.cpp` and compare the output to what you first saw.
0261 > - Try to make your new tube volume sensitive by setting as sensitive and adding a `DetElement` and giving it the necessary `addPhysVolID` values not currently used by the tracker.
0262 > - Open ended - Move your new Tube detector into a separate src file (Or create a new simple detector) and include it separately in the xml definition and readout. 
0263 
0264 ### ACTS?
0265 
0266 ToDo