Warning, /acts/docs/examples/howto/material_mapping.rst is written in an unsupported language. File is not indexed.
0001 .. _material_mapping_howto_examples:
0002
0003 Howto run the material mapping and validation
0004 =============================================
0005
0006 .. note::
0007 This documentation is for running the material mapping in the Examples framework.
0008 Documentation on how to use the Core library directly for material mapping is found :ref:`here<material_mapping_howto_core>`.
0009
0010 When performing track reconstruction, the proper amount of material crossed by the particle needs to be accounted for. This material is originally available in the detector simulation with a lot of details, which would make it expensive to directly use. To circumvent this issue, the material is mapped onto different surfaces in the tracking geometry. This process will be performed in 3 steps:
0011
0012 - first, a JSON geometry file is created, it will be used to configure which surface the material is mapped onto and with which binning.
0013 - second, a Geant4 simulation is used to collect the material inside the detector from the detailed geometry.
0014 - third, all the steps are projected onto the closest surfaces (or volume in case of volume mapping) and averaged out over many events to create a map.
0015
0016 This page will explain how to perform the material mapping with the ACTS Examples. For this example we will use the Open Data Detector (ODD) the last paragraph will explain what needs to be changed if you want to perform the material mapping with another detector.
0017
0018 Prerequisites
0019 -------------
0020 As a prerequisite you will need to build ACTS with the Examples, Geant4 and the JSON plugin (``ACTS_BUILD_EXAMPLES``, ``ACTS_BUILD_EXAMPLES_GEANT4`` and ``ACTS_BUILD_PLUGIN_JSON``) enabled, please refer to the general how-to ACTS guide. Depending on the type of detector you want to map you will need to use some additional packages, in our case ``ACTS_BUILD_EXAMPLES_DD4HEP`` and ``ACTS_BUILD_PLUGIN_TGEO`` are needed.
0021
0022 For this particular example the ODD will also be needed. To use it, don't forget to get the corresponding submodule and then recompile the ACTS code if needed.
0023
0024 .. code-block:: console
0025
0026 $ git submodule init
0027 $ git submodule update
0028
0029 Once Acts has been built we can start the mapping. The mapping is divided in two aspects: the surface mapping in which the material is mapped onto the closest surfaces (following the propagation direction) and the volume mapping in which the material is mapped onto a 3D (or 2D) grid associated to a volume. The first step is to select which surfaces and volumes we will want to map material onto. This is done by association of an ``Acts::ProtoSurfaceMaterial`` (or an ``Acts::ProtoVolumeMaterial``) with the surfaces (or volumes) of interest. In the case of the ODD and some other DD4hep detectors this is done at the building step. For other detectors, or if one wants to be able to control precisely which layer will be mapped on and with which binning, an additional step is required.
0030
0031 Mapping and configuration
0032 -------------------------
0033
0034 First we need to extract the list of all the surfaces and volumes in our detector. To do so we will use the ``geometry.py`` script:
0035
0036 .. code-block::
0037
0038 $ python3 <source>/Examples/Scripts/Python/geometry.py
0039
0040 Ideally the following options should be used in the python file:
0041
0042 .. code-block::
0043
0044 def runGeometry(
0045 trackingGeometry,
0046 decorators,
0047 outputDir,
0048 events=1,
0049 outputObj=False,
0050 outputCsv=False,
0051 outputJson=True,
0052 ):
0053
0054 For the following example we will be remapping the material of the ODD, we will thus get our detector via the following line:
0055
0056 .. code-block:: console
0057
0058 detector, trackingGeometry, decorators = getOpenDataDetector()
0059
0060 This algorithm is useful to obtain a visualisation of your detector using the different types of output available (``output-obj`` gives ``.obj`` with a 3D representation of the different subdetectors, for example). Here, we use ``output-json`` to obtain a map of all the surfaces and volumes in the detector with a ``ProtoSurfaceMaterial`` (or a ``ProtoVolumeMaterial``), ``mat-output-allmaterial`` ensure that a ``ProtoSurfaceMaterial`` (or a ``ProtoVolumeMaterial``) is associated to all the surfaces (or volumes), enforcing all of them to be written.
0061 Four types of surfaces exist:
0062
0063 - boundaries which represent the boundaries of the different volumes
0064 - approaches which correspond to the entrance and exist of the detector layer
0065 - representing which correspond to the surface representation of a layer (often positioned at the middle of the 2 approaches)
0066 - sensitives which correspond to the active part of the detector (sensors)
0067
0068 By default, all the surfaces will be written but one can turn a specific type off (for example the sensitive) by using the appropriate option: ``mat-output-XXX false``
0069
0070 The JSON file can now be edited to select which surfaces and volumes you want to have material mapped on. The JSON file is comprise of two parts, the first one contain a list of surfaces and the second a list of volumes. Information of the surface and volumes such as their type, range, id and position are available. To add one surface to the material mapping, one simply needs to switch the ``mapMaterial`` variable to ``true``. The binning can then be changed by changing the number associated to ``bins``, the type of bin can also be changed. For the volume, the same method can be applied, except that up to 3 bins can be associated.
0071 As a rule of thumb volume material should only be used for large homogeneous detector (like calorimeters and gaseous detectors), for the material mapping a good first try would be to use the representing surfaces of the layers with sensors. The binning depends heavily on the geometry and could be of the order of 100 (the more bins are used the more events need to be simulated to populate the bins).
0072
0073 .. warning::
0074 When mapping onto a surface, the material inside volumes with material (or ``ProtoMaterial``) will be ignored, you should thus avoid mapping material onto surfaces within material volumes. When mapping onto a volume, only the material within that volume will be used. If you have a large gap between the last material surface and the volume you might then want to also map material onto the boundary of the material volume.
0075
0076 In addition to this, the mapping type can be changed for surface mapping by changing the ``mappingType`` variable. Four different types of mapping are available:
0077
0078 - ``PreMapping``: Only map material from before the surface.
0079 - ``Default``: Map material from both before and after the surface
0080 - ``PostMapping``: Only map material from after the surface.
0081 - ``Sensor``: Only map the last material hits before the surface. Used to map only the sensor material onto the sensors.
0082
0083 In case two different surfaces would receive a material hit (Default followed by Default or PreMapping for example), the material hit is associated with the closest surface.
0084
0085 .. warning::
0086 Due to the implementation, all the material hits need to be associated with a surface. If a PostMapping surface follows a PreMapping or a Sensor surface, all the material between the two surface will be mapped onto the PostMapping surface and a warning will be issued. The same goes if the first surface encountered is a PostMapping surface.
0087
0088 This configuration can be cumbersome to do by hand especially when trying to map on sensitives surfaces. To simplify this task two python scripts are available in ``Examples/scripts/MaterialMapping``:
0089
0090 - ``writeMapConfig.py``
0091 - ``configureMap.py``
0092
0093 The first one take as an input the surfaces map previously generated and will return a JSON config file. In this file you can see all the different types of surfaces associated to each volume. You can then change the binning associated to a surface type. When the second script is called, the resulting map will have the binning applied to all the surface of the corresponding type and ``"mapMaterial"`` will be changed to true. Attention: the ``configureMap.py`` will modify the surfaces map used in input, so you might want to make a copy of it beforehand.
0094
0095
0096 .. code-block:: console
0097
0098 $ python3 <source>/Examples/Scripts/MaterialMapping/writeMapConfig.py geometry-map.json config-map.json
0099
0100 Then edit the config-map.json file
0101
0102 .. code-block:: console
0103
0104 $ python3 <source>/Examples/Scripts/MaterialMapping/configureMap.py geometry-map.json config-map.json
0105
0106 Geometry visualisation and preparation of JSON files
0107 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0108
0109 To help you visualising the geometry and understand the hierarchical structure of volumes and layers, a script has been provided: ``Examples/scripts/MaterialMapping/GeometryVisualisationAndMaterialHandling.py``. The documentation of the module can be printed using:
0110
0111 .. code-block:: console
0112
0113 $ python3 <source>/Examples/Scripts/MaterialMapping/GeometryVisualisationAndMaterialHandling.py --help
0114
0115 The first thing you can do, is to visualise your geometry with:
0116
0117 .. code-block:: console
0118
0119 $ python3 <source>/Examples/Scripts/MaterialMapping/GeometryVisualisationAndMaterialHandling.py --geometry <source>/thirdparty/OpenDataDetector/config/odd-material-mapping-config.json
0120
0121 This command produces a series of plots in the output folder ``plot``, or set a different name using ``--output_folder``.
0122
0123 The picture ``volumes_and_layers.png`` show you the volumes and all layers constructed in them:
0124
0125 .. image:: figures/materialMapping/volumes_and_layers.png
0126
0127 For each volume containing layers, another picture is produced to show the representative layers (without ``approach`` index) and highlight the ones with ``approach`` index. The picture below show layers for one of the ODD volumes. Knowledge of the approach layers is needed to select the layers you want the material to be mapped onto.
0128
0129 .. image:: figures/materialMapping/layers_for_volume_17.png
0130
0131 The totality of representative and approach layers is shown in a separate picture ``approach_layers.png``.
0132
0133 .. image:: figures/materialMapping/approach_layers.png
0134
0135 Additionally, another picture is produced to visualise boundaries of volumes containing layers.
0136
0137 .. image:: figures/materialMapping/boundaries.png
0138
0139 The same script can be used to dump a steering file that can help you selecting boundaries and approach layers you want the material to be mapped onto, using ``--dump_steering``. At this point you have to edit the steering file which has to contain **ONLY** the structures on which you want to map the material. Once this is done, you can read the steering file with the same python module to produce the final material map file to run material mapping. This is done enabling ``--edit``. At the end of the process, another plot is produced to visualise and validate the structures that will be selected in the mapping procedure to carry material.
0140
0141
0142 Geantino scan
0143 -------------
0144
0145 The next step is to do a geantino scan of our detector. For this we will use the ``material_recording.py`` script:
0146
0147 .. code-block:: console
0148
0149 $ python3 <source>/Examples/Scripts/Python/material_recording.py
0150
0151 The result of the geantino scan will be a root file containing material tracks. Those contain the direction and production vertex of the geantino, the total material accumulated and all the interaction points in the detector.
0152
0153 Material Mapping
0154 ----------------
0155
0156 With the surfaces map and the material track we can finally do the material mapping using the ``material_mapping.py`` script:
0157
0158 .. code-block:: console
0159
0160 $ python3 <source>/Examples/Scripts/Python/material_mapping.py
0161
0162 Note that technically when using DD4hep (in particular for the ODD) defining a ``matDeco`` in the main function is not strictly necessary as the DD4hep geometry can hold the information of which surface to map onto with which binning. We will ignore this option, since the goal of this guide is to explain how to make a material map regardless of the detector.
0163
0164 As an output you will obtain the material map as a root and JSON file and a new material track collection in a root file. This new collection adds to each material interaction the associated surface during the mapping. This can be used for the control plots.
0165 Depending on what you want to do there are three options you can change:
0166
0167 - ``mapSurface``: determine if material is mapped onto surfaces
0168 - ``mapVolume``: determine if material is mapped onto volumes
0169 - ``mappingStep``: determine the step size used in the sampling of the volume in the volume mapping. By default, the material interaction point obtained from G4 is accumulated at the intersection between the track and the volume material. The mapping will be therefore incorrect if the material extends through the bin. To avoid this, additional material points are created every ``mappingStep`` [mm] along the trajectory. The mapping step should be small compared to the bin size.
0170 - ``readCachedSurfaceInformation`` if added the material-surface association will be taken from the input material track file (doesn't work with geantino file, you need to use the material track file obtained from running the material mapping).
0171
0172 In addition to root and JSON output, one can also output the material map to a Cbor file (Concise Binary Object Representation). Doing so results in a file about 10 time smaller than the JSON one, but that file is no longer human-readable. This should be done once the map has been optimised and you want to export it.
0173
0174 .. note::
0175 You can map onto surfaces and volumes separately (for example if you want to optimise first one then the other). In that case after mapping one of those you will need to use the resulting JSON material map as an input to the ``mat-input-file``.
0176
0177 .. note::
0178 You might need to run the material mapping multiple times in a row to optimise the binning for each surface, which can be time-consuming. To improve the speed of subsequent mapping one can turn the ``mat-mapping-read-surfaces`` option to true, with this option the intersection of the material track with the surfaces will be taken directly from the input root file (which would have been updated during the first mapping). This will save the time needed to compute them. This can save up to 50% of the mapping time. Please note that this can only be used if the mapping surfaces used didn't change between this execution and the last.
0179
0180 Material Validation
0181 -------------------
0182
0183 Now that the map has been written, you may want to validate it. First you can use the ``MaterialValidation`` example. This will perform propagation throughout the detector once it has been decorated with the material map. It will then output material tracks with the same format as the one obtain with the Geantino.
0184
0185 By default, the Geantino scan is performed with no spread in :math:`z_0` and :math:`d_0`, while the validation has a spread of 55 mm, to obtain meaningful results, use the same spread for both (in our example a spread of 0). Another difference between the scan and the validation is that the first uses a flat distribution in :math:`\theta` while the second uses a flat distribution in :math:`\eta`, so some reweighing might be necessary when comparing some of the distributions.
0186
0187 .. code-block:: console
0188
0189 $ python3 <source>/Examples/Scripts/Python/material_validation.py
0190
0191 To do the validation, five root macros are available in ``scripts/MaterialMapping``:
0192
0193 - ``Mat_map.C``: general comparison at the track level and 2D map of the detector.
0194 - ``Mat_map_surface_plot.C``: for each mapped surface show the position of the material.
0195 - ``Mat_map_surface_plot_ratio.C``: material ratio between the truth and the validation for each surface.
0196 - ``Mat_map_surface_plot_dist.C``: position of the Geantino interaction with respect to the surface they are mapped on.
0197 - ``Mat_map_surface_plot_1D.C``: 1D distribution of the material in each surface.
0198
0199 .. code-block:: console
0200
0201 mkdir Validation
0202
0203 root -l -b <source>/Examples/Scripts/MaterialMapping/Mat_map.C'("propagation-material.root","material-map_tracks.root","Validation")''
0204 .q
0205
0206 mkdir Surfaces
0207 mkdir Surfaces/prop_plot
0208 mkdir Surfaces/map_plot
0209 mkdir Surfaces/ratio_plot
0210 mkdir Surfaces/dist_plot
0211 mkdir Surfaces/1D_plot
0212
0213 root -l -b <source>/Examples/Scripts/MaterialMapping/Mat_map_surface_plot_ratio.C'("propagation-material.root","material-map_tracks.root",100000,"Surfaces/ratio_plot","Surfaces/prop_plot","Surfaces/map_plot")'
0214 .q
0215 root -l -b <source>/Examples/Scripts/MaterialMapping/Mat_map_surface_plot_dist.C'("material-map_tracks.root",-1,"Surfaces/dist_plot")'
0216 .q
0217 root -l -b <source>/Examples/Scripts/MaterialMapping/Mat_map_surface_plot_1D.C'("material-map_tracks.root",100000,"Surfaces/1D_plot")'
0218 .q
0219
0220 Using the validation plots you can then adapt the binning and the mapped surface to improve the mapping.
0221
0222 On top of those plots:
0223
0224 .. code-block:: console
0225
0226 root -l -b <source>/Examples/Scripts/MaterialMapping/Mat_map_detector_plot_ratio.C'("propagation-material.root","material-map_tracks.root",{X,Y,Z},100000,"Det_ratio","Det_Acts","Det_G4")'
0227 .q
0228
0229 Can be use with X,Y,Z is a list of volumes, this will plot the material ratio between the map and the Geantino scan for the given volumes.
0230
0231
0232 Using a different detector
0233 --------------------------
0234
0235 If you want to use a different type of detector, you will first need to ensure that the relevant packages were added during the compilation. After this you can just replace the detector initialisation in the different main function. For reference you can have a look on the ODD for DD4Hep detector and on the ITk for TGeo detector.