DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
graphicalScan.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 //==========================================================================
11 //
12 // Simple program to make a "CT-scan" of a detector materials
13 // makes series of slices perpendicular to X, Y, or Z axis
14 // produces a TFile with a TH2F per slice
15 // scans the material along a few (2*nSamples, in the 2 slice dimensions) paths across each bin
16 // fills histogram bins with:
17 // average X0/length across these paths
18 // average lambda/length across these paths
19 // for each material, fraction of path length which crosses that material
20 // (inspired by material scan)
21 //
22 // Author : D.Jeans, UTokyo
23 //
24 //==========================================================================
25 
26 #include <TError.h>
27 #include <TFile.h>
28 #include <TH2F.h>
29 
30 // Framework include files
31 #include <DD4hep/Detector.h>
32 #include <DD4hep/Printout.h>
33 #include <DDRec/MaterialManager.h>
34 
35 #include <iostream>
36 #include <climits>
37 #include <cerrno>
38 #include <string>
39 #include <map>
40 
41 #undef NDEBUG
42 #include <cassert>
43 
44 using namespace dd4hep;
45 using namespace dd4hep::rec;
46 
47 using std::cout;
48 using std::endl;
49 
50 int main_wrapper(int argc, char** argv) {
51  struct Handler {
52  Handler() { SetErrorHandler(Handler::print); }
53  static void print(int level, Bool_t abort, const char *location, const char *msg) {
54  if ( level > kInfo || abort ) ::printf("%s: %s\n", location, msg);
55  }
56  static void usage() {
57  std::cout << " usage: graphicalScan compact.xml axis xMin xMax yMin yMax zMin zMax nSlices nBins nSamples FieldOrMaterial OutfileName" << std::endl
58  << " axis (X, Y, or Z) : perpendicular to the slices" << std::endl
59  << " xMin xMax yMin yMax zMin zMax : range of scans " << std::endl
60  << " nSlices : number of slices (equally spaced along chose axis)" << std::endl
61  << " nBins : number of bins along each axis of histograms" << std::endl
62  << " nSamples : the number of times each bin is sampled " << std::endl
63  << " FieldOrMaterial : scan field or material? F = field, M = material, FM or MF = both" << std::endl
64  << " OutfileName : output root file name" << std::endl
65  << " -> produces graphical scans of material and/or fields defined in a compact xml description"
66  << std::endl;
67  exit(1);
68  }
69  } _handler;
70 
71  // "axis" is the normal to the slices, which are equally spaced between the corresponding max and min
72  // each slice has nBins x nBins in the specified range
73  // the material in each bin is sampled along 2*nTests paths
74 
75  if( argc != 14 ) Handler::usage();
76 
77  std::string inFile = argv[1]; // input geometry description compact xml file
78 
79  std::string XYZ = argv[2]; // the axis
80 
81  TString labx, laby;
82  unsigned int index[3] = {99,99,99};
83  if ( XYZ=="x" || XYZ=="X" ) {
84  index[0] = 0; // this is the one perpendicular to slices
85  index[1] = 2;
86  index[2] = 1;
87  labx="Z [cm]";
88  laby="Y [cm]";
89  } else if ( XYZ=="y" || XYZ=="Y" ) {
90  index[0] = 1;
91  index[1] = 2;
92  index[2] = 0;
93  labx="Z [cm]";
94  laby="X [cm]";
95  } else if ( XYZ=="z" || XYZ=="Z" ) {
96  index[0] = 2;
97  index[1] = 0;
98  index[2] = 1;
99  labx="X [cm]";
100  laby="Y [cm]";
101  } else {
102  cout << "invalid XYZ" << endl;
103  return -1;
104  }
105 
106  double x0,y0,z0,x1,y1,z1;
107  unsigned int nslice, nbins, mm_count;
108  std::stringstream sstr;
109  sstr <<
110  argv[3] << " " << argv[4] << " " << argv[5] << " " <<
111  argv[6] << " " << argv[7] << " " << argv[8] << " " <<
112  argv[9] << " " << argv[10] << " " << argv[11] << "NONE";
113  sstr >> x0 >> x1 >> y0 >> y1 >> z0 >> z1 >> nslice >> nbins >> mm_count ;
114  if ( !sstr.good() ) {
115  Handler::usage();
116  ::exit(EINVAL);
117  }
118 
119  std::string FM = argv[12];
120  std::string outFileName = argv[13];
121 
122  if ( x0>x1 ) { double temp=x0; x0=x1; x1=temp; }
123  if ( y0>y1 ) { double temp=y0; y0=y1; y1=temp; }
124  if ( z0>z1 ) { double temp=z0; z0=z1; z1=temp; }
125 
126  if ( ! (nbins>0 && nbins<USHRT_MAX && nslice>0 && nslice<USHRT_MAX) ) {
127  cout << "funny # bins/slices " << endl;
128  ::exit(EINVAL);
129  }
130 
131  bool scanField(false);
132  bool scanMaterial(false);
133  if ( FM=="f" || FM=="F" ) {
134  scanField=true;
135  } else if ( FM=="m" || FM=="M" ) {
136  scanMaterial=true;
137  } else if ( FM=="fm" || FM=="FM" || FM=="mf" || FM=="MF" ) {
138  scanField=true;
139  scanMaterial=true;
140  } else {
141  cout << "invalid field/material flag: use one of f/F/m/M/fm/FM/mf/MF" << endl;
142  return 1;
143  }
144 
145  double mmin[3]={x0,y0,z0};
146  double mmax[3]={x1,y1,z1};
147 
148 
149  //------
150 
151  Detector& description = Detector::getInstance();
152  description.fromCompact(inFile);
153 
154  //-----
155 
156  TFile* f = new TFile(outFileName.c_str(),"recreate");
157 
158  Vector3D p0, p1; // the two points between which material is calculated
159 
160  MaterialManager matMgr(description.world().volume() ) ;
161 
162  for (unsigned int isl=0; isl<nslice; isl++) { // loop over slices
163 
164  double sz = nslice > 1 ?
165  mmin[index[0]] + isl*( mmax[index[0]] - mmin[index[0]] )/( nslice - 1 ) :
166  (mmin[index[0]] + mmax[index[0]])/2. ;
167 
168  p0.array()[ index[0] ] = sz;
169  p1.array()[ index[0] ] = sz;
170 
171  cout << "scanning slice " << isl << " at "+XYZ+" = " << sz << endl;
172 
173  TString dirn = "Slice"; dirn+=isl;
174  f->mkdir(dirn);
175  f->cd(dirn);
176 
177  std::map < std::string , TH2F* > scanmap;
178 
179 
180  TString hn = "slice"; hn+=isl; hn+="_X0";
181  TString hnn = "X0 "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
182 
183  for (int j=1; j<=2; j++) {
184  if ( mmax[index[j]] - mmin[index[j]] < 1e-4 ) {
185  cout << "ERROR: max and min of axis are the same!" << endl;
186  assert(0);
187  }
188  }
189 
190 
191  TH2F* h2slice = 0;
192 
193  if (scanMaterial) {
194 
195  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
196  scanmap["x0"] = h2slice;
197 
198  hn = "slice"; hn+=isl; hn+="_lambda";
199  hnn = "lambda "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
200  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
201  scanmap["lambda"] = h2slice;
202  }
203 
204  if (scanField) {
205  hn = "slice"; hn+=isl; hn+="_Bx";
206  hnn = "Bx[T] "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
207  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
208  scanmap["Bx"] = h2slice;
209 
210  hn = "slice"; hn+=isl; hn+="_By";
211  hnn = "By[T] "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
212  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
213  scanmap["By"] = h2slice;
214 
215  hn = "slice"; hn+=isl; hn+="_Bz";
216  hnn = "Bz[T] "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
217  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
218  scanmap["Bz"] = h2slice;
219 
220  hn = "slice"; hn+=isl; hn+="_Ex";
221  hnn = "Ex[V/m] "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
222  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
223  scanmap["Ex"] = h2slice;
224 
225  hn = "slice"; hn+=isl; hn+="_Ey";
226  hnn = "Ey[V/m] "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
227  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
228  scanmap["Ey"] = h2slice;
229 
230  hn = "slice"; hn+=isl; hn+="_Ez";
231  hnn = "Ez[V/m] "; hnn += XYZ; hnn+="="; hnn += Form("%7.3f",sz); hnn+=" [cm]";
232  h2slice = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
233  scanmap["Ez"] = h2slice;
234  }
235 
236 
237  for (int ix=1; ix<=h2slice->GetNbinsX(); ix++) { // loop over one axis of slice
238 
239  double xmin = h2slice->GetXaxis()->GetBinLowEdge(ix);
240  double xmax = h2slice->GetXaxis()->GetBinUpEdge(ix);
241 
242  for (int iy=1; iy<=h2slice->GetNbinsY(); iy++) { // and the other axis
243 
244  double ymin = h2slice->GetYaxis()->GetBinLowEdge(iy);
245  double ymax = h2slice->GetYaxis()->GetBinUpEdge(iy);
246 
247  if (scanField) {
248  // first get b field components in centre of bin
249  double posV[3];
250  posV[index[0]] = sz;
251  posV[index[1]] = 0.5*(xmin+xmax);
252  posV[index[2]] = 0.5*(ymin+ymax);
253 
254  double fieldV[3] ;
255  description.field().combinedMagnetic( posV , fieldV ) ;
256  scanmap["Bx"]->SetBinContent(ix, iy, fieldV[0] / dd4hep::tesla );
257  scanmap["By"]->SetBinContent(ix, iy, fieldV[1] / dd4hep::tesla );
258  scanmap["Bz"]->SetBinContent(ix, iy, fieldV[2] / dd4hep::tesla );
259 
260  description.field().combinedElectric( posV , fieldV ) ;
261  scanmap["Ex"]->SetBinContent(ix, iy, fieldV[0] / ( dd4hep::volt/dd4hep::meter ) );
262  scanmap["Ey"]->SetBinContent(ix, iy, fieldV[1] / ( dd4hep::volt/dd4hep::meter ) );
263  scanmap["Ez"]->SetBinContent(ix, iy, fieldV[2] / ( dd4hep::volt/dd4hep::meter ) );
264  }
265 
266  if (scanMaterial) {
267 
268  // for this bin, estimate the material
269  double sum_lambda(0);
270  double sum_x0(0);
271  double sum_length(0);
272 
273  std::map < std::string , float > materialmap;
274 
275  for (unsigned int jx=0; jx<2*mm_count; jx++) {
276  if ( jx<mm_count ) {
277  double xcom = xmin + (1+jx)*( xmax - xmin )/(mm_count+1.);
278  p0.array()[index[1]] = xcom; p0.array()[index[2]] = ymin;
279  p1.array()[index[1]] = xcom; p1.array()[index[2]] = ymax;
280  } else {
281  double ycom = ymin + (jx-mm_count+1)*( ymax - ymin )/(mm_count+1.);
282  p0.array()[index[1]] = xmin; p0.array()[index[2]] = ycom;
283  p1.array()[index[1]] = xmax; p1.array()[index[2]] = ycom;
284  }
285 
286  const MaterialVec& materials = matMgr.materialsBetween(p0, p1);
287  for( unsigned i=0,n=materials.size();i<n;++i){
288  TGeoMaterial* mat = materials[i].first->GetMaterial();
289  double length = materials[i].second;
290  sum_length += length;
291  double nx0 = length / mat->GetRadLen();
292  sum_x0 += nx0;
293  double nLambda = length / mat->GetIntLen();
294  sum_lambda += nLambda;
295 
296  std::string mname = mat->GetName();
297  if ( materialmap.find( mname )!=materialmap.end() ) {
298  materialmap[mname]+=length;
299  } else {
300  materialmap[mname]=length;
301  }
302 
303  }
304 
305  }
306 
307  scanmap["x0"]->SetBinContent(ix, iy, sum_x0/sum_length); // normalise to cm (ie x0/cm density: indep of bin size)
308  scanmap["lambda"]->SetBinContent(ix, iy, sum_lambda/sum_length);
309 
310  for ( std::map < std::string , float >::iterator jj = materialmap.begin(); jj!=materialmap.end(); jj++) {
311  if ( scanmap.find( jj->first )==scanmap.end() ) {
312  hn = "slice"; hn+=isl; hn+="_"+jj->first;
313  hnn = jj->first; hnn += " "+XYZ; hnn+="=";
314  // hnn+=sz;
315  hnn += Form("%7.3f",sz);
316  hnn+=" [cm]";
317  scanmap[jj->first] = new TH2F( hn, hnn, nbins, mmin[index[1]], mmax[index[1]], nbins, mmin[index[2]], mmax[index[2]] );
318  }
319  scanmap[jj->first]->SetBinContent(ix, iy, jj->second / sum_length );
320  }
321 
322  } // if (scanMaterial)
323 
324  }
325  }
326 
327  for ( std::map < std::string , TH2F* >::iterator jj = scanmap.begin(); jj!=scanmap.end(); jj++) {
328  jj->second->SetOption("zcol");
329  jj->second->GetXaxis()->SetTitle(labx);
330  jj->second->GetYaxis()->SetTitle(laby);
331  }
332  }
333  f->Write();
334  f->Close();
335  return 0;
336 }
337 
339 int main(int argc, char** argv) {
340  try {
341  return main_wrapper(argc, argv);
342  }
343  catch(const std::exception& e) {
344  std::cout << "Got uncaught exception: " << e.what() << std::endl;
345  }
346  catch (...) {
347  std::cout << "Got UNKNOWN uncaught exception." << std::endl;
348  }
349  return EINVAL;
350 }
dd4hep::OverlayedField::combinedElectric
void combinedElectric(const Position &pos, double *field) const
Returns the 3 electric field components (x, y, z) if many components are present.
Definition: Fields.cpp:155
dd4hep::Detector::world
virtual DetElement world() const =0
Return reference to the top-most (world) detector element.
dd4hep::rec
Namespace for the reconstruction part of the AIDA detector description toolkit.
Definition: SurfaceInstaller.h:28
dd4hep::rec::Vector3D::array
double * array()
direct access to data as double* - allows modification
Definition: Vector3D.h:216
dd4hep::rec::Vector3D
Definition: Vector3D.h:32
Detector.h
dd4hep::exception
void exception(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:69
dd4hep::rec::MaterialVec
std::vector< std::pair< Material, double > > MaterialVec
Definition: MaterialManager.h:30
main
int main(int argc, char **argv)
Main entry point as a program.
Definition: graphicalScan.cpp:339
dd4hep::OverlayedField::combinedMagnetic
void combinedMagnetic(const Position &pos, double *field) const
Returns the 3 magnetic field components (x, y, z) if many components are present.
Definition: Fields.cpp:161
dd4hep::Detector::getInstance
static Detector & getInstance(const std::string &name="default")
—Factory method----—
Definition: DetectorImp.cpp:150
dd4hep::DetElement::volume
Volume volume() const
Access to the logical volume of the detector element's placement.
Definition: DetElement.cpp:352
dd4hep::Detector::field
virtual OverlayedField field() const =0
Return handle to the combined electromagentic field description.
dd4hep::rec::MaterialManager
Definition: MaterialManager.h:41
dd4hep::Detector::fromCompact
virtual void fromCompact(const std::string &fname, DetectorBuildType type=BUILD_DEFAULT)=0
Deprecated call (use fromXML): Read compact geometry description or alignment file.
main_wrapper
int main_wrapper(int argc, char **argv)
Definition: graphicalScan.cpp:50
dd4hep::rec::MaterialManager::materialsBetween
const MaterialVec & materialsBetween(const Vector3D &p0, const Vector3D &p1, double epsilon=1e-4)
Definition: MaterialManager.cpp:40
MaterialManager.h
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
usage
void usage(std::string argv0)
Definition: listcomponents.cpp:41
Printout.h