npdet_to_step.cxx
Go to the documentation of this file.
1 #include "Math/Vector3D.h"
2 #include "Math/Vector4D.h"
3 #include "Math/VectorUtil.h"
4 #include "TCanvas.h"
5 #include "TLegend.h"
6 #include "TMath.h"
7 #include "TRandom3.h"
8 #include "TFile.h"
9 #include "TH1F.h"
10 #include "TH2F.h"
11 #include "TH1D.h"
12 #include "TH2D.h"
13 #include "TTree.h"
14 #include "TF1.h"
15 
16 #include <vector>
17 #include <tuple>
18 #include <algorithm>
19 #include <iterator>
20 #include <experimental/filesystem>
21 namespace fs = std::experimental::filesystem;
22 
23 // DD4hep
24 // -----
25 // In .rootlogon.C
26 // gSystem->Load("libDDDetectors");
27 // gSystem->Load("libDDG4IO");
28 // gInterpreter->AddIncludePath("/opt/software/local/include");
29 #include "DD4hep/Detector.h"
30 #include "DDG4/Geant4Data.h"
31 #include "DDRec/CellIDPositionConverter.h"
32 #include "DDRec/SurfaceManager.h"
33 #include "DDRec/Surface.h"
34 #include "DD4hep/DD4hepUnits.h"
35 #include "DD4hep/Printout.h"
36 
37 #include "TApplication.h"
38 #include "TMultiGraph.h"
39 #include "TGraph.h"
40 #include "TGeoToStep.h"
41 #include "TGeoManager.h"
42 #include "TGeoNode.h"
43 #include "TGeoVolume.h"
44 
45 #include "Math/DisplacementVector3D.h"
46 
47 #include <iostream>
48 #include <string>
49 
50 #include "clipp.h"
51 using namespace clipp;
52 
53 enum class mode { none, help, list, part };
54 
55 struct settings {
56  using string = std::string;
57  using part_map = std::map<string,int>;
58  //bool help = false;
59  bool success = false;
60  string infile = "";
61  string outfile = "detector_geometry";
62  string part_name = "";
63  int part_level = -1;
64  mode selected = mode::list;
65  bool level_set = false;
66  int global_level = 1;
67  bool list_all = false;
69 };
70 //______________________________________________________________________________
71 
72 void run_list_mode(const settings& s);
73 void run_part_mode(const settings& s);
74 //______________________________________________________________________________
75 
76 template<typename T>
77 void print_usage(T cli, const char* argv0 ){
78  std::cout << "Usage:\n" << usage_lines(cli, argv0)
79  << "\nOptions:\n" << documentation(cli) << '\n';
80 }
81 //______________________________________________________________________________
82 
83 template<typename T>
84 void print_man_page(T cli, const char* argv0 ){
85  //all formatting options (with their default values)
86  auto fmt = clipp::doc_formatting{}
87  .start_column(8) //column where usage lines and documentation starts
88  .doc_column(20) //parameter docstring start col
89  .indent_size(4) //indent of documentation lines for children of a documented group
90  .line_spacing(0) //number of empty lines after single documentation lines
91  .paragraph_spacing(1) //number of empty lines before and after paragraphs
92  .flag_separator(", ") //between flags of the same parameter
93  .param_separator(" ") //between parameters
94  .group_separator(" ") //between groups (in usage)
95  .alternative_param_separator("|") //between alternative flags
96  .alternative_group_separator(" | ") //between alternative groups
97  .surround_group("(", ")") //surround groups with these
98  .surround_alternatives("(", ")") //surround group of alternatives with these
99  .surround_alternative_flags("", "") //surround alternative flags with these
100  .surround_joinable("(", ")") //surround group of joinable flags with these
101  .surround_optional("[", "]") //surround optional parameters with these
102  .surround_repeat("", "..."); //surround repeatable parameters with these
103  //.surround_value("<", ">") //surround values with these
104  //.empty_label("") //used if parameter has no flags and no label
105  //.max_alternative_flags_in_usage(1) //max. # of flags per parameter in usage
106  //.max_alternative_flags_in_doc(2) //max. # of flags per parameter in detailed documentation
107  //.split_alternatives(true) //split usage into several lines for large alternatives
108  //.alternatives_min_split_size(3) //min. # of parameters for separate usage line
109  //.merge_alternative_flags_with_common_prefix(false) //-ab(cdxy|xy) instead of -abcdxy|-abxy
110  //.merge_joinable_flags_with_common_prefix(true); //-abc instead of -a -b -c
111 
112  auto mp = make_man_page(cli, argv0, fmt);
113  mp.prepend_section("DESCRIPTION", "Geometry tool for converting compact files to STEP (cad) files.");
114  mp.append_section("EXAMPLES", " $ npdet_to_step list compact.xml");
115  std::cout << mp << "\n";
116 }
117 //______________________________________________________________________________
118 
119 settings cmdline_settings(int argc, char* argv[])
120 {
121  settings s;
122 
123  //auto listMode = "list mode:" % (
124  // command("list").set(s.selected,mode::list) % "list detectors and print info about geometry ",
125  // option("-v","--verbose")
126  // );
127  auto listMode = "list mode:" % repeatable(
128  command("list").set(s.selected,mode::list) % "list detectors and print info about geometry ",
129  repeatable(
130  option("-l","--level").set(s.level_set)
131  & value("level",s.part_level)
132  & value("name")([&](const std::string& p)
133  {
134  s.part_name = p;
135  if(!s.level_set) { s.part_level = -1; }
136  s.part_name_levels[p] = s.part_level;
137  s.level_set = false;
138  }) % "Part/Node name (must be child of top node)"
139  )
140  );
141 
142  auto partMode = "part mode:" % repeatable(
143  command("part").set(s.selected,mode::part) % "Select only the first level nodes by name",
144  repeatable(
145  option("-l","--level").set(s.level_set) & value("level",s.part_level) % "Maximum level navigated to for part",
146  value("name")([&](const std::string& p)
147  {
148  s.part_name = p;
149  if(!s.level_set) { s.part_level = -1; }
150  s.part_name_levels[p] = s.part_level;
151  s.level_set = false;
152  }) % "Part/Node name (must be child of top node)"
153  )
154  );
155 
156  auto lastOpt = " options:" % (
157  option("-h", "--help").set(s.selected, mode::help) % "show help",
158  option("-g","--global_level") & integer("level",s.global_level),
159  option("-o","--output") & value("out",s.outfile),
160  value("file",s.infile).if_missing([]{ std::cout << "You need to provide an input xml filename as the last argument!\n"; } )
161  % "input xml file"
162  );
163 
164  auto helpMode = command("help").set(s.selected, mode::help);
165 
166  auto cli = (
167  helpMode | (partMode | listMode , lastOpt)
168  );
169 
170  assert( cli.flags_are_prefix_free() );
171  auto res = parse(argc, argv, cli);
172 
173  //auto doc_label = [](const parameter& p) {
174  // if(!p.flags().empty()) return p.flags().front();
175  // if(!p.label().empty()) return p.label();
176  // return doc_string{"<?>"};
177  //};
178  //std::string wrong;
179 
180  //auto& os = std::cout;
181  //std::cout << "args -> parameter mapping:\n";
182  //for(const auto& m : res) {
183  // os << "#" << m.index() << " " << m.arg() << " -> ";
184  // auto p = m.param();
185  // if(p) {
186  // os << doc_label(*p) << " \t";
187  // if(m.repeat() > 0) {
188  // os << (m.bad_repeat() ? "[bad repeat " : "[repeat ")
189  // << m.repeat() << "]";
190  // }
191  // if(m.blocked()) os << " [blocked]";
192  // if(m.conflict()) os << " [conflict]";
193  // os << '\n';
194  // }
195  // else {
196  // os << " [unmapped]\n";
197  // }
198  //}
199 
200  //std::cout << "missing parameters:\n";
201  //for(const auto& m : res.missing()) {
202  // auto p = m.param();
203  // if(p) {
204  // os << doc_label(*p) << " \t";
205  // os << " [missing after " << m.after_index() << "]\n";
206  // }
207  //}
208 
209  //std::cout << "wrong " << wrong << std::endl;
210  //if(res.unmapped_args_count()) { std::cout << "a\n"; }
211  //if(res.any_bad_repeat()) { std::cout << "b\n"; }
212  //if(res.any_blocked()) { std::cout << "c\n"; }
213  //if(res.any_conflict()) { std::cout << "d\n"; }
214 
215  if(s.selected == mode::help) {
216  print_man_page<decltype(cli)>(cli,argv[0]);
217  return s;
218  }
219 
220  if( res.any_error() ) {
221  s.success = false;
222  std::cout << make_man_page(cli, argv[0]).prepend_section("error: ",
223  " The best thing since sliced bread.");
224  return s;
225  }
226 
227  s.success = true;
228 
229  return s;
230 }
231 //______________________________________________________________________________
232 
233 
234 int main (int argc, char *argv[]) {
235 
236  settings s = cmdline_settings(argc,argv);
237  if( !s.success ) {
238  return 1;
239  }
240 
241  if(s.selected == mode::help) {
242  return 0;
243  }
244 
245  // --------------------------------------
246  // CLI Checks
247  if( !fs::exists(fs::path(s.infile)) ) {
248  std::cerr << "file, " << s.infile << ", does not exist\n";
249  return 1;
250  }
251  auto has_suffix = [&](const std::string &str, const std::string &suffix) {
252  return str.size() >= suffix.size() &&
253  str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
254  };
255  if( !has_suffix(s.outfile,".stp") ) {
256  s.outfile += ".stp";
257  }
258 
259  // Make things quite
260  gErrorIgnoreLevel = kWarning;// kPrint, kInfo, kWarning,
261  dd4hep::setPrintLevel(dd4hep::WARNING);
262 
263  // ---------------------------------------------
264  // Run modes
265  //
266  switch(s.selected) {
267  case mode::list:
268  run_list_mode(s);
269  break;
270  case mode::part:
271  run_part_mode(s);
272  break;
273  default:
274  break;
275  }
276 
277  return 0;
278 }
279 //______________________________________________________________________________
280 
281 
282 void print_daughter_nodes(TGeoNode* node, int print_depth) {
283  TGeoIterator nextNode( node->GetVolume() );
284  int path_index = 0;
285  TGeoNode* currentNode = nullptr;
286 
287  nextNode.SetType(0);
288  while( (currentNode = nextNode()) ) {
289  // Not iterator level starts at 1
290  auto nlevel = nextNode.GetLevel();
291  if( nlevel > print_depth ) {
292  continue;
293  }
294  for(int i=0;i<nlevel; i++){
295  std::cout << " \t";
296  }
297  std::cout << "/" <<currentNode->GetName() << " \t(vol: " << currentNode->GetVolume()->GetName() << ")" << "\n";
298  }
299 }
300 //______________________________________________________________________________
301 
302 void run_list_mode(const settings& s)
303 {
304  dd4hep::setPrintLevel(dd4hep::WARNING);
305  gErrorIgnoreLevel = kWarning;// kPrint, kInfo, kWarning,
306 
307  // -------------------------
308  // Get the DD4hep instance
309  // Load the compact XML file
310  dd4hep::Detector& detector = dd4hep::Detector::getInstance();
311  detector.fromCompact(s.infile);
312 
313  if(s.part_name_levels.size() == 0 ){
314  std::cout << gGeoManager->GetPath() << "\n";
315  print_daughter_nodes(gGeoManager->GetTopNode(), 1);
316  }
317  for(const auto& [p,l] : s.part_name_levels){
318  bool dir = gGeoManager->cd(p.c_str());
319  if (!dir) {
320  std::cerr << p << " not found!\n";
321  continue;
322  }
323  std::cout << p << std::endl;
324  TGeoNode *node = gGeoManager->GetCurrentNode();
325  print_daughter_nodes(node, l);
326  }
327 
328  //detector.manager().GetTopVolume()->GetNodes()->Print();
329  //detector.manager().GetTopVolume()->GetNode(0)->Dump();
330 }
331 //______________________________________________________________________________
332 
333 void run_part_mode(const settings& s)
334 {
335 
336  dd4hep::setPrintLevel(dd4hep::WARNING);
337  gErrorIgnoreLevel = kWarning;// kPrint, kInfo, kWarning,
338 
339  // -------------------------
340  // Get the DD4hep instance
341  // Load the compact XML file
342  dd4hep::Detector& detector = dd4hep::Detector::getInstance();
343  detector.fromCompact(s.infile);
344 
345  //detector.manager().GetTopVolume()->GetNodes()->Print();
346  //detector.manager().GetTopVolume()->GetNode(0)->Dump();
347 
348  TGeoToStep * mygeom= new TGeoToStep( &(detector.manager()) );
349  if( s.part_name_levels.size() > 1 ) {
350  mygeom->CreatePartialGeometry( s.part_name_levels, s.outfile.c_str() );
351  } else if( s.part_name_levels.size() == 1 ) {
352  // loop of 1
353  for(const auto& [n,l] : s.part_name_levels){
354  mygeom->CreatePartialGeometry( n.c_str(), l, s.outfile.c_str() );
355  }
356  } else {
357  mygeom->CreateGeometry(s.outfile.c_str(), s.global_level);
358  }
359  //detector.manager().Export("geometry.gdml");
360 }
361 
std::map< std::string, int > part_name_levels
parameter value(const doc_string &label, Targets &&... tgts)
makes required, blocking, repeatable value parameter; matches any non-empty string
Definition: clipp.h:2094
primary namespace
Definition: clipp.h:36
doc_formatting & alternative_group_separator(const string &sep)
determines string for separating alternative groups
Definition: clipp.h:5116
doc_formatting & indent_size(int indent)
determines indent of documentation lines for children of a documented group
Definition: clipp.h:5083
detail::assign_value< T, V > set(T &target, V value)
makes function object with a const char* parameter that assigns a value to a ref-captured object
Definition: clipp.h:1055
man_page make_man_page(const group &params, doc_string progname="", const doc_formatting &fmt=doc_formatting{})
generates man sections from command line parameters with sections "synopsis" and "options"
Definition: clipp.h:6086
parameter repeatable(parameter p)
makes a repeatable copy of a parameter
Definition: clipp.h:3592
doc_formatting & start_column(int col)
determines column where documentation printing starts
Definition: clipp.h:5074
settings cmdline_settings(int argc, char *argv[])
std::string outfile
parameter option(String &&flag, Strings &&... flags)
makes optional, non-blocking exact match parameter
Definition: clipp.h:2078
doc_formatting & surround_optional(const string &prefix, const string &postfix)
determnines strings surrounding optional parameters/groups
Definition: clipp.h:5141
void run_list_mode(const settings &s)
doc_formatting & surround_alternative_flags(const string &prefix, const string &postfix)
determnines strings surrounding alternative flags
Definition: clipp.h:5171
doc_formatting & param_separator(const string &sep)
determines string for separating parameters
Definition: clipp.h:5095
doc_formatting & alternative_param_separator(const string &sep)
determines string for separating alternative parameters
Definition: clipp.h:5109
parsing_result parse(arg_list args, const group &cli)
parses vector of arg strings and executes actions
Definition: clipp.h:4941
generates usage lines
Definition: clipp.h:5316
int main(int argc, char *argv[])
Derived & if_missing(simple_action a)
adds an action that will be called if a required parameter is missing
Definition: clipp.h:1252
void run_part_mode(const settings &s)
int global_level
doc_formatting & line_spacing(int lines)
determines number of empty rows after one single-line documentation entry
Definition: clipp.h:5217
std::string infile
parameter integer(const doc_string &label, Targets &&... tgts)
makes required, blocking value parameter; matches any string that represents an integer
Definition: clipp.h:2358
doc_formatting & doc_column(int col)
determines column where docstrings start
Definition: clipp.h:5078
void print_usage(T cli, const char *argv0)
parameter command(String &&flag, Strings &&... flags)
makes required non-blocking exact match parameter
Definition: clipp.h:2048
void print_man_page(T cli, const char *argv0)
doc_formatting & surround_group(const string &prefix, const string &postfix)
determnines strings surrounding non-exclusive groups
Definition: clipp.h:5181
part_map part_name_levels
std::map< string, int > part_map
man_page & prepend_section(string title, string content)
Definition: clipp.h:6025
void print_daughter_nodes(TGeoNode *node, int print_depth)
Derived & set(Target &t)
adds an action that will set the value of 't' from a 'const char*' arg
Definition: clipp.h:1215
Detector
Definition: DDG4.py:69
documentation formatting options
Definition: clipp.h:5069
doc_formatting & flag_separator(const string &sep)
determines string for separating flags of the same parameter
Definition: clipp.h:5123
doc_formatting & surround_repeat(const string &prefix, const string &postfix)
determnines strings surrounding repeatable parameters/groups
Definition: clipp.h:5151
generates parameter and group documentation from docstrings
Definition: clipp.h:5781
doc_formatting & paragraph_spacing(int lines)
determines number of empty rows before and after a paragraph; a paragraph is defined by a documented ...
Definition: clipp.h:5226
string part_name
doc_formatting & surround_alternatives(const string &prefix, const string &postfix)
determnines strings surrounding exclusive groups
Definition: clipp.h:5161
doc_formatting & group_separator(const string &sep)
determines string for separating groups (in usage lines)
Definition: clipp.h:5102
doc_formatting & surround_joinable(const string &prefix, const string &postfix)
determnines strings surrounding joinable groups
Definition: clipp.h:5191