From 2db1022fc1ec59aff4a66d6cac4be89a592b693d Mon Sep 17 00:00:00 2001 From: gwm17 Date: Tue, 16 Aug 2022 09:51:12 -0400 Subject: [PATCH 1/8] Remove obsolete premake --- premake5.lua | 130 --------------------------------------------------- 1 file changed, 130 deletions(-) delete mode 100644 premake5.lua diff --git a/premake5.lua b/premake5.lua deleted file mode 100644 index 0e09632..0000000 --- a/premake5.lua +++ /dev/null @@ -1,130 +0,0 @@ -workspace "Mask" - configurations { - "Release", - "Debug" - } - -project "Mask" - kind "StaticLib" - language "C++" - targetdir "lib" - objdir "objs" - cppdialect "C++17" - - files { - "src/Mask/*.cpp", - "include/*.h" - } - - includedirs { - "include" - } - - filter "configurations:Debug" - symbols "On" - - filter "configurations:Release" - optimize "On" - -project "RootPlot" - kind "ConsoleApp" - language "C++" - targetdir "bin" - objdir "objs" - cppdialect "c++17" - - files { - "src/Plotters/ROOT/RootPlotter.cpp", - "include/*.h" - } - - --User specified path to ROOT CERN libraries-- - ROOTIncludepath = "/Users/gordon/Cern/root/include" - ROOTLibpath = "/Users/gordon/Cern/root/lib" - - includedirs { - "include" - } - - sysincludedirs { - ROOTIncludepath - } - - libdirs { - "lib/", - ROOTLibpath - } - - links { - "Mask", "Gui", "Core", "Imt", "RIO", "Net", "Hist", - "Graf", "Graf3d", "Gpad", "ROOTDataFrame", "ROOTVecOps", - "Tree", "TreePlayer", "Rint", "Postscript", "Matrix", - "Physics", "MathCore", "Thread", "MultiProc", "m", "dl" - } - - filter "system:macosx or linux" - linkoptions { - "-pthread" - } - - filter "configurations:Debug" - symbols "On" - - filter "configurations:Release" - optimize "On" - -project "MaskApp" - kind "ConsoleApp" - language "C++" - targetdir "bin" - objdir "objs" - cppdialect "c++17" - - files { - "src/MaskApp/*.cpp" - } - - includedirs { - "include" - } - - links { - "Mask" - } - - filter "system:macosx or linux" - linkoptions { - "-pthread" - } - - filter "configurations:Debug" - symbols "On" - - filter "configurations:Release" - optimize "On" - -project "DetectEff" - kind "ConsoleApp" - language "C++" - targetdir "bin" - objdir "objs" - cppdialect "c++17" - - files { - "src/Detectors/*.cpp", - "include/*.h" - } - - includedirs { - "include" - } - - links { - "Mask" - } - - filter "configurations:Debug" - symbols "On" - - filter "configurations:Release" - optimize "On" From 9a4c30867791fdec1ec4af6b5912862d65e0bea9 Mon Sep 17 00:00:00 2001 From: gwm17 Date: Tue, 16 Aug 2022 09:52:39 -0400 Subject: [PATCH 2/8] Remove objs dir (unused) --- objs/.gitignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 objs/.gitignore diff --git a/objs/.gitignore b/objs/.gitignore deleted file mode 100644 index 226f3fb..0000000 --- a/objs/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -###keep only the directory, not the contents### -* -!.gitignore From 66900ea9b4bba282504ec3356a9894ebf6ef0a59 Mon Sep 17 00:00:00 2001 From: gwm17 Date: Thu, 18 Aug 2022 10:31:16 -0400 Subject: [PATCH 3/8] Update gitignore --- .gitignore | 5 +- bin/.gitignore | 5 - bin/PyPlotViewer | 5 - bin/PyPlotter | 6 - include/Eloss_Tables.h | 133 ----------- include/EnergyLoss.h | 58 ----- include/MaskFile.h | 77 ------ include/Rotation.h | 78 ------- include/Vec3.h | 61 ----- include/Vec4.h | 69 ------ src/Mask/EnergyLoss.cpp | 243 ------------------- src/Mask/MaskFile.cpp | 364 ----------------------------- src/Mask/Nucleus.cpp | 47 ---- src/Mask/Rotation.cpp | 71 ------ src/Mask/Vec3.cpp | 48 ---- src/Mask/Vec4.cpp | 73 ------ src/Plotters/Python/.gitignore | 3 - src/Plotters/Python/MaskFile.py | 80 ------- src/Plotters/Python/NucData.py | 70 ------ src/Plotters/Python/Nucleus.py | 106 --------- src/Plotters/Python/PyPlotter.py | 135 ----------- src/Plotters/Python/ViewPyPlots.py | 32 --- 22 files changed, 3 insertions(+), 1766 deletions(-) delete mode 100644 bin/.gitignore delete mode 100755 bin/PyPlotViewer delete mode 100755 bin/PyPlotter delete mode 100644 include/Eloss_Tables.h delete mode 100644 include/EnergyLoss.h delete mode 100644 include/MaskFile.h delete mode 100644 include/Rotation.h delete mode 100644 include/Vec3.h delete mode 100644 include/Vec4.h delete mode 100644 src/Mask/EnergyLoss.cpp delete mode 100644 src/Mask/MaskFile.cpp delete mode 100644 src/Mask/Nucleus.cpp delete mode 100644 src/Mask/Rotation.cpp delete mode 100644 src/Mask/Vec3.cpp delete mode 100644 src/Mask/Vec4.cpp delete mode 100644 src/Plotters/Python/.gitignore delete mode 100755 src/Plotters/Python/MaskFile.py delete mode 100755 src/Plotters/Python/NucData.py delete mode 100755 src/Plotters/Python/Nucleus.py delete mode 100755 src/Plotters/Python/PyPlotter.py delete mode 100755 src/Plotters/Python/ViewPyPlots.py diff --git a/.gitignore b/.gitignore index 4b337c1..f0eaf4d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,14 +9,15 @@ *.pcm *.o *.a +*.so *.swp -*.pickle .DS_Store Makefile *.make -__pycache__ .vscode/ build/ +lib/ +bin/ ###Keep this file### diff --git a/bin/.gitignore b/bin/.gitignore deleted file mode 100644 index 888fdbf..0000000 --- a/bin/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -###keep only the directory, not the contents### -* -!.gitignore -!PyPlotter -!PyPlotViewer \ No newline at end of file diff --git a/bin/PyPlotViewer b/bin/PyPlotViewer deleted file mode 100755 index c612b15..0000000 --- a/bin/PyPlotViewer +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -FileName=$1; - -./src/Plotters/Python/ViewPyPlots.py ${FileName} \ No newline at end of file diff --git a/bin/PyPlotter b/bin/PyPlotter deleted file mode 100755 index 253ddd3..0000000 --- a/bin/PyPlotter +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -InputFile=$1; -OutputFile=$2; - -./src/Plotters/Python/PyPlotter.py ${InputFile} ${OutputFile} \ No newline at end of file diff --git a/include/Eloss_Tables.h b/include/Eloss_Tables.h deleted file mode 100644 index 67b5abe..0000000 --- a/include/Eloss_Tables.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef ELOSS_TABLES_H -#define ELOSS_TABLES_H - -namespace Mask { - - #define MAX_Z 93 //Maximum number of elements for which we have hydrogen coefficients - - /*Atomic Masses for elements H through U. Taken from ELAST data*/ - static double NATURAL_MASS[MAX_Z] = - {0, - 1.00797, 4.0026, 6.939, 9.0122, 10.818, - 12.01115, 14.0067, 15.9994, 18.99984, 20.183, - 22.9898, 24.312, 26.9815, 28.086, 30.9738, - 32.064, 35.453, 39.948, 39.102, 40.08, - 44.956, 47.90, 50.942, 51.996, 54.938, - 55.847, 58.933, 58.71, 63.54, 65.37, - 69.72, 72.59, 74.922, 78.96, 79.909, - 83.80, 85.47, 87.62, 88.909, 91.22, - 92.906, 95.94, 98., 101.07, 102.905, - 106.4, 107.87, 112.4, 114.82, 118.69, - 121.75, 127.60, 126.904, 131.3, 132.905, - 137.34, 138.91, 140.12, 140.907, 144.24, - 146., 150.35, 151.96, 157.25, 158.924, - 162.50, 164.93, 167.26, 168.934, 173.04, - 174.97, 178.49, 180.948, 183.85, 186.2, - 190.2, 192.2, 195.09, 196.967, 200.59, - 204.37, 207.19, 208.98, 209., 210., - 222., 223., 226., 227., 232.038, - 231., 238.03 }; - - /*Stopping power coefficients for hydrogen into Z - *Taken from Ziegler, Hydrogen Stopping Powers and Ranges in All Elements, Volume 3 of - *The Stopping and Ranges of Ions in Matter, 1977, Pergamon Press Inc. - *Expanded table for method given in O.G. Spanc - *Note: some elements represent extrapolations when there was no data to fit - */ - static double HYDROGEN_COEFF[MAX_Z][12] = { - /*Blank*/{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}, - /*H*/{1.262,1.44,242.6,1.2E4,0.1159,0.0005099,5.436E4,-5.052,2.049,-0.3044,0.01966,-0.0004659}, - /*He*/{1.229,1.397,484.5,5873,0.05225,0.00102,2.451E4,-2.158,0.8278,-0.1172,0.007259,-0.000166}, - /*Li*/{1.411,1.6,725.6,3013,0.04578,0.00153,2.147E4,-0.5831,0.562,-0.1183,0.009298,-0.0002498}, - /*Be*/{2.248,2.59,966,153.8,0.03475,0.002039,1.63E4,0.2779,0.1745,-0.05684,0.005155,-0.0001488}, - /*B*/{2.474,2.815,1206,1060,0.02855,0.002549,1.345E4,-2.445,1.283,-0.2205,0.0156,-0.000393}, - /*C*/{2.631,2.989,1445,957.2,0.02819,0.003059,1.322E4,-4.38,2.044,-0.3283,0.02221,-0.0005417}, - /*N*/{2.954,3.35,1683,1900,0.02513,0.003569,1.179E4,-5.054,2.325,-0.3713,0.02506,-0.0006109}, - /*O*/{2.652,3,1920,2000,0.0223,0.004079,1.046E4,-6.734,3.019,-0.4748,0.03171,-0.0007669}, - /*F*/{2.085,2.352,2157,2634,0.01816,0.004589,8517,-5.571,2.449,-0.3781,0.02483,-0.0005919}, - /*Ne*/{1.951,2.199,2393,2699,0.01568,0.005099,7353,-4.408,1.879,-0.2814,0.01796,-0.0004168}, - /*Na*/{2.542,2.869,2628,1854,0.01472,0.005609,6905,-4.959,2.073,-0.3054,0.01921,-0.0004403}, - /*Mg*/{3.792,4.293,2862,1009,0.01397,0.006118,6551,-5.51,2.266,-0.3295,0.02047,-0.0004637}, - /*Al*/{4.154,4.739,2766,164.5,0.02023,0.006628,6309,-6.061,2.46,-0.3535,0.02173,-0.0004871}, - /*Si*/{4.15,4.7,3329,550,0.01321,0.007138,6194,-6.294,2.538,-0.3628,0.0222,-0.0004956}, - /*P*/{3.232,3.647,3561,1560,0.01267,0.007648,5942,-6.527,2.616,-0.3721,0.02267,-0.000504}, - /*S*/{3.447,3.891,3792,1219,0.01211,0.008158,5678,-6.761,2.694,-0.3814,0.02314,-0.0005125}, - /*Cl*/{5.047,5.714,4023,878.6,0.01178,0.008668,5524,-6.994,2.773,-0.3907,0.02361,-0.0005209}, - /*Ar*/{5.731,6.5,4253,530,0.01123,0.009178,5268,-7.227,2.851,-0.4,0.02407,-0.0005294}, - /*K*/{5.151,5.833,4482,545.7,0.01129,0.009687,5295,-7.44,2.923,-0.4094,0.02462,-0.0005411}, - /*Ca*/{5.521,6.252,4710,553.3,0.01112,0.0102,5214,-7.653,2.995,-0.4187,0.02516,-0.0005529}, - /*Sc*/{5.201,5.884,4938,560.9,0.009995,0.01071,4688,-8.012,3.123,-0.435,0.02605,-0.0005707}, - /*Ti*/{4.862,5.496,5165,568.5,0.009474,0.01122,4443,-8.371,3.251,-0.4513,0.02694,-0.0005886}, - /*V*/{4.48,5.055,5391,952.3,0.009117,0.01173,4276,-8.731,3.379,-0.4676,0.02783,-0.0006064}, - /*Cr*/{3.983,4.489,5616,1336,0.008413,0.01224,3946,-9.09,3.507,-0.4838,0.02872,-0.0006243}, - /*Mn*/{3.469,3.907,5725,1461,0.008829,0.01275,3785,-9.449,3.635,-0.5001,0.02961,-0.0006421}, - /*Fe*/{3.519,3.963,6065,1243,0.007782,0.01326,3650,-9.809,3.763,-0.5164,0.0305,-0.00066}, - /*Co*/{3.14,3.535,6288,1372,0.007361,0.01377,3453,-10.17,3.891,-0.5327,0.03139,-0.0006779}, - /*Ni*/{3.553,4.004,6205,555.1,0.008763,0.01428,3297,-10.53,4.019,-0.549,0.03229,-0.0006957}, - /*Cu*/{3.696,4.175,4673,387.8,0.02188,0.01479,3174,-11.18,4.252,-0.5791,0.03399,-0.0007314}, - /*Zn*/{4.21,4.75,6953,295.2,0.006809,0.0153,3194,-11.57,4.394,-0.598,0.03506,-0.0007537}, - /*Ga*/{5.041,5.697,7173,202.6,0.006725,0.01581,3154,-11.95,4.537,-0.6169,0.03613,-0.0007759}, - /*Ge*/{5.554,6.3,6496,110,0.009689,0.01632,3097,-12.34,4.68,-0.6358,0.03721,-0.0007981}, - /*As*/{5.323,6.012,7611,292.5,0.006447,0.01683,3024,-12.72,4.823,-0.6547,0.03828,-0.0008203}, - /*Se*/{5.874,6.656,7395,117.5,0.007684,0.01734,3006,-13.11,4.965,-0.6735,0.03935,-0.0008425}, - /*Br*/{5.611,6.335,8046,365.2,0.006244,0.01785,2928,-13.4,5.083,-0.6906,0.04042,-0.0008675}, - /*Kr*/{6.411,7.25,8262,220,0.006087,0.01836,2855,-13.69,5.2,-0.7076,0.0415,-0.0008925}, - /*Rb*/{5.694,6.429,8478,292.9,0.006087,0.01886,2855,-13.92,5.266,-0.714,0.04173,-0.0008943}, - /*Sr*/{6.339,7.159,8693,330.3,0.006003,0.01937,2815,-14.14,5.331,-0.7205,0.04196,-0.0008962}, - /*Y*/{6.407,7.234,8907,367.8,0.005889,0.01988,2762,-14.36,5.397,-0.7269,0.04219,-0.000898}, - /*Zr*/{6.734,7.603,9120,405.2,0.005765,0.02039,2704,-14.59,5.463,-0.7333,0.04242,-0.0008998}, - /*Nb*/{6.902,7.791,9333,442.7,0.005587,0.0209,2621,-16.22,6.094,-0.8225,0.04791,-0.001024}, - /*Mo*/{6.425,7.248,9545,480.2,0.005367,0.02141,2517,-17.85,6.725,-0.9116,0.05339,-0.001148}, - /*Tc*/{6.799,7.671,9756,517.6,0.005315,0.02192,2493,-17.96,6.752,-0.9135,0.05341,-0.001147}, - /*Ru*/{6.108,6.887,9966,555.1,0.005151,0.02243,2416,-18.07,6.779,-0.9154,0.05342,-0.001145}, - /*Rh*/{5.924,6.677,1.018E4,592.5,0.004919,0.02294,2307,-18.18,6.806,-0.9173,0.05343,-0.001143}, - /*Pd*/{5.238,5.9,1.038E4,630,0.004758,0.02345,2231,-18.28,6.833,-0.9192,0.05345,-0.001142}, - /*Ag*/{5.623,6.354,7160,337.6,0.01394,0.02396,2193,-18.39,6.86,-0.9211,0.05346,-0.00114}, - /*Cd*/{5.814,6.554,1.08E4,355.5,0.004626,0.02447,2170,-18.62,6.915,-0.9243,0.0534,-0.001134}, - /*In*/{6.23,7.024,1.101E4,370.9,0.00454,0.02498,2129,-18.85,6.969,-0.9275,0.05335,-0.001127}, - /*Sn*/{6.41,7.227,1.121E4,386.4,0.004474,0.02549,2099,-19.07,7.024,-0.9308,0.05329,-0.001121}, - /*Sb*/{7.5,8.48,8608,348,0.009074,0.026,2069,-19.57,7.225,-0.9603,0.05518,-0.001165}, - /*Te*/{6.979,7.871,1.162E4,392.4,0.004402,0.02651,2065,-20.07,7.426,-0.9899,0.05707,-0.001209}, - /*I*/{7.725,8.716,1.183E4,394.8,0.004376,0.02702,2052,-20.56,7.627,-1.019,0.05896,-0.001254}, - /*Xe*/{8.231,9.289,1.203E4,397.3,0.004384,0.02753,2056,-21.06,7.828,-1.049,0.06085,-0.001298}, - /*Cs*/{7.287,8.218,1.223E4,399.7,0.004447,0.02804,2086,-20.4,7.54,-1.004,0.05782,-0.001224}, - /*Ba*/{7.899,8.911,1.243E4,402.1,0.004511,0.02855,2116,-19.74,7.252,-0.9588,0.05479,-0.001151}, - /*La*/{8.041,9.071,1.263E4,404.5,0.00454,0.02906,2129,-19.08,6.964,-0.9136,0.05176,-0.001077}, - /*Ce*/{7.489,8.444,1.283E4,406.9,0.00442,0.02957,2073,-18.43,6.677,-0.8684,0.04872,-0.001003}, - /*Pr*/{7.291,8.219,1.303E4,409.3,0.004298,0.03008,2016,-17.77,6.389,-0.8233,0.04569,-0.0009292}, - /*Nd*/{7.098,8,1.323E4,411.8,0.004182,0.03059,1962,-17.11,6.101,-0.7781,0.04266,-0.0008553}, - /*Pm*/{6.91,7.786,1.343E4,414.2,0.00405,0.0311,1903,-16.45,5.813,-0.733,0.03963,-0.0007815}, - /*Sm*/{6.728,7.58,1.362E4,416.6,0.003976,0.03161,1865,-15.79,5.526,-0.6878,0.0366,-0.0007077}, - /*Eu*/{6.551,7.38,1.382E4,419,0.003877,0.03212,1819,-15.13,5.238,-0.6426,0.03357,-0.0006339}, - /*Gd*/{6.739,7.592,1.402E4,421.4,0.003863,0.03263,1812,-14.47,4.95,-0.5975,0.03053,-0.0005601}, - /*Tb*/{6.212,6.996,1.421E4,423.9,0.003725,0.03314,1747,-14.56,4.984,-0.6022,0.03082,-0.0005668}, - /*Dy*/{5.517,6.21,1.44E4,426.3,0.003632,0.03365,1703,-14.65,5.018,-0.6069,0.03111,-0.0005734}, - /*Ho*/{5.219,5.874,1.46E4,428.7,0.003498,0.03416,1640,-14.74,5.051,-0.6117,0.03141,-0.0005801}, - /*Er*/{5.071,5.706,1.479E4,433,0.003405,0.03467,1597,-14.83,5.085,-0.6164,0.0317,-0.0005867}, - /*Tm*/{4.926,5.542,1.498E4,433.5,0.003342,0.03518,1567,-14.91,5.119,-0.6211,0.03199,-0.0005933}, - /*Yb*/{4.787, 5.386,1.517E4,435.9,0.003292,0.03569,1544,-15,5.153,-0.6258,0.03228,-0.0006}, - /*Lu*/{4.893, 5.505,1.536E4,438.4,0.003243,0.0362,1521,-15.09,5.186,-0.6305,0.03257,-0.0006066}, - /*Hf*/{5.028, 5.657,1.555E4,440.8,0.003195,0.03671,1499,-15.18,5.22,-0.6353,0.03286,-0.0006133}, - /*Ta*/{4.738, 5.329,1.574E4,443.2,0.003186,0.03722,1494,-15.27,5.254,-0.64,0.03315,-0.0006199}, - /*W*/{4.574, 5.144,1.593E4,442.4,0.003144,0.03773,1475,-15.67,5.392,-0.6577,0.03418,-0.0006426}, - /*Re*/{5.2, 5.851,1.612E4,441.6,0.003122,0.03824,1464,-16.07,5.529,-0.6755,0.03521,-0.0006654}, - /*Os*/{5.07, 5.704,1.63E4,440.9,0.003082,0.03875,1446,-16.47,5.667,-0.6932,0.03624,-0.0006881}, - /*Ir*/{4.945, 5.563,1.649E4,440.1,0.002965,0.03926,1390,-16.88,5.804,-0.711,0.03727,-0.0007109}, - /*Pt*/{4.476, 5.034,1.667E4,439.3,0.002871,0.03977,1347,-17.28,5.942,-0.7287,0.0383,-0.0007336}, - /*Au*/{4.856, 5.46,1.832E4,438.5,0.002542,0.04028,1354,-17.02,5.846,-0.7149,0.0374,-0.0007114}, - /*Hg*/{4.308, 4.843,1.704E4,487.8,0.002882,0.04079,1352,-17.84,6.183,-0.7659,0.04076,-0.0007925}, - /*Tl*/{4.723, 5.311,1.722E4,537,0.002913,0.0413,1366,-18.66,6.52,-0.8169,0.04411,-0.0008737}, - /*Pb*/{5.319, 5.982,1.74E4,586.3,0.002871,0.04181,1347,-19.48,6.857,-0.8678,0.04747,-0.0009548}, - /*Bi*/{5.956, 6.7,1.78E4,677,0.00266,0.04232,1336,-19.55,6.871,-0.8686,0.04748,-0.0009544}, - /*Po*/{6.158, 6.928,1.777E4,586.3,0.002812,0.04283,1319,-19.62,6.884,-0.8694,0.04748,-0.000954}, - /*At*/{6.204, 6.979,1.795E4,586.3,0.002776,0.04334,1302,-19.69,6.898,-0.8702,0.04749,-0.0009536}, - /*Rn*/{6.181, 6.954,1.812E4,586.3,0.002748,0.04385,1289,-19.76,6.912,-0.871,0.04749,-0.0009532}, - /*Fr*/{6.949, 7.82,1.83E4,586.3,0.002737,0.04436,1284,-19.83,6.926,-0.8718,0.0475,-0.0009528}, - /*Ra*/{7.506, 8.448,1.848E4,586.3,0.002727,0.04487,1279,-19.9,6.94,-0.8726,0.04751,-0.0009524}, - /*Ac*/{7.649, 8.609,1.866E4,586.3,0.002697,0.04538,1265,-19.97,6.953,-0.8733,0.04751,-0.000952}, - /*Th*/{7.71, 8.679,1.883E4,586.3,0.002641,0.04589,1239,-20.04,6.967,-0.8741,0.04752,-0.0009516}, - /*Pa*/{7.407, 8.336,1.901E4,586.3,0.002603,0.0464,1221,-20.11,6.981,-0.8749,0.04752,-0.0009512}, - /*U*/{7.29, 8.204,1.918E4,586.3,0.002573,0.04691,1207,-20.18,6.995,-0.8757,0.04753,-0.0009508} - }; -} -#endif diff --git a/include/EnergyLoss.h b/include/EnergyLoss.h deleted file mode 100644 index 969e524..0000000 --- a/include/EnergyLoss.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - -EnergyLoss.h -Code for calculating the energy loss of a charged, massive particle through an arbitrary medium. -Based on code written by D.W. Visser at Yale for the original SPANC. Uses energy loss calulations -described by Ziegler in various SRIM textbooks. - -Written by G.W. McCann Aug. 2020 - -*/ - -#ifndef ENERGYLOSS_H -#define ENERGYLOSS_H - -#include -#include -#include -#include -#include -#include "MassLookup.h" - -namespace Mask { - class EnergyLoss { - - public: - EnergyLoss(); - ~EnergyLoss(); - double GetEnergyLoss(int zp, int ap, double e_initial, double thickness); - double GetReverseEnergyLoss(int zp, int ap, double e_final, double thickness); - double GetRange(double energy); - void SetTargetComponents(const std::vector& Zt, const std::vector& At, const std::vector& Stoich); - - private: - double GetElectronicStoppingPower(double energy); - double GetNuclearStoppingPower(double energy); - double GetTotalStoppingPower(double energy); - double Hydrogen_dEdx_Low(double e_per_u, int z); - double Hydrogen_dEdx_Med(double e_per_u, int z); - double Hydrogen_dEdx_High(double e_per_u, double energy, int z); - double CalculateEffectiveChargeRatio(double e_per_u, int z); - - int ZP, AP; - double MP; //units of u, isotopic - double comp_denom; - std::vector ZT, AT; - std::vector targ_composition; - - //constants for calculations - static constexpr double MAX_FRACTIONAL_STEP = 0.001; - static constexpr double MAX_DEPTH = 50; - static constexpr double MAX_H_E_PER_U = 100000.0; - static constexpr double AVOGADRO = 0.60221367; //N_A times 10^(-24) for converting - static constexpr double MEV2U = 1.0/931.4940954; - static constexpr double H_RESTMASS = 938.27231; //MeV, for beta calc - }; -} - -#endif diff --git a/include/MaskFile.h b/include/MaskFile.h deleted file mode 100644 index 42ffced..0000000 --- a/include/MaskFile.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef MASKFILE_H -#define MASKFILE_H - -#include -#include -#include - -#include "Nucleus.h" -#include "RxnType.h" - -namespace Mask { - - struct MaskFileHeader { - RxnType rxn_type = RxnType::None; - int nsamples = -1; - }; - - struct MaskFileData { - std::vector E, KE, p, theta, phi; //ordered: target, (if not decay)projectile, ejectile, residual, break1... - std::vector Z, A; - std::vector detect_flag; - bool eof = false; //flag on end of file - }; - - class MaskFile { - public: - enum class FileType { - read, - write, - append, - none - }; - - MaskFile(); - MaskFile(const std::string& name, MaskFile::FileType type); - bool Open(const std::string& name, MaskFile::FileType type); - inline bool IsOpen() { return file.is_open(); } - void Close(); - - void WriteHeader(RxnType rxn_type, int nsamples); - void WriteData(const std::vector& data); - void WriteData(const MaskFileData& data); - MaskFileHeader ReadHeader(); - MaskFileData ReadData(); - - - - private: - - FileType file_type; - std::string filename; - uint64_t buffer_position; - uint64_t buffer_end; - uint32_t data_size; - RxnType m_rxn_type; - uint32_t buffersize_bytes; - - std::fstream file; - - std::vector data_buffer; - - static constexpr uint32_t onestep_rxn_n = 2; - static constexpr uint32_t twostep_rxn_n = 4; - static constexpr uint32_t threestep_rxn_n = 6; - - static constexpr uint64_t buffersize = 10000; //number of events - static constexpr int width = 0; - static constexpr int precision = 3; - - static constexpr std::size_t double_size = sizeof(double); - static constexpr std::size_t int_size = sizeof(uint32_t); - static constexpr std::size_t bool_size = sizeof(bool); - }; - -}; - -#endif \ No newline at end of file diff --git a/include/Rotation.h b/include/Rotation.h deleted file mode 100644 index 9b8ba3c..0000000 --- a/include/Rotation.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Classes which define rotations about the x, y, and z axes. Using these, - any arbitrary orientation can be described. Methods implemented for vector multiplication - as well as generating the inverse of the rotation. -*/ -#ifndef ROTATION_H -#define ROTATION_H - -#include "Vec3.h" - -namespace Mask { - - class XRotation { - public: - XRotation(); - XRotation(double ang); - ~XRotation(); - Vec3 Rotate(const Vec3& vector); - inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); } - inline XRotation GetInverse() { return XRotation(-m_angle); } - inline Vec3 operator*(const Vec3& vector) { - double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2]; - double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2]; - double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2]; - return Vec3(x, y, z); - } - - private: - void GenerateMatrix(); - double m_angle; - double m_matrix[3][3]; - }; - - class YRotation { - public: - YRotation(); - YRotation(double ang); - ~YRotation(); - Vec3 Rotate(const Vec3& vector); - inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); } - inline YRotation GetInverse() { return YRotation(-m_angle); } - inline Vec3 operator*(const Vec3& vector) { - double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2]; - double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2]; - double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2]; - return Vec3(x, y, z); - } - - private: - void GenerateMatrix(); - double m_angle; - double m_matrix[3][3]; - }; - - class ZRotation { - public: - ZRotation(); - ZRotation(double ang); - ~ZRotation(); - Vec3 Rotate(const Vec3& vector); - inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); } - inline ZRotation GetInverse() { return ZRotation(-m_angle); } - inline Vec3 operator*(const Vec3& vector) { - double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2]; - double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2]; - double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2]; - return Vec3(x, y, z); - } - - private: - void GenerateMatrix(); - double m_angle; - double m_matrix[3][3]; - }; - -} - -#endif \ No newline at end of file diff --git a/include/Vec3.h b/include/Vec3.h deleted file mode 100644 index dcd1ad8..0000000 --- a/include/Vec3.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Class to represent a 3-space vector in both cartesian and spherical coordinates. Can perform vector - addition, subtraction, and dot product. - - --GWM Dec 2020 -*/ -#ifndef VEC3_H -#define VEC3_H - -#include - -namespace Mask { - - class Vec3 { - public: - Vec3(); - Vec3(double x, double y, double z); - ~Vec3(); - - void SetVectorCartesian(double x, double y, double z); - void SetVectorSpherical(double r, double theta, double phi); - inline double GetX() const { return m_data[0]; } - inline double GetY() const { return m_data[1]; } - inline double GetZ() const { return m_data[2]; } - inline double GetRho() const { return std::sqrt(std::pow(m_data[0], 2.0) + std::pow(m_data[1], 2.0)); } - inline double GetR() const { return std::sqrt(std::pow(m_data[0], 2.0) + std::pow(m_data[1], 2.0) + std::pow(m_data[2], 2.0)); } - inline double GetTheta() const { return Atan2(GetRho(), GetZ()); } - inline double GetPhi() const { - double phi = Atan2(GetY(), GetX()); - if(phi < 0) phi += M_PI*2.0; - return phi; - } - - inline const double operator[](int index) const { return index>2 || index<0 ? 0.0 : m_data[index]; } - inline Vec3& operator=(const Vec3& rhs) { SetVectorCartesian(rhs.GetX(), rhs.GetY(), rhs.GetZ()); return *this; } - inline Vec3 operator+(const Vec3& rhs) const { return Vec3(this->GetX()+rhs.GetX(), this->GetY()+rhs.GetY(), this->GetZ()+rhs.GetZ()); } - inline Vec3 operator-(const Vec3& rhs) const { return Vec3(this->GetX()-rhs.GetX(), this->GetY()-rhs.GetY(), this->GetZ()-rhs.GetZ()); } - - - double Dot(const Vec3& rhs) const; - Vec3 Cross(const Vec3& rhs) const; - - - - private: - - //Use instead of std::atan2. Better control over values close to x=0 - inline double Atan2(double y, double x) const { - if(x != 0.0) return std::atan2(y, x); - else if(y > 0.0) return M_PI/2.0; - else if(y < 0.0) return -M_PI/2.0; - else return 0.0; - } - - double m_data[3]; - - }; - -} - -#endif \ No newline at end of file diff --git a/include/Vec4.h b/include/Vec4.h deleted file mode 100644 index 51eb879..0000000 --- a/include/Vec4.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Class which represents a 4-momentum vector. Can perform vector addition, subtraction, dot product - and generate a boost vector to its rest frame as well as apply a boost to itself. - - --GWM Dec 2020. -*/ -#ifndef VEC4_H -#define VEC4_H - -#include - -namespace Mask { - - class Vec4 { - public: - Vec4(); - Vec4(double px, double py, double pz, double E); - virtual ~Vec4(); - void SetVectorCartesian(double px, double py, double pz, double E); - void SetVectorSpherical(double theta, double phi, double p, double E); - - inline double GetE() const { return m_data[3]; } - inline double GetPx() const { return m_data[0]; } - inline double GetPy() const { return m_data[1]; } - inline double GetPz() const { return m_data[2]; } - inline double GetP() const { return std::sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1] + m_data[2]*m_data[2]); } - inline double GetPxy() const { return std::sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1]); } - inline double GetTheta() const { return GetPxy() == 0.0 && GetPz() == 0.0 ? 0.0 : Atan2(GetPxy(), GetPz()); } - inline double GetPhi() const { - double phi = Atan2(GetPy(), GetPx()); - if(phi<0) phi += 2.0*M_PI; - return GetPx() == 0.0 && GetPy() == 0.0 ? 0.0 : phi; - } - - inline double GetInvMass() const { return std::sqrt(GetE()*GetE() - GetP()*GetP()); } - inline double GetKE() const { return GetE() - GetInvMass(); } - inline const double* GetBoost() const { return &m_boost[0]; } - - void ApplyBoost(const double* boost); - - //Only intended for use in looping access! - inline const double operator[] (int index) const { return index>3 || index < 0 ? 0.0 : m_data[index]; } - - inline Vec4& operator=(const Vec4& rhs) { SetVectorCartesian(rhs.GetPx(), rhs.GetPy(), rhs.GetPz(), rhs.GetE()); return *this; } - inline Vec4 operator+(const Vec4& rhs) const { return Vec4(rhs.GetPx()+GetPx(), rhs.GetPy()+GetPy(), rhs.GetPz()+GetPz(), rhs.GetE()+GetE()); } - inline Vec4 operator-(const Vec4& rhs) const { return Vec4(rhs.GetPx()-GetPx(), rhs.GetPy()-GetPy(), rhs.GetPz()-GetPz(), rhs.GetE()-GetE()); } - - double Dot(const Vec4& rhs) const; - Vec4 Cross(const Vec4& rhs) const; - - private: - void CalcBoostToCM(); - - //use instead of std::atan2. Better controll over x=0 - inline double Atan2(double y, double x) const { - if(x != 0) return std::atan2(y, x); - else if( y > 0 ) return M_PI/2.0; - else if( y < 0 ) return -M_PI/2.0; - else return 0.0; - } - - double m_data[4]; - double m_boost[3]; - - }; - -} - -#endif diff --git a/src/Mask/EnergyLoss.cpp b/src/Mask/EnergyLoss.cpp deleted file mode 100644 index 2fdcbfb..0000000 --- a/src/Mask/EnergyLoss.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - -EnergyLoss.cpp -Code for calculating the energy loss of a charged, massive particle through an arbitrary medium. -Based on code written by D.W. Visser at Yale for the original SPANC. Uses energy loss calulations -described by Ziegler in various SRIM textbooks. - -Written by G.W. McCann Aug. 2020 - -*/ - -#include "Eloss_Tables.h" -#include "EnergyLoss.h" -#include "KinematicsExceptions.h" -#include - -namespace Mask { - - EnergyLoss::EnergyLoss() : - ZP(-1), AP(-1), MP(-1.0), comp_denom(0) - { - } - - EnergyLoss::~EnergyLoss() {} - - /*Targets are defined by their atomic number, total number of nucleons, and their stoichiometry within the target compound*/ - void EnergyLoss::SetTargetComponents(const std::vector& Zt, const std::vector& At, const std::vector& Stoich) { - comp_denom = 0; - ZT = Zt; - AT = At; - for(unsigned int i=0; i MAX_Z) - throw ELossException("Maximum allowed target Z exceeded"); - } - targ_composition.resize(Stoich.size()); - - for(unsigned int i=0; i MAX_FRACTIONAL_STEP && depth < MAX_DEPTH) { - depth++; - x_step *= 0.5; - e_step = GetTotalStoppingPower(e_final)*x_step/1000.0; - } else if((x_step + x_traversed) >= thickness) { //last chunk - go = false; - x_step = thickness - x_traversed; //get valid portion of last chunk - e_final -= GetTotalStoppingPower(e_final)*x_step/1000.0; - if(e_final <= e_threshold) - return e_initial; - } else if(depth == MAX_DEPTH) { - return e_initial; - } else { - x_traversed += x_step; - e_step = GetTotalStoppingPower(e_final)*x_step/1000.0; - e_final -= e_step; - if(e_final <= e_threshold) - return e_initial; - } - } - return e_initial - e_final; - } - - /* - Returns units of MeV; thickness in ug/cm^2; e_final in units of MeV - Energy loss going through the target using energy of particle after traversal - */ - double EnergyLoss::GetReverseEnergyLoss(int zp, int ap, double e_final, double thickness) { - if( ZP != zp) { - ZP = zp; - AP = ap; - MP = MassLookup::GetInstance().FindMass(ZP, AP)*MEV2U; - - } - - double e_initial = e_final; - double x_traversed = 0.0; - double x_step = 0.25*thickness; //initial step in x - double e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0; //initial step in E - - bool go = true; - while(go) { - if(e_step/e_initial > MAX_FRACTIONAL_STEP) { - x_step *= 0.5; - e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0; - } else if (x_traversed+x_step > thickness) { - go = false; - x_step = thickness - x_traversed; - e_initial += GetTotalStoppingPower(e_initial)*x_step/1000.0; - } else { - x_traversed += x_step; - e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0; - e_initial += e_step; - } - } - - return e_initial-e_final; - } - - /* - Returns units of keV/(ug/cm^2) - Calculates Electronic stopping power by first calculating SE for hydrogen through the target and then using - corrections to calculate SE for projectile of interest - */ - double EnergyLoss::GetElectronicStoppingPower(double energy) { - //Wants in units of keV - energy *= 1000.0; - double e_per_u = energy/MP; - std::vector values; - if(e_per_u > MAX_H_E_PER_U) { - throw ELossException("Exceeded maximum allowed energy per nucleon"); - } else if (e_per_u > 1000.0) { - for(auto& z: ZT) - values.push_back(Hydrogen_dEdx_High(e_per_u, energy, z)); - } else if (e_per_u > 10.0) { - for(auto& z: ZT) - values.push_back(Hydrogen_dEdx_Med(e_per_u, z)); - } else if (e_per_u > 0.0) { - for(auto& z: ZT) - values.push_back(Hydrogen_dEdx_Low(e_per_u, z)); - } else { - throw ELossException("Negative energy per nucleon; given energy: "+std::to_string(energy)); - } - - if(values.size() == 0) - throw ELossException("Size of value array is 0. Unable to iterate over target components"); - - if(ZP > 1) { //not hydrogen, need to account for effective charge - for(unsigned int i=0; i -#include -#include - -/* - - FORMAT - - HEADER (contains rxntype & nuclei numbers & beam kinetic energy) (64 bits, 8 bytes) - NSAMPLES(32bit) RXNTYPE(32bit) - end HEADER - - There are NSAMPLES * (number of saved nuclei) data in the file. The number of nuclei saved is related to the - RXNTYPE. All nuclei (target, projectile, ejectile, residual, break1, etc...) are saved. A datum is as follows: - - DATUM (contains kinematic data for a nucleus) (384 bits, 48 bytes) - Z(32bit) A(32bit) DETECTFLAG(32bit) E(64bit) KE(64bit) P(64bit) THETA(64bit) PHI(64bit) - end DATUM - - -*/ - -namespace Mask { - - MaskFile::MaskFile() : - file_type(MaskFile::FileType::none), filename(""), buffer_position(0), buffer_end(0), data_size(0), buffersize_bytes(0), file() - { - } - - MaskFile::MaskFile(const std::string& name, MaskFile::FileType type) : - file_type(type), filename(name), buffer_position(0), buffer_end(0), data_size(0), buffersize_bytes(0), file() - { - Open(filename, type); - } - - bool MaskFile::Open(const std::string& name, MaskFile::FileType type) { - if(IsOpen()) { - std::cerr<<"Attempted to open file that is already open!"< 0 && buffer_position < buffersize_bytes && (file_type == FileType::write || file_type == FileType::append)) { - file.write(data_buffer.data(), buffer_position); - } - file.close(); - } - - void MaskFile::WriteHeader(RxnType rxn_type, int nsamples) { - - m_rxn_type = rxn_type; - switch(rxn_type) - { - case RxnType::PureDecay : - { - data_size = 3 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::OneStepRxn : - { - data_size = 4 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::TwoStepRxn : - { - data_size = 6 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::ThreeStepRxn : - { - data_size = 8 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::None : - { - std::cerr<<"Invalid RxnType at MaskFile::WriteHeader!"< temp_buffer(4); - file.read(temp_buffer.data(), 4); - header.nsamples = *(int*)(&temp_buffer[0]); - file.read(temp_buffer.data(), 4); - uint32_t type_value = *(uint32_t*)(&temp_buffer[0]); - m_rxn_type = GetRxnTypeFromInt(type_value); - - switch(m_rxn_type) - { - case RxnType::PureDecay: - { - data_size = 3 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::OneStepRxn: - { - data_size = 4 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::TwoStepRxn: - { - data_size = 6 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::ThreeStepRxn: - { - data_size = 8 * ( 5 * double_size + 2 * int_size + bool_size); - break; - } - case RxnType::None: - { - std::cerr<<"Unexpected reaction type at MaskFile::ReadHeader (rxn type = "<& data) { - - char* data_pointer; - double datum; - int number; - bool flag; - std::size_t j; - for(unsigned int i=0; i buffer_end) { - std::cerr<<"Attempting to read past end of file at MaskFile::ReadData! Returning empty"<A) return false; - - m_z = Z; - m_a = A; - m_gs_mass = MassLookup::GetInstance().FindMass(Z, A); - m_symbol = MassLookup::GetInstance().FindSymbol(Z, A); - SetVectorCartesian(0,0,0,m_gs_mass); - return true; - } - -} \ No newline at end of file diff --git a/src/Mask/Rotation.cpp b/src/Mask/Rotation.cpp deleted file mode 100644 index aa07ad8..0000000 --- a/src/Mask/Rotation.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - Classes which define rotations about the x, y, and z axes. Using these, - any arbitrary orientation can be described. Methods implemented for vector multiplication - as well as generating the inverse of the rotation. -*/ -#include "Rotation.h" - -namespace Mask { - - XRotation::XRotation() : - m_angle(0) - { - GenerateMatrix(); - } - - XRotation::XRotation(double angle) : - m_angle(angle) - { - GenerateMatrix(); - } - - XRotation::~XRotation() {} - - void XRotation::GenerateMatrix() { - m_matrix[0][0] = 1.0; m_matrix[0][1] = 0.0; m_matrix[0][2] = 0.0; - m_matrix[1][0] = 0.0; m_matrix[1][1] = std::cos(m_angle); m_matrix[1][2] = -std::sin(m_angle); - m_matrix[2][0] = 0.0; m_matrix[2][1] = std::sin(m_angle); m_matrix[2][2] = std::cos(m_angle); - } - - YRotation::YRotation() : - m_angle(0) - { - GenerateMatrix(); - } - - YRotation::YRotation(double angle) : - m_angle(angle) - { - GenerateMatrix(); - } - - YRotation::~YRotation() {} - - void YRotation::GenerateMatrix() { - m_matrix[0][0] = std::cos(m_angle); m_matrix[0][1] = 0.0; m_matrix[0][2] = -std::sin(m_angle); - m_matrix[1][0] = 0.0; m_matrix[1][1] = 1.0; m_matrix[1][2] = 0.0; - m_matrix[2][0] = std::sin(m_angle); m_matrix[2][1] = 0.0; m_matrix[2][2] = std::cos(m_angle); - } - - - ZRotation::ZRotation() : - m_angle(0) - { - GenerateMatrix(); - } - - ZRotation::ZRotation(double angle) : - m_angle(angle) - { - GenerateMatrix(); - } - - ZRotation::~ZRotation() {} - - void ZRotation::GenerateMatrix() { - m_matrix[0][0] = std::cos(m_angle); m_matrix[0][1] = -std::sin(m_angle); m_matrix[0][2] = 0.0; - m_matrix[1][0] = std::sin(m_angle); m_matrix[1][1] = std::cos(m_angle); m_matrix[1][2] = 0.0; - m_matrix[2][0] = 0.0; m_matrix[2][1] = 0.0; m_matrix[2][2] = 1.0; - } - -}; \ No newline at end of file diff --git a/src/Mask/Vec3.cpp b/src/Mask/Vec3.cpp deleted file mode 100644 index 42abdc9..0000000 --- a/src/Mask/Vec3.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - Class to represent a 3-space vector in both cartesian and spherical coordinates. Can perform vector - addition, subtraction, and dot product. - - --GWM Dec 2020 -*/ -#include "Vec3.h" - -namespace Mask { - - Vec3::Vec3() { - m_data[0] = 0.; - m_data[1] = 0.; - m_data[2] = 0.; - } - - Vec3::Vec3(double x, double y, double z) { - m_data[0] = x; - m_data[1] = y; - m_data[2] = z; - } - - Vec3::~Vec3() {} - - void Vec3::SetVectorCartesian(double x, double y, double z) { - m_data[0] = x; - m_data[1] = y; - m_data[2] = z; - } - - void Vec3::SetVectorSpherical(double r, double theta, double phi) { - m_data[0] = r*std::cos(phi)*std::sin(theta); - m_data[1] = r*std::sin(phi)*std::sin(theta); - m_data[2] = r*std::cos(theta); - } - - double Vec3::Dot(const Vec3& rhs) const { - return GetX()*rhs.GetX() + GetY()*rhs.GetY() + GetZ()*rhs.GetZ(); - } - - Vec3 Vec3::Cross(const Vec3& rhs) const { - double x = GetY()*rhs.GetZ() - GetZ()*rhs.GetY(); - double y = GetZ()*rhs.GetX() - GetX()*rhs.GetZ(); - double z = GetX()*rhs.GetY() - GetY()*rhs.GetX(); - return Vec3(x,y,z); - } - -} diff --git a/src/Mask/Vec4.cpp b/src/Mask/Vec4.cpp deleted file mode 100644 index 493ea3e..0000000 --- a/src/Mask/Vec4.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - Class which represents a 4-momentum vector. Can perform vector addition, subtraction, dot product - and generate a boost vector to its rest frame as well as apply a boost to itself. - - --GWM Dec 2020. - NOTE: uses (-,-,-,+) metric (same as ROOT convention) -*/ -#include "Vec4.h" - - -namespace Mask { - - Vec4::Vec4() { - for(auto& val: m_data) - val = 0.0; - for(auto& val: m_boost) - val = 0.0; - } - - Vec4::Vec4(double px, double py, double pz, double E) { - m_data[0] = px; - m_data[1] = py; - m_data[2] = pz; - m_data[3] = E; - CalcBoostToCM(); - } - - Vec4::~Vec4() {} - - void Vec4::SetVectorCartesian(double px, double py, double pz, double E) { - m_data[0] = px; - m_data[1] = py; - m_data[2] = pz; - m_data[3] = E; - - CalcBoostToCM(); - } - - void Vec4::SetVectorSpherical(double theta, double phi, double p, double E) { - m_data[0] = p*cos(phi)*sin(theta); - m_data[1] = p*sin(phi)*sin(theta); - m_data[2] = p*cos(theta); - m_data[3] = E; - CalcBoostToCM(); - } - - void Vec4::CalcBoostToCM() { - m_boost[0] = m_data[0]/m_data[3]; - m_boost[1] = m_data[1]/m_data[3]; - m_boost[2] = m_data[2]/m_data[3]; - } - - void Vec4::ApplyBoost(const double* beta) { - double beta2 = beta[0]*beta[0] + beta[1]*beta[1] + beta[2]*beta[2]; - double gamma = 1.0/std::sqrt(1.0 - beta2); - double bdotp = beta[0]*m_data[0] + beta[1]*m_data[1] + beta[2]*m_data[2]; - double gfactor = beta2>0.0 ? (gamma - 1.0)/beta2 : 0.0; - - SetVectorCartesian(GetPx()+gfactor*bdotp*beta[0]+gamma*beta[0]*GetE(), - GetPy()+gfactor*bdotp*beta[1]+gamma*beta[1]*GetE(), - GetPz()+gfactor*bdotp*beta[2]+gamma*beta[2]*GetE(), - gamma*(GetE() + bdotp)); - } - - double Vec4::Dot(const Vec4& rhs) const { - return GetE()*rhs.GetE() - GetPx()*rhs.GetPx() - GetPy()*rhs.GetPy() - GetPz()*rhs.GetPz(); - } - - Vec4 Vec4::Cross(const Vec4& rhs) const { - return Vec4(); - } - -} \ No newline at end of file diff --git a/src/Plotters/Python/.gitignore b/src/Plotters/Python/.gitignore deleted file mode 100644 index 231854d..0000000 --- a/src/Plotters/Python/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -__pycache__ - -!.gitignore \ No newline at end of file diff --git a/src/Plotters/Python/MaskFile.py b/src/Plotters/Python/MaskFile.py deleted file mode 100755 index 210d8f9..0000000 --- a/src/Plotters/Python/MaskFile.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 - -import numpy as np -import struct - -class MaskFileData : - def __init__(self, n): - self.Z = np.zeros(n, dtype=int) - self.A = np.zeros(n, dtype=int) - self.dFlag = np.zeros(n, dtype=bool) - self.E = np.zeros(n) - self.KE = np.zeros(n) - self.p = np.zeros(n) - self.theta = np.zeros(n) - self.phi = np.zeros(n) - -class MaskFile: - int_size = 4 - double_size = 8 - bool_size = 1 - - def __init__(self, filename=""): - self.eofFlag = False - self.openFlag = False - if filename != "" : - self.Open(filename) - - def Open(self, filename): - self.filename = filename - self.file = open(self.filename, mode="rb") - if self.file.closed : - self.openFlag = False - else: - self.openFlag = True - - def ReadHeader(self): - data = self.file.read(2*self.int_size) - - (self.nsamples, self.rxntype) = struct.unpack("ii", data) - self.datasize = (5*self.double_size+2*self.int_size+self.bool_size) - self.datastr = "=ii?ddddd" - - if self.rxntype == 0: - self.N_nuclei = 3 - elif self.rxntype == 1: - self.N_nuclei = 4 - elif self.rxntype == 2: - self.N_nuclei = 6 - elif self.rxntype == 3: - self.N_nuclei = 8 - - def ReadData(self): - data = MaskFileData(self.N_nuclei) - for i in range(self.N_nuclei): - buffer = self.file.read(self.datasize) - (data.Z[i], data.A[i], data.dFlag[i], data.E[i], data.KE[i], data.p[i], data.theta[i], data.phi[i]) = struct.unpack(self.datastr, buffer) - if buffer == "": - self.eofFlag = True - - return data - - def Close(self): - self.file.close() - -def main() : - file = MaskFile(filename="/data1/gwm17/mask_tests/7Bedp_870keV_beam_50CD2.mask") - file.ReadHeader() - print("samples: ", file.nsamples, "rxntype:", file.rxntype, "datasize:", file.datasize) - count=0 - for i in range(file.nsamples): - file.ReadData() - count += 1 - - print("count:",count) - print("eofFlag:",file.eofFlag) - - file.Close() - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/src/Plotters/Python/NucData.py b/src/Plotters/Python/NucData.py deleted file mode 100755 index 7b4200d..0000000 --- a/src/Plotters/Python/NucData.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 - -import numpy as np -import requests -import lxml.html as xhtml - - -class MassTable: - def __init__(self): - file = open("./etc/mass.txt","r") - self.mtable = {} - u2mev = 931.4940954 - me = 0.000548579909 #amu - self.etable = {} - - line = file.readline() - line = file.readline() - - for line in file: - entries = line.split() - n = entries[0] - z = entries[1] - a = entries[2] - element = entries[3] - massBig = float(entries[4]) - massSmall = float(entries[5]) - - key = '('+z+','+a+')' - value = ((massBig+massSmall*1e-6) - float(z)*me)*u2mev - self.mtable[key] = value - self.etable[key] = element - file.close() - - def GetMass(self, z, a): - key = '('+str(z)+','+str(a)+')' - if key in self.mtable: - return self.mtable[key] - else: - return 0 - - def GetSymbol(self, z, a): - key = '('+str(z)+','+str(a)+')' - if key in self.etable: - return str(a)+self.etable[key] - else: - return 'none' - -Masses = MassTable() - -def GetExcitations(symbol): - levels = np.array(np.empty(0)) - text = '' - - site = requests.get("https://www.nndc.bnl.gov/nudat2/getdatasetClassic.jsp?nucleus="+symbol+"&unc=nds") - contents = xhtml.fromstring(site.content) - tables = contents.xpath("//table") - rows = tables[2].xpath("./tr") - for row in rows[1:-2]: - entries = row.xpath("./td") - if len(entries) != 0: - entry = entries[0] - data = entry.xpath("./a") - if len(data) == 0: - text = entry.text - else: - text = data[0].text - text = text.replace('?', '') - text = text.replace('\xa0\xa0≈','') - levels = np.append(levels, float(text)/1000.0) - return levels diff --git a/src/Plotters/Python/Nucleus.py b/src/Plotters/Python/Nucleus.py deleted file mode 100755 index a77a087..0000000 --- a/src/Plotters/Python/Nucleus.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -import numpy as np -from NucData import Masses - -class Nucleus: - deg2rad = np.pi/180.0 - def __init__(self, Z=0, A=0): - self.Z = Z - self.A = A - if Z != 0 and A != 0: - self.gsMass = Masses.GetMass(self.Z, self.A) - self.vec4 = np.zeros(4) - self.symbol = Masses.GetSymbol(self.Z, self.A) - self.vec4[3] = self.gsMass - - def SetIsotope(self, Z, A): - self.gsMass = Masses.GetMass(Z, A) - self.symbol = Masses.GetSymbol(Z, A) - self.Z = Z - self.A = A - self.vec4 = np.zeros(4) - self.vec4[3] = self.gsMass - - def SetVectorCart(self, px, py, pz, E): - self.vec4[0] = px - self.vec4[1] = py - self.vec4[2] = pz - self.vec4[3] = E - - def SetVectorSpher(self, theta, phi, p, E): - self.vec4[0] = p*np.sin(theta)*np.cos(phi) - self.vec4[1] = p*np.sin(theta)*np.sin(phi) - self.vec4[2] = p*np.cos(theta) - self.vec4[3] = E - - def __add__(self, other): - vec4 = self.vec4 + other.vec4 - newNuc = Nucleus(self.Z + other.Z, self.A + other.A) - newNuc.SetVectorCart(vec4[0], vec4[1], vec4[2], vec4[3]) - return newNuc - - def __sub__(self, other): - vec4 = self.vec4 - other.vec4 - newNuc = Nucleus(self.Z - other.Z, self.A - other.A) - newNuc.SetVectorCart(vec4[0], vec4[1], vec4[2], vec4[3]) - return newNuc - - def __str__(self): - return "Nucleus({0},{1}) with 4-vector({2})".format(self.Z, self.A, self.vec4) - - def GetP(self): - return np.sqrt(self.vec4[0]**2.0 + self.vec4[1]**2.0 + self.vec4[2]**2.0) - - def GetInvMass(self): - return np.sqrt(self.vec4[3]**2.0 - self.GetP()**2.0) - - def GetKE(self): - return self.vec4[3] - self.GetInvMass() - - def GetTheta(self): - return np.arccos(self.vec4[2]/self.GetP()) - - def GetPhi(self): - result = np.arctan2(self.vec4[1], self.vec4[0]) - if result < 0.0: - result += 2.0*np.pi - return result - - def GetExcitation(self): - return self.GetInvMass() - self.gsMass - - def GetBoostToCMFrame(self): - boost_vec = np.zeros(3) - boost_vec[0] = self.vec4[0]/self.vec4[3] - boost_vec[1] = self.vec4[1]/self.vec4[3] - boost_vec[2] = self.vec4[2]/self.vec4[3] - return boost_vec - - def ApplyBoost(self, boost_vec): - beta2 = np.linalg.norm(boost_vec)**2.0 - gamma = 1.0/np.sqrt(1.0 - beta2) - bdotp = boost_vec[0]*self.vec4[0] + boost_vec[1]*self.vec4[1] + boost_vec[2]*self.vec4[2] - gfactor = (gamma-1.0)/beta2 if beta2 > 0.0 else 0.0 - - px = self.vec4[0]+gfactor*bdotp*boost_vec[0]+gamma*boost_vec[0]*self.vec4[3] - py = self.vec4[1]+gfactor*bdotp*boost_vec[1]+gamma*boost_vec[1]*self.vec4[3] - pz = self.vec4[2]+gfactor*bdotp*boost_vec[2]+gamma*boost_vec[2]*self.vec4[3] - E = gamma*(self.vec4[3] + bdotp) - - self.SetVectorCart(px, py, pz, E); - - -def main(): - nuc = Nucleus(1,1) - print("First",nuc) - nuc2 = Nucleus(2,4) - print("Second", nuc2) - result = nuc + nuc2 - print("Addition", result) - result2 = nuc2 - nuc - print("Subtraction", result2) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/src/Plotters/Python/PyPlotter.py b/src/Plotters/Python/PyPlotter.py deleted file mode 100755 index deb7042..0000000 --- a/src/Plotters/Python/PyPlotter.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 - -import numpy as np -import matplotlib.pyplot as plt -from Nucleus import Nucleus -from MaskFile import MaskFile, MaskFileData -from NucData import Masses -import pickle -import sys - -def PlotData(inputname, outputname): - rad2deg = 180.0/np.pi - - datafile = MaskFile(inputname) - datafile.ReadHeader() - - print("MaskFile opened -- rxntype:", datafile.rxntype, "number of samples:", datafile.nsamples) - - data = MaskFileData(datafile.N_nuclei) - - ke = np.zeros((datafile.N_nuclei, datafile.nsamples)) - ke_d = np.zeros((datafile.N_nuclei, datafile.nsamples)) - theta = np.zeros((datafile.N_nuclei, datafile.nsamples)) - theta_d = np.zeros((datafile.N_nuclei, datafile.nsamples)) - phi = np.zeros((datafile.N_nuclei, datafile.nsamples)) - phi_d = np.zeros((datafile.N_nuclei, datafile.nsamples)) - detect_mask = np.ones((datafile.N_nuclei, datafile.nsamples), dtype=bool) - names = [] - for i in range(datafile.N_nuclei): - names.append(" ") - - nuc = Nucleus() - - for i in range(datafile.nsamples): - data = datafile.ReadData() - - if i == 0: - for j in range(datafile.N_nuclei): - names[j] = Masses.GetSymbol(data.Z[j], data.A[j]) - - for j in range(datafile.N_nuclei): - nuc.SetIsotope(data.Z[j], data.A[j]) - nuc.SetVectorSpher(data.theta[j], data.phi[j], data.p[j], data.E[j]) - - ke[j][i] = nuc.GetKE() - theta[j][i] = data.theta[j]*rad2deg - phi[j][i] = data.phi[j]*rad2deg - if data.dFlag[j] == True: - ke_d[j][i] = data.KE[j] - theta_d[j][i] = data.theta[j]*rad2deg - phi_d[j][i] = data.phi[j]*rad2deg - else: - detect_mask[j][i] = False - - datafile.Close() - - #Remove empty values from detection arrays - final_theta_d = theta_d[detect_mask] - final_phi_d = phi_d[detect_mask] - final_ke_d = ke_d[detect_mask] - - #figs = {} - #axes = {} - - ''' - for i in range(len(names)): - figs[i], axes[i] = plt.subplots(2,2) - ''' - fig, axes = plt.subplots(len(names)-1,4) - fig.set_size_inches(12, 12) - - for i in range(1, len(names)): - ''' - axes[i][0][0].plot(theta[i], ke[i], marker=',', linestyle='None') - axes[i][0][0].set_title(names[i]+" KE vs. Theta") - axes[i][0][0].set_xlabel(r"$\theta$ (degrees)") - axes[i][0][0].set_ylabel("KE (MeV)") - - axes[i][0][1].plot(phi[i], ke[i], marker=",", linestyle='None') - axes[i][0][1].set_title(names[i]+" KE vs. Phi") - axes[i][0][1].set_xlabel(r"$\phi$ (degrees)") - axes[i][0][1].set_ylabel("KE (MeV)") - - axes[i][1][0].plot(theta_d[i], ke_d[i], marker=',', linestyle='None') - axes[i][1][0].set_title(names[i]+" KE vs. Theta -- Detected") - axes[i][1][0].set_xlabel(r"$\theta$ (degrees)") - axes[i][1][0].set_ylabel("KE (MeV)") - - axes[i][1][1].plot(phi_d[i], ke_d[i], marker=",", linestyle='None') - axes[i][1][1].set_title(names[i]+" KE vs. Phi -- Detected") - axes[i][1][1].set_xlabel(r"$\phi$ (degrees)") - axes[i][1][1].set_ylabel("KE (MeV)") - ''' - - axes[i-1][0].plot(theta[i], ke[i], marker=',', linestyle='None') - axes[i-1][0].set_title(names[i]+" KE vs. Theta") - axes[i-1][0].set_xlabel(r"$\theta$ (degrees)") - axes[i-1][0].set_ylabel("KE (MeV)") - - axes[i-1][1].plot(phi[i], ke[i], marker=",", linestyle='None') - axes[i-1][1].set_title(names[i]+" KE vs. Phi") - axes[i-1][1].set_xlabel(r"$\phi$ (degrees)") - axes[i-1][1].set_ylabel("KE (MeV)") - - axes[i-1][2].plot(theta_d[i], ke_d[i], marker=',', linestyle='None') - axes[i-1][2].set_title(names[i]+" KE vs. Theta -- Detected") - axes[i-1][2].set_xlabel(r"$\theta$ (degrees)") - axes[i-1][2].set_ylabel("KE (MeV)") - - axes[i-1][3].plot(phi_d[i], ke_d[i], marker=",", linestyle='None') - axes[i-1][3].set_title(names[i]+" KE vs. Phi -- Detected") - axes[i-1][3].set_xlabel(r"$\phi$ (degrees)") - axes[i-1][3].set_ylabel("KE (MeV)") - - plt.tight_layout() - plt.show(block=True) - - print("Writing figure to file:", outputname) - with open(outputname, "wb") as outfile: - pickle.dump(fig, outfile) - outfile.close() - - print("Finished.") - -def main(): - if len(sys.argv) == 3: - PlotData(sys.argv[1], sys.argv[2]) - else: - print("Unable to run PyPlotter, incorrect number of arguments! Need an input datafile name, and an output plot file name") - -if __name__ == '__main__': - main() - - - diff --git a/src/Plotters/Python/ViewPyPlots.py b/src/Plotters/Python/ViewPyPlots.py deleted file mode 100755 index 3ed324d..0000000 --- a/src/Plotters/Python/ViewPyPlots.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -import matplotlib.pyplot as plt -import numpy as np -import pickle -import sys - -def SetManager(figure): - dummy = plt.figure() - manager = dummy.canvas.manager - manager.canvas.figure = figure - figure.set_canvas(manager.canvas) - -def ViewPyPlots(filename): - - figure = pickle.load(open(filename, "rb")) - SetManager(figure) - - figure.set_size_inches(12, 12) - plt.tight_layout() - - plt.show(block=True) - - -def main(): - if len(sys.argv) == 2: - ViewPyPlots(sys.argv[1]) - else: - print("Unable to run ViewPyPlots, incorrect number of commandline arguments -- requires an input pickle file") - -if __name__ == '__main__': - main() \ No newline at end of file From 0b7b06e4f1d9c300e308b001ebc76fc30f28a3b2 Mon Sep 17 00:00:00 2001 From: gwm17 Date: Thu, 18 Aug 2022 10:32:48 -0400 Subject: [PATCH 4/8] Update project structure. Tighten up code, improve syntax, enforce style. Still bugged, but now working from proper environment. Switch back to ROOT as file I/O and data management --- CMakeLists.txt | 4 +- include/AnasenEfficiency.h | 69 --- include/AngularDistribution.h | 34 -- include/DecaySystem.h | 41 -- include/MaskApp.h | 38 -- include/Nucleus.h | 64 --- include/OneStepSystem.h | 34 -- include/QQQDetector.h | 57 -- include/RandomGenerator.h | 25 - include/Reaction.h | 78 --- include/RootPlotter.h | 52 -- include/SabreDetector.h | 177 ------ include/SabreEfficiency.h | 51 -- include/Stopwatch.h | 30 -- include/StripDetector.h | 76 --- include/ThreeStepSystem.h | 50 -- include/TwoStepSystem.h | 45 -- input.txt | 18 +- .../Detectors}/AnasenDeadChannelMap.h | 2 +- src/Detectors/AnasenEfficiency.cpp | 504 +++++++++--------- src/Detectors/AnasenEfficiency.h | 64 +++ src/Detectors/CMakeLists.txt | 13 +- .../Detectors}/DetectorEfficiency.h | 17 +- src/Detectors/QQQDetector.cpp | 163 +++--- src/Detectors/QQQDetector.h | 65 +++ .../Detectors}/SabreDeadChannelMap.h | 0 src/Detectors/SabreDetector.cpp | 242 +++++---- src/Detectors/SabreDetector.h | 189 +++++++ src/Detectors/SabreEfficiency.cpp | 358 +++++++------ src/Detectors/SabreEfficiency.h | 51 ++ src/Detectors/StripDetector.cpp | 154 +++--- src/Detectors/StripDetector.h | 82 +++ .../{DetectorEfficiency.cpp => main.cpp} | 20 +- src/Mask/AngularDistribution.cpp | 91 ++-- src/Mask/AngularDistribution.h | 35 ++ src/Mask/CMakeLists.txt | 42 +- src/Mask/DecaySystem.cpp | 77 +-- src/Mask/DecaySystem.h | 36 ++ {include => src/Mask}/KinematicsExceptions.h | 0 src/Mask/LayeredTarget.cpp | 135 +++-- {include => src/Mask}/LayeredTarget.h | 28 +- src/Mask/LegendrePoly.cpp | 25 +- {include => src/Mask}/LegendrePoly.h | 2 +- src/Mask/LinkDef_Nucleus.h | 7 + src/Mask/MaskApp.cpp | 87 +-- src/Mask/MaskApp.h | 37 ++ src/Mask/MassLookup.cpp | 50 +- {include => src/Mask}/MassLookup.h | 27 +- src/Mask/Nucleus.cpp | 17 + src/Mask/Nucleus.h | 59 ++ src/Mask/OneStepSystem.cpp | 84 +-- src/Mask/OneStepSystem.h | 30 ++ src/Mask/RandomGenerator.cpp | 8 +- src/Mask/RandomGenerator.h | 24 + src/Mask/Reaction.cpp | 295 +++++----- src/Mask/Reaction.h | 74 +++ src/Mask/ReactionSystem.cpp | 12 +- {include => src/Mask}/ReactionSystem.h | 39 +- {include => src/Mask}/RxnType.h | 0 src/Mask/Stopwatch.cpp | 41 +- src/Mask/Stopwatch.h | 32 ++ src/Mask/Target.cpp | 57 +- {include => src/Mask}/Target.h | 25 +- src/Mask/ThreeStepSystem.cpp | 150 +++--- src/Mask/ThreeStepSystem.h | 42 ++ src/Mask/TwoStepSystem.cpp | 121 +++-- src/Mask/TwoStepSystem.h | 40 ++ src/MaskApp/CMakeLists.txt | 2 +- src/MaskApp/main.cpp | 25 +- src/Plotters/{ROOT => }/CMakeLists.txt | 7 +- src/Plotters/ROOT/RootPlotter.cpp | 323 ----------- src/Plotters/RootPlotter.cpp | 139 +++++ src/Plotters/RootPlotter.h | 34 ++ src/Plotters/main.cpp | 14 + 74 files changed, 2644 insertions(+), 2596 deletions(-) delete mode 100644 include/AnasenEfficiency.h delete mode 100644 include/AngularDistribution.h delete mode 100644 include/DecaySystem.h delete mode 100644 include/MaskApp.h delete mode 100644 include/Nucleus.h delete mode 100644 include/OneStepSystem.h delete mode 100644 include/QQQDetector.h delete mode 100644 include/RandomGenerator.h delete mode 100644 include/Reaction.h delete mode 100644 include/RootPlotter.h delete mode 100644 include/SabreDetector.h delete mode 100644 include/SabreEfficiency.h delete mode 100644 include/Stopwatch.h delete mode 100644 include/StripDetector.h delete mode 100644 include/ThreeStepSystem.h delete mode 100644 include/TwoStepSystem.h rename {include => src/Detectors}/AnasenDeadChannelMap.h (94%) create mode 100644 src/Detectors/AnasenEfficiency.h rename {include => src/Detectors}/DetectorEfficiency.h (62%) create mode 100644 src/Detectors/QQQDetector.h rename {include => src/Detectors}/SabreDeadChannelMap.h (100%) create mode 100644 src/Detectors/SabreDetector.h create mode 100644 src/Detectors/SabreEfficiency.h create mode 100644 src/Detectors/StripDetector.h rename src/Detectors/{DetectorEfficiency.cpp => main.cpp} (71%) create mode 100644 src/Mask/AngularDistribution.h create mode 100644 src/Mask/DecaySystem.h rename {include => src/Mask}/KinematicsExceptions.h (100%) rename {include => src/Mask}/LayeredTarget.h (52%) rename {include => src/Mask}/LegendrePoly.h (69%) create mode 100644 src/Mask/LinkDef_Nucleus.h create mode 100644 src/Mask/MaskApp.h rename {include => src/Mask}/MassLookup.h (63%) create mode 100644 src/Mask/Nucleus.cpp create mode 100644 src/Mask/Nucleus.h create mode 100644 src/Mask/OneStepSystem.h create mode 100644 src/Mask/RandomGenerator.h create mode 100644 src/Mask/Reaction.h rename {include => src/Mask}/ReactionSystem.h (62%) rename {include => src/Mask}/RxnType.h (100%) create mode 100644 src/Mask/Stopwatch.h rename {include => src/Mask}/Target.h (59%) create mode 100644 src/Mask/ThreeStepSystem.h create mode 100644 src/Mask/TwoStepSystem.h rename src/Plotters/{ROOT => }/CMakeLists.txt (66%) delete mode 100644 src/Plotters/ROOT/RootPlotter.cpp create mode 100644 src/Plotters/RootPlotter.cpp create mode 100644 src/Plotters/RootPlotter.h create mode 100644 src/Plotters/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a507986..289801a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,10 @@ set(MASK_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) set(CMAKE_CXX_STANDARD 17) +find_package(ROOT REQUIRED COMPONENTS GenVector) + add_subdirectory(src/vendor/catima) add_subdirectory(src/Mask) add_subdirectory(src/MaskApp) add_subdirectory(src/Detectors) -add_subdirectory(src/Plotters/ROOT) \ No newline at end of file +add_subdirectory(src/Plotters) \ No newline at end of file diff --git a/include/AnasenEfficiency.h b/include/AnasenEfficiency.h deleted file mode 100644 index 3977fab..0000000 --- a/include/AnasenEfficiency.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef ANASEN_EFFICIENCY_H -#define ANASEN_EFFICIENCY_H - -#include - -#include "DetectorEfficiency.h" -#include "StripDetector.h" -#include "QQQDetector.h" -#include "Target.h" -#include "Nucleus.h" -#include "MaskFile.h" -#include "AnasenDeadChannelMap.h" - -struct DetectorResult { - bool detectFlag = false; - Mask::Vec3 direction; - double energy_deposited = 0.0; - std::string det_name = ""; -}; - -class AnasenEfficiency : public DetectorEfficiency { -public: - AnasenEfficiency(); - ~AnasenEfficiency(); - void CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) override; - void DrawDetectorSystem(const std::string& filename) override; - double RunConsistencyCheck() override; - inline void SetDeadChannelMap(const std::string& filename) { dmap.LoadMapfile(filename); } - -private: - DetectorResult IsRing1(Mask::Nucleus& nucleus); - DetectorResult IsRing2(Mask::Nucleus& nucleus); - DetectorResult IsQQQ(Mask::Nucleus& nucleus); - DetectorResult IsAnasen(Mask::Nucleus& nucleus); - void CountCoincidences(const Mask::MaskFileData& data, std::vector& counts, Mask::RxnType rxn_type); - - std::vector m_Ring1, m_Ring2; - std::vector m_forwardQQQs; - std::vector m_backwardQQQs; - - Mask::Target det_silicon; - - AnasenDeadChannelMap dmap; - - /**** ANASEN geometry constants *****/ - const int n_sx3_per_ring = 12; - const int n_qqq = 4; - const double sx3_length = 0.075; - const double sx3_width = 0.04; - const double barrel_gap = 0.0254; - const double sx3_frame = 0.049; //0.049 is base gap due to frames - const double ring1_z = sx3_length/2.0 + sx3_frame + barrel_gap/2.0; - const double ring2_z = (-1.0)*(barrel_gap/2.0 + sx3_length/2.0); - const double qqq_nom_z = 0.0125 + sx3_length + sx3_frame + barrel_gap/2.0; - const double qqq_rinner = 0.0501; - const double qqq_router = 0.0990; - const double qqq_deltaphi = 1.52119; - const double qqq_z[4] = {qqq_nom_z, qqq_nom_z, qqq_nom_z, qqq_nom_z}; - const double qqq_phi[4] = {5.49779, 0.785398, 2.35619, 3.92699}; - const double ring_rho[12] = {0.0890601, 0.0889871, 0.0890354, 0.0890247, 0.0890354, 0.0890354, 0.0890247, 0.0890354, 0.0890354, 0.0890247, 0.0890354, 0.0890354}; - const double ring_phi[12] = {4.97426, 5.49739, 6.02132, 0.261868, 0.785398, 1.30893, 1.83266, 2.35619, 2.87972, 3.40346, 3.92699, 4.45052}; - /*************************/ - - static constexpr double threshold = 0.6; //MeV - static constexpr double deg2rad = M_PI/180.0; - static constexpr double si_thickness = 1000 * 1e-4 * 2.3926 * 1e6; //thickness in um -> eff thickness in ug/cm^2 for detector -}; - -#endif \ No newline at end of file diff --git a/include/AngularDistribution.h b/include/AngularDistribution.h deleted file mode 100644 index 0cae6da..0000000 --- a/include/AngularDistribution.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ANGULARDISTRIBUTION_H -#define ANGULARDISTRIBUTION_H - -#include -#include -#include - -namespace Mask { - - class AngularDistribution { - public: - AngularDistribution(); - AngularDistribution(const std::string& file); - ~AngularDistribution(); - void ReadDistributionFile(const std::string& file); - double GetRandomCosTheta(); - inline int GetL() { return L; } - inline double GetBranchingRatio() { return branchingRatio; } - - private: - inline bool IsIsotropic() { return isoFlag; } - - std::uniform_real_distribution uniform_cosine_dist; - std::uniform_real_distribution uniform_prob_dist; - - double branchingRatio; - int L; - std::vector constants; - bool isoFlag; - }; - -} - -#endif \ No newline at end of file diff --git a/include/DecaySystem.h b/include/DecaySystem.h deleted file mode 100644 index 47509dc..0000000 --- a/include/DecaySystem.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef DECAYSYSTEM_H -#define DECAYSYSTEM_H - -#include "ReactionSystem.h" -#include "AngularDistribution.h" - -namespace Mask { - - class DecaySystem: public ReactionSystem { - public: - DecaySystem(); - DecaySystem(std::vector& z, std::vector& a); - ~DecaySystem(); - - bool SetNuclei(std::vector& z, std::vector& a) override; - void RunSystem() override; - const std::vector& GetNuclei() override; - - inline void SetDecay1Distribution(const std::string& filename) { decay1dist.ReadDistributionFile(filename); } - - inline const Nucleus& GetTarget() const { return step1.GetTarget(); } - inline const Nucleus& GetEjectile() const { return step1.GetEjectile(); } - inline const Nucleus& GetResidual() const { return step1.GetResidual(); } - - inline int GetDecay1AngularMomentum() { return decay1dist.GetL(); } - inline double GetDecay1BranchingRatio() { return decay1dist.GetBranchingRatio(); } - - - private: - void LinkTarget() override; - void SetSystemEquation() override; - - Reaction step1; - - AngularDistribution decay1dist; - - }; - -} - -#endif \ No newline at end of file diff --git a/include/MaskApp.h b/include/MaskApp.h deleted file mode 100644 index 39ec160..0000000 --- a/include/MaskApp.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MASKAPP_H -#define MASKAPP_H - -#include "ReactionSystem.h" -#include "DecaySystem.h" -#include "OneStepSystem.h" -#include "TwoStepSystem.h" -#include "ThreeStepSystem.h" -#include "RxnType.h" - -namespace Mask { - - class MaskApp { - public: - MaskApp(); - ~MaskApp(); - bool LoadConfig(const std::string& filename); - bool SaveConfig(const std::string& filename); - inline int GetNumberOfSamples() const { return m_nsamples; }; - inline const std::string GetSystemName() const { return m_sys == nullptr ? "" : m_sys->GetSystemEquation(); }; - inline const std::string GetOutputName() const { return m_outfile_name; }; - inline const RxnType GetReactionType() const { return m_rxn_type; }; - void Run(); - - private: - - ReactionSystem* m_sys; - - std::string m_outfile_name; - - RxnType m_rxn_type; - int m_nsamples; - - }; - -} - -#endif diff --git a/include/Nucleus.h b/include/Nucleus.h deleted file mode 100644 index e1dfc92..0000000 --- a/include/Nucleus.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Nucleus.h - Nucleus is a derived class of Vec4. A nucleus is the kinematics is essentially a 4 vector with the - additional properties of the number of total nucleons (A), the number of protons (Z), a ground state mass, - an exctitation energy, and an isotopic symbol. - - --GWM Jan 2021 -*/ -#ifndef NUCLEUS_H -#define NUCLEUS_H - -#include "Vec4.h" -#include - -namespace Mask { - -class Nucleus : public Vec4 { -public: - Nucleus(); - Nucleus(int Z, int A); - Nucleus(int Z, int A, double px, double py, double pz, double E); - virtual ~Nucleus() override; - bool SetIsotope(int Z, int A); - inline void SetThetaCM(double tcm) { m_theta_cm = tcm; }; //save theta in rxn CM frame - inline int GetZ() const { return m_z; }; - inline int GetA() const { return m_a; }; - inline double GetExcitationEnergy() const { return GetInvMass() - m_gs_mass; }; - inline double GetGroundStateMass() const { return m_gs_mass; }; - inline const char* GetIsotopicSymbol() const { return m_symbol.c_str(); }; - inline double GetThetaCM() const { return m_theta_cm; }; - inline void SetDetected() { m_detectFlag = true; }; - inline void SetNotDetected() { m_detectFlag = false; }; - inline bool IsDetected() const { return m_detectFlag; }; - - inline Nucleus& operator=(const Nucleus& rhs) { - SetIsotope(rhs.GetZ(), rhs.GetA()); - SetVectorCartesian(rhs.GetPx(), rhs.GetPy(), rhs.GetPz(), rhs.GetE()); - SetThetaCM(rhs.GetThetaCM()); - return *this; - }; - - //Conservation of nucleons and momentum - inline Nucleus operator+(const Nucleus& daughter) { - return Nucleus(GetZ()+daughter.GetZ(), GetA()+daughter.GetA(), GetPx()+daughter.GetPx(), GetPy()+daughter.GetPy(), GetPz()+daughter.GetPz(), GetE()+daughter.GetE()); - }; - inline Nucleus operator-(const Nucleus& daughter) { - return (GetZ() - daughter.GetZ()) <= 0 || (GetA() - daughter.GetA()) <= 0 ? Nucleus() : - Nucleus(GetZ()-daughter.GetZ(), GetA() - daughter.GetA(), GetPx()-daughter.GetPx(), GetPy()-daughter.GetPy(), GetPz()-daughter.GetPz(), GetE()-daughter.GetE()); - - }; - -private: - int m_z, m_a; - double m_gs_mass; - double m_theta_cm; - std::string m_symbol; - - bool m_detectFlag; - -}; - -}; - -#endif diff --git a/include/OneStepSystem.h b/include/OneStepSystem.h deleted file mode 100644 index d2e35c9..0000000 --- a/include/OneStepSystem.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ONESTEPSYSTEM_H -#define ONESTEPSYSTEM_H - -#include "ReactionSystem.h" - -namespace Mask { - - class OneStepSystem: public ReactionSystem { - public: - OneStepSystem(); - OneStepSystem(std::vector& z, std::vector& a); - ~OneStepSystem(); - - bool SetNuclei(std::vector& z, std::vector& a) override; - void RunSystem() override; - const std::vector& GetNuclei() override; - - inline void SetReactionThetaType(int type) { step1.SetEjectileThetaType(type); }; - inline const Nucleus& GetTarget() const { return step1.GetTarget(); }; - inline const Nucleus& GetProjectile() const { return step1.GetProjectile(); }; - inline const Nucleus& GetEjectile() const { return step1.GetEjectile(); }; - inline const Nucleus& GetResidual() const { return step1.GetResidual(); }; - - private: - void LinkTarget() override; - void SetSystemEquation() override; - - Reaction step1; - - }; - -} - -#endif \ No newline at end of file diff --git a/include/QQQDetector.h b/include/QQQDetector.h deleted file mode 100644 index 7889a70..0000000 --- a/include/QQQDetector.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - QQQDetector.h - Class implementing geometry for QQQDetector where the detector is perpendicular to the beam axis. - Detector is first generated centered on the x-axis (phi=0) - - Coordinate convention : +z is downstream, -z is upstream. +y is vertically down in the lab. -*/ -#ifndef QQQDETECTOR_H -#define QQQDETECTOR_H - -#include -#include -#include - -#include "Vec3.h" -#include "Rotation.h" -#include "RandomGenerator.h" - -class QQQDetector { -public: - QQQDetector(double R_in, double R_out, double deltaPhi, double phiCentral, double z, double x=0, double y=0); - ~QQQDetector(); - inline Mask::Vec3 GetRingCoordinates(int ringch, int corner) { return m_ringCoords[ringch][corner]; } - inline Mask::Vec3 GetWedgeCoordinates(int wedgech, int corner) { return m_wedgeCoords[wedgech][corner]; } - inline Mask::Vec3 GetNorm() { return m_norm; } - Mask::Vec3 GetTrajectoryCoordinates(double theta, double phi); - std::pair GetTrajectoryRingWedge(double theta, double phi); - Mask::Vec3 GetHitCoordinates(int ringch, int wedgech); - inline void TurnOnRandomizedCoordinates() { rndmFlag = true; } - inline void TurnOffRandomizedCoordinates() { rndmFlag = false; } - - inline int GetNumberOfRings() { return nrings; } - inline int GetNumberOfWedges() { return nwedges; } - -private: - - inline bool CheckChannel(int ch) { return (ch >=0 && ch < nrings); } - inline bool CheckCorner(int corner) { return (corner >=0 && corner < 4); } - - void CalculateCorners(); - Mask::Vec3 TransformCoordinates(Mask::Vec3& vector) { return m_ZRot*vector + m_translation; } - - double m_Rinner, m_Router, m_deltaR, m_deltaPhi, m_deltaPhi_per_wedge, m_phiCentral; - std::vector> m_ringCoords, m_wedgeCoords; - Mask::Vec3 m_translation; - Mask::Vec3 m_norm; - Mask::ZRotation m_ZRot; - - std::uniform_real_distribution m_uniform_fraction; - bool rndmFlag; - - static constexpr int nrings = 16; - static constexpr int nwedges = 16; - static constexpr double deg2rad = M_PI/180.0; -}; - -#endif \ No newline at end of file diff --git a/include/RandomGenerator.h b/include/RandomGenerator.h deleted file mode 100644 index b5cfdc8..0000000 --- a/include/RandomGenerator.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef RANDOMGENERATOR_H -#define RANDOMGENERATOR_H - -#include - -namespace Mask { - - class RandomGenerator { - public: - ~RandomGenerator(); - inline std::mt19937& GetGenerator() { return rng; } - - inline static RandomGenerator& GetInstance() { - static RandomGenerator s_instance; - return s_instance; - } - - private: - RandomGenerator(); - std::mt19937 rng; - }; - -} - -#endif \ No newline at end of file diff --git a/include/Reaction.h b/include/Reaction.h deleted file mode 100644 index 396c935..0000000 --- a/include/Reaction.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Reaction.h - Reaction is a class which implements either a decay or scattering reaction. As such it requires either - 3 (decay) or 4 (scattering) nuclei to perform any calcualtions. I also links together the target, which provides - energy loss calculations, with the kinematics. Note that Reaction does not own the LayeredTarget. - - --GWM Jan. 2021 -*/ -#ifndef REACTION_H -#define REACTION_H - -#include "Nucleus.h" -#include "LayeredTarget.h" - -namespace Mask { - - class Reaction { - public: - Reaction(); - Reaction(int zt, int at, int zp, int ap, int ze, int ae); - ~Reaction(); - bool Calculate(); - void SetNuclei(int zt, int at, int zp, int ap, int ze, int ae); - void SetNuclei(const Nucleus* nucs); - void SetBeamKE(double bke); - void SetEjectileThetaType(int type); - - inline void SetLayeredTarget(LayeredTarget* targ) { target = targ; }; - inline void SetPolarRxnAngle(double theta) { m_theta = theta; }; - inline void SetAzimRxnAngle(double phi) { m_phi = phi; }; - inline void SetExcitation(double ex) { m_ex = ex; }; - inline void SetTarget(const Nucleus& nuc) { reactants[0] = nuc; }; - inline void SetTarget(int z, int a) { reactants[0] = Nucleus(z, a); }; - inline void SetProjectile(const Nucleus& nuc) { reactants[1] = nuc; }; - inline void SetProjectile(int z, int a) { reactants[1] = Nucleus(z, a); }; - inline void SetEjectile(const Nucleus& nuc) { reactants[2] = nuc; }; - inline void SetEjectile(int z, int a) { reactants[2] = Nucleus(z, a); }; - inline void SetResidual(const Nucleus& nuc) { reactants[3] = nuc; }; - inline void SetResidual(int z, int a) { reactants[3] = Nucleus(z, a); }; - inline void SetRxnLayer(int layer) { rxnLayer = layer; }; - inline void TurnOffResidualEloss() { resid_elossFlag = false; }; - inline void TurnOnResidualEloss() { resid_elossFlag = true; }; - inline bool IsDecay() { return decayFlag; }; - inline const Nucleus* GetNuclei() const { return &(reactants[0]); }; - inline const Nucleus& GetProjectile() const { return reactants[1]; }; - inline const Nucleus& GetTarget() const { return reactants[0]; }; - inline const Nucleus& GetEjectile() const { return reactants[2]; }; - inline const Nucleus& GetResidual() const { return reactants[3]; }; - inline int GetRxnLayer() { return rxnLayer; }; - inline void ResetTarget() { reactants[0].SetVectorCartesian(0,0,0, reactants[0].GetGroundStateMass()); } - inline void ResetProjectile() { reactants[1].SetVectorCartesian(0,0,0, reactants[1].GetGroundStateMass()); } - inline void ResetEjectile() { reactants[2].SetVectorCartesian(0,0,0, reactants[2].GetGroundStateMass()); } - inline void ResetResidual() { reactants[3].SetVectorCartesian(0,0,0, reactants[3].GetGroundStateMass()); } - - private: - void CalculateDecay(); //target -> light_decay (eject) + heavy_decay(resid) - void CalculateReaction(); //target + project -> eject + resid - void CalculateReactionThetaLab(); - void CalculateReactionThetaCM(); - - Nucleus reactants[4]; //0=target, 1=projectile, 2=ejectile, 3=residual - LayeredTarget* target; //not owned by Reaction - - double m_bke, m_theta, m_phi, m_ex; - - int rxnLayer; - int m_eject_theta_type; - - bool decayFlag, nuc_initFlag, resid_elossFlag; - - static constexpr int lab = 0; - static constexpr int center_of_mass = 1; - - }; - -} - -#endif \ No newline at end of file diff --git a/include/RootPlotter.h b/include/RootPlotter.h deleted file mode 100644 index 31cb931..0000000 --- a/include/RootPlotter.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef ROOTPLOTTER_H -#define ROOTPLOTTER_H - -#include -#include - -#include "Nucleus.h" -#include "RxnType.h" -#include "MaskFile.h" - -#include -#include -#include -#include - -struct GraphData { - std::string name; - std::string title; - std::vector xvec; - std::vector yvec; - int color; -}; - -class RootPlotter { -public: - RootPlotter(); - ~RootPlotter(); - inline void ClearTable() { table->Clear(); }; - inline THashTable* GetTable() { - GenerateGraphs(); - return table; - }; - void FillData(const Mask::Nucleus& nuc, double detKE = 0.0, const std::string& modifier = ""); - void FillCorrelations(const Mask::MaskFileData& data, Mask::RxnType type); - void FillCorrelationsDetected(const Mask::MaskFileData& data, Mask::RxnType type); - -private: - THashTable* table; - - void GenerateGraphs(); - void MyFill(const std::string& name, const std::string& title, int bins, float min, float max, double val); - void MyFill(const std::string& name, const std::string& title, int binsx, float minx, float maxx, int binsy, float miny, float maxy, double valx, double valy); - void MyFill(const std::string& name, const std::string& title, double valx, double valy, int color); //TGraph - - std::vector garbage_collection; - std::vector graphs; - - static constexpr double rad2deg = 180.0/M_PI; - -}; - -#endif \ No newline at end of file diff --git a/include/SabreDetector.h b/include/SabreDetector.h deleted file mode 100644 index 9074b1d..0000000 --- a/include/SabreDetector.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - - Class which represents a single MMM detector in the SABRE array at FSU. Origial code by KGH, re-written by - GWM. - - Distances in meters, angles in radians. - - The channel arrays have four points, one for each corner. The corners are - as follows, as if looking BACK along beam (i.e. from the target's pov): - - 0---------------------1 - | | - | | x - | | <----- - | | | - | | | - 3---------------------2 y - (z is hence positive along beam direction) - - The channel numbers, also as looking back from target pov, are: - - >> rings are 0 -- 15 from inner to outer: - - 15 ------------------- - 14 ------------------- - 13 ------------------- - . - . - . - 2 ------------------- - 1 ------------------- - 0 ------------------- - - >> wedges are 0 -- 7 moving counterclockwise: - - 7 6 ... 1 0 - | | | | | | - | | | | | | - | | | | | | - | | | | | | - | | | | | | - | | | | | | - - - >> Note that the detector starts centered on the x-axis (central phi = 0) untilted, and then is rotated to wherever the frick - it is supposed to go; phi = 90 is centered on y axis, pointing down towards the bottom of the scattering chamber - - -- GWM, Dec 2020; based on the og code from kgh - -*/ - -#ifndef SABREDETECTOR_H -#define SABREDETECTOR_H - -#include -#include - -#include "Vec3.h" -#include "Rotation.h" - -class SabreDetector { -public: - - SabreDetector(); - SabreDetector(int detID, double Rin, double Rout, double deltaPhi_flat, double phiCentral, double tiltFromVert, double zdist, double xdist=0, double ydist=0); - ~SabreDetector(); - - /*Return coordinates of the corners of each ring/wedge in SABRE*/ - inline Mask::Vec3 GetRingFlatCoords(int ch, int corner) { return CheckRingLocation(ch, corner) ? m_ringCoords_flat[ch][corner] : Mask::Vec3(); }; - inline Mask::Vec3 GetWedgeFlatCoords(int ch, int corner) { return CheckWedgeLocation(ch, corner) ? m_wedgeCoords_flat[ch][corner] : Mask::Vec3(); }; - inline Mask::Vec3 GetRingTiltCoords(int ch, int corner) { return CheckRingLocation(ch, corner) ? m_ringCoords_tilt[ch][corner] : Mask::Vec3(); }; - inline Mask::Vec3 GetWedgeTiltCoords(int ch, int corner) { return CheckWedgeLocation(ch, corner) ? m_wedgeCoords_tilt[ch][corner] : Mask::Vec3(); }; - - Mask::Vec3 GetTrajectoryCoordinates(double theta, double phi); - std::pair GetTrajectoryRingWedge(double theta, double phi); - Mask::Vec3 GetHitCoordinates(int ringch, int wedgech); - - /*Basic getters*/ - inline int GetNumberOfWedges() { return m_nWedges; }; - inline int GetNumberOfRings() { return m_nRings; }; - inline double GetInnerRadius() { return m_Rinner; }; - inline double GetOuterRadius() { return m_Router; }; - inline double GetPhiCentral() { return m_phiCentral; }; - inline double GetTiltAngle() { return m_tilt; }; - inline Mask::Vec3 GetTranslation() { return m_translation; }; - inline Mask::Vec3 GetNormTilted() { return TransformToTiltedFrame(m_norm_flat); }; - int GetDetectorID() { return m_detectorID; } - - -private: - - /*Class constants*/ - static constexpr int m_nRings = 16; - static constexpr int m_nWedges = 8; - static constexpr double deg2rad = M_PI/180.0; - /*These are implicitly the width of the spacing between detector active strips*/ - static constexpr double POSITION_TOL = 0.0001; //0.1 mm position tolerance - static constexpr double ANGULAR_TOL = 0.1*M_PI/180.0; // 0.1 degree angular tolerance - - void CalculateCorners(); - - /*Performs the transformation to the tilted,rotated,translated frame of the SABRE detector*/ - inline Mask::Vec3 TransformToTiltedFrame(Mask::Vec3& vector) { return (m_ZRot*(m_YRot*vector)) + m_translation; }; - - /*Determine if a given channel/corner combo is valid*/ - inline bool CheckRingChannel(int ch) { return (ch=0) ? true : false; }; - inline bool CheckWedgeChannel(int ch) { return (ch=0) ? true : false; }; - inline bool CheckCorner(int corner) { return (corner < 4 && corner >=0) ? true : false; }; - inline bool CheckRingLocation(int ch, int corner) { return CheckRingChannel(ch) && CheckCorner(corner); }; - inline bool CheckWedgeLocation(int ch, int corner) { return CheckWedgeChannel(ch) && CheckCorner(corner); }; - - /* - For all of the calculations, need a limit precision to determine if values are actually equal or not - Here the approx. size of the strip spacing is used as the precision. - */ - inline bool CheckPositionEqual(double val1,double val2) { return fabs(val1-val2) > POSITION_TOL ? false : true; }; - inline bool CheckAngleEqual(double val1,double val2) { return fabs(val1-val2) > ANGULAR_TOL ? false : true; }; - - /*Determine if a hit is within the bulk detector*/ - inline bool IsInside(double r, double phi) { - double phi_1 = m_deltaPhi_flat/2.0; - double phi_2 = M_PI*2.0 - m_deltaPhi_flat/2.0; - return (((r > m_Rinner && r < m_Router) || CheckPositionEqual(r, m_Rinner) || CheckPositionEqual(r, m_Router)) && (phi > phi_2 || phi < phi_1 || CheckAngleEqual(phi, phi_1) || CheckAngleEqual(phi, phi_2))); - }; - - /* - For a given radius/phi are you inside of a given ring/wedge channel, - or are you on the spacing between these channels - */ - inline bool IsRing(double r, int ringch) { - double ringtop = m_Rinner + m_deltaR_flat_ring*(ringch + 1); - double ringbottom = m_Rinner + m_deltaR_flat_ring*(ringch); - return (r>ringbottom && rwedgebottom && phi> m_ringCoords_flat, m_wedgeCoords_flat; - std::vector> m_ringCoords_tilt, m_wedgeCoords_tilt; - -}; - - -#endif diff --git a/include/SabreEfficiency.h b/include/SabreEfficiency.h deleted file mode 100644 index 86a5dec..0000000 --- a/include/SabreEfficiency.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef SABREEFFICIENCY_H -#define SABREEFFICIENCY_H - -#include "MaskFile.h" -#include "DetectorEfficiency.h" -#include "SabreDetector.h" -#include "Target.h" -#include "SabreDeadChannelMap.h" -#include "Nucleus.h" - -class SabreEfficiency : public DetectorEfficiency { -public: - SabreEfficiency(); - ~SabreEfficiency(); - void SetDeadChannelMap(std::string& filename) { dmap.LoadMapfile(filename); }; - void CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) override; - void DrawDetectorSystem(const std::string& filename) override; - double RunConsistencyCheck() override; - -private: - std::pair IsSabre(Mask::Nucleus& nucleus); - void CountCoincidences(const Mask::MaskFileData& data, std::vector& counts, Mask::RxnType rxn_type); - - std::vector detectors; - - Mask::Target deadlayer; - Mask::Target sabre_eloss; - Mask::Target degrader; - SabreDeadChannelMap dmap; - - //Sabre constants - const double INNER_R = 0.0326; - const double OUTER_R = 0.1351; - const double TILT = 40.0; - const double DIST_2_TARG = -0.1245; - const double PHI_COVERAGE = 54.4; //delta phi for each det - const double PHI0 = 306.0; //center phi values for each det in array - const double PHI1 = 18.0; //# is equal to detID in channel map - const double PHI2 = 234.0; - const double PHI3 = 162.0; - const double PHI4 = 90.0; - const double DEG2RAD = M_PI/180.0; - static constexpr double DEADLAYER_THIN = 50 * 1e-7 * 2.3296 * 1e6; // ug/cm^2 (50 nm thick * density) - static constexpr double SABRE_THICKNESS = 500 * 1e-4 * 2.3926 * 1e6; // ug/cm^2 (500 um thick * density) - static constexpr double DEGRADER_THICKNESS = 70.0 * 1.0e-4 * 16.69 * 1e6; //tantalum degrader (70 um thick) - - const double ENERGY_THRESHOLD = 0.25; //in MeV - -}; - -#endif diff --git a/include/Stopwatch.h b/include/Stopwatch.h deleted file mode 100644 index af217c1..0000000 --- a/include/Stopwatch.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Stopwatch.h - Simple class designed to provide timing info on parts of the process. - Only for use in development. - - Written by G.W. McCann Oct. 2020 -*/ -#ifndef STOPWATCH_H -#define STOPWATCH_H - -#include - -class Stopwatch { - -public: - Stopwatch(); - ~Stopwatch(); - void Start(); - void Stop(); - double GetElapsedSeconds(); - double GetElapsedMilliseconds(); - -private: - using Time = std::chrono::high_resolution_clock::time_point; - using Clock = std::chrono::high_resolution_clock; - - Time start_time, stop_time; -}; - -#endif \ No newline at end of file diff --git a/include/StripDetector.h b/include/StripDetector.h deleted file mode 100644 index e415739..0000000 --- a/include/StripDetector.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef __STRIP_DETECTOR_H -#define __STRIP_DETECTOR_H - -// +z is along beam axis -// +y is vertically "downward" in the lab frame - -//angles must be in radians, but distances can be whatever -//PROVIDED all input distances are the same - -//Front strips from largest y to smallest y - -//Back strips from lowest z to highest z - -#include -#include -#include - -#include "Vec3.h" -#include "Rotation.h" -#include "RandomGenerator.h" - -struct StripHit -{ - int front_strip_index=-1; - int back_strip_index=-1; - double front_ratio=0.0; -}; - -class StripDetector { -public: - - StripDetector(int ns, double len, double wid, double cphi, double cz, double crho); - ~StripDetector(); - inline Mask::Vec3 GetFrontStripCoordinates(int stripch, int corner) { return front_strip_coords[stripch][corner]; } - inline Mask::Vec3 GetBackStripCoordinates(int stripch, int corner) { return back_strip_coords[stripch][corner]; } - inline Mask::Vec3 GetRotatedFrontStripCoordinates(int stripch, int corner) { return rotated_front_strip_coords[stripch][corner]; } - inline Mask::Vec3 GetRotatedBackStripCoordinates(int stripch, int corner) { return rotated_back_strip_coords[stripch][corner]; } - inline Mask::Vec3 GetNormRotated() { return zRot*m_norm_unrot; } - - inline void TurnOnRandomizedCoordinates() { rndmFlag = true; } - inline void TurnOffRandomizedCoordinates() { rndmFlag = false; } - - Mask::Vec3 GetHitCoordinates(int front_stripch, double front_strip_ratio); - StripHit GetChannelRatio(double theta, double phi); - -private: - inline bool ValidChannel(int f) { return ((f >= 0 && f < num_strips) ? true : false); }; - inline bool ValidRatio(double r) { return ((r >= -1 && r <= 1) ? true : false); }; - void CalculateCorners(); - - int num_strips; - static constexpr int num_corners = 4; - - double length; //common to all strips, hence total - double total_width; - double front_strip_width; //assuming equal widths - double back_strip_length; //assuming equal widths - - double center_phi; //assuming det centered above x-axis (corresponds to zero phi) - double center_z; - double center_rho; //perpendicular radius from axis - - std::vector> front_strip_coords, back_strip_coords; - std::vector> rotated_front_strip_coords, rotated_back_strip_coords; - - Mask::Vec3 m_norm_unrot; - - Mask::ZRotation zRot; - - std::uniform_real_distribution m_uniform_fraction; - - bool rndmFlag; - -}; - -#endif diff --git a/include/ThreeStepSystem.h b/include/ThreeStepSystem.h deleted file mode 100644 index 7093d75..0000000 --- a/include/ThreeStepSystem.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef THREESTEPSYSTEM_H -#define THREESTEPSYSTEM_H - -#include "ReactionSystem.h" -#include "AngularDistribution.h" - -namespace Mask { - - class ThreeStepSystem : public ReactionSystem { - public: - ThreeStepSystem(); - ThreeStepSystem(std::vector& z, std::vector& a); - ~ThreeStepSystem(); - bool SetNuclei(std::vector& z, std::vector& a) override; - void RunSystem() override; - const std::vector& GetNuclei() override; - - inline void SetDecay1Distribution(const std::string& filename) { decay1dist.ReadDistributionFile(filename); }; - inline void SetDecay2Distribution(const std::string& filename) { decay2dist.ReadDistributionFile(filename); }; - - inline void SetReactionThetaType(int type) { step1.SetEjectileThetaType(type); }; - inline const Nucleus& GetTarget() const { return step1.GetTarget(); }; - inline const Nucleus& GetProjectile() const { return step1.GetProjectile(); }; - inline const Nucleus& GetEjectile() const { return step1.GetEjectile(); }; - inline const Nucleus& GetResidual() const { return step1.GetResidual(); }; - inline const Nucleus& GetBreakup1() const { return step2.GetEjectile(); }; - inline const Nucleus& GetBreakup2() const { return step2.GetResidual(); }; - inline const Nucleus& GetBreakup3() const { return step3.GetEjectile(); }; - inline const Nucleus& GetBreakup4() const { return step3.GetResidual(); }; - - inline int GetDecay1AngularMomentum() { return decay1dist.GetL(); }; - inline int GetDecay2AngularMomentum(){ return decay2dist.GetL(); }; - inline double GetDecay1BranchingRatio() { return decay1dist.GetBranchingRatio(); }; - inline double GetDecay2BranchingRatio(){ return decay2dist.GetBranchingRatio(); }; - - protected: - void LinkTarget() override; - void SetSystemEquation() override; - - std::uniform_real_distribution m_phi2Range; - - Reaction step1, step2, step3; - - AngularDistribution decay1dist, decay2dist; - - }; - -} - -#endif \ No newline at end of file diff --git a/include/TwoStepSystem.h b/include/TwoStepSystem.h deleted file mode 100644 index cdde9b8..0000000 --- a/include/TwoStepSystem.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef TWOSTEPSYSTEM_H -#define TWOSTEPSYSTEM_H - -#include "ReactionSystem.h" -#include "AngularDistribution.h" - -namespace Mask { - - class TwoStepSystem : public ReactionSystem { - public: - TwoStepSystem(); - TwoStepSystem(std::vector& z, std::vector& a); - ~TwoStepSystem(); - bool SetNuclei(std::vector& z, std::vector& a) override; - void RunSystem() override; - const std::vector& GetNuclei() override; - - inline void SetDecay1Distribution(const std::string& filename) { decay1dist.ReadDistributionFile(filename); }; - - inline void SetReactionThetaType(int type) { step1.SetEjectileThetaType(type); }; - inline const Nucleus& GetTarget() const { return step1.GetTarget(); }; - inline const Nucleus& GetProjectile() const { return step1.GetProjectile(); }; - inline const Nucleus& GetEjectile() const { return step1.GetEjectile(); }; - inline const Nucleus& GetResidual() const { return step1.GetResidual(); }; - inline const Nucleus& GetBreakup1() const { return step2.GetEjectile(); }; - inline const Nucleus& GetBreakup2() const { return step2.GetResidual(); }; - - inline int GetDecay1AngularMomentum() { return decay1dist.GetL(); }; - inline double GetDecay1BranchingRatio() { return decay1dist.GetBranchingRatio(); }; - - private: - void LinkTarget() override; - void SetSystemEquation() override; - - std::uniform_real_distribution m_phi2Range; - - Reaction step1, step2; - - AngularDistribution decay1dist; - - }; - -} - -#endif \ No newline at end of file diff --git a/input.txt b/input.txt index f67ec79..215185c 100644 --- a/input.txt +++ b/input.txt @@ -1,28 +1,26 @@ ----------Data Information---------- -OutputFile: /data1/gwm17/7BeNov2021/sim/7Bedp_1100keV_beam_50CD2.mask +OutputFile: /media/data/gwm17/mask_tests/10B3Hea_test.root ----------Reaction Information---------- -ReactionType: TwoStepRxn +ReactionType: OneStepRxn Z A (order is target, projectile, ejectile, break1, break3(if pure decay is target, ejectile)) -1 2 -4 7 -1 1 +5 10 +2 3 2 4 ----------Target Information---------- NumberOfLayers: 1 begin_layer Thickness(ug/cm^2): 50 begin_elements (Z, A, Stoich.) - element 1 2 2 - element 6 12 1 + element 5 10 1 end_elements end_layer ----------Sampling Information---------- -NumberOfSamples: 100000 -BeamMeanEnergy(MeV): 1.1 BeamEnergySigma(MeV): 0.0 +NumberOfSamples: 1000 +BeamMeanEnergy(MeV): 24.0 BeamEnergySigma(MeV): 0.0 EjectileThetaType(0=Lab,1=CM): 1 EjectileThetaMin(deg): 0.0 EjectileThetaMax(deg): 180.0 EjectilePhiMin(deg): 0.0 EjectilePhiMax(deg): 360.0 -ResidualExMean(MeV): 0.0 ResidualExSigma(MeV): 0.0 +ResidualExMean(MeV): 16.8 ResidualExSigma(MeV): 0.023 Decay1_DistributionFile: ./etc/isotropic_dist.txt Decay2_DistributionFile: ./etc/isotropic_dist.txt -------------------------------------- diff --git a/include/AnasenDeadChannelMap.h b/src/Detectors/AnasenDeadChannelMap.h similarity index 94% rename from include/AnasenDeadChannelMap.h rename to src/Detectors/AnasenDeadChannelMap.h index d3c31e0..1fb0006 100644 --- a/include/AnasenDeadChannelMap.h +++ b/src/Detectors/AnasenDeadChannelMap.h @@ -25,7 +25,7 @@ public: AnasenDeadChannelMap(const std::string& filename); ~AnasenDeadChannelMap(); void LoadMapfile(const std::string& filename); - inline const bool IsValid() const { return valid_flag; } + const bool IsValid() const { return valid_flag; } const bool IsDead(AnasenDetectorType type, int detIndex, int channel, AnasenDetectorSide side) const; private: void InitMap(); diff --git a/src/Detectors/AnasenEfficiency.cpp b/src/Detectors/AnasenEfficiency.cpp index be71cce..5a0b7d8 100644 --- a/src/Detectors/AnasenEfficiency.cpp +++ b/src/Detectors/AnasenEfficiency.cpp @@ -3,194 +3,221 @@ #include #include +#include "TFile.h" +#include "TTree.h" + AnasenEfficiency::AnasenEfficiency() : - DetectorEfficiency(), det_silicon(si_thickness) + DetectorEfficiency(), m_detectorEloss({14}, {28}, {1}, s_detectorThickness) { - for(int i=0; i det_z = {14}; - std::vector det_a = {28}; - std::vector det_stoich = {1}; - det_silicon.SetElements(det_z, det_a, det_stoich); - } AnasenEfficiency::~AnasenEfficiency() {} -void AnasenEfficiency::DrawDetectorSystem(const std::string& filename) { +void AnasenEfficiency::DrawDetectorSystem(const std::string& filename) +{ std::ofstream output(filename); std::vector x, y, z; std::vector cx, cy, cz; - Mask::Vec3 coords; - for(int i=0; i r1_points; - std::vector r2_points; - std::vector fqqq_points; - std::vector bqqq_points; - for(int i=0; i r1_points; + std::vector r2_points; + std::vector fqqq_points; + std::vector bqqq_points; + for(int i=0; i M_PI/2.0) thetaIncident = M_PI - thetaIncident; - observation.energy_deposited = det_silicon.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), nucleus.GetKE(), thetaIncident); + observation.energy_deposited = m_detectorEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, nucleus.GetKE(), thetaIncident); observation.det_name = "R1"; return observation; } @@ -227,22 +255,23 @@ DetectorResult AnasenEfficiency::IsRing1(Mask::Nucleus& nucleus) { return observation; } -DetectorResult AnasenEfficiency::IsRing2(Mask::Nucleus& nucleus) { - +DetectorResult AnasenEfficiency::IsRing2(Mask::Nucleus& nucleus) +{ DetectorResult observation; double thetaIncident; - for(int i=0; i M_PI/2.0) thetaIncident = M_PI - thetaIncident; - observation.energy_deposited = det_silicon.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), nucleus.GetKE(), thetaIncident); + observation.energy_deposited = m_detectorEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, nucleus.GetKE(), thetaIncident); observation.det_name = "R2"; return observation; } @@ -251,40 +280,42 @@ DetectorResult AnasenEfficiency::IsRing2(Mask::Nucleus& nucleus) { return observation; } -DetectorResult AnasenEfficiency::IsQQQ(Mask::Nucleus& nucleus) { - +DetectorResult AnasenEfficiency::IsQQQ(Mask::Nucleus& nucleus) +{ DetectorResult observation; double thetaIncident; - for(int i=0; i M_PI/2.0) thetaIncident = M_PI - thetaIncident; - observation.energy_deposited = det_silicon.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), nucleus.GetKE(), thetaIncident); + observation.energy_deposited = m_detectorEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, nucleus.GetKE(), thetaIncident); observation.det_name = "FQQQ"; return observation; } } - for(int i=0; i M_PI/2.0) thetaIncident = M_PI - thetaIncident; - observation.energy_deposited = det_silicon.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), nucleus.GetKE(), thetaIncident); + observation.energy_deposited = m_detectorEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, nucleus.GetKE(), thetaIncident); observation.det_name = "BQQQ"; return observation; } @@ -293,95 +324,93 @@ DetectorResult AnasenEfficiency::IsQQQ(Mask::Nucleus& nucleus) { return observation; } -DetectorResult AnasenEfficiency::IsAnasen(Mask::Nucleus& nucleus) { +DetectorResult AnasenEfficiency::IsAnasen(Mask::Nucleus& nucleus) +{ DetectorResult result; - if(nucleus.GetKE() <= threshold) + if(nucleus.GetKE() <= s_energyThreshold) return result; - if(!result.detectFlag) { + if(!result.detectFlag) result = IsRing1(nucleus); - } - if(!result.detectFlag) { + if(!result.detectFlag) result = IsRing2(nucleus); - } - if(!result.detectFlag) { + if(!result.detectFlag) result = IsQQQ(nucleus); - } - return result; } -void AnasenEfficiency::CountCoincidences(const Mask::MaskFileData& data, std::vector& counts, Mask::RxnType rxn_type) { - if (rxn_type == Mask::RxnType::PureDecay && data.detect_flag[1] && data.detect_flag[2]) +void AnasenEfficiency::CountCoincidences(const std::vector& data, std::vector& counts) +{ + if (data.size() == 3 && data[1].isDetected && data[2].isDetected) { counts[0]++; } - else if (rxn_type == Mask::RxnType::OneStepRxn && data.detect_flag[2] && data.detect_flag[3]) + else if (data.size() == 4 && data[2].isDetected && data[3].isDetected) { counts[0]++; } - else if(rxn_type == Mask::RxnType::TwoStepRxn) + else if(data.size() == 6) { - if(data.detect_flag[2] && data.detect_flag[4]) + if(data[2].isDetected && data[4].isDetected) { counts[0]++; } - if(data.detect_flag[2] && data.detect_flag[5]) + if(data[2].isDetected && data[5].isDetected) { counts[1]++; } - if(data.detect_flag[4] && data.detect_flag[5]) + if(data[4].isDetected && data[5].isDetected) { counts[2]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[5]) + if(data[2].isDetected && data[4].isDetected && data[5].isDetected) { counts[3]++; } } - else if(rxn_type == Mask::RxnType::ThreeStepRxn) + else if(data.size() == 8) { - if(data.detect_flag[2] && data.detect_flag[4]) + if(data[2].isDetected && data[4].isDetected) { counts[0]++; } - if(data.detect_flag[2] && data.detect_flag[6]) + if(data[2].isDetected && data[6].isDetected) { counts[1]++; } - if(data.detect_flag[2] && data.detect_flag[7]) + if(data[2].isDetected && data[7].isDetected) { counts[2]++; } - if(data.detect_flag[4] && data.detect_flag[6]) + if(data[4].isDetected && data[6].isDetected) { counts[3]++; } - if(data.detect_flag[4] && data.detect_flag[7]) + if(data[4].isDetected && data[7].isDetected) { counts[4]++; } - if(data.detect_flag[6] && data.detect_flag[7]) + if(data[6].isDetected && data[7].isDetected) { counts[5]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[6]) + if(data[2].isDetected && data[4].isDetected && data[6].isDetected) { counts[6]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[7]) + if(data[2].isDetected && data[4].isDetected && data[7].isDetected) { counts[7]++; } - if(data.detect_flag[2] && data.detect_flag[6] && data.detect_flag[7]) + if(data[2].isDetected && data[6].isDetected && data[7].isDetected) { counts[8]++; } - if(data.detect_flag[4] && data.detect_flag[6] && data.detect_flag[7]) + if(data[4].isDetected && data[6].isDetected && data[7].isDetected) { counts[9]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[6] && data.detect_flag[7]) + if(data[2].isDetected && data[4].isDetected && data[6].isDetected && data[7].isDetected) { counts[10]++; } @@ -401,141 +430,138 @@ void AnasenEfficiency::CalculateEfficiency(const std::string& inputname, const s std::cout<<"Loading in output from kinematics simulation: "<Get("SimTree"); + std::vector* dataHandle = new std::vector(); + intree->SetBranchAddress("nuclei", &dataHandle); + + output->cd(); + TTree* outtree = new TTree("SimTree", "SimTree"); + outtree->Branch("nuclei", dataHandle); + + input->cd(); + stats<<"Efficiency statistics for data from "<GetEntry(1); std::vector counts; std::vector coinc_counts; - switch(header.rxn_type) { - case Mask::RxnType::PureDecay: - counts.resize(3, 0); - coinc_counts.resize(1, 0); - break; - case Mask::RxnType::OneStepRxn: - counts.resize(4, 0); - coinc_counts.resize(1, 0); - break; - case Mask::RxnType::TwoStepRxn: - counts.resize(6, 0); - coinc_counts.resize(4, 0); - break; - case Mask::RxnType::ThreeStepRxn: - counts.resize(8, 0); - coinc_counts.resize(11, 0); - break; + counts.resize(dataHandle->size()); + switch(counts.size()) + { + case 3: coinc_counts.resize(1, 0); break; + case 4: coinc_counts.resize(1, 0); break; + case 6: coinc_counts.resize(4, 0); break; + case 8: coinc_counts.resize(11, 0); break; default: { - std::cerr<<"Bad reaction type at AnasenEfficiency::CalculateEfficiency (given value: "<Close(); + output->Close(); stats.close(); return; } } - int percent5 = header.nsamples*0.05; - int count = 0; - int npercent = 0; + uint64_t nentries = intree->GetEntries(); + uint64_t percent5 = nentries*0.05; + uint64_t count = 0; + uint64_t npercent = 0; Mask::Nucleus nucleus; - int index=0; - while(true) { - if(++count == percent5) {//Show progress every 5% + for(uint64_t i=0; iGetEntry(i); + if(++count == percent5) + {//Show progress every 5% npercent++; count = 0; std::cout<<"\rPercent completed: "<size(); j++) + { + Mask::Nucleus& nucleus = (*dataHandle)[j]; + DetectorResult result = IsAnasen(nucleus); + if(result.detectFlag) + { + nucleus.isDetected = true; + nucleus.detectedKE = result.energy_deposited; + nucleus.detectedTheta = result.direction.Theta(); + nucleus.detectedPhi = result.direction.Phi(); + counts[j]++; } } - CountCoincidences(data, coinc_counts, header.rxn_type); + CountCoincidences(*dataHandle, coinc_counts); - output.WriteData(data); - - index++; + outtree->Fill(); } + input->Close(); + output->cd(); + outtree->Write(outtree->GetName(), TObject::kOverwrite); + output->Close(); - input.Close(); - output.Close(); + delete dataHandle; stats<size() == 3) { - stats<size() == 4) { - stats<size() == 6) { - stats<size() == 8) { - stats< + +#include "DetectorEfficiency.h" +#include "StripDetector.h" +#include "QQQDetector.h" +#include "Target.h" +#include "Nucleus.h" +#include "AnasenDeadChannelMap.h" + +class AnasenEfficiency : public DetectorEfficiency +{ +public: + AnasenEfficiency(); + ~AnasenEfficiency(); + void CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) override; + void DrawDetectorSystem(const std::string& filename) override; + double RunConsistencyCheck() override; + inline void SetDeadChannelMap(const std::string& filename) { dmap.LoadMapfile(filename); } + +private: + DetectorResult IsRing1(Mask::Nucleus& nucleus); + DetectorResult IsRing2(Mask::Nucleus& nucleus); + DetectorResult IsQQQ(Mask::Nucleus& nucleus); + DetectorResult IsAnasen(Mask::Nucleus& nucleus); + void CountCoincidences(const std::vector& data, std::vector& counts); + + std::vector m_Ring1, m_Ring2; + std::vector m_forwardQQQs; + std::vector m_backwardQQQs; + + Mask::Target m_detectorEloss; + + AnasenDeadChannelMap dmap; + + /**** ANASEN geometry constants *****/ + static constexpr int s_nSX3PerBarrel = 12; + static constexpr int s_nQQQ = 4; + static constexpr double s_sx3Length = 0.075; + static constexpr double s_sx3Width = 0.04; + static constexpr double s_barrelGap = 0.0254; + static constexpr double s_sx3FrameGap = 0.049; //0.049 is base gap due to frames + static constexpr double s_barrel1Z = s_sx3Length/2.0 + s_sx3FrameGap + s_barrelGap/2.0; + static constexpr double s_barrel2Z = (-1.0)*(s_barrelGap/2.0 + s_sx3Length/2.0); + static constexpr double s_qqqZ = 0.0125 + s_sx3Length + s_sx3FrameGap + s_barrelGap/2.0; + static constexpr double s_qqqInnerR = 0.0501; + static constexpr double s_qqqOuterR = 0.0990; + static constexpr double s_qqqDeltaPhi = 1.52119; + static constexpr double s_qqqZList[4] = {s_qqqZ, s_qqqZ, s_qqqZ, s_qqqZ}; + static constexpr double s_qqqPhiList[4] = {5.49779, 0.785398, 2.35619, 3.92699}; + static constexpr double s_barrelRhoList[12] = {0.0890601, 0.0889871, 0.0890354, 0.0890247, 0.0890354, 0.0890354, 0.0890247, + 0.0890354, 0.0890354, 0.0890247, 0.0890354, 0.0890354}; + static constexpr double s_barrelPhiList[12] = {4.97426, 5.49739, 6.02132, 0.261868, 0.785398, 1.30893, 1.83266, 2.35619, 2.87972, + 3.40346, 3.92699, 4.45052}; + /*************************/ + + static constexpr double s_energyThreshold = 0.6; //MeV + static constexpr double s_deg2rad = M_PI/180.0; + static constexpr double s_detectorThickness = 1000 * 1e-4 * 2.3926 * 1e6; //thickness in um -> eff thickness in ug/cm^2 for detector +}; + +#endif \ No newline at end of file diff --git a/src/Detectors/CMakeLists.txt b/src/Detectors/CMakeLists.txt index 1852b72..0165619 100644 --- a/src/Detectors/CMakeLists.txt +++ b/src/Detectors/CMakeLists.txt @@ -1,18 +1,27 @@ add_executable(DetectEff) -target_include_directories(DetectEff PUBLIC ${MASK_INCLUDE_DIR}) +target_include_directories(DetectEff PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..) target_sources(DetectEff PUBLIC AnasenDeadChannelMap.cpp + AnasenDeadChannelMap.h AnasenEfficiency.cpp - DetectorEfficiency.cpp + AnasenEfficiency.h + main.cpp + DetectorEfficiency.h QQQDetector.cpp + QQQDetector.h SabreDeadChannelMap.cpp + SabreDeadChannelMap.h SabreDetector.cpp + SabreDetector.h SabreEfficiency.cpp + SabreEfficiency.h StripDetector.cpp + StripDetector.h ) target_link_libraries(DetectEff + MaskDict Mask catima ) diff --git a/include/DetectorEfficiency.h b/src/Detectors/DetectorEfficiency.h similarity index 62% rename from include/DetectorEfficiency.h rename to src/Detectors/DetectorEfficiency.h index e0a1385..7f3f292 100644 --- a/include/DetectorEfficiency.h +++ b/src/Detectors/DetectorEfficiency.h @@ -4,7 +4,18 @@ #include #include -class DetectorEfficiency { +#include "Math/Point3D.h" + +struct DetectorResult +{ + bool detectFlag = false; + ROOT::Math::XYZPoint direction; + double energy_deposited = 0.0; + std::string det_name = ""; +}; + +class DetectorEfficiency +{ public: DetectorEfficiency() {}; virtual ~DetectorEfficiency() {}; @@ -14,9 +25,9 @@ public: virtual double RunConsistencyCheck() = 0; protected: - inline bool IsDoubleEqual(double x, double y) { return std::fabs(x-y) < epsilon ? true : false; }; + inline bool IsDoubleEqual(double x, double y) { return std::fabs(x-y) < s_epsilon ? true : false; }; - static constexpr double epsilon = 1.0e-6; + static constexpr double s_epsilon = 1.0e-6; }; #endif \ No newline at end of file diff --git a/src/Detectors/QQQDetector.cpp b/src/Detectors/QQQDetector.cpp index 1222fe0..11d5155 100644 --- a/src/Detectors/QQQDetector.cpp +++ b/src/Detectors/QQQDetector.cpp @@ -1,107 +1,116 @@ #include "QQQDetector.h" QQQDetector::QQQDetector(double R_in, double R_out, double deltaPhi, double phiCentral, double z, double x, double y) : - m_Rinner(R_in), m_Router(R_out), m_deltaPhi(deltaPhi), m_phiCentral(phiCentral), m_translation(x,y,z), m_norm(0.0,0.0,1.0), m_uniform_fraction(0.0, 1.0), rndmFlag(false) + m_innerR(R_in), m_outerR(R_out), m_deltaPhi(deltaPhi), m_centralPhi(phiCentral), m_translation(x,y,z), m_norm(0.0,0.0,1.0), + m_uniformFraction(0.0, 1.0), m_isSmearing(false) { - m_deltaR = (m_Router - m_Rinner)/nrings; - m_deltaPhi_per_wedge = m_deltaPhi/nwedges; - m_ZRot.SetAngle(m_phiCentral); - m_ringCoords.resize(nrings); - m_wedgeCoords.resize(nwedges); - for(auto& ring : m_ringCoords) { + m_deltaR = (m_outerR - m_innerR)/s_nRings; + m_deltaPhiWedge = m_deltaPhi/s_nWedges; + m_zRotation.SetAngle(m_centralPhi); + m_ringCoords.resize(s_nRings); + m_wedgeCoords.resize(s_nWedges); + for(auto& ring : m_ringCoords) ring.resize(4); - } - for(auto& wedge : m_wedgeCoords) { + for(auto& wedge : m_wedgeCoords) wedge.resize(4); - } CalculateCorners(); } QQQDetector::~QQQDetector() {} -void QQQDetector::CalculateCorners() { +void QQQDetector::CalculateCorners() +{ double x0, x1, x2, x3; double y0, y1, y2, y3; double z0, z1, z2, z3; //Generate flat ring corner coordinates - for(int i=0; i min_rho) { - for(auto& wedge : m_wedgeCoords) { - min_phi = wedge[0].GetPhi(); - max_phi = wedge[3].GetPhi(); - if(phi < min_phi && phi < max_phi) { - result.SetVectorSpherical(r_traj, theta, phi); + for(auto& ring : m_ringCoords) + { + min_rho = ring[1].Rho(); + max_rho = ring[0].Rho(); + if(rho_traj < max_rho && rho_traj > min_rho) + { + for(auto& wedge : m_wedgeCoords) + { + min_phi = wedge[0].Phi(); + max_phi = wedge[3].Phi(); + if(phi < min_phi && phi < max_phi) + { + result.SetXYZ(std::sin(theta)*std::cos(phi)*r_traj, + std::sin(theta)*std::sin(phi)*r_traj, + std::cos(theta)*r_traj); break; } } @@ -109,55 +118,57 @@ Mask::Vec3 QQQDetector::GetTrajectoryCoordinates(double theta, double phi) { } return result; - } -std::pair QQQDetector::GetTrajectoryRingWedge(double theta, double phi) { - double z_to_detector = m_translation.GetZ(); +std::pair QQQDetector::GetTrajectoryRingWedge(double theta, double phi) +{ + double z_to_detector = m_translation.Vect().Z(); double rho_traj = z_to_detector*std::tan(theta); double min_rho, max_rho, min_phi, max_phi; - for(int r=0; r min_rho) { - for(int w=0; w min_rho) + { + for(int w=0; w min_phi && phi < max_phi) { + min_phi = wedge[0].Phi(); + max_phi = wedge[3].Phi(); + if(phi > min_phi && phi < max_phi) return std::make_pair(r, w); - } } } } return std::make_pair(-1, -1); - } -Mask::Vec3 QQQDetector::GetHitCoordinates(int ringch, int wedgech) { +ROOT::Math::XYZPoint QQQDetector::GetHitCoordinates(int ringch, int wedgech) +{ if(!CheckChannel(ringch) || !CheckChannel(wedgech)) - return Mask::Vec3(); + return ROOT::Math::XYZPoint(); double r_center, phi_center; - if(rndmFlag) + if(m_isSmearing) { - r_center = m_Rinner + (m_uniform_fraction(Mask::RandomGenerator::GetInstance().GetGenerator())+ringch)*m_deltaR; - phi_center = -m_deltaPhi/2.0 + (m_uniform_fraction(Mask::RandomGenerator::GetInstance().GetGenerator())+wedgech)*m_deltaPhi_per_wedge; + r_center = m_innerR + (m_uniformFraction(Mask::RandomGenerator::GetInstance().GetGenerator())+ringch)*m_deltaR; + phi_center = -m_deltaPhi/2.0 + (m_uniformFraction(Mask::RandomGenerator::GetInstance().GetGenerator())+wedgech)*m_deltaPhiWedge; } else { - r_center = m_Rinner + (0.5+ringch)*m_deltaR; - phi_center = -m_deltaPhi/2.0 + (0.5+wedgech)*m_deltaPhi_per_wedge; + r_center = m_innerR + (0.5+ringch)*m_deltaR; + phi_center = -m_deltaPhi/2.0 + (0.5+wedgech)*m_deltaPhiWedge; } double x = r_center*std::cos(phi_center); double y = r_center*std::sin(phi_center); double z = 0; - Mask::Vec3 hit(x, y, z); + ROOT::Math::XYZPoint hit(x, y, z); return TransformCoordinates(hit); } \ No newline at end of file diff --git a/src/Detectors/QQQDetector.h b/src/Detectors/QQQDetector.h new file mode 100644 index 0000000..9126a3c --- /dev/null +++ b/src/Detectors/QQQDetector.h @@ -0,0 +1,65 @@ +/* + QQQDetector.h + Class implementing geometry for QQQDetector where the detector is perpendicular to the beam axis. + Detector is first generated centered on the x-axis (phi=0) + + Coordinate convention : +z is downstream, -z is upstream. +y is vertically down in the lab. +*/ +#ifndef QQQDETECTOR_H +#define QQQDETECTOR_H + +#include +#include + +#include "RandomGenerator.h" +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/RotationZ.h" +#include "Math/Translation3D.h" + +class QQQDetector +{ +public: + QQQDetector(double R_in, double R_out, double deltaPhi, double phiCentral, double z, double x=0, double y=0); + ~QQQDetector(); + const ROOT::Math::XYZPoint& GetRingCoordinates(int ringch, int corner) { return m_ringCoords[ringch][corner]; } + const ROOT::Math::XYZPoint& GetWedgeCoordinates(int wedgech, int corner) { return m_wedgeCoords[wedgech][corner]; } + const ROOT::Math::XYZVector& GetNorm() { return m_norm; } + ROOT::Math::XYZPoint GetTrajectoryCoordinates(double theta, double phi); + std::pair GetTrajectoryRingWedge(double theta, double phi); + ROOT::Math::XYZPoint GetHitCoordinates(int ringch, int wedgech); + + void SetSmearing(bool isSmearing) { m_isSmearing = isSmearing; } + + int GetNumberOfRings() { return s_nRings; } + int GetNumberOfWedges() { return s_nWedges; } + +private: + + bool CheckChannel(int ch) { return (ch >=0 && ch < s_nRings); } + bool CheckCorner(int corner) { return (corner >=0 && corner < 4); } + + void CalculateCorners(); + ROOT::Math::XYZPoint TransformCoordinates(ROOT::Math::XYZPoint& vector) { return m_translation * (m_zRotation * vector) ; } + + double m_innerR; + double m_outerR; + double m_deltaR; + double m_deltaPhi; + double m_deltaPhiWedge; + double m_centralPhi; + + std::vector> m_ringCoords, m_wedgeCoords; + ROOT::Math::Translation3D m_translation; + ROOT::Math::XYZVector m_norm; + ROOT::Math::RotationZ m_zRotation; + + std::uniform_real_distribution m_uniformFraction; + bool m_isSmearing; + + static constexpr int s_nRings = 16; + static constexpr int s_nWedges = 16; + static constexpr double s_deg2rad = M_PI/180.0; +}; + +#endif \ No newline at end of file diff --git a/include/SabreDeadChannelMap.h b/src/Detectors/SabreDeadChannelMap.h similarity index 100% rename from include/SabreDeadChannelMap.h rename to src/Detectors/SabreDeadChannelMap.h diff --git a/src/Detectors/SabreDetector.cpp b/src/Detectors/SabreDetector.cpp index 02ff130..9d9da27 100644 --- a/src/Detectors/SabreDetector.cpp +++ b/src/Detectors/SabreDetector.cpp @@ -53,126 +53,133 @@ #include "SabreDetector.h" SabreDetector::SabreDetector() : -m_Router(0.1351), m_Rinner(0.0326), m_deltaPhi_flat(54.4*deg2rad), m_phiCentral(0.0), m_tilt(0.0), m_translation(0.,0.,0.), m_norm_flat(0,0,1.0), -m_detectorID(-1) +m_outerR(0.1351), m_innerR(0.0326), m_deltaPhiFlat(54.4*s_deg2rad), m_centerPhi(0.0), m_tilt(0.0), + m_translation(0.,0.,0.), m_norm(0,0,1.0), m_detectorID(-1) { - m_YRot.SetAngle(m_tilt); - m_ZRot.SetAngle(m_phiCentral); + m_yRotation.SetAngle(m_tilt); + m_zRotation.SetAngle(m_centerPhi); //Initialize the coordinate arrays - m_ringCoords_flat.resize(m_nRings); - m_ringCoords_tilt.resize(m_nRings); - m_wedgeCoords_flat.resize(m_nWedges); - m_wedgeCoords_tilt.resize(m_nWedges); - for(int i=0; i SabreDetector::GetTrajectoryRingWedge(double theta, double phi) { - if(m_translation.GetX() != 0.0 || m_translation.GetY() != 0.0) { +std::pair SabreDetector::GetTrajectoryRingWedge(double theta, double phi) +{ + if(m_translation.Vect().X() != 0.0 || m_translation.Vect().Y() != 0.0) return std::make_pair(-1, -1); - } //Calculate the *potential* phi in the flat detector - double phi_numerator = std::cos(m_tilt)*(std::sin(phi)*std::cos(m_phiCentral) - std::sin(m_phiCentral)*std::cos(phi)); - double phi_denominator = std::cos(m_phiCentral)*std::cos(phi) + std::sin(m_phiCentral)*std::sin(phi); + double phi_numerator = std::cos(m_tilt)*(std::sin(phi)*std::cos(m_centerPhi) - std::sin(m_centerPhi)*std::cos(phi)); + double phi_denominator = std::cos(m_centerPhi)*std::cos(phi) + std::sin(m_centerPhi)*std::sin(phi); double phi_flat = std::atan2(phi_numerator, phi_denominator); - if(phi_flat < 0) phi_flat += M_PI*2.0; + if(phi_flat < 0) + phi_flat += M_PI*2.0; //Calculate the *potential* R in the flat detector - double r_numerator = m_translation.GetZ()*std::cos(phi)*std::sin(theta); - double r_denominator = std::cos(phi_flat)*std::cos(m_phiCentral)*std::cos(m_tilt)*std::cos(theta) - std::sin(phi_flat)*std::sin(m_phiCentral)*std::cos(theta) - std::cos(phi_flat)*std::sin(m_tilt)*std::cos(phi)*std::sin(theta); + double r_numerator = m_translation.Vect().Z()*std::cos(phi)*std::sin(theta); + double r_denominator = std::cos(phi_flat)*std::cos(m_centerPhi)*std::cos(m_tilt)*std::cos(theta) - + std::sin(phi_flat)*std::sin(m_centerPhi)*std::cos(theta) - + std::cos(phi_flat)*std::sin(m_tilt)*std::cos(phi)*std::sin(theta); double r_flat = r_numerator/r_denominator; //Calculate the distance from the origin to the hit on the detector @@ -262,31 +274,41 @@ std::pair SabreDetector::GetTrajectoryRingWedge(double theta, double p //Check to see if our flat coords fall inside the flat detector - if(IsInside(r_flat, phi_flat)) { + if(IsInside(r_flat, phi_flat)) + { int ringch, wedgech; - if(phi_flat > M_PI) phi_flat -= 2.0*M_PI; //Need phi in terms of [-deltaPhi_flat/2, deltaPhi_flat/2] - for(int i=0; i M_PI) + phi_flat -= 2.0*M_PI; //Need phi in terms of [-deltaPhi_flat/2, deltaPhi_flat/2] + for(int i=0; i SabreDetector::GetTrajectoryRingWedge(double theta, double p randomly wiggle the point within the pixel. Method intended for use with data, or to smear out simulated data to mimic real data. */ -Mask::Vec3 SabreDetector::GetHitCoordinates(int ringch, int wedgech) { - if(!CheckRingChannel(ringch) || !CheckWedgeChannel(wedgech)) { - return Mask::Vec3(); - } +ROOT::Math::XYZPoint SabreDetector::GetHitCoordinates(int ringch, int wedgech) +{ + if(!CheckRingChannel(ringch) || !CheckWedgeChannel(wedgech)) + return ROOT::Math::XYZPoint(); - double r_center = m_Rinner + (0.5+ringch)*m_deltaR_flat_ring; - double phi_center = -m_deltaPhi_flat/2.0 + (0.5+wedgech)*m_deltaPhi_flat_wedge; + double r_center = m_innerR + (0.5+ringch)*m_deltaRFlatRing; + double phi_center = -m_deltaPhiFlat/2.0 + (0.5+wedgech)*m_deltaPhiFlatWedge; double x = r_center*std::cos(phi_center); double y = r_center*std::sin(phi_center); double z = 0; - Mask::Vec3 hit(x, y, z); + ROOT::Math::XYZPoint hit(x, y, z); - return TransformToTiltedFrame(hit); + return Transform(hit); } diff --git a/src/Detectors/SabreDetector.h b/src/Detectors/SabreDetector.h new file mode 100644 index 0000000..b9b1d23 --- /dev/null +++ b/src/Detectors/SabreDetector.h @@ -0,0 +1,189 @@ +/* + + Class which represents a single MMM detector in the SABRE array at FSU. Origial code by KGH, re-written by + GWM. + + Distances in meters, angles in radians. + + The channel arrays have four points, one for each corner. The corners are + as follows, as if looking BACK along beam (i.e. from the target's pov): + + 0---------------------1 + | | + | | x + | | <----- + | | | + | | | + 3---------------------2 y + (z is hence positive along beam direction) + + The channel numbers, also as looking back from target pov, are: + + >> rings are 0 -- 15 from inner to outer: + + 15 ------------------- + 14 ------------------- + 13 ------------------- + . + . + . + 2 ------------------- + 1 ------------------- + 0 ------------------- + + >> wedges are 0 -- 7 moving counterclockwise: + + 7 6 ... 1 0 + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | | | | + + + >> Note that the detector starts centered on the x-axis (central phi = 0) untilted, and then is rotated to wherever the frick + it is supposed to go; phi = 90 is centered on y axis, pointing down towards the bottom of the scattering chamber + + -- GWM, Dec 2020; based on the og code from kgh + +*/ + +#ifndef SABREDETECTOR_H +#define SABREDETECTOR_H + +#include +#include + +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/RotationZ.h" +#include "Math/RotationY.h" +#include "Math/Translation3D.h" + +class SabreDetector { +public: + + SabreDetector(); + SabreDetector(int detID, double Rin, double Rout, double deltaPhi_flat, double phiCentral, double tiltFromVert, double zdist, double xdist=0, double ydist=0); + ~SabreDetector(); + + /*Return coordinates of the corners of each ring/wedge in SABRE*/ + const ROOT::Math::XYZPoint& GetRingFlatCoords(int ch, int corner) const { return m_flatRingCoords[ch][corner]; } + const ROOT::Math::XYZPoint& GetWedgeFlatCoords(int ch, int corner) const { return m_flatWedgeCoords[ch][corner]; } + const ROOT::Math::XYZPoint& GetRingTiltCoords(int ch, int corner) const { return m_tiltRingCoords[ch][corner]; } + const ROOT::Math::XYZPoint& GetWedgeTiltCoords(int ch, int corner) const { return m_tiltWedgeCoords[ch][corner]; } + + ROOT::Math::XYZPoint GetTrajectoryCoordinates(double theta, double phi); + std::pair GetTrajectoryRingWedge(double theta, double phi); + ROOT::Math::XYZPoint GetHitCoordinates(int ringch, int wedgech); + + int GetNumberOfWedges() { return s_nWedges; } + int GetNumberOfRings() { return s_nRings; } + ROOT::Math::XYZVector GetNormTilted() { return m_zRotation*(m_yRotation*m_norm); } + int GetDetectorID() { return m_detectorID; } + +private: + + + + void CalculateCorners(); + + /*Performs the transformation to the tilted,rotated,translated frame of the SABRE detector*/ + ROOT::Math::XYZPoint Transform(const ROOT::Math::XYZPoint& vector) { return m_translation*(m_zRotation*(m_yRotation*vector)); }; + + /*Determine if a given channel/corner combo is valid*/ + bool CheckRingChannel(int ch) { return (ch=0) ? true : false; }; + bool CheckWedgeChannel(int ch) { return (ch=0) ? true : false; }; + bool CheckCorner(int corner) { return (corner < 4 && corner >=0) ? true : false; }; + bool CheckRingLocation(int ch, int corner) { return CheckRingChannel(ch) && CheckCorner(corner); }; + bool CheckWedgeLocation(int ch, int corner) { return CheckWedgeChannel(ch) && CheckCorner(corner); }; + + /* + For all of the calculations, need a limit precision to determine if values are actually equal or not + Here the approx. size of the strip spacing is used as the precision. + */ + bool CheckPositionEqual(double val1,double val2) { return fabs(val1-val2) > s_positionTol ? false : true; }; + bool CheckAngleEqual(double val1,double val2) { return fabs(val1-val2) > s_angularTol ? false : true; }; + + /*Determine if a hit is within the bulk detector*/ + bool IsInside(double r, double phi) + { + double phi_1 = m_deltaPhiFlat/2.0; + double phi_2 = M_PI*2.0 - m_deltaPhiFlat/2.0; + return (((r > m_innerR && r < m_outerR) || CheckPositionEqual(r, m_innerR) || CheckPositionEqual(r, m_outerR)) + && (phi > phi_2 || phi < phi_1 || CheckAngleEqual(phi, phi_1) || CheckAngleEqual(phi, phi_2))); + }; + + /* + For a given radius/phi are you inside of a given ring/wedge channel, + or are you on the spacing between these channels + */ + bool IsRing(double r, int ringch) + { + double ringtop = m_innerR + m_deltaRFlatRing*(ringch + 1); + double ringbottom = m_innerR + m_deltaRFlatRing*(ringch); + return (r>ringbottom && rwedgebottom && phi> m_flatRingCoords, m_flatWedgeCoords; + std::vector> m_tiltRingCoords, m_tiltWedgeCoords; + +}; + + +#endif diff --git a/src/Detectors/SabreEfficiency.cpp b/src/Detectors/SabreEfficiency.cpp index 4bdadc6..5d0a7b2 100644 --- a/src/Detectors/SabreEfficiency.cpp +++ b/src/Detectors/SabreEfficiency.cpp @@ -1,40 +1,44 @@ #include "SabreEfficiency.h" -#include "MaskFile.h" #include #include #include +#include "TFile.h" +#include "TTree.h" + SabreEfficiency::SabreEfficiency() : - DetectorEfficiency(), deadlayer(DEADLAYER_THIN), sabre_eloss(SABRE_THICKNESS), degrader(DEGRADER_THICKNESS) + DetectorEfficiency(), m_deadlayerEloss({14}, {28}, {1}, s_deadlayerThickness), + m_detectorEloss({14}, {28}, {1}, s_detectorThickness), m_degraderEloss({73}, {181}, {1}, s_degraderThickness) { - //Only 0, 1, 4 valid in degrader land - //detectors.emplace_back(0, INNER_R,OUTER_R,PHI_COVERAGE*DEG2RAD,PHI0*DEG2RAD,TILT*DEG2RAD,DIST_2_TARG); - //detectors.emplace_back(1, INNER_R,OUTER_R,PHI_COVERAGE*DEG2RAD,PHI1*DEG2RAD,TILT*DEG2RAD,DIST_2_TARG); - detectors.emplace_back(2, INNER_R,OUTER_R,PHI_COVERAGE*DEG2RAD,PHI2*DEG2RAD,TILT*DEG2RAD,DIST_2_TARG); - detectors.emplace_back(3, INNER_R,OUTER_R,PHI_COVERAGE*DEG2RAD,PHI3*DEG2RAD,TILT*DEG2RAD,DIST_2_TARG); - //detectors.emplace_back(4, INNER_R,OUTER_R,PHI_COVERAGE*DEG2RAD,PHI4*DEG2RAD,TILT*DEG2RAD,DIST_2_TARG); - - std::vector dead_z = {14}; - std::vector dead_a = {28}; - std::vector dead_stoich = {1}; - deadlayer.SetElements(dead_z, dead_a, dead_stoich); - sabre_eloss.SetElements(dead_z, dead_a, dead_stoich); - std::vector deg_z = {73}; - std::vector deg_a = {181}; - std::vector deg_s = {1}; - degrader.SetElements(deg_z, deg_a, deg_s); + for(int i=0; iGet("SimTree"); + std::vector* dataHandle = new std::vector(); + intree->SetBranchAddress("nuclei", &dataHandle); + + output->cd(); + TTree* outtree = new TTree("SimTree", "SimTree"); + outtree->Branch("nuclei", dataHandle); + + input->cd(); + + stats<<"Efficiency statistics for data from "<GetEntry(1); std::vector counts; std::vector coinc_counts; - switch(header.rxn_type) { - case Mask::RxnType::PureDecay: - counts.resize(3, 0); - coinc_counts.resize(1, 0); - break; - case Mask::RxnType::OneStepRxn: - counts.resize(4, 0); - coinc_counts.resize(1, 0); - break; - case Mask::RxnType::TwoStepRxn: - counts.resize(6, 0); - coinc_counts.resize(4, 0); - break; - case Mask::RxnType::ThreeStepRxn: - counts.resize(8, 0); - coinc_counts.resize(11, 0); - break; + counts.resize(dataHandle->size()); + switch(counts.size()) + { + case 3: coinc_counts.resize(1, 0); break; + case 4: coinc_counts.resize(1, 0); break; + case 6: coinc_counts.resize(4, 0); break; + case 8: coinc_counts.resize(11, 0); break; default: { - std::cerr<<"Bad reaction type at AnasenEfficiency::CalculateEfficiency (given value: "<Close(); + output->Close(); stats.close(); return; } } - int percent5 = header.nsamples*0.05; - int count = 0; - int npercent = 0; + uint64_t nentries = intree->GetEntries(); + uint64_t percent5 = nentries*0.05; + uint64_t count = 0; + uint64_t npercent = 0; - while(true) { - if(++count == percent5) {//Show progress every 5% + Mask::Nucleus nucleus; + for(uint64_t i=0; iGetEntry(i); + if(++count == percent5) + {//Show progress every 5% npercent++; count = 0; std::cout<<"\rPercent completed: "<size(); j++) + { + Mask::Nucleus& nucleus = (*dataHandle)[j]; + DetectorResult result = IsSabre(nucleus); + if(result.detectFlag) + { + nucleus.isDetected = true; + nucleus.detectedKE = result.energy_deposited; + nucleus.detectedTheta = result.direction.Theta(); + nucleus.detectedPhi = result.direction.Phi(); + counts[j]++; } } - CountCoincidences(data, coinc_counts, header.rxn_type); + CountCoincidences(*dataHandle, coinc_counts); - output.WriteData(data); + outtree->Fill(); } + input->Close(); + output->cd(); + outtree->Write(outtree->GetName(), TObject::kOverwrite); + output->Close(); - input.Close(); - output.Close(); + delete dataHandle; stats< ringxs, ringys, ringzs; std::vector wedgexs, wedgeys, wedgezs; - Mask::Vec3 coords; - for(int i=0; i<5; i++) { - for(int j=0; j SabreEfficiency::IsSabre(Mask::Nucleus& nucleus) { - if(nucleus.GetKE() <= ENERGY_THRESHOLD) { - return std::make_pair(false, 0.0); - } +DetectorResult SabreEfficiency::IsSabre(Mask::Nucleus& nucleus) +{ + DetectorResult observation; + if(nucleus.GetKE() <= s_energyThreshold) + return observation; - Mask::Vec3 coords; - double thetaIncident, eloss, e_deposited; + double thetaIncident; double ke = 0.0; - for(auto& detector : detectors) { - auto chan = detector.GetTrajectoryRingWedge(nucleus.GetTheta(), nucleus.GetPhi()); - if(chan.first != -1 && chan.second != -1) { - if(dmap.IsDead(detector.GetDetectorID(), chan.first, 0) || dmap.IsDead(detector.GetDetectorID(), chan.second, 1)) break; //dead channel check - coords = detector.GetTrajectoryCoordinates(nucleus.GetTheta(), nucleus.GetPhi()); - thetaIncident = std::acos(coords.Dot(detector.GetNormTilted())/(coords.GetR())); - //eloss = degrader.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), nucleus.GetKE(), thetaIncident); - //ke = nucleus.GetKE() - eloss; - eloss = deadlayer.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), ke, M_PI - thetaIncident); - ke = nucleus.GetKE() - eloss; - //ke -= eloss; - if(ke <= ENERGY_THRESHOLD) break; //deadlayer check - e_deposited = sabre_eloss.GetEnergyLossTotal(nucleus.GetZ(), nucleus.GetA(), ke, M_PI - thetaIncident); - return std::make_pair(true, e_deposited); - } + for(auto& detector : m_detectors) + { + if(!m_activeDetectors[detector.GetDetectorID()]) + continue; + + auto channel = detector.GetTrajectoryRingWedge(nucleus.vec4.Theta(), nucleus.vec4.Phi()); + if(channel.first == -1 || channel.second == -1) + continue; + if(m_deadMap.IsDead(detector.GetDetectorID(), channel.first, 0) || m_deadMap.IsDead(detector.GetDetectorID(), channel.second, 1)) + break; //dead channel check + + observation.detectFlag = true; + observation.direction = detector.GetTrajectoryCoordinates(nucleus.vec4.Theta(), nucleus.vec4.Phi()); + thetaIncident = std::acos(observation.direction.Dot(detector.GetNormTilted())/(observation.direction.R())); + + //Energy loss + ke = nucleus.GetKE(); + if(m_degradedDetectors[detector.GetDetectorID()]) + ke -= m_degraderEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, ke, M_PI - thetaIncident); + ke -= m_deadlayerEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, ke, M_PI - thetaIncident); + if(ke <= s_energyThreshold) + break; + + observation.det_name = "SABRE"+std::to_string(detector.GetDetectorID()); + observation.energy_deposited = m_detectorEloss.GetEnergyLossTotal(nucleus.Z, nucleus.A, ke, M_PI - thetaIncident); + return observation; } - return std::make_pair(false,0.0); + observation.detectFlag = false; + return observation; } -void SabreEfficiency::CountCoincidences(const Mask::MaskFileData& data, std::vector& counts, Mask::RxnType rxn_type) { - if (rxn_type == Mask::RxnType::PureDecay && data.detect_flag[1] && data.detect_flag[2]) +void SabreEfficiency::CountCoincidences(const std::vector& data, std::vector& counts) +{ + if (data.size() == 3 && data[1].isDetected && data[2].isDetected) { counts[0]++; } - else if (rxn_type == Mask::RxnType::OneStepRxn && data.detect_flag[2] && data.detect_flag[3]) + else if (data.size() == 4 && data[2].isDetected && data[3].isDetected) { counts[0]++; } - else if(rxn_type == Mask::RxnType::TwoStepRxn) + else if(data.size() == 6) { - if(data.detect_flag[2] && data.detect_flag[4]) + if(data[2].isDetected && data[4].isDetected) { counts[0]++; } - if(data.detect_flag[2] && data.detect_flag[5]) + if(data[2].isDetected && data[5].isDetected) { counts[1]++; } - if(data.detect_flag[4] && data.detect_flag[5]) + if(data[4].isDetected && data[5].isDetected) { counts[2]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[5]) + if(data[2].isDetected && data[4].isDetected && data[5].isDetected) { counts[3]++; } } - else if(rxn_type == Mask::RxnType::ThreeStepRxn) + else if(data.size() == 8) { - if(data.detect_flag[2] && data.detect_flag[4]) + if(data[2].isDetected && data[4].isDetected) { counts[0]++; } - if(data.detect_flag[2] && data.detect_flag[6]) + if(data[2].isDetected && data[6].isDetected) { counts[1]++; } - if(data.detect_flag[2] && data.detect_flag[7]) + if(data[2].isDetected && data[7].isDetected) { counts[2]++; } - if(data.detect_flag[4] && data.detect_flag[6]) + if(data[4].isDetected && data[6].isDetected) { counts[3]++; } - if(data.detect_flag[4] && data.detect_flag[7]) + if(data[4].isDetected && data[7].isDetected) { counts[4]++; } - if(data.detect_flag[6] && data.detect_flag[7]) + if(data[6].isDetected && data[7].isDetected) { counts[5]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[6]) + if(data[2].isDetected && data[4].isDetected && data[6].isDetected) { counts[6]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[7]) + if(data[2].isDetected && data[4].isDetected && data[7].isDetected) { counts[7]++; } - if(data.detect_flag[2] && data.detect_flag[6] && data.detect_flag[7]) + if(data[2].isDetected && data[6].isDetected && data[7].isDetected) { counts[8]++; } - if(data.detect_flag[4] && data.detect_flag[6] && data.detect_flag[7]) + if(data[4].isDetected && data[6].isDetected && data[7].isDetected) { counts[9]++; } - if(data.detect_flag[2] && data.detect_flag[4] && data.detect_flag[6] && data.detect_flag[7]) + if(data[2].isDetected && data[4].isDetected && data[6].isDetected && data[7].isDetected) { counts[10]++; } diff --git a/src/Detectors/SabreEfficiency.h b/src/Detectors/SabreEfficiency.h new file mode 100644 index 0000000..193f0f9 --- /dev/null +++ b/src/Detectors/SabreEfficiency.h @@ -0,0 +1,51 @@ +#ifndef SABREEFFICIENCY_H +#define SABREEFFICIENCY_H + +#include "DetectorEfficiency.h" +#include "SabreDetector.h" +#include "Target.h" +#include "SabreDeadChannelMap.h" +#include "Mask/Nucleus.h" + +class SabreEfficiency : public DetectorEfficiency +{ +public: + SabreEfficiency(); + ~SabreEfficiency(); + void SetDeadChannelMap(const std::string& filename) { m_deadMap.LoadMapfile(filename); }; + void CalculateEfficiency(const std::string& inputname, const std::string& outputname, const std::string& statsname) override; + void DrawDetectorSystem(const std::string& filename) override; + double RunConsistencyCheck() override; + +private: + DetectorResult IsSabre(Mask::Nucleus& nucleus); + void CountCoincidences(const std::vector& data, std::vector& counts); + + std::vector m_detectors; + + Mask::Target m_deadlayerEloss; + Mask::Target m_detectorEloss; + Mask::Target m_degraderEloss; + SabreDeadChannelMap m_deadMap; + + bool m_activeDetectors[5]; + bool m_degradedDetectors[5]; + + //Sabre constants + static constexpr double s_innerR = 0.0326; + static constexpr double s_outerR = 0.1351; + static constexpr double s_tilt = 40.0; + static constexpr double s_zOffset = -0.1245; + static constexpr double s_deltaPhi = 54.4; //delta phi for each det + static constexpr int s_nDets = 5; + static constexpr double s_centerPhiList[s_nDets] = {306.0, 18.0, 234.0, 162.0, 90.0}; + static constexpr double s_deg2rad = M_PI/180.0; + static constexpr double s_deadlayerThickness = 50 * 1e-7 * 2.3296 * 1e6; // ug/cm^2 (50 nm thick * density) + static constexpr double s_detectorThickness = 500 * 1e-4 * 2.3926 * 1e6; // ug/cm^2 (500 um thick * density) + static constexpr double s_degraderThickness = 70.0 * 1.0e-4 * 16.69 * 1e6; //tantalum degrader (70 um thick) + + static constexpr double s_energyThreshold = 0.25; //in MeV + +}; + +#endif diff --git a/src/Detectors/StripDetector.cpp b/src/Detectors/StripDetector.cpp index 3718e20..126e90f 100644 --- a/src/Detectors/StripDetector.cpp +++ b/src/Detectors/StripDetector.cpp @@ -17,32 +17,34 @@ */ StripDetector::StripDetector(int ns, double len, double wid, double cphi, double cz, double crho) : - m_norm_unrot(1.0,0.0,0.0), m_uniform_fraction(0.0, 1.0), rndmFlag(false) + m_norm(1.0,0.0,0.0), m_uniformFraction(0.0, 1.0), m_isSmearing(false) { - num_strips = ns; + m_nStrips = ns; - length = std::fabs(len); - total_width = std::fabs(wid); - front_strip_width = total_width/num_strips; - back_strip_length = length/num_strips; + m_stripLength = std::fabs(len); + m_totalWidth = std::fabs(wid); + m_frontStripWidth = m_totalWidth/m_nStrips; + m_backStripLength = m_stripLength/m_nStrips; - while (cphi < 0) cphi += 2*M_PI; - center_phi = cphi; - center_z = cz; - center_rho = std::fabs(crho); + while (cphi < 0) + cphi += 2*M_PI; + m_centerPhi = cphi; + m_centerZ = cz; + m_centerRho = std::fabs(crho); - zRot.SetAngle(center_phi); + m_zRotation.SetAngle(m_centerPhi); - front_strip_coords.resize(num_strips); - back_strip_coords.resize(num_strips); - rotated_front_strip_coords.resize(num_strips); - rotated_back_strip_coords.resize(num_strips); - for(int i=0; i M_PI) phi -= 2*M_PI; + if (phi > M_PI) + phi -= 2*M_PI; //then we can check easily whether it even hit the detector in phi - double det_max_phi = atan2(total_width/2,center_rho); + double det_max_phi = std::atan2(m_totalWidth/2,m_centerRho); double det_min_phi = -det_max_phi; - if (phi < det_min_phi || phi > det_max_phi) return hit; + if (phi < det_min_phi || phi > det_max_phi) + return hit; //for theta it's not so simple, so we have to go through the typical plane-intersect method //first thing's first: we have a fixed x for the entire detector plane: - double xhit = center_rho; + double xhit = m_centerRho; //thus we find the corresponding y and z for that fixed x, given the input theta and phi: double yhit = xhit*tan(phi); double zhit = sqrt(xhit*xhit+yhit*yhit)/tan(theta); - for (int s=0; s= front_strip_coords[s][0].GetX() && xhit <= front_strip_coords[s][0].GetX() && //Check min and max x (constant in flat) - yhit >= front_strip_coords[s][1].GetY() && yhit <= front_strip_coords[s][2].GetY() && //Check min and max y - zhit >= front_strip_coords[s][1].GetZ() && zhit <= front_strip_coords[s][0].GetZ()) //Check min and max z + for (int s=0; s=m_frontStripCoords[s][0].X() && xhit <=m_frontStripCoords[s][0].X() && //Check min and max x (constant in flat) + yhit >=m_frontStripCoords[s][1].Y() && yhit <=m_frontStripCoords[s][2].Y() && //Check min and max y + zhit >=m_frontStripCoords[s][1].Z() && zhit <=m_frontStripCoords[s][0].Z()) //Check min and max z { hit.front_strip_index = s; - hit.front_ratio = (zhit-center_z)/(length/2); + hit.front_ratio = (zhit-m_centerZ)/(m_stripLength/2); break; } } - for (int s=0; s= back_strip_coords[s][0].GetX() && xhit <= back_strip_coords[s][0].GetX() && //Check min and max x (constant in flat) - yhit >= back_strip_coords[s][1].GetY() && yhit <= back_strip_coords[s][2].GetY() && //Check min and max y - zhit >= back_strip_coords[s][1].GetZ() && zhit <= back_strip_coords[s][0].GetZ()) //Check min and max z + for (int s=0; s= m_backStripCoords[s][0].X() && xhit <= m_backStripCoords[s][0].X() && //Check min and max x (constant in flat) + yhit >= m_backStripCoords[s][1].Y() && yhit <= m_backStripCoords[s][2].Y() && //Check min and max y + zhit >= m_backStripCoords[s][1].Z() && zhit <= m_backStripCoords[s][0].Z()) //Check min and max z { hit.back_strip_index = s; break; diff --git a/src/Detectors/StripDetector.h b/src/Detectors/StripDetector.h new file mode 100644 index 0000000..cc6463a --- /dev/null +++ b/src/Detectors/StripDetector.h @@ -0,0 +1,82 @@ +#ifndef STRIP_DETECTOR_H +#define STRIP_DETECTOR_H + +// +z is along beam axis +// +y is vertically "downward" in the lab frame + +//angles must be in radians, but distances can be whatever +//PROVIDED all input distances are the same + +//Front strips from largest y to smallest y + +//Back strips from lowest z to highest z + +#include +#include + +#include "Math/Point3D.h" +#include "Math/Vector3D.h" +#include "Math/RotationZ.h" +#include "Mask/RandomGenerator.h" + +struct StripHit +{ + int front_strip_index=-1; + int back_strip_index=-1; + double front_ratio=0.0; +}; + +class StripDetector +{ +public: + + StripDetector(int ns, double len, double wid, double cphi, double cz, double crho); + ~StripDetector(); + const ROOT::Math::XYZPoint& GetFrontStripCoordinates(int stripch, int corner) const { return m_frontStripCoords[stripch][corner]; } + const ROOT::Math::XYZPoint& GetBackStripCoordinates(int stripch, int corner) const { return m_backStripCoords[stripch][corner]; } + const ROOT::Math::XYZPoint& GetRotatedFrontStripCoordinates(int stripch, int corner) const + { + return m_rotFrontStripCoords[stripch][corner]; + } + const ROOT::Math::XYZPoint& GetRotatedBackStripCoordinates(int stripch, int corner) const + { + return m_rotBackStripCoords[stripch][corner]; + } + ROOT::Math::XYZVector GetNormRotated() const { return m_zRotation * m_norm; } + + void SetPixelSmearing(bool isSmearing) { m_isSmearing = isSmearing; } + + ROOT::Math::XYZPoint GetHitCoordinates(int front_stripch, double front_strip_ratio); + StripHit GetChannelRatio(double theta, double phi); + +private: + bool ValidChannel(int f) { return ((f >= 0 && f < m_nStrips) ? true : false); }; + bool ValidRatio(double r) { return ((r >= -1 && r <= 1) ? true : false); }; + void CalculateCorners(); + + int m_nStrips; + static constexpr int s_nCorners = 4; + + double m_stripLength; //common to all strips, hence total + double m_totalWidth; + double m_frontStripWidth; //assuming equal widths + double m_backStripLength; //assuming equal widths + + double m_centerPhi; //assuming det centered above x-axis (corresponds to zero phi) + double m_centerZ; + double m_centerRho; //perpendicular radius from axis + + std::vector> m_frontStripCoords, m_backStripCoords; + std::vector> m_rotFrontStripCoords, m_rotBackStripCoords; + + ROOT::Math::XYZVector m_norm; + + ROOT::Math::RotationZ m_zRotation; + + std::uniform_real_distribution m_uniformFraction; + + bool m_isSmearing; + +}; + +#endif diff --git a/src/Detectors/DetectorEfficiency.cpp b/src/Detectors/main.cpp similarity index 71% rename from src/Detectors/DetectorEfficiency.cpp rename to src/Detectors/main.cpp index 3bc6e76..b03a378 100644 --- a/src/Detectors/DetectorEfficiency.cpp +++ b/src/Detectors/main.cpp @@ -4,9 +4,11 @@ #include #include -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ - if(argc != 4) { + if(argc != 4) + { std::cerr<<"Incorrect number of commandline arguments! Returning."<>junk>>l; - while(input>>junk) { + while(input>>junk) + { input>>par; - constants.push_back(par); + m_constants.push_back(par); } input.close(); - if(constants.size() != ((unsigned int) l+1)) { - std::cerr<<"Unexpected number of constants for given angular momentum! Expected "< branchingRatio) return -10; + test = m_uniformProbDist(RandomGenerator::GetInstance().GetGenerator()); + if(test > m_branchingRatio) + return -10; - do { + do + { probability = 0.0; - costheta = uniform_cosine_dist(RandomGenerator::GetInstance().GetGenerator()); - test = uniform_prob_dist(RandomGenerator::GetInstance().GetGenerator()); - for(unsigned int i=0; i probability); + costheta = m_uniformCosineDist(RandomGenerator::GetInstance().GetGenerator()); + test = m_uniformProbDist(RandomGenerator::GetInstance().GetGenerator()); + for(std::size_t i=0; i probability); return costheta; } diff --git a/src/Mask/AngularDistribution.h b/src/Mask/AngularDistribution.h new file mode 100644 index 0000000..df32809 --- /dev/null +++ b/src/Mask/AngularDistribution.h @@ -0,0 +1,35 @@ +#ifndef ANGULARDISTRIBUTION_H +#define ANGULARDISTRIBUTION_H + +#include +#include +#include + +namespace Mask { + + class AngularDistribution + { + public: + AngularDistribution(); + AngularDistribution(const std::string& file); + ~AngularDistribution(); + void ReadDistributionFile(const std::string& file); + double GetRandomCosTheta(); + int GetL() { return m_L; } + double GetBranchingRatio() { return m_branchingRatio; } + + private: + bool IsIsotropic() { return m_isIsotropic; } + + std::uniform_real_distribution m_uniformCosineDist; + std::uniform_real_distribution m_uniformProbDist; + + double m_branchingRatio; + int m_L; + std::vector m_constants; + bool m_isIsotropic; + }; + +} + +#endif \ No newline at end of file diff --git a/src/Mask/CMakeLists.txt b/src/Mask/CMakeLists.txt index cb12a41..ec14d3f 100644 --- a/src/Mask/CMakeLists.txt +++ b/src/Mask/CMakeLists.txt @@ -1,30 +1,56 @@ +add_library(MaskDict SHARED) +target_include_directories(MaskDict + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + SYSTEM PUBLIC ${ROOT_INCLUDE_DIRS} +) + +ROOT_GENERATE_DICTIONARY(mask_dict Nucleus.h LINKDEF LinkDef_Nucleus.h MODULE MaskDict) + +target_sources(MaskDict PRIVATE Nucleus.h Nucleus.cpp MassLookup.h MassLookup.cpp) +target_link_libraries(MaskDict ${ROOT_LIBRARIES}) +set_target_properties(MaskDict PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${MASK_LIBRARY_DIR}) +add_custom_command(TARGET MaskDict POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/libMaskDict_rdict.pcm + ${MASK_LIBRARY_DIR}/libMaskDict_rdict.pcm + ) + add_library(Mask STATIC) target_include_directories(Mask PUBLIC ${MASK_INCLUDE_DIR} + ${ROOT_INCLUDE_DIRS} ) target_sources(Mask PRIVATE AngularDistribution.cpp + AngularDistribution.h DecaySystem.cpp - EnergyLoss.cpp + DecaySystem.h LayeredTarget.cpp + LayeredTarget.h LegendrePoly.cpp + LegendrePoly.h MaskApp.cpp - MaskFile.cpp + MaskApp.h MassLookup.cpp - Nucleus.cpp + MassLookup.h OneStepSystem.cpp + OneStepSystem.h RandomGenerator.cpp + RandomGenerator.h Reaction.cpp + Reaction.h ReactionSystem.cpp - Rotation.cpp + ReactionSystem.h Stopwatch.cpp + Stopwatch.h Target.cpp + Target.h ThreeStepSystem.cpp + ThreeStepSystem.h TwoStepSystem.cpp - Vec3.cpp - Vec4.cpp + TwoStepSystem.h ) -target_link_libraries(Mask catima) -set_target_properties(Mask PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${MASK_LIBRARY_DIR}) \ No newline at end of file +target_link_libraries(Mask catima MaskDict ${ROOT_LIBRARIES}) +set_target_properties(Mask PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${MASK_LIBRARY_DIR}) \ No newline at end of file diff --git a/src/Mask/DecaySystem.cpp b/src/Mask/DecaySystem.cpp index 66846c4..11a562e 100644 --- a/src/Mask/DecaySystem.cpp +++ b/src/Mask/DecaySystem.cpp @@ -1,76 +1,81 @@ #include "DecaySystem.h" #include "RandomGenerator.h" +#include + namespace Mask { DecaySystem::DecaySystem() : ReactionSystem() { - nuclei.resize(3); + m_nuclei.resize(3); } - DecaySystem::DecaySystem(std::vector& z, std::vector& a) : + DecaySystem::DecaySystem(const std::vector& z, const std::vector& a) : ReactionSystem() { - nuclei.resize(3); + m_nuclei.resize(3); SetNuclei(z, a); } DecaySystem::~DecaySystem() {} - bool DecaySystem::SetNuclei(std::vector& z, std::vector& a) { - if(z.size() != a.size() || z.size() != 2) { + bool DecaySystem::SetNuclei(const std::vector& z, const std::vector& a) + { + if(z.size() != a.size() || z.size() != 2) return false; - } - step1.SetNuclei(z[0], a[0], 0, 0, z[1], a[1]); + int zr = z[0] - z[1]; + int ar = a[0] - a[1]; + + m_nuclei[0] = CreateNucleus(z[0], a[0]); //target + m_nuclei[1] = CreateNucleus(z[1], a[1]); //breakup1 + m_nuclei[2] = CreateNucleus(zr, ar); //breakup2 + + m_step1.BindNuclei(&(m_nuclei[0]), nullptr, &(m_nuclei[1]), &(m_nuclei[2])); SetSystemEquation(); return true; } - const std::vector& DecaySystem::GetNuclei() + std::vector* DecaySystem::GetNuclei() { - nuclei[0] = step1.GetTarget(); - nuclei[1] = step1.GetEjectile(); - nuclei[2] = step1.GetResidual(); - - return nuclei; + return &m_nuclei; } void DecaySystem::LinkTarget() { - step1.SetLayeredTarget(&target); + m_step1.SetLayeredTarget(&m_target); - rxnLayer = target.FindLayerContaining(step1.GetTarget().GetZ(), step1.GetTarget().GetA()); - if(rxnLayer != -1) { - step1.SetRxnLayer(rxnLayer); - target_set_flag = true; - } else { + m_rxnLayer = m_target.FindLayerContaining(m_nuclei[0].Z, m_nuclei[0].A); + if(m_rxnLayer != m_target.GetNumberOfLayers()) + { + m_step1.SetRxnLayer(m_rxnLayer); + m_isTargetSet = true; + } + else throw ReactionLayerException(); - } } - void DecaySystem::SetSystemEquation() { - m_sys_equation = step1.GetTarget().GetIsotopicSymbol(); - m_sys_equation += "-> "; - m_sys_equation += step1.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += "+"; - m_sys_equation += step1.GetResidual().GetIsotopicSymbol(); + void DecaySystem::SetSystemEquation() + { + std::stringstream stream; + stream << m_nuclei[0].isotopicSymbol << "->" + << m_nuclei[1].isotopicSymbol << "+" + << m_nuclei[2].isotopicSymbol; + m_sysEquation = stream.str(); } - void DecaySystem::RunSystem() { + void DecaySystem::RunSystem() + { //Link up the target if it hasn't been done yet - if(!target_set_flag) { + if(!m_isTargetSet) LinkTarget(); - } - double rxnTheta = std::acos(decay1dist.GetRandomCosTheta()); + double rxnTheta = std::acos(m_step1Distribution.GetRandomCosTheta()); double rxnPhi = (*m_phi1Range)(RandomGenerator::GetInstance().GetGenerator()); - step1.SetPolarRxnAngle(rxnTheta); - step1.SetAzimRxnAngle(rxnPhi); - - step1.TurnOnResidualEloss(); - step1.Calculate(); - + m_step1.SetPolarRxnAngle(rxnTheta); + m_step1.SetAzimRxnAngle(rxnPhi); + m_step1.SetResidualEnergyLoss(true); + m_step1.Calculate(); } } \ No newline at end of file diff --git a/src/Mask/DecaySystem.h b/src/Mask/DecaySystem.h new file mode 100644 index 0000000..5a2aaab --- /dev/null +++ b/src/Mask/DecaySystem.h @@ -0,0 +1,36 @@ +#ifndef DECAYSYSTEM_H +#define DECAYSYSTEM_H + +#include "ReactionSystem.h" +#include "AngularDistribution.h" + +namespace Mask { + + class DecaySystem: public ReactionSystem { + public: + DecaySystem(); + DecaySystem(const std::vector& z, const std::vector& a); + ~DecaySystem(); + + bool SetNuclei(const std::vector& z, const std::vector& a) override; + void RunSystem() override; + std::vector*GetNuclei() override; + + void SetDecay1Distribution(const std::string& filename) { m_step1Distribution.ReadDistributionFile(filename); } + + int GetDecay1AngularMomentum() { return m_step1Distribution.GetL(); } + double GetDecay1BranchingRatio() { return m_step1Distribution.GetBranchingRatio(); } + + private: + void LinkTarget() override; + void SetSystemEquation() override; + + Reaction m_step1; + + AngularDistribution m_step1Distribution; + + }; + +} + +#endif \ No newline at end of file diff --git a/include/KinematicsExceptions.h b/src/Mask/KinematicsExceptions.h similarity index 100% rename from include/KinematicsExceptions.h rename to src/Mask/KinematicsExceptions.h diff --git a/src/Mask/LayeredTarget.cpp b/src/Mask/LayeredTarget.cpp index cd74e6f..184f49c 100644 --- a/src/Mask/LayeredTarget.cpp +++ b/src/Mask/LayeredTarget.cpp @@ -16,17 +16,16 @@ Written by G.W. McCann Aug. 2020 namespace Mask { LayeredTarget::LayeredTarget() : - name(""), m_fractional_depth_dist(0.0, 1.0) + m_name(""), m_fractionalDepthDistribution(0.0, 1.0) { } LayeredTarget::~LayeredTarget() {} /*Add in a Target made of a compound defined by a set of Zs, As, Ss, and a thickness*/ - void LayeredTarget::AddLayer(std::vector& Z, std::vector& A, std::vector& stoich, double thickness) { - Target t(thickness); - t.SetElements(Z, A, stoich); - layers.push_back(t); + void LayeredTarget::AddLayer(const std::vector& Z, const std::vector& A, const std::vector& stoich, double thickness) + { + m_layers.emplace_back(Z, A, stoich, thickness); } /* @@ -34,9 +33,10 @@ namespace Mask { Calculates energy loss assuming that the reaction occurs in the middle of the target layer Note that the layer order can matter! */ - double LayeredTarget::GetProjectileEnergyLoss(int zp, int ap, double startEnergy, int rxnLayer, double angle) { - - if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) { + double LayeredTarget::GetProjectileEnergyLoss(int zp, int ap, double startEnergy, std::size_t rxnLayer, double angle) + { + if(rxnLayer > m_layers.size()) + { std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"< layers.size()) { + if(rxnLayer > m_layers.size()) + { std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<=0; i--) { - if(i == ((unsigned int)rxnLayer)) { - eloss += layers[i].GetEnergyLossFractionalDepth(ze, ae, newEnergy, angle, m_fractional_depth_dist(RandomGenerator::GetInstance().GetGenerator())); - newEnergy = startEnergy - eloss; - } else { - eloss += layers[i].GetEnergyLossTotal(ze, ae, newEnergy, angle); - newEnergy = startEnergy - eloss; - } + eloss += m_layers[rxnLayer].GetEnergyLossFractionalDepth(ze, ae, newEnergy, angle, m_fractionalDepthDistribution(gen.GetGenerator())); + newEnergy = startEnergy - eloss; + if(rxnLayer == 0) + return eloss; + + for(std::size_t i=rxnLayer-1; i>0; i--) //unsigned ints cant be less than 0 + { + eloss += m_layers[i].GetEnergyLossTotal(ze, ae, newEnergy, angle); + newEnergy = startEnergy - eloss; } + eloss += m_layers[0].GetEnergyLossTotal(ze, ae, newEnergy, angle); + newEnergy = startEnergy - eloss; } return eloss; } /*ReverseEnergyLoss version of GetEjectileEnergyLoss*/ - double LayeredTarget::GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle) { - - if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) { + double LayeredTarget::GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, std::size_t rxnLayer, double angle) + { + if(rxnLayer > m_layers.size()) + { std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<=rxnLayer; i--) { - if(i == rxnLayer) { - eloss += layers[i].GetReverseEnergyLossFractionalDepth(ze, ae, newEnergy, angle, m_fractional_depth_dist(RandomGenerator::GetInstance().GetGenerator())); - newEnergy = startEnergy + eloss; - } else { - eloss += layers[i].GetReverseEnergyLossTotal(ze, ae, newEnergy, angle); - newEnergy = startEnergy + eloss; - } + for(std::size_t i=(m_layers.size()-1); i>rxnLayer; i--) + { + eloss += m_layers[i].GetReverseEnergyLossTotal(ze, ae, newEnergy, angle); + newEnergy = startEnergy + eloss; } - } else { + eloss += m_layers[rxnLayer].GetReverseEnergyLossFractionalDepth(ze, ae, newEnergy, angle, m_fractionalDepthDistribution(gen.GetGenerator())); + newEnergy = startEnergy + eloss; + } + else + { double newEnergy = startEnergy; - for(int i=0; i <= rxnLayer; i++) { - if(i == rxnLayer) { - eloss += layers[i].GetReverseEnergyLossFractionalDepth(ze, ae, newEnergy, angle, m_fractional_depth_dist(RandomGenerator::GetInstance().GetGenerator())); - newEnergy = startEnergy + eloss; - } else { - eloss += layers[i].GetReverseEnergyLossTotal(ze, ae, newEnergy, angle); - newEnergy = startEnergy + eloss; - } + for(std::size_t i=0; i < rxnLayer; i++) + { + eloss += m_layers[i].GetReverseEnergyLossTotal(ze, ae, newEnergy, angle); + newEnergy = startEnergy + eloss; } + eloss += m_layers[rxnLayer].GetReverseEnergyLossFractionalDepth(ze, ae, newEnergy, angle, m_fractionalDepthDistribution(gen.GetGenerator())); + newEnergy = startEnergy + eloss; } return eloss; } - int LayeredTarget::FindLayerContaining(int Z, int A) { - for(unsigned int i=0; i& Z, std::vector& A, std::vector& stoich, double thickness); - double GetProjectileEnergyLoss(int zp, int ap, double startEnergy, int rxnLayer, double angle); - double GetEjectileEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle); - double GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle); - int FindLayerContaining(int Z, int A); - inline int GetNumberOfLayers() { return layers.size(); } - inline void SetName(std::string& n) { name = n; } - inline const Target& GetLayerInfo(int index) { return layers[index]; } - inline const std::string& GetName() { return name; } + void AddLayer(const std::vector& Z, const std::vector& A, const std::vector& stoich, double thickness); + double GetProjectileEnergyLoss(int zp, int ap, double startEnergy, std::size_t rxnLayer, double angle); + double GetEjectileEnergyLoss(int ze, int ae, double startEnergy, std::size_t rxnLayer, double angle); + double GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, std::size_t rxnLayer, double angle); + std::size_t FindLayerContaining(int Z, int A); + std::size_t GetNumberOfLayers() { return m_layers.size(); } + void SetName(std::string& n) { m_name = n; } + const Target& GetLayerInfo(int index) { return m_layers[index]; } + const std::string& GetName() { return m_name; } private: - std::vector layers; - std::string name; - std::uniform_real_distribution m_fractional_depth_dist; + std::vector m_layers; + std::string m_name; + std::uniform_real_distribution m_fractionalDepthDistribution; }; } diff --git a/src/Mask/LegendrePoly.cpp b/src/Mask/LegendrePoly.cpp index a326a94..7dd310a 100644 --- a/src/Mask/LegendrePoly.cpp +++ b/src/Mask/LegendrePoly.cpp @@ -3,33 +3,38 @@ namespace Mask { - double P_l(int l, double x) { - if(l == 0) { + double P_l(int l, double x) + { + if(l == 0) return 1.0; - } else if (l == 1) { + else if (l == 1) return x; - } else { + else return (2.0*l - 1.0)/l*x*P_l(l-1, x) - (l-1.0)/l*P_l(l-2, x); - } } - double Normed_P_l_sq(int l, double x) { + double Normed_P_l_sq(int l, double x) + { return (2.0*l+1.0)/2.0*std::pow(P_l(l, x), 2.0); } - double P_0(double x) { + double P_0(double x) + { return 1.0; } - double P_1(double x) { + double P_1(double x) + { return x; } - double P_2(double x) { + double P_2(double x) + { return 0.5*(3.0*x*x -1.0); } - double P_l_ROOT(double* x, double* pars) { + double P_l_ROOT(double* x, double* pars) + { return P_l(pars[0], x[0]); } diff --git a/include/LegendrePoly.h b/src/Mask/LegendrePoly.h similarity index 69% rename from include/LegendrePoly.h rename to src/Mask/LegendrePoly.h index 6e9f04b..0c1174e 100644 --- a/include/LegendrePoly.h +++ b/src/Mask/LegendrePoly.h @@ -4,7 +4,7 @@ namespace Mask { double P_l(int l, double x); - double P_l_ROOT(double* x, double* pars); + double P_l_ROOT(double* x, double* pars); //Only for use with ROOT cern in plotting double Normed_P_l_sq(int l, double x); double P_0(double x); diff --git a/src/Mask/LinkDef_Nucleus.h b/src/Mask/LinkDef_Nucleus.h new file mode 100644 index 0000000..68c436c --- /dev/null +++ b/src/Mask/LinkDef_Nucleus.h @@ -0,0 +1,7 @@ +#ifdef __CLING__ + +#pragma link C++ struct Mask::Nucleus+; +#pragma link C++ class std::vector+; +#pragma link C++ class std::string+; + +#endif \ No newline at end of file diff --git a/src/Mask/MaskApp.cpp b/src/Mask/MaskApp.cpp index fb7ee7a..490b3e4 100644 --- a/src/Mask/MaskApp.cpp +++ b/src/Mask/MaskApp.cpp @@ -1,19 +1,21 @@ #include "MaskApp.h" -#include "MaskFile.h" #include #include +#include "TFile.h" +#include "TTree.h" + namespace Mask { MaskApp::MaskApp() : - m_sys(nullptr) + m_system(nullptr) { std::cout<<"----------GWM Kinematics Simulation----------"<>junk>>m_outfile_name; + input>>junk>>m_outputName; std::vector avec, zvec, svec; int z, a, s; getline(input, junk); getline(input, junk); input>>junk>>junk; - m_rxn_type = GetRxnTypeFromString(junk); + m_rxnType = GetRxnTypeFromString(junk); getline(input, junk); getline(input, junk); - switch(m_rxn_type) + switch(m_rxnType) { case RxnType::PureDecay: { - m_sys = new DecaySystem(); - m_rxn_type = RxnType::PureDecay; - for(int i=0; i<2; i++) { + m_system = new DecaySystem(); + for(int i=0; i<2; i++) + { input>>z>>a; avec.push_back(a); zvec.push_back(z); @@ -53,20 +55,21 @@ namespace Mask { } case RxnType::OneStepRxn: { - m_sys = new OneStepSystem(); - m_rxn_type = RxnType::OneStepRxn; - for(int i=0; i<3; i++) { + m_system = new OneStepSystem(); + for(int i=0; i<3; i++) + { input>>z>>a; avec.push_back(a); zvec.push_back(z); } + std::cout<<"here"<>z>>a; avec.push_back(a); zvec.push_back(z); @@ -75,9 +78,9 @@ namespace Mask { } case RxnType::ThreeStepRxn: { - m_sys = new ThreeStepSystem(); - m_rxn_type = RxnType::ThreeStepRxn; - for(int i=0; i<5; i++) { + m_system = new ThreeStepSystem(); + for(int i=0; i<5; i++) + { input>>z>>a; avec.push_back(a); zvec.push_back(z); @@ -87,7 +90,7 @@ namespace Mask { default: return false; } - m_sys->SetNuclei(zvec, avec); + m_system->SetNuclei(zvec, avec); int nlayers; double thickness; @@ -110,7 +113,7 @@ namespace Mask { input>>z>>a>>s; zvec.push_back(z); avec.push_back(a); svec.push_back(s); } - m_sys->AddTargetLayer(zvec, avec, svec, thickness); + m_system->AddTargetLayer(zvec, avec, svec, thickness); input>>junk; } std::cout<<"Reaction equation: "<>junk>>m_nsamples; input>>junk>>par1>>junk>>par2; - m_sys->SetBeamDistro(par1, par2); + m_system->SetBeamDistro(par1, par2); input>>junk>>par1; - switch(m_rxn_type) + switch(m_rxnType) { case RxnType::PureDecay : break; case RxnType::None : break; case RxnType::OneStepRxn : { - dynamic_cast(m_sys)->SetReactionThetaType(par1); + dynamic_cast(m_system)->SetReactionThetaType(par1); break; } case RxnType::TwoStepRxn : { - dynamic_cast(m_sys)->SetReactionThetaType(par1); + dynamic_cast(m_system)->SetReactionThetaType(par1); break; } case RxnType::ThreeStepRxn : { - dynamic_cast(m_sys)->SetReactionThetaType(par1); + dynamic_cast(m_system)->SetReactionThetaType(par1); break; } } input>>junk>>par1>>junk>>par2; - m_sys->SetTheta1Range(par1, par2); + m_system->SetTheta1Range(par1, par2); input>>junk>>par1>>junk>>par2; - m_sys->SetPhi1Range(par1, par2); + m_system->SetPhi1Range(par1, par2); input>>junk>>par1>>junk>>par2; - m_sys->SetExcitationDistro(par1, par2); + m_system->SetExcitationDistro(par1, par2); input>>junk>>dfile1; input>>junk>>dfile2; - switch(m_rxn_type) + switch(m_rxnType) { - case RxnType::PureDecay : break; - case RxnType::None : break; - case RxnType::OneStepRxn : + case RxnType::PureDecay : { - DecaySystem* this_sys = dynamic_cast(m_sys); + DecaySystem* this_sys = dynamic_cast(m_system); this_sys->SetDecay1Distribution(dfile1); std::cout<<"Decay1 angular momentum: "<GetDecay1AngularMomentum()<GetDecay1BranchingRatio()<(m_sys); + TwoStepSystem* this_sys = dynamic_cast(m_system); this_sys->SetDecay1Distribution(dfile1); std::cout<<"Decay1 angular momentum: "<GetDecay1AngularMomentum()<GetDecay1BranchingRatio()<(m_sys); + ThreeStepSystem* this_sys = dynamic_cast(m_system); this_sys->SetDecay1Distribution(dfile1); this_sys->SetDecay2Distribution(dfile2); std::cout<<"Decay1 angular momentum: "<GetDecay1AngularMomentum()<<" Decay2 angular momentum: "<GetDecay2AngularMomentum()<Branch("nuclei", m_system->GetNuclei()); //For progress tracking uint32_t percent5 = 0.05*m_nsamples; @@ -214,11 +218,12 @@ namespace Mask { std::cout<<"\rPercent complete: "<RunSystem(); - output.WriteData(m_sys->GetNuclei()); + m_system->RunSystem(); + tree->Fill(); } - output.Close(); + tree->Write(tree->GetName(), TObject::kOverwrite); + output->Close(); std::cout<GetSystemEquation(); } + const std::string GetOutputName() const { return m_outputName; } + const RxnType GetReactionType() const { return m_rxnType; } + + void Run(); + + private: + ReactionSystem* m_system; + std::string m_outputName; + RxnType m_rxnType; + int m_nsamples; + + }; + +} + +#endif diff --git a/src/Mask/MassLookup.cpp b/src/Mask/MassLookup.cpp index 5d9c1f3..4bd1e7c 100644 --- a/src/Mask/MassLookup.cpp +++ b/src/Mask/MassLookup.cpp @@ -10,38 +10,41 @@ Written by G.W. McCann Aug. 2020 */ #include "MassLookup.h" #include "KinematicsExceptions.h" +#include namespace Mask { - - MassLookup::MassLookup() { - + MassLookup* MassLookup::s_instance = new MassLookup(); + + MassLookup::MassLookup() + { std::ifstream massfile("etc/mass.txt"); - if(massfile.is_open()) { - std::string junk, A, element; - int Z; + KeyPair key; + if(massfile.is_open()) + { + std::string junk, element; double atomicMassBig, atomicMassSmall, isotopicMass; getline(massfile,junk); getline(massfile,junk); - while(massfile>>junk) { - massfile>>Z>>A>>element>>atomicMassBig>>atomicMassSmall; - isotopicMass = (atomicMassBig + atomicMassSmall*1e-6 - Z*electron_mass)*u_to_mev; - std::string key = "("+std::to_string(Z)+","+A+")"; - massTable[key] = isotopicMass; - elementTable[Z] = element; + while(massfile>>junk) + { + massfile>>key.Z>>key.A>>element>>atomicMassBig>>atomicMassSmall; + isotopicMass = (atomicMassBig + atomicMassSmall*1e-6 - key.Z*electron_mass)*u_to_mev; + massTable[key.GetID()] = isotopicMass; + elementTable[key.GetID()] = std::to_string(key.A) + element; } - } else { - throw MassFileException(); } + else + throw MassFileException(); } - MassLookup::~MassLookup() { - } + MassLookup::~MassLookup() {} //Returns nuclear mass in MeV - double MassLookup::FindMass(int Z, int A) { - std::string key = "("+std::to_string(Z)+","+std::to_string(A)+")"; - auto data = massTable.find(key); + double MassLookup::FindMass(int Z, int A) + { + KeyPair key({Z, A}); + auto data = massTable.find(key.GetID()); if(data == massTable.end()) throw MassException(); @@ -49,13 +52,14 @@ namespace Mask { } //returns element symbol - std::string MassLookup::FindSymbol(int Z, int A) { - auto data = elementTable.find(Z); + std::string MassLookup::FindSymbol(int Z, int A) + { + KeyPair key({Z, A}); + auto data = elementTable.find(key.GetID()); if(data == elementTable.end()) throw MassException(); - std::string fullsymbol = std::to_string(A) + data->second; - return fullsymbol; + return data->second; } } \ No newline at end of file diff --git a/include/MassLookup.h b/src/Mask/MassLookup.h similarity index 63% rename from include/MassLookup.h rename to src/Mask/MassLookup.h index 5bba409..61220cf 100644 --- a/include/MassLookup.h +++ b/src/Mask/MassLookup.h @@ -18,22 +18,35 @@ Converted to true singleton to simplify usage -- Aug. 2021 GWM namespace Mask { - class MassLookup { + class MassLookup + { public: + + struct KeyPair + { + uint32_t Z; + uint32_t A; + + //Use szudzik pairing method to make unqiue key out of two unsigned ints. Use size_t as extra safety. + std::size_t GetID() + { + return Z >= A ? Z*Z + Z + A : A*A + Z; + } + }; + ~MassLookup(); double FindMass(int Z, int A); double FindMassU(int Z, int A) { return FindMass(Z, A)/u_to_mev; } std::string FindSymbol(int Z, int A); - static MassLookup& GetInstance() { - static MassLookup s_instance; - return s_instance; - } + static MassLookup& GetInstance() { return *s_instance; } private: MassLookup(); - std::unordered_map massTable; - std::unordered_map elementTable; + + static MassLookup* s_instance; + std::unordered_map massTable; + std::unordered_map elementTable; //constants static constexpr double u_to_mev = 931.4940954; diff --git a/src/Mask/Nucleus.cpp b/src/Mask/Nucleus.cpp new file mode 100644 index 0000000..d375fb3 --- /dev/null +++ b/src/Mask/Nucleus.cpp @@ -0,0 +1,17 @@ +#include "Nucleus.h" + +namespace Mask { + + Nucleus CreateNucleus(int z, int a) + { + Nucleus nuc; + nuc.Z = z; + nuc.A = a; + nuc.groundStateMass = MassLookup::GetInstance().FindMass(z, a); + nuc.isotopicSymbol = MassLookup::GetInstance().FindSymbol(z, a); + nuc.vec4 = ROOT::Math::PxPyPzEVector(0., 0., 0., nuc.groundStateMass); + return nuc; + } + + bool EnforceDictionaryLinked() { return true; } +} \ No newline at end of file diff --git a/src/Mask/Nucleus.h b/src/Mask/Nucleus.h new file mode 100644 index 0000000..d5b4b47 --- /dev/null +++ b/src/Mask/Nucleus.h @@ -0,0 +1,59 @@ +/* + Nucleus.h + Nucleus is a derived class of Vec4. A nucleus is the kinematics is essentially a 4 vector with the + additional properties of the number of total nucleons (A), the number of protons (Z), a ground state mass, + an exctitation energy, and an isotopic symbol. + + --GWM Jan 2021 +*/ +#ifndef NUCLEUS_H +#define NUCLEUS_H + +#include +#include +#include "Math/Vector4D.h" +#include "MassLookup.h" + +namespace Mask { + + struct Nucleus + { + void SetVec4Spherical(double theta, double phi, double p, double E) + { + vec4.SetPxPyPzE(std::sin(theta)*std::cos(phi)*p, + std::sin(theta)*std::sin(phi)*p, + std::cos(theta)*p, + E + ); + } + + double GetKE() const + { + return vec4.E() - vec4.M(); + } + + double GetExcitationEnergy() const + { + return vec4.M() - groundStateMass; + } + + int Z = 0; + int A = 0; + double groundStateMass = 0.0; + std::string isotopicSymbol = ""; + double thetaCM = 0.0; + ROOT::Math::PxPyPzEVector vec4; + + bool isDetected = false; + double detectedKE = 0.0; + double detectedTheta = 0.0; + double detectedPhi = 0.0; + }; + + Nucleus CreateNucleus(int z, int a); + + bool EnforceDictionaryLinked(); + +}; + +#endif diff --git a/src/Mask/OneStepSystem.cpp b/src/Mask/OneStepSystem.cpp index 1641d3e..acf269f 100644 --- a/src/Mask/OneStepSystem.cpp +++ b/src/Mask/OneStepSystem.cpp @@ -1,68 +1,76 @@ #include "OneStepSystem.h" #include "RandomGenerator.h" +#include + namespace Mask { OneStepSystem::OneStepSystem() : ReactionSystem() { - nuclei.resize(4); + m_nuclei.resize(4); } - OneStepSystem::OneStepSystem(std::vector& z, std::vector& a) : + OneStepSystem::OneStepSystem(const std::vector& z, const std::vector& a) : ReactionSystem() { - nuclei.resize(4); + m_nuclei.resize(4); SetNuclei(z, a); } OneStepSystem::~OneStepSystem() {} - bool OneStepSystem::SetNuclei(std::vector& z, std::vector& a) { - if(z.size() != a.size() || z.size() != 3) { + bool OneStepSystem::SetNuclei(const std::vector& z, const std::vector& a) + { + if(z.size() != a.size() || z.size() != 3) return false; - } - - step1.SetNuclei(z[0], a[0], z[1], a[1], z[2], a[2]); + + int zr = z[0] + z[1] - z[2]; + int ar = a[0] + a[1] - a[2]; + + m_nuclei[0] = CreateNucleus(z[0], a[0]); //target + m_nuclei[1] = CreateNucleus(z[1], a[1]); //projectile + m_nuclei[2] = CreateNucleus(z[2], a[2]); //ejectile + m_nuclei[3] = CreateNucleus(zr, ar); //residual + + m_step1.BindNuclei(&(m_nuclei[0]), &(m_nuclei[1]), &(m_nuclei[2]), &(m_nuclei[3])); SetSystemEquation(); return true; } - const std::vector& OneStepSystem::GetNuclei() + std::vector* OneStepSystem::GetNuclei() { - nuclei[0] = step1.GetTarget(); - nuclei[1] = step1.GetProjectile(); - nuclei[2] = step1.GetEjectile(); - nuclei[3] = step1.GetResidual(); - - return nuclei; + return &m_nuclei; } - void OneStepSystem::LinkTarget() { - step1.SetLayeredTarget(&target); + void OneStepSystem::LinkTarget() + { + m_step1.SetLayeredTarget(&m_target); - rxnLayer = target.FindLayerContaining(step1.GetTarget().GetZ(), step1.GetTarget().GetA()); - if(rxnLayer != -1) { - step1.SetRxnLayer(rxnLayer); - target_set_flag = true; - } else { - throw ReactionLayerException(); + m_rxnLayer = m_target.FindLayerContaining(m_nuclei[0].Z, m_nuclei[0].A); + if(m_rxnLayer != m_target.GetNumberOfLayers()) + { + m_step1.SetRxnLayer(m_rxnLayer); + m_isTargetSet = true; } + else + throw ReactionLayerException(); } - void OneStepSystem::SetSystemEquation() { - m_sys_equation = step1.GetTarget().GetIsotopicSymbol(); - m_sys_equation += "("; - m_sys_equation += step1.GetProjectile().GetIsotopicSymbol(); - m_sys_equation += ", "; - m_sys_equation += step1.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += ")"; - m_sys_equation += step1.GetResidual().GetIsotopicSymbol(); + void OneStepSystem::SetSystemEquation() + { + std::stringstream stream; + stream << m_nuclei[0].isotopicSymbol << "(" + << m_nuclei[1].isotopicSymbol << ", " + << m_nuclei[2].isotopicSymbol << ")" + << m_nuclei[3].isotopicSymbol; + m_sysEquation = stream.str(); } void OneStepSystem::RunSystem() { //Link up the target if it hasn't been done yet - if(!target_set_flag) { + if(!m_isTargetSet) + { LinkTarget(); } @@ -72,13 +80,13 @@ namespace Mask { double rxnPhi = (*m_phi1Range)(RandomGenerator::GetInstance().GetGenerator()); double residEx = (*m_exDist)(RandomGenerator::GetInstance().GetGenerator()); - step1.SetBeamKE(bke); - step1.SetPolarRxnAngle(rxnTheta); - step1.SetAzimRxnAngle(rxnPhi); - step1.SetExcitation(residEx); + m_step1.SetBeamKE(bke); + m_step1.SetPolarRxnAngle(rxnTheta); + m_step1.SetAzimRxnAngle(rxnPhi); + m_step1.SetExcitation(residEx); - step1.TurnOnResidualEloss(); - step1.Calculate(); + m_step1.SetResidualEnergyLoss(true); + m_step1.Calculate(); } } \ No newline at end of file diff --git a/src/Mask/OneStepSystem.h b/src/Mask/OneStepSystem.h new file mode 100644 index 0000000..6e7a352 --- /dev/null +++ b/src/Mask/OneStepSystem.h @@ -0,0 +1,30 @@ +#ifndef ONESTEPSYSTEM_H +#define ONESTEPSYSTEM_H + +#include "ReactionSystem.h" + +namespace Mask { + + class OneStepSystem: public ReactionSystem { + public: + OneStepSystem(); + OneStepSystem(const std::vector& z, const std::vector& a); + ~OneStepSystem(); + + bool SetNuclei(const std::vector& z, const std::vector& a) override; + void RunSystem() override; + std::vector* GetNuclei() override; + + void SetReactionThetaType(int type) { m_step1.SetEjectileThetaType(type); }; + + private: + void LinkTarget() override; + void SetSystemEquation() override; + + Reaction m_step1; + + }; + +} + +#endif \ No newline at end of file diff --git a/src/Mask/RandomGenerator.cpp b/src/Mask/RandomGenerator.cpp index 5453786..1153103 100644 --- a/src/Mask/RandomGenerator.cpp +++ b/src/Mask/RandomGenerator.cpp @@ -1,11 +1,13 @@ #include "RandomGenerator.h" namespace Mask { - RandomGenerator::RandomGenerator() { + RandomGenerator* RandomGenerator::s_instance = new RandomGenerator(); + + RandomGenerator::RandomGenerator() + { std::random_device rd; rng.seed(rd()); } - RandomGenerator::~RandomGenerator() { - } + RandomGenerator::~RandomGenerator() {} } \ No newline at end of file diff --git a/src/Mask/RandomGenerator.h b/src/Mask/RandomGenerator.h new file mode 100644 index 0000000..fd8a0b2 --- /dev/null +++ b/src/Mask/RandomGenerator.h @@ -0,0 +1,24 @@ +#ifndef RANDOMGENERATOR_H +#define RANDOMGENERATOR_H + +#include + +namespace Mask { + + class RandomGenerator + { + public: + ~RandomGenerator(); + std::mt19937& GetGenerator() { return rng; } + static RandomGenerator& GetInstance() { return *s_instance; } + + private: + RandomGenerator(); + + static RandomGenerator* s_instance; + std::mt19937 rng; + }; + +} + +#endif \ No newline at end of file diff --git a/src/Mask/Reaction.cpp b/src/Mask/Reaction.cpp index bf9e26e..e77e144 100644 --- a/src/Mask/Reaction.cpp +++ b/src/Mask/Reaction.cpp @@ -1,4 +1,4 @@ -/* +/*ayer Reaction.cpp Reaction is a class which implements either a decay or scattering reaction. As such it requires either 3 (decay) or 4 (scattering) nuclei to perform any calcualtions. I also links together the target, which provides @@ -9,29 +9,33 @@ #include "Reaction.h" #include "KinematicsExceptions.h" +#include "Math/Boost.h" + namespace Mask { Reaction::Reaction() : - target(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), rxnLayer(0), m_eject_theta_type(lab), nuc_initFlag(false), resid_elossFlag(false) + m_target(nullptr), m_projectile(nullptr), m_ejectile(nullptr), m_residual(nullptr), m_layeredTarget(nullptr), + m_bke(0), m_theta(0), m_phi(0), m_ex(0), m_rxnLayer(0), m_ejectThetaType(s_lab), m_isInit(false), m_isResidEloss(false) { } - Reaction::Reaction(int zt, int at, int zp, int ap, int ze, int ae) : - target(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), rxnLayer(0), m_eject_theta_type(lab), resid_elossFlag(false) + Reaction::Reaction(Nucleus* target, Nucleus* projectile, Nucleus* ejectile, Nucleus* residual) : + m_target(nullptr), m_projectile(nullptr), m_ejectile(nullptr), m_residual(nullptr), + m_layeredTarget(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), m_rxnLayer(0), m_ejectThetaType(s_lab), m_isResidEloss(false) { - SetNuclei(zt, at, zp, ap, ze, ae); + BindNuclei(target, projectile, ejectile, residual); } Reaction::~Reaction() { } - bool Reaction::Calculate() { - - if(!nuc_initFlag) + bool Reaction::Calculate() + { + if(!m_isInit) return false; - if(decayFlag) { + if(m_isDecay) { CalculateDecay(); return true; } else { @@ -40,203 +44,184 @@ namespace Mask { } } - //Deep copy of nucleus array - void Reaction::SetNuclei(const Nucleus* nucs) { - reactants[0] = nucs[0]; - reactants[1] = nucs[1]; - reactants[2] = nucs[2]; - reactants[3] = nucs[3]; - nuc_initFlag = true; + void Reaction::BindNuclei(Nucleus* target, Nucleus* projectile, Nucleus* ejectile, Nucleus* residual) + { + m_target = target; + m_projectile = projectile; + m_ejectile = ejectile; + m_residual = residual; + + if(m_projectile == nullptr) + m_isDecay = true; + else + m_isDecay = false; + + if(m_target == nullptr || m_ejectile == nullptr || m_residual == nullptr) + m_isInit = false; + else + m_isInit = true; } - void Reaction::SetNuclei(int zt, int at, int zp, int ap, int ze, int ae) { - int zr, ar; - reactants[0] = Nucleus(zt, at); - reactants[2] = Nucleus(ze, ae); - if(ap == 0) { - decayFlag = true; - zr = zt - ze; - ar = at - ae; - } else { - reactants[1] = Nucleus(zp, ap); - decayFlag = false; - zr = zt + zp - ze; - ar = at + ap - ae; - } - - if(zr < 0 || ar <= 0) { - nuc_initFlag = false; - } else { - reactants[3] = Nucleus(zr, ar); - nuc_initFlag = true; - } - } - - void Reaction::SetBeamKE(double bke) { - if(!nuc_initFlag || decayFlag) + void Reaction::SetBeamKE(double bke) + { + if(!m_isInit || m_isDecay) return; - m_bke = bke - target->GetProjectileEnergyLoss(reactants[1].GetZ(), reactants[1].GetA(), bke, rxnLayer, 0); + m_bke = bke - m_layeredTarget->GetProjectileEnergyLoss(m_projectile->Z, m_projectile->A, bke, m_rxnLayer, 0); } - void Reaction::SetEjectileThetaType(int type) { - if(decayFlag) return; - if(type != center_of_mass && type != lab) return; + void Reaction::SetEjectileThetaType(int type) + { + if(m_isDecay) + return; + if(type != s_centerOfMass && type != s_lab) + return; - m_eject_theta_type = type; + m_ejectThetaType = type; } //Methods given by Iliadis in Nuclear Physics of Stars, Appendix C //For use with lab frame restricted angles. May not give appropriate disribution for ejectile - void Reaction::CalculateReactionThetaLab() { - reactants[0].SetVectorCartesian(0.,0.,0.,reactants[0].GetGroundStateMass()); - double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * reactants[1].GetGroundStateMass())); - double beam_E = m_bke + reactants[1].GetGroundStateMass(); - reactants[1].SetVectorCartesian(0.,0.,beam_pz,beam_E); + void Reaction::CalculateReactionThetaLab() + { + m_target->vec4.SetPxPyPzE(0.,0.,0.,m_target->groundStateMass); + double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * m_projectile->groundStateMass)); + double beam_E = m_bke + m_projectile->groundStateMass; + m_projectile->vec4.SetPxPyPzE(0.,0.,beam_pz,beam_E); - double Q = reactants[0].GetGroundStateMass() + reactants[1].GetGroundStateMass() - (reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() + m_ex); + double Q = m_target->groundStateMass + m_projectile->groundStateMass - (m_ejectile->groundStateMass + m_residual->groundStateMass + m_ex); - double Ethresh = -Q*(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())/(reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass()); - if(m_bke < Ethresh) { + double Ethresh = -Q*(m_ejectile->groundStateMass+m_residual->groundStateMass) / + (m_ejectile->groundStateMass + m_residual->groundStateMass - m_projectile->groundStateMass); + if(m_bke < Ethresh) throw EnergyThresholdException(); - } - double term1 = sqrt(reactants[1].GetGroundStateMass()*reactants[2].GetGroundStateMass()*m_bke)/(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())*cos(m_theta); - double term2 = (m_bke*(reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass()) + reactants[3].GetGroundStateMass()*Q)/(reactants[3].GetGroundStateMass() + reactants[2].GetGroundStateMass()); - double sqrt_pos_ejectKE = term1 + sqrt(term1*term1 + term2); - double sqrt_neg_ejectKE = term1 - sqrt(term1*term1 + term2); + double term1 = std::sqrt(m_projectile->groundStateMass * m_ejectile->groundStateMass * m_bke)/ + (m_ejectile->groundStateMass + m_residual->groundStateMass) * std::cos(m_theta); + double term2 = (m_bke * (m_residual->groundStateMass - m_projectile->groundStateMass) + m_residual->groundStateMass*Q) / + (m_residual->groundStateMass + m_ejectile->groundStateMass); + double sqrt_pos_ejectKE = term1 + std::sqrt(term1*term1 + term2); + double sqrt_neg_ejectKE = term1 - std::sqrt(term1*term1 + term2); double ejectKE; - if(sqrt_pos_ejectKE > 0) { + if(sqrt_pos_ejectKE > 0) ejectKE = sqrt_pos_ejectKE*sqrt_pos_ejectKE; - } else { + else ejectKE = sqrt_neg_ejectKE*sqrt_neg_ejectKE; - } - double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass())); - double ejectE = ejectKE + reactants[2].GetGroundStateMass(); + + double ejectP = std::sqrt(ejectKE * (ejectKE + 2.0 * m_ejectile->groundStateMass)); + double ejectE = ejectKE + m_ejectile->groundStateMass; - reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP, ejectE); + m_ejectile->SetVec4Spherical(m_theta, m_phi, ejectP, ejectE); - reactants[3] = reactants[0] + reactants[1] - reactants[2]; + m_residual->vec4 = m_target->vec4 + m_projectile->vec4 - m_ejectile->vec4; - ejectKE -= target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), ejectKE, rxnLayer, m_theta); - ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass())); - ejectE = ejectKE + reactants[2].GetGroundStateMass(); - reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP, ejectE); + ejectKE -= m_layeredTarget->GetEjectileEnergyLoss(m_ejectile->Z, m_ejectile->A, ejectKE, m_rxnLayer, m_theta); + ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * m_ejectile->groundStateMass)); + ejectE = ejectKE + m_ejectile->groundStateMass; + m_ejectile->SetVec4Spherical(m_theta, m_phi, ejectP, ejectE); - if(resid_elossFlag) { - double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta()); - double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass())); - double residE = residKE + reactants[3].GetInvMass(); - reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE); + if(m_isResidEloss) { + double residKE = m_residual->GetKE() - m_layeredTarget->GetEjectileEnergyLoss(m_residual->Z, m_residual->A, m_residual->GetKE(), + m_rxnLayer, m_residual->vec4.Theta()); + double residP = std::sqrt(residKE*(residKE + 2.0*m_residual->vec4.M())); + double residE = residKE + m_residual->vec4.M(); + m_residual->SetVec4Spherical(m_residual->vec4.Theta(), m_residual->vec4.Phi(), residP, residE); } } //Methods from original ANASEN. Gives proper distribution for inverse kinematics. - void Reaction::CalculateReactionThetaCM() { + void Reaction::CalculateReactionThetaCM() + { //Target assumed at rest, with 0 excitation energy - reactants[0].SetVectorCartesian(0.,0.,0.,reactants[0].GetGroundStateMass()); - double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * reactants[1].GetGroundStateMass())); - double beam_E = m_bke + reactants[1].GetGroundStateMass(); - reactants[1].SetVectorCartesian(0.,0.,beam_pz,beam_E); + m_target->vec4.SetPxPyPzE(0.,0.,0.,m_target->groundStateMass); + double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * m_projectile->groundStateMass)); + double beam_E = m_bke + m_projectile->groundStateMass; + m_projectile->vec4.SetPxPyPzE(0.,0.,beam_pz,beam_E); + double Q = m_target->groundStateMass + m_projectile->groundStateMass - (m_ejectile->groundStateMass + m_residual->groundStateMass + m_ex); - double Q = reactants[0].GetGroundStateMass() + reactants[1].GetGroundStateMass() - (reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() + m_ex); - - double Ethresh = -Q*(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())/(reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass()); - if(m_bke < Ethresh) { + double Ethresh = -Q*(m_ejectile->groundStateMass + m_residual->groundStateMass) / + (m_ejectile->groundStateMass + m_residual->groundStateMass - m_projectile->groundStateMass); + if(m_bke < Ethresh) throw EnergyThresholdException(); - } - auto parent = reactants[0] + reactants[1]; - double boost2lab[3]; - double boost2cm[3]; - const double* boost = parent.GetBoost(); - for(int i=0; i<3; i++) { - boost2lab[i] = boost[i]; - boost2cm[i] = boost[i]*(-1.0); - } - parent.ApplyBoost(boost2cm); - double ejectE_cm = (std::pow(reactants[2].GetGroundStateMass(), 2.0) - std::pow(reactants[3].GetGroundStateMass() + m_ex, 2.0) + std::pow(parent.GetE(),2.0))/(2.0*parent.GetE()); - double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - std::pow(reactants[2].GetGroundStateMass(), 2.0)); - reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP_cm, ejectE_cm); - reactants[2].ApplyBoost(boost2lab); - reactants[3] = reactants[0] + reactants[1] - reactants[2]; + ROOT::Math::PxPyPzEVector parent = m_target->vec4 + m_projectile->vec4; + ROOT::Math::Boost boost(parent.BoostToCM()); + parent = boost*parent; + double ejectE_cm = (std::pow(m_ejectile->groundStateMass, 2.0) - + std::pow(m_residual->groundStateMass + m_ex, 2.0) + std::pow(parent.E(),2.0))/ + (2.0*parent.E()); + double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - std::pow(m_ejectile->groundStateMass, 2.0)); + m_ejectile->SetVec4Spherical(m_theta, m_phi, ejectP_cm, ejectE_cm); + m_ejectile->vec4 = boost.Inverse() * m_ejectile->vec4; + m_residual->vec4 = m_target->vec4 + m_projectile->vec4 - m_ejectile->vec4; - double ejectKE = reactants[2].GetKE(); - double ejectP = reactants[2].GetP(); - double ejectE = reactants[2].GetE(); + double ejectKE = m_ejectile->GetKE(); + double ejectP = m_ejectile->vec4.P(); + double ejectE = m_ejectile->vec4.E(); //energy loss for ejectile (after reaction!) - ejectKE -= target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), ejectKE, rxnLayer, reactants[2].GetTheta()); - ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass())); - ejectE = ejectKE + reactants[2].GetGroundStateMass(); - reactants[2].SetVectorSpherical(reactants[2].GetTheta(), reactants[2].GetPhi(), ejectP, ejectE); + ejectKE -= m_layeredTarget->GetEjectileEnergyLoss(m_ejectile->Z, m_ejectile->A, ejectKE, m_rxnLayer, m_ejectile->vec4.Theta()); + ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * m_ejectile->groundStateMass)); + ejectE = ejectKE + m_ejectile->groundStateMass; + m_ejectile->SetVec4Spherical(m_ejectile->vec4.Theta(), m_ejectile->vec4.Phi(), ejectP, ejectE); //if on, get eloss for residual (after reaction!) - if(resid_elossFlag) { - double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta()); - double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass())); - double residE = residKE + reactants[3].GetInvMass(); - reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE); + if(m_isResidEloss) + { + double residKE = m_residual->GetKE() - + m_layeredTarget->GetEjectileEnergyLoss(m_residual->Z, m_residual->A, m_residual->GetKE(), m_rxnLayer, m_residual->vec4.Theta()); + double residP = std::sqrt(residKE*(residKE + 2.0*m_residual->vec4.M())); + double residE = residKE + m_residual->vec4.M(); + m_residual->SetVec4Spherical(m_residual->vec4.Theta(), m_residual->vec4.Phi(), residP, residE); } } - void Reaction::CalculateReaction() { - switch(m_eject_theta_type) { - case center_of_mass: - { - CalculateReactionThetaCM(); - break; - } - case lab: - { - CalculateReactionThetaLab(); - break; - } + void Reaction::CalculateReaction() + { + switch(m_ejectThetaType) + { + case s_centerOfMass: CalculateReactionThetaCM(); break; + case s_lab: CalculateReactionThetaLab(); break; } } //Calculate in CM, where decay is isotropic - void Reaction::CalculateDecay() { - - double Q = reactants[0].GetInvMass() - reactants[2].GetGroundStateMass() - reactants[3].GetGroundStateMass(); - if(Q < 0) { + void Reaction::CalculateDecay() + { + double Q = m_target->vec4.M() - m_ejectile->groundStateMass - m_residual->groundStateMass; + if(Q < 0) throw QValueException(); - } - const double* boost = reactants[0].GetBoost(); - double boost2cm[3]; - double boost2lab[3]; - for(int i=0; i<3; i++) { - boost2lab[i] = boost[i]; - boost2cm[i] = boost[i]*(-1.0); - } + ROOT::Math::Boost boost(m_target->vec4.BoostToCM()); + m_target->vec4 = boost*m_target->vec4; + double ejectE_cm = (m_ejectile->groundStateMass*m_ejectile->groundStateMass - + m_residual->groundStateMass*m_residual->groundStateMass + m_target->vec4.E()*m_target->vec4.E()) / + (2.0*m_target->vec4.E()); + double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - m_ejectile->groundStateMass*m_ejectile->groundStateMass); - reactants[0].ApplyBoost(&(boost2cm[0])); - double ejectE_cm = (reactants[2].GetGroundStateMass()*reactants[2].GetGroundStateMass() - reactants[3].GetGroundStateMass()*reactants[3].GetGroundStateMass() + reactants[0].GetE()*reactants[0].GetE())/ - (2.0*reactants[0].GetE()); - double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - reactants[2].GetGroundStateMass()*reactants[2].GetGroundStateMass()); + m_ejectile->SetVec4Spherical(m_theta, m_phi, ejectP_cm, ejectE_cm); + m_ejectile->thetaCM = m_theta; - reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP_cm, ejectE_cm); - reactants[2].SetThetaCM(m_theta); + m_target->vec4 = boost.Inverse() * m_target->vec4; + m_ejectile->vec4 = boost.Inverse() * m_ejectile->vec4; - reactants[0].ApplyBoost(boost2lab); - reactants[2].ApplyBoost(boost2lab); - - reactants[3] = reactants[0] - reactants[2]; + m_residual->vec4 = m_target->vec4 - m_ejectile->vec4; //energy loss for the *light* break up nucleus - double ejectKE = reactants[2].GetKE() - target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), reactants[2].GetKE(), rxnLayer, reactants[2].GetTheta()); - double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0*reactants[2].GetGroundStateMass())); - double ejectE = ejectKE + reactants[2].GetGroundStateMass(); - reactants[2].SetVectorSpherical(reactants[2].GetTheta(), reactants[2].GetPhi(), ejectP, ejectE); + double ejectKE = m_ejectile->GetKE() - + m_layeredTarget->GetEjectileEnergyLoss(m_ejectile->Z, m_ejectile->A, m_ejectile->GetKE(), m_rxnLayer, m_ejectile->vec4.Theta()); + double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0*m_ejectile->groundStateMass)); + double ejectE = ejectKE + m_ejectile->groundStateMass; + m_ejectile->SetVec4Spherical(m_ejectile->vec4.Theta(), m_ejectile->vec4.Phi(), ejectP, ejectE); //if on, get eloss for *heavy* break up nucleus - if(resid_elossFlag) { - - double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta()); - double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass())); - double residE = residKE + reactants[3].GetInvMass(); - reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE); + if(m_isResidEloss) + { + double residKE = m_residual->GetKE() - + m_layeredTarget->GetEjectileEnergyLoss(m_residual->Z, m_residual->A, m_residual->GetKE(), m_rxnLayer, m_residual->vec4.Theta()); + double residP = std::sqrt(residKE*(residKE + 2.0*m_residual->vec4.M())); + double residE = residKE + m_residual->vec4.M(); + m_residual->SetVec4Spherical(m_residual->vec4.Theta(), m_residual->vec4.Phi(), residP, residE); } } diff --git a/src/Mask/Reaction.h b/src/Mask/Reaction.h new file mode 100644 index 0000000..a1c166c --- /dev/null +++ b/src/Mask/Reaction.h @@ -0,0 +1,74 @@ +/* + Reaction.h + Reaction is a class which implements either a decay or scattering reaction. As such it requires either + 3 (decay) or 4 (scattering) nuclei to perform any calcualtions. I also links together the target, which provides + energy loss calculations, with the kinematics. Note that Reaction does not own the LayeredTarget. + + --GWM Jan. 2021 +*/ +#ifndef REACTION_H +#define REACTION_H + +#include "Nucleus.h" +#include "LayeredTarget.h" + +namespace Mask { + + class Reaction + { + public: + Reaction(); + Reaction(Nucleus* target, Nucleus* projectile, Nucleus* ejectile, Nucleus* residual); + ~Reaction(); + bool Calculate(); //do sim + + void BindNuclei(Nucleus* target, Nucleus* projectile, Nucleus* ejectile, Nucleus* residual); + void SetBeamKE(double bke); + void SetEjectileThetaType(int type); + + void SetLayeredTarget(LayeredTarget* targ) { m_layeredTarget = targ; }; + + void SetPolarRxnAngle(double theta) { m_theta = theta; }; + void SetAzimRxnAngle(double phi) { m_phi = phi; }; + void SetExcitation(double ex) { m_ex = ex; }; + + void BindTarget(Nucleus* nuc) { m_target = nuc; }; + void BindProjectile(Nucleus* nuc) { m_projectile = nuc; }; + void BindEjectile(Nucleus* nuc) { m_ejectile = nuc; }; + void BindResidual(Nucleus* nuc) { m_residual = nuc; }; + + void SetRxnLayer(std::size_t layer) { m_rxnLayer = layer; }; + void SetResidualEnergyLoss(bool isEloss) { m_isResidEloss = isEloss; }; + + bool IsDecay() const { return m_isDecay; }; + + std::size_t GetRxnLayer() const { return m_rxnLayer; }; + + private: + void CalculateDecay(); //target -> light_decay (eject) + heavy_decay(resid) + void CalculateReaction(); //target + project -> eject + resid + void CalculateReactionThetaLab(); + void CalculateReactionThetaCM(); + + //Reactants -> NOT OWNED BY RXN + Nucleus* m_target; + Nucleus* m_projectile; + Nucleus* m_ejectile; + Nucleus* m_residual; + + LayeredTarget* m_layeredTarget; //not owned by Reaction + + double m_bke, m_theta, m_phi, m_ex; + + int m_rxnLayer; + int m_ejectThetaType; + + bool m_isDecay, m_isInit, m_isResidEloss; + + static constexpr int s_lab = 0; + static constexpr int s_centerOfMass = 1; + }; + +} + +#endif \ No newline at end of file diff --git a/src/Mask/ReactionSystem.cpp b/src/Mask/ReactionSystem.cpp index f4292d4..dd18de2 100644 --- a/src/Mask/ReactionSystem.cpp +++ b/src/Mask/ReactionSystem.cpp @@ -5,20 +5,22 @@ namespace Mask { ReactionSystem::ReactionSystem() : - m_beamDist(nullptr), m_theta1Range(nullptr), m_phi1Range(nullptr), m_exDist(nullptr), target_set_flag(false), - rxnLayer(0), m_sys_equation("") + m_beamDist(nullptr), m_theta1Range(nullptr), m_phi1Range(nullptr), m_exDist(nullptr), m_isTargetSet(false), + m_rxnLayer(0), m_sysEquation("") { } - ReactionSystem::~ReactionSystem() { + ReactionSystem::~ReactionSystem() + { delete m_beamDist; delete m_theta1Range; delete m_phi1Range; delete m_exDist; } - void ReactionSystem::AddTargetLayer(std::vector& zt, std::vector& at, std::vector& stoich, double thickness) { - target.AddLayer(zt, at, stoich, thickness); + void ReactionSystem::AddTargetLayer(const std::vector& zt, const std::vector& at, const std::vector& stoich, double thickness) + { + m_target.AddLayer(zt, at, stoich, thickness); } } \ No newline at end of file diff --git a/include/ReactionSystem.h b/src/Mask/ReactionSystem.h similarity index 62% rename from include/ReactionSystem.h rename to src/Mask/ReactionSystem.h index acb0bd2..43a6aca 100644 --- a/include/ReactionSystem.h +++ b/src/Mask/ReactionSystem.h @@ -16,59 +16,64 @@ namespace Mask { - class ReactionSystem { + class ReactionSystem + { public: ReactionSystem(); virtual ~ReactionSystem(); - virtual bool SetNuclei(std::vector& z, std::vector& a) = 0; + virtual bool SetNuclei(const std::vector& z, const std::vector& a) = 0; virtual void RunSystem() = 0; - virtual const std::vector& GetNuclei() = 0; + virtual std::vector* GetNuclei() = 0; - void AddTargetLayer(std::vector& zt, std::vector& at, std::vector& stoich, double thickness); + void AddTargetLayer(const std::vector& zt, const std::vector& at, const std::vector& stoich, double thickness); /*Set sampling parameters*/ - inline void SetBeamDistro(double mean, double sigma) { + void SetBeamDistro(double mean, double sigma) + { if(m_beamDist) delete m_beamDist; m_beamDist = new std::normal_distribution(mean, sigma); } - inline void SetTheta1Range(double min, double max) { + void SetTheta1Range(double min, double max) + { if(m_theta1Range) delete m_theta1Range; - m_theta1Range = new std::uniform_real_distribution(std::cos(min*deg2rad), std::cos(max*deg2rad)); + m_theta1Range = new std::uniform_real_distribution(std::cos(min*s_deg2rad), std::cos(max*s_deg2rad)); } - inline void SetPhi1Range(double min, double max) { + void SetPhi1Range(double min, double max) + { if(m_phi1Range) delete m_phi1Range; - m_phi1Range = new std::uniform_real_distribution(min*deg2rad, max*deg2rad); + m_phi1Range = new std::uniform_real_distribution(min*s_deg2rad, max*s_deg2rad); } - inline void SetExcitationDistro(double mean, double sigma) { + void SetExcitationDistro(double mean, double sigma) + { if(m_exDist) delete m_exDist; m_exDist = new std::normal_distribution(mean, sigma); } - inline const std::string& GetSystemEquation() const { return m_sys_equation; } + const std::string& GetSystemEquation() const { return m_sysEquation; } protected: virtual void LinkTarget() = 0; virtual void SetSystemEquation() = 0; - LayeredTarget target; + LayeredTarget m_target; //Sampling information std::normal_distribution *m_beamDist, *m_exDist; std::uniform_real_distribution *m_theta1Range, *m_phi1Range; - bool target_set_flag, gen_set_flag; - int rxnLayer; - std::string m_sys_equation; - std::vector nuclei; - static constexpr double deg2rad = M_PI/180.0; + bool m_isTargetSet; + std::size_t m_rxnLayer; + std::string m_sysEquation; + std::vector m_nuclei; + static constexpr double s_deg2rad = M_PI/180.0; }; } diff --git a/include/RxnType.h b/src/Mask/RxnType.h similarity index 100% rename from include/RxnType.h rename to src/Mask/RxnType.h diff --git a/src/Mask/Stopwatch.cpp b/src/Mask/Stopwatch.cpp index 337098e..d85403a 100644 --- a/src/Mask/Stopwatch.cpp +++ b/src/Mask/Stopwatch.cpp @@ -7,25 +7,34 @@ */ #include "Stopwatch.h" -Stopwatch::Stopwatch() { - start_time = Clock::now(); - stop_time = start_time; -} +namespace Mask { -Stopwatch::~Stopwatch() {} + Stopwatch::Stopwatch() + { + start_time = Clock::now(); + stop_time = start_time; + } -void Stopwatch::Start() { - start_time = Clock::now(); -} + Stopwatch::~Stopwatch() {} -void Stopwatch::Stop() { - stop_time = Clock::now(); -} + void Stopwatch::Start() + { + start_time = Clock::now(); + } -double Stopwatch::GetElapsedSeconds() { - return std::chrono::duration_cast>(stop_time-start_time).count(); -} + void Stopwatch::Stop() + { + stop_time = Clock::now(); + } + + double Stopwatch::GetElapsedSeconds() + { + return std::chrono::duration_cast>(stop_time-start_time).count(); + } + + double Stopwatch::GetElapsedMilliseconds() + { + return std::chrono::duration_cast>(stop_time-start_time).count()*1000.0; + } -double Stopwatch::GetElapsedMilliseconds() { - return std::chrono::duration_cast>(stop_time-start_time).count()*1000.0; } \ No newline at end of file diff --git a/src/Mask/Stopwatch.h b/src/Mask/Stopwatch.h new file mode 100644 index 0000000..5571673 --- /dev/null +++ b/src/Mask/Stopwatch.h @@ -0,0 +1,32 @@ +/* + Stopwatch.h + Simple class designed to provide timing info on parts of the process. + Only for use in development. + + Written by G.W. McCann Oct. 2020 +*/ +#ifndef STOPWATCH_H +#define STOPWATCH_H + +#include +namespace Mask { + + class Stopwatch + { + public: + Stopwatch(); + ~Stopwatch(); + void Start(); + void Stop(); + double GetElapsedSeconds(); + double GetElapsedMilliseconds(); + + private: + using Time = std::chrono::high_resolution_clock::time_point; + using Clock = std::chrono::high_resolution_clock; + + Time start_time, stop_time; + }; + +} +#endif \ No newline at end of file diff --git a/src/Mask/Target.cpp b/src/Mask/Target.cpp index 0a2a908..cef01e3 100644 --- a/src/Mask/Target.cpp +++ b/src/Mask/Target.cpp @@ -16,45 +16,50 @@ Written by G.W. McCann Aug. 2020 namespace Mask { /*Targets must be of known thickness*/ - Target::Target(double thick) { - thickness = thick; - thickness_gcm2 = thickness*1.0e-6; + Target::Target(const std::vector& z, const std::vector& a, const std::vector& stoich, double thick) : + m_thickness(thick), m_thickness_gcm2(thick*1.0e-6) + { + Init(z, a, stoich); } Target::~Target() {} /*Set target elements of given Z, A, S*/ - void Target::SetElements(std::vector& z, std::vector& a, std::vector& stoich) { - Z = z; - A = a; - Stoich = stoich; + void Target::Init(const std::vector& z, const std::vector& a, const std::vector& stoich) + { + m_Z = z; + m_A = a; + m_stoich = stoich; MassLookup& masses = MassLookup::GetInstance(); - eloss.SetTargetComponents(Z, A, Stoich); - for(size_t i=0; i M_PI/2.) theta = M_PI - theta; + catima::Projectile proj(MassLookup::GetInstance().FindMassU(zp, ap), zp, 0.0, 0.0); proj.T = startEnergy/proj.A; - target_material.thickness(thickness_gcm2/fabs(cos(theta))); - return catima::integrate_energyloss(proj, target_material); - //return eloss.GetEnergyLoss(zp, ap, startEnergy, thickness/fabs(cos(theta))); + m_material.thickness(m_thickness_gcm2/fabs(cos(theta))); + return catima::integrate_energyloss(proj, m_material); } /*Calculates the energy loss for traveling some fraction through the target*/ @@ -67,13 +72,13 @@ namespace Mask { catima::Projectile proj(MassLookup::GetInstance().FindMassU(zp, ap), zp, 0.0, 0.0); proj.T = finalEnergy/proj.A; - target_material.thickness(thickness_gcm2*percent_depth/fabs(cos(theta))); - return catima::integrate_energyloss(proj, target_material); - //return eloss.GetEnergyLoss(zp, ap, finalEnergy, thickness*percent_depth/(std::fabs(std::cos(theta)))); + m_material.thickness(m_thickness_gcm2*percent_depth/fabs(cos(theta))); + return catima::integrate_energyloss(proj, m_material); } /*Calculates reverse energy loss for travelling all the way through the target*/ - double Target::GetReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double theta) { + double Target::GetReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double theta) + { if(theta == M_PI/2.) return finalEnergy; else if (theta > M_PI/2.) @@ -81,9 +86,8 @@ namespace Mask { catima::Projectile proj(MassLookup::GetInstance().FindMassU(zp, ap), zp, 0.0, 0.0); proj.T = finalEnergy/proj.A; - target_material.thickness(thickness_gcm2/fabs(cos(theta))); - return catima::reverse_integrate_energyloss(proj, target_material); - //return eloss.GetReverseEnergyLoss(zp, ap, finalEnergy, thickness/fabs(cos(theta))); + m_material.thickness(m_thickness_gcm2/fabs(cos(theta))); + return catima::reverse_integrate_energyloss(proj, m_material); } /*Calculates the reverse energy loss for traveling some fraction through the target*/ @@ -95,9 +99,8 @@ namespace Mask { theta = M_PI-theta; catima::Projectile proj(MassLookup::GetInstance().FindMassU(zp, ap), zp, 0.0, 0.0); proj.T = finalEnergy/proj.A; - target_material.thickness(thickness_gcm2*percent_depth/fabs(cos(theta))); - return catima::reverse_integrate_energyloss(proj, target_material); - //return eloss.GetReverseEnergyLoss(zp, ap, finalEnergy, thickness*percent_depth/(std::fabs(std::cos(theta)))); + m_material.thickness(m_thickness_gcm2*percent_depth/fabs(cos(theta))); + return catima::reverse_integrate_energyloss(proj, m_material); } } diff --git a/include/Target.h b/src/Mask/Target.h similarity index 59% rename from include/Target.h rename to src/Mask/Target.h index 83839eb..be8b4a4 100644 --- a/include/Target.h +++ b/src/Mask/Target.h @@ -16,7 +16,6 @@ Written by G.W. McCann Aug. 2020 #include #include #include -#include "EnergyLoss.h" #include "catima/gwm_integrators.h" #include "MassLookup.h" @@ -25,26 +24,26 @@ namespace Mask { class Target { public: - Target(double thick); + Target(const std::vector& z, const std::vector& a, const std::vector& stoich, double thick); ~Target(); - void SetElements(std::vector& z, std::vector& a, std::vector& stoich); bool ContainsElement(int z, int a); double GetEnergyLossTotal(int zp, int ap, double startEnergy, double angle); double GetReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double angle); double GetEnergyLossFractionalDepth(int zp, int ap, double startEnergy, double angle, double percent_depth); double GetReverseEnergyLossFractionalDepth(int zp, int ap, double finalEnergy, double angle, double percent_depth); - inline const double& GetThickness() { return thickness; } - inline int GetNumberOfElements() { return Z.size(); } - inline int GetElementZ(int index) { return Z[index]; } - inline int GetElementA(int index) { return A[index]; } - inline int GetElementStoich(int index) { return Stoich[index]; } + inline const double& GetThickness() { return m_thickness; } + inline int GetNumberOfElements() { return m_Z.size(); } + inline int GetElementZ(int index) { return m_Z[index]; } + inline int GetElementA(int index) { return m_A[index]; } + inline int GetElementStoich(int index) { return m_stoich[index]; } private: - EnergyLoss eloss; - catima::Material target_material; - double thickness; - double thickness_gcm2; - std::vector Z, A, Stoich; + void Init(const std::vector& z, const std::vector& a, const std::vector& stoich); + + catima::Material m_material; + double m_thickness; + double m_thickness_gcm2; + std::vector m_Z, m_A, m_stoich; }; diff --git a/src/Mask/ThreeStepSystem.cpp b/src/Mask/ThreeStepSystem.cpp index 81f35b6..800ae3e 100644 --- a/src/Mask/ThreeStepSystem.cpp +++ b/src/Mask/ThreeStepSystem.cpp @@ -7,133 +7,131 @@ namespace Mask { ThreeStepSystem::ThreeStepSystem() : ReactionSystem(), m_phi2Range(0, 2.0*M_PI) { - nuclei.resize(8); + m_nuclei.resize(8); } - ThreeStepSystem::ThreeStepSystem(std::vector& z, std::vector& a) : + ThreeStepSystem::ThreeStepSystem(const std::vector& z, const std::vector& a) : ReactionSystem(), m_phi2Range(0, 2.0*M_PI) { - nuclei.resize(8); + m_nuclei.resize(8); SetNuclei(z, a); } ThreeStepSystem::~ThreeStepSystem() {} - - bool ThreeStepSystem::SetNuclei(std::vector&z, std::vector& a) { - if(z.size() != a.size() || z.size() < 5) { + bool ThreeStepSystem::SetNuclei(const std::vector& z, const std::vector& a) + { + if(z.size() != a.size() || z.size() < 5) return false; - } + int zr = z[0] + z[1] - z[2]; int zb2 = zr - z[3]; + int zb4 = zb2 - z[4]; int ar = a[0] + a[1] - a[2]; int ab2 = ar - a[3]; + int ab4 = ab2 - a[4]; + + m_nuclei[0] = CreateNucleus(z[0], a[0]); //target + m_nuclei[1] = CreateNucleus(z[1], a[1]); //projectile + m_nuclei[2] = CreateNucleus(z[2], a[2]); //ejectile + m_nuclei[3] = CreateNucleus(zr, ar); //residual + m_nuclei[4] = CreateNucleus(z[3], a[3]); //breakup1 + m_nuclei[5] = CreateNucleus(zb2, ab2); //breakup2 + m_nuclei[5] = CreateNucleus(z[4], a[4]); //breakup3 + m_nuclei[5] = CreateNucleus(zb4, ab4); //breakup4 + + m_step1.BindNuclei(&(m_nuclei[0]), &(m_nuclei[1]), &(m_nuclei[2]), &(m_nuclei[3])); + m_step2.BindNuclei(&(m_nuclei[3]), nullptr, &(m_nuclei[4]), &(m_nuclei[5])); + m_step3.BindNuclei(&(m_nuclei[5]), nullptr, &(m_nuclei[6]), &(m_nuclei[7])); - step1.SetNuclei(z[0], a[0], z[1], a[1], z[2], a[2]); - step2.SetNuclei(zr, ar, 0, 0, z[3], a[3]); - step3.SetNuclei(zb2, ab2, 0, 0, z[4], a[4]); SetSystemEquation(); return true; } - const std::vector& ThreeStepSystem::GetNuclei() + std::vector* ThreeStepSystem::GetNuclei() { - nuclei[0] = step1.GetTarget(); - nuclei[1] = step1.GetProjectile(); - nuclei[2] = step1.GetEjectile(); - nuclei[3] = step1.GetResidual(); - nuclei[4] = step2.GetEjectile(); - nuclei[5] = step2.GetResidual(); - nuclei[6] = step3.GetEjectile(); - nuclei[7] = step3.GetResidual(); - - return nuclei; + return &m_nuclei; } - void ThreeStepSystem::LinkTarget() { - step1.SetLayeredTarget(&target); - step2.SetLayeredTarget(&target); - step3.SetLayeredTarget(&target); + void ThreeStepSystem::LinkTarget() + { + m_step1.SetLayeredTarget(&m_target); + m_step2.SetLayeredTarget(&m_target); + m_step3.SetLayeredTarget(&m_target); - rxnLayer = target.FindLayerContaining(step1.GetTarget().GetZ(), step1.GetTarget().GetA()); - if(rxnLayer != -1) { - step1.SetRxnLayer(rxnLayer); - step2.SetRxnLayer(rxnLayer); - step3.SetRxnLayer(rxnLayer); - target_set_flag = true; - } else { + m_rxnLayer = m_target.FindLayerContaining(m_nuclei[0].Z, m_nuclei[0].A); + if(m_rxnLayer != m_target.GetNumberOfLayers()) + { + m_step1.SetRxnLayer(m_rxnLayer); + m_step2.SetRxnLayer(m_rxnLayer); + m_step3.SetRxnLayer(m_rxnLayer); + m_isTargetSet = true; + } else throw ReactionLayerException(); - } } - void ThreeStepSystem::SetSystemEquation() { - m_sys_equation = step1.GetTarget().GetIsotopicSymbol(); - m_sys_equation += "("; - m_sys_equation += step1.GetProjectile().GetIsotopicSymbol(); - m_sys_equation += ", "; - m_sys_equation += step1.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += ")"; - m_sys_equation += step1.GetResidual().GetIsotopicSymbol(); - m_sys_equation += "-> "; - m_sys_equation += step2.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += " + "; - m_sys_equation += step2.GetResidual().GetIsotopicSymbol(); - m_sys_equation += "-> "; - m_sys_equation += step3.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += " + "; - m_sys_equation += step3.GetResidual().GetIsotopicSymbol(); + void ThreeStepSystem::SetSystemEquation() + { + std::stringstream stream; + stream << m_nuclei[0].isotopicSymbol << "(" + << m_nuclei[1].isotopicSymbol << ", " + << m_nuclei[2].isotopicSymbol << ")" + << m_nuclei[3].isotopicSymbol << "->" + << m_nuclei[4].isotopicSymbol << "+" + << m_nuclei[5].isotopicSymbol << "->" + << m_nuclei[6].isotopicSymbol << "+" + << m_nuclei[7].isotopicSymbol; + m_sysEquation = stream.str(); } void ThreeStepSystem::RunSystem() { //Link up the target if it hasn't been done yet - if(!target_set_flag) { + if(!m_isTargetSet) LinkTarget(); - } //Sample parameters double bke = (*m_beamDist)(RandomGenerator::GetInstance().GetGenerator()); double rxnTheta = acos((*m_theta1Range)(RandomGenerator::GetInstance().GetGenerator())); double rxnPhi = (*m_phi1Range)(RandomGenerator::GetInstance().GetGenerator()); - double decay1costheta = decay1dist.GetRandomCosTheta(); + double decay1costheta = m_step2Distribution.GetRandomCosTheta(); double decay1Theta = std::acos(decay1costheta); double decay1Phi = m_phi2Range(RandomGenerator::GetInstance().GetGenerator()); - double decay2costheta = decay2dist.GetRandomCosTheta(); + double decay2costheta = m_step3Distribution.GetRandomCosTheta(); double decay2Theta = std::acos(decay2costheta); double decay2Phi = m_phi2Range(RandomGenerator::GetInstance().GetGenerator()); double residEx = (*m_exDist)(RandomGenerator::GetInstance().GetGenerator()); - step1.SetBeamKE(bke); - step1.SetPolarRxnAngle(rxnTheta); - step1.SetAzimRxnAngle(rxnPhi); - step1.SetExcitation(residEx); + m_step1.SetBeamKE(bke); + m_step1.SetPolarRxnAngle(rxnTheta); + m_step1.SetAzimRxnAngle(rxnPhi); + m_step1.SetExcitation(residEx); - step2.SetPolarRxnAngle(decay1Theta); - step2.SetAzimRxnAngle(decay1Phi); + m_step2.SetPolarRxnAngle(decay1Theta); + m_step2.SetAzimRxnAngle(decay1Phi); - step3.SetPolarRxnAngle(decay2Theta); - step3.SetAzimRxnAngle(decay2Phi); + m_step3.SetPolarRxnAngle(decay2Theta); + m_step3.SetAzimRxnAngle(decay2Phi); - step1.Calculate(); + m_step1.Calculate(); - step2.SetTarget(step1.GetResidual()); - if(decay1costheta == -10) { - step2.ResetEjectile(); - step2.ResetResidual(); - step3.ResetTarget(); - step3.ResetEjectile(); - step3.ResetResidual(); + if(decay1costheta == -10) + { + m_nuclei[4].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[4].groundStateMass); + m_nuclei[5].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[5].groundStateMass); + m_nuclei[6].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[6].groundStateMass); + m_nuclei[7].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[7].groundStateMass); return; } - step2.Calculate(); + m_step2.Calculate(); - step3.SetTarget(step2.GetResidual()); - if(decay2costheta == -10) { - step3.ResetEjectile(); - step3.ResetResidual(); + if(decay2costheta == -10) + { + m_nuclei[6].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[6].groundStateMass); + m_nuclei[7].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[7].groundStateMass); return; } - step3.TurnOnResidualEloss(); - step3.Calculate(); + m_step3.SetResidualEnergyLoss(true); + m_step3.Calculate(); } diff --git a/src/Mask/ThreeStepSystem.h b/src/Mask/ThreeStepSystem.h new file mode 100644 index 0000000..9e800a2 --- /dev/null +++ b/src/Mask/ThreeStepSystem.h @@ -0,0 +1,42 @@ +#ifndef THREESTEPSYSTEM_H +#define THREESTEPSYSTEM_H + +#include "ReactionSystem.h" +#include "AngularDistribution.h" + +namespace Mask { + + class ThreeStepSystem : public ReactionSystem { + public: + ThreeStepSystem(); + ThreeStepSystem(const std::vector& z, const std::vector& a); + ~ThreeStepSystem(); + bool SetNuclei(const std::vector& z, const std::vector& a) override; + void RunSystem() override; + std::vector* GetNuclei() override; + + inline void SetDecay1Distribution(const std::string& filename) { m_step2Distribution.ReadDistributionFile(filename); }; + inline void SetDecay2Distribution(const std::string& filename) { m_step3Distribution.ReadDistributionFile(filename); }; + + void SetReactionThetaType(int type) { m_step1.SetEjectileThetaType(type); }; + + int GetDecay1AngularMomentum() { return m_step2Distribution.GetL(); }; + int GetDecay2AngularMomentum(){ return m_step3Distribution.GetL(); }; + double GetDecay1BranchingRatio() { return m_step2Distribution.GetBranchingRatio(); }; + double GetDecay2BranchingRatio(){ return m_step3Distribution.GetBranchingRatio(); }; + + protected: + void LinkTarget() override; + void SetSystemEquation() override; + + std::uniform_real_distribution m_phi2Range; + + Reaction m_step1, m_step2, m_step3; + + AngularDistribution m_step2Distribution, m_step3Distribution; + + }; + +} + +#endif \ No newline at end of file diff --git a/src/Mask/TwoStepSystem.cpp b/src/Mask/TwoStepSystem.cpp index 6310aac..9750fd6 100644 --- a/src/Mask/TwoStepSystem.cpp +++ b/src/Mask/TwoStepSystem.cpp @@ -2,111 +2,114 @@ #include "RandomGenerator.h" #include "KinematicsExceptions.h" +#include + namespace Mask { TwoStepSystem::TwoStepSystem() : ReactionSystem(), m_phi2Range(0, 2.0*M_PI) { - nuclei.resize(6); + m_nuclei.resize(6); } - TwoStepSystem::TwoStepSystem(std::vector& z, std::vector& a) : + TwoStepSystem::TwoStepSystem(const std::vector& z, const std::vector& a) : ReactionSystem(), m_phi2Range(0, 2.0*M_PI) { - nuclei.resize(6); + m_nuclei.resize(6); SetNuclei(z, a); } - TwoStepSystem::~TwoStepSystem() { + TwoStepSystem::~TwoStepSystem() {} - } - - bool TwoStepSystem::SetNuclei(std::vector&z, std::vector& a) { - if(z.size() != a.size() || z.size() != 4) { + bool TwoStepSystem::SetNuclei(const std::vector&z, const std::vector& a) + { + if(z.size() != a.size() || z.size() != 4) return false; - } + int zr = z[0] + z[1] - z[2]; int ar = a[0] + a[1] - a[2]; + int zb = zr - z[3]; + int ab = ar - a[3]; + + m_nuclei[0] = CreateNucleus(z[0], a[0]); //target + m_nuclei[1] = CreateNucleus(z[1], a[1]); //projectile + m_nuclei[2] = CreateNucleus(z[2], a[2]); //ejectile + m_nuclei[3] = CreateNucleus(zr, ar); //residual + m_nuclei[4] = CreateNucleus(z[3], a[3]); //breakup1 + m_nuclei[5] = CreateNucleus(zb, ab); //breakup2 - step1.SetNuclei(z[0], a[0], z[1], a[1], z[2], a[2]); - step2.SetNuclei(zr, ar, 0, 0, z[3], a[3]); + m_step1.BindNuclei(&(m_nuclei[0]), &(m_nuclei[1]), &(m_nuclei[2]), &(m_nuclei[3])); + m_step2.BindNuclei(&(m_nuclei[3]), nullptr, &(m_nuclei[4]), &(m_nuclei[5])); SetSystemEquation(); return true; } - const std::vector& TwoStepSystem::GetNuclei() + std::vector* TwoStepSystem::GetNuclei() { - nuclei[0] = step1.GetTarget(); - nuclei[1] = step1.GetProjectile(); - nuclei[2] = step1.GetEjectile(); - nuclei[3] = step1.GetResidual(); - nuclei[4] = step2.GetEjectile(); - nuclei[5] = step2.GetResidual(); - - return nuclei; + return &m_nuclei; } - void TwoStepSystem::LinkTarget() { - step1.SetLayeredTarget(&target); - step2.SetLayeredTarget(&target); + void TwoStepSystem::LinkTarget() + { + m_step1.SetLayeredTarget(&m_target); + m_step2.SetLayeredTarget(&m_target); - rxnLayer = target.FindLayerContaining(step1.GetTarget().GetZ(), step1.GetTarget().GetA()); - if(rxnLayer != -1) { - step1.SetRxnLayer(rxnLayer); - step2.SetRxnLayer(rxnLayer); - target_set_flag = true; - } else { + m_rxnLayer = m_target.FindLayerContaining(m_nuclei[0].Z, m_nuclei[0].A); + if(m_rxnLayer != m_target.GetNumberOfLayers()) + { + m_step1.SetRxnLayer(m_rxnLayer); + m_step2.SetRxnLayer(m_rxnLayer); + m_isTargetSet = true; + } + else throw ReactionLayerException(); - } } - void TwoStepSystem::SetSystemEquation() { - m_sys_equation = step1.GetTarget().GetIsotopicSymbol(); - m_sys_equation += "("; - m_sys_equation += step1.GetProjectile().GetIsotopicSymbol(); - m_sys_equation += ", "; - m_sys_equation += step1.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += ")"; - m_sys_equation += step1.GetResidual().GetIsotopicSymbol(); - m_sys_equation += "-> "; - m_sys_equation += step2.GetEjectile().GetIsotopicSymbol(); - m_sys_equation += "+"; - m_sys_equation += step2.GetResidual().GetIsotopicSymbol(); + void TwoStepSystem::SetSystemEquation() + { + std::stringstream stream; + stream << m_nuclei[0].isotopicSymbol << "(" + << m_nuclei[1].isotopicSymbol << ", " + << m_nuclei[2].isotopicSymbol << ")" + << m_nuclei[3].isotopicSymbol << "->" + << m_nuclei[4].isotopicSymbol << "+" + << m_nuclei[5].isotopicSymbol; + m_sysEquation = stream.str(); } - void TwoStepSystem::RunSystem() { + void TwoStepSystem::RunSystem() + { //Link up the target if it hasn't been done yet - if(!target_set_flag) { + if(!m_isTargetSet) LinkTarget(); - } //Sample parameters double bke = (*m_beamDist)(RandomGenerator::GetInstance().GetGenerator()); double rxnTheta = acos((*m_theta1Range)(RandomGenerator::GetInstance().GetGenerator())); double rxnPhi = (*m_phi1Range)(RandomGenerator::GetInstance().GetGenerator()); - double decay1costheta = decay1dist.GetRandomCosTheta(); + double decay1costheta = m_step2Distribution.GetRandomCosTheta(); double decay1Theta = std::acos(decay1costheta); double decay1Phi = m_phi2Range(RandomGenerator::GetInstance().GetGenerator()); double residEx = (*m_exDist)(RandomGenerator::GetInstance().GetGenerator()); - step1.SetBeamKE(bke); - step1.SetPolarRxnAngle(rxnTheta); - step1.SetAzimRxnAngle(rxnPhi); - step1.SetExcitation(residEx); + m_step1.SetBeamKE(bke); + m_step1.SetPolarRxnAngle(rxnTheta); + m_step1.SetAzimRxnAngle(rxnPhi); + m_step1.SetExcitation(residEx); - step2.SetPolarRxnAngle(decay1Theta); - step2.SetAzimRxnAngle(decay1Phi); + m_step2.SetPolarRxnAngle(decay1Theta); + m_step2.SetAzimRxnAngle(decay1Phi); - step1.Calculate(); + m_step1.Calculate(); - step2.SetTarget(step1.GetResidual()); - if(decay1costheta == -10) { - step2.ResetEjectile(); - step2.ResetResidual(); + if(decay1costheta == -10) + { + m_nuclei[4].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[4].groundStateMass); + m_nuclei[5].vec4.SetPxPyPzE(0., 0., 0., m_nuclei[5].groundStateMass); return; } - step2.TurnOnResidualEloss(); - step2.Calculate(); + m_step2.SetResidualEnergyLoss(true); + m_step2.Calculate(); } diff --git a/src/Mask/TwoStepSystem.h b/src/Mask/TwoStepSystem.h new file mode 100644 index 0000000..55623b4 --- /dev/null +++ b/src/Mask/TwoStepSystem.h @@ -0,0 +1,40 @@ +#ifndef TWOSTEPSYSTEM_H +#define TWOSTEPSYSTEM_H + +#include "ReactionSystem.h" +#include "AngularDistribution.h" + +namespace Mask { + + class TwoStepSystem : public ReactionSystem + { + public: + TwoStepSystem(); + TwoStepSystem(const std::vector& z, const std::vector& a); + ~TwoStepSystem(); + bool SetNuclei(const std::vector& z, const std::vector& a) override; + void RunSystem() override; + std::vector* GetNuclei() override; + + void SetDecay1Distribution(const std::string& filename) { m_step2Distribution.ReadDistributionFile(filename); }; + + void SetReactionThetaType(int type) { m_step1.SetEjectileThetaType(type); }; + + int GetDecay1AngularMomentum() { return m_step2Distribution.GetL(); }; + double GetDecay1BranchingRatio() { return m_step2Distribution.GetBranchingRatio(); }; + + private: + void LinkTarget() override; + void SetSystemEquation() override; + + std::uniform_real_distribution m_phi2Range; + + Reaction m_step1, m_step2; + + AngularDistribution m_step2Distribution; + + }; + +} + +#endif \ No newline at end of file diff --git a/src/MaskApp/CMakeLists.txt b/src/MaskApp/CMakeLists.txt index 9cf35b9..8c4e80c 100644 --- a/src/MaskApp/CMakeLists.txt +++ b/src/MaskApp/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable(MaskApp) -target_include_directories(MaskApp PUBLIC ${MASK_INCLUDE_DIR}) +target_include_directories(MaskApp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) target_sources(MaskApp PUBLIC main.cpp diff --git a/src/MaskApp/main.cpp b/src/MaskApp/main.cpp index 2d95c9f..2cec2fd 100644 --- a/src/MaskApp/main.cpp +++ b/src/MaskApp/main.cpp @@ -1,27 +1,32 @@ #include #include -#include "Stopwatch.h" -#include "MaskFile.h" -#include "MaskApp.h" -#include "KinematicsExceptions.h" +#include "Mask/Stopwatch.h" +#include "Mask/MaskApp.h" +#include "Mask/KinematicsExceptions.h" -int main(int argc, char** argv) { - if(argc<2) { +int main(int argc, char** argv) +{ + if(argc<2) + { std::cerr<<"Incorrect number of arguments!"< -#include - -#include - -RootPlotter::RootPlotter() : - table(new THashTable()) -{ -} - -RootPlotter::~RootPlotter() {} - -void RootPlotter::FillData(const Mask::Nucleus& nuc, double detKE, const std::string& modifier) { - std::string sym = nuc.GetIsotopicSymbol(); - std::string ke_vs_th_name = sym + modifier + "_ke_vs_theta"; - std::string ke_vs_th_title = ke_vs_th_name + ";#theta_{lab} (degrees);Kinetic Energy (MeV)"; - std::string ke_vs_ph_name = sym + modifier + "_ke_vs_phi"; - std::string ke_vs_ph_title = ke_vs_ph_name + ";#phi_{lab} (degrees);Kinetic Energy (MeV)"; - std::string th_vs_ph_name = sym + modifier + "_theta_vs_phi"; - std::string th_vs_ph_title = th_vs_ph_name + ";#theta_{lab};#phi_{lab}"; - std::string ex_name = sym + modifier + "_ex"; - std::string ex_title = ex_name + ";E_{ex} (MeV);counts"; - std::string angdist_name = sym + modifier +"_angDist"; - std::string angdist_title = angdist_name+";cos#right(#theta_{CM}#left);counts"; - - if(detKE == 0.0) - { - MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.GetTheta()*rad2deg, nuc.GetKE(), 2); - MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.GetPhi()*rad2deg, nuc.GetKE(), 4); - MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.GetTheta()*rad2deg, nuc.GetPhi()*rad2deg, 2); - MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); - MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.GetThetaCM())); - } - else - { - MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.GetTheta()*rad2deg, detKE, 2); - MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.GetPhi()*rad2deg, detKE, 4); - MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.GetTheta()*rad2deg, nuc.GetPhi()*rad2deg, 2); - MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); - MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.GetThetaCM())); - } - -} - -void RootPlotter::FillCorrelations(const Mask::MaskFileData& data, Mask::RxnType type) -{ - std::string theta_eject_theta_resid_name = "theta_eject_theta_resid_cor"; - std::string theta_eject_theta_resid_title = theta_eject_theta_resid_name + ";#theta_{lab} Ejectile (deg);#theta_{lab} Residual"; - if(type == Mask::RxnType::PureDecay) - { - MyFill(theta_eject_theta_resid_name, theta_eject_theta_resid_title, data.theta[1]*rad2deg, data.theta[2]*rad2deg, 4); - } - else - { - MyFill(theta_eject_theta_resid_name, theta_eject_theta_resid_title, data.theta[2]*rad2deg, data.theta[3]*rad2deg, 4); - } - - if(type == Mask::RxnType::TwoStepRxn || type == Mask::RxnType::ThreeStepRxn) - { - TVector3 p1, p2; - p1.SetMagThetaPhi(1.0, data.theta[3], data.phi[3]); - p2.SetMagThetaPhi(1.0, data.theta[4], data.phi[4]); - double theta_resid_break1 = std::acos(p1.Dot(p2)); - std::string theta_break1_theta_break2_name = "theta_break1_theta_break2_cor"; - std::string theta_break1_theta_break2_title = theta_break1_theta_break2_name + ";#theta_{lab} Breakup1 (deg);#theta_{lab} Breakup2 (deg)"; - MyFill(theta_break1_theta_break2_name, theta_break1_theta_break2_title, data.theta[4]*rad2deg, data.theta[5]*rad2deg, 4); - std::string theta_resid_theta_break1_name = "theta_resid_theta_break1_cor"; - std::string theta_resid_theta_break1_title = theta_resid_theta_break1_name + ";#theta_{lab} Residual (deg);#theta_{lab} Breakup1 (deg)"; - MyFill(theta_resid_theta_break1_name, theta_resid_theta_break1_title, data.theta[3]*rad2deg, data.theta[4]*rad2deg, 4); - std::string ke_break1_theta_rel_name = "ke_break1_theta_rel"; - std::string ke_break1_theta_rel_title = ke_break1_theta_rel_name + ";#theta_{resid-break1};KE_{break1} (MeV)"; - MyFill(ke_break1_theta_rel_name, ke_break1_theta_rel_title, theta_resid_break1*rad2deg, data.KE[4], 4); - } - if(type == Mask::RxnType::ThreeStepRxn) - { - std::string theta_break3_theta_break4_name = "theta_break3_theta_break4_cor"; - std::string theta_break3_theta_break4_title = theta_break3_theta_break4_name + ";#theta_{lab} Breakup3 (deg);#theta_{lab} Breakup4 (deg)"; - MyFill(theta_break3_theta_break4_name, theta_break3_theta_break4_title, data.theta[6]*rad2deg, data.theta[7]*rad2deg, 4); - } -} - -void RootPlotter::FillCorrelationsDetected(const Mask::MaskFileData& data, Mask::RxnType type) -{ - std::string theta_eject_theta_resid_name = "theta_eject_theta_resid_cor_detected"; - std::string theta_eject_theta_resid_title = theta_eject_theta_resid_name + ";#theta_{lab} Ejectile (deg);#theta_{lab} Residual"; - if(type == Mask::RxnType::PureDecay && data.detect_flag[1] && data.detect_flag[2]) - { - MyFill(theta_eject_theta_resid_name, theta_eject_theta_resid_title, data.theta[1]*rad2deg, data.theta[2]*rad2deg, 4); - } - else if(data.detect_flag[2] && data.detect_flag[3]) - { - MyFill(theta_eject_theta_resid_name, theta_eject_theta_resid_title, data.theta[2]*rad2deg, data.theta[3]*rad2deg, 4); - } - if((type == Mask::RxnType::TwoStepRxn || type == Mask::RxnType::ThreeStepRxn) && data.detect_flag[4]) - { - TVector3 p1, p2; - p1.SetMagThetaPhi(1.0, data.theta[3], data.phi[3]); - p2.SetMagThetaPhi(1.0, data.theta[4], data.phi[4]); - double theta_resid_break1 = std::acos(p1.Dot(p2)); - std::string theta_resid_theta_break1_name = "theta_resid_theta_break1_cor_detected"; - std::string theta_resid_theta_break1_title = theta_resid_theta_break1_name + ";#theta_{lab} Residual (deg);#theta_{lab} Breakup1 (deg)"; - MyFill(theta_resid_theta_break1_name, theta_resid_theta_break1_title, data.theta[3]*rad2deg, data.theta[4]*rad2deg, 4); - std::string ke_break1_theta_rel_name = "ke_break1_theta_rel_detected"; - std::string ke_break1_theta_rel_title = ke_break1_theta_rel_name + ";#theta_{resid-break1};KE_{break1} (MeV)"; - MyFill(ke_break1_theta_rel_name, ke_break1_theta_rel_title, theta_resid_break1*rad2deg, data.KE[4], 4); - } - - if((type == Mask::RxnType::TwoStepRxn || type == Mask::RxnType::ThreeStepRxn) && data.detect_flag[4] && data.detect_flag[5]) - { - std::string theta_break1_theta_break2_name = "theta_break1_theta_break2_cor_detected"; - std::string theta_break1_theta_break2_title = theta_break1_theta_break2_name + ";#theta_{lab} Breakup1 (deg);#theta_{lab} Breakup2 (deg)"; - MyFill(theta_break1_theta_break2_name, theta_break1_theta_break2_title, data.theta[4]*rad2deg, data.theta[5]*rad2deg, 4); - } - if(type == Mask::RxnType::ThreeStepRxn && data.detect_flag[6] && data.detect_flag[7]) - { - std::string theta_break3_theta_break4_name = "theta_break3_theta_break4_cor_detected"; - std::string theta_break3_theta_break4_title = theta_break3_theta_break4_name + ";#theta_{lab} Breakup3 (deg);#theta_{lab} Breakup4 (deg)"; - MyFill(theta_break3_theta_break4_name, theta_break3_theta_break4_title, data.theta[6]*rad2deg, data.theta[7]*rad2deg, 4); - } -} - -void RootPlotter::MyFill(const std::string& name, const std::string& title, int bins, float min, float max, double val) { - TH1F* h = (TH1F*) table->FindObject(name.c_str()); - if(h) { - h->Fill(val); - } else { - h = new TH1F(name.c_str(), title.c_str(), bins, min, max); - h->Fill(val); - table->Add(h); - } -} - -void RootPlotter::MyFill(const std::string& name, const std::string& title, int binsx, float minx, float maxx, int binsy, float miny, float maxy, double valx, double valy) { - TH2F* h = (TH2F*) table->FindObject(name.c_str()); - if(h) { - h->Fill(valx, valy); - } else { - h = new TH2F(name.c_str(), title.c_str(), binsx, minx, maxx, binsy, miny, maxy); - h->Fill(valx, valy); - table->Add(h); - } -} - -void RootPlotter::MyFill(const std::string& name, const std::string& title, double valx, double valy, int color) { - for(auto& g : graphs) { - if(g.name == name) { - g.xvec.push_back(valx); - g.yvec.push_back(valy); - return; - } - } - - GraphData new_g; - new_g.name = name; - new_g.title = title; - new_g.xvec.push_back(valx); - new_g.yvec.push_back(valy); - new_g.color = color; - - graphs.push_back(new_g); -} - -void RootPlotter::GenerateGraphs() { - for(auto& g : graphs) { - TGraph* graph = new TGraph(g.xvec.size(), &(g.xvec[0]), &(g.yvec[0])); - graph->SetName(g.name.c_str()); - graph->SetTitle(g.title.c_str()); - graph->SetMarkerColor(g.color); - table->Add(graph); - garbage_collection.push_back(graph); - } -} - -std::vector GetParents(const Mask::MaskFileData& data, Mask::RxnType rxn_type) -{ - std::vector parents; - Mask::Nucleus temp1, temp2, temp3; - switch(rxn_type) - { - case Mask::RxnType::None : break; - case Mask::RxnType::PureDecay : - { - temp1.SetIsotope(data.Z[0], data.A[0]); - temp1.SetVectorSpherical(data.theta[0], data.phi[0], data.p[0], data.E[0]); - parents.push_back(temp1); - return parents; - } - case Mask::RxnType::OneStepRxn : - { - temp1.SetIsotope(data.Z[0], data.A[0]); - temp1.SetVectorSpherical(data.theta[0], data.phi[0], data.p[0], data.E[0]); - temp2.SetIsotope(data.Z[1], data.A[1]); - temp2.SetVectorSpherical(data.theta[1], data.phi[1], data.p[1], data.E[1]); - temp3 = temp1 + temp2; - parents.push_back(temp3); - return parents; - } - case Mask::RxnType::TwoStepRxn : - { - temp1.SetIsotope(data.Z[0], data.A[0]); - temp1.SetVectorSpherical(data.theta[0], data.phi[0], data.p[0], data.E[0]); - temp2.SetIsotope(data.Z[1], data.A[1]); - temp2.SetVectorSpherical(data.theta[1], data.phi[1], data.p[1], data.E[1]); - temp3 = temp1 + temp2; - parents.push_back(temp3); - temp3.SetIsotope(data.Z[3], data.A[3]); - temp3.SetVectorSpherical(data.theta[3], data.phi[3], data.p[3], data.E[3]); - parents.push_back(temp3); - return parents; - } - case Mask::RxnType::ThreeStepRxn : - { - temp1.SetIsotope(data.Z[0], data.A[0]); - temp1.SetVectorSpherical(data.theta[0], data.phi[0], data.p[0], data.E[0]); - temp2.SetIsotope(data.Z[1], data.A[1]); - temp2.SetVectorSpherical(data.theta[1], data.phi[1], data.p[1], data.E[1]); - temp3 = temp1 + temp2; - parents.push_back(temp3); - temp3.SetIsotope(data.Z[3], data.A[3]); - temp3.SetVectorSpherical(data.theta[3], data.phi[3], data.p[3], data.E[3]); - parents.push_back(temp3); - temp3.SetIsotope(data.Z[5], data.A[5]); - temp3.SetVectorSpherical(data.theta[5], data.phi[5], data.p[5], data.E[5]); - parents.push_back(temp3); - return parents; - } - } - return parents; -} - -void SetThetaCM(Mask::Nucleus& daughter, const Mask::Nucleus& parent) -{ - const double* boost = parent.GetBoost(); - double boost2cm[3]; - double boost2lab[3]; - for(int i=0; i<3; i++) - { - boost2lab[i] = boost[i]; - boost2cm[i] = -1.0*boost[i]; - } - - daughter.ApplyBoost(boost2cm); - daughter.SetThetaCM(daughter.GetTheta()); - daughter.ApplyBoost(boost2lab); -} - -int main(int argc, char** argv) { - if(argc != 3) { - std::cout<<"Unable to run ROOT plotting tool with incorrect number of arguments! Expected 2 args, given: "< parents; //for use with CM theta calc - - double flush_frac = 0.05; - int count = 0, flush_val = flush_frac*header.nsamples, flush_count = 0; - while(true) { - if(count == flush_val) { - count = 0; - flush_count++; - std::cout<<"\rPercent of file processed: "<cd(); - plotter.GetTable()->Write(); - root_out->Close(); - - return 0; -} diff --git a/src/Plotters/RootPlotter.cpp b/src/Plotters/RootPlotter.cpp new file mode 100644 index 0000000..6bb7310 --- /dev/null +++ b/src/Plotters/RootPlotter.cpp @@ -0,0 +1,139 @@ +#include "RootPlotter.h" +#include +#include +#include + +#include + +RootPlotter::RootPlotter() +{ + TH1::AddDirectory(kFALSE); + //Enforce dictionary linking + if(Mask::EnforceDictionaryLinked()) + { + std::cout<<"Dictionary Linked"<Get("SimTree"); + std::vector* dataHandle = new std::vector(); + tree->SetBranchAddress("nuclei", &dataHandle); + + TFile* output = TFile::Open(outputname.c_str(), "RECREATE"); + + double flushFrac = 0.05; + uint64_t nentries = tree->GetEntries(); + uint64_t flushVal = flushFrac*nentries; + uint64_t count=0; + uint64_t flushCount = 0; + + for(uint64_t i=0; iGetEntry(i); + for(Mask::Nucleus& nuc : *(dataHandle)) + { + FillData(nuc); + } + } + + input->Close(); + delete dataHandle; + + output->cd(); + for(auto& obj : m_map) + obj.second->Write(obj.second->GetName(), TObject::kOverwrite); + output->Close(); +} + +void RootPlotter::FillData(const Mask::Nucleus& nuc) +{ + std::string modifier = ""; + if(nuc.isDetected) + modifier = "detected"; + + std::string sym = nuc.isotopicSymbol; + std::string ke_vs_th_name = sym + modifier + "_ke_vs_theta"; + std::string ke_vs_th_title = ke_vs_th_name + ";#theta_{lab} (degrees);Kinetic Energy (MeV)"; + std::string ke_vs_ph_name = sym + modifier + "_ke_vs_phi"; + std::string ke_vs_ph_title = ke_vs_ph_name + ";#phi_{lab} (degrees);Kinetic Energy (MeV)"; + std::string th_vs_ph_name = sym + modifier + "_theta_vs_phi"; + std::string th_vs_ph_title = th_vs_ph_name + ";#theta_{lab};#phi_{lab}"; + std::string ex_name = sym + modifier + "_ex"; + std::string ex_title = ex_name + ";E_{ex} (MeV);counts"; + std::string angdist_name = sym + modifier +"_angDist"; + std::string angdist_title = angdist_name+";cos#right(#theta_{CM}#left);counts"; + + if(nuc.isDetected) + { + MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.GetKE(), 2); + MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.GetKE(), 4); + MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.vec4.Phi()*s_rad2deg, 2); + MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); + MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); + } + else + { + MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.detectedKE, 2); + MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.detectedKE, 4); + MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.vec4.Phi()*s_rad2deg, 2); + MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); + MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); + } + +} + +void RootPlotter::MyFill(const std::string& name, const std::string& title, int bins, float min, float max, double val) +{ + auto iter = m_map.find(name); + if(iter != m_map.end()) + { + std::shared_ptr h = std::static_pointer_cast(iter->second); + h->Fill(val); + } + else + { + std::shared_ptr h = std::make_shared(name.c_str(), title.c_str(), bins, min, max); + h->Fill(val); + m_map[name] = h; + } +} + +void RootPlotter::MyFill(const std::string& name, const std::string& title, int binsx, float minx, float maxx, + int binsy, float miny, float maxy, double valx, double valy) +{ + auto iter = m_map.find(name); + if(iter != m_map.end()) + { + std::shared_ptr h = std::static_pointer_cast(iter->second); + h->Fill(valx, valy); + } + else + { + std::shared_ptr h = std::make_shared(name.c_str(), title.c_str(), binsx, minx, maxx, binsy, miny, maxy); + h->Fill(valx, valy); + m_map[name] = h; + } +} + +void RootPlotter::MyFill(const std::string& name, const std::string& title, double valx, double valy, int color) +{ + auto iter = m_map.find(name); + if(iter != m_map.end()) + { + std::shared_ptr g = std::static_pointer_cast(iter->second); + g->SetPoint(g->GetN(), valx, valy); + } + else + { + std::shared_ptr g = std::make_shared(1, &valx, &valy); + g->SetName(name.c_str()); + g->SetTitle(title.c_str()); + g->SetMarkerColor(color); + m_map[name] = g; + } +} \ No newline at end of file diff --git a/src/Plotters/RootPlotter.h b/src/Plotters/RootPlotter.h new file mode 100644 index 0000000..1cc263e --- /dev/null +++ b/src/Plotters/RootPlotter.h @@ -0,0 +1,34 @@ +#ifndef ROOTPLOTTER_H +#define ROOTPLOTTER_H + +#include +#include +#include + +#include "Nucleus.h" + +#include +#include +#include + +class RootPlotter +{ +public: + RootPlotter(); + ~RootPlotter(); + + void Run(const std::string& inputname, const std::string& outputname); + +private: + void FillData(const Mask::Nucleus& nuc); + void MyFill(const std::string& name, const std::string& title, int bins, float min, float max, double val); + void MyFill(const std::string& name, const std::string& title, int binsx, float minx, float maxx, int binsy, float miny, float maxy, + double valx, double valy); + void MyFill(const std::string& name, const std::string& title, double valx, double valy, int color); //TGraph + + std::unordered_map> m_map; + + static constexpr double s_rad2deg = 180.0/M_PI; +}; + +#endif \ No newline at end of file diff --git a/src/Plotters/main.cpp b/src/Plotters/main.cpp new file mode 100644 index 0000000..43a461f --- /dev/null +++ b/src/Plotters/main.cpp @@ -0,0 +1,14 @@ +#include "RootPlotter.h" +#include + +int main(int argc, char** argv) +{ + if(argc != 3) + { + std::cerr<<"Root plotter requires two commandline arguments: path to input file and path to outputfile"< Date: Sat, 20 Aug 2022 09:05:34 -0700 Subject: [PATCH 5/8] Now passes intial testing, seems fully functional. Need to do some optimization tests against old way to see if actually improved anything. --- src/Mask/MassLookup.cpp | 4 ++-- src/Mask/MassLookup.h | 6 +++--- src/Mask/Nucleus.cpp | 2 +- src/Mask/Nucleus.h | 6 +++--- src/Plotters/RootPlotter.cpp | 25 ++++++++++++++----------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Mask/MassLookup.cpp b/src/Mask/MassLookup.cpp index 4bd1e7c..ad26256 100644 --- a/src/Mask/MassLookup.cpp +++ b/src/Mask/MassLookup.cpp @@ -41,7 +41,7 @@ namespace Mask { MassLookup::~MassLookup() {} //Returns nuclear mass in MeV - double MassLookup::FindMass(int Z, int A) + double MassLookup::FindMass(uint32_t Z, uint32_t A) { KeyPair key({Z, A}); auto data = massTable.find(key.GetID()); @@ -52,7 +52,7 @@ namespace Mask { } //returns element symbol - std::string MassLookup::FindSymbol(int Z, int A) + std::string MassLookup::FindSymbol(uint32_t Z, uint32_t A) { KeyPair key({Z, A}); auto data = elementTable.find(key.GetID()); diff --git a/src/Mask/MassLookup.h b/src/Mask/MassLookup.h index 61220cf..fac5e9e 100644 --- a/src/Mask/MassLookup.h +++ b/src/Mask/MassLookup.h @@ -35,9 +35,9 @@ namespace Mask { }; ~MassLookup(); - double FindMass(int Z, int A); - double FindMassU(int Z, int A) { return FindMass(Z, A)/u_to_mev; } - std::string FindSymbol(int Z, int A); + double FindMass(uint32_t Z, uint32_t A); + double FindMassU(uint32_t Z, uint32_t A) { return FindMass(Z, A)/u_to_mev; } + std::string FindSymbol(uint32_t Z, uint32_t A); static MassLookup& GetInstance() { return *s_instance; } diff --git a/src/Mask/Nucleus.cpp b/src/Mask/Nucleus.cpp index d375fb3..c82b7f5 100644 --- a/src/Mask/Nucleus.cpp +++ b/src/Mask/Nucleus.cpp @@ -2,7 +2,7 @@ namespace Mask { - Nucleus CreateNucleus(int z, int a) + Nucleus CreateNucleus(uint32_t z, uint32_t a) { Nucleus nuc; nuc.Z = z; diff --git a/src/Mask/Nucleus.h b/src/Mask/Nucleus.h index d5b4b47..2769cf6 100644 --- a/src/Mask/Nucleus.h +++ b/src/Mask/Nucleus.h @@ -37,8 +37,8 @@ namespace Mask { return vec4.M() - groundStateMass; } - int Z = 0; - int A = 0; + uint32_t Z = 0; + uint32_t A = 0; double groundStateMass = 0.0; std::string isotopicSymbol = ""; double thetaCM = 0.0; @@ -50,7 +50,7 @@ namespace Mask { double detectedPhi = 0.0; }; - Nucleus CreateNucleus(int z, int a); + Nucleus CreateNucleus(uint32_t z, uint32_t a); bool EnforceDictionaryLinked(); diff --git a/src/Plotters/RootPlotter.cpp b/src/Plotters/RootPlotter.cpp index 6bb7310..81918d9 100644 --- a/src/Plotters/RootPlotter.cpp +++ b/src/Plotters/RootPlotter.cpp @@ -5,6 +5,11 @@ #include +static double FullPhi(double phi) +{ + return phi < 0.0 ? 2.0*M_PI + phi : phi; +} + RootPlotter::RootPlotter() { TH1::AddDirectory(kFALSE); @@ -46,7 +51,7 @@ void RootPlotter::Run(const std::string& inputname, const std::string& outputnam output->cd(); for(auto& obj : m_map) - obj.second->Write(obj.second->GetName(), TObject::kOverwrite); + obj.second->Write(); output->Close(); } @@ -68,19 +73,17 @@ void RootPlotter::FillData(const Mask::Nucleus& nuc) std::string angdist_name = sym + modifier +"_angDist"; std::string angdist_title = angdist_name+";cos#right(#theta_{CM}#left);counts"; + + MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.GetKE(), 2); + MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), FullPhi(nuc.vec4.Phi())*s_rad2deg, nuc.GetKE(), 4); + MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, FullPhi(nuc.vec4.Phi())*s_rad2deg, 2); + MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); + MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); if(nuc.isDetected) - { - MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.GetKE(), 2); - MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.GetKE(), 4); - MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.vec4.Phi()*s_rad2deg, 2); - MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); - MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); - } - else { MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.detectedKE, 2); - MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.detectedKE, 4); - MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.vec4.Phi()*s_rad2deg, 2); + MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), FullPhi(nuc.vec4.Phi())*s_rad2deg, nuc.detectedKE, 4); + MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, FullPhi(nuc.vec4.Phi())*s_rad2deg, 2); MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); } From 322e09188424237f69bab581974acdebdd4ecf45 Mon Sep 17 00:00:00 2001 From: Gordon McCann Date: Sat, 20 Aug 2022 09:13:08 -0700 Subject: [PATCH 6/8] Update README --- README.md | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index ec05426..602d887 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,15 @@ # MASK: Monte cArlo Simulation of Kinematics MASK is a Monte Carlo simulation of reaction kinematics for use detector systems at Florida State University. -MASK is capable of simulating multi-step kinematic reaction-decay sequences, storing data in a lightweight binary format, after which the kinematic data can be fed to a detector geometry for efficiency testing. Currently geometries for ANASEN and SABRE are included in the code. +MASK is capable of simulating multi-step kinematic reaction-decay sequences, storing data in ROOT Trees, after which the kinematic data can be fed to a detector geometry for efficiency testing. Currently geometries for ANASEN and SABRE are included in the code. ## Building MASK -Dowload the repository from github. The code is to be built using Premake5, an open source and free project building software. To build on Linux and MacOSX run -`premake5 gmake2` -to generate the makefiles. Then execute -`make` -to build the program. To build on Windows run -`premake5 vs20xx` -where xx should be replaced with your version of Visual Studio, and then build as a normal Visual Studio project. For more documentation see the Premake wiki. By default `make` runs in Debug mode. For release mode use `make config=release` +Dowload the repository from github. CMake is use to build the project; in most environments you can build Mask using the following methods: +- `mkdir build` +- `cd build` +- `cmake ..` +- `make` -### Building RootPlot -One of the executables, RootPlot, requires linking against external libraries from the ROOT cern analysis package. Path to the necessary header files and libraries must be set by the user on a machine-by-machine basis in the premake5.lua file. Set the ROOTIncludepath and ROOTLibpath to match your install. An easy way to check for the paths on a unix system is through the root-config tool. root-config --cflags has the include path (the path after -I) and root-config --glibs has the lib path (after -L). If you do not have ROOT installed, you will not be able to compile RootPlot, and you will not be able to use the generic `make` command, which will try to build all executables. Instead use `make Mask` or `make DetectEff` (or `make config=release Mask`, etc). +Executables will be installed to the repostiory's `bin` directory. Libraries will be installed to the `lib` directory. ## Running MASK By default MASK is capable of simulating reactions of up to three steps. Here is a brief outline of each type: @@ -22,7 +19,7 @@ By default MASK is capable of simulating reactions of up to three steps. Here is 2. A reaction of type 2 is a reaction followed by a subsequent decay of the residual nucleus. Again, all sampling is allowed. 3. A reaction of type 3 is a reaction followed by a subsequent decay of the residual, followed by a decay of one of the products. Again, all sampling is allowed -For decays, a specific angular distribution can be given as input as a text file with values of coefficiencts of a Legendre polynomial series. Examples can be found in the `./etc` directory, including an isotropic case. It is assumed that the decays in the center-of-mass frame are isotropic in phi (i.e. m=0). Decay1 corresponds to the first decay, if there are multiple steps, Decay2 to the second. If there are no decays, these parameters are not used (or if only one decay, Decay2_AngularMomentum is not used). The input file requires that the user include target information, which will be used to calculate energy loss for all of the reactants and reaction products. The target can contain layers, and each layer can be composed of a compound of elements with a given stoichiometry. If the user wishes to not include energy loss in the kinematics, simply give all target layers a thickness of 0. Note that more layers and more thickness = more time spent calculating energy loss. These energy loss methods are only applicable for solid targets, and should not be applied to gas or liquid targets. Energy loss calculations have a stated uncertainty of approximately five percent. +For decays, a specific angular distribution can be given as input as a text file with values of coefficiencts of a Legendre polynomial series. Examples can be found in the `./etc` directory, including an isotropic case. It is assumed that the decays in the center-of-mass frame are isotropic in phi (i.e. m=0). Decay1 corresponds to the first decay, if there are multiple steps, Decay2 to the second. If there are no decays, these parameters are not used (or if only one decay, Decay2_AngularMomentum is not used). The input file requires that the user include target information, which will be used to calculate energy loss for all of the reactants and reaction products. The energy loss through materials is calculated using the `catima` library (found in `src/vendor`), which is a C/C++ interface to the `atima` library (the same energy loss methods used by LISE). The target can contain layers, and each layer can be composed of a compound of elements with a given stoichiometry. If the user wishes to not include energy loss in the kinematics, simply give all target layers a thickness of 0. Note that more layers and more thickness = more time spent calculating energy loss. These energy loss methods are only applicable for solid targets, and should not be applied to gas or liquid targets. Energy loss calculations have a stated uncertainty of approximately five percent. To choose which detector scheme is run, modify the main function in DetectorEfficiency.cpp. The included geometries also have options to do an internal geometry consistency check and print out coordinates for drawing the detector arrays. @@ -36,7 +33,7 @@ To run DetEff use the format `./bin/DetEff ` -where the detection datafile contains all of the kinematics data as well as information about which particles are detected (this is in the mask file format) and the statsfile is a text file containing efficiency statistics. +where the detection datafile contains all of the kinematics data as well as information about which particles are detected and the statsfile is a text file containing efficiency statistics. RootPlot is run as @@ -44,12 +41,6 @@ RootPlot is run as where the datafile can be either the datafile from Mask or the datafile from DetEff. The outputfile is saved in the ROOT file format. -PyPlotter is run as - -`./bin/PyPlotter ` - -where again datafile can come from either Mask or DetEff. The outputfile is saved in the Python pickle file format. Pickled files can be reopened using the PyPlotViewer script run as -`./bin/PyPlotViewer ` - ## Requirements -MASK, the kinematics simulation, and DetEff, the detection efficiency simulation, require no external dependancies. The RootPlot plotting tool requires the ROOT cern data analysis package, and the PyPlotter tool requires Python3 and the matplotlib and numpy packages. \ No newline at end of file +ROOT version 6.22 or greater is required +CMake version 3.0 or greater is required \ No newline at end of file From 216e597c57a9e85fad73641f91d5236fe36f5c92 Mon Sep 17 00:00:00 2001 From: gwm17 Date: Mon, 29 Aug 2022 15:14:55 -0400 Subject: [PATCH 7/8] Clean up user input, inheritance structure. Update input.txt, README. Add in default release build --- CMakeLists.txt | 8 ++ README.md | 61 ++++++++------- input.txt | 23 +++--- src/Mask/AngularDistribution.cpp | 3 + src/Mask/DecaySystem.h | 2 +- src/Mask/MaskApp.cpp | 126 ++++++------------------------- src/Mask/Nucleus.h | 4 +- src/Mask/OneStepSystem.h | 2 +- src/Mask/Reaction.cpp | 15 ++-- src/Mask/Reaction.h | 8 +- src/Mask/ReactionSystem.cpp | 24 ++++++ src/Mask/ReactionSystem.h | 7 +- src/Mask/RxnType.h | 30 ++++++++ src/Mask/ThreeStepSystem.h | 6 +- src/Mask/TwoStepSystem.h | 4 +- src/Plotters/RootPlotter.cpp | 22 +++--- 16 files changed, 171 insertions(+), 174 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 289801a..55d5672 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,13 @@ cmake_minimum_required(VERSION 3.16) + +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_BUILD_TYPE "Release") + message("Building release") +else() + message("Building debug") +endif() + project(Mask) set(MASK_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin) diff --git a/README.md b/README.md index ec05426..1842173 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,58 @@ # MASK: Monte cArlo Simulation of Kinematics MASK is a Monte Carlo simulation of reaction kinematics for use detector systems at Florida State University. -MASK is capable of simulating multi-step kinematic reaction-decay sequences, storing data in a lightweight binary format, after which the kinematic data can be fed to a detector geometry for efficiency testing. Currently geometries for ANASEN and SABRE are included in the code. +MASK is capable of simulating multi-step kinematic reaction-decay sequences, storing data in a lightweight binary format, after which the kinematic data can be fed to a detector geometry for efficiency testing. Currently geometries for ANASEN and SABRE are included in the code. Mask depends on the CERN ROOT analysis framework. All data is stored in the ROOT format using a custom dictionary. ## Building MASK -Dowload the repository from github. The code is to be built using Premake5, an open source and free project building software. To build on Linux and MacOSX run -`premake5 gmake2` -to generate the makefiles. Then execute -`make` -to build the program. To build on Windows run -`premake5 vs20xx` -where xx should be replaced with your version of Visual Studio, and then build as a normal Visual Studio project. For more documentation see the Premake wiki. By default `make` runs in Debug mode. For release mode use `make config=release` +To clone MASK and all submodules use `git clone --recursive https://github.com/gwm17/Kinematics.git`. +Mask is built using the CMake build tool. On most systems this can be done using the following commands inside the Mask repository: -### Building RootPlot -One of the executables, RootPlot, requires linking against external libraries from the ROOT cern analysis package. Path to the necessary header files and libraries must be set by the user on a machine-by-machine basis in the premake5.lua file. Set the ROOTIncludepath and ROOTLibpath to match your install. An easy way to check for the paths on a unix system is through the root-config tool. root-config --cflags has the include path (the path after -I) and root-config --glibs has the lib path (after -L). If you do not have ROOT installed, you will not be able to compile RootPlot, and you will not be able to use the generic `make` command, which will try to build all executables. Instead use `make Mask` or `make DetectEff` (or `make config=release Mask`, etc). +- `mkdir build` +- `cd build` +- `cmake ..` +- `make` -## Running MASK +By default Mask builds for release. To build for debug replace `cmake ..` with `cmake -DCMAKE_BUILD_TYPE=Debug ..`. Mask uses CMake to find the installed ROOT libraries and headers. + +## Using the kinematics simulation By default MASK is capable of simulating reactions of up to three steps. Here is a brief outline of each type: -0. A reaction of type 0 is a pure decay. It is assumed isotropic by default; any other case will require the modification of the code. -1. A reaction of type 1 is a pure reaction. It can incorporate all of the input file sampling parameters. -2. A reaction of type 2 is a reaction followed by a subsequent decay of the residual nucleus. Again, all sampling is allowed. -3. A reaction of type 3 is a reaction followed by a subsequent decay of the residual, followed by a decay of one of the products. Again, all sampling is allowed +0. A pure decay involves a "target" decaying into an ejectile and residual. It is assumed isotropic by default; any other case will require the modification of the code. +1. A single step reaction involves a target being hit by a projectile and emitting an ejectile and a residual. It can incorporate all of the input file sampling parameters. +2. A two step reaction is a single step reaction where the residual subsequently decays into two daughters (called breakups). Again, all sampling is allowed. +3. A three step reaction is a two step reaction where one of the breakup particles subsequently decays into two more breakup particles. Again, all sampling is allowed -For decays, a specific angular distribution can be given as input as a text file with values of coefficiencts of a Legendre polynomial series. Examples can be found in the `./etc` directory, including an isotropic case. It is assumed that the decays in the center-of-mass frame are isotropic in phi (i.e. m=0). Decay1 corresponds to the first decay, if there are multiple steps, Decay2 to the second. If there are no decays, these parameters are not used (or if only one decay, Decay2_AngularMomentum is not used). The input file requires that the user include target information, which will be used to calculate energy loss for all of the reactants and reaction products. The target can contain layers, and each layer can be composed of a compound of elements with a given stoichiometry. If the user wishes to not include energy loss in the kinematics, simply give all target layers a thickness of 0. Note that more layers and more thickness = more time spent calculating energy loss. These energy loss methods are only applicable for solid targets, and should not be applied to gas or liquid targets. Energy loss calculations have a stated uncertainty of approximately five percent. +For decays, a specific angular distribution can be given as input as a text file with values of coefficiencts of a Legendre polynomial series. Examples can be found in the `./etc` directory, including an isotropic case. It is assumed that the decays in the center-of-mass frame are isotropic in phi (i.e. m=0). Decay1 corresponds to the first decay, if there are multiple steps, Decay2 to the second. If there are no decays, these parameters are not used (or if only one decay, Decay2_AngularMomentum is not used). -To choose which detector scheme is run, modify the main function in DetectorEfficiency.cpp. The included geometries also have options to do an internal geometry consistency check and print out coordinates for drawing the detector arrays. +The input file requires that the user include target information, which will be used to calculate energy loss for all of the reactants and reaction products. The target can contain layers, and each layer can be composed of a compound of elements with a given stoichiometry. If the user wishes to not include energy loss in the kinematics, simply give all target layers a thickness of 0. Note that more layers and more thickness = more time spent calculating energy loss. These energy loss methods are only applicable for solid targets, and should not be applied to gas or liquid targets. Energy loss calculations have a stated uncertainty of approximately five percent. The energy loss library used is called `catima` and can be found [here](https://github.com/gwm17/catima). -To run MASK simply do the following from the MASK directory: +To run MASK simply do the following from the MASK repository: -`./bin/Mask input.txt` +`./bin/MaskApp input.txt` Input.txt can be replaced by any text file with the correct format. +## Using the detector geometry simulation +Detector geometry is encoded using ROOT math libraries in the `src/Detectors` folder. Two different detector geometries are already present: SPS-SABRE and ANASEN. To add a new geometry, follow the guidelines outlined by each of these cases. + +To choose which detector scheme is run, modify the main function in `src/Detectors/main.cpp`. The included geometries also have options to do an internal geometry consistency check and print out coordinates for drawing the detector arrays, which can be useful for testing. + + + To run DetEff use the format `./bin/DetEff ` where the detection datafile contains all of the kinematics data as well as information about which particles are detected (this is in the mask file format) and the statsfile is a text file containing efficiency statistics. -RootPlot is run as +## Data visualization +All data is saved as ROOT trees of std::vectors of Mask::Nucleus classes. To enable this, a ROOT dictionary is generated and linked into a shared library found in the `lib` directory of the repository. This allows the user to link to the shared library for accessing and analyzing the data generated by MASK. + +Mask also provides a default visualization tool called RootPlot. RootPlot is run as `./bin/RootPlot ` -where the datafile can be either the datafile from Mask or the datafile from DetEff. The outputfile is saved in the ROOT file format. - -PyPlotter is run as - -`./bin/PyPlotter ` - -where again datafile can come from either Mask or DetEff. The outputfile is saved in the Python pickle file format. Pickled files can be reopened using the PyPlotViewer script run as -`./bin/PyPlotViewer ` +where the datafile can be either the datafile from Mask or the datafile from DetEff.s ## Requirements -MASK, the kinematics simulation, and DetEff, the detection efficiency simulation, require no external dependancies. The RootPlot plotting tool requires the ROOT cern data analysis package, and the PyPlotter tool requires Python3 and the matplotlib and numpy packages. \ No newline at end of file +- Requires CMake > 3.16 +- Requires ROOT > 6.16 \ No newline at end of file diff --git a/input.txt b/input.txt index 215185c..5ca223b 100644 --- a/input.txt +++ b/input.txt @@ -1,25 +1,26 @@ ----------Data Information---------- -OutputFile: /media/data/gwm17/mask_tests/10B3Hea_test.root +OutputFile: /media/data/gwm17/mask_tests/10B3Hea_16800keV_5Lia_74B.root ----------Reaction Information---------- -ReactionType: OneStepRxn -Z A (order is target, projectile, ejectile, break1, break3(if pure decay is target, ejectile)) -5 10 -2 3 -2 4 +begin_nuclei(Z,A) + 5 10 + 2 3 + 2 4 + 2 4 +end_nuclei(Z,A) ----------Target Information---------- NumberOfLayers: 1 begin_layer - Thickness(ug/cm^2): 50 + Thickness(ug/cm^2): 74 begin_elements (Z, A, Stoich.) element 5 10 1 end_elements end_layer ----------Sampling Information---------- -NumberOfSamples: 1000 +NumberOfSamples: 1000000 BeamMeanEnergy(MeV): 24.0 BeamEnergySigma(MeV): 0.0 -EjectileThetaType(0=Lab,1=CM): 1 -EjectileThetaMin(deg): 0.0 EjectileThetaMax(deg): 180.0 -EjectilePhiMin(deg): 0.0 EjectilePhiMax(deg): 360.0 +EjectileThetaType(0=Lab,1=CM): 0 +EjectileThetaMin(deg): 15.0 EjectileThetaMax(deg): 15.0 +EjectilePhiMin(deg): 0.0 EjectilePhiMax(deg): 0.0 ResidualExMean(MeV): 16.8 ResidualExSigma(MeV): 0.023 Decay1_DistributionFile: ./etc/isotropic_dist.txt Decay2_DistributionFile: ./etc/isotropic_dist.txt diff --git a/src/Mask/AngularDistribution.cpp b/src/Mask/AngularDistribution.cpp index 54ec7a9..0884e80 100644 --- a/src/Mask/AngularDistribution.cpp +++ b/src/Mask/AngularDistribution.cpp @@ -72,6 +72,9 @@ namespace Mask { //Total branching ratio m_branchingRatio = m_constants[0]*2.0; m_L = l; + + std::cout<<"Angular distribution from "<*GetNuclei() override; - void SetDecay1Distribution(const std::string& filename) { m_step1Distribution.ReadDistributionFile(filename); } + virtual void SetDecay1Distribution(const std::string& filename) override { m_step1Distribution.ReadDistributionFile(filename); } int GetDecay1AngularMomentum() { return m_step1Distribution.GetL(); } double GetDecay1BranchingRatio() { return m_step1Distribution.GetBranchingRatio(); } diff --git a/src/Mask/MaskApp.cpp b/src/Mask/MaskApp.cpp index 490b3e4..07a92e8 100644 --- a/src/Mask/MaskApp.cpp +++ b/src/Mask/MaskApp.cpp @@ -36,62 +36,29 @@ namespace Mask { int z, a, s; getline(input, junk); getline(input, junk); - input>>junk>>junk; - m_rxnType = GetRxnTypeFromString(junk); - getline(input, junk); - getline(input, junk); - switch(m_rxnType) + + while(input>>junk) { - case RxnType::PureDecay: - { - m_system = new DecaySystem(); - for(int i=0; i<2; i++) - { - input>>z>>a; - avec.push_back(a); - zvec.push_back(z); - } + if(junk == "begin_nuclei(Z,A)") + continue; + else if (junk == "end_nuclei(Z,A)") break; - } - case RxnType::OneStepRxn: + else { - m_system = new OneStepSystem(); - for(int i=0; i<3; i++) - { - input>>z>>a; - avec.push_back(a); - zvec.push_back(z); - } - std::cout<<"here"<>a; + zvec.push_back(z); + avec.push_back(a); } - case RxnType::TwoStepRxn: - { - m_system = new TwoStepSystem(); - for(int i=0; i<4; i++) - { - input>>z>>a; - avec.push_back(a); - zvec.push_back(z); - } - break; - } - case RxnType::ThreeStepRxn: - { - m_system = new ThreeStepSystem(); - for(int i=0; i<5; i++) - { - input>>z>>a; - avec.push_back(a); - zvec.push_back(z); - } - break; - } - default: - return false; } - m_system->SetNuclei(zvec, avec); - + + m_system = CreateSystem(zvec, avec); + if(m_system == nullptr) + { + std::cerr<<"Failure to parse reaction system... configuration not loaded."<>junk>>m_nsamples; input>>junk>>par1>>junk>>par2; m_system->SetBeamDistro(par1, par2); - input>>junk>>par1; - switch(m_rxnType) - { - case RxnType::PureDecay : break; - case RxnType::None : break; - case RxnType::OneStepRxn : - { - dynamic_cast(m_system)->SetReactionThetaType(par1); - break; - } - case RxnType::TwoStepRxn : - { - dynamic_cast(m_system)->SetReactionThetaType(par1); - break; - } - case RxnType::ThreeStepRxn : - { - dynamic_cast(m_system)->SetReactionThetaType(par1); - break; - } - } + input>>junk>>thetaTypeString; + m_system->SetReactionThetaType(StringToRxnThetaType(thetaTypeString)); + input>>junk>>par1>>junk>>par2; m_system->SetTheta1Range(par1, par2); input>>junk>>par1>>junk>>par2; @@ -155,36 +105,8 @@ namespace Mask { m_system->SetExcitationDistro(par1, par2); input>>junk>>dfile1; input>>junk>>dfile2; - switch(m_rxnType) - { - case RxnType::PureDecay : - { - DecaySystem* this_sys = dynamic_cast(m_system); - this_sys->SetDecay1Distribution(dfile1); - std::cout<<"Decay1 angular momentum: "<GetDecay1AngularMomentum()<GetDecay1BranchingRatio()<(m_system); - this_sys->SetDecay1Distribution(dfile1); - std::cout<<"Decay1 angular momentum: "<GetDecay1AngularMomentum()<GetDecay1BranchingRatio()<(m_system); - this_sys->SetDecay1Distribution(dfile1); - this_sys->SetDecay2Distribution(dfile2); - std::cout<<"Decay1 angular momentum: "<GetDecay1AngularMomentum()<<" Decay2 angular momentum: "<GetDecay2AngularMomentum()<GetDecay1BranchingRatio()<<" Decay2 total branching ratio: "<GetDecay2BranchingRatio()<SetDecay1Distribution(dfile1); + m_system->SetDecay2Distribution(dfile2); std::cout<<"Number of samples: "<* GetNuclei() override; - void SetReactionThetaType(int type) { m_step1.SetEjectileThetaType(type); }; + virtual void SetReactionThetaType(RxnThetaType type) override { m_step1.SetEjectileThetaType(type); }; private: void LinkTarget() override; diff --git a/src/Mask/Reaction.cpp b/src/Mask/Reaction.cpp index e77e144..fbc1d07 100644 --- a/src/Mask/Reaction.cpp +++ b/src/Mask/Reaction.cpp @@ -15,13 +15,13 @@ namespace Mask { Reaction::Reaction() : m_target(nullptr), m_projectile(nullptr), m_ejectile(nullptr), m_residual(nullptr), m_layeredTarget(nullptr), - m_bke(0), m_theta(0), m_phi(0), m_ex(0), m_rxnLayer(0), m_ejectThetaType(s_lab), m_isInit(false), m_isResidEloss(false) + m_bke(0), m_theta(0), m_phi(0), m_ex(0), m_rxnLayer(0), m_ejectThetaType(RxnThetaType::None), m_isInit(false), m_isResidEloss(false) { } Reaction::Reaction(Nucleus* target, Nucleus* projectile, Nucleus* ejectile, Nucleus* residual) : m_target(nullptr), m_projectile(nullptr), m_ejectile(nullptr), m_residual(nullptr), - m_layeredTarget(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), m_rxnLayer(0), m_ejectThetaType(s_lab), m_isResidEloss(false) + m_layeredTarget(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), m_rxnLayer(0), m_ejectThetaType(RxnThetaType::None), m_isResidEloss(false) { BindNuclei(target, projectile, ejectile, residual); } @@ -70,13 +70,11 @@ namespace Mask { m_bke = bke - m_layeredTarget->GetProjectileEnergyLoss(m_projectile->Z, m_projectile->A, bke, m_rxnLayer, 0); } - void Reaction::SetEjectileThetaType(int type) + void Reaction::SetEjectileThetaType(RxnThetaType type) { if(m_isDecay) return; - if(type != s_centerOfMass && type != s_lab) - return; - + m_ejectThetaType = type; } @@ -180,8 +178,9 @@ namespace Mask { { switch(m_ejectThetaType) { - case s_centerOfMass: CalculateReactionThetaCM(); break; - case s_lab: CalculateReactionThetaLab(); break; + case RxnThetaType::CenterOfMass: CalculateReactionThetaCM(); break; + case RxnThetaType::Lab: CalculateReactionThetaLab(); break; + case RxnThetaType::None: CalculateReactionThetaCM(); break; //default behavior } } diff --git a/src/Mask/Reaction.h b/src/Mask/Reaction.h index a1c166c..7923139 100644 --- a/src/Mask/Reaction.h +++ b/src/Mask/Reaction.h @@ -11,6 +11,7 @@ #include "Nucleus.h" #include "LayeredTarget.h" +#include "RxnType.h" namespace Mask { @@ -24,7 +25,7 @@ namespace Mask { void BindNuclei(Nucleus* target, Nucleus* projectile, Nucleus* ejectile, Nucleus* residual); void SetBeamKE(double bke); - void SetEjectileThetaType(int type); + void SetEjectileThetaType(RxnThetaType type); void SetLayeredTarget(LayeredTarget* targ) { m_layeredTarget = targ; }; @@ -61,12 +62,9 @@ namespace Mask { double m_bke, m_theta, m_phi, m_ex; int m_rxnLayer; - int m_ejectThetaType; + RxnThetaType m_ejectThetaType; bool m_isDecay, m_isInit, m_isResidEloss; - - static constexpr int s_lab = 0; - static constexpr int s_centerOfMass = 1; }; } diff --git a/src/Mask/ReactionSystem.cpp b/src/Mask/ReactionSystem.cpp index dd18de2..f8e9cb9 100644 --- a/src/Mask/ReactionSystem.cpp +++ b/src/Mask/ReactionSystem.cpp @@ -1,6 +1,11 @@ #include "ReactionSystem.h" +#include "RxnType.h" #include "KinematicsExceptions.h" #include "LegendrePoly.h" +#include "DecaySystem.h" +#include "OneStepSystem.h" +#include "TwoStepSystem.h" +#include "ThreeStepSystem.h" namespace Mask { @@ -23,4 +28,23 @@ namespace Mask { m_target.AddLayer(zt, at, stoich, thickness); } + ReactionSystem* CreateSystem(const std::vector& z, const std::vector& a) + { + if(z.size() != a.size()) + { + std::cerr<<"Size of Z list does not equal size of A list!"< #include @@ -25,6 +26,9 @@ namespace Mask { virtual bool SetNuclei(const std::vector& z, const std::vector& a) = 0; virtual void RunSystem() = 0; virtual std::vector* GetNuclei() = 0; + virtual void SetReactionThetaType(RxnThetaType type) {} + virtual void SetDecay1Distribution(const std::string& filename) {} + virtual void SetDecay2Distribution(const std::string& filename) {} void AddTargetLayer(const std::vector& zt, const std::vector& at, const std::vector& stoich, double thickness); @@ -56,7 +60,7 @@ namespace Mask { delete m_exDist; m_exDist = new std::normal_distribution(mean, sigma); } - + const std::string& GetSystemEquation() const { return m_sysEquation; } protected: @@ -76,6 +80,7 @@ namespace Mask { static constexpr double s_deg2rad = M_PI/180.0; }; + ReactionSystem* CreateSystem(const std::vector& z, const std::vector& a); } #endif \ No newline at end of file diff --git a/src/Mask/RxnType.h b/src/Mask/RxnType.h index bd2f8bc..9b4f841 100644 --- a/src/Mask/RxnType.h +++ b/src/Mask/RxnType.h @@ -14,6 +14,21 @@ namespace Mask { None=4 }; + enum class RxnThetaType + { + CenterOfMass, + Lab, + None + }; + + enum RxnSize + { + DecaySize = 2, + OneStepSize = 3, + TwoStepSize = 4, + ThreeStepSize = 5 + }; + static RxnType GetRxnTypeFromString(const std::string& type_str) { if (type_str == "PureDecay") @@ -52,6 +67,21 @@ namespace Mask { return static_cast(type); } + static RxnThetaType StringToRxnThetaType(const std::string& type) + { + if(type == "CenterOfMass") + { + return RxnThetaType::CenterOfMass; + } + else if(type == "Lab") + { + return RxnThetaType::Lab; + } + else + { + return RxnThetaType::None; + } + } } #endif \ No newline at end of file diff --git a/src/Mask/ThreeStepSystem.h b/src/Mask/ThreeStepSystem.h index 9e800a2..a79017e 100644 --- a/src/Mask/ThreeStepSystem.h +++ b/src/Mask/ThreeStepSystem.h @@ -15,10 +15,10 @@ namespace Mask { void RunSystem() override; std::vector* GetNuclei() override; - inline void SetDecay1Distribution(const std::string& filename) { m_step2Distribution.ReadDistributionFile(filename); }; - inline void SetDecay2Distribution(const std::string& filename) { m_step3Distribution.ReadDistributionFile(filename); }; + virtual void SetDecay1Distribution(const std::string& filename) override { m_step2Distribution.ReadDistributionFile(filename); }; + virtual void SetDecay2Distribution(const std::string& filename) override { m_step3Distribution.ReadDistributionFile(filename); }; - void SetReactionThetaType(int type) { m_step1.SetEjectileThetaType(type); }; + virtual void SetReactionThetaType(RxnThetaType type) override { m_step1.SetEjectileThetaType(type); }; int GetDecay1AngularMomentum() { return m_step2Distribution.GetL(); }; int GetDecay2AngularMomentum(){ return m_step3Distribution.GetL(); }; diff --git a/src/Mask/TwoStepSystem.h b/src/Mask/TwoStepSystem.h index 55623b4..9b1249b 100644 --- a/src/Mask/TwoStepSystem.h +++ b/src/Mask/TwoStepSystem.h @@ -16,9 +16,9 @@ namespace Mask { void RunSystem() override; std::vector* GetNuclei() override; - void SetDecay1Distribution(const std::string& filename) { m_step2Distribution.ReadDistributionFile(filename); }; + virtual void SetDecay1Distribution(const std::string& filename) override { m_step2Distribution.ReadDistributionFile(filename); }; - void SetReactionThetaType(int type) { m_step1.SetEjectileThetaType(type); }; + virtual void SetReactionThetaType(RxnThetaType type) override { m_step1.SetEjectileThetaType(type); }; int GetDecay1AngularMomentum() { return m_step2Distribution.GetL(); }; double GetDecay1BranchingRatio() { return m_step2Distribution.GetBranchingRatio(); }; diff --git a/src/Plotters/RootPlotter.cpp b/src/Plotters/RootPlotter.cpp index 6bb7310..476f934 100644 --- a/src/Plotters/RootPlotter.cpp +++ b/src/Plotters/RootPlotter.cpp @@ -34,13 +34,20 @@ void RootPlotter::Run(const std::string& inputname, const std::string& outputnam for(uint64_t i=0; iGetEntry(i); for(Mask::Nucleus& nuc : *(dataHandle)) { FillData(nuc); } } - + std::cout<Close(); delete dataHandle; @@ -68,15 +75,12 @@ void RootPlotter::FillData(const Mask::Nucleus& nuc) std::string angdist_name = sym + modifier +"_angDist"; std::string angdist_title = angdist_name+";cos#right(#theta_{CM}#left);counts"; + MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.GetKE(), 2); + MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.GetKE(), 4); + MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.vec4.Phi()*s_rad2deg, 2); + MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); + MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); if(nuc.isDetected) - { - MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.GetKE(), 2); - MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.GetKE(), 4); - MyFill(th_vs_ph_name.c_str(), th_vs_ph_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.vec4.Phi()*s_rad2deg, 2); - MyFill(ex_name.c_str(),ex_title.c_str(),260,-1.0,25,nuc.GetExcitationEnergy()); - MyFill(angdist_name.c_str(), angdist_title.c_str(),20,-1.0,1.0,std::cos(nuc.thetaCM)); - } - else { MyFill(ke_vs_th_name.c_str(), ke_vs_th_title.c_str(), nuc.vec4.Theta()*s_rad2deg, nuc.detectedKE, 2); MyFill(ke_vs_ph_name.c_str(), ke_vs_ph_title.c_str(), nuc.vec4.Phi()*s_rad2deg, nuc.detectedKE, 4); From 2c2a24fd1e9e83446c40d3b5907f6aa43662a14a Mon Sep 17 00:00:00 2001 From: gwm17 Date: Mon, 29 Aug 2022 15:24:15 -0400 Subject: [PATCH 8/8] Cleanup README --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 89aeef0..f28a651 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,6 @@ By default MASK is capable of simulating reactions of up to three steps. Here is For decays, a specific angular distribution can be given as input as a text file with values of coefficiencts of a Legendre polynomial series. Examples can be found in the `./etc` directory, including an isotropic case. It is assumed that the decays in the center-of-mass frame are isotropic in phi (i.e. m=0). Decay1 corresponds to the first decay, if there are multiple steps, Decay2 to the second. If there are no decays, these parameters are not used (or if only one decay, Decay2_AngularMomentum is not used). The input file requires that the user include target information, which will be used to calculate energy loss for all of the reactants and reaction products. The energy loss through materials is calculated using the `catima` library (found in `src/vendor`), which is a C/C++ interface to the `atima` library (the same energy loss methods used by LISE). The target can contain layers, and each layer can be composed of a compound of elements with a given stoichiometry. If the user wishes to not include energy loss in the kinematics, simply give all target layers a thickness of 0. Note that more layers and more thickness = more time spent calculating energy loss. These energy loss methods are only applicable for solid targets, and should not be applied to gas or liquid targets. Energy loss calculations have a stated uncertainty of approximately five percent. -The input file requires that the user include target information, which will be used to calculate energy loss for all of the reactants and reaction products. The target can contain layers, and each layer can be composed of a compound of elements with a given stoichiometry. If the user wishes to not include energy loss in the kinematics, simply give all target layers a thickness of 0. Note that more layers and more thickness = more time spent calculating energy loss. These energy loss methods are only applicable for solid targets, and should not be applied to gas or liquid targets. Energy loss calculations have a stated uncertainty of approximately five percent. The energy loss library used is called `catima` and can be found [here](https://github.com/gwm17/catima). - To run MASK simply do the following from the MASK repository: `./bin/MaskApp input.txt` @@ -36,8 +34,6 @@ Detector geometry is encoded using ROOT math libraries in the `src/Detectors` fo To choose which detector scheme is run, modify the main function in `src/Detectors/main.cpp`. The included geometries also have options to do an internal geometry consistency check and print out coordinates for drawing the detector arrays, which can be useful for testing. - - To run DetEff use the format `./bin/DetEff `