File indexing completed on 2025-08-06 08:14:12
0001 #ifndef tuClass__h
0002
0003 #ifndef noiPads__h
0004 #define noiPads__h
0005
0006 #include "noiDict.h"
0007 #include "noi_fnc.h"
0008 const int kLeft = 2;
0009 const int kRight = 3;
0010
0011
0012
0013 struct noiPadDim {
0014
0015
0016
0017
0018
0019
0020
0021
0022 double low;
0023 double p_low;
0024 double p_up;
0025 double up;
0026
0027 void check_input() {
0028 if ( low < 0. || low > 1.
0029 || p_low < 0. || p_low > 1.
0030 || p_up < 0. || p_up > 1.
0031 || up < 0. || up > 1. ) {
0032 cout << " Fatal error: input coordinates for tuPadDim for pads must all "
0033 " be in range [0,1] " << endl;
0034 print();
0035 exit (2);
0036 } else if ( low > p_low || p_low > p_up || p_up > up ) {
0037 cout << " Fatal error: input coordinates must monotonically increase " << endl;
0038 print();
0039 exit(2);
0040 }
0041 };
0042 noiPadDim( double _low, double _p_low, double _p_up, double _up ) :
0043 low{_low}, p_low{_p_low}, p_up{_p_up}, up{_up} { check_input(); };
0044 noiPadDim( double _low, double _up ) :
0045 low{_low}, p_low{_low}, p_up{_up}, up{_up} { check_input(); };
0046 noiPadDim( double _low, double _p_low, double _up ) :
0047 low{_low}, p_low{_p_low}, p_up{_up}, up{_up} { check_input(); };
0048 noiPadDim( ) :
0049 low{0.}, p_low{0.}, p_up{1.}, up{1.} { check_input(); };
0050
0051 void print() const {
0052 cout << Form(" Four points are: (%.2f, %.2f %.2f, %.2f)",low,p_low,p_up,up) << endl;
0053 };
0054 double low_margin () const {
0055 double margin { (p_low - low) / (up - low) };
0056 if (margin < 0) margin = 0;
0057 return margin;
0058 };
0059 double up_margin () const {
0060
0061 double margin { (up - p_up) / (up - low) };
0062 if (margin < 0) margin = 0;
0063 return margin;
0064 };
0065 bool operator==(noiPadDim& B) const {
0066 return low == B.low
0067 && p_low == B.p_low
0068 && p_up == B.p_up
0069 && up == B.up;
0070 };
0071 };
0072 struct noiPadDimSet {
0073
0074
0075
0076 vector<double> lefts;
0077 vector<double> rights;
0078 int nPads;
0079
0080 static noiPadDim make_pad(double left,
0081 double left_margin, double pad_width,
0082 double right_margin)
0083 {
0084 return noiPadDim{ left,
0085 left+left_margin,
0086 left+left_margin+pad_width,
0087 left+left_margin+pad_width+right_margin };
0088 };
0089
0090 vector<noiPadDim> calc_pads() {
0091 int npads = nPads;
0092 bool flip_direction = false;
0093 if (npads < 0) {
0094 npads = -npads;
0095 flip_direction=true;
0096 };
0097 vector<noiPadDim> pads (npads) ;
0098
0099 double first_left = (lefts.size() > 0) ? lefts[0] : 0.2;
0100 double inner_left = (lefts.size() > 1) ? lefts[1] : 0.0001;
0101 double page_left = (lefts.size() > 2) ? lefts[2] : 0.01;
0102
0103 double last_right = (rights.size() > 0) ? rights[0] : 0.0001;
0104 double inner_right = (rights.size() > 1) ? rights[1] : 0.0;
0105 double page_right = (rights.size() > 2) ? rights[2] : 0.01;
0106
0107 if (npads == 0) throw std::runtime_error(
0108 "fatal in noiPadDimSet must request at least one pad");
0109 if (npads == 1) {
0110 double pad_width = 1.-first_left-page_left-last_right-page_right;
0111 if (pad_width<=0) throw std::runtime_error(
0112 "fatal in noiPadDimSet margins have consumed more than 100\% of TCanvas");
0113 pads[0] = make_pad( page_left, first_left, pad_width, last_right );
0114 return pads;
0115 }
0116
0117 double pad_width { (1.-(first_left+page_left+last_right+page_right+
0118 (inner_left+inner_right)*(npads-1)))/npads };
0119 if (pad_width<=0) throw std::runtime_error(
0120 "fatal in noiPadDimSet margins have consumed more than 100\% of TCanvas");
0121
0122 int index = flip_direction ? npads-1 : 0;
0123 pads[index] = make_pad(page_left, first_left, pad_width, inner_right);
0124 double left = pads[index].up;
0125
0126 for (int i=1;i<npads-1;++i) {
0127 int index = flip_direction ? npads-i-1 : i;
0128 pads[index] = make_pad(left, inner_left, pad_width, inner_right);
0129 left = pads[index].up;
0130 }
0131 pads[flip_direction ? 0 : npads-1] = make_pad(left, inner_left, pad_width, last_right);
0132 return pads;
0133 };
0134
0135
0136 noiPadDimSet(vector<double> _lefts, vector<double> _rights ) :
0137 rights{_rights}
0138 {
0139 if (_lefts.size() == 0) nPads = 1;
0140 else if (_lefts[0] >= 1.) {
0141 nPads = (int) _lefts[0];
0142 for (int i{0}; i<(int)_lefts.size()-1; ++i) lefts.push_back(_lefts[i+1]);
0143 } else {
0144 nPads = 1;
0145 lefts = _lefts;
0146 }
0147 };
0148
0149 };
0150
0151 struct noiPads {
0152
0153 string prefix="";
0154 int i_prefix=1;
0155 TCanvas* canvas = nullptr;
0156 vector<pair<noiPadDim,noiPadDim>> pad_dimensions;
0157 vector<TPad*> pads;
0158 TPad* canvas_pad;
0159 int nRow{1};
0160 int nCol{1};
0161 int canvas_width { 1200 };
0162 int canvas_height { 800 };
0163
0164 noiPads ( int nYpads=1, vector<double> dimensions={}, int nXpads=1 ) {
0165
0166 noiPadDimSet xPads{ {0.2, 0.0001, 0.01}, {0.0001,0.0,0.01 }};
0167 noiPadDimSet yPads{ {0.2, 0.0001, 0.01}, {0.0001,0.0,0.01 }};
0168
0169 int which = 0;
0170 int cnt = 0;
0171 canvas_width = -1;
0172 canvas_height = -1;
0173 for (auto val : dimensions) {
0174 if (val > 6) {
0175 if (canvas_width == -1) canvas_width = val;
0176 else canvas_height = val;
0177 continue;
0178 } else if (val > 1) {
0179 which = (int) val;
0180 cnt = 0;
0181 continue;
0182 } else if (which == 0) {
0183 which = kLeft;
0184 }
0185 switch (which) {
0186 case 6:
0187 yPads.rights[cnt] = val;
0188 break;
0189 case 5:
0190 yPads.lefts[cnt] = val;
0191 break;
0192 case kLeft:
0193 xPads.lefts[cnt] = val;
0194 break;
0195 case kRight:
0196 xPads.rights[cnt] = val;
0197 break;
0198 default:
0199 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)",
0200 which));
0201 }
0202 ++cnt;
0203 }
0204 yPads.nPads = -nYpads;
0205 xPads.nPads = nXpads;
0206 if (canvas_width == -1) canvas_width = 1200;
0207 if (canvas_height == -1) canvas_height = 800;
0208 nCol = TMath::Abs(nXpads);
0209 nRow = TMath::Abs(nYpads);
0210 for (auto x_pad : xPads.calc_pads())
0211 for (auto y_pad : yPads.calc_pads())
0212 pad_dimensions.push_back( {y_pad, x_pad} );
0213 };
0214
0215
0216 noiPads ( vector<pair<noiPadDim, noiPadDim>> _pad_dimensions={{{},{}}}, int _canvas_width=0, int _canvas_height=0) :
0217 pad_dimensions{ _pad_dimensions }
0218 {
0219 if (_canvas_width) canvas_width = _canvas_width;
0220 if (_canvas_height) canvas_height = _canvas_height;
0221 };
0222
0223 void add_pad(pair<noiPadDim,noiPadDim>& coord){
0224 canvas->cd();
0225
0226 if (pads.size()==0) {
0227 canvas_pad = new TPad(noiUniqueName(i_prefix,prefix.c_str()),"",0.,0.,1.,1.);
0228 canvas_pad ->SetFillStyle(4000);
0229 canvas_pad ->SetFrameFillStyle(4000);
0230
0231 canvas_pad->Draw();
0232 canvas->cd();
0233 }
0234
0235 const noiPadDim x { coord.second };
0236 const noiPadDim y { coord.first };
0237 int i{0};
0238
0239 TPad* p = new TPad(noiUniqueName(),"",x.low,y.low,x.up,y.up);
0240
0241
0242 p->SetLeftMargin(x.low_margin());
0243 p->SetRightMargin(x.up_margin());
0244 p->SetBottomMargin(y.low_margin());
0245 p->SetTopMargin(y.up_margin());
0246
0247 p->SetFillStyle(4000);
0248 p->SetFrameFillStyle(4000);
0249 p->Draw();
0250 pads.push_back(p);
0251 };
0252
0253 void add_pad(vector<pair<noiPadDim,noiPadDim>> input) {
0254 for (auto& inp : input) add_pad(inp);
0255 };
0256
0257 void init() {
0258
0259
0260 canvas = new TCanvas(noiUniqueName(i_prefix,Form("canv_%s",prefix.c_str())), "",canvas_width, canvas_height);
0261 canvas->SetFillStyle(4000);
0262 canvas->SetFrameFillStyle(4000);
0263 canvas->Draw();
0264 canvas->cd();
0265
0266
0267 add_pad(pad_dimensions);
0268
0269 canvas->cd();
0270 };
0271
0272 TPad* operator()(int row=0, int col=0) {
0273 if (pads.size() == 0) init();
0274 if (row < 0) {
0275 row = -row;
0276 col = row % nCol;
0277 row = row / nCol;
0278 }
0279 int i_pad = row+col*nRow;
0280 if (i_pad >= (int)pads.size()) {
0281 i_pad = i_pad % (int) pads.size();
0282 }
0283 pads[i_pad]->cd();
0284 return pads[i_pad];
0285 };
0286
0287 void stamp(string msg, noiDict opt={}, noiDict dict = {{
0288 "TextColor", (kGray+2),
0289 "TextSize", 16,
0290 "x-loc", .05,
0291 "y-loc", .05}} )
0292 {
0293 dict += opt;
0294 if (msg.size() > 120) {
0295 cout << "pads stamp msg size: " << msg.size() << endl;
0296 noiDict dsize {{ "TextSize", 10 }};
0297 dict += dsize;
0298 }
0299 canvas_pad->cd();
0300
0301 noiDrawTLatex(msg.c_str(),dict("x-loc"), dict("y-loc"), dict);
0302 };
0303
0304
0305 void pdf(string string_with_dollar0, vector<string> other={}) {
0306 string name = gSystem->pwd();
0307 name += "/";
0308 istringstream iss;
0309 iss.str(string_with_dollar0);
0310 string word;
0311 while (iss >> word) {
0312 name += noiStripEnds( noiStripStart(word, "./"), {".C",".cc",".cxx",".pdf"});
0313 }
0314 for (auto& words : other) {
0315 iss.clear();
0316 iss.str(words);
0317 while (iss >> word) {
0318 name += noiStripEnds( noiStripStart(word, "./"), {".C",".cc",".cxx",".pdf"});
0319 }
0320 }
0321 name += ".pdf";
0322 canvas->Print(name.c_str());
0323 };
0324 };
0325
0326
0327 #endif
0328
0329 #endif