GamR  0.0.0
GammaROOT
Loading...
Searching...
No Matches
LevelSchemeDraw.cc
Go to the documentation of this file.
1#include <string>
2#include <algorithm>
3#include <iostream>
4#include <iomanip>
5
6#include <TStyle.h>
7#include <TH2F.h>
8#include <TGaxis.h>
9#include <TCanvas.h>
10#include <TLine.h>
11#include <TText.h>
12#include <TLatex.h>
13#include <TString.h>
14#include <TArrow.h>
15#include <TMinuit.h>
16
17#include "LevelSchemeDraw.hh"
18#include <utils/Utilities.hh>
19
20// ignoring npar, gin, iflag in GlobalChiSquare::doit
21// TMinuit expects these extra variables that we don't use
22#pragma GCC diagnostic ignored "-Wunused-parameter"
23
24namespace GamR {
25 namespace Nucleus {
26 namespace LevelSchemeDraw {
27
28 void State::Paint(Option_t *option) {
29 if (extension) {
30 extline->SetX1(fExtLeft);
31 extline->SetX2(fExtRight);
32 extline->SetY1(fDrawPos);
33 extline->SetY2(fDrawPos);
34 extline->SetLineColor(kGray+1);
35 extline->SetLineStyle(2);
36 extline->SetLineWidth(1);
37 extline->Paint();
38 }
39
40 TAttLine::Modify();
41
42 double x[2];
43 double y[2];
44 x[0] = fLeft;
45 x[1] = fRight;
46 y[0] = fDrawPos;
47 y[1] = fDrawPos;
48 gPad->PaintPolyLine(2, &x[0], &y[0], option);
49
50 int py0 = gPad->YtoPixel(0);
51 fLeftLabel->SetText(fLeft, gPad->AbsPixeltoY((gPad->YtoAbsPixel(fLabelPos))-5), fLeftLab.c_str());
52 fLeftLabel->SetTextFont(42);
53 fLeftLabel->SetTextSize(textsize);
54 fLeftLabel->SetTextColor(GetLineColor());
55 fLeftLabel->Paint();
56
57 fRightLabel->SetText(fRight, gPad->AbsPixeltoY((gPad->YtoAbsPixel(fLabelPos))-5), fRightLab.c_str());
58 fRightLabel->SetTextFont(42);
59 fRightLabel->SetTextAlign(31);
60 fRightLabel->SetTextSize(textsize);
61 fRightLabel->SetTextColor(GetLineColor());
62 fRightLabel->Paint();
63 }
64
65 Int_t State::DistancetoPrimitive(Int_t px, Int_t py) {
66 //distance to main line
67 double dx = 0;
68 if (px > gPad->XtoAbsPixel(fRight)) { dx = px - gPad->XtoAbsPixel(fRight); }
69 else if (px < gPad->XtoAbsPixel(fLeft)) { dx = gPad->XtoAbsPixel(fLeft) - px; }
70 double dy = gPad->YtoAbsPixel(fDrawPos) - py;
71 double main_dist = sqrt(dx*dx + dy*dy);
72
73 return main_dist;
74 }
75
76 void State::ExecuteEvent(Int_t event, Int_t px, Int_t py)
77 {
78 if (!gPad)
79 return;
80 int kMaxDiff = 20;
81
82 if (!gPad->IsEditable())
83 return;
84
85 switch (event) {
86 case kMouseMotion:
87 p1 = false;
88 if (DistancetoPrimitive(px, py) < kMaxDiff) {
89 gPad->SetCursor(kPointer);
90 px1 = gPad->XtoAbsPixel(fLeft);
91 px2 = gPad->XtoAbsPixel(fRight);
92 pxold = px;
93 p1 = true;
94 return;
95 }
96 break;
97 case kButton1Motion:
98 if (p1) {
99 fLeft = gPad->AbsPixeltoX(px)-gPad->AbsPixeltoX(pxold) + gPad->AbsPixeltoX(px1);
100 fRight = gPad->AbsPixeltoX(px)-gPad->AbsPixeltoX(pxold) + gPad->AbsPixeltoX(px2);
101 }
102 gPad->Modified(kTRUE);
103 gPad->Update();
104 break;
105 }
106 }
107
108 double Transition::XtoAbsPixel(double x) {
109 double xscale = (gPad->XtoAbsPixel(gPad->GetUxmax()) - gPad->XtoAbsPixel(gPad->GetUxmin()) + 1.0)/
110 (gPad->GetUxmax() - gPad->GetUxmin());
111 return gPad->XtoAbsPixel(gPad->GetUxmin())-0.5 + xscale * x;
112 }
113
114 double Transition::YtoAbsPixel(double y) {
115 double yscale = (gPad->YtoAbsPixel(gPad->GetUymax()) - gPad->YtoAbsPixel(gPad->GetUymin()) + 1.0)/
116 (gPad->GetUymax() - gPad->GetUymin());
117 return gPad->YtoAbsPixel(gPad->GetUymin())+0.5 + yscale * y;
118 }
119
120 double Transition::AbsPixeltoX(double xpix) {
121 double xscale = (gPad->XtoAbsPixel(gPad->GetUxmax()) - gPad->XtoAbsPixel(gPad->GetUxmin()) + 1.0)/
122 (gPad->GetUxmax() - gPad->GetUxmin());
123 return (xpix - gPad->XtoAbsPixel(gPad->GetUxmin())-0.5)/xscale;
124 }
125
126 double Transition::AbsPixeltoY(double ypix) {
127 double yscale = (gPad->YtoAbsPixel(gPad->GetUymax()) - gPad->YtoAbsPixel(gPad->GetUymin()) + 1.0)/
128 (gPad->GetUymax() - gPad->GetUymin());
129 return (ypix - gPad->YtoAbsPixel(gPad->GetUymin())+0.5)/yscale;
130 }
131
133 double xscale = (gPad->XtoAbsPixel(gPad->GetUxmax()) - gPad->XtoAbsPixel(gPad->GetUxmin()) + 1.0)/
134 (gPad->GetUxmax() - gPad->GetUxmin());
135 double yscale = (gPad->YtoAbsPixel(gPad->GetUymax()) - gPad->YtoAbsPixel(gPad->GetUymin()) + 1.0)/
136 (gPad->GetUymax() - gPad->GetUymin());
137 double pixdx = xscale * (GetX2() - GetX1());
138 double pixdy = yscale * (GetY2() - GetY1());
139
140 /*
141 double pixx1 = gPad->XtoAbsPixel(GetX1());
142 double pixx2 = gPad->XtoAbsPixel(GetX2());
143 double pixy1 = gPad->YtoAbsPixel(GetY1());
144 double pixy2 = gPad->YtoAbsPixel(GetY2());
145 */
146
147 //double pixdx = pixx2 - pixx1; //gPad->XtoAbsPixel(dx);
148 //double pixdy = pixy2 - pixy1; //gPad->YtoAbsPixel(dy);
149
150
151 double pixlen = std::sqrt(pixdx*pixdx + pixdy*pixdy);
152 return pixlen;
153 }
154
156 /*
157 double pixx1 = gPad->XtoAbsPixel(GetX1());
158 double pixx2 = gPad->XtoAbsPixel(GetX2());
159 double pixy1 = gPad->YtoAbsPixel(GetY1());
160 double pixy2 = gPad->YtoAbsPixel(GetY2());
161
162 double pixdx = pixx2 - pixx1; //gPad->XtoAbsPixel(dx);
163 double pixdy = pixy2 - pixy1; //gPad->YtoAbsPixel(dy);
164 */
165
166 double xscale = (gPad->XtoAbsPixel(gPad->GetUxmax()) - gPad->XtoAbsPixel(gPad->GetUxmin()) + 1.0)/
167 (gPad->GetUxmax() - gPad->GetUxmin());
168 double yscale = (gPad->YtoAbsPixel(gPad->GetUymax()) - gPad->YtoAbsPixel(gPad->GetUymin()) + 1.0)/
169 (gPad->GetUymax() - gPad->GetUymin());
170 double pixdx = xscale * (GetX2() - GetX1());
171 double pixdy = yscale * (GetY2() - GetY1());
172
173 double pixlen = std::sqrt(pixdx*pixdx + pixdy*pixdy);
174 pixdx /= pixlen;
175 pixdy /= pixlen;
176
177 double perpthet = std::atan2(pixdx,-pixdy);
178 return perpthet;
179 }
180
182 double perpthet = GetPerpTheta();
183
184 return std::max(std::sqrt(std::pow((gPad->YtoAbsPixel(std::sin(perpthet))-gPad->YtoAbsPixel(0.0))*fWidth, 2)
185 + std::pow((gPad->XtoAbsPixel(std::cos(perpthet)) - gPad->XtoAbsPixel(0.0))*fWidth, 2))*fScheme->fWidthScale, 3.0);
186 }
187
189 double perpthet = GetPerpTheta();
190 double pixwidth = GetWidth();
191 return std::cos(perpthet)*pixwidth;
192 }
193
195 double perpthet = GetPerpTheta();
196 double pixwidth = GetWidth();
197 return std::sin(perpthet)*pixwidth;
198 }
199
200 double Transition::GetHeadWidth() { return std::max(1.7*GetWidth(), 8.0); }
201
203 double perpthet = GetPerpTheta();
204 double pixwidth = GetHeadWidth();
205 return std::cos(perpthet)*pixwidth;
206 }
207
209 double perpthet = GetPerpTheta();
210 double pixwidth = GetHeadWidth();
211 return std::sin(perpthet)*pixwidth;
212 }
213
214 double Transition::GetHeadLength() { return std::min(0.66*GetHeadWidth(), 0.5*GetLength()); }
215
216 double Transition::GetX1() { return fInitial->fLeft + (fInitial->fRight - fInitial->fLeft) * fStart; }
217
218 double Transition::GetX2() { return fFinal->fLeft + (fFinal->fRight - fFinal->fLeft) * fStop; }
219
220 double Transition::GetY1() { return fInitial->fDrawPos; }
221
222 double Transition::GetY2() { return fFinal->fDrawPos; }
223
224 void Transition::PaintArrow() { //here some maths happens to draw a nice arrow
225 //first work out start and end points in world coordinates
226 double x1 = fInitial->fLeft + (fInitial->fRight - fInitial->fLeft) * fStart;
227 double x2 = fFinal->fLeft + (fFinal->fRight - fFinal->fLeft) * fStop;
228
229 double y1 = fInitial->fDrawPos;
230 double y2 = fFinal->fDrawPos;
231
232 double dx = x2 - x1;
233 double dy = y2 - y1;
234
235 double length = std::sqrt(dx*dx + dy*dy);
236 dx /= length;
237 dy /= length;
238
239 double pixx1 = XtoAbsPixel(x1);
240 double pixx2 = XtoAbsPixel(x2);
241 double pixy1 = YtoAbsPixel(y1);
242 double pixy2 = YtoAbsPixel(y2);
243
244 //pixy1 = gPad->GetWh() - pixy1;
245 //pixy2 = gPad->GetWh() - pixy2;
246
247 double pixdx = pixx2 - pixx1; //gPad->XtoAbsPixel(dx);
248 double pixdy = pixy2 - pixy1; //gPad->YtoAbsPixel(dy);
249
250
251 double pixlen = std::sqrt(pixdx*pixdx + pixdy*pixdy);
252 pixdx /= pixlen;
253 pixdy /= pixlen;
254
255 double perpthet = std::atan2(pixdx,-pixdy);
256 double topwidth = GetWidth()/2.0/std::cos(perpthet);
257
258 //SetPoint(0, gPad->AbsPixeltoX(pixx1 - topwidth), gPad->AbsPixeltoY(pixy1));
259 //SetPoint(1, gPad->AbsPixeltoX(pixx1 + topwidth), gPad->AbsPixeltoY(pixy1));
260 SetPoint(0, AbsPixeltoX(pixx1 - topwidth), AbsPixeltoY(pixy1));
261 SetPoint(1, AbsPixeltoX(pixx1 + topwidth), AbsPixeltoY(pixy1));
262
263 double headposx = x1 + dx*(length);//-GetHeadLength());
264 double headposy = y1 + dy*(length);//-GetHeadLength());
265
266 double pixheadposx = XtoAbsPixel(headposx) - pixdx*GetHeadLength();
267 double pixheadposy = YtoAbsPixel(headposy) - pixdy*GetHeadLength();
268
269 SetPoint(2, AbsPixeltoX(pixheadposx + GetWidthX()/2.0),
270 AbsPixeltoY(pixheadposy + GetWidthY()/2.0));
271 SetPoint(3, AbsPixeltoX(pixheadposx + GetHeadWidthX()/2.0),
272 AbsPixeltoY(pixheadposy + GetHeadWidthY()/2.0));
273 SetPoint(4, x2, y2);
274 SetPoint(5, AbsPixeltoX(pixheadposx - GetHeadWidthX()/2.0),
275 AbsPixeltoY(pixheadposy - GetHeadWidthY()/2.0));
276 SetPoint(6, AbsPixeltoX(pixheadposx - GetWidthX()/2.0),
277 AbsPixeltoY(pixheadposy - GetWidthY()/2.0));
278
279 PaintPolyLine(7, GetX(), GetY(), "F");
280 }
281
282 void Transition::Paint(Option_t *option) {
283 TAttLine::Modify();
284 TAttFill::Modify();
285
286 PaintArrow();
287
288 //paint transition label
289
290 TString transition_string;
291 transition_string.Form("%3.2g", fWidth);
292 double label_x = GetX1() + fLabelPos*(GetX2()-GetX1());
293 double label_y = GetY1() + fLabelPos*(GetY2()-GetY1());
294 fLabel->SetText(label_x, label_y, transition_string.Data());
295 fLabel->SetTextFont(42);
296 //fLabel->SetTextAngle(45);
297 fLabel->SetTextSize(textsize);
298 fLabel->SetTextAlign(22);
299 fLabel->SetTextColor(kBlack);
300 UInt_t w, h;
301 fLabel->GetBoundingBox(w,h);
302 fLabelBox->SetX1(gPad->PixeltoX(gPad->XtoPixel(label_x) - w/2 - 5));
303 fLabelBox->SetX2(gPad->PixeltoX(gPad->XtoPixel(label_x) + w/2 + 5));
304 fLabelBox->SetY1(gPad->AbsPixeltoY(gPad->YtoAbsPixel(label_y) + h/2 + 5));
305 fLabelBox->SetY2(gPad->AbsPixeltoY(gPad->YtoAbsPixel(label_y) - h/2 - 5));
306
307 fLabelBox->SetFillColorAlpha(kWhite, 0.7);
308 fLabelBox->Paint();
309
310 fLabel->Paint();
311
312 }
313
315 //some maths to work out the closest distance to the transition
316
317 double midx = (GetX1() + GetX2())/2.0;
318 double midy = (GetY1() + GetY2())/2.0;
319 double dx = gPad->XtoAbsPixel(midx) - px;
320 double dy = gPad->YtoAbsPixel(midy) - py;
321 double main_dist = sqrt(dx*dx + dy*dy);
322
323 double tpx = gPad->XtoAbsPixel(GetX1());
324 double bpx = gPad->XtoAbsPixel(GetX2());
325 double tpy = gPad->YtoAbsPixel(GetY1());
326 double bpy = gPad->YtoAbsPixel(GetY2());
327
328 double d1 = abs(tpx-px) + abs(tpy-py);
329 double d2 = abs(bpx-px) + abs(bpy-py);
330
331 return std::min(main_dist, std::min(d1, d2));
332 }
333
334 void Transition::ExecuteEvent(Int_t event, Int_t px, Int_t py)
335 {
336 if (!gPad)
337 return;
338 int kMaxDiff = 20;
339
340 if (!gPad->IsEditable())
341 return;
342
343 switch (event) {
344 case kMouseMotion:
345 {
346
347 if (DistancetoPrimitive(px, py) < kMaxDiff) {
348 gPad->SetCursor(kPointer);
349 //return;
350 }
351
352 p1 = false;
353 p2 = false;
354 px1 = gPad->XtoAbsPixel(GetX1());
355 px2 = gPad->XtoAbsPixel(GetX2());
356 py1 = gPad->YtoAbsPixel(GetY1());
357 py2 = gPad->YtoAbsPixel(GetY2());
358
359 double d1 = abs(px1-px) + abs(py1-py);
360 if (d1 < kMaxDiff) {
361 px1old = px1;
362 p1 = true;
363 gPad->SetCursor(kPointer);
364 return;
365 }
366
367 double d2 = abs(px2-px) + abs(py2-py);
368 if (d2 < kMaxDiff) {
369 px2old = px2;
370 p2 = true;
371 gPad->SetCursor(kPointer);
372 return;
373 }
374 break;
375 }
376 case kButton1Motion:
377 {
378 if (p1) {
379 double abspos = (gPad->AbsPixeltoX(px)-gPad->AbsPixeltoX(px1old) + gPad->AbsPixeltoX(px1));
380 double relpos = (abspos - fInitial->fLeft)/(fInitial->fRight - fInitial->fLeft);
381 fStart = relpos;
382 }
383 if (p2) {
384 double abspos = (gPad->AbsPixeltoX(px)-gPad->AbsPixeltoX(px2old) + gPad->AbsPixeltoX(px2));
385 double relpos = (abspos - fFinal->fLeft)/(fFinal->fRight - fFinal->fLeft);
386 fStop = relpos;
387 }
388 gPad->Modified(kTRUE);
389 gPad->Update();
390 break;
391 }
392 }
393 }
394
395 void Scheme::Paint(Option_t *option) {
396
397 //gPad->SetFrameLineColor(0);
398
399 //
400 gStyle->SetOptStat(0);
401 if (!gPad->GetListOfPrimitives()->Contains(fDrawHist)) {
402 fDrawHist->AppendPad();
403 }
404
405 /*
406 if (!fAxis) {
407 fAxis = new TGaxis(0, 0, drawLow, drawHigh , drawLow, drawHigh, 510, "");
408 fAxis->AppendPad();
409
410 }
411 */
412
413
414 for (auto &state : fStates) {
415 if (!gPad->GetListOfPrimitives()->Contains(&state.second)) {
416 state.second.AppendPad();
417 }
418 }
419
420 for (auto &transition : fTransitions) {
421 if (!gPad->GetListOfPrimitives()->Contains(&transition)) {
422 transition.AppendPad();
423 }
424 }
425 }
426
427
428 void Scheme::ReadScheme(std::string filename) {
429 std::ifstream infile(filename);
430
431 std::string line;
432 while (std::getline(infile, line)) {
433 if (line.size() == 0) { continue; }
434 if (line[0] == '#') { continue; }
435 if (line[0] == ';') { continue; }
436
437 std::stringstream ss(line);
438
439 std::string label;
440 ss >> label;
441
442 if (label == "L") {
443 //level
444 std::string name;
445 double energy;
446 double left;
447 double right;
448 std::string leftlab;
449 std::string rightlab;
450
451 ss >> name >> energy >> left >> right >> leftlab >> rightlab;
452
453 AddState(name, energy, left, right, leftlab, rightlab);
454
455 }
456 else if (label == "E") {
457 double extleft, extright;
458 std::string name;
459 if (ss >> name >> extleft >> extright) {
460 fStates[name].SetExtension(extleft, extright);
461 }
462 }
463 else if (label == "T") {
464 std::string name_init;
465 std::string name_fin;
466 double width;
467 double start;
468 double stop;
469 UInt_t color;
470 double labelpos;
471
472 ss >> name_init >> name_fin >> width >> start >> stop >> labelpos >> color;
473
474 EColor col = static_cast<EColor>(color);
475
476 AddTransition(name_init, name_fin, width, start, stop, labelpos, col);
477 }
478 }
479 }
480
481 void Scheme::WriteScheme(std::string filename) {
482 std::ofstream outfile(filename);
483 for (auto &state : fStates) {
484 outfile << std::setw(5) << std::left << "L"
485 << std::setw(10) << std::left << state.second.GetName()
486 << std::setw(10) << std::left << state.second.fEnergy
487 << std::setw(10) << std::left << std::setprecision(5) << state.second.fLeft
488 << std::setw(10) << std::left << std::setprecision(5) << state.second.fRight
489 << std::setw(10) << std::left << state.second.fLeftLab
490 << std::setw(10) << std::left << state.second.fRightLab;
491 outfile << std::endl;
492 }
493 for (auto &state : fStates) {
494 if (state.second.extension) {
495 outfile << std::setw(5) << std::left << "E"
496 << std::setw(10) << std::left << state.second.GetName()
497 << std::setw(10) << std::left << std::setprecision(5) << state.second.fExtLeft
498 << std::setw(10) << std::left << std::setprecision(5) << state.second.fExtRight << std::endl;
499 }
500 }
501
502 for (auto &transition : fTransitions) {
503 outfile << std::setw(5) << std::left << "T"
504 << std::setw(10) << std::left << transition.fInitial->GetName()
505 << std::setw(10) << std::left << transition.fFinal->GetName()
506 << std::setw(10) << std::left << transition.fWidth
507 << std::setw(10) << std::left << std::setprecision(5) << transition.fStart
508 << std::setw(10) << std::left << std::setprecision(5) << transition.fStop
509 << std::setw(10) << std::left << std::setprecision(5) << transition.fLabelPos
510 << std::setw(10) << std::left << transition.GetFillColor() << std::endl;
511
512 }
513 }
514
515 void State::AddTransition(const char *name_fin, double width, double start, double stop, double labelpos, EColor color) {
516 std::string nf(name_fin);
517 fScheme->AddTransition(GetName(), nf, width, start, stop, labelpos, color);
518 }
519 }
520 }
521}
void ss(std::vector< int > indexes, TCanvas *canvas, Option_t *option)
void py(TVirtualPad *canvas)
void px(TVirtualPad *canvas)
std::map< std::string, State > fStates
void AddState(std::string name, double energy, double left, double right, std::string leftlab, std::string rightlab, EColor color=kBlack)
void ReadScheme(std::string filename)
void AddTransition(std::string initState, std::string finState, double width, double start, double stop, double labelpos=0.5, EColor color=kBlack)
void WriteScheme(std::string filename)
void AddTransition(const char *name_fin, double width, double start, double stop, double labelpos=0.5, EColor color=kBlack)
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Int_t DistancetoPrimitive(Int_t px, Int_t py)
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Definition Gain.cc:19