From 2f77be65f0e223ba9e11a78217e41ac6497004e7 Mon Sep 17 00:00:00 2001
From: Whitney Armstrong <warmstrong@anl.gov>
Date: Mon, 23 Mar 2020 16:58:05 -0500
Subject: [PATCH] 	new file:   part1/overview.md

---
 src/docs/part1/overview.md | 380 +++++++++++++++++++++++++++++++++++++
 1 file changed, 380 insertions(+)
 create mode 100644 src/docs/part1/overview.md

diff --git a/src/docs/part1/overview.md b/src/docs/part1/overview.md
new file mode 100644
index 0000000..a45006d
--- /dev/null
+++ b/src/docs/part1/overview.md
@@ -0,0 +1,380 @@
+Tutorial Part 1
+===============
+
+  * [Introduction](#introduction)
+  * [How to build a detector from scratch](#how-to-build-a-detector-from-scratch)
+    + [Compiling a new detector](#compiling-a-new-detector)
+    + [Building the geometry](#building-the-geometry)
+      - [Compact detector description entry element](#compact-detector-description-entry-element)
+      - [Geometry Construction](#geometry-construction)
+        * [XML Parsing Tip : Provide good default values](#xml-parsing-tip--provide-good-default-values)
+      - [Critical parts of build_detector](#critical-parts-of-build_detector)
+  * [The Readout and Bit Fields](#the-readout-and-bit-fields)
+  * [Simple Reconstruction Overview of scripts](#simple-reconstruction-overview-of-scripts)
+    + [Dependencies](#dependencies)
+    + [Running the scripts](#running-the-scripts)
+    + [To Do](#to-do)
+
+Introduction
+------------
+
+To a newcomer it might not be immediately clear why a *generic detector 
+library* based on `dd4hep` is a good solution to the 'simulation and 
+reconstruction geometry problem'. However, with the following examples we 
+intend to show how generic detector libraries can be used to access the 
+geometry information in simulation and reconstruction. 
+
+We try to emphasize in the following examples that dd4hep (plus a data model) 
+allows the software components to be only loosely decoupled. This allows for a 
+'no framework' framework approach where the emphasis is on the underlying 
+algorithms used (or being designed). Furthermore, using ROOT's TDataframe, the 
+details of each task are made manifest.
+
+Furthermore, the 'no framework' framework allows for the each step to be 
+executed using any tool available, however, the IO and data model should be 
+fixed. 
+
+
+How to build a detector from scratch
+------------------------------------
+
+Building a new (generic) detector using dd4hep is rather straight forward if we 
+make the following assumptions.
+
+1. We will use the built-in sensitive detectors
+2. We will use the built-in data model (hits) associated with these detectors
+
+These items can be customized by using the DD4hep plugin mechanism. This will 
+be covered in another tutorial.
+
+### Compiling a new detector
+
+For this tutorial we will build a simplified Roman Pot detector.
+We will discuss the detector built in the source file
+`src/GenericDetectors/src/SimpleRomanPot_geo.cpp`.
+To compile this detector into the GenericDetectors library the detector needs 
+to be added to the list of sources in the cmake file 
+`src/GenericDetectors/CMakeLists.txt`.
+
+```
+dd4hep_add_plugin(${a_lib_name} SOURCES
+  src/BeamPipe_geo.cpp
+  ...
+  src/SimpleRomanPot_geo.cpp # add this line
+  )
+```
+
+###  Building the geometry
+
+The work of defining the detector is done in a function (here called 
+`build_detector`) that is registered using the DD4hep plugin macro 
+`DECLARE_DETELEMENT`.
+
+```
+static Ref_t build_detector(Detector& dtor, xml_h e, SensitiveDetector sens)
+{
+  xml_det_t   x_det     = e;
+  Material    air       = dtor.air();
+...
+}
+DECLARE_DETELEMENT(SimpleRomanPot, build_detector)
+```
+
+The argument signature of the `build_detector` is:
+- `Detector& dtor`: This handle provides the main hook to the detector tree (`dd4hep::Detector`).
+- `xml_h e`: Handle to the XML `<detector>` tag associated with the detector in 
+  the "compact" detector description file (more on this later). This provides 
+  the mechanism for feeding in the run-time construction parameters. 
+- `SensitiveDetector sens`: The sensitive detector to be assigned to the 
+  sensitive volumes/elements of the detector. 
+
+The DD4hep plugin macro `DECLARE_DETELEMENT(SimpleRomanPot, build_detector)` 
+stamps out the necessary boiler plate code to register a new detector called 
+`SimpleRomanPot` which is build by calling `build_detector`.
+
+#### Compact detector description entry element
+
+The `<detector>` tag defines a new instance of a detector and requires the 
+attributes "id", "name", and "type". For example:
+
+```
+<detector id="1" name="MyRomanPot" type="SimpleRomanPot"
+          vis="RedVis" readout="RomanPotHits" zoffset="1.0*m">
+</detector>
+````
+
+This defines an instance of the detector named "MyRomanPot" of type 
+"SimpleRomanPot" (i.e. the type-name given in the first argument of the DD4hep 
+`DECLARE_DETELEMENT` macro) and with id=1. The additional attributes (vis, 
+readout, zoffset) will are optional.
+
+The detector tag is provided as the second argument in the `build_detector` 
+function. It can be parsed *how ever you want* in order to extract detector 
+information. The allowed attributes are listed in 
+[`UnicodeValues.h`](http://test-dd4hep.web.cern.ch/test-dd4hep/doxygen/html/_unicode_values_8h_source.html) 
+where it is clear how to add new attributes.
+
+
+#### Geometry Construction
+
+If you are familiar with Geant4 or TGeo geometry construction then this will be 
+easy. DD4hep has TGeo under hood but there are a few naming tweaks. The 
+following table will help orient the user. 
+
+| *DD4hep*       |   *Geant4*        | *TGeo |
+| ------       | --------        | ---- |
+| Solid        | G4VSolid        | TGeoShape |
+| Volume       | G4LogicalVolume | TGeoVolume |
+| PlacedVolume | G4PVPlacement   | TGeoNode |
+| Element      | G4Element       | TGeoElement |
+| Material     | G4Material      | TGeoMaterial/TGeoMedium|
+
+##### XML Parsing Tip : Provide good default values
+
+If you have a detector parameter which we later will tweak (while optimizing 
+the design) try to get the value from the xml element but provide a good 
+default value.  For example:
+
+```
+double radius = ( x_det.hasAttr(_Unicode(radius)) ) ?  x_det.attr<double>(_Unicode(radius)) : 5.0*dd4hep::cm;
+```
+
+This provides a default radius of 5 cm when `x_det` does not have a "radius" 
+attribute defined. We will return to this later. 
+
+####  Critical parts of build_detector
+
+
+We will now look at parts of the source file `src/GenericDetectors/src/SimpleRomanPot_geo.cpp`.
+
+```
+static Ref_t build_detector(Detector& dtor, xml_h e, SensitiveDetector sens)
+{
+  xml_det_t   x_det     = e;
+  Material    air       = dtor.air();
+  Material    carbon    = dtor.material("CarbonFiber");
+  Material    silicon   = dtor.material("SiliconOxide");
+  Material    aluminum  = dtor.material("Aluminum");
+  Material    vacuum    = dtor.material("Vacuum");
+  Material supp_mat     = carbon;
+  Material sens_mat     = silicon;
+  int           det_id   = x_det.id();      // id=1
+  string        det_name = x_det.nameStr(); // "MyRomanPot"
+```
+
+Here we are grabbing the materials that are assumed to be already defined. Also 
+we are getting the detector id and name defined in the `detector` tag.
+
+Next we define an [Assembly 
+volume](http://test-dd4hep.web.cern.ch/test-dd4hep/doxygen/html/classdd4hep_1_1_assembly.html).
+Here we also stumble upon the important class 
+[`dd4hep::DetElement`](http://test-dd4hep.web.cern.ch/test-dd4hep/doxygen/html/classdd4hep_1_1_det_element.html#details).
+It is a means of providing the detector hierarchy/tree, but doesn't necessarily 
+have to map exactly to detector geometry. However, it typically will typically 
+parallel the geometry (and probably should).
+
+```
+  string  module_name = "RomanPot";
+  Assembly    assembly(det_name + "_assembly");
+  DetElement  sdet(    det_name, det_id);
+  sens.setType("tracker");
+```
+The last line sets the `SensitiveDetector sens` argument to be the tracker type 
+(which is a DD4hep built-in). We will soon assign this to sensitive volumes.  
+`sdet` is associated with the mother detector element by the constructor which 
+looks up the detector name (here "MyRomanPot").
+
+```
+  double z_offset  = (x_det.hasAttr(_Unicode(zoffset))) ? x_det.attr<double>(_Unicode(zoffset)) : 0.0;
+  double thickness  = (x_det.hasAttr(_Unicode(thickness))) ? x_det.attr<double>(_Unicode(thickness)) : 0.01*dd4hep::cm;
+```
+Here we grab attributes and provide default values. We continue with default 
+values that could also be define through attributes, however, we will want to 
+add child elements of the detector tag (so the attributes does not grow too 
+long).
+
+```
+  double rp_chamber_thickness = 5.0*dd4hep::mm;
+  double rp_chamber_radius    = 5.0*dd4hep::cm;
+  double rp_chamber_length    = 50.0*dd4hep::cm;
+  Tube    rp_beam_pipe_tube(rp_chamber_radius, rp_chamber_radius+rp_chamber_thickness, rp_chamber_length/2.0);
+  Tube    rp_beam_vacuum_tube(0.0, rp_chamber_radius+rp_chamber_thickness, rp_chamber_length/2.0);
+  Tube    rp_beam_vacuum_tube2(0.0, rp_chamber_radius, rp_chamber_length/2.0);
+
+  double rp_detector_tube_radius    = 2.5*dd4hep::cm;
+  double rp_detector_tube_length    = 20.0*dd4hep::cm;
+  Tube    rp_detector_tube(rp_detector_tube_radius, rp_detector_tube_radius+rp_chamber_thickness, rp_detector_tube_length/2.0);
+  Tube    rp_detector_vacuum_tube(0.0, rp_detector_tube_radius+rp_chamber_thickness, rp_detector_tube_length/2.0);
+  Tube    rp_detector_vacuum_tube2(0.0, rp_detector_tube_radius, rp_detector_tube_length/2.0);
+
+  ROOT::Math::Rotation3D rot_X( ROOT::Math::RotationX(M_PI/2.0) );
+  ROOT::Math::Rotation3D rot_Y( ROOT::Math::RotationY(M_PI/2.0) );
+
+  UnionSolid rp_chamber_tee1(rp_beam_vacuum_tube, rp_detector_vacuum_tube, rot_X);
+  UnionSolid rp_chamber_tee12(rp_chamber_tee1, rp_detector_vacuum_tube, rot_Y);
+
+  UnionSolid rp_chamber_tee2(rp_beam_vacuum_tube2, rp_detector_vacuum_tube2, rot_X);
+  UnionSolid rp_chamber_tee22(rp_chamber_tee2, rp_detector_vacuum_tube2, rot_Y);
+
+  SubtractionSolid  sub1(rp_chamber_tee12,rp_chamber_tee22);
+  Volume  rp_chamber_vol("rp_chamber_walls_vol", sub1, aluminum);
+  Volume  rp_vacuum_vol("rp_chamber_vacuum_vol", rp_chamber_tee22, vacuum);
+```
+The above code builds the up the two solids associated with 3 tubes 
+intersecting. One volume is the aluminum vacuum chamber walls and the other is 
+the vacuum contained within this envelope.
+
+Next we must place these two volumes in the assembly volume (which is just an 
+empty container-like volume.  The PlacedVolume is then associated with a 
+BitFieldValue  in the readout's BitField64 readout string.  In this case the 
+"layer" BitFieldValue. The BitField64 is used to construct unique VolumeIDs and 
+CellIDs for PlacedVolumes and Segmentations  respectively.
+
+```
+  PlacedVolume pv;
+  pv = assembly.placeVolume( rp_chamber_vol );
+  pv = assembly.placeVolume( rp_vacuum_vol );
+  pv.addPhysVolID( "layer", 2 );
+```
+
+Set the PlacedVolume BitFieldValue ID. "2" in this case.
+
+```
+  double supp_x_half         = 1.0*dd4hep::cm;
+  double supp_y_half         = 1.0*dd4hep::cm;
+  double supp_thickness      = 1.0*dd4hep::mm;
+  double supp_gap_half_width = 1.0*dd4hep::mm;
+  double sens_thickness      = 0.1*dd4hep::mm;
+
+  Box supp_box( supp_x_half,     supp_y_half,     supp_thickness/2.0 );
+  Box sens_box( supp_x_half-supp_gap_half_width, supp_y_half-supp_gap_half_width, sens_thickness/2.0 );
+
+```
+
+Next we define vectors which are used to define a "surface" (which will later 
+generate simulation tracker hits).
+
+```
+  // 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. ) ;
+  //Vector3D o( 0. , 0. , 0. ) ;
+
+  // 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
+  // The tracking surface is used in reconstruction. It provides  material thickness
+  // and radation lengths needed for various algorithms, routines, etc.
+  double inner_thickness = supp_thickness/2.0;
+  double outer_thickness = supp_thickness/2.0;
+  double z_shift  = 5.0*dd4hep::mm;
+  double xy_shift = 15.0*dd4hep::mm;
+
+  SurfaceType type( SurfaceType::Sensitive ) ;
+```
+
+We now define a simple rectangular pixel sensor. This will be the first of 
+four:  two will come in along the x axis and two along the y axis.
+
+```
+  // ------------- x1
+  Volume      support1_vol( "xsenseor_supp", supp_box, supp_mat  );
+  Volume      sensor1_vol(  "xsenseor_sens", sens_box, sens_mat );
+  VolPlane    surf1( sensor1_vol, type, inner_thickness , outer_thickness, u,v,n);
+  sensor1_vol.setSensitiveDetector(sens);
+```
+The code above builds two volumes one which will contain the sensitive volume.  
+The sensitive volume is assigned to be a sensitive detector.
+
+```
+  DetElement layer1_DE( sdet, "layer1_DE", 1 );
+  pv = rp_vacuum_vol.placeVolume( support1_vol, Position(xy_shift,0, -z_shift) );
+  pv.addPhysVolID("layer", 1 );  
+  layer1_DE.setPlacement( pv ) ;
+```
+The above creates a new DetElement, places the support volume in the vacuum, 
+sets this PlacedVolume to associate with the layer bitfield, and adds the PV to 
+the DetElement. Note the DetElement is constructed with the parent element 
+(sdet) being the first argument. In this way it is clear we are building,  
+(semi-)parallel to the geometry, a detector element hierarchy.
+
+```
+  DetElement  mod1(  layer1_DE , "module_1", 1 );
+  pv = support1_vol.placeVolume(sensor1_vol, Position(0,0,0));
+  pv.addPhysVolID("module", 1 );  
+  mod1.setPlacement( pv );
+```
+This creates the module DetElement and places the sensitive volume in the 
+support volume (already placed). It also assocates the pv with the module 
+bitfield and then adds the PV to the DetElement.
+
+The above is repeated for the three remaining sensitive elements. 
+
+Finally we get the top level volume to place the assemble volume.  Note we are 
+using the zoffset. This PV is then associated with the top level "system" 
+bitfieldvalue.
+
+```
+  pv = dtor.pickMotherVolume(sdet).placeVolume(assembly, Position(0,0,z_offset));
+  pv.addPhysVolID("system", det_id);      // Set the subdetector system ID.
+  sdet.setPlacement(pv);
+
+  assembly->GetShape()->ComputeBBox() ;
+  return sdet;
+}
+
+```
+
+The Readout and Bit Fields
+--------------------------
+
+
+Simple Reconstruction Overview of scripts
+---------------------------------------
+
+In the examples here we use ROOT and the LCIO data model.
+The following scripts should be executed in order:
+
+1. `run_example` : bash script that runs `ddsim` with the Geant4 macro file 
+   `gps.mac` and the input geometry defined in `gem_tracker_disc.xml`.
+2. `scripts/example_hit_position.cxx` : ROOT script showing how to use both the 
+   "segmentation" and "surface" geometry to get the hit position information. 
+3. `scripts/example_cell_size.cxx` : ROOT script showing how information about 
+   the geometry beyond the position.
+4. `scripts/example_digi.cxx` : ROOT script performing a crude digitization of 
+   gem tracker hits.
+5. `scripts/example_hit_recon.cxx` : ROOT script that shows how to to use 
+   dd4hep to lookup a 'segment' (cell) position based on the unique cellID 
+   attached to the hit object.
+6. `scripts/example_tracking.cxx` : ROOT script showing how to use the 
+   `GenFind` finding library along with `GenFit` to produce tracks.
+
+### Dependencies
+
+There are some library dependencies:
+
+- DD4hep
+- lcgeo
+- GenFind
+- GenFit
+- NPdet
+
+
+### Running the scripts
+
+
+```
+./run_example
+root scripts/example_digi.cxx++
+root scripts/example_hit_position.cxx++ # no output
+root scripts/example_cell_size.cxx++    # no output
+root scripts/example_hit_recon.cxx++
+root scripts/example_tracking.cxx++
+```
+
+### To Do
+
+- Show how to build a detector
+- Finish track fitting script.
+- Create example for basic PFA usage
+
-- 
GitLab