Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
noiPads.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file noiPads.h
1 #ifndef tuClass__h
2 
3 #ifndef noiPads__h
4 #define noiPads__h
5 
6 #include "noiDict.h"
7 #include "noi_fnc.h"
8  const int kLeft = 2;
9  const int kRight = 3;
10 // David Stewart, Dec 1 2022
11 // Stripped down version of tuPads
12 // used in conveinece for plotting
13 struct noiPadDim {
14  // a structure to contain the four coordinates requisite for a TPad (in x or y):
15  // low : left/bottom edge of TPad (outer edge of margin)
16  // p_low : left/bottom edge of the plot area
17  // p_up : right/top edge of the plot area
18  // up : right/top edge of TPad
19  //
20  // If initialized with only two arguments (low, up), then set p_low to low and p_up to up
21  // If initialized with three arguments (low, plow, up) set p_up to up
22  double low;
23  double p_low;
24  double p_up;
25  double up;
26 
27  void check_input() {
28  if ( low < 0. || low > 1.
29  || p_low < 0. || p_low > 1.
30  || p_up < 0. || p_up > 1.
31  || up < 0. || up > 1. ) {
32  cout << " Fatal error: input coordinates for tuPadDim for pads must all "
33  " be in range [0,1] " << endl;
34  print();
35  exit (2);
36  } else if ( low > p_low || p_low > p_up || p_up > up ) {
37  cout << " Fatal error: input coordinates must monotonically increase " << endl;
38  print();
39  exit(2);
40  }
41  };
42  noiPadDim( double _low, double _p_low, double _p_up, double _up ) :
43  low{_low}, p_low{_p_low}, p_up{_p_up}, up{_up} { check_input(); };
44  noiPadDim( double _low, double _up ) :
45  low{_low}, p_low{_low}, p_up{_up}, up{_up} { check_input(); };
46  noiPadDim( double _low, double _p_low, double _up ) :
47  low{_low}, p_low{_p_low}, p_up{_up}, up{_up} { check_input(); };
48  noiPadDim( ) :
49  low{0.}, p_low{0.}, p_up{1.}, up{1.} { check_input(); };
50 
51  void print() const {
52  cout << Form(" Four points are: (%.2f, %.2f %.2f, %.2f)",low,p_low,p_up,up) << endl;
53  };
54  double low_margin () const {
55  double margin { (p_low - low) / (up - low) };
56  if (margin < 0) margin = 0;
57  return margin;
58  };
59  double up_margin () const {
60  // use to get set the lower margin
61  double margin { (up - p_up) / (up - low) };
62  if (margin < 0) margin = 0;
63  return margin;
64  };
65  bool operator==(noiPadDim& B) const {
66  return low == B.low
67  && p_low == B.p_low
68  && p_up == B.p_up
69  && up == B.up;
70  };
71 };
72 struct noiPadDimSet {
73  /* noiPadDimSet(int _nPads, // make negative is wish to flip directtuns */
74  /* vector<double> _lefts={}, */
75  /* vector<double> _rights={}); */
76  vector<double> lefts;
77  vector<double> rights;
78  int nPads;
79 
80  static noiPadDim make_pad(double left,
81  double left_margin, double pad_width,
82  double right_margin)
83  {
84  return noiPadDim{ left,
85  left+left_margin,
86  left+left_margin+pad_width,
87  left+left_margin+pad_width+right_margin };
88  };
89 
90  vector<noiPadDim> calc_pads() {
91  int npads = nPads;
92  bool flip_direction = false;
93  if (npads < 0) {
94  npads = -npads;
95  flip_direction=true;
96  };
97  vector<noiPadDim> pads (npads) ;
98 
99  double first_left = (lefts.size() > 0) ? lefts[0] : 0.2;
100  double inner_left = (lefts.size() > 1) ? lefts[1] : 0.0001;
101  double page_left = (lefts.size() > 2) ? lefts[2] : 0.01;
102 
103  double last_right = (rights.size() > 0) ? rights[0] : 0.0001;
104  double inner_right = (rights.size() > 1) ? rights[1] : 0.0;
105  double page_right = (rights.size() > 2) ? rights[2] : 0.01;
106 
107  if (npads == 0) throw std::runtime_error(
108  "fatal in noiPadDimSet must request at least one pad");
109  if (npads == 1) {
110  double pad_width = 1.-first_left-page_left-last_right-page_right;
111  if (pad_width<=0) throw std::runtime_error(
112  "fatal in noiPadDimSet margins have consumed more than 100\% of TCanvas");
113  pads[0] = make_pad( page_left, first_left, pad_width, last_right );
114  return pads;
115  }
116 
117  double pad_width { (1.-(first_left+page_left+last_right+page_right+
118  (inner_left+inner_right)*(npads-1)))/npads };
119  if (pad_width<=0) throw std::runtime_error(
120  "fatal in noiPadDimSet margins have consumed more than 100\% of TCanvas");
121 
122  int index = flip_direction ? npads-1 : 0;
123  pads[index] = make_pad(page_left, first_left, pad_width, inner_right);
124  double left = pads[index].up;
125 
126  for (int i=1;i<npads-1;++i) {
127  int index = flip_direction ? npads-i-1 : i;
128  pads[index] = make_pad(left, inner_left, pad_width, inner_right);
129  left = pads[index].up;
130  }
131  pads[flip_direction ? 0 : npads-1] = make_pad(left, inner_left, pad_width, last_right);
132  return pads;
133  };
134 
135 
136  noiPadDimSet(vector<double> _lefts, vector<double> _rights ) :
137  rights{_rights}
138  {
139  if (_lefts.size() == 0) nPads = 1;
140  else if (_lefts[0] >= 1.) {
141  nPads = (int) _lefts[0];
142  for (int i{0}; i<(int)_lefts.size()-1; ++i) lefts.push_back(_lefts[i+1]);
143  } else {
144  nPads = 1;
145  lefts = _lefts;
146  }
147  };
148  /* operator vector<noiPadDim> (); */
149 };
150 
151 struct noiPads {
152  // data
153  string prefix="";
154  int i_prefix=1;
155  TCanvas* canvas = nullptr;
156  vector<pair<noiPadDim,noiPadDim>> pad_dimensions;
157  vector<TPad*> pads; // all the generated smaller pads
158  TPad* canvas_pad; // a single big pad the size of the canvas
159  int nRow{1};
160  int nCol{1};
161  int canvas_width { 1200 };
162  int canvas_height { 800 };
163 
164  noiPads ( int nYpads=1, vector<double> dimensions={}, int nXpads=1 ) {
165  // build the noiPadDimSet out of dimensions
166  noiPadDimSet xPads{ {0.2, 0.0001, 0.01}, {0.0001,0.0,0.01 }};
167  noiPadDimSet yPads{ {0.2, 0.0001, 0.01}, {0.0001,0.0,0.01 }};
168 
169  int which = 0;
170  int cnt = 0;
171  canvas_width = -1;
172  canvas_height = -1;
173  for (auto val : dimensions) {
174  if (val > 6) { // set first dimensions
175  if (canvas_width == -1) canvas_width = val;
176  else canvas_height = val;
177  continue;
178  } else if (val > 1) {
179  which = (int) val;
180  cnt = 0;
181  continue;
182  } else if (which == 0) {
183  which = kLeft;
184  }
185  switch (which) {
186  case 6: // kTop
187  yPads.rights[cnt] = val;
188  break;
189  case 5: // kBottom
190  yPads.lefts[cnt] = val;
191  break;
192  case kLeft:
193  xPads.lefts[cnt] = val;
194  break;
195  case kRight:
196  xPads.rights[cnt] = val;
197  break;
198  default:
199  throw std::runtime_error(Form("fatal error: noiPads::noiPads: Error in selection of pad dimensions: was %i but must be (2,3,5,6:kLeft,Right,Bottom,Top)",
200  which));
201  }
202  ++cnt;
203  }
204  yPads.nPads = -nYpads;
205  xPads.nPads = nXpads;
206  if (canvas_width == -1) canvas_width = 1200;
207  if (canvas_height == -1) canvas_height = 800;
208  nCol = TMath::Abs(nXpads);
209  nRow = TMath::Abs(nYpads);
210  for (auto x_pad : xPads.calc_pads())
211  for (auto y_pad : yPads.calc_pads())
212  pad_dimensions.push_back( {y_pad, x_pad} );
213  };
214 
215 
216  noiPads ( vector<pair<noiPadDim, noiPadDim>> _pad_dimensions={{{},{}}}, int _canvas_width=0, int _canvas_height=0) :
217  pad_dimensions{ _pad_dimensions }
218  {
219  if (_canvas_width) canvas_width = _canvas_width;
220  if (_canvas_height) canvas_height = _canvas_height;
221  };
222 
223  void add_pad(pair<noiPadDim,noiPadDim>& coord){
224  canvas->cd();
225 
226  if (pads.size()==0) {
227  canvas_pad = new TPad(noiUniqueName(i_prefix,prefix.c_str()),"",0.,0.,1.,1.);
228  canvas_pad ->SetFillStyle(4000);
229  canvas_pad ->SetFrameFillStyle(4000);
230 
231  canvas_pad->Draw();
232  canvas->cd();
233  }
234 
235  const noiPadDim x { coord.second };
236  const noiPadDim y { coord.first };
237  int i{0};
238  /* while (gDirectory->FindObjectAny(Form("loc_pad_%i",i))) { ++i; } */
239  TPad* p = new TPad(noiUniqueName(),"",x.low,y.low,x.up,y.up);
240 
241  // set the boundaries left(l), right(r), top(t), bottom(b)
242  p->SetLeftMargin(x.low_margin());
243  p->SetRightMargin(x.up_margin());
244  p->SetBottomMargin(y.low_margin());
245  p->SetTopMargin(y.up_margin());
246 
247  p->SetFillStyle(4000);
248  p->SetFrameFillStyle(4000);
249  p->Draw();
250  pads.push_back(p);
251  };
252 
253  void add_pad(vector<pair<noiPadDim,noiPadDim>> input) {
254  for (auto& inp : input) add_pad(inp);
255  };
256 
257  void init() {
258  // make and stylize the TCanvas and pads currently in the list
259  /* const char* t_name = Form("canv_%s",noiUniqueName()); */
260  canvas = new TCanvas(noiUniqueName(i_prefix,Form("canv_%s",prefix.c_str())), "",canvas_width, canvas_height);
261  canvas->SetFillStyle(4000);
262  canvas->SetFrameFillStyle(4000);
263  canvas->Draw();
264  canvas->cd();
265 
266  // add all pads
267  add_pad(pad_dimensions);
268 
269  canvas->cd();
270  };
271 
272  TPad* operator()(int row=0, int col=0) {
273  if (pads.size() == 0) init();
274  if (row < 0) {
275  row = -row;
276  col = row % nCol;
277  row = row / nCol;
278  }
279  int i_pad = row+col*nRow;
280  if (i_pad >= (int)pads.size()) {
281  i_pad = i_pad % (int) pads.size();
282  }
283  pads[i_pad]->cd();
284  return pads[i_pad];
285  };
286 
287  void stamp(string msg, noiDict opt={}, noiDict dict = {{
288  "TextColor", (kGray+2),
289  "TextSize", 16,
290  "x-loc", .05,
291  "y-loc", .05}} )
292  {
293  dict += opt;
294  if (msg.size() > 120) {
295  cout << "pads stamp msg size: " << msg.size() << endl;
296  noiDict dsize {{ "TextSize", 10 }};
297  dict += dsize;
298  }
299  canvas_pad->cd();
300  /* cout << " x: " << dict["x-loc"] << " " << dict["y-loc"] << endl; */
301  noiDrawTLatex(msg.c_str(),dict("x-loc"), dict("y-loc"), dict);
302  };
303  // save the output; check for *cc or *C ending and save as .pdf if required
304 
305  void pdf(string string_with_dollar0, vector<string> other={}) {
306  string name = gSystem->pwd();
307  name += "/";
308  istringstream iss;
309  iss.str(string_with_dollar0);
310  string word;
311  while (iss >> word) {
312  name += noiStripEnds( noiStripStart(word, "./"), {".C",".cc",".cxx",".pdf"});
313  }
314  for (auto& words : other) {
315  iss.clear();
316  iss.str(words);
317  while (iss >> word) {
318  name += noiStripEnds( noiStripStart(word, "./"), {".C",".cc",".cxx",".pdf"});
319  }
320  }
321  name += ".pdf";
322  canvas->Print(name.c_str());
323  };
324 };
325 
326 
327 #endif
328 
329 #endif