6#include "tkn_root_macros.h"
12#include <TGraphAsymmErrors.h>
18#include <TPaletteAxis.h>
32enum class EvenEven { No, Yes };
38 static constexpr int Nm[7] = {2 , 8 , 20 , 28 , 50 , 82 , 126 };
39 static constexpr double NmMin[7]= {0. , 1. , 12., 18., 46., 93. , 98. };
40 static constexpr double NmMax[7]= {10., 22., 40., 52., 90., 140., 126.*3};
41 static constexpr double ZmMin[7]= {0.2, 0.2, 6. , 10., 26., 44. , 74.};
42 static constexpr double ZmMax[7]= {9. , 17., 30., 35., 53., 74. , 95.};
49TH2D* MakeHist(
const char* name,
int NMax,
int ZMax, EvenEven mode) {
50 if (mode == EvenEven::Yes) {
52 return new TH2D(name,
";N;Z",
53 (NMax+2)/2, -1, NMax+1,
54 (ZMax+2)/2, -1, ZMax+1);
57 return new TH2D(name,
";N;Z",
58 NMax+1, -0.5, NMax+0.5,
59 ZMax+1, -0.5, ZMax+0.5);
64void HideEmptyBins(TH2* h,
double sentinel=-1e8) {
65 for (
int ix=1; ix<=h->GetNbinsX(); ++ix)
66 for (
int iy=1; iy<=h->GetNbinsY(); ++iy)
67 if (h->GetBinContent(ix,iy)==0.0) h->SetBinContent(ix,iy, sentinel);
71void ApplyCleanStyle(TH2* h,
const ChartWindow& w,
double zmin,
double zmax) {
72 gStyle->SetOptStat(0);
73 gStyle->SetNumberContours(255);
74 gStyle->SetPalette(kRainBow);
79 h->GetXaxis()->SetRangeUser(w.
xmin, w.
xmax);
80 h->GetYaxis()->SetRangeUser(w.
ymin, w.
ymax);
83 h->GetXaxis()->SetLabelSize(0);
84 h->GetXaxis()->SetTitleSize(0);
85 h->GetXaxis()->SetTickLength(0);
86 h->GetXaxis()->SetAxisColor(0);
87 h->GetYaxis()->SetLabelSize(0);
88 h->GetYaxis()->SetTitleSize(0);
89 h->GetYaxis()->SetTickLength(0);
90 h->GetYaxis()->SetAxisColor(0);
91 gPad->SetFrameLineColor(0);
98void PlacePalette(TH2* h,
double x1=0.92,
double x2=0.96,
double y1=0.12,
double y2=0.90)
104 auto mask =
new TBox(gPad->GetUxmax(), gPad->GetY1(), gPad->GetX2(), gPad->GetY2());
105 mask->SetFillColor(kWhite); mask->SetLineColor(kWhite); mask->Draw(
"same");
108 mask =
new TBox(gPad->GetX1(), gPad->GetY1(), gPad->GetX2(), gPad->GetUymin());
109 mask->SetFillColor(kWhite); mask->SetLineColor(kWhite); mask->Draw(
"same");
112 mask =
new TBox(gPad->GetX1(), gPad->GetY1(), gPad->GetUxmin(), gPad->GetY2());
113 mask->SetFillColor(kWhite); mask->SetLineColor(kWhite); mask->Draw(
"same");
116 mask =
new TBox(gPad->GetX1(), gPad->GetUymax(), gPad->GetX2(), gPad->GetY2());
117 mask->SetFillColor(kWhite); mask->SetLineColor(kWhite); mask->Draw(
"same");
120 if (
auto pal=(TPaletteAxis*)h->GetListOfFunctions()->FindObject(
"palette")) {
121 pal->SetX1NDC(x1); pal->SetX2NDC(x2);
122 pal->SetY1NDC(y1); pal->SetY2NDC(y2);
123 pal->SetLineColor(0);
124 pal->SetLabelSize(0.035);
125 pal->SetTitleSize(0.040);
126 pal->SetTickLength(0.02);
129 gPad->Modified(); gPad->Update();
136void DrawMagicGridAndLabels(EvenEven mode,
137 int lineColor=kGray+2,
int lineStyle=1,
float lineWidth=2.f,
138 int textColor=kGray+3,
double textSize=0.035)
141 gPad->Modified(); gPad->Update();
143 const double nxmin = gPad->GetUxmin();
144 const double nxmax = gPad->GetUxmax();
145 const double nymin = gPad->GetUymin();
146 const double nymax = gPad->GetUymax();
148 const double offset = (mode==EvenEven::Yes ? 1.0 : 0.5);
149 const double dx = (mode==EvenEven::Yes ? 0.045 : 0.03) * (nxmax - nxmin);
150 const double dy = (mode==EvenEven::Yes ? 0.045 : 0.03) * (nymax - nymin);
152 TLatex lab; lab.SetTextFont(42); lab.SetTextColor(textColor); lab.SetTextSize(textSize);
155 for (
int i=0; i<7; ++i) {
160 if (N >= nxmin + offset && N <= nxmax - offset && z1 < nymax) {
161 for (
double s : {-offset, +offset}) {
162 auto L =
new TLine(N + s, z1, N + s, z2);
163 L->SetLineColor(lineColor); L->SetLineStyle(lineStyle); L->SetLineWidth(lineWidth);
166 lab.SetTextAlign(22);
167 lab.DrawLatex(N, z1 - dy, Form(
"%d", N));
172 for (
int i=0; i<7; ++i) {
177 if (Z >= nymin + offset && Z <= nymax - offset && n1 < nxmax) {
178 for (
double s : {-offset, +offset}) {
179 auto L =
new TLine(n1, Z + s, n2, Z + s);
180 L->SetLineColor(lineColor); L->SetLineStyle(lineStyle); L->SetLineWidth(lineWidth);
183 lab.SetTextAlign(22);
184 lab.DrawLatex(n1 - dx, Z, Form(
"%d", Z));
190void DrawAxisHints() {
191 TArrow arrow; arrow.SetLineColorAlpha(kGray+2, 0.9); arrow.SetLineWidth(2);
193 auto arr = arrow.DrawArrow(0.55, 0.045, 0.65, 0.045, 0.012,
"|>"); arr->SetNDC();
194 TLatex tx; tx.SetTextFont(42); tx.SetTextSize(0.04); tx.SetTextColor(kGray+2); tx.SetTextAlign(22);
195 tx.DrawLatexNDC(0.67, 0.05,
"N");
197 arr = arrow.DrawArrow(0.022, 0.5, 0.022, 0.65, 0.012,
"|>"); arr->SetNDC();
198 TLatex tz; tz.SetTextFont(42); tz.SetTextSize(0.04); tz.SetTextColor(kGray+2); tz.SetTextAlign(22);
200 tz.DrawLatexNDC(0.02, 0.67,
"Z");
205void DrawTitleTopLeft(
const char* txt) {
206 const double xL=gPad->GetLeftMargin(), yT=1.0-gPad->GetTopMargin();
207 TLatex t; t.SetNDC(
true); t.SetTextFont(42); t.SetTextColor(kGray+3); t.SetTextSize(0.045); t.SetTextAlign(13);
208 t.DrawLatex(xL+0.010, yT-0.010, txt);
218static void DrawSmoothBandX(
const std::vector<double>& x,
219 const std::vector<double>& y,
220 const std::vector<double>& ex,
221 Color_t fillColor,
float alpha = 0.25,
222 Color_t lineColor = kBlack,
int lineWidth = 2,
223 bool smooth =
true,
int nsamples = -1)
225 const int n = (int)x.size();
229 std::vector<int> idx(n); std::iota(idx.begin(), idx.end(), 0);
230 std::sort(idx.begin(), idx.end(), [&](
int a,
int b){ return y[a] < y[b]; });
232 std::vector<double> yS(n), xHi(n), xLo(n);
233 for (
int i=0;i<n;++i) {
234 const int k = idx[i];
236 xHi[i] = x[k] + ex[k];
237 xLo[i] = x[k] - ex[k];
240 std::vector<double> xp, yp;
249 auto build_stairs = [](
const std::vector<double>& yv,
250 const std::vector<double>& xv,
251 std::vector<double>& outX,
252 std::vector<double>& outY)
254 const int m = (int)xv.size();
255 outX.clear(); outY.clear();
256 outX.reserve(2*m); outY.reserve(2*m);
257 outX.push_back(xv[0]); outY.push_back(yv[0]);
258 for (
int i=0;i<m-1;++i) {
259 outX.push_back(xv[i]); outY.push_back(yv[i+1]);
260 outX.push_back(xv[i+1]); outY.push_back(yv[i+1]);
264 std::vector<double> xU, yU, xL, yL;
265 build_stairs(yS, xHi, xU, yU);
266 build_stairs(yS, xLo, xL, yL);
269 xp.reserve(xU.size() + xL.size());
270 yp.reserve(yU.size() + yL.size());
271 for (
size_t i=0;i<xU.size();++i) { xp.push_back(xU[i]); yp.push_back(yU[i]); }
272 for (
int i=(
int)xL.size()-1;i>=0;--i) { xp.push_back(xL[i]); yp.push_back(yL[i]); }
275 auto* poly =
new TPolyLine((
int)xp.size(), xp.data(), yp.data());
276 poly->SetFillColorAlpha(fillColor, alpha);
277 poly->SetLineColor(lineColor);
278 poly->SetLineWidth(lineWidth);
282 auto* grHi =
new TGraph((
int)xU.size());
283 auto* grLo =
new TGraph((
int)xL.size());
284 for (
int i=0;i<(int)xU.size();++i) grHi->SetPoint(i, xU[i], yU[i]);
285 for (
int i=0;i<(int)xL.size();++i) grLo->SetPoint(i, xL[i], yL[i]);
286 grHi->SetLineColor(lineColor); grHi->SetLineWidth(lineWidth); grHi->Draw(
"L");
287 grLo->SetLineColor(lineColor); grLo->SetLineWidth(lineWidth); grLo->Draw(
"L");
290 TSpline3 sHi(
"sHi", yS.data(), xHi.data(), n);
291 TSpline3 sLo(
"sLo", yS.data(), xLo.data(), n);
293 const int m = (nsamples>1) ? nsamples : std::max(100, 4*n);
294 const double yMin = yS.front(), yMax = yS.back();
296 xp.reserve(2*m); yp.reserve(2*m);
297 for (
int i=0;i<m;++i) {
298 const double yy = yMin + (yMax - yMin) * (
double(i)/
double(m-1));
299 xp.push_back(sHi.Eval(yy));
302 for (
int i=m-1;i>=0;--i) {
303 const double yy = yMin + (yMax - yMin) * (
double(i)/
double(m-1));
304 xp.push_back(sLo.Eval(yy));
308 auto* poly =
new TPolyLine((
int)xp.size(), xp.data(), yp.data());
309 poly->SetFillColorAlpha(fillColor, alpha);
310 poly->SetLineColor(lineColor);
311 poly->SetLineWidth(lineWidth);
314 auto* grHi =
new TGraph(m);
315 auto* grLo =
new TGraph(m);
316 for (
int i=0;i<m;++i) {
317 grHi->SetPoint(i, xp[i], yp[i]);
318 grLo->SetPoint(i, xp[2*m-1-i], yp[2*m-1-i]);
320 grHi->SetLineColor(lineColor); grHi->SetLineWidth(lineWidth); grHi->Draw(
"L");
321 grLo->SetLineColor(lineColor); grLo->SetLineWidth(lineWidth); grLo->Draw(
"L");
329static void BuildEnvelopeCenterHalfwidth(
330 const std::vector<tkn_drip_point>& pts,
332 std::vector<double>& xNmid,
333 std::vector<double>& yZ,
334 std::vector<double>& exHalfWidth
336 std::map<int, std::pair<int,int>> z2mm;
337 for (
const auto& p : pts) {
338 auto& mm = z2mm[p.Z];
339 if (mm.first==0 && mm.second==0) mm = {p.N,p.N};
340 mm.first = (mm.first==0 ? p.N : std::min(mm.first, p.N));
341 mm.second = (mm.second==0 ? p.N : std::max(mm.second, p.N));
343 xNmid.clear(); yZ.clear(); exHalfWidth.clear();
344 xNmid.reserve(z2mm.size()); yZ.reserve(z2mm.size()); exHalfWidth.reserve(z2mm.size());
346 for (
const auto& [Z, mm] : z2mm) {
347 const double Nmid = 0.5*(mm.first + mm.second);
348 double halfW = 0.5*(mm.second - mm.first);
349 if (halfW < minHalfBin) halfW = minHalfBin;
350 xNmid.push_back(Nmid);
351 yZ.push_back((
double)Z);
352 exHalfWidth.push_back(halfW);
357static TGraph* MakeDripLineFromPoints(
const std::vector<tkn_drip_point>& pts,
358 Color_t color, Style_t lineStyle = 1, Width_t lineWidth = 3,
359 Style_t markerStyle = 20, Size_t markerSize = 0)
361 if (pts.empty())
return nullptr;
362 std::vector<tkn_drip_point> v = pts;
363 std::sort(v.begin(), v.end(), [](
auto& a,
auto& b){ return (a.Z<b.Z)||(a.Z==b.Z && a.N<b.N); });
365 std::vector<double> xs, ys; xs.reserve(v.size()); ys.reserve(v.size());
366 for (
const auto& p : v) { xs.push_back(p.N); ys.push_back(p.Z); }
368 auto* gr =
new TGraph((
int)xs.size(), xs.data(), ys.data());
369 gr->SetLineColor(color); gr->SetLineStyle(lineStyle); gr->SetLineWidth(lineWidth);
370 gr->SetMarkerStyle(markerStyle);
if (markerSize>0) gr->SetMarkerSize(markerSize);
371 gr->SetMarkerColor(color);
382void DrawDripLinesIfAvailable(EvenEven mode)
384 const double minHalfBin = (mode==EvenEven::No) ? 0.5 : 1.0;
387 auto s2n_all = gmanager->get_drip_line(
"S2n",
false);
388 auto s2p_all = gmanager->get_drip_line(
"S2p",
false);
391 std::vector<double> xNmid, yZ, exHalf;
392 if (!s2n_all.empty()) {
393 BuildEnvelopeCenterHalfwidth(s2n_all, minHalfBin, xNmid, yZ, exHalf);
394 DrawSmoothBandX(xNmid, yZ, exHalf,
399 if (!s2p_all.empty()) {
400 BuildEnvelopeCenterHalfwidth(s2p_all, minHalfBin, xNmid, yZ, exHalf);
401 DrawSmoothBandX(xNmid, yZ, exHalf,
414 TLatex lab; lab.SetTextFont(42); lab.SetTextSize(0.04); lab.SetTextAlign(13);
415 lab.SetTextColor(kAzure+2);
416 lab.DrawLatexNDC(gPad->GetLeftMargin()+0.010, 0.90,
"S_{2n} drip line");
417 lab.SetTextColor(kRed+1);
418 lab.DrawLatexNDC(gPad->GetLeftMargin()+0.010, 0.86,
"S_{2p} drip line");
426static void DrawStableNucleiBoxes(EvenEven mode,
427 Color_t color = kGray+2,
429 Width_t lineWidth = 2,
433 const double halfBin = (mode == EvenEven::Yes) ? 1.0 : 0.5;
435 glog.set_warnings(
false);
436 for (
const auto& nuc : gmanager->get_nuclei()) {
437 const int Z = nuc->get_z();
438 const int N = nuc->get_n();
440 if (mode == EvenEven::Yes && ((N % 2) || (Z % 2)))
continue;
441 if (!nuc->is_stable())
continue;
443 const double x1 = N - halfBin + inset;
444 const double x2 = N + halfBin - inset;
445 const double y1 = Z - halfBin + inset;
446 const double y2 = Z + halfBin - inset;
448 auto* box =
new TBox(x1, y1, x2, y2);
449 box->SetLineColorAlpha(color, alpha);
450 box->SetLineWidth(lineWidth);
453 box->SetFillStyle(1001);
454 box->SetFillColorAlpha(color, alpha);
456 box->SetFillStyle(0);
465void plot_nuclear_chart_deformation()
467 EvenEven mode = EvenEven::Yes;
469 const int NMax=180, ZMax=120;
471 TH2D* h = MakeHist(
"NucChart_BE2", NMax, ZMax, mode);
474 glog.set_warnings(
false);
475 for (
const auto &nuc : gmanager->get_nuclei([](
auto nuc) {
476 return (nuc->get_z()%2==0 && nuc->get_n()%2==0);
479 auto lev_scheme = nuc->get_level_scheme();
480 auto gamma = lev_scheme->get_decay<
tkgammadecay>(
"2+1->0+1",
false);
483 if(BE2W<=0||std::isnan(BE2W))
continue;
484 h->Fill(nuc->get_n(), nuc->get_z(), BE2W / ((
float)nuc->get_a()));
490 auto* c =
new TCanvas(
"c_be2",
"",1000,600);
491 c->SetMargin(0.06, 0.09, 0.08, 0.04);
493 ApplyCleanStyle(h, W, 0.0, 2.0);
496 DrawDripLinesIfAvailable(EvenEven::Yes);
497 DrawStableNucleiBoxes(EvenEven::Yes, kGray+1, 1.0,
499 PlacePalette(h, 0.92, 0.96, c->GetBottomMargin(), 1-c->GetTopMargin());
500 DrawMagicGridAndLabels(mode);
503 DrawTitleTopLeft(
"B(E2)/A (W.u.)");
507 gPad->Modified(); gPad->Update();
509 c->SaveAs(
"nuclear_chart_deformation.png");
513void plot_nuclear_chart_double_mass_diff()
515 EvenEven mode = EvenEven::No;
517 const int NMax=180, ZMax=120;
519 TH2D* h = MakeHist(
"NucChart_DD", NMax, ZMax, mode);
521 glog.set_warnings(
false);
522 const int dn=2, dz=2;
523 for (
const auto &nuc : gmanager->get_nuclei()) {
525 tknucleus n1(nuc->get_z()-dz, nuc->get_a()-dn-dz);
526 tknucleus n2(nuc->get_z()+dz, nuc->get_a()+dn+dz);
527 if (!n1.is_known() || !n2.is_known())
continue;
532 if (std::isnan(me) || std::isnan(me1) || std::isnan(me2))
continue;
534 const double dd = (me1 - 2.0*me + me2) / (2.0*std::sqrt(dn*dn + dz*dz));
535 h->SetBinContent(h->FindBin(nuc->get_n(), nuc->get_z()), dd);
540 auto* c =
new TCanvas(
"c_dd",
"",1000,600);
541 c->SetMargin(0.06, 0.09, 0.08, 0.04);
543 ApplyCleanStyle(h, W, -1.0, 2.5);
546 DrawDripLinesIfAvailable(EvenEven::Yes);
547 DrawStableNucleiBoxes(EvenEven::No, kBlack, 0.6,
549 PlacePalette(h, 0.92, 0.96, c->GetBottomMargin(), 1-c->GetTopMargin());
550 DrawMagicGridAndLabels(mode);
553 DrawTitleTopLeft(
"Double differential of the mass excess");
557 gPad->Modified(); gPad->Update();
559 c->SaveAs(
"nuclear_chart_double_mass_diff.png");
Stores information on a gamma-ray decay.
double get_trans_prob(bool _elec, int _L, bool _WU)
returns the gamma gamma transition probability value (ex: BE2 in Weiksopf units, get_trans_prob(1,...
A nucleus made of Z protons and N neutrons.
void DrawLogoAndCredit(double x1, double y1, double width, double text_size, const char *creditTxt, const char *opt)
static constexpr double ZmMax[7]
static constexpr int Nm[7]
static constexpr double NmMax[7]
static constexpr double ZmMin[7]
static constexpr double NmMin[7]