1
0
Fork 0
mirror of https://github.com/gwm17/Mask.git synced 2024-05-18 23:03:20 -04:00

Update gitignore

This commit is contained in:
Gordon McCann 2022-08-18 10:31:16 -04:00
parent 9a4c308677
commit 66900ea9b4
22 changed files with 3 additions and 1766 deletions

5
.gitignore vendored
View File

@ -9,14 +9,15 @@
*.pcm
*.o
*.a
*.so
*.swp
*.pickle
.DS_Store
Makefile
*.make
__pycache__
.vscode/
build/
lib/
bin/
###Keep this file###

5
bin/.gitignore vendored
View File

@ -1,5 +0,0 @@
###keep only the directory, not the contents###
*
!.gitignore
!PyPlotter
!PyPlotViewer

View File

@ -1,5 +0,0 @@
#!/bin/bash
FileName=$1;
./src/Plotters/Python/ViewPyPlots.py ${FileName}

View File

@ -1,6 +0,0 @@
#!/bin/bash
InputFile=$1;
OutputFile=$2;
./src/Plotters/Python/PyPlotter.py ${InputFile} ${OutputFile}

View File

@ -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

View File

@ -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 <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <cmath>
#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<int>& Zt, const std::vector<int>& At, const std::vector<int>& 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<int> ZT, AT;
std::vector<double> 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

View File

@ -1,77 +0,0 @@
#ifndef MASKFILE_H
#define MASKFILE_H
#include <string>
#include <fstream>
#include <vector>
#include "Nucleus.h"
#include "RxnType.h"
namespace Mask {
struct MaskFileHeader {
RxnType rxn_type = RxnType::None;
int nsamples = -1;
};
struct MaskFileData {
std::vector<double> E, KE, p, theta, phi; //ordered: target, (if not decay)projectile, ejectile, residual, break1...
std::vector<int> Z, A;
std::vector<bool> 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<Nucleus>& 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<char> 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

View File

@ -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

View File

@ -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 <cmath>
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

View File

@ -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 <cmath>
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

View File

@ -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 <iostream>
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<int>& Zt, const std::vector<int>& At, const std::vector<int>& Stoich) {
comp_denom = 0;
ZT = Zt;
AT = At;
for(unsigned int i=0; i<Stoich.size(); i++) {
comp_denom += Stoich[i];
if(ZT[i] > MAX_Z)
throw ELossException("Maximum allowed target Z exceeded");
}
targ_composition.resize(Stoich.size());
for(unsigned int i=0; i<Stoich.size(); i++)
targ_composition[i] = Stoich[i]/comp_denom;
}
/*
Returns units of MeV; thickness in ug/cm^2; e_initial in units of MeV
Energy loss going through the target
*/
double EnergyLoss::GetEnergyLoss(int zp, int ap, double e_initial, double thickness) {
if( ZP != zp) {
ZP = zp;
AP = ap;
MP = MassLookup::GetInstance().FindMass(ZP, AP)*MEV2U;
}
if(thickness == 0.0 || e_initial == 0.0 || zp == 0)
return 0;
double e_final = e_initial;
double x_traversed = 0;
double x_step = 0.25*thickness; //initial step in x
double e_step = GetTotalStoppingPower(e_final)*x_step/1000.0; //initial step in e
double e_threshold = 0.05*e_initial;
int depth=0;
bool go = true;
while(go) {
//If intial guess of step size is too large, shrink until in range
if(e_step/e_final > 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<double> 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<values.size(); i++)
values[i] *= CalculateEffectiveChargeRatio(e_per_u, ZT[i]);
}
double stopping_total = 0;
double conversion_factor = 0;
for(unsigned int i=0; i<ZT.size(); i++) {
conversion_factor += targ_composition[i]*NATURAL_MASS[ZT[i]];
stopping_total += values[i]*targ_composition[i];
}
stopping_total *= AVOGADRO/conversion_factor;
return stopping_total;
}
//Returns units of keV/(ug/cm^2)
double EnergyLoss::GetNuclearStoppingPower(double energy) {
energy *= 1000.0;
double stopping_total = 0.0;
double sn, x, epsilon, conversion_factor;
for(unsigned int i=0; i<ZT.size(); i++) {
x = (MP + NATURAL_MASS[ZT[i]]) * std::sqrt(std::pow(ZP, 2.0/3.0) + std::pow(ZT[i], 2.0/3.0));
epsilon = 32.53*NATURAL_MASS[ZT[i]]*energy/(ZP*ZT[i]*x);
sn = 8.462*(0.5*std::log(1.0+epsilon)/(epsilon+0.10718*std::pow(epsilon, 0.37544)))*ZP*ZT[i]*MP/x;
conversion_factor = AVOGADRO/NATURAL_MASS[ZT[i]];
stopping_total += sn*conversion_factor*targ_composition[i];
}
return stopping_total;
}
/*Wrapper function for aquiring total stopping (elec + nuc)*/
double EnergyLoss::GetTotalStoppingPower(double energy) {
if(ZP == 0)
return GetNuclearStoppingPower(energy);
return GetElectronicStoppingPower(energy)+GetNuclearStoppingPower(energy);
}
/*Charge rel to H*/
double EnergyLoss::CalculateEffectiveChargeRatio(double e_per_u, int z) {
double z_ratio;
if(ZP == 2) {
double ln_epu = std::log(e_per_u);
double gamma = 1.0+(0.007+0.00005*z)*std::exp(-std::pow(7.6-ln_epu,2.0));
double alpha = 0.7446 + 0.1429*ln_epu + 0.01562*std::pow(ln_epu, 2.0) - 0.00267*std::pow(ln_epu,3.0)
+ 1.338E-6*std::pow(ln_epu,8.0);
z_ratio = gamma*(1.0-std::exp(-alpha))*2.0;
} else if (ZP == 3) {
double ln_epu = std::log(e_per_u);
double gamma = 1.0+(0.007+0.00005*z)*std::exp(-std::pow(7.6-ln_epu,2.0));
double alpha = 0.7138+0.002797*e_per_u+1.348E-6*std::pow(e_per_u, 2.0);
z_ratio = gamma*(1-std::exp(-alpha))*3.0;
} else {
double B = 0.886*std::pow(e_per_u/25.0, 0.5)/std::pow(ZP, 2.0/3.0);
double A = B + 0.0378*std::sin(M_PI/2.0*B);
z_ratio = (1.0 - std::exp(-A)*(1.034-0.1777*std::exp(-0.08114*ZP)))*ZP;
}
return z_ratio*z_ratio; //for stopping power uses ratio sq.
}
double EnergyLoss::Hydrogen_dEdx_Low(double e_per_u, int z) {
return std::sqrt(e_per_u)*HYDROGEN_COEFF[z][0];
}
double EnergyLoss::Hydrogen_dEdx_Med(double e_per_u, int z) {
double x = HYDROGEN_COEFF[z][1]*std::pow(e_per_u, 0.45);
double y = HYDROGEN_COEFF[z][2]/e_per_u * std::log(1.0+HYDROGEN_COEFF[z][3]/e_per_u+HYDROGEN_COEFF[z][4]*e_per_u);
return x*y/(x+y);
}
double EnergyLoss::Hydrogen_dEdx_High(double e_per_u, double energy, int z) {
energy /= 1000.0; //back to MeV for ease of beta calc
double beta_sq = energy * (energy+2.0*MP/MEV2U)/std::pow(energy+MP/MEV2U, 2.0);
double alpha = HYDROGEN_COEFF[z][5]/beta_sq;
double epsilon = HYDROGEN_COEFF[z][6]*beta_sq/(1.0-beta_sq) - beta_sq - HYDROGEN_COEFF[z][7];
for(int i=1; i<5; i++)
epsilon += HYDROGEN_COEFF[z][7+i]*std::pow(std::log(e_per_u), i);
return alpha * std::log(epsilon);
}
//unimplemented
double EnergyLoss::GetRange(double energy) {
std::cerr<<"EnergyLoss::GetRange is not implemented! Returning 0.0"<<std::endl;
return 0.0;
}
}

View File

@ -1,364 +0,0 @@
#include "MaskFile.h"
#include <iostream>
#include <iomanip>
#include <sstream>
/*
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!"<<std::endl;
return false;
}
if(type == FileType::read) {
file.open(name, std::ios::in);
buffer_position = 0;
} else if (type == FileType::write) {
file.open(name, std::ios::out | std::ios::trunc);
} else if (type == FileType::append) {
file.open(name, std::ios::out | std::ios::app);
} else {
std::cerr<<"Invalid FileType at MaskFile::Open()"<<std::endl;
return IsOpen();
}
return IsOpen();
}
void MaskFile::Close() {
//Final flush (if necessary)
if(buffer_position > 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!"<<std::endl;
return;
}
}
buffersize_bytes = buffersize * data_size; //buffersize_bytes = # of events * size of an event
data_buffer.resize(buffersize_bytes);
uint32_t type_value = GetIntFromRxnType(m_rxn_type);
file.write((char*) &nsamples, int_size);
file.write((char*) &type_value, int_size);
}
MaskFileHeader MaskFile::ReadHeader() {
MaskFileHeader header;
std::vector<char> 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 = "<<GetIntFromRxnType(m_rxn_type)<<")! Returning"<<std::endl;
return header;
}
}
buffersize_bytes = buffersize * data_size;//buffersize_bytes = size of a datum * # of events
header.rxn_type = m_rxn_type;
data_buffer.resize(buffersize_bytes);
return header;
}
void MaskFile::WriteData(const std::vector<Nucleus>& data) {
char* data_pointer;
double datum;
int number;
bool flag;
std::size_t j;
for(unsigned int i=0; i<data.size(); i++) {
number = data[i].GetZ();
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
number = data[i].GetA();
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
flag = data[i].IsDetected();
data_pointer = (char*) &flag;
for(j=0; j<bool_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetE();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetKE();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetP();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetTheta();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data[i].GetPhi();
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
}
//Flush the buffer when it is full, and reset the position.
if(buffer_position == buffersize_bytes) {
file.write(data_buffer.data(), data_buffer.size());
buffer_position = 0;
}
}
void MaskFile::WriteData(const MaskFileData& data) {
char* data_pointer;
double datum;
int number;
bool flag;
std::size_t j;
for(unsigned int i=0; i<data.Z.size(); i++) {
number = data.Z[i];
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
number = data.A[i];
data_pointer = (char*) &number;
for(j=0; j<int_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
flag = data.detect_flag[i];
data_pointer = (char*) &flag;
for(j=0; j<bool_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.E[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.KE[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.p[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.theta[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
datum = data.phi[i];
data_pointer = (char*) &datum;
for(j=0; j<double_size; j++) {
data_buffer[buffer_position] = *(data_pointer + j);
buffer_position++;
}
}
//Flush the buffer when it is full, and reset the position.
if(buffer_position == buffersize_bytes) {
file.write(data_buffer.data(), data_buffer.size());
buffer_position = 0;
}
}
/*
Read data from the buffer and submit it to the client side as a MaskFileData struct.
When file reaches the end of the file (no more data to read), an empty MaskFileData with
eof == true is sent out signaling that the file is finished.
Should be used like
Mask::MaskFile input(file, Mask::MaskFile::FileType::read);
Mask::MaskFileHeader header = input.ReadHeader();
Mask::MaskFileData data;
while(true) {
data = input.ReadData();
if(data.eof) break;
Do some stuff...
}
input.Close();
Good luck
*/
MaskFileData MaskFile::ReadData() {
MaskFileData data;
//Fill the buffer when needed, reset the positon, and find the end
if(buffer_position == data_buffer.size() || buffer_position == buffer_end) {
file.read(data_buffer.data(), buffersize_bytes);
buffer_position = 0;
buffer_end = file.gcount();
if(buffer_end == 0 && file.eof()) {
data.eof = true;
return data;
}
}
uint64_t local_end = buffer_position + data_size;
if(local_end > buffer_end) {
std::cerr<<"Attempting to read past end of file at MaskFile::ReadData! Returning empty"<<std::endl;
data.eof = true;
return data;
}
while(buffer_position < local_end) {
data.Z.push_back(*(int*)(&data_buffer[buffer_position]));
buffer_position += int_size;
data.A.push_back(*(int*)(&data_buffer[buffer_position]));
buffer_position += int_size;
data.detect_flag.push_back(*(bool*)(&data_buffer[buffer_position]));
buffer_position += bool_size;
data.E.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.KE.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.p.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.theta.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
data.phi.push_back(*(double*)(&data_buffer[buffer_position]));
buffer_position += double_size;
}
return data;
}
};

View File

@ -1,47 +0,0 @@
/*
Nucleus.cpp
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
*/
#include "Nucleus.h"
#include "MassLookup.h"
namespace Mask {
Nucleus::Nucleus () :
Vec4(), m_z(0), m_a(0), m_gs_mass(0), m_theta_cm(0), m_symbol(""), m_detectFlag(false)
{
}
Nucleus::Nucleus(int Z, int A) :
Vec4(), m_z(Z), m_a(A), m_theta_cm(0), m_detectFlag(false)
{
m_gs_mass = MassLookup::GetInstance().FindMass(Z, A);
m_symbol = MassLookup::GetInstance().FindSymbol(Z, A);
SetVectorCartesian(0,0,0,m_gs_mass); //by defualt a nucleus has mass given by the g.s.
}
Nucleus::Nucleus(int Z, int A, double px, double py, double pz, double E) :
Vec4(px, py, pz, E), m_z(Z), m_a(A)
{
m_gs_mass = MassLookup::GetInstance().FindMass(Z, A);
m_symbol = MassLookup::GetInstance().FindSymbol(Z, A);
}
Nucleus::~Nucleus() {}
bool Nucleus::SetIsotope(int Z, int A) {
if(Z>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;
}
}

View File

@ -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;
}
};

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -1,3 +0,0 @@
__pycache__
!.gitignore

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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()