diff --git a/.gitignore b/.gitignore index 22ae63e..dfd9b8b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,7 @@ Cleopatra/SimTransfer Cleopatra/SimTransfer_single Cleopatra/Cleopatra +EventBuilder + __pycache__ *.DS_Store \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 8ca9a6b..1fce0d0 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,8 @@ "name": "Mac", "includePath": [ "${workspaceFolder}/**", - "/Applications/root_v6.30.06/include/**" + "/Applications/root_v6.30.06/include/**", + "/opt/homebrew/Cellar/root/6.34.08_1/**" ], "defines": [], "compilerPath": "/usr/bin/g++", diff --git a/Armory/ClassReactionConfig.h b/Armory/ClassReactionConfig.h index b7f6ed5..6c302b6 100644 --- a/Armory/ClassReactionConfig.h +++ b/Armory/ClassReactionConfig.h @@ -258,29 +258,29 @@ inline bool ReactionConfig::LoadReactionConfig(TMacro * macro){ if(str[1] == "+" && dondon[2].find('+') != std::string::npos ){ // printf(" only comfim + states\n"); - exList[ID].Add( atoi(dondon[1].c_str()), 1.0, 1.0, atoi(str[3].c_str())); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); } if(str[1] == "-" && dondon[2].find('-') != std::string::npos ){ // printf(" only comfim - states\n"); - exList[ID].Add( atoi(dondon[1].c_str()), 1.0, 1.0, atoi(str[3].c_str())); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); } if( str[1] == "known" ){ // printf(" All comfim state\n"); - exList[ID].Add( atoi(dondon[1].c_str()), 1.0, 1.0, atoi(str[3].c_str())); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); } }else{ if(str[1] == "+all" && dondon[2].find('+') != std::string::npos ){ // printf(" All state : %s\n", str[1].c_str()); - exList[ID].Add( atoi(dondon[1].c_str()), 1.0, 1.0, atoi(str[3].c_str())); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); } if(str[1] == "-all" && dondon[2].find('-') != std::string::npos ){ // printf(" All state : %s\n", str[1].c_str()); - exList[ID].Add( atoi(dondon[1].c_str()), 1.0, 1.0, atoi(str[3].c_str())); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); } if( str[1] == "all" ){ // printf(" All state \n"); - exList[ID].Add( atoi(dondon[1].c_str()), 1.0, 1.0, atoi(str[3].c_str())); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); } } diff --git a/Armory/EventBuilder b/Armory/EventBuilder index 4505ee1..ebcc552 120000 --- a/Armory/EventBuilder +++ b/Armory/EventBuilder @@ -1 +1 @@ -/home/ryan/SOLARIS_DAQ/Aux/EventBuilder \ No newline at end of file +/Users/solaris/SOLARIS_DAQ/Aux/EventBuilder \ No newline at end of file diff --git a/Cleopatra/ClassSimPlotter.h b/Cleopatra/ClassSimPlotter.h index 752c8a0..d209d46 100644 --- a/Cleopatra/ClassSimPlotter.h +++ b/Cleopatra/ClassSimPlotter.h @@ -482,6 +482,7 @@ inline void Plotter::Plot(){ }///===== end of pad loop + cCheck->Update(); } std::vector Plotter::FindRange(TString branch){ diff --git a/Cleopatra/PlotTGraphTObjArray.h b/Cleopatra/PlotTGraphTObjArray.h index d646f5b..ea3b14e 100644 --- a/Cleopatra/PlotTGraphTObjArray.h +++ b/Cleopatra/PlotTGraphTObjArray.h @@ -44,7 +44,7 @@ void PlotTGraphTObjArray(TString rootFileName, bool isSavePNG = false){ const int n = gList->GetLast() + 1 ; - TGraph * gr[n]; + TGraph ** gr = new TGraph *[n]; //Get minimum, maximum Y double maxY = 0; @@ -94,5 +94,8 @@ void PlotTGraphTObjArray(TString rootFileName, bool isSavePNG = false){ gROOT->ProcessLine(".q"); } + + for( int i = 0; i < n; i++) delete gr[i]; + delete [] gr; } diff --git a/Cleopatra/SimChecker.C b/Cleopatra/SimChecker.C index 21ae1c4..32c324f 100644 --- a/Cleopatra/SimChecker.C +++ b/Cleopatra/SimChecker.C @@ -24,6 +24,7 @@ #include "../Cleopatra/ClassIsotope.h" #include "../Cleopatra/ClassTransfer.h" #include "../Cleopatra/ClassSimPlotter.h" +#include plotID StringToPlotID(TString str); @@ -45,14 +46,14 @@ void SimChecker(TString filename = "transfer.root", printf(">>>>> %d reactions found.\n", numReact); - std::string reactionList[numReact]; + std::vector reactionList(numReact); for( int i = 0; i < numReact; i++ ){ std::string haha = ListOfReactions->GetListOfLines()->At(i)->GetName(); std::vector kaka = AnalysisLib::SplitStr(haha, "|"); reactionList[i]= kaka[1]; } - ExcitedEnergies reactEx[numReact]; //2-D array [i][j] = i-reaction, j-Ex + std::vector reactEx(numReact); //2-D array [i][j] = i-reaction, j-Ex TMacro * AllExList = (TMacro *) file->FindObjectAny("AllExList"); TMacro * ExID_ReactID_List = (TMacro *) file->FindObjectAny("ExID_ReactID_List"); @@ -90,8 +91,8 @@ void SimChecker(TString filename = "transfer.root", //^################################################ Find e-range, z-range - double zRange[numReact][2]; - double eMax[numReact]; + std::vector> zRange(numReact, std::vector(2)); + std::vector eMax(numReact); int count = 0; for( int i = 0; i < numReact; i++ ){ @@ -197,13 +198,14 @@ void SimChecker(TString filename = "transfer.root", printf("#####################################################\n"); - Plotter * plotter[numReact]; + Plotter ** plotter = new Plotter*[numReact]; for( int i = 0; i < numReact; i++){ plotter[i] = new Plotter(tree, i, reactionList[i], detGeo, reactEx[i], gate, padPlotID); plotter[i]->SetRanges(zRange[i][0], zRange[i][1], eMax[i], elumMax, thetaCMMax); plotter[i]->SetCanvas(colCount, rowCount, 500, padPlotID); plotter[i]->Plot(); + } return; diff --git a/Cleopatra/SimTransfer.C b/Cleopatra/SimTransfer.C index 62dd3c7..25c70a3 100644 --- a/Cleopatra/SimTransfer.C +++ b/Cleopatra/SimTransfer.C @@ -96,7 +96,7 @@ void Transfer( TMacro dwbaExList_Used; TMacro dwbaReactList_Used; - bool useDWBA[numTransfer]; + bool *useDWBA = new bool[numTransfer]; for( int i = 0; i < numTransfer; i++ ) useDWBA[i] = false; if( distFile->IsOpen() ) { @@ -111,7 +111,7 @@ void Transfer( int numEx = dwbaExList->GetListOfLines()->GetSize() - 1 ; - ExcitedEnergies dwbaExTemp[numTransfer]; + ExcitedEnergies * dwbaExTemp = new ExcitedEnergies[numTransfer]; for( int i = 1; i <= numEx ; i++){ std::string reactionName = dwbaReactList->GetListOfLines()->At(i-1)->GetName(); @@ -145,6 +145,8 @@ void Transfer( } } + delete [] dwbaExTemp; + }else{ printf("------- no DWBA input. Use the ExList from %s\n", basicConfig.c_str()); } @@ -740,6 +742,7 @@ void Transfer( delete [] transfer; delete [] decay; delete [] helios; + delete [] useDWBA; distFile->Close(); delete distFile; diff --git a/armory/AnalysisLib.h b/armory/AnalysisLib.h new file mode 100644 index 0000000..7944804 --- /dev/null +++ b/armory/AnalysisLib.h @@ -0,0 +1,392 @@ +#ifndef ANALYSIS_LIB_H +#define ANALYSIS_LIB_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace AnalysisLib { + +//*######################################### Execute Python Script +std::vector executePythonScript(std::string command) { + std::vector result; + printf("Python : %s \n", command.c_str()); + FILE* pipe = popen(command.c_str(), "r"); + if (!pipe) { + std::cerr << "Failed to open pipe for command: " << command << std::endl; + return result; + } + + constexpr int buffer_size = 256; + char buffer[buffer_size]; + + while (fgets(buffer, buffer_size, pipe) != nullptr) { + result.emplace_back(buffer); + } + + pclose(pipe); + return result; +} + +//*######################################### TRAPEZOID +TGraph * TrapezoidFilter(TGraph * trace, int baseLineEnd = 80, int riseTime = 10, int flatTop = 20, float decayTime = 2000){ + ///Trapezoid filter https://doi.org/10.1016/0168-9002(94)91652-7 + + TGraph * trapezoid = new TGraph(); + trapezoid->Clear(); + + ///find baseline; + double baseline = 0; + for( int i = 0; i < baseLineEnd; i++){ + baseline += trace->Eval(i); + } + baseline = baseline*1./baseLineEnd; + + int length = trace->GetN(); + + double pn = 0.; + double sn = 0.; + for( int i = 0; i < length ; i++){ + + double dlk = trace->Eval(i) - baseline; + if( i - riseTime >= 0 ) dlk -= trace->Eval(i - riseTime) - baseline; + if( i - flatTop - riseTime >= 0 ) dlk -= trace->Eval(i - flatTop - riseTime) - baseline; + if( i - flatTop - 2*riseTime >= 0) dlk += trace->Eval(i - flatTop - 2*riseTime) - baseline; + + if( i == 0 ){ + pn = dlk; + sn = pn + dlk*decayTime; + }else{ + pn = pn + dlk; + sn = sn + pn + dlk*decayTime; + } + trapezoid->SetPoint(i, i, sn / decayTime / riseTime); + } + return trapezoid; +} + +bool isEmptyOrSpaces(const std::string& str) { + if (str.empty()) { + return true; + } + for (char c : str) { + if (!std::isspace(c)) { + return false; + } + } + return true; +} + +std::vector SplitStr(std::string tempLine, std::string splitter, int shift = 0){ + + std::vector output; + + size_t pos; + do{ + pos = tempLine.find(splitter); /// fine splitter + if( pos == 0 ){ ///check if it is splitter again + tempLine = tempLine.substr(pos+1); + continue; + } + + std::string secStr; + if( pos == std::string::npos ){ + secStr = tempLine; + }else{ + secStr = tempLine.substr(0, pos+shift); + tempLine = tempLine.substr(pos+shift); + } + + ///check if secStr is begin with space + while( secStr.substr(0, 1) == " ") secStr = secStr.substr(1); + + ///check if secStr is end with space + while( secStr.back() == ' ') secStr = secStr.substr(0, secStr.size()-1); + + output.push_back(secStr); + ///printf(" |%s---\n", secStr.c_str()); + + }while(pos != std::string::npos ); + + return output; +}; + +//************************************** TCutG + +TObjArray * LoadListOfTCut(TString fileName, TString cutName = "cutList"){ + + if( fileName == "" ) return nullptr; + + TObjArray * cutList = nullptr; + + TFile * fCut = new TFile(fileName); + bool isCutFileOpen = fCut->IsOpen(); + if(!isCutFileOpen) { + printf( "Failed to open rdt-cutfile 1 : %s\n" , fileName.Data()); + }else{ + cutList = (TObjArray *) fCut->FindObjectAny(cutName); + + if( cutList ){ + int numCut = cutList->GetEntries(); + printf("=========== found %d cutG in %s \n", numCut, fCut->GetName()); + + for(int i = 0; i < numCut ; i++){ + printf("cut name : %s , VarX: %s, VarY: %s, numPoints: %d \n", + cutList->At(i)->GetName(), + ((TCutG*)cutList->At(i))->GetVarX(), + ((TCutG*)cutList->At(i))->GetVarY(), + ((TCutG*)cutList->At(i))->GetN() + ); + } + } + } + + return cutList; +} + +TCutG * LoadSingleTCut( TString fileName, TString cutName = "cutEZ"){ + + if( fileName == "" ) return nullptr; + TCutG * cut = nullptr; + + TFile * fCut = new TFile(fileName); + bool isCutFileOpen = fCut->IsOpen(); + if( !isCutFileOpen) { + printf( "Failed to open E-Z cutfile : %s\n" , fileName.Data()); + }else{ + cut = (TCutG *) fCut->FindObjectAny(cutName); + if( cut != NULL ) { + printf("Found EZ cut| name : %s, VarX: %s, VarY: %s, numPoints: %d \n", + cut->GetName(), + cut->GetVarX(), + cut->GetVarY(), + cut->GetN() + ); + } + } + + return cut; +} + + +//************************************** Others +std::vector> combination(std::vector arr, int r){ + + std::vector> output; + + int n = arr.size(); + std::vector v(n); + std::fill(v.begin(), v.begin()+r, 1); + do { + //for( int i = 0; i < n; i++) { printf("%d ", v[i]); }; printf("\n"); + + std::vector temp; + for (int i = 0; i < n; ++i) { + if (v[i]) { + //printf("%.1f, ", arr[i]); + temp.push_back(arr[i]); + } + } + //printf("\n"); + + output.push_back(temp); + + } while (std::prev_permutation(v.begin(), v.end())); + + return output; +} + +double* sumMeanVar(std::vector data){ + + int n = data.size(); + double sum = 0; + for( int k = 0; k < n; k++) sum += data[k]; + double mean = sum/n; + double var = 0; + for( int k = 0; k < n; k++) var += pow(data[k] - mean,2); + + static double output[3]; + output[0] = sum; + output[1] = mean; + output[2] = var; + + return output; +} + +double* fitSlopeIntercept(std::vector dataX, std::vector dataY){ + + double * smvY = sumMeanVar(dataY); + double sumY = smvY[0]; + double meanY = smvY[1]; + + double * smvX = sumMeanVar(dataX); + double sumX = smvX[0]; + double meanX = smvX[1]; + double varX = smvX[2]; + + int n = dataX.size(); + double sumXY = 0; + for( int j = 0; j < n; j++) sumXY += dataX[j] * dataY[j]; + + double slope = ( sumXY - sumX * sumY/n ) / varX; + double intercept = meanY - slope * meanX; + + static double output[2]; + output[0] = slope; + output[1] = intercept; + + return output; + +} + +std::vector> FindMatchingPair(std::vector enX, std::vector enY){ + + //output[0] = fitEnergy; + //output[1] = refEnergy; + + int nX = enX.size(); + int nY = enY.size(); + + std::vector fitEnergy; + std::vector refEnergy; + + if( nX > nY ){ + + std::vector> output = combination(enX, nY); + + double * smvY = sumMeanVar(enY); + double sumY = smvY[0]; + double meanY = smvY[1]; + double varY = smvY[2]; + + double optRSquared = 0; + double absRSqMinusOne = 1; + int maxID = 0; + + for( int k = 0; k < (int) output.size(); k++){ + + double * smvX = sumMeanVar(output[k]); + double sumX = smvX[0]; + double meanX = smvX[1]; + double varX = smvX[2]; + + double sumXY = 0; + for( int j = 0; j < nY; j++) sumXY += output[k][j] * enY[j]; + + double rSq = abs(sumXY - sumX*sumY/nY)/sqrt(varX*varY); + + //for( int j = 0; j < nY ; j++){ printf("%.1f, ", output[k][j]); }; printf("| %.10f\n", rSq); + + if( abs(rSq-1) < absRSqMinusOne ) { + absRSqMinusOne = abs(rSq-1); + optRSquared = rSq; + maxID = k; + } + } + + fitEnergy = output[maxID]; + refEnergy = enY; + + printf(" R^2 : %.20f\n", optRSquared); + + //calculation fitting coefficient + //double * si = fitSlopeIntercept(fitEnergy, refEnergy); + //printf( " y = %.4f x + %.4f\n", si[0], si[1]); + + }else if( nX < nY ){ + + std::vector> output = combination(enY, nX); + + + double * smvX = sumMeanVar(enX); + double sumX = smvX[0]; + double meanX = smvX[1]; + double varX = smvX[2]; + + double optRSquared = 0; + double absRSqMinusOne = 1; + int maxID = 0; + + for( int k = 0; k < (int) output.size(); k++){ + + double * smvY = sumMeanVar(output[k]); + double sumY = smvY[0]; + double meanY = smvY[1]; + double varY = smvY[2]; + + double sumXY = 0; + for( int j = 0; j < nX; j++) sumXY += output[k][j] * enX[j]; + + double rSq = abs(sumXY - sumX*sumY/nX)/sqrt(varX*varY); + + //for( int j = 0; j < nX ; j++){ printf("%.1f, ", output[k][j]); }; printf("| %.10f\n", rSq); + + if( abs(rSq-1) < absRSqMinusOne ) { + absRSqMinusOne = abs(rSq-1); + optRSquared = rSq; + maxID = k; + } + } + + fitEnergy = enX; + refEnergy = output[maxID]; + printf(" R^2 : %.20f\n", optRSquared); + + }else{ + fitEnergy = enX; + refEnergy = enY; + + //if nX == nY, ther could be cases that only partial enX and enY are matched. + + } + + printf("fitEnergy = ");for( int k = 0; k < (int) fitEnergy.size() ; k++){ printf("%7.2f, ", fitEnergy[k]); }; printf("\n"); + printf("refEnergy = ");for( int k = 0; k < (int) refEnergy.size() ; k++){ printf("%7.2f, ", refEnergy[k]); }; printf("\n"); + + std::vector> haha; + haha.push_back(fitEnergy); + haha.push_back(refEnergy); + + return haha; + +} + +std::string create_range_string(const std::vector& nums) { + std::string range_str; + int lastNum = nums[0]; + int rangeStart = lastNum; + for (int i = 1; i < (int) nums.size(); i++) { + if (nums[i] == lastNum + 1) { + lastNum = nums[i]; + } else { + if (rangeStart == lastNum) { + range_str += std::to_string(rangeStart) + "_"; + } else { + range_str += std::to_string(rangeStart) + "-" + std::to_string(lastNum) + "_"; + } + rangeStart = lastNum = nums[i]; + } + } + // Add the last range + if (rangeStart == lastNum) { + range_str += std::to_string(rangeStart); + } else { + range_str += std::to_string(rangeStart) + "-" + std::to_string(lastNum); + } + return range_str; +} + + +} + +#endif \ No newline at end of file diff --git a/armory/AutoFit.C b/armory/AutoFit.C new file mode 100644 index 0000000..4b94781 --- /dev/null +++ b/armory/AutoFit.C @@ -0,0 +1,2861 @@ +/*************************************************** + * This is a root macro for Auto fitting + * + * Created by Tsz Leung (Ryan) TANG, around 2019. + * updated 01-04-2022 + * + * contact goluckyryan@gmail.com + ***************************************************/ + +#ifndef AutoFit_C +#define AutoFit_C + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace AutoFit{ + +//Global fit paramaters +std::vector BestFitMean; +std::vector BestFitCount; +std::vector BestFitSigma; + +TString recentFitMethod; + +void ShowFitMethod(){ + printf("----------------------- Method of Fitting ---------------\n"); + printf("---------------------------------------------------------\n"); + printf(" fitAuto() - estimate BG, find peak, and fit n-Gauss \n"); + printf(" fitGaussPol() - fit 1 Gauss + pol-n BG\n"); + printf(" fit2GaussP1() - fit 2 Gauss + pol-1 BG \n"); + printf(" fitGF3Pol() - fit GF3 + pol-n BG \n"); + //printf(" fitNGF3() - fit n-GF3, estimated BG \n"); + printf(" fitNGauss() - fit n-Gauss, estimated BG, need input\n"); + printf(" fitNGaussSub() - fit estimated BG with Pol, subtract, fit n-Guass\n"); + printf(" fitNGaussPol() - fit n-Gauss + pol-n BG \n"); + printf(" fitNGaussPolSub() - subtract Pol-n BG, fit n-Gauss \n"); + printf("\n"); + printf("------- Mouse click Fit : \n"); + printf(" clickFitNGaussPol() - fit n-Gauss + pol-n BG \n"); + printf(" clickFitNGaussPolSub() - Fit Pol-n BG, subtract, fit n-Gauss\n"); + printf("\n"); + printf("------- Utility : \n"); + printf(" SaveFitPara() - Save the inital/Best fit parameters.\n"); + printf(" ShowFitMerhod() - Show this menual.\n"); + printf("---------------------------------------------------------\n"); +} + +void AutoFit(){ + ShowFitMethod(); +} + +std::vector SplitStrAF(std::string tempLine, std::string splitter, int shift = 0){ + + std::vector output; + + size_t pos; + do{ + pos = tempLine.find(splitter); // fine splitter + if( pos == 0 ){ //check if it is splitter again + tempLine = tempLine.substr(pos+1); + continue; + } + + std::string secStr; + if( pos == std::string::npos ){ + secStr = tempLine; + }else{ + secStr = tempLine.substr(0, pos+shift); + tempLine = tempLine.substr(pos+shift); + } + + //check if secStr is begin with space + if( secStr.substr(0, 1) == " "){ + secStr = secStr.substr(1); + } + + output.push_back(secStr); + //printf(" |%s---\n", secStr.c_str()); + + }while(pos != std::string::npos ); + + return output; +} + +TColor RGBWheel(double ang){ + + ang = ang * TMath::DegToRad(); + + double r = std::max(0., (1+2*cos(ang))/3.); + double g = std::max(0., (1 - cos(ang) + sqrt(3)* sin(ang))/3.); + double b = std::max(0., (1 - cos(ang) - sqrt(3)* sin(ang))/3.); + + TColor col(r,g,b); + + return col; + +} + +int nPeaks = 16; +Double_t nGauss(Double_t *x, Double_t *par) { + Double_t result = 0; + for (Int_t p=0;pGetNpar(); + int count = totPar/numParPerPeak; + printf("ID "); + for( int i = 0; i < numParPerPeak; i++){ + printf("par%d ", i); + } + printf("\n"); + + for( int i = 0; i < count ; i++){ + printf("%3d ", i); + for( int j = 0; j < numParPerPeak; j++){ + int parID = numParPerPeak * i + j; + printf("%.3f(%.3f) ", fit->GetParameter(parID), fit->GetParError(parID)); + } + printf("\n"); + } +} + +void GoodnessofFit(TH1F * hist, TF1 * fit){ + + int nBin = hist->GetNbinsX(); + int effBin = 0; + double mean = 0; + double ysq = 0; + double SSR = 0; + double chisq = 0; //with estimated error be sqrt(y) + double Xsq = 0; // for Pearson's chi-sq test + for( int i = 1; i <= nBin; i++){ + + double e = hist->GetBinError(i); + if( e > 0 ) { + effBin ++; + double y = hist->GetBinContent(i); + double x = hist->GetBinCenter(i); + double ybar = fit->Eval(x); + ysq += y*y; + mean += y; + SSR += (y - ybar)*(y-ybar); + chisq += (y - ybar)*(y-ybar)/e/e; + + + if( ybar > e ) { + Xsq += (y - ybar)*(y-ybar)/ybar; + }else{ + Xsq += (y - ybar)*(y-ybar)/e; + } + //printf(" %d | x : %f, y : %f, ybar : %f , X-sq : %f\n", i, x, y, ybar, Xsq); + } + } + mean = mean / nBin; + double SSTotal = ysq + mean*mean; + + int npar = fit->GetNpar(); + int ndf = effBin - npar; + printf("#################################################\n"); + printf("## Goodness of Fit. ##\n"); + printf("#################################################\n"); + printf(" eff. Bin(%d) - numPar(%d) = ndf = %d \n", effBin, npar, ndf); + + printf("============== Regression analysis\n"); + printf("----------------- R-sq \n"); + printf(" SSTotal = %f \n", SSTotal); + printf(" SSR = %f \n", SSR); + printf(" MSR = %f <-- is it similar to sample variance?\n", SSR/ndf); + double Rsq = 1 - SSR/SSTotal; + printf(" R-sq = %f \n", Rsq ); + + printf("----------------- Chi-sq \n"); + printf(" Chi-sq = %f \n", chisq); + printf(" rd. Chi-sq = %f \n", chisq/ndf); + printf("ROOT Chi-Sq = %f , NDF = %d \n", fit->GetChisquare(), fit->GetNDF()); + //================ chi-sq test + printf("============== Hypothesis testing\n"); + printf(" Null Hypothesis : the fitting model is truth. \n"); + printf(" * p-value = prob. that Null Hypo. is truth. \n"); + printf(" * the Pearson's test in here only for background free data \n"); + printf(" Pearson's X-sq = %.2f \n", Xsq); + double p = 1 - TMath::Prob(Xsq, ndf); + printf(" Pearson's p-value = %.2f %s 0.05 | %s\n", p, p < 0.05 ? "<": ">", p < 0.05 ? "reject" : "cannot reject"); + double pchi = 1 - TMath::Prob(chisq, ndf); + printf(" Chi-sq p-value = %.2f %s 0.05 | %s\n", pchi, pchi < 0.05 ? "<": ">", pchi < 0.05 ? "reject" : "cannot reject"); + double pRoot = 1- fit->GetProb(); + printf("ROOT Chi-sq p-value = %.2f %s 0.05 | %s\n", pRoot, pRoot < 0.05 ? "<": ">", pRoot < 0.05 ? "reject" : "cannot reject"); + printf("################################################\n"); +} + +std::vector energy, height, sigma, lowE, highE ; +std::vector energyFlag, sigmaFlag; + +bool loadFitParameters(TString fitParaFile){ + + energy.clear(); energyFlag.clear(); + sigma.clear(); sigmaFlag.clear(); + + lowE.clear(); highE.clear(); + + height.clear(); + + bool paraRead = false; + + printf("====================================================================== \n"); + printf("----- loading fit parameters from : %s", fitParaFile.Data()); + std::ifstream file; + file.open(fitParaFile.Data()); + + if( !file){ + printf("\ncannot read file : %s \n", fitParaFile.Data()); + return 0; + } + + while( file.good()) { + std::string tempLine; + getline(file, tempLine); + + if( tempLine.substr(0, 1) == "#" ) continue; + if( tempLine.substr(0, 2) == "//" ) continue; + if( tempLine.size() < 5 ) continue; + + ///printf("%s\n", tempLine.c_str()); + + std::vector temp = SplitStrAF(tempLine, " "); + + if( temp.size() < 7 ) continue; + + energy.push_back( atof(temp[0].c_str())); + lowE.push_back( atof(temp[1].c_str())); + highE.push_back( atof(temp[2].c_str())); + energyFlag.push_back(atoi(temp[3].c_str())); + sigma.push_back( atof(temp[4].c_str())); + sigmaFlag.push_back( atoi(temp[5].c_str())); + height.push_back( atof(temp[6].c_str())); + + } + + printf("... done.\n"); + + int n = energy.size(); + TString limStr = "(fixed)"; + printf("%2s| %34s | %10s \n", "ID", "Peak [MeV]", "Sigma [MeV]"); + for( int j = 0; j < n; j ++){ + if( energyFlag[j] == 0 ) limStr.Form("(limited, %6.3f - %6.3f)", lowE[j], highE[j]); + printf("%2d| %7.4f %-26s | %7.4f (%5s) \n", j, energy[j], limStr.Data(), sigma[j], sigmaFlag[j] == 1 ? "fixed" : "free"); + } + + paraRead = true; + + printf("====================================================================== \n"); + + return paraRead; + +} + +TCanvas * NewCanvas(TString name, TString title, int divX, int divY, int padSizeX, int padSizeY){ + TCanvas * output = NULL; + if( gROOT->FindObjectAny(name) == NULL ){ + output = new TCanvas(name, title, divX * padSizeX, divY * padSizeY); + }else{ + output = (TCanvas *) gROOT->FindObjectAny(name) ; + output->Clear(); + } + output->Divide(divX, divY); + return output; +} + +void ScaleAndDrawHist(TH1F * hist, double xMin, double xMax){ + + if ( xMin != xMax ) hist->GetXaxis()->SetRangeUser(xMin, xMax); + int maxBin = hist->GetMaximumBin(); + double ymax = hist->GetBinContent(maxBin); + hist->GetYaxis()->SetRangeUser(0, 1.1 * ymax); + hist->Draw(); + +} + +void PlotResidual(TH1F * hist, TF1 * fit){ + + TH1F * hRes = (TH1F*) hist->Clone(); + hRes->GetListOfFunctions()->Clear(); + hRes->SetTitle("Residual"); + hRes->SetName("hRes"); + hRes->SetYTitle("Hist - fit"); + hRes->Sumw2(0); + hRes->Sumw2(1); + hRes->Add(fit, -1); + hRes->Draw(); + +} + + +//######################################## +//### Fit a Gauss + Pol-n +//######################################## +void fitGaussPol(TH1F * hist, double mean, double sigmaMax, int degPol, double xMin, double xMax, TString optStat = ""){ + + printf("=========================================================\n"); + printf("================ fit 1-Gauss + Pol-%d BG ================\n", degPol); + printf(" * mean Range +- 5 sigmaMax \n"); + printf(" * inital parameters of the polynomial is random/pow(10, i) \n"); + printf("==========================================================\n"); + + recentFitMethod = "fitGaussPol"; + + gStyle->SetOptStat(optStat); + TCanvas * cFitGaussPol = NewCanvas("cFitGaussPol", Form("fit Gauss & Pol-%d | fitGaussPol", degPol), 1, 2, 800, 350); + cFitGaussPol->cd(1); + + ScaleAndDrawHist(hist, xMin, xMax); + + const int nPar = 3 + degPol + 1; + + TString funcExp = "[0] * TMath::Gaus(x, [1], [2], 1)"; + for( int i = 0; i < degPol+1 ; i++){ + funcExp += Form(" + [%d]*TMath::Power(x,%d)", i+3 , i); + } + TF1 * fit = new TF1("fit", funcExp.Data(), xMin, xMax); + + double * para = new double[nPar]; + para[0] = 100 * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[1] = mean; + para[2] = sigmaMax/2.; + for( int i = 0 ; i < degPol+1; i++){ + para[3 + i ] = gRandom->Rndm()/TMath::Power(10, i); + } + + fit->SetLineWidth(2); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + fit->SetParLimits(0, 0, 1e9); + fit->SetParLimits(1, mean - 5*sigmaMax, mean + 5 * sigmaMax); + fit->SetParLimits(2, 0, sigmaMax); + + hist->Fit("fit", "Rq"); + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + double bw = hist->GetBinWidth(1); + + printf("histogram name : %s \n====== Gaussian:\ncount: %8.0f(%3.0f)\nmean : %8.4f(%8.4f)\nsigma: %8.4f(%8.4f) \n", + hist->GetName(), + paraA[0] / bw, paraE[0] /bw, + paraA[1], paraE[1], + paraA[2], paraE[2]); + + printf("------- the polnomail BG:\n"); + for(int i = 0 ; i < degPol+1; i++){ + printf("%2d | %8.4f(%8.4f) \n", i, paraA[3+i], paraE[3+i]); + } + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.DrawLatex(0.12, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + text.DrawLatex(0.12, 0.75,Form("count: %4.0f(%3.0f)", paraA[0] / bw, paraE[0] /bw)); + text.DrawLatex(0.12, 0.70,Form("E_{x}: %6.3f(%5.3f) MeV", paraA[1], paraE[1])); + text.DrawLatex(0.12, 0.65,Form("#sigma: %3.0f(%3.0f) keV", paraA[2] * 1000., paraE[2] * 1000.)); + + for( int i = 0; i < degPol + 1; i++){ + text.DrawLatex(0.60, 0.85 - 0.05*i ,Form("%3s: %8.3f(%8.3f)", Form("p%d", i), paraA[3+i], paraE[3+i])); + } + + TString expression = "[0] "; + for( int j = 1; j < degPol + 1; j++){ + expression += Form(" + [%d]*TMath::Power(x, %d)", j, j); + } + TF1 * g0 = new TF1("g0", expression.Data(), xMin, xMax); + for( int j = 0; j < degPol + 1 ; j++){ + g0->SetParameter(j, paraA[3+j]); + } + g0->SetLineColor(4); + g0->Draw("same"); + + TF1* f0 = new TF1("f0", "[0] * TMath::Gaus(x, [1], [2], 1)", xMin, xMax); + f0->SetParameter(0, paraA[0]); + f0->SetParameter(1, paraA[1]); + f0->SetParameter(2, paraA[2]); + f0->SetLineColor(2); + f0->SetNpx(1000); + f0->Draw("same"); + +// GoodnessofFit(hist, fit); + + cFitGaussPol->cd(2); + PlotResidual(hist, fit); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + BestFitCount.push_back(paraA[0]); + BestFitMean.push_back(paraA[1]); + BestFitSigma.push_back(paraA[2]); + +} + +//######################################## +//#### fit 2 gauss + pol-1 // not updated +//######################################## +std::vector fit2GaussP1(TH1F * hist, double mean1, double sigma1, + double mean2, double sigma2, + double xMin, double xMax, TString optStat = "", bool newCanvas = false){ + + + printf("=========================================================\n"); + printf("================ fit 2-Gauss + Pol-1 BG ================\n" ); + printf(" NOT updated. It works, but the code is old \n"); + printf("==========================================================\n"); + + recentFitMethod = "fit2GaussP1"; + + std::vector output; + output.clear(); + + gStyle->SetOptStat(optStat); + TCanvas * cFit2GaussP1 = NewCanvas("cFit2GaussP1", "fit Gauss & P1 | fit2GaussP1", 1, 1, 800, 350); + cFit2GaussP1->cd(1); + + ScaleAndDrawHist(hist, xMin, xMax); + + TF1 * fit = new TF1("fit", "[0] * TMath::Gaus(x, [1], [2], 1) + [3] * TMath::Gaus(x, [4], [5], 1) + [6] + [7]*x", xMin, xMax); + + double * para = new double[8]; + para[0] = 20 * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[1] = mean1; + para[2] = sigma1; + para[3] = 100 * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[4] = mean2; + para[5] = sigma2; + para[6] = 1; + para[7] = 0; + + fit->SetLineWidth(2); + fit->SetLineColor(2); + fit->SetNpx(1000); + fit->SetParameters(para); + + hist->Fit("fit", "Rq"); + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + double bw = hist->GetBinWidth(1); + + printf("%7s ====== count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + hist->GetName(), + paraA[0] / bw, paraE[0] /bw, + paraA[1], paraE[1], + paraA[2], paraE[2]); + printf("%7s ====== count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + "", + paraA[3] / bw, paraE[3] /bw, + paraA[4], paraE[4], + paraA[5], paraE[5]); + + output.push_back( paraA[0]/bw); + output.push_back( paraE[0]/bw); + output.push_back( paraA[1]); + output.push_back( paraE[1]); + output.push_back( paraA[2]); + output.push_back( paraE[2]); + + output.push_back( paraA[3]/bw); + output.push_back( paraE[3]/bw); + output.push_back( paraA[4]); + output.push_back( paraE[4]); + output.push_back( paraA[5]); + output.push_back( paraE[5]); + + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + text.DrawLatex(0.15, 0.75,Form("count: %4.0f(%3.0f), E_{x}: %6.3f(%5.3f) MeV, #sigma: %3.0f(%3.0f) keV ", + paraA[0] / bw, paraE[0] /bw, + paraA[1], paraE[1], + paraA[2] * 1000., paraE[2] * 1000.)); + text.DrawLatex(0.15, 0.7, Form("count: %4.0f(%3.0f), E_{x}: %6.3f(%5.3f) MeV, #sigma: %3.0f(%3.0f) keV ", + paraA[3] / bw, paraE[3] /bw, + paraA[4], paraE[4], + paraA[5] * 1000., paraE[5] * 1000.)); + + text.DrawLatex(0.15, 0.6, Form("Line : %6.3f(%5.3f) + %6.3f(%5.3f)x ", + paraA[6], paraE[6], + paraA[7], paraE[7])); + + GoodnessofFit(hist, fit); + + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < 2; i++){ + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } + + return output; +} + + +//######################################## +//#### fit for gamma + pol-n BG +//######################################## +void fitGF3Pol(TH1F * hist, double mean, double sigmaMax, double ratio, double beta, double step, int degPol, double xMin, double xMax, TString optStat = ""){ + + printf("=========================================================\n"); + printf("================ fit GF1 + Pol-%d BG ================\n", degPol); + printf(" * mean Range = xMin, xMax \n"); + printf(" * inital parameters of the polynomial is random/pow(10, i) \n"); + printf("==========================================================\n"); + + recentFitMethod = "fitGF3Pol"; + + gStyle->SetOptStat(optStat); + + gStyle->SetOptStat(optStat); + TCanvas * cFitGF3Pol = NewCanvas("cFitGF3Pol", Form("fit GF3 + pol-%d | fitGF3Pol", degPol), 1, 2, 800, 350); + cFitGF3Pol->cd(1); + + ScaleAndDrawHist(hist, xMin, xMax); + + nPeaks = 1; + nPols = degPol; + int nPar = 6*nPeaks + degPol + 1; + + TF1 * fit = new TF1("fit", nGF3Pol, xMin, xMax, nPar); + + fit->Print(); + + double * para = new double[nPar]; + para[0] = hist->GetMaximum() *4; + para[1] = mean; + para[2] = sigmaMax/2.; + para[3] = ratio ; + para[4] = beta ; + para[5] = step ; + for( int i = 0 ; i < degPol + 1; i++){ + para[6+i] = gRandom->Rndm()/TMath::Power(10, i); + } + + fit->SetLineWidth(2); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + fit->SetParLimits(0, 0, 1e9); + fit->SetParLimits(1, xMin, xMax); + fit->SetParLimits(2, 0.00000001, sigmaMax); + fit->SetParLimits(3, 0, 0.5); + fit->SetParLimits(4, 1, 400); + fit->SetParLimits(5, 0, 0.5); + + hist->Fit("fit", "Rq"); + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + double chisquare = fit->GetChisquare(); + int ndf = fit->GetNDF(); + double bw = hist->GetBinWidth(1); + + printf("histogram : %s \n", hist->GetName()); + printf("========= The Gaussian \n"); + printf("count: %8.0f(%3.0f)\n", paraA[0] / bw, paraE[0] /bw); + printf("mean : %8.4f(%8.4f)\n", paraA[1], paraE[1]); + printf("sigma: %8.4f(%8.4f)\n", paraA[2], paraE[2]); + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + text.SetTextColor(1); + + text.DrawLatex(0.12, 0.65, Form("count : %5.0f(%5.0f)", paraA[0]/bw, paraE[0]/bw)); + text.DrawLatex(0.12, 0.60, Form(" mean : %5.3f(%5.3f) keV", paraA[1], paraE[1])); + text.DrawLatex(0.12, 0.55, Form("sigma : %5.3f(%5.3f) keV", paraA[2], paraE[2])); + text.DrawLatex(0.12, 0.50, Form(" FWHM : %5.3f(%5.3f) keV", paraA[2] *2.355, paraE[2]*2.355)); + + text.DrawLatex(0.12, 0.40, Form("#chi^2/ndf : %5.3f", chisquare/ndf)); + + //GoodnessofFit(hist, fit); + + /// 0 1 2 3 4 5 + std::string label[8] = {"Area", "mean", "sigma", "ratio", "beta", "step"}; + printf("---------- The detail\n"); + for(int i = 0 ; i < 6 ; i++){ + printf("%d | %8s | %f (%f) \n", i, label[i].c_str(), paraA[i], paraE[i]); + text.DrawLatex(0.65, 0.85-0.05*i, Form("%6s: %5.3f(%5.3f)", label[i].c_str(), paraA[i], paraE[i])); + } + for(int i = 6 ; i < nPar; i++){ + printf("%d | %8s | %f (%f) \n", i, Form("p%d", i-6), paraA[i], paraE[i]); + text.DrawLatex(0.65, 0.85-0.05*i, Form("%6s: %5.3f (%5.3f) \n", Form("p%d", i-6), paraA[i], paraE[i])); + } + + /// norm * (1-ratio)* TMath::Gaus(x[0], mean, sigma, 1) + TF1 * g0 = new TF1("g0", "[0] * (1.0-[3]) * TMath::Gaus(x, [1], [2], 1)", xMin, xMax); + g0->SetParameter(0, paraA[0]); + g0->SetParameter(1, paraA[1]); + g0->SetParameter(2, paraA[2]); + g0->SetParameter(3, paraA[3]); + g0->SetNpx(1000); + g0->SetLineColor(kRed); + + /// norm * ratio * exp( sigma * sigma/2/beta/beta)* exp((x[0]-mean)/beta) * TMath::Erfc( (x[0]-mean)/(sigma * sqrt(2)) + sigma/beta/sqrt(2)) ; + TF1 * g1 = new TF1("g1", "[0] * [3] * exp( [2] * [2]/2/[4]/[4]) / (2* [4])* exp((x-[1])/[4]) * TMath::Erfc( (x-[1])/([2] * sqrt(2)) + [2]/[4]/sqrt(2)) ", xMin, xMax); + g1->SetParameter(0, paraA[0]); + g1->SetParameter(1, paraA[1]); + g1->SetParameter(2, paraA[2]); + g1->SetParameter(3, paraA[3]); + g1->SetParameter(4, paraA[4]); + g1->SetNpx(1000); + g1->SetLineColor(kGreen +3); + + /// norm * step * TMath::Erfc( (x[0]-mean)/(sigma * sqrt(2)) ); + TF1 * g2 = new TF1("g2", "[0] * [3] * TMath::Erfc( (x-[1])/([2] * sqrt(2)) );", xMin, xMax); + g2->SetParameter(0, paraA[0]); + g2->SetParameter(1, paraA[1]); + g2->SetParameter(2, paraA[2]); + g2->SetParameter(3, paraA[5]); + g2->SetNpx(1000); + g2->SetLineColor(kViolet); + + + TString expression = "[0] "; + for( int j = 1; j < degPol + 1; j++){ + expression += Form(" + [%d]*TMath::Power(x, %d)", j, j); + } + TF1 * g3 = new TF1("g3", expression.Data(), xMin, xMax); + for( int j = 0; j < degPol + 1 ; j++){ + g3->SetParameter(j, paraA[6+j]); + } + g3->SetLineColor(kBlue); + g3->Draw("same"); + + + g0->Draw("same"); + g1->Draw("same"); + g2->Draw("same"); + g3->Draw("same"); + + cFitGF3Pol->cd(2); + PlotResidual(hist, fit); + +} + +//############################################## +//##### Auto Fit n-Gauss with estimated BG +//############################################## +std::vector fitAuto(TH1F * hist, int bgEst = 10, + double peakThreshold = 0.05, + double sigmaMax = 0, + int peakDensity = 4, + TString optStat = ""){ + + printf("================================================================\n"); + printf("========== Auto Fit n-Gauss with estimated BG ==================\n"); + printf(" * bgEst = parameter of BG estimation, larger BG, more linear \n"); + printf(" * peakThreshold = precentage of the highest peak that will count \n"); + printf(" * sigmaMax = maximum sigma, if -1, program try to find the sigma \n"); + printf(" * peakDensity = peak will closer when the number is larger "); + printf(" \n"); + printf(" after peaks found, the i-th peaks will be limited by the mid-point\n"); + printf(" by the (i-1)-th peak and the i-th peak, and the mid-point of the\n"); + printf(" i-th peak and (i+1)-th peak \n"); + printf(" i.e. [peak(i-1)+peak(i)]/2 < limit of peak(i) < [peak(i)+peak(i+1)]/2 \n"); + printf("================================================================\n"); + + recentFitMethod = "fitAuto"; + + gStyle->SetOptStat(optStat); + TCanvas *cFitAuto = NewCanvas("cFitAuto","Auto Fitting | fitAuto", 1, 4, 800, 300); + cFitAuto->cd(1); + + ScaleAndDrawHist(hist, 0, 0); + + TH1F * specS = (TH1F*) hist->Clone(); + double xMin = hist->GetXaxis()->GetXmin(); + double xMax = hist->GetXaxis()->GetXmax(); + int xBin = hist->GetXaxis()->GetNbins(); + + TString titleH; + titleH.Form("fitted spectrum (BG=%d); Ex [MeV]; Count / %4.0f keV", bgEst, (xMax-xMin)*1000./xBin ); + specS->SetTitle(titleH); + specS->SetName("specS"); + ///specS->GetXaxis()->SetTitleSize(0.06); + ///specS->GetYaxis()->SetTitleSize(0.06); + ///specS->GetXaxis()->SetTitleOffset(0.7); + ///specS->GetYaxis()->SetTitleOffset(0.6); + + //=================== find peak and fit + gStyle->SetOptFit(0); + TSpectrum * peak = new TSpectrum(50); + nPeaks = peak->Search(hist, peakDensity, "", peakThreshold); + + if( bgEst > 0 ) { + printf("============= estimating background...\n"); + TH1 * h1 = peak->Background(hist, bgEst); + h1->Draw("same"); + printf("============= substracting the linear background...\n"); + specS->Sumw2(); + specS->Add(h1, -1.); + } + + cFitAuto->cd(2)->SetGrid(); + cFitAuto->cd(2); + specS->Draw("hist"); + + //========== Fitting + printf("============= Fitting....."); + printf(" found %d peaks \n", nPeaks); + + double * xpos = peak->GetPositionX(); + double * ypos = peak->GetPositionY(); + + int * inX = new int[nPeaks]; + TMath::Sort(nPeaks, xpos, inX, 0 ); + std::vector energy, height; + for( int j = 0; j < nPeaks; j++){ + energy.push_back(xpos[inX[j]]); + height.push_back(ypos[inX[j]]); + } + for( int j = 0; j < nPeaks; j++){ + printf(" energy : %f , %f \n", energy[j], height[j]); + } + + + if( sigmaMax == 0 ){ + printf("------------- Estimate sigma for each peak \n"); + sigma.clear(); + int binMin = hist->FindBin(xMin); + int binMax = hist->FindBin(xMax); + for( int i = 0; i < nPeaks ; i++){ + int b0 = hist->FindBin(energy[i]); + double sMin = (xMax-xMin)/5., sMax = (xMax-xMin)/5.; + //---- backward search, stop when + for( int b = b0-1 ; b > binMin ; b-- ){ + double y = hist->GetBinContent(b); + double x = hist->GetBinCenter(b); + if( y < (height[i])/2. ) { + sMin = energy[i] - hist->GetBinCenter(b); + break; + } + } + //---- forward search, stop when + for( int b = b0+1 ; b < binMax ; b++ ){ + double y = hist->GetBinContent(b); + double x = hist->GetBinCenter(b); + if( y < (height[i])/2. ) { + sMax = hist->GetBinCenter(b) - energy[i]; + break; + } + } + + double temp = TMath::Min(sMin, sMax); + /// When there are multiple peaks closely packed : + if( i > 0 && temp > 2.5 * sigma.back() ) temp = sigma.back(); + sigma.push_back(temp); + + printf("%2d | x : %8.2f | sigma(est) %f \n", i, energy[i], sigma[i]); + } + }else if( sigmaMax < 0 ){ + printf("========== use user input sigma : %f (fixed)\n", abs(sigmaMax)); + sigma.clear(); + for( int i = 0; i < nPeaks ; i++) sigma.push_back(abs(sigmaMax)); + }else if( sigmaMax > 0 ){ + printf("========== use user input sigma : %f/2. \n", sigmaMax/2.); + sigma.clear(); + for( int i = 0; i < nPeaks ; i++) sigma.push_back(sigmaMax/2.); + } + + + + int numParPerPeak = 3; + const int n = numParPerPeak * nPeaks; + double * para = new double[n]; + for(int i = 0; i < nPeaks ; i++){ + para[numParPerPeak*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[numParPerPeak*i+1] = energy[i]; + if( sigmaMax == 0 ){ + para[numParPerPeak*i+2] = sigma[i]; + }else if(sigmaMax < 0 ){ + para[numParPerPeak*i+2] = abs(sigmaMax); + }else if(sigmaMax > 0 ){ + para[numParPerPeak*i+2] = sigmaMax/2.; + } + } + + TF1 * fit = new TF1("fit", nGauss, xMin, xMax, 3 * nPeaks ); + fit->SetLineWidth(2); + fit->SetLineColor(2); + fit->SetNpx(1000); + fit->SetParameters(para); + + if( nPeaks > 1 ){ + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(numParPerPeak*i+0, 0, 1e+9); + double de1 = 1, de2 = 1; + if( i == 0 ){ + de2 = (energy[i+1] - energy[i])/2.; + de1 = de2; + }else if( i < nPeaks -1 ){ + de1 = (energy[i] - energy[i-1])/2.; + de2 = (energy[i+1] - energy[i])/2.; + }else{ + de1 = (energy[i] - energy[i-1])/2.; + de2 = de1; + } + + fit->SetParLimits(numParPerPeak*i+1, energy[i] - de1 , energy[i] + de2); + if( sigmaMax== 0 ) fit->SetParLimits(numParPerPeak*i+2, 0, 1.5*sigma[i]); // add 50% margin of sigma + if( sigmaMax < 0 ) fit->FixParameter(numParPerPeak*i+2, abs(sigmaMax)); + if( sigmaMax > 0 ) fit->SetParLimits(numParPerPeak*i+2, 0, sigmaMax); + } + }else{ + fit->SetParLimits(0, 0, 1e+9); + fit->SetParLimits(2, 0, sigmaMax); + } + + specS->Fit("fit", "q"); + + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + //======== calculate reduce chi-squared + //GoodnessofFit(specS, fit); + + double bw = specS->GetBinWidth(1); + + std::vector exPos; + for(int i = 0; i < nPeaks ; i++){ + exPos.push_back(paraA[numParPerPeak*i+1]); + printf("%2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[numParPerPeak*i] / bw, paraE[numParPerPeak*i] /bw, + paraA[numParPerPeak*i+1], paraE[numParPerPeak*i+1], + paraA[numParPerPeak*i+2], paraE[numParPerPeak*i+2]); + + } + cFitAuto->Update(); + + //draw the indivual fit + fit->Draw("same"); + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[numParPerPeak*i]); + gFit[i]->SetParameter(1, paraA[numParPerPeak*i+1]); + gFit[i]->SetParameter(2, paraA[numParPerPeak*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + specS->Draw("hist same"); + + //======== print text on plot + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.SetTextSize(0.06); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + cFitAuto->cd(3); + PlotResidual(specS, fit); + + cFitAuto->cd(4); + text.SetTextSize(0.05); + text.SetTextColor(2); + + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } + + return exPos; + +} + + +//######################################## +//###### NOT tested +//######################################## +std::vector fitNGF3(TH1 * hist, int bgEst = 10, + double peakThreshold = 0.1, + double sigmaMax = 20, + int peakDensity = 4, + TString optStat = "", bool newPlot = true){ + + TCanvas *cFitAuto = NULL; + if( newPlot ){ + cFitAuto = new TCanvas("cFitAuto","Auto Fitting", 100, 100, 800,800); + cFitAuto->Divide(1,2); + + gStyle->SetOptStat(optStat); + cFitAuto->cd(1); + hist->Draw(); + } + + recentFitMethod = "fitNGF3"; + + TH1F * specS = (TH1F*) hist->Clone(); + double xMin = hist->GetXaxis()->GetXmin(); + double xMax = hist->GetXaxis()->GetXmax(); + int xBin = hist->GetXaxis()->GetNbins(); + + TString titleH; + titleH.Form("fitted spectrum (BG=%d); Ex [MeV]; Count / %4.0f keV", bgEst, (xMax-xMin)*1000./xBin ); + specS->SetTitle(titleH); + specS->SetName("specS"); + ///specS->GetXaxis()->SetTitleSize(0.06); + ///specS->GetYaxis()->SetTitleSize(0.06); + ///specS->GetXaxis()->SetTitleOffset(0.7); + ///specS->GetYaxis()->SetTitleOffset(0.6); + + //=================== find peak and fit + gStyle->SetOptFit(0); + TSpectrum * peak = new TSpectrum(50); + nPeaks = peak->Search(hist, peakDensity, "", peakThreshold); + + if( bgEst > 0 ) { + printf("============= estimating background...\n"); + TH1 * h1 = peak->Background(hist, bgEst); + h1->Draw("same"); + printf("============= substracting the linear background...\n"); + specS->Sumw2(); + specS->Add(h1, -1.); + } + + if( newPlot ){ + cFitAuto->cd(2)->SetGrid(); + cFitAuto->cd(2); + } + specS->Draw("hist"); + + + //========== Fitting + if( newPlot ){ + printf("============= Fitting....."); + printf(" found %d peaks \n", nPeaks); + } + double * xpos = peak->GetPositionX(); + double * ypos = peak->GetPositionY(); + + int * inX = new int[nPeaks]; + TMath::Sort(nPeaks, xpos, inX, 0 ); + std::vector energy, height; + for( int j = 0; j < nPeaks; j++){ + energy.push_back(xpos[inX[j]]); + height.push_back(ypos[inX[j]]); + } + if( newPlot ){ + for( int j = 0; j < nPeaks; j++){ + printf(" energy : %f , %f \n", energy[j], height[j]); + } + } + + int numParPerPeak = 6; + const int n = numParPerPeak * nPeaks; + double * para = new double[n]; + for(int i = 0; i < nPeaks ; i++){ + para[numParPerPeak*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[numParPerPeak*i+1] = energy[i]; + para[numParPerPeak*i+2] = sigmaMax; + para[numParPerPeak*i+3] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()) * 0.1; + para[numParPerPeak*i+4] = sigmaMax; + para[numParPerPeak*i+5] = -4; + } + + TF1 * fit = new TF1("fit", nGF3, xMin, xMax, numParPerPeak * nPeaks ); + fit->SetLineWidth(2); + fit->SetLineColor(2); + fit->SetNpx(1000); + fit->SetParameters(para); + + if( nPeaks > 1 ){ + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(numParPerPeak*i+0, 0, 1e+9); + double de1 = 1, de2 = 1; + if( i == 0 ){ + de2 = (energy[i+1] - energy[i])/2.; + de1 = de2; + }else if( i < nPeaks -1 ){ + de1 = (energy[i] - energy[i-1])/2.; + de2 = (energy[i+1] - energy[i])/2.; + }else{ + de1 = (energy[i] - energy[i-1])/2.; + de2 = de1; + } + + fit->SetParLimits(numParPerPeak*i+1, energy[i] - de1 , energy[i] + de2); + fit->SetParLimits(numParPerPeak*i+2, 0, sigmaMax * 5); + + fit->SetParLimits(numParPerPeak*i+3, 0, 1e+9); + fit->SetParLimits(numParPerPeak*i+4, 0, sigmaMax); + fit->SetParLimits(numParPerPeak*i+5, -10, -2); + + } + }else{ + fit->SetParLimits(0, 0, 1e+9); + fit->SetParLimits(2, 0, sigmaMax); + fit->SetParLimits(3, 0, 1e+9); + fit->SetParLimits(4, 0, sigmaMax); + fit->SetParLimits(5, -10, -2); + } + specS->Fit("fit", "q"); + + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + //======== calculate reduce chi-squared + if( newPlot ) GoodnessofFit(specS, fit); + + double bw = specS->GetBinWidth(1); + + std::vector exPos; + for(int i = 0; i < nPeaks ; i++){ + exPos.push_back(paraA[numParPerPeak*i+1]); + double totCount = paraA[numParPerPeak*i] + paraA[numParPerPeak*i+3]; + double totCountErr = sqrt(paraE[numParPerPeak*i]*paraE[numParPerPeak*i] + paraE[numParPerPeak*i+3]*paraE[numParPerPeak*i+3]); + printf("%2d , count: %8.0f(%3.0f)+%8.0f(%3.0f)=%8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f), skewneww: %4.1f(%4.1f) \n", + i, + paraA[numParPerPeak*i] / bw, paraE[numParPerPeak*i] /bw, + paraA[numParPerPeak*i+3] / bw, paraE[numParPerPeak*i+3] /bw, + totCount / bw, totCountErr /bw, + paraA[numParPerPeak*i+1], paraE[numParPerPeak*i+1], + paraA[numParPerPeak*i+2], paraE[numParPerPeak*i+2], + paraA[numParPerPeak*i+5], paraE[numParPerPeak*i+5]); + + //PrintPar(fit, numParPerPeak); + } + if( newPlot ) cFitAuto->Update(); + + //draw the indivual fit + fit->Draw("same"); + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + TF1 ** kFit = new TF1 *[nn]; + TF1 ** zFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1) + [3] * TMath::Gaus(x,[1],[4], 1) * ( 1 + TMath::Erf( [5]*(x-[1])/sqrt(2)/[4] ))", xMin, xMax); + gFit[i]->SetParameter(0, paraA[numParPerPeak*i]); + gFit[i]->SetParameter(1, paraA[numParPerPeak*i+1]); + gFit[i]->SetParameter(2, paraA[numParPerPeak*i+2]); + gFit[i]->SetParameter(3, paraA[numParPerPeak*i+3]); + gFit[i]->SetParameter(4, paraA[numParPerPeak*i+4]); + gFit[i]->SetParameter(5, paraA[numParPerPeak*i+5]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + + kFit[i] = new TF1(Form("kFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1) * ( 1 + TMath::Erf( [3]*(x-[1])/sqrt(2)/[2] ))", xMin, xMax); + kFit[i]->SetParameter(0, paraA[numParPerPeak*i+3]); + kFit[i]->SetParameter(1, paraA[numParPerPeak*i+1]); + kFit[i]->SetParameter(2, paraA[numParPerPeak*i+4]); + kFit[i]->SetParameter(3, paraA[numParPerPeak*i+5]); + kFit[i]->SetLineColor(i+1); + kFit[i]->SetNpx(1000); + kFit[i]->SetLineWidth(1); + kFit[i]->Draw("same"); + + zFit[i] = new TF1(Form("zFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + zFit[i]->SetParameter(0, paraA[numParPerPeak*i]); + zFit[i]->SetParameter(1, paraA[numParPerPeak*i+1]); + zFit[i]->SetParameter(2, paraA[numParPerPeak*i+2]); + zFit[i]->SetLineColor(i+1); + zFit[i]->SetNpx(1000); + zFit[i]->SetLineWidth(1); + zFit[i]->Draw("same"); + + } + + specS->Draw("hist same"); + + return exPos; + +} + +//######################################## +//###### fir N Gauss with estimated BG +//######################################## +void fitNGauss(TH1F * hist, int bgEst = 10, TString fitFile = "AutoFit_para.txt", TString optStat = ""){ + + printf("================================================================\n"); + printf("================ fit N-Gauss with estimated BG ================\n"); + printf(" * bgEst = larger of bgEst, more linear the estimated BG \n"); + printf(" * need the file input \n"); + printf(" \n"); + printf(" 1) The histogram will be subtracted by the estimated BG. \n"); + printf(" 2) n-Gauss will then be fitted the BG subtracted histogram \n"); + printf("================================================================\n"); + + recentFitMethod = "fitNGauss"; + + bool isParaRead = loadFitParameters(fitFile); + if( !isParaRead ) { + printf("Please provide a valid input file\n"); + return; + } + + nPeaks = energy.size(); + + gStyle->SetOptStat(optStat); + TCanvas *cFitNGauss = NewCanvas("cFitNGauss","Fit n-Gauss | fitNGauss", 1,4, 800, 300);; + cFitNGauss->cd(1); + + ScaleAndDrawHist(hist, 0, 0); + + TH1F * specS = (TH1F*) hist->Clone(); + double xMin = hist->GetXaxis()->GetXmin(); + double xMax = hist->GetXaxis()->GetXmax(); + int xBin = hist->GetXaxis()->GetNbins(); + + TString titleH; + titleH.Form("fitNGauss (BG = %2d); Ex [MeV]; Count / %4.0f keV", bgEst, (xMax-xMin)*1000./xBin ); + specS->SetTitle(titleH); + specS->SetName("specS"); + + //=================== find peak and fi + + gStyle->SetOptFit(0); + //cFitNGauss->cd(2)->SetGrid(); + cFitNGauss->cd(2); + + if( bgEst > 0 ) { + printf("============= estimating background...\n"); + TSpectrum * peak = new TSpectrum(50); + TH1 * h1 = peak->Background(hist, bgEst); + cFitNGauss->cd(1); + h1->Draw("same"); + cFitNGauss->cd(2); + printf("============= substracting the estimated background...\n"); + specS->Sumw2(); + specS->Add(h1, -1.); + } + + specS->Draw("hist"); + + //========== Fitting + printf("============= Fitting %d-Gauss..... \n", nPeaks); + + const int n = 3 * nPeaks; + double * para = new double[n]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = energy[i]; + para[3*i+2] = sigma[i]/2.; + } + + TF1 * fit = new TF1("fit", nGauss, xMin, xMax, 3* nPeaks ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //fixing parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + + if( energyFlag[i] == 1 ) { + fit->FixParameter(3*i+1, energy[i]); + }else{ + fit->SetParLimits(3*i+1, lowE[i], highE[i]); + } + if( sigmaFlag[i] == 1 ) { + fit->FixParameter(3*i+2, sigma[i]); + }else{ + fit->SetParLimits(3*i+2, 0, sigma[i]); + } + } + + specS->Fit("fit", "q"); + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + //======== calculate reduce chi-squared + //GoodnessofFit(specS, fit); + + double bw = specS->GetBinWidth(1); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + //draw the indivual fit + specS->Draw("hist"); + fit->Draw("same"); + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + specS->Draw("hist same"); + //specS->Draw("E same"); + + + //======== print text on plot + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.06); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + cFitNGauss->cd(3); + PlotResidual(specS, fit); + + cFitNGauss->cd(4); + + text.SetTextSize(0.05); + text.SetTextColor(2); + + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } + + cFitNGauss->Update(); +} + + +//######################################## +//#### not updated +//######################################## +void fitNGaussSub(TH1F * hist, int bgEst = 10, int degPol = 1, TString fitFile = "AutoFit_para.txt", TString optStat = ""){ + + + printf("==================================================================\n"); + printf("======== fit N-Gauss with estimated BG (method-2) ================\n"); + printf(" * bgEst = larger of bgEst, more linear the estimated BG \n"); + printf(" * degPol = degree of polynomial \n"); + printf(" * need the file input \n"); + printf(" \n"); + printf(" 1) A BG is estimated, and then the BG is fitted by a polynomial. \n"); + printf(" 2) The histogram will be subtracted by the polynomial. \n"); + printf(" 3) n-Gauss will then be fitted the subtracted histogram \n"); + printf("================================================================\n"); + + recentFitMethod = "fitNGaussSub"; + + bool isParaRead = loadFitParameters(fitFile); + if( !isParaRead ) { + printf("Please provide a valid input file\n"); + return; + } + + nPeaks = energy.size(); + nPols = degPol; + + gStyle->SetOptStat(optStat); + TCanvas *cFitNGaussSub = NewCanvas("cFitNGaussSub","Fit n-Gauss, replace estimated BG with Pol-n | fitNGauss2", 1, 4, 800, 300 ); + //if(! cFitNGaussSub->GetShowEventStatus() ) cFitNGaussSub->ToggleEventStatus(); + + cFitNGaussSub->cd(1); + ScaleAndDrawHist(hist, 0, 0); + + TH1F * specS = (TH1F*) hist->Clone(); + double xMin = hist->GetXaxis()->GetXmin(); + double xMax = hist->GetXaxis()->GetXmax(); + int xBin = hist->GetXaxis()->GetNbins(); + + TString titleH; + titleH.Form("fitNGauss2 (replace Est. BG with Pol-%d) (BG = %2d); Ex [MeV]; Count / %4.0f keV", degPol, bgEst, (xMax-xMin)*1000./xBin ); + specS->SetTitle(titleH); + specS->SetName("specS"); + + printf("============= estimating background...\n"); + TSpectrum * peak = new TSpectrum(50); + TH1 * h1 = peak->Background(hist, bgEst); + + printf("============= fit the est-background with a polynomial function...\n"); + + TString polExp = "[0]"; + for( int i = 1; i < degPol + 1; i++){ + polExp += Form("+[%d]*TMath::Power(x,%d)", i, i ); + } + TF1 * bg = new TF1("bg", polExp.Data(), xMin, xMax); + + bg->SetParameter(0, 50); + bg->SetParameter(0, 0); + bg->SetLineColor(2); + bg->SetNpx(1000); + h1->Fit("bg", "R", ""); + + hist->Draw(); + bg->Draw("same"); + + + //======== print text on plot + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + + const Double_t * paraAt = bg->GetParameters(); + const Double_t * paraEt = bg->GetParErrors(); + + for( int i = 0; i < degPol + 1; i++){ + text.DrawLatex(0.6, 0.85 - 0.05*i, Form("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraAt[i], paraEt[i])); + } + + gStyle->SetOptFit(0); +// cFitNGaussSub->cd(2)->SetGrid(); + cFitNGaussSub->cd(2); + + printf("============= substracting the polynomial background...\n"); + specS->Sumw2(); + specS->Add(bg, -1.); + specS->Draw("hist"); + + //========== Fitting + printf("============= Fitting..... \n"); + + const int n = 3 * nPeaks; + double * para = new double[n]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = energy[i]; + para[3*i+2] = sigma[i]/2.; + } + + TF1 * fit = new TF1("fit", nGauss, xMin, xMax, 3* nPeaks ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //fixing parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + + if( energyFlag[i] == 1 ) { + fit->FixParameter(3*i+1, energy[i]); + }else{ + fit->SetParLimits(3*i+1, lowE[i], highE[i]); + } + if( sigmaFlag[i] == 1 ) { + fit->FixParameter(3*i+2, sigma[i]); + }else{ + fit->SetParLimits(3*i+2, 0, sigma[i]); + } + } + + specS->Fit("fit", "q"); + + const Double_t* paraE = fit->GetParErrors(); + const Double_t* paraA = fit->GetParameters(); + + GoodnessofFit(specS, fit); + + double bw = specS->GetBinWidth(1); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + + //draw the indivual fit + specS->Draw("hist"); + fit->Draw("same"); + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + specS->Draw("hist same"); + //specS->Draw("E same"); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.SetTextSize(0.06); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + + cFitNGaussSub->cd(3); + PlotResidual(specS, fit); + + cFitNGaussSub->cd(4); + + text.SetTextSize(0.05); + text.SetTextColor(2); + + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } + +} + + +//######################################## +//#### fit N-Gauss with pol-n BG +//######################################## +void fitNGaussPol(TH1F * hist, int degPol, TString fitFile = "AutoFit_para.txt",double xMin = 0, double xMax = 0, TString optStat = ""){ + + printf("================================================================\n"); + printf("================ fit N-Gauss with Pol-%1d BG ==================\n", degPol); + printf(" * degPol = degree of polynomial \n"); + printf(" * need the file input \n"); + printf(" * xMin, xMax = if left empty, full range will be used\n"); + printf(" \n"); + printf(" 1) The histogram will be fitted by n-Gauss + Pol \n"); + printf("================================================================\n"); + + recentFitMethod = "fitNGaussPol"; + + bool isParaRead = loadFitParameters(fitFile); + if( !isParaRead ) { + printf("Please provide a valid input file\n"); + return; + } + + gStyle->SetOptStat(optStat); + nPeaks = energy.size(); + nPols = degPol; + + TCanvas * cFitNGaussPol = NewCanvas("cFitNGaussPol", Form("Fitting with n-Gauss + pol-%d | fitNGaussPol", degPol), 1, 3, 800, 300); + //if(! cFitNGaussPol->GetShowEventStatus() ) cFitNGaussPol->ToggleEventStatus(); + cFitNGaussPol->cd(1); + + ScaleAndDrawHist(hist, xMin, xMax); + + if( xMin == xMax){ + xMin = hist->GetXaxis()->GetXmin(); + xMax = hist->GetXaxis()->GetXmax(); + } + int xBin = hist->GetXaxis()->GetNbins(); + + + printf("============= find the polynomial background ..... \n"); + + int nPar = 3 * nPeaks + nPols + 1; + double * para = new double[nPar]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = energy[i]; + para[3*i+2] = sigma[i]/2.; + } + + for(int i = 0; i < nPols + 1; i++){ + //if( ggg == NULL ){ + para[3*nPeaks+i] = gRandom->Rndm()/TMath::Power(10, 3*i); + //}else{ + // para[3*nPeaks+i] = gPara[i]; + //} + } + + TF1 * fit = new TF1("fit", nGaussPol, xMin, xMax, nPar ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //fixing parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + if( energyFlag[i] == 1 ) { + fit->FixParameter(3*i+1, energy[i]); + }else{ + fit->SetParLimits(3*i+1, lowE[i], highE[i]); + } + if( sigmaFlag[i] == 1 ) { + fit->FixParameter(3*i+2, sigma[i]); + }else{ + fit->SetParLimits(3*i+2, 0, sigma[i]); + } + } + + hist->Fit("fit", "Rq"); + + //=========== get the polynomial part + const Double_t* paraA = fit->GetParameters(); + const Double_t* paraE = fit->GetParErrors(); + + TString polExp = "[0]"; + for( int i = 1; i < degPol + 1; i++){ + polExp += Form("+[%d]*TMath::Power(x,%d)", i, i ); + } + + TF1 * bg = new TF1("bg", polExp.Data(), xMin, xMax); + for( int i = 0; i < degPol + 1; i++){ + bg->SetParameter(i, paraA[3*nPeaks+i]); + } + bg->SetNpx(1000); + + for( int i = 0; i < degPol + 1; i++){ + printf("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraA[3*nPeaks+i], paraE[3*nPeaks+i]); + } + printf("====================================\n"); + + cFitNGaussPol->cd(1); + bg->Draw("same"); + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + text.SetTextColor(1); + + for( int i = 0; i < degPol + 1; i++){ + text.DrawLatex(0.6, 0.85 - 0.05*i, Form("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraA[3*nPeaks+i], paraE[3*nPeaks+i])); + } + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.SetTextSize(0.06); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + + //GoodnessofFit(specS, fit); + + double bw = hist->GetBinWidth(1); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + cFitNGaussPol->Update(); + + cFitNGaussPol->cd(2); + PlotResidual(hist, fit); + + cFitNGaussPol->cd(3); + + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.05); + text.SetTextColor(2); + + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } +} + + + + +//######################################## +//#### fit N-Gauss with pol-n BG +//######################################## +void fitNGaussPolSub(TH1F * hist, int degPol, TString fitFile = "AutoFit_para.txt",double xMin = 0, double xMax = 0, TString optStat = ""){ + + printf("================================================================\n"); + printf("========= fit N-Gauss with Pol-%1d BG / 2nd method ============\n", degPol); + printf(" * degPol = degree of polynomial \n"); + printf(" * need the file input \n"); + printf(" * xMin, xMax = if left empty, full range will be used\n"); + printf(" \n"); + printf(" 1) The histogram will be fitted by n-Gauss + Pol -> to get the estimated BG \n"); + printf(" 2) The histogram will be subtracted by the Pol BG. \n"); + printf(" 3) n-Gauss will then be fitted the BG subtracted histogram \n"); + printf("================================================================\n"); + + recentFitMethod = "fitNGaussPolSub"; + + bool isParaRead = loadFitParameters(fitFile); + if( !isParaRead ) { + printf("Please provide a valid input file\n"); + return; + } + + gStyle->SetOptStat(optStat); + nPeaks = energy.size(); + nPols = degPol; + + TCanvas * cFitNGaussPolSub = NewCanvas("cFitNGaussPolSub", Form("Fitting with n-Gauss + pol-%d (method-2) | fitGaussPol2", degPol), 1, 4, 800, 300); + //if(! cFitNGaussPol->GetShowEventStatus() ) cFitNGaussPol->ToggleEventStatus(); + cFitNGaussPolSub->cd(1); + + ScaleAndDrawHist(hist, xMin, xMax); + + if( xMin == xMax){ + xMin = hist->GetXaxis()->GetXmin(); + xMax = hist->GetXaxis()->GetXmax(); + } + int xBin = hist->GetXaxis()->GetNbins(); + + printf("============= find the polynomial background ..... \n"); + + int nPar = 3 * nPeaks + nPols + 1; + double * para = new double[nPar]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = energy[i]; + para[3*i+2] = sigma[i]/2.; + } + + for(int i = 0; i < nPols + 1; i++){ + para[3*nPeaks+i] = gRandom->Rndm()/TMath::Power(10, 3*i); + } + + TF1 * fit = new TF1("fit", nGaussPol, xMin, xMax, nPar ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //fixing parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + if( energyFlag[i] == 1 ) { + fit->FixParameter(3*i+1, energy[i]); + }else{ + fit->SetParLimits(3*i+1, lowE[i], highE[i]); + } + if( sigmaFlag[i] == 1 ) { + fit->FixParameter(3*i+2, sigma[i]); + }else{ + fit->SetParLimits(3*i+2, 0, sigma[i]); + } + } + + hist->Fit("fit", "nq"); + + //=========== get the polynomial part and substract + const Double_t* paraAt = fit->GetParameters(); + const Double_t* paraEt = fit->GetParErrors(); + + TString polExp = "[0]"; + for( int i = 1; i < degPol + 1; i++){ + polExp += Form("+[%d]*TMath::Power(x,%d)", i, i ); + } + + TF1 * bg = new TF1("bg", polExp.Data(), xMin, xMax); + for( int i = 0; i < degPol + 1; i++){ + bg->SetParameter(i, paraAt[3*nPeaks+i]); + } + bg->SetNpx(1000); + + for( int i = 0; i < degPol + 1; i++){ + printf("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraAt[3*nPeaks+i], paraEt[3*nPeaks+i]); + } + printf("====================================\n"); + + cFitNGaussPolSub->cd(1); + bg->Draw("same"); + + TH1F * specS = (TH1F*) hist->Clone(); + TString titleH; + titleH.Form("pol-%d BG Subtracted spectrum (fitNGaussPol-2); Ex [MeV]; Count / %4.0f keV", degPol, (xMax-xMin)*1000./xBin ); + specS->SetTitle(titleH); + specS->SetName("specS"); + + //=================== find peak and fit + + gStyle->SetOptFit(0); + ///cFitNGaussPol->cd(2)->SetGrid(); + cFitNGaussPolSub->cd(2); + + printf("============= substracting the polynomial background...\n"); + specS->Sumw2(); + specS->Add(bg, -1.); + specS->Draw("hist"); + + //======= fit again + printf("============= fitting the subtracted spectrum.... \n"); + + nPar = 3* nPeaks; + TF1 * fita = new TF1("fita", nGauss, xMin, xMax, nPar ); + fita->SetLineWidth(3); + fita->SetLineColor(1); + fita->SetNpx(1000); + fita->SetParameters(para); + + //fixing parameters + for( int i = 0; i < nPeaks; i++){ + fita->SetParLimits(3*i , 0, 1e9); + + if( energyFlag[i] == 1 ) { + fita->FixParameter(3*i+1, energy[i]); + }else{ + fita->SetParLimits(3*i+1, lowE[i], highE[i]); + } + if( sigmaFlag[i] == 1 ) { + fita->FixParameter(3*i+2, sigma[i]); + }else{ + fita->SetParLimits(3*i+2, 0, sigma[i]); + } + } + + specS->Fit("fita", "q"); + + const Double_t* paraE = fita->GetParErrors(); + const Double_t* paraA = fita->GetParameters(); + + //GoodnessofFit(specS, fit); + + double bw = specS->GetBinWidth(1); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + + //draw the indivual fit + specS->Draw("hist"); + fita->Draw("same"); + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + specS->Draw("hist same"); + //specS->Draw("E same"); + + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + text.SetTextColor(1); + + for( int i = 0; i < degPol + 1; i++){ + text.DrawLatex(0.6, 0.85 - 0.05*i, Form("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraA[3*nPeaks+i], paraE[3*nPeaks+i])); + } + + double chi2 = fita->GetChisquare(); + int ndf = fita->GetNDF(); + text.SetTextSize(0.06); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + + cFitNGaussPolSub->cd(3); + PlotResidual(specS, fita); + + cFitNGaussPolSub->cd(4); + + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.05); + text.SetTextColor(2); + + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } + + +} + +//################################################# +//#### fit N-Gauss with pol-n BG using mouse click +//################################################# + +int nClick = 0; +bool peakFlag = 1; +std::vector xPeakList; +std::vector yPeakList; +std::vector xBGList; +std::vector yBGList; + +TH1F * tempHist; +int markerStyle = 23; +int markerColor = 2; +int markerBGColor = 4; + +void Clicked() { + int event = gPad->GetEvent(); + if (event != 11) return; + TObject *select = gPad->GetSelected(); + if (!select) return; + + TH1F *h = (TH1F*)select; + int px = gPad->GetEventX(); + double xd = gPad->AbsPixeltoX(px); + float x = gPad->PadtoX(xd); + + if( peakFlag ) { + xPeakList.push_back(x); + }else{ + xBGList.push_back(x); + } + int b = tempHist->FindBin(x); + double y = tempHist->GetBinContent(b); + if( peakFlag ){ + yPeakList.push_back(y); + }else{ + yBGList.push_back(y); + } + // add marker in the histogram + TMarker * mark = new TMarker(x,y, markerStyle); + mark->SetMarkerColor(markerColor); + tempHist->GetListOfFunctions()->Add(mark); + + printf("%2d | x : %8.2f , y : %.0f \n", nClick, x, y); + + nClick ++; + +} + + +void SaveFitPara(bool isBestFit = true, TString fileName = "AutoFit_para.txt"){ + + if( xPeakList.size() == 0 && BestFitMean.size() == 0 ){ + printf(" no fit paramaters availible. \n"); + return; + } + + if( recentFitMethod == "fitGF3Pol" || recentFitMethod == "fitGF3" ){ + printf(" Not support for GF3 fitting. \n"); + return; + } + + printf("Save to : %s \n", fileName.Data()); + FILE * file_out; + file_out = fopen (fileName.Data(), "w+"); + + fprintf(file_out, "# for n-Gauss fit, can use \"#\", or \"//\" to comment out whole line\n"); + fprintf(file_out, "# peak low high fixed? sigma_Max fixed? hight\n"); + + + if ( xPeakList.size() == 0 || isBestFit ){ + for( int i = 0 ; i < BestFitMean.size() ; i++){ + fprintf(file_out, "%.3f %.3f %.3f 0 %.3f 0 %.0f\n", + BestFitMean[i], + BestFitMean[i] - 5*BestFitSigma[i], + BestFitMean[i] + 5*BestFitSigma[i], + BestFitSigma[i], + BestFitCount[i]); + } + }else{ + for( int i = 0 ; i < xPeakList.size() ; i++){ + fprintf(file_out, "%.3f %.3f %.3f 0 %.3f 0 %.0f\n", + xPeakList[i], + xPeakList[i] - 5*sigma[i], + xPeakList[i] + 5*sigma[i], + sigma[i], + yPeakList[i]); + } + } + fclose(file_out); +} + + +void clickFitNGaussPol(TH1F * hist, int degPol, double sigmaMax = 0, double meanRange = 0){ + + printf("=========================================================\n"); + printf("======== fit n-Gauss + Pol-%d BG using mouse click =====\n", degPol ); + printf("==========================================================\n"); + + recentFitMethod = "clickFitNGaussPol"; + + gStyle->SetOptStat(""); + gStyle->SetOptFit(0); + + TCanvas * cClickFitNGaussPol = NULL; + if( gROOT->FindObjectAny("cClickFitGaussPol") == NULL ){ + cClickFitNGaussPol = new TCanvas("cClickFitNGaussPol", Form("fit Gauss & Pol-%d by mouse click | clickFitGaussPol", degPol), 1400, 1200); + }else{ + delete gROOT->FindObjectAny("cClickFitNGaussPol") ; + cClickFitNGaussPol = new TCanvas("cClickFitNGaussPol", Form("fit Gauss & Pol-%d by mouse click | clickFitGaussPol", degPol), 1400, 1200); + } + cClickFitNGaussPol->Divide(1, 4); + for(int i = 1; i <= 4 ; i++){ + cClickFitNGaussPol->cd(i)->SetGrid(0,0); + } + + if(! cClickFitNGaussPol->GetShowEventStatus() ) cClickFitNGaussPol->ToggleEventStatus(); + cClickFitNGaussPol->cd(1); + + + hist->GetListOfFunctions()->Clear(); + ScaleAndDrawHist(hist, 0, 0); + TH1F* hspec = (TH1F*) hist->Clone(); + hspec->Sumw2(); + cClickFitNGaussPol->Update(); + cClickFitNGaussPol->Draw(); + + TLatex helpMsg; + helpMsg.SetNDC(); + helpMsg.SetTextFont(82); + helpMsg.SetTextSize(0.06); + helpMsg.SetTextColor(kRed); + helpMsg.DrawLatex(0.15, 0.8, "Click for peaks: (Double-click / x / Ctrl to end) "); + + printf("--------- Click the histogram for peaks: (Double-click / x / Ctrl to end) \n"); + nClick = 0; + xPeakList.clear(); + yPeakList.clear(); + markerColor = 2; + markerStyle = 23; + peakFlag = 1; + cClickFitNGaussPol->cd(1)->SetCrosshair(1); + cClickFitNGaussPol->cd(1)->AddExec("ex", "Clicked()"); + tempHist = hist; + TObject * obj ; + do{ + obj = gPad->WaitPrimitive(); + if( obj == NULL ) break; + }while( obj != NULL); + + if( degPol >= 0 ){ + printf("--------- Click the histogram for Background: (Double-click / x / Ctrl to end) \n"); + printf(" * when no input, program will estimate \n"); + + cClickFitNGaussPol->cd(1)->Clear(); + hist->Draw(); + helpMsg.SetTextColor(markerBGColor); + helpMsg.DrawLatex(0.15, 0.8, "Click for BG: (Double-click / x / Ctrl to end) "); + helpMsg.DrawLatex(0.15, 0.75, "* when no input, program will estimate"); + cClickFitNGaussPol->Update(); + cClickFitNGaussPol->Draw(); + + nClick = 0; + xBGList.clear(); + yBGList.clear(); + markerColor = markerBGColor; + markerStyle = 33; + peakFlag = 0; + cClickFitNGaussPol->cd(1)->AddExec("ex", "Clicked()"); + do{ + obj = gPad->WaitPrimitive(); + if( obj == NULL ) break; + }while( obj != NULL); + + } + + cClickFitNGaussPol->cd(1)->DeleteExec("ex"); + cClickFitNGaussPol->cd(1)->SetCrosshair(0); + cClickFitNGaussPol->cd(1)->Clear(); + hist->Draw(); + + tempHist = NULL; + + cClickFitNGaussPol->Update(); + cClickFitNGaussPol->Draw(); + + nPols = degPol; + double xMin = hspec->GetXaxis()->GetXmin(); + double xMax = hspec->GetXaxis()->GetXmax(); + + TString polExp = "[0]"; + for( int i = 1; i < degPol + 1; i++) polExp += Form("+[%d]*TMath::Power(x,%d)", i, i ); + TF1 *bg = new TF1("bg", polExp.Data(), xMin, xMax); + bg->SetNpx(1000); + bg->SetLineColor(markerBGColor); + bg->SetLineWidth(1); + if( xBGList.size() > 0 ) { + printf("---------------- fit the BG with Pol-%d \n", nPols); + TGraph * gBG = new TGraph((int) xBGList.size(), &xBGList[0], &yBGList[0]); + for( int i = 0; i < degPol + 1; i++) bg->SetParameter(i, gRandom->Rndm()/TMath::Power(10, 3*i)); + gBG->Fit("bg", "Rq"); + bg->Draw("same"); + //printf("--------------- Subtracting the BG \n"); + //hspec->Add(bg, -1); + }else{ + for( int i = 0; i < nPols+1; i++) bg->SetParameter(i, 0.); + } + + nPeaks = (int) xPeakList.size(); + if( sigmaMax == 0 ){ + printf("------------- Estimate sigma for each peak \n"); + sigma.clear(); + int binMin = hist->FindBin(xMin); + int binMax = hist->FindBin(xMax); + for( int i = 0; i < nPeaks ; i++){ + int b0 = hist->FindBin(xPeakList[i]); + double estBG = bg->Eval(xPeakList[i]); + double sMin = (xMax-xMin)/5., sMax = (xMax-xMin)/5.; + //---- backward search, stop when + for( int b = b0-1 ; b > binMin ; b-- ){ + double y = hist->GetBinContent(b); + double x = hist->GetBinCenter(b); + if( y - (bg->Eval(x)) < (yPeakList[i]-estBG)/2. ) { + sMin = xPeakList[i] - hist->GetBinCenter(b); + break; + } + } + //---- forward search, stop when + for( int b = b0+1 ; b < binMax ; b++ ){ + double y = hist->GetBinContent(b); + double x = hist->GetBinCenter(b); + if( y - (bg->Eval(x)) < (yPeakList[i]-estBG)/2. ) { + sMax = hist->GetBinCenter(b) - xPeakList[i]; + break; + } + } + + double temp = TMath::Min(sMin, sMax); + /// When there are multiple peaks closely packed : + if( i > 0 && temp > 2.5 * sigma.back() ) temp = sigma.back(); + sigma.push_back(temp); + + printf("%2d | x : %8.2f | sigma(est) %f \n", i, xPeakList[i], sigma[i]); + + } + + //---- use the mean of the sigma + double sigma0 = 0; + for( int i = 0; i < nPeaks ; i++) sigma0 += sigma[i]; + sigma0 = sigma0/(nPeaks+1); + for( int i = 0; i < nPeaks ; i++) sigma[i] = sigma0; + printf("========== use the mean sigma : %f \n", sigma0); + }else if( sigmaMax < 0 ){ + printf("========== use user input sigma : %f (fixed)\n", abs(sigmaMax)); + sigma.clear(); + for( int i = 0; i < nPeaks ; i++) sigma.push_back(abs(sigmaMax)); + }else if( sigmaMax > 0 ){ + printf("========== use user input sigma : %f/2. \n", sigmaMax/2.); + sigma.clear(); + for( int i = 0; i < nPeaks ; i++) sigma.push_back(sigmaMax/2.); + } + + printf("-------------- Fit the spectrum with %d-Gauss + Pol-%d\n", nPeaks, nPols ); + cClickFitNGaussPol->cd(2); + hspec->Draw("hist"); + + int nPar = 3 * nPeaks + nPols + 1; + double * para = new double[nPar]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = yPeakList[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = xPeakList[i]; + if( sigmaMax == 0){ + para[3*i+2] = sigma[i]; + }else if(sigmaMax < 0 ){ + para[3*i+2] = abs(sigmaMax); + }else if(sigmaMax > 0 ){ + para[3*i+2] = sigmaMax/2.; + } + } + for(int i = 0; i < nPols+1 ; i++){ + para[3*nPeaks+i] = bg->GetParameter(i); + } + + TF1 * fit = new TF1("fit", nGaussPol, xMin, xMax, nPar ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //limit parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + + if( meanRange <= 0 ) { + double dE1, dE2; + if( i == 0 ){ + dE2 = xPeakList[i+1] - xPeakList[i]; + dE1 = dE2; + }else if ( i == nPeaks-1 ){ + dE1 = xPeakList[i] - xPeakList[i-1]; + dE2 = dE1; + }else{ + dE1 = xPeakList[i] - xPeakList[i-1]; + dE2 = xPeakList[i+1] - xPeakList[i]; + } + fit->SetParLimits(3*i+1, xPeakList[i] - dE1 , xPeakList[i] + dE2 ); + }else{ + fit->SetParLimits(3*i+1, xPeakList[i] - meanRange/2. , xPeakList[i] + meanRange/2. ); + } + if( sigmaMax== 0 ) fit->SetParLimits(3*i+2, 0, 1.5*sigma[i]); // add 50% margin of sigma + if( sigmaMax < 0 ) fit->FixParameter(3*i+2, abs(sigmaMax)); + if( sigmaMax > 0 ) fit->SetParLimits(3*i+2, 0, sigmaMax); + } + + hspec->Fit("fit", "Rq"); + fit->Draw("same"); + + //=========== get the polynomial part + const Double_t* paraA = fit->GetParameters(); + const Double_t* paraE = fit->GetParErrors(); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + double bw = hspec->GetBinWidth(1); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.06); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + for( int i = 0; i < degPol + 1; i++){ + text.DrawLatex(0.6, 0.85 - 0.05*i, Form("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraA[3*nPeaks+i], paraE[3*nPeaks+i])); + } + + TF1 ** gFit = new TF1 *[nPeaks]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + if( degPol >= 0 ){ + TF1 *bg2 = new TF1("bg", polExp.Data(), xMin, xMax); + bg2->SetNpx(1000); + bg2->SetLineColor(markerBGColor); + bg2->SetLineWidth(1); + for( int i = 0; i < nPols + 1; i++){ + bg2->SetParameter(i, paraA[3*nPeaks+i]); + } + bg2->Draw("same"); + } + + cClickFitNGaussPol->cd(3); + PlotResidual(hspec, fit); + + cClickFitNGaussPol->cd(4); + + text.SetTextSize(0.05); + text.SetTextColor(2); + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } + +} + + + +void clickFitNGaussPolSub(TH1F * hist, int degPol, double sigmaMax = 0, double meanRange = 0){ + + printf("=========================================================\n"); + printf("= fit n-Gauss + Pol-%d BG using mouse click (method-2) =\n", degPol ); + printf("==========================================================\n"); + + recentFitMethod = "clickFitNGaussPolSub"; + + gStyle->SetOptStat(""); + gStyle->SetOptFit(0); + + TCanvas * cClickFitNGaussPolsub = NULL; + if( gROOT->FindObjectAny("cClickFitGaussPolsub") == NULL ){ + cClickFitNGaussPolsub = new TCanvas("cClickFitNGaussPol", Form("fit Gauss & Pol-%d by mouse click (sub) | clickFitGaussPolsub", degPol), 1400, 1200); + }else{ + delete gROOT->FindObjectAny("cClickFitNGaussPolsub") ; + cClickFitNGaussPolsub = new TCanvas("cClickFitNGaussPolsub", Form("fit Gauss & Pol-%d by mouse click (sub) | clickFitGaussPolsub", degPol), 1400, 1200); + } + cClickFitNGaussPolsub->Divide(1, 4); + for(int i = 1; i <= 4 ; i++){ + cClickFitNGaussPolsub->cd(i)->SetGrid(0,0); + } + + if(! cClickFitNGaussPolsub->GetShowEventStatus() ) cClickFitNGaussPolsub->ToggleEventStatus(); + cClickFitNGaussPolsub->cd(1); + + + hist->GetListOfFunctions()->Clear(); + ScaleAndDrawHist(hist, 0, 0); + TH1F* hspec = (TH1F*) hist->Clone(); + hspec->Sumw2(); + cClickFitNGaussPolsub->Update(); + cClickFitNGaussPolsub->Draw(); + + TLatex helpMsg; + helpMsg.SetNDC(); + helpMsg.SetTextFont(82); + helpMsg.SetTextSize(0.06); + helpMsg.SetTextColor(kRed); + helpMsg.DrawLatex(0.15, 0.8, "Click for peaks: (Double-click / x / Ctrl to end) "); + + + printf("--------- Click the histogram for peaks: (Double-click / x / Ctrl to end) \n"); + nClick = 0; + xPeakList.clear(); + yPeakList.clear(); + markerColor = 2; + markerStyle = 23; + peakFlag = 1; + cClickFitNGaussPolsub->cd(1)->SetCrosshair(1); + cClickFitNGaussPolsub->cd(1)->AddExec("ex", "Clicked()"); + tempHist = hist; + TObject * obj ; + do{ + obj = gPad->WaitPrimitive(); + if( obj == NULL ) break; + }while( obj != NULL); + + if( degPol >= 0 ){ + printf("--------- Click the histogram for Background: (Double-click / x / Ctrl to end) \n"); + + cClickFitNGaussPolsub->cd(1)->Clear(); + hist->Draw(); + helpMsg.SetTextColor(markerBGColor); + helpMsg.DrawLatex(0.15, 0.8, "Click for BG: (Double-click / x / Ctrl to end) "); + cClickFitNGaussPolsub->Update(); + cClickFitNGaussPolsub->Draw(); + + nClick = 0; + xBGList.clear(); + yBGList.clear(); + markerColor = markerBGColor; + markerStyle = 33; + peakFlag = 0; + do{ + obj = gPad->WaitPrimitive(); + if( obj == NULL ) break; + }while( obj != NULL); + } + cClickFitNGaussPolsub->cd(1)->DeleteExec("ex"); + cClickFitNGaussPolsub->cd(1)->SetCrosshair(0); + cClickFitNGaussPolsub->cd(1)->Clear(); + hist->Draw(); + + tempHist = NULL; + + if( xBGList.size() == 0 ) helpMsg.DrawLatex(0.15, 0.75, " No BG defined ! fitting could be problematics. "); + + cClickFitNGaussPolsub->Update(); + cClickFitNGaussPolsub->Draw(); + + nPols = degPol; + double xMin = hspec->GetXaxis()->GetXmin(); + double xMax = hspec->GetXaxis()->GetXmax(); + + TString polExp = "[0]"; + for( int i = 1; i < degPol + 1; i++) polExp += Form("+[%d]*TMath::Power(x,%d)", i, i ); + TF1 *bg = new TF1("bg", polExp.Data(), xMin, xMax); + bg->SetNpx(1000); + bg->SetLineColor(markerBGColor); + bg->SetLineWidth(1); + if( xBGList.size() > 0 ) { + printf("---------------- fit the BG with Pol-%d \n", nPols); + + TGraph * gBG = new TGraph((int) xBGList.size(), &xBGList[0], &yBGList[0]); + + for( int i = 0; i < degPol + 1; i++) bg->SetParameter(i, gRandom->Rndm()/TMath::Power(10, 3*i)); + + gBG->Fit("bg", "Rq"); + bg->Draw("same"); + + printf("--------------- Subtracting the BG \n"); + hspec->Add(bg, -1); + }else{ + for( int i = 0; i < nPols+1; i++) bg->SetParameter(i, 0.); + } + + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.06); + + double chi2BG = bg->GetChisquare(); + int ndfBG = bg->GetNDF(); + + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2BG/ndfBG)); + + //=========== get the polynomial BG + const Double_t* paraAt = bg->GetParameters(); + const Double_t* paraEt = bg->GetParErrors(); + + for( int i = 0; i < degPol + 1; i++){ + text.DrawLatex(0.6, 0.85 - 0.05*i, Form("%4s : %8.2f(%8.2f)\n", Form("p%d", i), paraAt[i], paraEt[i])); + } + + nPeaks = (int) xPeakList.size(); + if( sigmaMax == 0 ){ + printf("------------- Estimate sigma for each peak \n"); + sigma.clear(); + int binMin = hist->FindBin(xMin); + int binMax = hist->FindBin(xMax); + + for( int i = 0; i < nPeaks ; i++){ + int b0 = hist->FindBin(xPeakList[i]); + double estBG = bg->Eval(xPeakList[i]); + double sMin = (xMax-xMin)/5., sMax = (xMax-xMin)/5.; + //---- backward search, stop when + for( int b = b0-1 ; b > binMin ; b-- ){ + double y = hist->GetBinContent(b); + double x = hist->GetBinCenter(b); + if( y - (bg->Eval(x)) < (yPeakList[i]-estBG)/2. ) { + sMin = xPeakList[i] - hist->GetBinCenter(b); + break; + } + } + //---- forward search, stop when + for( int b = b0+1 ; b < binMax ; b++ ){ + double y = hist->GetBinContent(b); + double x = hist->GetBinCenter(b); + if( y - (bg->Eval(x)) < (yPeakList[i]-estBG)/2. ) { + sMax = hist->GetBinCenter(b) - xPeakList[i]; + break; + } + } + + double temp = TMath::Min(sMin, sMax); + /// When there are multiple peaks closely packed : + if( i > 0 && temp > 2.5 * sigma.back() ) temp = sigma.back(); + sigma.push_back(temp); + + printf("%2d | x : %8.2f | sigma(est) %f \n", i, xPeakList[i], sigma[i]); + + } + }else if( sigmaMax < 0 ){ + printf("========== use user input sigma : %f (fixed)\n", abs(sigmaMax)); + sigma.clear(); + for( int i = 0; i < nPeaks ; i++) sigma.push_back(abs(sigmaMax)); + }else if( sigmaMax > 0 ){ + printf("========== use user input sigma : %f/2. \n", sigmaMax/2.); + sigma.clear(); + for( int i = 0; i < nPeaks ; i++) sigma.push_back(sigmaMax/2.); + } + + printf("-------------- Fit the subtracted spectrum with %d-Gauss\n", nPeaks ); + cClickFitNGaussPolsub->cd(2); + hspec->Draw("hist"); + + int nPar = 3 * nPeaks; + double * para = new double[nPar]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = yPeakList[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = xPeakList[i]; + if( sigmaMax == 0){ + para[3*i+2] = sigma[i]; + }else if(sigmaMax < 0 ){ + para[3*i+2] = abs(sigmaMax); + }else if(sigmaMax > 0 ){ + para[3*i+2] = sigmaMax/2.; + } + } + + TF1 * fit = new TF1("fit", nGauss, xMin, xMax, nPar ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //limit parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + + if( meanRange <= 0 ) { + double dE1, dE2; + if( i == 0 ){ + dE2 = xPeakList[i+1] - xPeakList[i]; + dE1 = dE2; + }else if ( i == nPeaks-1 ){ + dE1 = xPeakList[i] - xPeakList[i-1]; + dE2 = dE1; + }else{ + dE1 = xPeakList[i] - xPeakList[i-1]; + dE2 = xPeakList[i+1] - xPeakList[i]; + } + fit->SetParLimits(3*i+1, xPeakList[i] - dE1 , xPeakList[i] + dE2 ); + }else{ + fit->SetParLimits(3*i+1, xPeakList[i] - meanRange/2. , xPeakList[i] + meanRange/2. ); + } + if( sigmaMax== 0 ) fit->SetParLimits(3*i+2, 0, 1.5*sigma[i]); // add 50% margin of sigma + if( sigmaMax < 0 ) fit->FixParameter(3*i+2, abs(sigmaMax)); + if( sigmaMax > 0 ) fit->SetParLimits(3*i+2, 0, sigmaMax); + } + + hspec->Fit("fit", "Rq"); + fit->Draw("same"); + + //=========== get the fit parameters + const Double_t* paraA = fit->GetParameters(); + const Double_t* paraE = fit->GetParErrors(); + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + double bw = hspec->GetBinWidth(1); + + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + TF1 ** gFit = new TF1 *[nPeaks]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + cClickFitNGaussPolsub->cd(3); + PlotResidual(hspec, fit); + + cClickFitNGaussPolsub->cd(4); + + text.SetTextSize(0.05); + text.SetTextColor(2); + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + BestFitCount.clear(); + BestFitMean.clear(); + BestFitSigma.clear(); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + + BestFitCount.push_back(paraA[3*i]/ bw); + BestFitMean.push_back(paraA[3*i+1]); + BestFitSigma.push_back(paraA[3*i+2]); + } +} + + +//######################################## +//#### fit N-Gauss with pol-1 BG at fixed for < 0 +//######################################## +void fitSpecial(TH1F * hist, TString fitFile = "AutoFit_para.txt"){ + + printf("================================================================\n"); + printf("================ Special fit for h074_82Kr =====================\n"); + printf(" * need the file input \n"); + printf("================================================================\n"); + + + bool isParaRead = loadFitParameters(fitFile); + if( !isParaRead ) { + printf("Please provide a valid input file\n"); + return; + } + + gStyle->SetOptStat(""); + gStyle->SetOptFit(0); + nPeaks = energy.size(); + nPols = 1; + + TCanvas * cFitSpecial = NewCanvas("cFitSpecial", "Fitting for h074_82Kr", 1, 3, 800, 300); + //if(! cFitSpecial->GetShowEventStatus() ) cFitSpecial->ToggleEventStatus(); + cFitSpecial->cd(1); + + ScaleAndDrawHist(hist, 0, 0); + + double xMin = hist->GetXaxis()->GetXmin(); + double xMax = hist->GetXaxis()->GetXmax(); + int xBin = hist->GetXaxis()->GetNbins(); + + printf("============= find the pol-1 background ..... \n"); + + TF1 * fitpol1 = new TF1("fitpol1", "pol1", xMin, -0.3); + fitpol1->SetParameter(0, gRandom->Rndm()); + fitpol1->SetParameter(1, gRandom->Rndm()); + + hist->Fit("fitpol1", "Rq"); + + double x0 = fitpol1->GetParameter(0); + double x1 = fitpol1->GetParameter(1); + + + int nPar = 3 * nPeaks + nPols + 1; + double * para = new double[nPar]; + for(int i = 0; i < nPeaks ; i++){ + para[3*i+0] = height[i] * 0.05 * TMath::Sqrt(TMath::TwoPi()); + para[3*i+1] = energy[i]; + para[3*i+2] = sigma[i]/2.; + } + + para[3*nPeaks+0] = x0; + para[3*nPeaks+1] = x1; + + + TF1 * fit = new TF1("fit", nGaussPol, xMin, xMax, nPar ); + fit->SetLineWidth(3); + fit->SetLineColor(1); + fit->SetNpx(1000); + fit->SetParameters(para); + + //fixing parameters + for( int i = 0; i < nPeaks; i++){ + fit->SetParLimits(3*i , 0, 1e9); + if( energyFlag[i] == 1 ) { + fit->FixParameter(3*i+1, energy[i]); + }else{ + fit->SetParLimits(3*i+1, lowE[i], highE[i]); + } + if( sigmaFlag[i] == 1 ) { + fit->FixParameter(3*i+2, sigma[i]); + }else{ + fit->SetParLimits(3*i+2, 0, sigma[i]); + } + } + + fit->FixParameter(3*nPeaks + 0, x0); + fit->FixParameter(3*nPeaks + 1, x1); + + hist->Fit("fit", "Rq"); + + //=========== get the polynomial part + const Double_t* paraA = fit->GetParameters(); + const Double_t* paraE = fit->GetParErrors(); + + TString polExp = "[0]"; + for( int i = 1; i < nPols + 1; i++){ + polExp += Form("+[%d]*TMath::Power(x,%d)", i, i ); + } + + TF1 * bg = new TF1("bg", polExp.Data(), xMin, xMax); + for( int i = 0; i < nPols + 1; i++){ + bg->SetParameter(i, paraA[3*nPeaks+i]); + } + bg->SetNpx(1000); + + for( int i = 0; i < nPols + 1; i++){ + printf("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraA[3*nPeaks+i], paraE[3*nPeaks+i]); + } + printf("====================================\n"); + + cFitSpecial->cd(1); + bg->Draw("same"); + + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.04); + text.SetTextColor(1); + + for( int i = 0; i < nPols + 1; i++){ + text.DrawLatex(0.6, 0.85 - 0.05*i, Form("%4s : %8.4e(%8.4e)\n", Form("p%d", i), paraA[3*nPeaks+i], paraE[3*nPeaks+i])); + } + + double chi2 = fit->GetChisquare(); + int ndf = fit->GetNDF(); + text.SetTextSize(0.06); + text.DrawLatex(0.15, 0.8, Form("#bar{#chi^{2}} : %5.3f", chi2/ndf)); + + + //GoodnessofFit(specS, fit); + + double bw = hist->GetBinWidth(1); + + for(int i = 0; i < nPeaks ; i++){ + printf(" %2d , count: %8.0f(%3.0f), mean: %8.4f(%8.4f), sigma: %8.4f(%8.4f) \n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2]); + } + printf("\n"); + + + const int nn = nPeaks; + TF1 ** gFit = new TF1 *[nn]; + for( int i = 0; i < nPeaks; i++){ + gFit[i] = new TF1(Form("gFit%d", i), "[0] * TMath::Gaus(x,[1],[2], 1)", xMin, xMax); + gFit[i]->SetParameter(0, paraA[3*i]); + gFit[i]->SetParameter(1, paraA[3*i+1]); + gFit[i]->SetParameter(2, paraA[3*i+2]); + gFit[i]->SetLineColor(i+1); + gFit[i]->SetNpx(1000); + gFit[i]->SetLineWidth(1); + gFit[i]->Draw("same"); + } + + cFitSpecial->Update(); + + cFitSpecial->cd(2); + PlotResidual(hist, fit); + + cFitSpecial->cd(3); + + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.05); + text.SetTextColor(2); + + text.DrawLatex(0.1, 0.9, Form(" %13s, %18s, %18s", "count", "mean", "sigma")); + + for( int i = 0; i < nPeaks; i++){ + text.DrawLatex(0.1, 0.8-0.05*i, Form(" %2d, %8.0f(%3.0f), %8.4f(%8.4f), %8.4f(%8.4f)\n", + i, + paraA[3*i] / bw, paraE[3*i] /bw, + paraA[3*i+1], paraE[3*i+1], + paraA[3*i+2], paraE[3*i+2])); + } + +} + +} + +#endif diff --git a/armory/ClassCorrParas.h b/armory/ClassCorrParas.h new file mode 100644 index 0000000..960862e --- /dev/null +++ b/armory/ClassCorrParas.h @@ -0,0 +1,175 @@ +#ifndef Parameters_H +#define Parameters_H + +//************************************** Correction parameters; +class CorrParas { +private: + + int defaultSize; + +public: + CorrParas(int defaultSize = 100){ + is_xn_OK = false; + is_xfxne_OK = false; + is_e_OK = false; + is_xScale_OK = false; + is_rdt_OK = false; + + this->defaultSize = defaultSize; + }; + + void LoadAllCorrections(){ + LoadXNCorr(); + LoadXFXN2ECorr(); + LoadECorr(); + LoadXScaleCorr(); + LoadRDTCorr(); + } + + void CheckCorrParasSize(size_t arraySize, size_t rdtSize){ + printf("------------ Check Correction parameter sizes\n"); + + if( is_xn_OK && xnCorr.size() < arraySize ) { + printf(" xnCorr [%zu] < array size %zu. Set xnCorr[1..99] = 1.0 \n", xnCorr.size(), arraySize); + for( int i = 0; i < defaultSize; i++ ) xnCorr.push_back(1.0); + is_xn_OK = false; + } + if( is_xfxne_OK && xfxneCorr.size() < arraySize ) { + printf(" xfxneCorr [%zu] < array size %zu. Set xfxneCorr[1..99] = (0.0, 1.0) \n", xfxneCorr.size(), arraySize); + for( int i = 0; i < defaultSize; i++ ) xfxneCorr.push_back({0.0, 1.0}); + is_xScale_OK = false; + } + if( is_e_OK && eCorr.size() < arraySize ) { + printf(" eCorr [%zu] < array size %zu. Set eCorr[1..99] = (1.0, 0.0) \n", xnCorr.size(), arraySize); + for( int i = 0; i < defaultSize; i++ ) eCorr.push_back({1.0, 0.0}); + is_e_OK = false; + } + if( is_xScale_OK && xScale.size() < arraySize ) { + printf(" xScale [%zu] < array size %zu. Set xScale[1..99] = 1.0 \n", xScale.size(), arraySize); + for( int i = 0; i < defaultSize; i++ ) xScale.push_back(1.0); + is_xScale_OK = false; + } + if( is_rdt_OK && rdtCorr.size() < rdtSize ) { + printf(" rdtCorr [%zu] < array size %zu. Set rdtScale[1..99] = (0.0, 1.0) \n", rdtCorr.size(), arraySize); + for( int i = 0; i < defaultSize; i++ ) rdtCorr.push_back({0.0, 1.0}); + is_rdt_OK = false; + } + + printf("------------ Done Check Corr. Para. Size.\n"); + } + + bool is_xn_OK; + bool is_xfxne_OK; + bool is_e_OK; + bool is_xScale_OK; + bool is_rdt_OK; + + std::vector xnCorr; //correction of xn to match xf + std::vector> xfxneCorr; //correction of xn and xf to match e + std::vector> eCorr; // correction to e, ch -> MeV + std::vector xScale; // correction of x to be (0,1) + std::vector> rdtCorr; // correction of rdt, ch -> MeV + + //~========================================= xf = xn correction + void LoadXNCorr(bool verbose = false, const char * fileName = "correction_xf_xn.dat"){ + printf(" loading xf-xn correction."); + xnCorr.clear(); + std::ifstream file; + file.open(fileName); + if( file.is_open() ){ + float a; + while( file >> a ) xnCorr.push_back(a); + printf(".......... done. size:%zu\n", xnCorr.size()); + is_xn_OK = true; + }else{ + for( int i = 0; i < defaultSize; i++ ) xnCorr.push_back(1.0); + printf(".......... fail. xnCorr[1..99] = 1.0\n"); + is_xn_OK = false; + } + file.close(); + if( verbose ) for(int i = 0; i < (int) xnCorr.size(); i++) printf("%2d | %10.3f\n", i, xnCorr[i]); + } + + //~========================================= X-Scale correction + void LoadXScaleCorr(bool verbose = false, const char * fileName = "correction_scaleX.dat"){ + printf(" loading x-Scale correction."); + xScale.clear(); + std::ifstream file; + file.open(fileName); + if( file.is_open() ){ + float a; + while( file >> a ) xScale.push_back(a); + printf("........ done. size:%zu\n", xScale.size()); + is_xScale_OK = true; + }else{ + for( int i = 0; i < defaultSize; i++ ) xScale.push_back(1.0); + printf("........ fail. xScale[1..99] = 1.0\n"); + is_xScale_OK = false; + } + file.close(); + if( verbose ) for(int i = 0; i < (int) xScale.size(); i++) printf("%2d | %10.3f\n", i, xnCorr[i]); + } + + //~========================================= e = xf + xn correction + void LoadXFXN2ECorr(bool verbose = false, const char * fileName = "correction_xfxn_e.dat"){ + printf(" loading xf/xn-e correction."); + xfxneCorr.clear(); + std::ifstream file; + file.open(fileName); + if( file.is_open() ){ + float a, b; + while( file >> a >> b) xfxneCorr.push_back({a, b}); + printf("........ done. size:%zu\n", xfxneCorr.size()); + is_xfxne_OK = true; + }else{ + for( int i = 0; i < defaultSize; i++ ) xfxneCorr.push_back({0.0, 1.0}); + printf("........ fail. xfxneCorr[1..99] = (0.0, 1.0)\n"); + is_xfxne_OK = false; + } + file.close(); + if( verbose ) for(int i = 0; i < (int) xfxneCorr.size(); i++) printf("%2d | %10.3f, %10.3f\n", i, xfxneCorr[i][0], xfxneCorr[i][1]); + } + + //~========================================= e correction + void LoadECorr(bool verbose = false, const char * fileName = "correction_e.dat"){ + printf(" loading e correction."); + eCorr.clear(); + std::ifstream file; + file.open(fileName); + if( file.is_open() ){ + float a, b; + while( file >> a >> b) eCorr.push_back( {a, b} ); // 1/a1, a0 , e' = e * a1 + a0 + printf(".............. done. size:%zu\n", eCorr.size()); + is_e_OK = true; + }else{ + for( int i = 0; i < defaultSize; i++ ) eCorr.push_back( {1.0, 0.0} ); + printf(".............. fail. eCorr[1..99] = (1.0, 0.0) \n"); + is_e_OK = false; + } + file.close(); + if( verbose ) for(int i = 0; i < (int) eCorr.size(); i++) printf("%2d | %10.3f, %10.3f\n", i, eCorr[i][0], eCorr[i][1]); + } + + //~========================================= rdt correction + void LoadRDTCorr(bool verbose = false, const char * fileName = "correction_rdt.dat"){ + printf(" loading rdt correction."); + rdtCorr.clear(); + std::ifstream file; + file.open(fileName); + if( file.is_open() ){ + float a, b; + while( file >> a >> b) rdtCorr.push_back({a, b}); + printf("............ done. size:%zu\n", rdtCorr.size()); + is_rdt_OK = true; + }else{ + for( int i = 0; i < defaultSize; i++ ) rdtCorr.push_back( {0.0, 1.0} ); + printf("............ fail. rdtCorr[1..99] = (0.0, 1.0)\n"); + is_rdt_OK = false; + } + file.close(); + if( verbose ) for(int i = 0; i < (int) rdtCorr.size(); i++) printf("%2d | %10.3f, %10.3f\n", i, rdtCorr[i][0], rdtCorr[i][1]); + } + +}; + +#endif \ No newline at end of file diff --git a/armory/ClassDetGeo.h b/armory/ClassDetGeo.h new file mode 100644 index 0000000..41b0bf5 --- /dev/null +++ b/armory/ClassDetGeo.h @@ -0,0 +1,268 @@ +#ifndef ClassDetGeo_H +#define ClassDetGeo_H + +#include /// for FILE +#include +#include +#include +#include + +#include "TMath.h" +#include "TString.h" +#include "TMacro.h" + +#include "AnalysisLib.h" + +struct Array{ + + bool enable; + + double detPerpDist; /// distance from axis + double detWidth; /// width + double detLength; /// length + double blocker; + double firstPos; /// meter + double eSigma; /// intrinsic energy resolution MeV + double zSigma; /// intrinsic position resolution mm + bool detFaceOut; ///detector_facing_Out_or_In + std::vector pos; /// realtive position in meter + int colDet, rowDet; /// colDet = number of different pos, rowDet, number of same pos + std::vector detPos; ///absolute position of detector + int numDet; /// colDet * rowDet + + double zMin, zMax; + + void DeduceAbsolutePos(){ + + colDet = pos.size(); + numDet = colDet * rowDet; + detPos.clear(); + + for(int id = 0; id < colDet; id++){ + if( firstPos > 0 ) detPos.push_back(firstPos + pos[id]); + if( firstPos < 0 ) detPos.push_back(firstPos - pos[colDet - 1 - id]); + // printf("%d | %f, %f \n", id, pos[id], detPos[id]); + } + + zMin = TMath::Min(detPos.front(), detPos.back()) - (firstPos < 0 ? detLength : 0); + zMax = TMath::Max(detPos.front(), detPos.back()) + (firstPos > 0 ? detLength : 0); + } + + void Print() const{ + + printf("------------------------------- Array\n"); + + for(int i = 0; i < colDet ; i++){ + if( firstPos > 0 ){ + printf("%d, %8.2f mm - %8.2f mm \n", i, detPos[i], detPos[i] + detLength); + }else{ + printf("%d, %8.2f mm - %8.2f mm \n", i, detPos[i] - detLength , detPos[i]); + } + } + + printf(" Blocker Position: %8.2f mm \n", firstPos > 0 ? firstPos - blocker : firstPos + blocker ); + printf(" First Position: %8.2f mm \n", firstPos); + printf(" number of det : %d = %d x %d (side x col) \n", numDet, rowDet, colDet); + printf(" detector facing : %s\n", detFaceOut ? "Out" : "In"); + printf(" energy resol.: %f MeV\n", eSigma); + printf(" pos-Z resol.: %f mm \n", zSigma); + } + +}; + +struct Auxillary{ + + //========== recoil + double detPos; // + double outerRadius; + double innerRadius; + + bool isCoincident; + + double detPos1 = 0; // virtual recoil + double detPos2 = 0; // virtual recoil + + //========== enum + double elumPos1 = 0; + double elumPos2 = 0; + + void Print() const { + printf("------------------------------- Auxillary\n"); + printf(" Recoil detector pos: %8.2f mm, radius: %6.2f - %6.2f mm \n", detPos, innerRadius, outerRadius); + + if( elumPos1 != 0 || elumPos2 != 0 || detPos1 != 0 || detPos2 != 0){ + printf("=================================== Virtual Detectors\n"); + if( elumPos1 != 0 ) printf(" Elum 1 pos.: %f mm \n", elumPos1); + if( elumPos2 != 0 ) printf(" Elum 2 pos.: %f mm \n", elumPos2); + if( detPos1 != 0 ) printf(" Recoil 1 pos.: %f mm \n", detPos1); + if( detPos2 != 0 ) printf(" Recoil 2 pos.: %f mm \n", detPos2); + printf("=====================================================\n"); + } + } + +}; + +class DetGeo { + +public: + DetGeo(){}; + DetGeo(TString detGeoTxt){ LoadDetectorGeo(detGeoTxt, false);} + DetGeo(TMacro * macro){ LoadDetectorGeo(macro, false);} + ~DetGeo(){}; + + double Bfield; /// T + int BfieldSign ; /// sign of B-field + double bore; /// bore , mm + + unsigned short numGeo; + double zMin, zMax; /// total range span of all arrays + + bool LoadDetectorGeo(TString fileName, bool verbose = true); + bool LoadDetectorGeo(TMacro * macro, bool verbose = true); + + //=================== array + std::vector array; + std::vector aux; + + void Print( int printArray = 0) ; // 0 = no print, -1 = print all, 1 = print only enabled + + short GetArrayID(int id){ + int detCount = 0; + for( int i = 0; i < numGeo; i ++ ){ + detCount += array[i].numDet; + if( id < detCount ) return i; + } + return -1; + } + +private: + +}; + +inline bool DetGeo::LoadDetectorGeo(TString fileName, bool verbose){ + + TMacro * haha = new TMacro(); + if( haha->ReadFile(fileName) > 0 ) { + if( LoadDetectorGeo(haha, verbose) ){ + delete haha; + return true; + }else{ + delete haha; + return false; + } + }else{ + delete haha; + return false; + } +} + +///Using TMacro to load the detectorGeo frist, +///this indrect method is good for loading detectorGeo from TMacro in root file +inline bool DetGeo::LoadDetectorGeo(TMacro * macro, bool verbose){ + + if( macro == NULL ) return false; + + TList * haha = macro->GetListOfLines(); + int numLine = (haha)->GetSize(); + + // for( int i = 0; i < 2 ; i++) array[i].pos.clear(); + + int detFlag = 0; + int detLine = 0; + + for( int i = 0 ; i < numLine; i++){ + + std::string line = macro->GetListOfLines()->At(i)->GetName(); + + if( AnalysisLib::isEmptyOrSpaces(line) ) continue; + + std::vector str = AnalysisLib::SplitStr(line, " "); + + // printf("%3d | %s\n", i, str[0].c_str()); + if( str[0].find("#//") != std::string::npos ) continue; + if( str[0].find("####") != std::string::npos ) break; + if( str[0].find("#===") != std::string::npos ) { + detFlag ++; + array.push_back(Array()); + aux.push_back(Auxillary()); + detLine = 0; + continue;; + } + + if( detFlag == 0 ){ + if ( detLine == 0 ) { + Bfield = atof(str[0].c_str()); + BfieldSign = Bfield > 0 ? 1: -1; + } + if ( detLine == 1 ) bore = atof(str[0].c_str()); + } + + if( detFlag > 0){ + unsigned short ID = detFlag - 1; + if ( detLine == 0 ) array[ID].enable = str[0] == "true" ? true : false; + if ( detLine == 1 ) aux[ID].detPos = atof(str[0].c_str()); + if ( detLine == 2 ) aux[ID].innerRadius = atof(str[0].c_str()); + if ( detLine == 3 ) aux[ID].outerRadius = atof(str[0].c_str()); + if ( detLine == 4 ) aux[ID].isCoincident = str[0] == "true" ? true : false; + if ( detLine == 5 ) aux[ID].detPos1 = atof(str[0].c_str()); + if ( detLine == 6 ) aux[ID].detPos2 = atof(str[0].c_str()); + if ( detLine == 7 ) aux[ID].elumPos1 = atof(str[0].c_str()); + if ( detLine == 8 ) aux[ID].elumPos2 = atof(str[0].c_str()); + if ( detLine == 9 ) array[ID].detPerpDist = atof(str[0].c_str()); + if ( detLine == 10 ) array[ID].detWidth = atof(str[0].c_str()); + if ( detLine == 11 ) array[ID].detLength = atof(str[0].c_str()); + if ( detLine == 12 ) array[ID].blocker = atof(str[0].c_str()); + if ( detLine == 13 ) array[ID].firstPos = atof(str[0].c_str()); + if ( detLine == 14 ) array[ID].eSigma = atof(str[0].c_str()); + if ( detLine == 15 ) array[ID].zSigma = atof(str[0].c_str()); + if ( detLine == 16 ) array[ID].detFaceOut = str[0] == "Out" ? true : false; + if ( detLine == 17 ) array[ID].rowDet = atoi(str[0].c_str()); + if ( detLine >= 18 ) array[ID].pos.push_back(atof(str[0].c_str())); + } + + detLine ++; + } + + zMin = 99999; + zMax = -99999; + numGeo = 0; + + for( int i = 0; i < detFlag; i ++ ){ + array[i].DeduceAbsolutePos(); + if (array[i].enable ) { + numGeo ++; + double zmax = TMath::Max(array[i].zMin, array[i].zMax); + double zmin = TMath::Min(array[i].zMin, array[i].zMax); + if( zmax > zMax ) zMax = zmax; + if( zmin < zMin ) zMin = zmin; + } + } + + if( verbose ) Print(false); + + return true; + +} + +inline void DetGeo::Print(int printArray){ + + printf("#####################################################\n"); + printf(" B-field : %8.2f T, %s\n", Bfield, Bfield > 0 ? "out of plan" : "into plan"); + printf(" Bore : %8.2f mm\n", bore); + printf(" No. of det. Set. : %zu \n", array.size()); + + printf(" z-Min : %8.2f mm\n", zMin); + printf(" z-Max : %8.2f mm\n", zMax); + if( printArray != 0 ) { + for( size_t i = 0; i < array.size() ; i++){ + if( printArray > 0 && !array[i].enable ) continue; + printf("================================= %zu-th Detector Info (%s)\n", i, array[i].enable ? "enabled" : "disabled"); + array[i].Print(); + aux[i].Print(); + } + } + printf("#####################################################\n"); + +} + +#endif \ No newline at end of file diff --git a/armory/ClassReactionConfig.h b/armory/ClassReactionConfig.h new file mode 100644 index 0000000..6c302b6 --- /dev/null +++ b/armory/ClassReactionConfig.h @@ -0,0 +1,345 @@ +#ifndef ClassReactionConfig_H +#define ClassReactionConfig_H + +#include /// for FILE +#include +#include +#include +#include + +#include "TMath.h" +#include "TString.h" +#include "TMacro.h" + +#include "AnalysisLib.h" +#include "../Cleopatra/ClassIsotope.h" + +struct Recoil { + + Isotope light; + unsigned short lightA, lightZ; + unsigned short heavyA, heavyZ; + + std::string lightStoppingPowerFile = ""; ///stopping_power_for_light_recoil + std::string heavyStoppingPowerFile = ""; ///stopping_power_for_heavy_recoil + + bool isDecay = false; ///isDacay + unsigned short decayA = 0; ///decayNucleus_A + unsigned short decayZ = 0; ///decayNucleus_Z + + void Print() const { + printf(" light : A = %3d, Z = %2d \n", lightA, lightZ); + printf(" heavy : A = %3d, Z = %2d \n", heavyA, heavyZ); + + printf(" light stopping file : %s \n", lightStoppingPowerFile.c_str()); + printf(" heavy stopping file : %s \n", heavyStoppingPowerFile.c_str()); + printf(" is simulate decay : %s \n", isDecay ? "Yes" : "No"); + if( isDecay ){ + printf(" heavy decay : A = %d, Z = %d \n", decayA, decayZ); + } + } + +}; + +struct EnergyLevel{ + + float Ex, xsec, SF, sigma; + + EnergyLevel(float Ex, float xsec, float SF, float sigma) { + this->Ex = Ex; + this->xsec = xsec; + this->SF = SF; + this->sigma = sigma; + } + + void Print(std::string str) const { + printf("%11.3f %8.1f %5.1f %5.3f%s", Ex, xsec, SF, sigma, str.c_str() ); + } + +}; + + +struct ExcitedEnergies { + + std::vector ExList; + + void Clear(){ + ExList.clear(); + } + + void Add(float Ex, float xsec, float SF, float sigma){ + ExList.push_back( EnergyLevel(Ex, xsec, SF, sigma)); + } + + void Print() const { + printf("Energy[MeV] Rel.Xsec SF sigma\n"); + for( size_t i = 0; i < ExList.size(); i++){ + ExList[i].Print("\n"); + } + } + +}; + +class ReactionConfig { + +public: + ReactionConfig(){} + ReactionConfig(TString configTxt){ LoadReactionConfig(configTxt);} + ReactionConfig(TMacro * macro){ LoadReactionConfig(macro);} + ~ReactionConfig(){} + + Isotope beam; + unsigned short beamA, beamZ; + float beamEx; ///excitation_energy_of_A[MeV] + float beamEnergy; ///MeV/u + float beamEnergySigma; ///beam-energy_sigma_in_MeV/u + float beamTheta; ///beam-angle_in_mrad + float beamThetaSigma; ///beam-emittance_in_mrad + float beamX; ///x_offset_of_Beam_in_mm + float beamY; ///y_offset_of_Beam_in_mm + + Isotope target; + unsigned short targetA, targetZ; + bool isTargetScattering; ///isTargetScattering + float targetDensity; ///target_density_in_g/cm3 + float targetThickness; ///targetThickness_in_cm + std::string beamStoppingPowerFile; ///stopping_power_for_beam + + std::vector recoil; + std::vector exList; + + int numEvents; ///number_of_Event_being_generated + bool isRedo; ///isReDo + + void SetReactionSimple(int beamA, int beamZ, + int targetA, int targetZ, + int recoilA, int recoilZ, + float beamEnergy_AMeV); + + bool LoadReactionConfig(TString fileName); + bool LoadReactionConfig(TMacro * macro); + + void Print(int ID = -1, bool withEx = true) const; + +private: + +}; + +inline void ReactionConfig::SetReactionSimple(int beamA, int beamZ, + int targetA, int targetZ, + int recoilA, int recoilZ, + float beamEnergy_AMeV){ + + this->beamA = beamA; + this->beamZ = beamZ; + this->targetA = targetA; + this->targetZ = targetZ; + + this->recoil.push_back(Recoil()); + + this->recoil.back().lightA = recoilA; + this->recoil.back().lightZ = recoilZ; + recoil.back().heavyA = this->beamA + this->targetA - recoil.back().lightA; + recoil.back().heavyZ = this->beamZ + this->targetZ - recoil.back().lightZ; + + beamEnergy = beamEnergy_AMeV; + beamEnergySigma = 0; + beamTheta = 0; + beamThetaSigma = 0; + beamX = 0; + beamY = 0; + +} + +inline bool ReactionConfig::LoadReactionConfig(TString fileName){ + TMacro * haha = new TMacro(); + if( haha->ReadFile(fileName) > 0 ) { + if( LoadReactionConfig(haha) ){ + delete haha; + return true; + }else{ + delete haha; + return false; + } + }else{ + delete haha; + return false; + } +} + +inline bool ReactionConfig::LoadReactionConfig(TMacro * macro){ + + if( macro == NULL ) return false; + + int recoilFlag = 0; + int recoilLine = 0; + + int numLine = macro->GetListOfLines()->GetSize(); + + for( int i = 0; i < numLine; i ++){ + + std::string line = macro->GetListOfLines()->At(i)->GetName(); + if( AnalysisLib::isEmptyOrSpaces(line) ) continue; + + std::vector str =AnalysisLib::SplitStr(line, " "); + // printf("%d |%s|%d|%d\n", i, str[0].c_str(), recoilFlag, recoilLine); + + if( str[0].find("####") != std::string::npos ) break; + if( str[0].find("#---") != std::string::npos ) continue; + if( str[0].find("#===") != std::string::npos ) { + recoilFlag ++; + recoilLine = 0; + recoil.push_back(Recoil()); + exList.push_back(ExcitedEnergies()); + continue; + } + + if( recoilFlag == 0 ){ + if( recoilLine == 0 ) { + beam.SetIsoByName(str[0]); + beamA = beam.A; + beamZ = beam.Z; + } + if( recoilLine == 1 ) beamEx = atoi(str[0].c_str()); + if( recoilLine == 2 ) beamEnergy = atof(str[0].c_str()); + if( recoilLine == 3 ) beamEnergySigma = atof(str[0].c_str()); + if( recoilLine == 4 ) beamTheta = atof(str[0].c_str()); + if( recoilLine == 5 ) beamThetaSigma = atof(str[0].c_str()); + if( recoilLine == 6 ) beamX = atof(str[0].c_str()); + if( recoilLine == 7 ) beamY = atof(str[0].c_str()); + + if( recoilLine == 8 ) { + target.SetIsoByName(str[0]); + targetA = target.A; + targetZ = target.Z; + } + if( recoilLine == 9 ) isTargetScattering = str[0].compare("true") == 0 ? true: false; + if( recoilLine == 10 ) targetDensity = atof(str[0].c_str()); + if( recoilLine == 11 ) targetThickness = atof(str[0].c_str()); + if( recoilLine == 12 ) beamStoppingPowerFile = str[0]; + + if( recoilLine == 13 ) numEvents = atoi(str[0].c_str()); + if( recoilLine == 14 ) isRedo = str[0].compare("true" ) == 0 ? true : false; + } + + if( recoilFlag > 0 ){ + + unsigned ID = recoilFlag - 1; + if( recoilLine == 0 ) { + recoil[ID].light.SetIsoByName(str[0]); + recoil[ID].lightA = recoil[ID].light.A; + recoil[ID].lightZ = recoil[ID].light.Z; + } + if( recoilLine == 1 ) recoil[ID].lightStoppingPowerFile = str[0]; + if( recoilLine == 2 ) recoil[ID].heavyStoppingPowerFile = str[0]; + if( recoilLine == 3 ) recoil[ID].isDecay = str[0].compare("true") == 0 ? true : false; + if( recoilLine == 4 ) recoil[ID].decayA = atoi(str[0].c_str()); + if( recoilLine == 5 ) recoil[ID].decayZ = atoi(str[0].c_str()); + + if( recoilLine > 5 && str.size() == 4) { + if( str[0].find('#') != std::string::npos) continue; + if( str[0] == "IAEA"){ + + recoil[ID].heavyA = beamA + targetA - recoil[ID].lightA; + recoil[ID].heavyZ = beamZ + targetZ - recoil[ID].lightZ; + printf(">>>>>>>>>>>>> Retrieving Ex data from IAEA website....\n"); + std::string scriptPath = "../WebSimHelper/getEx.py " + std::to_string(recoil[ID].heavyA) + " " + std::to_string(recoil[ID].heavyZ) + " " + str[2]; + std::vector output = AnalysisLib::executePythonScript(scriptPath); + + if( output.size() > 1 ){ + for( size_t dudu = 1 ; dudu < output.size(); dudu ++ ){ + printf("%s", output[dudu].c_str()); + std::vector dondon = AnalysisLib::SplitStr(output[dudu], " "); + + if( str[1].find("all") == std::string::npos){ // only comfirm states + if(dondon[2].find(')') != std::string::npos ) continue; + if(dondon[2].find('N') != std::string::npos ) continue; + // printf("kdlsakdas ---- %s\n", str[1].c_str()); + + if(str[1] == "+" && dondon[2].find('+') != std::string::npos ){ + // printf(" only comfim + states\n"); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); + } + if(str[1] == "-" && dondon[2].find('-') != std::string::npos ){ + // printf(" only comfim - states\n"); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); + } + if( str[1] == "known" ){ + // printf(" All comfim state\n"); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); + } + + }else{ + if(str[1] == "+all" && dondon[2].find('+') != std::string::npos ){ + // printf(" All state : %s\n", str[1].c_str()); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); + } + if(str[1] == "-all" && dondon[2].find('-') != std::string::npos ){ + // printf(" All state : %s\n", str[1].c_str()); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); + } + if( str[1] == "all" ){ + // printf(" All state \n"); + exList[ID].Add( atoi(dondon[1].c_str())/1000., 1.0, 1.0, atoi(str[3].c_str())); + } + + } + } + }else{ + printf(" No states found from IAEA database, assume ground state."); + exList[ID].Add( 0, 1.0, 1.0, 0.01); + } + }else{ + exList[ID].Add( atoi(str[0].c_str()), atoi(str[1].c_str()), atoi(str[2].c_str()), atoi(str[3].c_str())); + } + } + + } + + recoilLine ++; + + } + + for( size_t i = 0; i < recoil.size(); i++){ + recoil[i].heavyA = beamA + targetA - recoil[i].lightA; + recoil[i].heavyZ = beamZ + targetZ - recoil[i].lightZ; + } + return true; +} + +inline void ReactionConfig::Print(int ID, bool withEx) const{ + + printf("#####################################################\n"); + + printf("number of Simulation Events : %d \n", numEvents); + printf(" is Redo until hit array : %s \n", isRedo ? "Yes" : "No"); + + printf("================================= Beam\n"); + printf(" beam : A = %3d, Z = %2d, Ex = %.2f MeV\n", beamA, beamZ, beamEx); + printf(" beam Energy : %.2f +- %.2f MeV/u, dE/E = %5.2f %%\n", beamEnergy, beamEnergySigma, beamEnergySigma/beamEnergy); + printf(" Angle : %.2f +- %.2f mrad\n", beamTheta, beamThetaSigma); + printf(" offset : (x,y) = (%.2f, %.2f) mmm \n", beamX, beamY); + + printf("================================= Target\n"); + printf(" target : A = %3d, Z = %2d \n", targetA, targetZ); + printf(" enable scattering : %s \n", isTargetScattering ? "Yes" : "No"); + if(isTargetScattering){ + printf(" target density : %.f g/cm3\n", targetDensity); + printf(" thickness : %.f cm\n", targetThickness); + printf(" beam stopping file : %s \n", beamStoppingPowerFile.c_str()); + } + + printf("================================= Number of recoil reactions : %zu\n", recoil.size()); + for( int i = 0; i < (int)recoil.size(); i ++ ){ + if( ID == i || ID < 0 ){ + printf("------------------------------------------ Recoil-%d\n", i); + recoil[i].Print(); + if( withEx ) exList[i].Print(); + } + } + + + printf("#####################################################\n"); +} + +#endif \ No newline at end of file diff --git a/armory/ClassReactionParas_tobeKill.h b/armory/ClassReactionParas_tobeKill.h new file mode 100644 index 0000000..7abdf74 --- /dev/null +++ b/armory/ClassReactionParas_tobeKill.h @@ -0,0 +1,158 @@ +#ifndef ReactionParameters_H +#define ReactionParameters_H + +#include "ClassDetGeo.h" + +class ReactionParas{ + +public: + ReactionParas(); + + double Et; // total energy in CM frame + double beta; // Lorentz beta from Lab to CM + double gamma; // Lorentz gamma from Lab to CM + double alpha; // E-Z slope / beta + double G; //The G-coefficient.... + double massB; // heavy mass + double q; // charge of light particle + double mass; //light mass + bool hasReactionPara; + + double detPrepDist; + + void LoadReactionParas(bool verbose = false); + std::pair CalExTheta(double e, double z) + +}; + +ReactionParas::ReactionParas(){ + +} + +//~========================================= reaction parameters +inline void ReactionParas::LoadReactionParas(bool verbose = false){ + + //check is the transfer.root is using the latest reactionConfig.txt + //sicne reaction.dat is generated as a by-product of transfer.root + //TFile * transfer = new TFile("transfer.root"); + //TString aaa1 = ""; + //TString aaa2 = ""; + //if( transfer->IsOpen() ){ + // TMacro * reactionConfig = (TMacro *) transfer->FindObjectAny("reactionConfig"); + // TMacro presentReactionConfig ("reactionConfig.txt"); + // aaa1 = ((TMD5*) reactionConfig->Checksum())->AsString(); + // aaa2 = ((TMD5*) presentReactionConfig.Checksum())->AsString(); + //} + //printf("%s\n", aaa1.Data()); + //printf("%s\n", aaa2.Data()); + + //if( aaa1 != aaa2 ) { + // printf("########################## recalculate transfer.root \n"); + // system("../Cleopatra/Transfer"); + // printf("########################## transfer.root updated\n"); + //} + + std::string fileName; + + detPrepDist = Array::detPerpDist; + + printf(" loading reaction parameters"); + std::ifstream file; + file.open(fileName.c_str()); + hasReactionPara = false; + if( file.is_open() ){ + std::string x; + int i = 0; + while( file >> x ){ + if( x.substr(0,2) == "//" ) continue; + if( i == 0 ) mass = atof(x.c_str()); + if( i == 1 ) q = atof(x.c_str()); + if( i == 2 ) beta = atof(x.c_str()); + if( i == 3 ) Et = atof(x.c_str()); + if( i == 4 ) massB = atof(x.c_str()); + i = i + 1; + } + printf("........ done.\n"); + + hasReactionPara = true; + alpha = 299.792458 * abs(detGeo.Bfield) * q / TMath::TwoPi()/1000.; //MeV/mm + gamma = 1./TMath::Sqrt(1-beta * beta); + G = alpha * gamma * beta * detPrepDist ; + + if( verbose ){ + printf("\tmass-b : %f MeV/c2 \n", mass); + printf("\tcharge-b : %f \n", q); + printf("\tE-total : %f MeV \n", Et); + printf("\tmass-B : %f MeV/c2 \n", massB); + printf("\tbeta : %f \n", beta); + printf("\tB-field : %f T \n", detGeo.Bfield); + printf("\tslope : %f MeV/mm \n", alpha * beta); + printf("\tdet radius: %f mm \n", detPrepDist); + printf("\tG-coeff : %f MeV \n", G); + printf("=====================================================\n"); + } + + }else{ + printf("........ fail.\n"); + } + file.close(); + +} + +inline std::pair ReactionParas::CalExTheta(double e, double z){ + + ReactionParas * reactParas = nullptr; + + if( detGeo.array1.zMin <= z && z <= detGeo.array1.zMax ){ + reactParas = &reactParas1; + if( !hasReactionPara) return {TMath::QuietNaN(), TMath::QuietNaN()}; + } + + if( detGeo.array2.zMin <= z && z <= detGeo.array2.zMax ){ + reactParas = &reactParas2; + if( !hasReactionPara) return {TMath::QuietNaN(), TMath::QuietNaN()}; + } + + double Ex = TMath::QuietNaN(); + double thetaCM = TMath::QuietNaN(); + + double y = e + mass; // to give the KE + mass of proton; + double Z = alpha * gamma * beta * z; + double H = TMath::Sqrt(TMath::Power(gamma * beta,2) * (y*y - mass * mass) ) ; + + if( TMath::Abs(Z) < H ) { + ///using Newton's method to solve 0 == H * sin(phi) - G * tan(phi) - Z = f(phi) + double tolerrence = 0.001; + double phi = 0; ///initial phi = 0 -> ensure the solution has f'(phi) > 0 + double nPhi = 0; /// new phi + + int iter = 0; + do{ + phi = nPhi; + nPhi = phi - (H * TMath::Sin(phi) - G * TMath::Tan(phi) - Z) / (H * TMath::Cos(phi) - G /TMath::Power( TMath::Cos(phi), 2)); + iter ++; + if( iter > 10 || TMath::Abs(nPhi) > TMath::PiOver2()) break; + }while( TMath::Abs(phi - nPhi ) > tolerrence); + phi = nPhi; + + /// check f'(phi) > 0 + double Df = H * TMath::Cos(phi) - G / TMath::Power( TMath::Cos(phi),2); + if( Df > 0 && TMath::Abs(phi) < TMath::PiOver2() ){ + double K = H * TMath::Sin(phi); + double x = TMath::ACos( mass / ( y * gamma - K)); + double momt = mass * TMath::Tan(x); /// momentum of particel b or B in CM frame + double EB = TMath::Sqrt(mass * mass + Et * Et - 2 * Et * TMath::Sqrt(momt*momt + mass * mass)); + Ex = EB - massB; + + double hahaha1 = gamma * TMath::Sqrt(mass * mass + momt * momt) - y; + double hahaha2 = gamma * beta * momt; + thetaCM = TMath::ACos(hahaha1/hahaha2) * TMath::RadToDeg(); + + } + } + return std::make_pair(Ex, thetaCM); + +} + + +#endif \ No newline at end of file diff --git a/armory/GeneralSort.C b/armory/GeneralSort.C new file mode 100644 index 0000000..8bd25a9 --- /dev/null +++ b/armory/GeneralSort.C @@ -0,0 +1,199 @@ +#define GeneralSort_cxx + +#include +#include +#include + +#include "GeneralSort.h" + +#include +#include +#include +#include +#include + +Long64_t processedEntry = 0; +float lastPercentage = 0; + +//^############################################################## +Bool_t GeneralSort::Process(Long64_t entry){ + + if( entry < 1 ) printf("============================== start processing data\n"); + + ///initialization + for( int i = 0; i < mapping::nDetType; i++){ + if( mapping::detNum[i] == 0 ) continue; + for( int j = 0; j < mapping::detNum[i]; j++){ + eE[i][j] = TMath::QuietNaN(); + eT[i][j] = 0; + + if( isTraceExist && traceMethod > 1){ + teE[i][j] = TMath::QuietNaN(); + teT[i][j] = TMath::QuietNaN(); + teR[i][j] = TMath::QuietNaN(); + } + } + } + + b_evID->GetEntry(entry); + b_multi->GetEntry(entry); + b_bd->GetEntry(entry); + b_ch->GetEntry(entry); + b_e->GetEntry(entry); + b_e_t->GetEntry(entry); + + for( unsigned int i = 0 ; i < multi; i++){ + + int detID = mapping::map[bd[i]][ch[i]]; + if( detID < 0 ) continue; + int detType = mapping::FindDetTypeIndex(detID); + int reducedDetID = detID - (detID/100) * 100; + eE[detType][reducedDetID] = e[i] * mapping::detParity[detType]; + eT[detType][reducedDetID] = e_t[i]; + } + + //@===================================== Trace + if( isTraceExist && traceMethod > 0 ){ + + b_tl->GetEntry(entry); + b_trace->GetEntry(entry); + + int countTrace = 0; + + arr->Clear("C"); + + for( unsigned int i = 0; i < multi; i++){ + int detID = mapping::map[bd[i]][ch[i]]; + if( detID < 0 ) continue; + + int traceLength = tl[i]; + gTrace = (TGraph*) arr->ConstructedAt(countTrace, "C"); + gTrace->Clear(); + gTrace->Set(traceLength); + + gTrace->SetTitle(Form("ev:%llu,nHit:%d,id:%d,len:%d", evID, i, detID, traceLength)); + countTrace ++; + + for( int k = 0 ; k < traceLength; k++){ + gTrace->SetPoint(k, k, trace[i][k]); + } + + //***=================== fit + if( traceMethod == 2){ + + int detType = mapping::FindDetTypeIndex(detID); + if( mapping::detNum[detType] == 0 ) continue; + + //TODO use a blackList + //if( mapping::detTypeName[detType] != "rdt") continue; + + gFit->SetRange(0, traceLength); + + gFit->SetParameter(0, e[i]); + gFit->SetParameter(1, 100); //triggerTime //TODO how to not hardcode? + gFit->SetParameter(2, 10); //rise time //TODO how to not hardcode? + gFit->SetParameter(3, trace[i][0]); //base line + gFit->SetParameter(4, 100); // decay //TODO how to not hardcode? + gFit->SetParameter(5, -0.01); // pre-rise slope //TODO how to not hardcode? + + gFit->SetParLimits(1, 85, 125); //raneg for the trigger time + gFit->SetParLimits(5, -2, 0); + + gTrace->Fit("gFit", "QR", "", 0, traceLength); + + int reducedDetID = detID - (detID/100) * 100; + teE[detType][reducedDetID] = gFit->GetParameter(0); + teT[detType][reducedDetID] = gFit->GetParameter(1); + teR[detType][reducedDetID] = gFit->GetParameter(2); + + // delete gFit; + // gFit = nullptr; + } + + //***=================== Trapezoid filter + if( traceMethod == 3){ + //TODO + } + + } + + } + + if( !isParallel){ + processedEntry ++; + float percentage = processedEntry*100/NumEntries; + if( percentage >= lastPercentage ) { + TString msg; msg.Form("%lu", NumEntries); + int len = msg.Sizeof(); + printf("Processed : %*lld, %3.0f%% | Elapsed %6.1f sec | expect %6.1f sec\n\033[A\r", len, entry, percentage, stpWatch.RealTime(), stpWatch.RealTime()/percentage*100); + stpWatch.Start(kFALSE); + lastPercentage = percentage + 1.0; + if( lastPercentage >= 100) printf("\n"); + + } + } + + newSaveTree->Fill(); + + return kTRUE; +} + +//^############################################################## +void GeneralSort::Terminate(){ + + printf("=============================== %s\n", __func__); + + // CleanUpMemory(); //? Should Clean? + + if( !isParallel){ + stpWatch.Start(kFALSE); + saveFile->cd(); + // newSaveTree->Print("toponly"); + newSaveTree->Write(); + saveFile->Close(); + } + + //get entries + saveFile = TFile::Open(saveFileName); + if( saveFile->IsOpen() ){ + TTree * tree = (TTree*) saveFile->FindObjectAny("gen_tree"); + int validCount = tree->GetEntries(); + saveFile->Close(); + printf("=========================================================================\n"); + PrintTraceMethod(); + printf("----- saved as \033[1;33m%s\033[0m. valid event: %d\n", saveFileName.Data() , validCount); + printf("=========================================================================\n"); + } +} + +//^############################################################## +void GeneralSort::Begin(TTree * tree){ + + printf( "================================================================================\n"); + printf( "============================ SOLARIS GeneralSort.C =========================\n"); + printf( "================================================================================\n"); + + mapping::PrintMapping(); + + DecodeOption(); + if(!isParallel) { + tree->GetEntriesFast(); + stpWatch.Start(); + } + +} + +void GeneralSort::SlaveBegin(TTree * /*tree*/){ +} + +void GeneralSort::SlaveTerminate(){ + printf("============= %s\n", __func__); + if( isParallel){ + printf("%s::SaveTree\n", __func__); + saveFile->cd(); + newSaveTree->Write(); + fOutput->Add(proofFile); + saveFile->Close(); + printf("---- closing this worker\n"); + } +} \ No newline at end of file diff --git a/armory/GeneralSort.h b/armory/GeneralSort.h new file mode 100644 index 0000000..afb8a5a --- /dev/null +++ b/armory/GeneralSort.h @@ -0,0 +1,359 @@ +#ifndef GeneralSort_h +#define GeneralSort_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//^######################################### Skip list for trace fitting +//TODO + +/*********************************======= + +the sequence of each method + +1) Begin (master, stdout) + 2) SlaveBegin (slave) + 3) Init + 4) Notify + 5) Process (looping each event) + 6) SlaveTerminate +7) Terminate + +// variable in the Master will not pass to Slave + +******************************************/ + +/// in Process_Sort, copy the Mapping.h to ~/.proof/working/ +#include "../working/Mapping.h" + +//^######################################### FIT FUNCTION +const int numPara = 6; +double fitFunc(double * x, double * par){ + /// par[0] = A + /// par[1] = t0 + /// par[2] = rise time + /// par[3] = baseline + /// par[4] = decay + /// par[5] = pre-rise slope + + if( x[0] < par[1] ) return par[3] + par[5] * (x[0]-par[1]); + + return par[3] + par[0] * (1 - TMath::Exp(- (x[0] - par[1]) / par[2]) ) * TMath::Exp(- (x[0] - par[1]) / par[4]); +} + +TStopwatch stpWatch; + +//^######################################### Class definition +// Header file for the classes stored in the TTree if any. +class GeneralSort : public TSelector { +public : + TTree *fChain; //!pointer to the analyzed TTree or TChain + +// Fixed size dimensions of array or collections stored in the TTree if any. + + // Declaration of leaf types + ULong64_t evID; + UInt_t multi; + UShort_t bd[100]; //[multi] + UShort_t ch[100]; //[multi] + UShort_t e[100]; //[multi] + ULong64_t e_t[100]; //[multi] + UShort_t lowFlag[100]; //[multi] + UShort_t highFlag[100]; //[multi] + Int_t tl[100]; //[multi] + Int_t trace[100][2500]; //[multi] + + // List of branches + TBranch *b_evID; //! + TBranch *b_multi; //! + TBranch *b_bd; //! + TBranch *b_ch; //! + TBranch *b_e; //! + TBranch *b_e_t; //! + TBranch *b_lowFlag; //! + TBranch *b_highFlag; //! + TBranch *b_tl; //! + TBranch *b_trace; //! + + GeneralSort(TTree * /*tree*/ =0) : fChain(0) { + printf("constructor :: %s\n", __func__); + + isTraceExist = false; + traceMethod = 0; // 0 = ignore trace, 1 = no trace fit, 2 = fit, 3 = trapezoid + + isParallel = false; + + saveFile = nullptr; + newSaveTree = nullptr; + + eE = nullptr; + eT = nullptr; + + arr = nullptr; + gTrace = nullptr; + gFit = nullptr; + arrTrapezoid = nullptr; + gTrapezoid = nullptr; + + teE = nullptr; + teT = nullptr; + teR = nullptr; + + } + virtual ~GeneralSort() { } + virtual Int_t Version() const { return 2; } + virtual void Begin(TTree *tree); + virtual void SlaveBegin(TTree *tree); + virtual void Init(TTree *tree); + virtual Bool_t Notify(); + virtual Bool_t Process(Long64_t entry); + virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; } + virtual void SetOption(const char *option) { fOption = option; } + virtual void SetObject(TObject *obj) { fObject = obj; } + virtual void SetInputList(TList *input) { fInput = input; } + virtual TList *GetOutputList() const { return fOutput; } + virtual void SlaveTerminate(); + virtual void Terminate(); + + ClassDef(GeneralSort,0); + + bool isTraceExist; + int traceMethod; + + void CleanUpMemory(); + + void SetTraceMethod(int methodID) {traceMethod = methodID;} + void PrintTraceMethod(); + + void SetUpTree(); + void DecodeOption(); + bool isParallel; + + unsigned long NumEntries; + + TString saveFileName; + TFile * saveFile; //! + TProofOutputFile * proofFile; //! + TTree * newSaveTree; //! + + Float_t ** eE; //! + ULong64_t ** eT; //! + + //trace + TClonesArray * arr ;//! + TGraph * gTrace; //! + TF1 * gFit; //! + TClonesArray * arrTrapezoid ;//! + TGraph * gTrapezoid; //! + + //trace energy, trigger time, rise time + Float_t **teE; //! + Float_t **teT; //! + Float_t **teR; //! + +}; + +#endif + +#ifdef GeneralSort_cxx + +//^############################################################## +void GeneralSort::SetUpTree(){ + + printf("%s\n", __func__); + + if( isParallel){ + proofFile = new TProofOutputFile(saveFileName, "M"); + saveFile = proofFile->OpenFile("RECREATE"); + }else{ + saveFile = new TFile(saveFileName,"RECREATE"); + } + + newSaveTree = new TTree("gen_tree", "Tree After GeneralSort"); + newSaveTree->SetDirectory(saveFile); + newSaveTree->AutoSave(); + + newSaveTree->Branch( "evID", &evID, "evID/l"); // simply copy + + eE = new Float_t * [mapping::nDetType]; + eT = new ULong64_t * [mapping::nDetType]; + + for( int i = 0 ; i < mapping::nDetType; i++){ + if( mapping::detNum[i] == 0 ) continue; + eE[i] = new Float_t[mapping::detNum[i]]; + eT[i] = new ULong64_t[mapping::detNum[i]]; + + for( int j = 0; j < mapping::detNum[i]; j++){ + eE[i][j] = TMath::QuietNaN(); + eT[i][j] = 0; + } + + newSaveTree->Branch( mapping::detTypeName[i].c_str(), eE[i], Form("%s[%d]/F", mapping::detTypeName[i].c_str(), mapping::detNum[i])); + newSaveTree->Branch( (mapping::detTypeName[i]+"_t").c_str(), eT[i], Form("%s_t[%d]/l", mapping::detTypeName[i].c_str(), mapping::detNum[i])); + } + + + if( isTraceExist && traceMethod > 0){ + + arr = new TClonesArray("TGraph"); + + newSaveTree->Branch("trace", arr, 256000); + arr->BypassStreamer(); + arr->Clear("C"); + + if( traceMethod > 1 ){ + + teE = new Float_t * [mapping::nDetType]; + teT = new Float_t * [mapping::nDetType]; + teR = new Float_t * [mapping::nDetType]; + + for( int i = 0 ; i < mapping::nDetType; i++){ + if( mapping::detNum[i] == 0 ) continue; + teE[i] = new Float_t[mapping::detNum[i]]; + teT[i] = new Float_t[mapping::detNum[i]]; + teR[i] = new Float_t[mapping::detNum[i]]; + + for( int j = 0; j Branch( ("w" + mapping::detTypeName[i]).c_str(), teE[i], Form("trace_%s[%d]/F", mapping::detTypeName[i].c_str(), mapping::detNum[i])); + newSaveTree->Branch( ("w" + mapping::detTypeName[i]+"T").c_str(), teT[i], Form("trace_%s_time[%d]/F", mapping::detTypeName[i].c_str(), mapping::detNum[i])); + newSaveTree->Branch( ("w" + mapping::detTypeName[i]+"R").c_str(), teR[i], Form("trace_%s_rise[%d]/F", mapping::detTypeName[i].c_str(), mapping::detNum[i])); + } + + } + } + + if( !isParallel ) newSaveTree->Print("toponly"); +} + +//^############################################################## +void GeneralSort::DecodeOption(){ + TString option = GetOption(); + if( option != ""){ + TObjArray * tokens = option.Tokenize(","); + traceMethod = ((TObjString*) tokens->At(0))->String().Atoi(); + saveFileName = ((TObjString*) tokens->At(1))->String(); + isParallel = ((TObjString*) tokens->At(2))->String().Atoi(); + }else{ + traceMethod = -1; + saveFileName = "temp.root"; + isParallel = false; + } + + PrintTraceMethod(); + printf(" Parallel: %s \n", isParallel ? "Yes" : "No"); + printf(" save file: %s \n", saveFileName.Data()); + +} + +//^############################################################## +void GeneralSort::Init(TTree *tree){ + printf("============= %s\n", __func__); + // Set branch addresses and branch pointers + if (!tree) return; + fChain = tree; + fChain->SetMakeClass(1); + + fChain->SetBranchAddress("evID", &evID, &b_evID); + fChain->SetBranchAddress("multi", &multi, &b_multi); + fChain->SetBranchAddress("bd", bd, &b_bd); + fChain->SetBranchAddress("ch", ch, &b_ch); + fChain->SetBranchAddress("e", e, &b_e); + fChain->SetBranchAddress("e_t", e_t, &b_e_t); + fChain->SetBranchAddress("lowFlag", lowFlag, &b_lowFlag); + fChain->SetBranchAddress("highFlag", highFlag, &b_highFlag); + + TBranch * br = (TBranch *) fChain->GetListOfBranches()->FindObject("traceLen"); + if( br == NULL ){ + printf(" ++++++++ no Trace.\n"); + isTraceExist = false; + }else{ + printf(" ++++++++ Found Trace.\n"); + isTraceExist = true; + fChain->SetBranchAddress("traceLen", tl, &b_tl); + fChain->SetBranchAddress("trace", trace, &b_trace); + } + + NumEntries = fChain->GetEntries(); + printf( " ======== total Entry : %ld\n", NumEntries); + + //########################### Get Option + DecodeOption(); + + SetUpTree(); + + gFit = new TF1("gFit", fitFunc, 0, 1250, numPara); + gFit->SetLineColor(6); + + printf("---- end of Init %s\n ", __func__); + +} + +Bool_t GeneralSort::Notify(){ + return kTRUE; +} + +void GeneralSort::PrintTraceMethod(){ + const char* traceMethodStr; + switch(traceMethod) { + case 0 : traceMethodStr = "Ignore Trace"; break; + case 1 : traceMethodStr = "None and Copy Trace"; break; + case 2 : traceMethodStr = "Fit"; break; + case 3 : traceMethodStr = "Trapezoid"; break; + default: traceMethodStr = "Unknown"; break; + } + printf("\033[1;33m ===== Trace method ? %s (%d) \033[m\n", traceMethodStr, traceMethod); +} + +void GeneralSort::CleanUpMemory(){ + printf("Clean up memory"); + if( traceMethod > 1 ){ + for( int i = 0 ; i < mapping::nDetType; i++){ + if( mapping::detNum[i] == 0 ) continue; + delete [] teE[i]; + delete [] teT[i]; + delete [] teR[i]; + + delete [] eE[i]; + delete [] eT[i]; + } + delete [] teE; + delete [] teT; + delete [] teR; + } + + for( int i = 0 ; i < mapping::nDetType; i++){ + if( mapping::detNum[i] == 0 ) continue; + delete [] eE[i]; + delete [] eT[i]; + } + delete [] eE; + delete [] eT; + + //trace + if( arr ) delete arr ; + if( gTrace ) delete gTrace; + if( gFit ) delete gFit; + if( arrTrapezoid ) delete arrTrapezoid ; + if( gTrapezoid ) delete gTrapezoid; + + printf(".... done\n"); + +} + +#endif // #ifdef GeneralSort_cxx diff --git a/armory/GeneralSortAgent.C b/armory/GeneralSortAgent.C new file mode 100644 index 0000000..12510bf --- /dev/null +++ b/armory/GeneralSortAgent.C @@ -0,0 +1,56 @@ + +#include "TTree.h" +#include "TChain.h" +#include "TMacro.h" +#include "TFile.h" +#include "TProof.h" + +void GeneralSortAgent(Int_t runNum, int nWorker = 1, int traceMethod = 0){ + + TString name; + name.Form("../root_data/run%03d.root", runNum); + + TChain * chain = new TChain("tree"); + chain->Add(name); + + chain->GetListOfFiles()->Print(); + + printf("\033[1;33m---------------------total number of Events %llu\033[0m\n", chain->GetEntries()); + + if( chain->GetEntries() == 0 ) return; + + //this is the option for TSelector, the first one is traceMethod, 2nd is save fileName; + TString option; + + if( abs(nWorker) == 1){ + + option.Form("%d,../root_data/gen_run%03d.root,%d", traceMethod, runNum, 0); + chain->Process("../Armory/GeneralSort.C+", option); + + }else{ + + TProof * p = TProof::Open("", Form("workers=%d", abs(nWorker))); + p->ShowCache(); + printf("----------------------------\n"); + + chain->SetProof(); + option.Form("%d,../root_data/gen_run%03d.root,%d", traceMethod, runNum, 1); + chain->Process("../Armory/GeneralSort.C+", option); + } + + //========== open the output root and copy teh timestamp Marco + + TFile * f1 = new TFile(Form("../root_data/run%03d.root", runNum), "READ"); + TMacro * m = (TMacro* ) f1->Get("timeStamp"); + m->AddLine(Form("%d", runNum)); + + TFile * f2 = new TFile(Form("../root_data/gen_run%03d.root", runNum), "UPDATE"); + f2->cd(); + m->Write("timeStamp"); + + f1->Close(); + f2->Close(); + + delete chain; + +} \ No newline at end of file diff --git a/armory/Process_BasicConfig b/armory/Process_BasicConfig new file mode 100644 index 0000000..1246ce3 --- /dev/null +++ b/armory/Process_BasicConfig @@ -0,0 +1,90 @@ +#!/bin/bash -l + +############################################## +# +# This script define color and dataPath +# +############################################## + +if [ ! -z $RED ]; then + echo "Process_BasicConfig already loaded." + return +fi + +RED='\033[1;31m' +YELLOW='\033[1;33m' +ORANGE='\033[0;33m' +GREEN='\033[1;32m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' #no color +LRED='\033[1;91m' + +echo -e "${RED}##################### Loading Process_BasicConfig.sh ${NC}" + +############## need to distingish mac and daq +Arch="$(uname -s)" +PCName="$(hostname)" +PCID=-1 #if PCID == 1 (DAQ), 2 (MAC), 3 (test station), -1(OTHER) + +#------ Set up data folder, check disk space +echo -e "${YELLOW}##################### Check computer name and arch. ${NC}" +echo "PC name : ${PCName}" +echo "Archetech: ${Arch}" + + +rawDataPath=${SOLARISANADIR}/data_raw/ +rootDataPath=${SOLARISANADIR}/root_data/ + +echo "Raw Data Path : "${rawDataPath} +echo "Root Data Path : "${rootDataPath} + + +if [ ${Arch} == "Linux" ] && [ ${PCName} == "solaris-daq" ]; then + + PCID=1 + + # pathsSetting=${HOME}/SOLARIS_DAQ/programSettings.txt + # if [ -e ${pathsSetting} ]; then + # #echo "Found DAQ programSettings.txt for paths settings" + + # analysisPath=$(cat ${pathsSetting} | head -n 2 | tail -n 1) + + # if [ ! "${analysisPath}" = "$SOLARISANADIR" ]; then + # echo "The analysisPath from ${analysisPath} is different from present folder $SOLARISANADIR. Abort." + # exit + # fi + + # rawDataPathParent=$(cat ${pathsSetting} | head -n 3 | tail -n 1) + # rootDataPathParent=$(cat ${pathsSetting} | head -n 4 | tail -n 1) + + # databaseIP=$(cat ${pathsSetting} | head -n 6 | tail -n 1) + # databaseName=$(cat ${pathsSetting} | head -n 7 | tail -n 1) + + # #echo ${rawDataPathParent} + # #echo ${rootDataPathParent} + # #echo ${databaseIP} + # #echo ${databaseName} + + # else + + # echo "${RED} Cannot found DAQ programSettings.txt for path settings ${NC}" + # echo "Seek Ryan for help" + # exit + + # fi + +fi + +if [ ${Arch} == "Darwin" ] && [ ${PCName} == "SOLARISs-Mac-Studio.local" ]; then + PCID=2 + # rawDataPathParent=${HOME}/experimentalData/ + # rootDataPathParent=${HOME}/experimentalData/ +fi + +if [ ${Arch} == "Linux" ] && [ ${PCName} == "solarisdaq" ]; then + PCID=3 + # rawDataPathParent=${SOLARISANADIR}/data_raw/ + # rootDataPathParent=${SOLARISANADIR}/root_data/ +fi + diff --git a/armory/Process_Download b/armory/Process_Download new file mode 100755 index 0000000..aa5e0bd --- /dev/null +++ b/armory/Process_Download @@ -0,0 +1,109 @@ +#!/bin/bash + +echo -e "${RED}##################### Loading Process_Download.sh ${NC}" + +if [ $# -eq 0 ] || [ $1 == "-help" ]; then + echo "$./process_Download [RunNum]" + echo " RunNum = run number" + echo " * if RunNum = all, sync all" + exit 1 +fi; +RUN=$1 + +runNum=${RUN#0} #remove zero +RUN=$(printf '%03d' $runNum) ##add back the zero + +source $SOLARISANADIR/Armory/Process_BasicConfig + +if [ -z $expName ]; then + source $SOLARISANADIR/working/expName.sh +fi + +IP=solarisdaq # defined at ~/.ssh/config +USR=solaris + +if [ ${RUN} == "all" ]; then + + if [ ${PCID} -eq 2 ]; then + + #=========== Ping to check the connectivity + echo "Checking $IP connetivity, max wait for 3 sec...." + ping -c 3 -W 3 $IP #> /dev/null + if [ $? -ne 0 ]; then + echo -e "$RED !!!!!!! $IP is not alive $NC" + else + #============ Get the raw data + rsync -avuht --progress $USR@$IP:$rawDataPath/$expName_* $MacRawDataPath/data/. + + echo -e "$YELLOW======== rsync RunTimeStamp.dat $NC" + rsync -avuht --progress $USR@$IP:$rawDataPath/$RunTimeStamp* $MacRawDataPath/data/. + + echo -e "$YELLOW======== rsync expName.sh $NC" + rsync -avuht --progress $USR@$IP:Analysis/working/expName.sh $SOLARISANADIR/working/. + fi + else + echo -e "$RED############### Only in SOLARIS MAC can donwload data. skip.$NC" + fi + + echo -e "$YELLOW=============================================$NC" + tail -10 $MacRawDataPath/raw_data/RunTimeStamp.dat + echo -e "$YELLOW=============================================$NC" + + exit 1 +fi + +#just in case people put %03d as RUN +if [ "${RUN:0:2}" == "00" ]; then + RUN=${RUN:2:1} +elif [ "${RUN:0:1}" == "0" ]; then + RUN=${RUN:1:2} +else + RUN=$(printf '%d' $RUN) +fi +RUN=$(printf '%03d' ${RUN}) + +####################################### +#################### Download raw data +echo -e "${CYAN}>>>>>>>>>>>>>>> Download raw data: run ${RUN}${NC}" +if [ ${PCID} -eq 2 ]; then + + #=========== Ping to check the connectivity + echo "Checking $IP connetivity, max wait for 3 sec...." + ping -c 3 $IP -W 3 #> /dev/null + if [ $? -ne 0 ]; then + echo -e "$RED !!!!!!! $IP is not alive $NC" + else + #============ Get the raw data + echo -e "================= RUN $RUN: Get the raw data `date`" + + rsync -avuht --progress $USR@$IP:$rawDataPath/$expName_$RUN* $MacRawDataPath/data/. + + echo -e "$YELLOW======== rsync RunTimeStamp.dat $NC" + rsync -avuht --progress $USR@$IP:$rawDataPath/$RunTimeStamp* $MacRawDataPath/data/. + + echo -e "$YELLOW======== rsync expName.sh $NC" + rsync -avuht --progress $USR@$IP:Analysis/working/expName.sh $SOLARISANADIR/working/. + fi +else + echo -e "$CYAN############### Only in SOLARIS MAC can donwload data. skip.$NC" +fi + +if [ -z ${rawDataPath}/RunTimeStamp.dat ]; then + echo -e "$YELLOW=============================================$NC" + tail -10 ${rawDataPath}/RunTimeStamp.dat + echo -e "$YELLOW=============================================$NC" +fi + +count=`ls -1 ${rawDataPath}/${expName}_${RUN}_*.sol 2>/dev/null | wc -l` +echo -e "========================= Number of Files : ${count}${YELLOW}" +if [ ${count} -eq 0 ]; then + echo "${NC}============================================" + echo "==== RAW Files of RUN-${RUN} not found! " + echo "============================================" + isRunDataExist=false + exit 1 +else + du -hc ${rawDataPath}//${expName}_${RUN}_*.sol + echo -e "$NC=============================================" + isRunDataExist=true +fi diff --git a/armory/Process_EventBuilder b/armory/Process_EventBuilder new file mode 100755 index 0000000..d9c8ae5 --- /dev/null +++ b/armory/Process_EventBuilder @@ -0,0 +1,111 @@ +#!/bin/bash + +echo -e "${RED}##################### Loading Process_EventBuilder.sh ${NC}" + +if [ -z $SOLARISANADIR ]; then + echo "###### env variable SOLARISANADIR not defined. Abort. Please run the SOLARIS.sh." + echo "better add \"source \" into .bashrc" + exit +fi + +if command -v EventBuilder > /dev/null 2>&1; then + echo "EventBuilder exists" +else + echo -e "${RED}EventBuilder does not exist${NC}" + echo -e "${RED}Create a symbolic link of the EventBuilder from the SOLARIS_DAQ/Aux/${NC}" + exit +fi + +if [ $# -ne 3 ] || [ $1 == "-help" ]; then + echo "$ Process_EventBuilder [RunNum] [EventBuild] [timeWin]" + echo " RunNum = run number" + echo " EventBld = 2/1/0/-1/-2 || 2 = with Trace" + echo " timeWin = number of tick for an event " + echo "" + exit 1 +fi; + +RUN=$1 +EventBld=$2 +timeWin=$3 + +source ${SOLARISANADIR}/Armory/Process_BasicConfig +if [ -z $expName ]; then + source $SOLARISANADIR/working/expName.sh +fi + +runNum=${RUN#0} #remove zero +RUN=$(printf '%03d' $runNum) ##add back the zero + +rawDataPattern="$rawDataPath/${expName}_${RUN}_*.sol" +rootDataName="$rootDataPath/run$RUN.root" + +#==== check raw data exist +isRawDataExist=`ls -1 ${rawDataPattern}* 2>/dev/null | wc -l` + +if [ ! $isRawDataExist -gt 0 ]; then + echo -e "${LRED}################# Run Data $rawDataPattern not exist. Abort. ${NC}" + exit +fi + +echo -e "${YELLOW} ============== list of files ${NC}" +\du -h ${rawDataPattern}* +totSize=$(\du -hc ${rawDataPattern}* | tail -n 1 | awk '{print $1}') +echo -e "${YELLOW} ============== total file size : ${totSize}${NC}" + + +#==== check raw data timeStamp +if [ ${Arch} == "Linux" ]; then + rawDataTime=`stat -c "%Z" ${rawDataPattern}* | sort -rn | head -1` +else + rawDataTime=`stat -f "%Sm" -t "%Y%m%d%H%M%S" $rawDataPattern | sort -rn | head -1` +fi + +#==== check if root data exist +isRootDataExist=`ls -1 $rootDataName 2>/dev/null | wc -l` + +#==== if root data exist, check timeStamp +if [ ${isRootDataExist} -gt 0 ]; then + if [ ${Arch} == "Linux" ]; then + rootDataTime=`stat -c "%Z" $rootDataName | sort -rn | head -1` + else + rootDataTime=`stat -f "%Sm" -t "%Y%m%d%H%M%S" $rootDataName | sort -rn | head -1` + fi +else + rootDataTime=0 +fi + + +if [ ${EventBld} -eq 0 ]; then + + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> Event Building Skipped by user. ${NC}" + +elif [ ${EventBld} -ge 1 ]; then + + if [ ${rawDataTime} -ge ${rootDataTime} ]; then + + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> Event Building $(date) ${NC}" + if [ ${EventBld} -eq 1 ]; then + EventBuilder $rootDataName ${timeWin} 0 $rawDataPattern + elif [ ${EventBld} -eq 2 ]; then + EventBuilder $rootDataName ${timeWin} 1 $rawDataPattern + fi + echo -e "${LRED}<<<<<<<<<<<<<<<< Done Event Building $(date) ${NC}" + + else + echo -e "${GREEN} root data are newer than raw data. No need to merged again.${NC}" + echo -e "${GREEN} You can Force merging using option -${EventBld}, ${ORANGE} see ./process_run.sh -help${NC}" + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> Event Building Skipped. ${NC}" + fi + +else + + echo -e "${LRED}>>>>>>>>>>>>>>> Force Event Building $(date) ${NC}" + if [ ${EventBld} -eq -1 ]; then + EventBuilder $rootDataName ${timeWin} 0 $rawDataPattern + elif [ ${EventBld} -eq -2 ]; then + EventBuilder $rootDataName ${timeWin} 1 $rawDataPattern + fi + echo -e "${LRED}<<<<<<<<<<<<<<<< Done Event Building $(date) ${NC}" + +fi \ No newline at end of file diff --git a/armory/Process_MultiRuns b/armory/Process_MultiRuns new file mode 100755 index 0000000..fd0257f --- /dev/null +++ b/armory/Process_MultiRuns @@ -0,0 +1,96 @@ +#!/bin/bash -l + +if [ -z $SOLARISANADIR ]; then + echo "###### env variable SOLARISANADIR not defined. Abort. Please run the SOLARIS.sh." + echo "better add \"source \" into .bashrc" + exit +fi + +if [ $# -le 2 ] || [ $1 == "-help" ]; then + echo "$./process_MultiRuns [RunNum1] [RunNum2] [EventBuild] [GeneralSort] [numMacTerminal]" + echo " RunNum1 = start run number" + echo " RunNum2 = stop run number" + echo " EventBld = 2/1/0/-1/-2 || 2 = with Trace" + echo " GeneralSort = n/0/-n || n = number of worker" + echo " TraceMethod = -1/0/1/2 || -1 no trace, 0 save trace, 1 fit, 2 trapezoid" + echo " numMacTerminal = n ^ || in order to speed up in Mac " + echo " * negative option = force " + echo " ^ only for mac, and it will override GeneralSort to be 1 worker. " + exit 1 +fi; + + +runID1=$1 +runID2=$2 +buidEvt=$3 +nWorker=0 +traceMethod=0 +nTerminal=0 + +if [ $# -ge 4 ]; then nWorker=$4; fi +if [ $# -ge 5 ]; then traceMethod=$5; fi +if [ $# -ge 6 ]; then nTerminal=$6; fi + +source ${SOLARISANADIR}/armory/Process_BasicConfig +source ${SOLARISANADIR}/working/expName.sh + + +if [ $PCID -eq 2 ]; then + if [ $nTerminal -ge 2 ]; then + if [[ $nWorker -ge 0 ]]; then + nWorker=1; + else + nWorker=-1; + fi + fi +else + $nTerminal=0; +fi + + +if [ $nTerminal -eq 0 ]; then + + for i in $(seq $runID1 $runID2); do + Process_Run $i $buidEvt $nWorker $traceMethod 0 + done + +else + + if [ $PCID -ne 2 ]; then + exit 1 + fi + + # Calculate the size of each segment + segment_size=$(( ($runID2 - $runID1 + 1) / $nTerminal )) + + # Iterate through the segments + for i in $(seq 0 $(( $nTerminal - 1 ))); do + start=$(( $runID1 + ($i * $segment_size) )) + end=$(( $start + $segment_size - 1 )) + + # Handle the last segment, which may be larger + if [[ $i -eq $(( $nTerminal - 1 )) ]]; then + end=$runID2 + fi + + echo "Segment $(( $i + 1 )): [$start, $end]" + + profile_name="Homebrew" + width=700 + height=500 + x_pos=200 + y_pos=200 + +osascript <\" into .bashrc" + exit +fi + +if [ "$PWD" != "${SOLARISANADIR}/working" ]; then + echo "============= go to the Working directory" + cd "${SOLARISANADIR}/working" +fi + +if [ $# -eq 0 ] || [ $1 == "-help" ]; then + echo "$ Process_Run [RunNum] [EventBuild] [GeneralSort] [Monitor]" + echo " RunNum = run number / \"lastRun\" " + echo " EventBld = 2/1/0/-1/-2 || 2 = with Trace" + echo " GeneralSort = n/0/-n || n = number of worker + TraceMethod * 100" + echo " TraceMethod = 0 no trace" + echo " = 1 save trace" + echo " = 2 WS fit" + echo " = 3 trapezoid(not implemented)" + echo " e.g. 208 = WS trace with 8 workers" + + #======== change Monitor to Action. + + echo " Monitor = 2/1/0 || 1 = single run, 2 = using the list in ChainMonitors.C" + echo "" + echo " * negative option = force." + echo " * Defult timeWindow for Event builder is 100 tick = 800 ns." + echo "" + exit 1 +fi; + +RUN=$1 +runNum=$1 +EventBld=1 +nWorker=1 +TraceMethod=0 +isMonitor=1 + +if [ $# -ge 2 ]; then EventBld=$2; fi +if [ $# -ge 3 ]; then nWorker=$3; fi +if [ $# -ge 4 ]; then isMonitor=$4; fi + + +temp=$((nWorker / 100)); +if [ $temp -lt 0 ]; then + TraceMethod=$((-1 * temp)); +fi + +nWorker=$((nWorker % 100 )); + +runNum=${RUN#0} #remove zero +RUN=$(printf '%03d' $runNum) ##add back the zero + +################################### Setting display +echo "#################################################" +echo "### Process_Run #####" +echo "#################################################" +echo "### RunID : ${RUN}" +echo "### Event Builder : $EventBld" +echo "### General Sort : $nWorker worker(s)" +echo "### Trace Method : $TraceMethod" +echo "### Monitor : $isMonitor" +echo "#################################################" + +source ${SOLARISANADIR}/Armory/Process_BasicConfig +source ${rawDataPath}/expName.sh + +#################################### CHECK IS RUN DATA EXIST +isRunDataExist=false + +#################################### EVENT BUILDER +source Process_Download $RUN + +if [ $isRunDataExist ]; then + source Process_EventBuilder $RUN $EventBld $timeWin +fi + +#################################### GeneralSort + +if [ $isRunDataExist ]; then + source Process_Sort $RUN $nWorker $TraceMethod +fi +#################################### Monitor + +if [ $isMonitor -eq 0 ]; then + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> Monitor Skipped by user. ${NC}" +elif [ $isMonitor -eq 1 ]; then + root -l "ChainMonitors.C($runNum)" +elif [ $isMonitor -eq 2 ]; then + root -l "ChainMonitors.C" +fi + + + + diff --git a/armory/Process_Sort b/armory/Process_Sort new file mode 100755 index 0000000..b0def9e --- /dev/null +++ b/armory/Process_Sort @@ -0,0 +1,95 @@ +#!/bin/bash -l + +echo -e "${RED}##################### Loading Process_Sort.sh ${NC}" + +if [ -z $SOLARISANADIR ]; then + echo "###### env variable SOLARISANADIR not defined. Abort. Please run the SOLARIS.sh." + echo "better add \"source \" into .bashrc" + exit +fi + +if [ $# -eq 0 ] || [ $1 == "-help" ]; then + echo "$ Process_Sort [RunNum] [GeneralSort] [TraceMethod]" + echo " RunNum = run number" + echo " GeneralSort = n/0/-n || n = number of worker" + echo " TraceMethod = -1/0/1/2 || -1 no trace, 0 save trace, 1 fit, 2 trapezoid" + echo "" + exit 1 +fi; + +RUN=$1 +nWorker=$2 +TraceMethod=$3 + +source $SOLARISANADIR/Armory/Process_BasicConfig +if [ -z $expName ]; then + source $SOLARISANADIR/working/expName.sh +fi + +runNum=${RUN#0} #remove zero +RUN=$(printf '%03d' $runNum) ##add back the zero + +if [ ${nWorker} -eq 0 ]; then + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> GeneralSort Skipped by user. ${NC}" +else + source $ROOTSYS/bin/thisroot.sh + + #--------- Check is runXXX.root exist + rootDataPath=$SOLARISANADIR/root_data + rootDataName="$rootDataPath/run$RUN.root" + isRootDataExist=`ls -1 $rootDataName 2>/dev/null | wc -l` + + #==== if root data exist, check timeStamp + if [ $isRootDataExist -gt 0 ]; then + if [ ${Arch} == "Linux" ]; then + rootDataTime=`stat -c "%Z" $rootDataName | sort -rn | head -1` + else + rootDataTime=`stat -f "%Sm" -t "%Y%m%d%H%M%S" $rootDataName | sort -rn | head -1` + fi + else + rootDataTime=0 + echo -e "$LRED ################# run$RUN.root does not exist. Abort. $NC" + exit 1 + fi + + #-------- check gen_root timestamp + genRootDataName="$rootDataPath/gen_run$RUN.root" + isGenRootDataExist=`ls -1 $genRootDataName 2>/dev/null | wc -l` + + #----- if gen_runXXX.data exist, check timeStamp + if [ $isGenRootDataExist -gt 0 ]; then + if [ ${Arch} == "Linux" ]; then + genRootDataTime=`stat -c "%Z" $genRootDataName | sort -rn | head -1` + else + genRootDataTime=`stat -f "%Sm" -t "%Y%m%d%H%M%S" $genRootDataName | sort -rn | head -1` + fi + else + genRootDataTime=0 + fi + + mkdir -p ~/.proof/working + cp ${SOLARISANADIR}/working/Mapping.h ~/.proof/working/. + + if [ $nWorker -le -1 ]; then + echo -e "${LRED}>>>>>>>>>>>>>>> Force GeneralSort $(date) ${NC}" + root -l -q -b "$SOLARISANADIR/Armory/GeneralSortAgent.C($runNum, $nWorker, $TraceMethod)" + echo -e "${LRED}<<<<<<<<<<<<<<<< Done GeneralSort $(date) ${NC}" + fi + + if [ $nWorker -ge 1 ]; then + + if [ $rootDataTime -ge $genRootDataTime ]; then + + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> GeneralSort $(date) ${NC}" + root -l -q -b "$SOLARISANADIR/Armory/GeneralSortAgent.C($runNum, $nWorker, $TraceMethod)" + echo -e "${LRED}<<<<<<<<<<<<<<<< Done GeneralSort $(date) ${NC}" + + else + echo -e "${GREEN} gen_run$RUN.root is newer than run$RUN.root. No need to GeneralSort again.${NC}" + echo -e "${GREEN} You can Force GeneralSort using option -${nWorker}, ${ORANGE} see Process_Run -help${NC}" + echo -e "${LRED}>>>>>>>>>>>>>>>>>>>>> GeneralSort Skipped. ${NC}" + fi + + fi + +fi \ No newline at end of file diff --git a/armory/readRawTrace.C b/armory/readRawTrace.C new file mode 100644 index 0000000..f2630f9 --- /dev/null +++ b/armory/readRawTrace.C @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../working/Mapping.h" + +void readRawTrace(TString fileName, int minDetID = 0, int maxDetID = 1000){ + +/**///============================================================== + + TFile * f1 = new TFile (fileName, "read"); + TTree * tree = (TTree *) f1->Get("tree"); + + if( tree == NULL ) { + printf("===== Are you using gen_runXXX.root ? please use runXXX.root\n"); + return; + } + + int totnumEntry = tree->GetEntries(); + printf( "========== total Entry : %d \n", totnumEntry); + + TCanvas * cRead = new TCanvas("cRead", "Read Raw Trace", 0, 1500, 800, 300); + cRead->Divide(1,1); + for( int i = 1; i <= 2 ; i++){ + cRead->cd(i)->SetGrid(); + } + cRead->SetGrid(); + + gStyle->SetOptFit(0); + +/**///============================================================== + Int_t bd[200]; + Int_t ch[200]; + Int_t numHit; + Int_t trace[200][2500]; + Int_t traceLength[200]; + tree->SetBranchAddress("bd", bd); + tree->SetBranchAddress("ch", ch); + tree->SetBranchAddress("multi", &numHit); + tree->SetBranchAddress("trace", trace); + tree->SetBranchAddress("tl", traceLength); + + TLatex text ; + text.SetNDC(); + text.SetTextFont(62); + text.SetTextSize(0.06); + text.SetTextColor(2); + + bool breakFlag = false; + bool lastEvFlag = false; + std::vector oldEv; + int evPointer = 0; + + TGraph * graph = new TGraph(); + + for( int ev = 0; ev < totnumEntry; ev++){ + + if( lastEvFlag ) { + ev = oldEv[evPointer]; + lastEvFlag = false; + } + tree->GetEntry(ev); + + int countJ = 0; + + for( int j = 0; j < numHit ; j++){ + + int detID = mapping[bd[j]][ch[j]]; + + if( !(minDetID <= detID && detID <= maxDetID ) ) continue; + + if( countJ == 0 ) printf("-------------------------------- ev : %d, evPointer : %d| num Trace : %d\n", ev, evPointer, numHit); + + printf("nHit: %d, id : %d, trace Length : %u ( enter = next , q = stop, w = last)\n", j, detID, traceLength[j]); + + graph->Clear(); + graph->Set(traceLength[j]); + for( int k = 0; k < traceLength[j] ; k++){ + graph->SetPoint(k, k, trace[j][k]); + //printf("%4d, %5d |", k, trace[j][k]); + //if( k % 10 ==0 ) printf("\n"); + } + + graph->SetTitle(Form("ev: %d, nHit : %d, id : %d, trace Length : %u\n", ev, j, detID, traceLength[j])); + + cRead->cd(1); + cRead->Clear(); + graph->Draw("Al"); + //g->GetXaxis()->SetRangeUser(0, g->GetN()); + //g->GetYaxis()->SetRangeUser(7500, 35000); + + cRead->Update(); + gSystem->ProcessEvents(); + + + char s[80]; + fgets(s, sizeof s, stdin); + + if( s[0] == 113 ) { // 'q' = 113 + breakFlag = true; + break; + }else if( s[0] == 119 ) { // 'w' = 119 + + if( j > 0 || countJ > 0 ) { + j = j - 2; + } + + if( (j == 0 && (int)oldEv.size() >= 0 && evPointer > 0 ) || countJ == 0 ) { + if( evPointer > 0 ) evPointer --; + if( evPointer == 0 ) printf(" the first event!!! \n"); + lastEvFlag = true; + //printf(" ev : %d, evPt : %d \n", oldEv[evPointer], evPointer); + break; + } + } + + countJ ++; + + } + if( breakFlag ) break; + + if( lastEvFlag == false && countJ > 0 ){ + if( oldEv.size() == evPointer ) oldEv.push_back(ev); + evPointer ++; + } + + + } + + //gROOT->ProcessLine(".q"); + +} diff --git a/armory/readTrace.C b/armory/readTrace.C new file mode 100644 index 0000000..980aeb7 --- /dev/null +++ b/armory/readTrace.C @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void readTrace(TString fileName, int minDetID = 0, int maxDetID = 1000, bool isGoodOnly = false){ + +/**///============================================================== + + TFile * f1 = new TFile (fileName, "read"); + TTree * tree = (TTree *) f1->Get("gen_tree"); + + int totnumEntry = tree->GetEntries(); + printf( "========== total Entry : %d \n", totnumEntry); + + TCanvas * cRead = new TCanvas("cRead", "Read Trace", 0, 1500, 800, 300); + cRead->Divide(1,1); + for( int i = 1; i <= 2 ; i++){ + cRead->cd(i)->SetGrid(); + } + cRead->SetGrid(); + + gStyle->SetOptFit(0); + +/**///============================================================== + TClonesArray * arr = new TClonesArray("TGraph"); + tree->SetBranchAddress("trace", &arr); + + //TODO UP-Down arrow for pervious-next control + TLine timeVLine; + + TLatex text ; + text.SetNDC(); + text.SetTextFont(62); + text.SetTextSize(0.06); + text.SetTextColor(2); + + bool breakFlag = false; + bool lastEvFlag = false; + std::vector oldEv; + int evPointer = 0; + + for( int ev = 0; ev < totnumEntry; ev++){ + + if( lastEvFlag ) { + ev = oldEv[evPointer]; + lastEvFlag = false; + } + tree->GetEntry(ev); + + int nTrace = arr->GetEntriesFast(); + + int countJ = 0; + + for( int j = 0; j < nTrace ; j++){ + + TGraph * g = (TGraph*) arr->At(j); + + TString gTitle; + gTitle = g->GetTitle(); + ///printf("TGraph Title : %s\n", gTitle.Data()); + + int detID = 0; + int pos = gTitle.Index("id:"); + gTitle.Remove(0, pos+3); + gTitle.Remove(3); + detID = gTitle.Atoi(); + + if( !(minDetID <= detID && detID <= maxDetID ) ) continue; + + if( countJ == 0 ) printf("-------------------------------- ev : %d, evPointer : %d| num Trace : %d\n", ev, evPointer, nTrace); + + + TF1 * gFit = (TF1 *) g->FindObject("gFit"); + + TString kTitle; + + if( gFit != NULL ){ + double base, time = 0, riseTime, energy, chiSq; + energy = gFit->GetParameter(0); + time = gFit->GetParameter(1); + riseTime = gFit->GetParameter(2); + base = gFit->GetParameter(3); + chiSq = gFit->GetChisquare()/gFit->GetNDF(); + int kind = gFit->GetLineColor(); + int det = gFit->GetLineStyle(); + + ///if( !(minDetID <= det && det <= maxDetID ) ) continue; + + if( isGoodOnly){ + if( abs(energy) < 1.5* g->GetRMS(2) ) continue; + if( time > gFit->GetXmax() || time < gFit->GetXmin()) continue; + if( time > 200 || time < 20) continue; + if( riseTime > gFit->GetXmax()/7. || riseTime < 0 ) continue; + } + + //if( energy < 400 ) continue; + + kTitle = Form("(%3d,%d), base: %8.1f, rise: %6.2f, time: %6.1f, energy: %8.1f | chi2: %8.1f, RMS: %6.1f", + det, kind, base, riseTime, time, energy, chiSq, g->GetRMS(2)); + + printf("%s |(q = break, w = last one)", kTitle.Data()); + + + timeVLine.SetX1(time); + timeVLine.SetX2(time); + timeVLine.SetY1(-1000); + timeVLine.SetY2(20000); + timeVLine.SetLineColor(4); + } + + cRead->cd(1); + //cRead->Clear(); + g->Draw("AC"); + //g->GetXaxis()->SetRangeUser(0, g->GetN()); + //g->GetYaxis()->SetRangeUser(7500, 35000); + timeVLine.Draw("same"); + if( gFit != NULL ) text.DrawText(0.11, 0.85, kTitle.Data()); + + cRead->Update(); + gSystem->ProcessEvents(); + + + char s[80]; + fgets(s, sizeof s, stdin); + + if( s[0] == 113 ) { // 'q' = 113 + breakFlag = true; + break; + }else if( s[0] == 119 ) { // 'w' = 119 + + if( j > 0 || countJ > 0 ) { + j = j - 2; + } + + if( (j == 0 && (int)oldEv.size() >= 0 && evPointer > 0 ) || countJ == 0 ) { + if( evPointer > 0 ) evPointer --; + if( evPointer == 0 ) printf(" the first event!!! \n"); + lastEvFlag = true; + //printf(" ev : %d, evPt : %d \n", oldEv[evPointer], evPointer); + break; + } + } + + countJ ++; + + } + if( breakFlag ) break; + + if( lastEvFlag == false && countJ > 0 ){ + if( oldEv.size() == evPointer ) oldEv.push_back(ev); + evPointer ++; + } + + + } + + //gROOT->ProcessLine(".q"); + +} diff --git a/cleopatra/Check_Simulation_obsolete.C b/cleopatra/Check_Simulation_obsolete.C new file mode 100644 index 0000000..53caec4 --- /dev/null +++ b/cleopatra/Check_Simulation_obsolete.C @@ -0,0 +1,656 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../Armory/AnalysisLib.h" +#include "../Armory/ClassDetGeo.h" +#include "../Armory/ClassReactionConfig.h" +#include "../Cleopatra/ClassIsotope.h" +#include "../Cleopatra/ClassTransfer.h" + +double * FindRange(TString branch, TString gate, TTree * tree, double output[2]); +double ExtractNumber(int index, TMacro * macro); +TString ExtractString(int index, TMacro * macro); +vector StringToVector(TString str); +vector intConvertor(vector arr); +vector doubleConvertor(vector arr); + +enum plotID { pEZ, /// 0 + pRecoilXY, /// 1 + pRecoilXY1, /// 2 + pRecoilXY2, /// 3 + pRecoilRZ, /// 4 + pRecoilRTR, /// 5 + pTDiffZ, /// 6 + pThetaCM, /// 7 + pThetaCM_Z, /// 8 + pExCal, /// 9 + pRecoilRThetaCM, /// 10 + pArrayXY, /// 11 + pInfo, /// 12 + pHitID, /// 13 + pElum1XY, /// 14 + pEElum1R, /// 15 + pElum1RThetaCM, /// 16 + pEmpty }; /// 17 +plotID StringToPlotID(TString str); + +//*===================================================== +void Check_Simulation(TString filename = "transfer.root", + TString configFile = "../working/Check_Simulation_Config.txt", + Int_t padSize = 500, + bool outputCanvas = false){ + + printf("=========================== Check_Simulation.C\n"); + + TMacro * config = new TMacro(configFile); + int numLine = config->GetListOfLines()->GetSize(); + int startLineNum = 0; + for( int i = 0; i < numLine ; i++){ + TString haha = config->GetListOfLines()->At(i)->GetName(); + haha.Remove(4); + if( haha != "////" ) { + startLineNum = i; + break; + } + } + + TString gate = ExtractString(startLineNum+1, config); + double elumRange = ExtractNumber(startLineNum+2, config); + std::vector thetaCMRange = doubleConvertor( StringToVector( ExtractString(startLineNum+3,config) )); + bool shownKELines = (ExtractString(startLineNum+4, config).Remove(4) == "true" ? true : false); + bool isOverRideEx = (ExtractString(startLineNum+5, config).Remove(4) == "true" ? true : false); + std::vector oExRange = doubleConvertor( StringToVector ( ExtractString(startLineNum+6, config ))); + + printf("%s \n", gate.Data()); + + ///==== config Canvas + std::vector plotConfig = StringToVector( ExtractString(startLineNum, config)); + std::vector canvas; + int colCount = 0; + int colCount_new = 0; + int rowCount = 1; + for( int i = 0; i < (int) plotConfig.size(); i++){ + if( plotConfig[i] == "break" ) { + rowCount ++; + if( colCount_new > colCount ) colCount = colCount_new; + colCount_new = 0; + continue; + } + canvas.push_back( StringToPlotID(plotConfig[i])); + colCount_new ++; + } + + if( colCount == 0 ) colCount = colCount_new; + //printf("plot row: %d, col: %d \n", rowCount, colCount); + + std::vector Div = {colCount, rowCount}; + + TFile * file = new TFile(filename, "read"); + TTree * tree = (TTree*) file->Get("tree"); + + TObjArray * fxList = (TObjArray *) file->FindObjectAny("EZCurve"); + TObjArray * txList = (TObjArray *) file->FindObjectAny("thetaCM_Z"); + + gStyle->SetOptStat(""); + gStyle->SetStatY(0.9); + gStyle->SetStatX(0.9); + gStyle->SetStatW(0.4); + gStyle->SetStatH(0.2); + gStyle->SetLabelSize(0.05, "XY"); + gStyle->SetTitleFontSize(0.1); + + //*================== detGeoID + TMacro * detGeoIDTxt = (TMacro *) file->FindObjectAny("detGeoID"); + int detGeoID = atoi(detGeoIDTxt->GetListOfLines()->At(0)->GetName()); + + //*================== reactionConfig + TMacro * reactionConfigTxt = (TMacro *) file->FindObjectAny("reactionConfig"); + TString Reaction = reactionConfigTxt->GetName(); + + ReactionConfig reactionConfig(reactionConfigTxt); + Recoil recoil = reactionConfig.recoil[detGeoID]; + + int nEvent = reactionConfig.numEvents; + printf("number of events generated : %d \n", nEvent); + + reactionConfig.Print(detGeoID, false); + + //*================================== detetcor Geometry + printf("=================================\n"); + printf(" loading detector Geometry.\n"); + TMacro * detGeoTxt = (TMacro *) file->FindObjectAny("detGeo"); + + DetGeo detGeo(detGeoTxt); + Array array = detGeo.array[detGeoID]; + + detGeo.Print(); + array.Print(); + + printf("=================================\n"); + + int numDet = array.colDet * array.rowDet ; + + double zRange[3] = {400, -1000, 1000}; /// zRange[0] = nBin + zRange[1] = array.zMin - 50; + zRange[2] = array.zMax + 50; + + printf(" zRange : %f - %f \n", zRange[1], zRange[2]); + printf("=================================\n"); + + //*========================================= Ex List; + double ExRange[2]; + int numEx = 0; + ExcitedEnergies exList; + + // if DEBA_ExList exist, use this, else use the recoil ExList + TMacro * exListTxt = (TMacro *) file->FindObjectAny("DWBA_ExList"); + + ExRange[0] = 9999999; + ExRange[1] = -9999999; + + if( exListTxt == nullptr ){ + + exList = reactionConfig.exList[detGeoID]; + numEx = exList.ExList.size(); + + for( size_t i = 0; i < numEx; i++ ){ + double ex = exList.ExList[i].Ex; + if( ex < ExRange[0] ) ExRange[0] = ex; + if( ex > ExRange[1] ) ExRange[1] = ex; + } + + }else{ + + numEx = exListTxt->GetListOfLines()->GetSize()-1; + for( int i = 1 ; i <= numEx ; i++){ + std::vector tempStr = AnalysisLib::SplitStr(exListTxt->GetListOfLines()->At(i)->GetName(), " "); + double ex = atof(tempStr[0].c_str()); + if( ex < ExRange[0] ) ExRange[0] = ex; + if( ex > ExRange[1] ) ExRange[1] = ex; + exList.Add(ex, atof(tempStr[1].c_str()), 1.0, 0.00); + } + + } + + exList.Print(); + + double dExRange = ExRange[1] - ExRange[0]; + ExRange[0] = ExRange[0] - 0.3 - dExRange * 0.1; + ExRange[1] = ExRange[1] + 0.3 + dExRange * 0.1; + + printf("Number of Ex states = %d \n", numEx); + + //*=================================== calculate Ranges + //eRange by zRange and exList + + TransferReaction transfer; + transfer.SetReactionSimple( reactionConfig.beamA, + reactionConfig.beamZ, + reactionConfig.targetA, + reactionConfig.targetZ, + recoil.lightA, + recoil.lightZ, + reactionConfig.beamEnergy); + + double QQ = transfer.GetCMTotalEnergy(); + double gamm = transfer.GetReactionGamma(); + double mass = transfer.GetMass_b(); + double slope = transfer.GetEZSlope( detGeo.Bfield); + + double eRange[2] = {0, 10}; + eRange[1] = zRange[2] * slope; + + // printf("intercept of 0 MeV : %f MeV \n", intercept); + printf("eRange 0 MeV : %f MeV \n", eRange[1]); + + double dERange = eRange[1] - eRange[0]; + + eRange[0] = eRange[0] - dERange * 0.1; + eRange[1] = eRange[1] + dERange * 0.1; + + + //thetaCMRange + double momentum = transfer.GetMomentumbCM(); + double beta = transfer.GetReactionBeta(); + double alpha = slope / beta; + double thetaMax = acos( (beta * QQ- alpha / gamm * zRange[2])/momentum) * TMath::RadToDeg(); + thetaCMRange[1] = (int) TMath::Ceil(thetaMax/10.)*10; + ///printf(" momentum : %f \n", momentum); + ///printf(" thetaCM Max : %f \n", thetaMax); + ///printf(" thetaCM Range : %d \n", thetaCMRange[1]); + + + double recoilERange[2] = {0, 100}; + + //=================================================== + printf("============================== Gate\n"); + printf("gate : %s\n", gate.Data()); + printf("====================================\n"); + + Int_t size[2] = {padSize,padSize}; ///x,y, single Canvas size + TCanvas * cCheck = new TCanvas("cCheck", "Check For Simulation", 0, 0, size[0]*Div[0], size[1]*Div[1]); + if(cCheck->GetShowEditor() )cCheck->ToggleEditor(); + if(cCheck->GetShowToolBar() )cCheck->ToggleToolBar(); + cCheck->Divide(Div[0],Div[1]); + + for( int i = 1; i <= Div[0]*Div[1] ; i++){ + cCheck->cd(i); + + if( canvas[i-1] == pThetaCM ) { + cCheck->cd(i)->SetGrid(0,0); + cCheck->cd(i)->SetLogy(); + } + + if( canvas[i-1] == pHitID ){ + cCheck->cd(i)->SetLogy(); + } + + plotID pID = canvas[i-1]; + + ///######################################## + if( pID == pEZ){ + TH2F * hez = new TH2F("hez", Form("e-z [gated] @ %5.0f mm; z [mm]; e [MeV]", array.firstPos), zRange[0], zRange[1], zRange[2], + 400, eRange[0], eRange[1]); + tree->Draw("e:z>>hez", gate, "colz"); + if( shownKELines){ + for( int i = 0; i < numEx ; i++){ + fxList->At(i)->Draw("same"); + } + } + } + + if( pID == pRecoilXY ){ + TH2F * hRecoilXY = new TH2F("hRecoilXY", Form("RecoilXY [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[detGeoID].detPos ), + 400, -detGeo.aux[detGeoID].outerRadius, detGeo.aux[detGeoID].outerRadius, + 400, -detGeo.aux[detGeoID].outerRadius, detGeo.aux[detGeoID].outerRadius); + tree->Draw("yRecoil:xRecoil>>hRecoilXY", gate, "colz"); + TArc * detArc1 = new TArc(0,0, detGeo.aux[detGeoID].outerRadius); + detArc1->SetLineColor(kBlue-8); + detArc1->SetFillStyle(0); + detArc1->Draw("same"); + TArc * detArc2 = new TArc(0,0, detGeo.aux[detGeoID].innerRadius); + detArc2->SetLineColor(kBlue-8); + detArc2->SetFillStyle(0); + detArc2->Draw("same"); + + if( reactionConfig.beamX != 0. || reactionConfig.beamY != 0. ){ + TArc * arc = new TArc(reactionConfig.beamX, reactionConfig.beamY, 1); + arc->SetLineColor(2); + detArc1->SetFillStyle(0); + arc->Draw("same"); + } + } + + if( pID == pRecoilXY1 ){ + TH2F * hRecoilXY1 = new TH2F("hRecoilXY1", Form("RecoilXY-1 [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[detGeoID].detPos1 ), + 400, -detGeo.aux[detGeoID].outerRadius, detGeo.aux[detGeoID].outerRadius, + 400, -detGeo.aux[detGeoID].outerRadius, detGeo.aux[detGeoID].outerRadius); + tree->Draw("yRecoil1:xRecoil1>>hRecoilXY1", gate, "colz"); + } + + if( pID == pRecoilXY2 ){ + TH2F * hRecoilXY2 = new TH2F("hRecoilXY2", Form("RecoilXY-2 [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[detGeoID].detPos2 ), + 400, -detGeo.aux[detGeoID].outerRadius, detGeo.aux[detGeoID].outerRadius, + 400, -detGeo.aux[detGeoID].outerRadius, detGeo.aux[detGeoID].outerRadius); + tree->Draw("yRecoil2:xRecoil2>>hRecoilXY2", gate, "colz"); + } + + if( pID == pRecoilRZ ){ + TH2F * hRecoilRZ = new TH2F("hRecoilRZ", "RecoilR - Z [gated]; z [mm]; RecoilR [mm]", zRange[0], zRange[1], zRange[2], 400,0, detGeo.aux[detGeoID].outerRadius); + tree->Draw("rhoRecoil:z>>hRecoilRZ", gate, "colz"); + } + + if( pID == pRecoilRTR ){ + FindRange("TB", gate, tree, recoilERange); + TH2F * hRecoilRTR = new TH2F("hRecoilRTR", "RecoilR - recoilE [gated]; recoil Energy [MeV]; RecoilR [mm]", 500, recoilERange[0], recoilERange[1], 500, 0, detGeo.aux[detGeoID].outerRadius); + tree->Draw("rhoRecoil:TB>>hRecoilRTR", gate, "colz"); + } + + if( pID == pTDiffZ ){ + double tDiffRange [2]; + FindRange("t-tB", gate, tree, tDiffRange); + TH2F * hTDiffZ = new TH2F("hTDiffZ", "time(Array) - time(Recoil) vs Z [gated]; z [mm]; time diff [ns]", zRange[0], zRange[1], zRange[2], 500, tDiffRange[0], tDiffRange[1]); + tree->Draw("t - tB : z >> hTDiffZ", gate, "colz"); + } + + if( pID == pThetaCM ){ + TH1F * hThetaCM[numEx]; + TLegend * legend = new TLegend(0.8,0.2,0.99,0.8); + double maxCount = 0; + int startID = 0; // set the start ExID + for( int i = startID; i < numEx; i++){ + hThetaCM[i] = new TH1F(Form("hThetaCM%d", i), Form("thetaCM [gated] (ExID=%d); thetaCM [deg]; count", i), 200, thetaCMRange[0], thetaCMRange[1]); + hThetaCM[i]->SetLineColor(i+1-startID); + hThetaCM[i]->SetFillColor(i+1-startID); + hThetaCM[i]->SetFillStyle(3000+i-startID); + tree->Draw(Form("thetaCM>>hThetaCM%d", i), gate + Form("&& ExID==%d", i), ""); + legend->AddEntry(hThetaCM[i], Form("Ex=%5.1f MeV", exList.ExList[i].Ex)); + double max = hThetaCM[i]->GetMaximum(); + if( max > maxCount ) maxCount = max; + } + + for( int i = startID; i < numEx; i++){ + hThetaCM[i]->GetYaxis()->SetRangeUser(1, maxCount * 1.2); + if( i == startID ) { + hThetaCM[i]->Draw(); + }else{ + hThetaCM[i]->Draw("same"); + } + } + legend->Draw(); + } + + if( pID == pThetaCM_Z ){ + TH2F *hThetaCM_Z = new TH2F("hThetaCM_Z","ThetaCM vs Z ; Z [mm]; thetaCM [deg]",zRange[0], zRange[1], zRange[2], 200, thetaCMRange[0], thetaCMRange[1]); + tree->Draw("thetaCM:z>>hThetaCM_Z",gate,"col"); + if( shownKELines){ + for( int i = 0; i < numEx ; i++){ + txList->At(i)->Draw("same"); + } + } + } + + if( pID == pExCal ){ + TH1F * hExCal = new TH1F("hExCal", Form("calculated Ex [gated]; Ex [MeV]; count / %.2f keV", (ExRange[1]-ExRange[0])/400.*1000), 400, ExRange[0], ExRange[1]); + tree->Draw("ExCal>>hExCal", gate, ""); + Isotope hRecoil(recoil.heavyA, recoil.heavyZ); + double Sn = hRecoil.CalSp(0,1); + double Sp = hRecoil.CalSp(1,0); + double Sa = hRecoil.CalSp2(4,2); + double S2n = hRecoil.CalSp(0, 2); + + printf("Heavy recoil: %s \n", hRecoil.Name.c_str()); + printf("Sn : %f MeV/u \n", Sn); + printf("Sp : %f MeV/u \n", Sp); + printf("Sa : %f MeV/u \n", Sa); + printf("S2n : %f MeV/u \n", S2n); + + double yMax = hExCal->GetMaximum(); + TLine * lineSn = new TLine(Sn, 0, Sn, yMax); lineSn->SetLineColor(2); lineSn->Draw(""); + TLine * lineSp = new TLine(Sp, 0, Sp, yMax); lineSp->SetLineColor(4); lineSp->Draw("same"); + TLine * lineSa = new TLine(Sa, 0, Sa, yMax); lineSa->SetLineColor(6); lineSa->Draw("same"); + TLine * lineS2n = new TLine(S2n, 0, S2n, yMax); lineS2n->SetLineColor(8); lineS2n->Draw("same"); + + TLatex * text = new TLatex(); + text->SetTextFont(82); + text->SetTextSize(0.06); + text->SetTextColor(2); text->DrawLatex(Sn, yMax*0.9, "S_{n}"); + text->SetTextColor(4); text->DrawLatex(Sp, yMax*0.9, "S_{p}"); + text->SetTextColor(6); text->DrawLatex(Sa, yMax*0.9, "S_{a}"); + text->SetTextColor(8); text->DrawLatex(S2n, yMax*0.9, "S_{2n}"); + + } + + if( pID == pRecoilRThetaCM ){ + TH2F * hRecoilRThetaCM = new TH2F("hRecoilRThetaCM", "RecoilR - thetaCM [gated]; thetaCM [deg]; RecoilR [mm]", 400, 0, 60, 400,0, detGeo.aux[detGeoID].outerRadius); + tree->Draw("rhoRecoil:thetaCM>>hRecoilRThetaCM", gate, "colz"); + } + + if( pID == pArrayXY ){ + TH2F * hArrayXY = new TH2F("hArrayXY", "Array-XY [gated]; X [mm]; Y [mm]", 400, -array.detPerpDist*1.5, array.detPerpDist*1.5, 400, -array.detPerpDist*1.5, array.detPerpDist*1.5); + tree->Draw("yArray:xArray>>hArrayXY", gate, "colz"); + } + + if( pID == pInfo ){ + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.06); + text.SetTextColor(2); + + text.DrawLatex(0., 0.9, Reaction); + text.DrawLatex(0., 0.8, detGeo.Bfield > 0 ? "out of plan" : "into plan"); + text.SetTextColor(1); + text.DrawLatex(0., 0.7, "gate:"); + + text.SetTextColor(2); + //check gate text length, if > 30, break by "&&" + int ll = gate.Length(); + if( ll > 30 ) { + vector strList = AnalysisLib::SplitStr( (string) gate.Data(), "&&"); + for( int i = 0; i < strList.size(); i++){ + text.DrawLatex(0., 0.6 - 0.05*i, (TString) strList[i]); + } + }else{ + text.DrawLatex(0., 0.6, gate); + } + + if( reactionConfig.beamX != 0.0 || reactionConfig.beamY != 0.0 ){ + text.DrawLatex(0.0, 0.1, Form("Bema pos: (%4.1f, %4.1f) mm", reactionConfig.beamX, reactionConfig.beamY)); + } + } + + if( pID == pElum1XY ){ + TH2F * hElum1XY = new TH2F("hElum1XY", Form("Elum-1 XY [gated] @ %.0f mm ; X [mm]; Y [mm]", detGeo.aux[detGeoID].elumPos1), 400, -elumRange, elumRange, 400, -elumRange, elumRange); + tree->Draw("yElum1:xElum1>>hElum1XY", gate, "colz"); + + double count = hElum1XY->GetEntries(); + + if( count < 2000. ) { + hElum1XY->SetMarkerStyle(7); + if( count < 500. ) hElum1XY->SetMarkerStyle(3); + hElum1XY->Draw("scat"); + } + } + + if( pID == pEElum1R ){ + TH2F * hEElum1Rho = new TH2F("hEElum1Rho", "Elum-1 E-R [gated]; R[mm]; Energy[MeV]", 400, 0, elumRange, 400, eRange[0], eRange[1]); + tree->Draw("Tb:rhoElum1>>hEElum1Rho", gate, "colz"); + } + + if( pID == pElum1RThetaCM){ + int angBin = 400; + + TH2F * hElum1RThetaCM = new TH2F("hElum1RThetaCM", "Elum-1 rho vs ThetaCM [gated]; thatCM [deg]; Elum- rho [mm]", angBin, thetaCMRange[0], thetaCMRange[1], 400, 0, elumRange); + tree->Draw("rhoElum1:thetaCM>>hElum1RThetaCM", gate, "colz"); + + TH1F * htemp = (TH1F *) hElum1RThetaCM->ProjectionX("htemp"); + + double rel = (thetaCMRange[1] - thetaCMRange[0])*1.0/angBin; + printf("angular resolution : %f deg \n", rel); + + vector xList; + double old_y = 0; + for( int i = 1; i <= angBin; i++){ + double y = htemp->GetBinContent(i); + if( old_y == 0 && y > 0) xList.push_back(htemp->GetBinCenter(i)); + if( old_y > 0 && y == 0 ) xList.push_back(htemp->GetBinCenter(i)); + old_y = y; + } + + printf("list of gaps :\n"); + for( int i = 0; i < (int) xList.size(); i+=2){ + printf("%d | %.3f - %.3f deg\n", i, xList[i], xList[i+1]); + } + + TF1 f1("f1", "sin(x)"); + double acceptance = 0; + double err1 = 0; + double err2 = 0; + for( int i = 0; i < (int) xList.size(); i += 2 ){ + acceptance += f1.Integral(xList[i] * TMath::DegToRad(), xList[i+1] * TMath::DegToRad() ) * TMath::TwoPi(); + err1 += f1.Integral((xList[i]-rel) * TMath::DegToRad(), (xList[i+1] + rel) * TMath::DegToRad() ) * TMath::TwoPi(); + err2 += f1.Integral((xList[i]+rel) * TMath::DegToRad(), (xList[i+1] - rel) * TMath::DegToRad() ) * TMath::TwoPi(); + } + printf("acceptance = %f sr +- %f \n", acceptance, (err1-err2)/2); + + TLatex text; + text.SetTextFont(82); + text.SetTextSize(0.06); + text.SetTextColor(2); + text.SetTextAngle(90); + + for( int i = 0; i < (int) xList.size(); i++){ + text.DrawLatex(xList[i], elumRange/2, Form("%.2f", xList[i])); + } + + text.SetNDC(); + text.SetTextAngle(0); + text.DrawLatex(0.15, 0.15, Form("accp. = %.2f(%.2f) msr", acceptance * 1000., (err1-err2)*1000./2)); + + } + + if( pID == pHitID ){ + printf("=======================meaning of Hit ID\n"); + printf(" 1 = light recoil hit array & heavy recoil hit recoil\n"); + printf(" 0 = no detector\n"); + printf(" -1 = light recoil go opposite side of array\n"); + printf(" -2 = light recoil hit > det width\n"); + printf(" -3 = light recoil hit > array \n"); + printf(" -4 = light recoil hit blocker \n"); + printf(" -10 = light recoil orbit radius too big \n"); + printf(" -11 = light recoil orbit radius too small\n"); + printf(" -12 = when reocol at the same side of array, light recoil blocked by recoil detector\n"); + printf(" -13 = more than 3 loops\n"); + printf(" -14 = heavy recoil did not hit recoil \n"); + printf(" -15 = cannot find hit on array\n"); + printf(" -20 = unknown\n"); + printf("===========================================\n"); + + TH1F * hHit = new TH1F("hHit", "hit; hit-ID; count", 13, -11, 2); + tree->Draw("hit>>hHit", "", ""); + } + + } + + cCheck->Modified(); + cCheck->Update(); + + if( outputCanvas ){ + TDatime dateTime; + TString outPNGName = Form("Sim_%d%02d%02d_%06d.png", dateTime.GetYear(), dateTime.GetMonth(), dateTime.GetDay(), dateTime.GetTime()); + + cCheck->SaveAs(outPNGName); + printf("%s\n", outPNGName.Data()); + + gROOT->ProcessLine(".q"); + + } +} + +///============================================================ +///============================================================ + +double * FindRange(TString branch, TString gate, TTree * tree, double output[2]){ + tree->Draw(Form("%s>>temp1", branch.Data()), gate); + TH1F * temp1 = (TH1F *) gROOT->FindObjectAny("temp1"); + + output[1] = temp1->GetXaxis()->GetXmax(); + output[0] = temp1->GetXaxis()->GetXmin(); + + delete temp1; + return output; +} + +double ExtractNumber(int index, TMacro * macro){ + + TString field = macro->GetListOfLines()->At(index)->GetName(); + int pos = field.First('/'); + if( pos >= 0 ) field.Remove(pos); + + return field.Atof(); + +} +TString ExtractString(int index, TMacro * macro){ + + TString field = macro->GetListOfLines()->At(index)->GetName(); + + int pos = field.First('/'); + if( pos >= 0 ) field.Remove(pos); + + return field; + +} + +vector StringToVector(TString str){ + + vector temp; + + bool startFlag = false; + bool endFlag = false; + string jaja=""; + for(int i = 0; i < str.Length(); i++){ + + if( str[i] == '{' ) { + startFlag = true; + continue; + } + if( str[i] == ' '){ + continue; + } + if( startFlag && !endFlag){ + + if( str[i] == ',' ){ + temp.push_back(jaja); + jaja=""; + continue; + } + + if( str[i] == '}') { + temp.push_back(jaja); + endFlag = true; + continue; + } + jaja += str[i]; + + } + } + return temp; +} + +vector intConvertor(vector arr){ + vector out ; + for( int i = 0 ; i < (int) arr.size(); i++){ + out.push_back( arr[i].Atoi()); + } + return out; +} +vector doubleConvertor(vector arr){ + vector out ; + for( int i = 0 ; i < (int) arr.size(); i++){ + out.push_back( arr[i].Atof()); + } + return out; +} + +plotID StringToPlotID(TString str){ + + if( str == "pEZ") return plotID::pEZ; /// 0 + if( str == "pRecoilXY") return plotID::pRecoilXY; /// 1 + if( str == "pThetaCM" ) return plotID::pThetaCM; /// 2 + if( str == "pExCal" ) return plotID::pExCal; /// 2 + if( str == "pArrayXY" ) return plotID::pArrayXY; /// 3 + if( str == "pInfo" ) return plotID::pInfo; /// 4 + if( str == "pElum1XY" ) return plotID::pElum1XY; /// 5 + if( str == "pRecoilXY1" ) return plotID::pRecoilXY1; /// 6 + if( str == "pRecoilXY2" ) return plotID::pRecoilXY2; /// 7 + if( str == "pTDiffZ" ) return plotID::pTDiffZ; /// 8 + if( str == "pRecoilRThetaCM" ) return plotID::pRecoilRThetaCM; /// 9 + if( str == "pRecoilRZ" ) return plotID::pRecoilRZ; /// 10 + if( str == "pEElum1R" ) return plotID::pEElum1R; /// 11 + if( str == "pRecoilRTR" ) return plotID::pRecoilRTR; /// 12 + if( str == "pThetaCM_Z" ) return plotID::pThetaCM_Z; /// 13 + if( str == "pElum1RThetaCM" ) return plotID::pElum1RThetaCM; /// 14 + + if( str == "pHitID" ) return plotID::pHitID; /// 13 + if( str == "pEmpty" ) return plotID::pEmpty ; /// 16 + + return plotID::pEmpty; +} diff --git a/cleopatra/ClassDecay.h b/cleopatra/ClassDecay.h new file mode 100644 index 0000000..7aefb40 --- /dev/null +++ b/cleopatra/ClassDecay.h @@ -0,0 +1,180 @@ +#ifndef decay_h +#define decay_h + +#include "TVector3.h" + +#include "../Cleopatra/ClassIsotope.h" +#include "../Armory/ClassReactionConfig.h" + +//======================================================= +//####################################################### +// Class for Particle Decay +// B --> d + D +// input : TLorentzVector, emitting particle +// output : scattered TLorentzVector +//======================================================= +class Decay{ +public: + Decay(); + ~Decay(); + + double GetQValue() { return Q;} + + double GetAngleChange(){ + TVector3 vD = PD.Vect(); + TVector3 vB = PB.Vect(); + vD.SetMag(1); + vB.SetMag(1); + double dot = vD.Dot(vB); + return TMath::ACos(dot)*TMath::RadToDeg() ; + } + + double GetThetaCM() { return theta * TMath::RadToDeg();} + + double GetCMMomentum(){ return k;} + TLorentzVector GetDaugther_d() {return Pd;} + TLorentzVector GetDaugther_D() {return PD;} + + void SetMotherDaugther(Recoil recoil){ + + Isotope Mother(recoil.heavyA, recoil.heavyZ); + Isotope Daugther_D(recoil.decayA, recoil.decayZ); + Isotope Daugther_d(recoil.heavyA - recoil.decayA, recoil.heavyZ - recoil.decayZ); + + zB = recoil.heavyZ; + zD = recoil.decayZ; + zd = recoil.heavyZ - recoil.decayZ; + + mB = Mother.Mass; + mD = Daugther_D.Mass; + md = Daugther_d.Mass; + + double Q = mB - mD - md; + + printf("====== decay mode : %s --> %s + %s, Q = %.3f MeV \n", Mother.Name.c_str(), Daugther_d.Name.c_str(), Daugther_D.Name.c_str(), Q); + + isMotherSet = true; + + } + + void SetMotherDaugther(int AB, int zB, int AD, int zD){ + Isotope Mother(AB, zB); + Isotope Daugther_D(AD, zD); + Isotope Daugther_d(AB-AD, zB-zD); + + mB = Mother.Mass; + mD = Daugther_D.Mass; + md = Daugther_d.Mass; + + double Q = mB - mD - md; + + printf("====== decay mode : %s --> %s + %s, Q = %.3f MeV \n", Mother.Name.c_str(), Daugther_d.Name.c_str(), Daugther_D.Name.c_str(), Q); + + isMotherSet = true; + } + + int CalDecay(TLorentzVector P_mother, double ExB, double ExD, double normOfReactionPlane = 0){ + if( !isMotherSet ) { + return -1; + } + this->PB = P_mother; + + double MB = mB + ExB; ///mother + double MD = mD + ExD; ///Big_Daugther + Q = MB - MD - md; + if( Q < 0 ) { + this->PD = this->PB; + dTheta = TMath::QuietNaN(); + k = TMath::QuietNaN(); + return -2; + } + + //clear + TLorentzVector temp(0,0,0,0); + PD = temp; + Pd = temp; + + PD.SetUniqueID(zD); + Pd.SetUniqueID(zd); + + k = TMath::Sqrt((MB+MD+md)*(MB+MD-md)*(MB-MD+md)*(MB-MD-md))/2./MB; + + //in mother's frame, assume isotropic decay + theta = TMath::ACos(2 * gRandom->Rndm() - 1) ; + + //for non isotropic decay, edit f1. + //theta = TMath::ACos(f1->GetRandom()); + + double phi = TMath::TwoPi() * gRandom->Rndm(); + PD.SetE(TMath::Sqrt(mD * mD + k * k )); + PD.SetPz(k); + PD.SetTheta(theta); + PD.SetPhi(phi); + + Pd.SetE(TMath::Sqrt(md * md + k * k )); + Pd.SetPz(k); + Pd.SetTheta(theta + TMath::Pi()); + Pd.SetPhi(phi + TMath::Pi()); + + PD.RotateY(TMath::Pi()/2.); + PD.RotateZ(normOfReactionPlane); + + Pd.RotateY(TMath::Pi()/2.); + Pd.RotateZ(normOfReactionPlane); + + //Transform to Lab frame; + TVector3 boost = PB.BoostVector(); + + PD.Boost(boost); + Pd.Boost(boost); + + return 1; + } + +private: + TLorentzVector PB, Pd, PD; + + double mB, mD, md; + double zB, zD, zd; + double theta; + + TF1 * f1; + + bool isMotherSet; + double Q; + double k; // momentum in B-frame + double dTheta; // change of angle +}; + +Decay::Decay(){ + TLorentzVector temp(0,0,0,0); + PB = temp; + Pd = temp; + PD = temp; + + mB = TMath::QuietNaN(); + mD = TMath::QuietNaN(); + md = TMath::QuietNaN(); + + zB = 0; + zD = 0; + zd = 0; + + theta = TMath::QuietNaN(); + + k = TMath::QuietNaN(); + + Q = TMath::QuietNaN(); + dTheta = TMath::QuietNaN(); + isMotherSet = false; + + // f1 = new TF1("f1", "(1+ROOT::Math::legendre(2,x))/2.", -1, 1); //need to compile ROOT with -Dmathmore=ON + f1 = new TF1("f1", "sin(x)", -1, 1); +} + +Decay::~Decay(){ + delete f1; +} + + +#endif \ No newline at end of file diff --git a/cleopatra/ClassHelios.h b/cleopatra/ClassHelios.h new file mode 100644 index 0000000..6ab1893 --- /dev/null +++ b/cleopatra/ClassHelios.h @@ -0,0 +1,551 @@ +#ifndef HELIOS_Library_h +#define HELIOS_Library_h + +#include "TBenchmark.h" +#include "TLorentzVector.h" +#include "TVector3.h" +#include "TMath.h" +#include "TFile.h" +#include "TTree.h" +#include "TRandom.h" +#include "TMacro.h" +#include "TGraph.h" +#include +#include + +#include "../Armory/AnalysisLib.h" +#include "../Armory/ClassDetGeo.h" +#include "../Armory/ClassReactionConfig.h" + +//======================================================= +//####################################################### +//Class for HELIOS +//input Lorentz vector, detector configuration +//output e, z, Ex, thetaCM, etc +//======================================================= + +struct trajectory{ + double theta, phi; + double vt, vp; // tranvser and perpendicular velocity + double rho; // orbit radius + double z0, t0; // position cycle + double x, y, z; // hit position + double t; //actual orbit time; + double R; //hit radius = sqrt(x^2+y^2); + int detID, detRowID; + int loop; + double effLoop; + + void PrintTrajectory(){ + printf("=====================\n"); + printf(" theta : %f deg\n", theta*TMath::RadToDeg()); + printf(" phi : %f deg\n", phi*TMath::RadToDeg()); + printf(" vt : %f mm/ns\n", vt); + printf(" vp : %f mm/ns\n", vp); + printf(" rho : %f mm\n", rho); + printf(" z0 : %f mm\n", z0); + printf(" t0 : %f ns\n", t0); + printf("(x, y, z) : (%f, %f. %f) mm\n", x, y, z); + printf(" R : %f mm\n", R); + printf(" t : %f ns\n", t); + printf(" effLoop : %f cycle\n", effLoop); + printf(" Loop : %d cycle\n", loop); + printf(" detRowID : %d \n", detRowID); + printf(" detID : %d \n", detID); + + } + + void Clear(){ + theta = TMath::QuietNaN(); + phi = TMath::QuietNaN(); + vt = TMath::QuietNaN(); + vp = TMath::QuietNaN(); + rho = TMath::QuietNaN(); + z0 = TMath::QuietNaN(); + t0 = TMath::QuietNaN(); + x = TMath::QuietNaN(); + y = TMath::QuietNaN(); + z = TMath::QuietNaN(); + effLoop = TMath::QuietNaN(); + detID = -1; + detRowID = -1; + loop = -1; + } +}; + +class HELIOS{ +public: + + HELIOS(); + HELIOS(std::string detGeoFile, unsigned short ID); + ~HELIOS(); + + void SetCoincidentWithRecoil(bool TorF){ this->isCoincidentWithRecoil = TorF;} + bool GetCoincidentWithRecoil(){return this->isCoincidentWithRecoil;} + bool SetDetectorGeometry(std::string filename, unsigned short ID); + void SetBeamPosition(double x, double y) { xOff = x; yOff = y;} + + void OverrideMagneticField(double BField); + void OverrideFirstPos(double firstPos); + void OverrideDetectorDistance(double perpDist); + void OverrideDetectorFacing(bool isOutside); + + int CheckDetAcceptance(); + int CalArrayHit(TLorentzVector Pb, bool debug = false); + int CalRecoilHit(TLorentzVector PB); + void CalTrajectoryPara(TLorentzVector P, bool isLightRecoil); + + int GetNumberOfDetectorsInSamePos(){return array.rowDet;} + double GetEnergy()const {return e;} + double GetDetX() const {return detX;} // position in each detector, range from -1, 1 + + /// clockwise rotation for B-field along the z-axis, sign = 1. + double XPos(double Zpos, double theta, double phi, double rho, int sign){ + if( TMath::IsNaN(Zpos) ) return TMath::QuietNaN(); + return rho * ( TMath::Sin( TMath::Tan(theta) * Zpos / rho - sign * phi ) + sign * TMath::Sin(phi) ) + xOff; + } + double YPos(double Zpos, double theta, double phi, double rho, int sign){ + if( TMath::IsNaN(Zpos) ) return TMath::QuietNaN(); + return rho * sign * (TMath::Cos( TMath::Tan(theta) * Zpos / rho - sign * phi ) - TMath::Cos(phi)) + yOff; + } + double RPos(double Zpos, double theta, double phi, double rho, int sign){ + if( TMath::IsNaN(Zpos) ) return TMath::QuietNaN(); + double x = XPos(Zpos, theta, phi, rho, sign) ; + double y = YPos(Zpos, theta, phi, rho, sign) ; + return sqrt(x*x+y*y); + } + + double GetXPos(double ZPos){ return TMath::IsNaN(ZPos) ? TMath::QuietNaN() : XPos( ZPos, orbitb.theta, orbitb.phi, orbitb.rho, detGeo.BfieldSign); } + double GetYPos(double ZPos){ return TMath::IsNaN(ZPos) ? TMath::QuietNaN() : YPos( ZPos, orbitb.theta, orbitb.phi, orbitb.rho, detGeo.BfieldSign); } + double GetR(double ZPos) { return TMath::IsNaN(ZPos) ? TMath::QuietNaN() : RPos( ZPos, orbitb.theta, orbitb.phi, orbitb.rho, detGeo.BfieldSign); } + + double GetRecoilEnergy(){return eB;} + double GetRecoilXPos(double ZPos){ return TMath::IsNaN(ZPos) ? TMath::QuietNaN() : XPos( ZPos, orbitB.theta, orbitB.phi, orbitB.rho, detGeo.BfieldSign); } + double GetRecoilYPos(double ZPos){ return TMath::IsNaN(ZPos) ? TMath::QuietNaN() : YPos( ZPos, orbitB.theta, orbitB.phi, orbitB.rho, detGeo.BfieldSign); } + double GetRecoilR(double ZPos) { return TMath::IsNaN(ZPos) ? TMath::QuietNaN() : RPos( ZPos, orbitB.theta, orbitB.phi, orbitB.rho, detGeo.BfieldSign); } + + void PrintGeometry() const; + + double GetBField() const {return detGeo.Bfield;} + double GetDetRadius() const {return array.detPerpDist;} + + trajectory GetTrajectory_b() const {return orbitb;} + trajectory GetTrajectory_B() const {return orbitB;} + + DetGeo GetDetectorGeometry() const {return detGeo;} + Array GetArrayGeometry() const {return array;} + Auxillary GetAuxGeometry() const {return aux;} + + TString GetHitMessage() {return hitMessage;} + TString GetAcceptanceMessage() { AcceptanceCodeToMsg(acceptanceCode); return acceptanceMsg;} + + TString AcceptanceCodeToMsg(short code ); + +private: + + DetGeo detGeo; + Array array; + Auxillary aux; + + trajectory orbitb, orbitB; + + double e,detX ; ///energy of light recoil, position X + double rhoHit; /// radius of particle-b hit on recoil detector + + double eB; ///energy of heavy recoil + + bool isDetReady; + + TString hitMessage; + TString acceptanceMsg; //acceptance check + short acceptanceCode; + + double xOff, yOff; // beam position + + bool overrideDetDistance; + bool overrideFirstPos; + bool isCoincidentWithRecoil; + + const double c = 299.792458; //mm/ns + + void Clear(); + +}; + +HELIOS::HELIOS(){ + Clear(); +} + +HELIOS::HELIOS(std::string detGeoFile, unsigned short ID){ + Clear(); + SetDetectorGeometry(detGeoFile, ID); +} + +HELIOS::~HELIOS(){ + +} + +void HELIOS::Clear(){ + + orbitb.Clear(); + orbitB.Clear(); + + e = TMath::QuietNaN(); + eB = TMath::QuietNaN(); + detX = TMath::QuietNaN(); + rhoHit = TMath::QuietNaN(); + + xOff = 0.0; + yOff = 0.0; + + isDetReady = false; + + hitMessage = ""; + acceptanceMsg = ""; + acceptanceCode = 0; + + overrideDetDistance = false; + overrideFirstPos = false; + isCoincidentWithRecoil = false; +} + +void HELIOS::OverrideMagneticField(double BField){ + this->detGeo.Bfield = BField; + this->detGeo.BfieldSign = BField > 0 ? 1: -1; +} + +void HELIOS::OverrideFirstPos(double firstPos){ + overrideFirstPos = true; + printf("------ Overriding FirstPosition to : %8.2f mm \n", firstPos); + this->array.firstPos = firstPos; +} + +void HELIOS::OverrideDetectorDistance(double perpDist){ + overrideDetDistance = true; + printf("------ Overriding Detector Distance to : %8.2f mm \n", perpDist); + this->array.detPerpDist = perpDist; +} + +void HELIOS::OverrideDetectorFacing(bool isOutside){ + this->array.detFaceOut = isOutside; + printf(" Detectors are facing %s\n", array.detFaceOut ? "outside": "inside" ); +} + +bool HELIOS::SetDetectorGeometry(std::string filename, unsigned short ID){ + + if( detGeo.LoadDetectorGeo(filename, false)) { + + array = detGeo.array[ID]; + aux = detGeo.aux[ID]; + isCoincidentWithRecoil = detGeo.aux[ID].isCoincident; + isDetReady = true; + + }else{ + printf("cannot read file %s.\n", filename.c_str()); + isDetReady = false; + } + + return isDetReady; +} + +void HELIOS::PrintGeometry() const{ + + printf("=====================================================\n"); + printf(" B-field : %8.2f T, %s\n", detGeo.Bfield, detGeo.Bfield > 0 ? "out of plan" : "into plan"); + printf(" Bore : %8.2f mm\n", detGeo.bore); + printf("----------------------------------- Detector Position \n"); + array.Print(); + aux.Print(); + printf("=====================================================\n"); + +} + +TString HELIOS::AcceptanceCodeToMsg(short code ){ + + switch(code){ + case 3 : acceptanceMsg = "try one more loop"; break; + case 2 : acceptanceMsg = "hit less than the nearest array. increase loop"; break; + case 1 : acceptanceMsg = "GOOD!! hit Array"; break; + + case 0 : acceptanceMsg = "detector geometry incomplete."; break; + case -1 : acceptanceMsg = "array at upstream, z is downstream."; break; + case -2 : acceptanceMsg = "array at downstream, z is upstream."; break; + case -3 : acceptanceMsg = "hit at the XY gap."; break; + case -4 : acceptanceMsg = "hit more upstream than the array length"; break; + case -5 : acceptanceMsg = "hit more downstream than the array length"; break; + case -6 : acceptanceMsg = "hit blocker"; break; + case -7 : acceptanceMsg = "hit array Z-gap"; break; + + case -10 : acceptanceMsg = "rho is too big"; break; + case -11 : acceptanceMsg = "rho is too small"; break; + case -12 : acceptanceMsg = "light recoil blocked by recoil detector"; break; + case -13 : acceptanceMsg = "more than 3 loops."; break; + case -14 : acceptanceMsg = "heavy recoil does not hit recoil detector"; break; + case -15 : acceptanceMsg = "det Row ID == -1"; break; + default : acceptanceMsg = "unknown error."; break; + } + + return acceptanceMsg; + +} + +int HELIOS::CheckDetAcceptance(){ + + //CalArrayHit and CalRecoilHit must be done before. + + if( isDetReady == false ) { acceptanceCode = 0; return acceptanceCode; } + + // -1 ========= when recoil direction is not same side of array + if( array.firstPos < 0 && orbitb.z > 0 ) {acceptanceCode = -1; return acceptanceCode;} + + // -2 ========= when recoil direction is not same side of array + if( array.firstPos > 0 && orbitb.z < 0 ) {acceptanceCode = -2; return acceptanceCode;} + + // -11 ======== rho is too small + if( 2 * orbitb.rho < array.detPerpDist ) { acceptanceCode = -11; return acceptanceCode;} + + // -15 ========= if detRowID == -1, should be (2 * orbitb.rho < perpDist) + if( orbitb.detRowID == -1 ) {acceptanceCode = -15; return acceptanceCode;} + + // -10 =========== when rho is too big . + if( array.detFaceOut && detGeo.bore < 2 * orbitb.rho) { acceptanceCode = -10; return acceptanceCode;} + + // -14 ========== check particle-B hit radius on recoil dectector + if( isCoincidentWithRecoil && orbitB.R > aux.outerRadius ) {acceptanceCode = -14; return acceptanceCode;} + + //if( isCoincidentWithRecoil && (orbitB.R > rhoRecoilout || orbitB.R < rhoRecoilin) ) return -14; + + // -12 ========= check is particle-b was blocked by recoil detector + rhoHit = GetR(aux.detPos); + if( orbitb.z > 0 && aux.detPos > 0 && orbitb.z > aux.detPos && rhoHit < aux.outerRadius ) { acceptanceCode = -12; return acceptanceCode;} + if( orbitb.z < 0 && aux.detPos < 0 && orbitb.z < aux.detPos && rhoHit < aux.outerRadius ) { acceptanceCode = -12; return acceptanceCode;} + + // -13 ========= not more than 3 loops + if( orbitb.loop > 3 ) {acceptanceCode = -13; return acceptanceCode;} + + // -3 ========= calculate the "y"-distance from detector center + if( sqrt(orbitb.R*orbitb.R - array.detPerpDist * array.detPerpDist)> array.detWidth/2 ) { acceptanceCode = -3; return acceptanceCode;} + + // -4, -5 ==== when zPos further the range of whole array, more loop would not save + if( array.firstPos < 0 && orbitb.z < array.detPos[0] - array.detLength ) { acceptanceCode = -4; return acceptanceCode;} + if( array.firstPos > 0 && orbitb.z > array.detPos[array.colDet-1] + array.detLength ) { acceptanceCode = -5; return acceptanceCode;} + + // -6 ======== Hit on blacker + if( array.blocker != 0 && array.firstPos > 0 && array.detPos[0] - array.blocker < orbitb.z && orbitb.z < array.detPos[0] ) {acceptanceCode = -6; return acceptanceCode;} + if( array.blocker != 0 && array.firstPos < 0 && array.detPos[array.colDet-1] < orbitb.z && orbitb.z < array.detPos[array.colDet-1] + array.blocker ) { acceptanceCode = -6; return acceptanceCode;} + + // 2 ====== when zPos less then the nearest position, more loop may hit + int increaseLoopFlag = 0; + if( array.firstPos < 0 && array.detPos[array.colDet-1] < orbitb.z ) increaseLoopFlag = 2; + if( array.firstPos > 0 && array.detPos[0] > orbitb.z ) increaseLoopFlag = 2; + if (increaseLoopFlag == 2 ) { + orbitb.z += orbitb.z0; + orbitb.effLoop += 1.0; + orbitb.loop += 1; + orbitb.t = orbitb.t0 * orbitb.effLoop; + acceptanceCode = 2; + return acceptanceCode; + } + + // 1 ======= check hit array z- position + if( array.firstPos < 0 ){ + for( int i = 0; i < array.colDet; i++){ + if( array.detPos[i] - array.detLength <= orbitb.z && orbitb.z <= array.detPos[i]) { + orbitb.detID = i; + detX = ( orbitb.z - (array.detPos[i] + array.detLength/2 ))/ array.detLength * 2 ;// range from -1 , 1 + acceptanceCode = 1; + return acceptanceCode; + } + } + }else{ + for( int i = 0; i < array.colDet ; i++){ + if( array.detPos[i] <= orbitb.z && orbitb.z <= array.detPos[i] + array.detLength) { + ///printf(" %d | %f < z = %f < %f \n", i, array.detPos[i], orbitb.z, array.detPos[i]+length); + orbitb.detID = i; + detX = ( orbitb.z - (array.detPos[i] - array.detLength/2 ))/ array.detLength*2 ;// range from -1 , 1 + acceptanceCode = 1; + return acceptanceCode; + } + } + } + + + // -7 ======== check hit array gap + if( array.firstPos < 0 ){ + for( int i = 0; i < array.colDet-1 ; i++){ + if( array.detPos[i] < orbitb.z && orbitb.z < array.detPos[i+1] - array.detLength ) { acceptanceCode = -7; return acceptanceCode; }//increaseLoopFlag = 3; + } + }else{ + for( int i = 0; i < array.colDet-1 ; i++){ + if( array.detPos[i] + array.detLength < orbitb.z && orbitb.z < array.detPos[i+1] ) { acceptanceCode = -7; return acceptanceCode; }//increaseLoopFlag = 3; + } + } + if (increaseLoopFlag == 3 ) { + orbitb.z += orbitb.z0; + orbitb.effLoop += 1.0; + orbitb.loop += 1; + orbitb.t = orbitb.t0 * orbitb.effLoop; + acceptanceCode = 3; + return acceptanceCode; + } + + acceptanceCode = -20 ; + return acceptanceCode; // for unknown reason +} + +void HELIOS::CalTrajectoryPara(TLorentzVector P, bool isLightRecoil){ + + if( isLightRecoil ){ + orbitb.theta = P.Theta(); + orbitb.phi = P.Phi(); + orbitb.rho = P.Pt() / abs(detGeo.Bfield) / P.GetUniqueID() / c * 1000; //mm + orbitb.vt = P.Beta() * TMath::Sin(P.Theta()) * c ; // mm / nano-second + orbitb.vp = P.Beta() * TMath::Cos(P.Theta()) * c ; // mm / nano-second + orbitb.t0 = TMath::TwoPi() * orbitb.rho / orbitb.vt; // nano-second + orbitb.z0 = orbitb.vp * orbitb.t0; + + orbitb.detID = -1; + orbitb.detRowID = -1; + + }else{ + orbitB.theta = P.Theta(); + orbitB.phi = P.Phi(); + orbitB.rho = P.Pt() / abs(detGeo.Bfield) / P.GetUniqueID() / c * 1000; //mm + orbitB.vt = P.Beta() * TMath::Sin(P.Theta()) * c ; // mm / nano-second + orbitB.vp = P.Beta() * TMath::Cos(P.Theta()) * c ; // mm / nano-second + orbitB.t0 = TMath::TwoPi() * orbitB.rho / orbitB.vt; // nano-second + orbitB.z0 = orbitB.vp * orbitB.t0; + + orbitB.detID = -1; + orbitB.detRowID = -1; + } +} + +int HELIOS::CalArrayHit(TLorentzVector Pb, bool debug){ + + e = Pb.E() - Pb.M(); + detX = TMath::QuietNaN(); + rhoHit = TMath::QuietNaN(); + + CalTrajectoryPara(Pb, true); + + int targetLoop = 1; + int inOut = array.detFaceOut == true ? 1: 0; //1 = from Outside, 0 = from inside + + if( debug ) { + printf("===================================\n"); + printf("theta : %f deg, phi : %f deg \n", orbitb.theta * TMath::RadToDeg(), orbitb.phi * TMath::RadToDeg()); + printf("z0: %f mm, rho : %f mm \n", orbitb.z0, orbitb.rho); + printf(" inOut : %d = %s \n", inOut, inOut == 1 ? "Out" : "in"); + printf(" z range : %.2f - %.2f \n", detGeo.zMin, detGeo.zMax); + printf(" B-field sign : %d\n", detGeo.BfieldSign); + printf("-----------------------------------\n"); + } + + std::vector zPossible; + std::vector dID; //detRowID + + int iStart = ( detGeo.BfieldSign == 1 ? 0 : -array.rowDet ); + int iEnd = ( detGeo.BfieldSign == 1 ? 2 * array.rowDet : array.rowDet ); + for( int i = iStart; i < iEnd ; i++){ + + double phiD = TMath::TwoPi()/array.rowDet * i ; + double dphi = orbitb.phi - phiD; + double aEff = array.detPerpDist - (xOff * TMath::Cos(phiD) + yOff * TMath::Sin(phiD)); + double hahaha = asin( aEff/ orbitb.rho - detGeo.BfieldSign * sin(dphi)); + + int n = 2*targetLoop + inOut; + + double zP = orbitb.z0 /TMath::TwoPi() * ( detGeo.BfieldSign * dphi + n * TMath::Pi() + pow(-1, n) * hahaha ); + + if( debug ) { + double xP = GetXPos(zP) ; + double yP = GetYPos(zP) ; + printf("phiD: %4.0f, dphi: %6.1f, mod(pi): %6.1f, Loop : %9.5f, zHit : %8.3f mm, (x,y) = (%7.2f, %7.2f) \n", + phiD * TMath::RadToDeg(), + (orbitb.phi-phiD) * TMath::RadToDeg(), + fmod(orbitb.phi-phiD, TMath::Pi())*TMath::RadToDeg(), + zP/orbitb.z0, zP, xP, yP ); + } + + ///Selection + if( !TMath::IsNaN(zP) && 0 < zP/orbitb.z0 && TMath::Max(0, targetLoop-1) < zP/orbitb.z0 && zP/orbitb.z0 < targetLoop ) { + zPossible.push_back(zP); + dID.push_back(i); + } + } + + if( debug ) printf("-----------------------------------\n"); + double dMin = 1; + for( int i = 0; i < (int) zPossible.size(); i++){ + + double dd = abs(zPossible[i]/orbitb.z0 - (targetLoop - (1-inOut))); + + if( debug ) printf(" %d | zP : %8.3f mm; loop : %9.5f ", i, zPossible[i], zPossible[i]/orbitb.z0); + + if( dd < dMin) { + orbitb.z = zPossible[i]; + dMin = dd; + orbitb.effLoop = zPossible[i]/orbitb.z0; + orbitb.loop = TMath::Ceil(orbitb.effLoop); + orbitb.detRowID = (12+dID[i])%4; + orbitb.t = orbitb.t0 * orbitb.effLoop; + + double phiD = TMath::TwoPi()/array.rowDet * dID[i] ; + double dphi = orbitb.phi - phiD ; + + if( debug ) { + // Check is in or out + double hitDir = cos( orbitb.z/orbitb.z0 * TMath::TwoPi() - detGeo.BfieldSign * dphi ); + printf(" hitDir : %4.1f ", hitDir); + if( ( inOut == 1 && hitDir > 0 ) || (inOut == 0 && hitDir < 0 ) ) { + printf(" != %f ", array.detPerpDist); + orbitb.z = TMath::QuietNaN(); + orbitb.loop = -1; + orbitb.detRowID = -1; + hitMessage = "wrong direction."; + return - 2; + } + + // this must be false, otherwise, calculation error + double xPos = GetXPos(orbitb.z ) ; + double yPos = GetYPos(orbitb.z ) ; + double a = xPos * cos(phiD) + yPos * sin(phiD); + printf(" a : %f ", a); + if( abs(a - array.detPerpDist) > 0.01) { + printf(" != %f ", array.detPerpDist); + orbitb.z = TMath::QuietNaN(); + orbitb.loop = -1; + orbitb.detRowID = -1; + hitMessage = "not on the detector plan."; + return -3; + } + } + } + if(debug) printf("\n"); + } + + // calculate x, y, R + orbitb.x = GetXPos(orbitb.z) ; + orbitb.y = GetYPos(orbitb.z) ; + orbitb.R = GetR(orbitb.z); + + hitMessage = "successful hit."; + return 1; // return 1 when OK +} + +int HELIOS::CalRecoilHit(TLorentzVector PB){ + + CalTrajectoryPara(PB, false); + + orbitB.z = aux.detPos; + orbitB.x = GetRecoilXPos(aux.detPos) ; + orbitB.y = GetRecoilYPos(aux.detPos) ; + orbitB.R = GetRecoilR(aux.detPos); + orbitB.effLoop = orbitB.z/orbitB.z0; + orbitB.t = orbitB.t0 * orbitB.effLoop ; + + return 1; +} + +#endif diff --git a/cleopatra/ClassIsotope.h b/cleopatra/ClassIsotope.h new file mode 100644 index 0000000..4416dba --- /dev/null +++ b/cleopatra/ClassIsotope.h @@ -0,0 +1,520 @@ +/*********************************************************************** + * + * This is Isotope.h, To extract the isotope mass from massXX.txt + * + *------------------------------------------------------- + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + + +#ifndef ISOTOPE_H +#define ISOTOPE_H + +#include +#include +#include +#include +#include +#include +#include "constant.h" // amu +#include //atoi +#include + +std::string massData="../Cleopatra/mass20.txt"; + +// about the mass**.txt +// Mass Excess = (ATOMIC MASS - A)*amu | e.g. n : (1.088664.91585E-6-1)*amu +// mass excess uncertaintly +// BEA = (Z*M(1H) + N*M(1n) - Me(A,Z))/A , Me is the mass with electrons +// BEA = (Z*mp + N*mn - M(A,Z))/A , M is the mass without electrons + +class Isotope { +public: + int A, Z; + double Mass, MassError, BEA; + std::string Name, Symbol; + std::string dataSource; + + Isotope(){dataSource = massData;}; + Isotope(int a, int z){ dataSource = massData; SetIso(a,z); }; + Isotope(std::string name){ dataSource = massData; SetIsoByName(name); }; + + void SetMassTablePath(std::string path){ dataSource = path;} + + void SetIso(int a, int z); + void SetIsoByName(std::string name); + + double CalSp(int Np, int Nn); // this for the Np-proton, Nn-neutron removal + double CalSp2(int a, int z); // this is for (a,z) nucleus removal + + double CalBeta(double T){ + double Etot = Mass + T; + double gamma = 1 + T/Mass; + double beta = sqrt(1 - 1 / gamma / gamma ) ; + return beta; + } + + void Print(); + void ListShell(); + +private: + void FindMassByAZ(int a, int z); // give mass, massError, BEA, Name, Symbol; + void FindMassByName(std::string name); // give Z, mass, massError, BEA; + + int TwoJ(int nShell); + std::string Orbital(int nShell); + int magic(int i){ + switch (i){ + case 0: return 2; break; + case 1: return 8; break; + case 2: return 20; break; + case 3: return 28; break; + case 4: return 40; break; + case 5: return 50; break; + case 6: return 82; break; + case 7: return 128; break; + } + return 0; + } + + int magicShellID(int i){ + switch (i){ + case 0: return 0; break; + case 1: return 2; break; + case 2: return 5; break; + case 3: return 6; break; + case 4: return 9; break; + case 5: return 10; break; + case 6: return 15; break; + case 7: return 21; break; + } + return 0; + } + + int fileStartLine; + int fileEndLine; + int lineMass050_099; + int lineMass100_149; + int lineMass150_199; + int lineMass200; + + + void setFileLines(){ + fileStartLine = 37; + fileEndLine = 3594; + + lineMass050_099 = 466; + lineMass100_149 = 1160; + lineMass150_199 = 1994; + lineMass200 = 2774; + } + + bool isFindOnce; + +}; + +void Isotope::SetIso(int a, int z){ + this->A = a; + this->Z = z; + FindMassByAZ(a,z); +} + +void Isotope::SetIsoByName(std::string name){ + FindMassByName(name); +} + +void Isotope::FindMassByAZ(int A, int Z){ + std::string line; + int lineNum=0; + int list_A, list_Z; + + std::ifstream myfile; + int flag=0; + + setFileLines(); + + int numLineStart = fileStartLine; + int numLineEnd = fileEndLine; + + if ( A >= 50 && A < 100) numLineStart = lineMass050_099; + if ( A >=100 && A < 150) numLineStart = lineMass100_149; + if ( A >=150 && A < 200) numLineStart = lineMass150_199; + if ( A >=200 ) numLineStart = lineMass200; + + myfile.open(dataSource.c_str()); + + if (myfile.is_open()) { + while (/*! myfile.eof() &&*/ flag == 0 && lineNum = numLineStart ){ + list_Z = atoi((line.substr(10,5)).c_str()); + list_A = atoi((line.substr(15,5)).c_str()); + + if ( A == list_A && Z == list_Z) { + this->BEA = atof((line.substr(54,11)).c_str()); + this->Mass = list_Z*mp + (list_A-list_Z)*mn - this->BEA/1000*list_A; + this->MassError = atof((line.substr(65,7)).c_str()); + std::string str = line.substr(20,2); + str.erase(remove(str.begin(), str.end(), ' '), str.end()); + this->Symbol = str; + + std::ostringstream ss; + ss << A << this->Symbol; + this->Name = ss.str(); + flag = 1; + }else if ( list_A > A) { + this->BEA = -404; + this->Mass = -404; + this->MassError = -404; + this->Symbol = "non"; + this->Name = "non"; + break; + } + + } + } + + if( this->Name == "1H" ) this->Name = "p"; + if( this->Name == "2H" ) this->Name = "d"; + if( this->Name == "3H" ) this->Name = "t"; + if( this->Name == "4He" ) this->Name = "a"; + + myfile.close(); + }else { + printf("Unable to open %s\n", dataSource.c_str()); + } +} + +void Isotope::FindMassByName(std::string name){ + + // done seperate the Mass number and the name + if( name == "n" ) { + this->Name = "1n"; + this->BEA = 0; + this->Mass = mn; + this->MassError = 0; + this->Name = "n"; + this->A = 1; + this->Z = 0; + return; + } + if( name == "p" ) name = "1H"; + if( name == "d" ) name = "2H"; + if( name == "t" ) name = "3H"; + if( name == "a" ) name = "4He"; + + std::string temp = name; + int lastDigit = 0; + + for(int i=0; temp[i]; i++){ + if(temp[i] == '0') lastDigit = i; + if(temp[i] == '1') lastDigit = i; + if(temp[i] == '2') lastDigit = i; + if(temp[i] == '3') lastDigit = i; + if(temp[i] == '4') lastDigit = i; + if(temp[i] == '5') lastDigit = i; + if(temp[i] == '6') lastDigit = i; + if(temp[i] == '7') lastDigit = i; + if(temp[i] == '8') lastDigit = i; + if(temp[i] == '9') lastDigit = i; + } + + this->Symbol = temp.erase(0, lastDigit +1); + //check is Symbol is 2 charaters, if not, add " " at the end + if( this->Symbol.length() == 1 ){ + this->Symbol = this->Symbol + " "; + } + + + temp = name; + int len = temp.length(); + temp = temp.erase(lastDigit+1, len); + + this->A = atoi(temp.c_str()); + //printf(" Symbol = |%s| , Mass = %d\n", this->Symbol.c_str(), this->A); + + // find the nucleus in the data + std::string line; + int lineNum=0; + int list_A; + std::string list_symbol; + + std::ifstream myfile; + int flag=0; + + setFileLines(); + + int numLineStart = fileStartLine; + int numLineEnd = fileEndLine; + + if ( A >= 50 && A < 100) numLineStart = lineMass050_099; + if ( A >=100 && A < 150) numLineStart = lineMass100_149; + if ( A >=150 && A < 200) numLineStart = lineMass150_199; + if ( A >=200 ) numLineStart = lineMass200; + + myfile.open(dataSource.c_str()); + + if (myfile.is_open()) { + while (/*! myfile.eof() &&*/ flag == 0 && lineNum = numLineStart ){ + list_symbol = line.substr(20,2); + list_A = atoi((line.substr(15,5)).c_str()); + + //printf(" A = %d, Sym = |%s| \n", list_A, list_symbol.c_str()); + + if ( this->A == list_A && this->Symbol == list_symbol) { + this->Z = atoi((line.substr(10,5)).c_str()); + this->BEA = atof((line.substr(54,11)).c_str()); + this->Mass = this->Z*mp + (list_A-this->Z)*mn - this->BEA/1000*list_A; + this->MassError = atof((line.substr(65,7)).c_str()); + + std::string str = line.substr(20,2); + str.erase(remove(str.begin(), str.end(), ' '), str.end()); + this->Symbol = str; + + std::ostringstream ss; + ss << this->A << this->Symbol; + this->Name = ss.str(); + flag = 1; + }else if ( list_A > this->A) { + this->BEA = -404; + this->Mass = -404; + this->MassError = -404; + this->Symbol = "non"; + this->Name = "non"; + break; + } + + } + } + myfile.close(); + }else { + printf("Unable to open %s\n", dataSource.c_str()); + } +} + +double Isotope::CalSp(int Np, int Nn){ + Isotope nucleusD(A - Np - Nn, Z - Np); + + if( nucleusD.Mass != -404){ + return nucleusD.Mass + Nn*mn + Np*mp - this->Mass; + }else{ + return -404; + } +} + +double Isotope::CalSp2(int a, int z){ + Isotope nucleusD(A - a , Z - z); + Isotope nucleusS(a,z); + + if( nucleusD.Mass != -404 && nucleusS.Mass != -404){ + return nucleusD.Mass + nucleusS.Mass - this->Mass; + }else{ + return -404; + } +} + +int Isotope::TwoJ(int nShell){ + + switch(nShell){ + case 0: return 1; break; // 0s1/2 + case 1: return 3; break; // 0p3/2 + case 2: return 1; break; // 0p1/2 -- 8 + case 3: return 5; break; // 0d5/2 + case 4: return 1; break; // 1s1/2 + case 5: return 3; break; // 0d3/2 -- 20 + case 6: return 7; break; // 0f7/2 -- 28 + case 7: return 3; break; // 1p3/2 + case 8: return 1; break; // 1p1/2 + case 9: return 5; break; // 0f5/2 -- 40 + case 10: return 9; break; // 0g9/2 -- 50 + case 11: return 7; break; // 0g7/2 + case 12: return 5; break; // 1d5/2 + case 13: return 11; break; // 0h11/2 + case 14: return 3; break; // 1d3/2 + case 15: return 1; break; // 2s1/2 -- 82 + case 16: return 9; break; // 0h9/2 + case 17: return 7; break; // 1f7/2 + case 18: return 13; break; // 0i13/2 + case 19: return 3; break; // 2p3/2 + case 20: return 5; break; // 1f5/2 + case 21: return 1; break; // 1p1/2 -- 126 + case 22: return 9; break; // 1g9/2 + case 23: return 11; break; // 0i11/2 + case 24: return 15; break; // 0j15/2 + case 25: return 5; break; // 2d5/2 + case 26: return 1; break; // 3s1/2 + case 27: return 3; break; // 2d3/2 + case 28: return 7; break; // 1g7/2 + } + + return 0; +} + +std::string Isotope::Orbital(int nShell){ + + switch(nShell){ + case 0: return "0s1 "; break; // + case 1: return "0p3 "; break; // + case 2: return "0p1 "; break; //-- 8 + case 3: return "0d5 "; break; // + case 4: return "1s1 "; break; // + case 5: return "0d3 "; break; //-- 20 + case 6: return "0f7 "; break; //-- 28 + case 7: return "1p3 "; break; // + case 8: return "1p1 "; break; // + case 9: return "0f5 "; break; //-- 40 + case 10: return "0g9 "; break; //-- 50 + case 11: return "0g7 "; break; // + case 12: return "1d5 "; break; // + case 13: return "0h11"; break; // + case 14: return "1d3 "; break; // + case 15: return "2s1 "; break; //-- 82 + case 16: return "0h9 "; break; // + case 17: return "1f7 "; break; // + case 18: return "0i13"; break; // + case 19: return "2p3 "; break; // + case 20: return "1f5 "; break; // + case 21: return "1p1 "; break; //-- 126 + case 22: return "1g9 "; break; // + case 23: return "0i11"; break; // + case 24: return "0j15"; break; // + case 25: return "2d5 "; break; // + case 26: return "3s1 "; break; // + case 27: return "2d3 "; break; // + case 28: return "1g7 "; break; // + } + + return "nan"; +} + +void Isotope::ListShell(){ + + if( Mass < 0 ) return; + + int n = A-Z; + int p = Z; + + int k = std::min(n,p); + int nMagic = 0; + for( int i = 0; i < 7; i++){ + if( magic(i) < k && k <= magic(i+1) ){ + nMagic = i; + break; + } + } + + int coreShell = magicShellID(nMagic-1); + int coreZ1 = magic(nMagic-1); + int coreZ2 = magic(nMagic); + + Isotope core1( 2*coreZ1, coreZ1); + Isotope core2( 2*coreZ2, coreZ2); + + printf("------------------ Core:%3s, inner Core:%3s \n", (core2.Name).c_str(), (core1.Name).c_str()); + printf(" || "); + int t = std::max(n,p); + int nShell = 0; + do{ + int occ = TwoJ(nShell)+1; + if( nShell > coreShell) { + printf("%4s", Orbital(nShell).c_str()); + if( nShell == 0 || nShell == 2 || nShell == 5 || nShell ==6 || nShell == 9 || nShell == 10 || nShell == 15 || nShell == 21){ + printf("|"); + }else{ + printf(","); + } + } + t = t - occ; + nShell++; + }while( t > 0 && nShell < 29); + for( int i = 1; i <= 6; i++){ + if (nShell < 28) { + printf("%4s,", Orbital(nShell).c_str()); + }else if( nShell == 28 ) { + printf("%4s", Orbital(nShell).c_str()); + } + nShell ++; + } + if (nShell < 29) printf("%4s", Orbital(nShell).c_str()); + printf("\n"); + + + printf(" Z = %3d || ", p); + nShell = 0; + do{ + int occ = TwoJ(nShell)+1; + if( nShell > coreShell ){ + if( p > occ ) { + printf("%-4d", occ); + if( nShell == 0 || nShell == 2 || nShell == 5 || nShell ==6 || nShell == 9 || nShell == 10 || nShell == 15 || nShell == 21){ + printf("|"); + }else{ + printf(","); + } + }else{ + printf("%-4d", p); + } + } + p = p - occ; + nShell++; + }while( p > 0 && nShell < 29); + printf("\n"); + + printf(" N = %3d || ", n); + nShell = 0; + do{ + int occ = TwoJ(nShell)+1; + if ( nShell > coreShell ){ + if( n > occ ) { + printf("%-4d", occ); + if( nShell == 0 || nShell == 2 || nShell == 5 || nShell ==6 || nShell == 9 || nShell == 10 || nShell == 15 || nShell == 21){ + printf("|"); + }else{ + printf(","); + } + }else{ + printf("%-4d", n); + } + } + n = n - occ; + nShell++; + }while( n > 0 && nShell < 29); + printf("\n"); + + printf("------------------ \n"); +} + + + +void Isotope::Print(){ + + if (Mass > 0){ + + printf(" using mass data : %s \n", dataSource.c_str()); + printf(" mass of \e[47m\e[31m%s\e[m nucleus (Z,A)=(%3d,%3d) is \e[47m\e[31m%12.5f\e[m MeV, BE/A=%7.5f MeV\n", Name.c_str(), Z, A, Mass, BEA/1000.); + printf(" total BE : %12.5f MeV\n",BEA*A/1000.); + printf(" mass in amu : %12.5f u\n",Mass/amu); + printf(" mass excess : %12.5f MeV\n", Mass + Z*0.510998950 - A*amu); + printf("-------------- Seperation energy \n"); + printf(" S1p: %8.4f| S1n: %8.4f| S(2H ): %8.4f| S1p1n : %8.4f\n", CalSp(1, 0), CalSp(0, 1), CalSp2(2, 1), CalSp(1, 1)); + printf(" S2p: %8.4f| S2n: %8.4f| S(3He): %8.4f| S(3H) : %8.4f\n", CalSp(2, 0), CalSp(0, 2), CalSp2(3, 2), CalSp2(3, 1)); + printf(" S3p: %8.4f| S3n: %8.4f| S(4He): %8.4f|\n", CalSp(3, 0), CalSp(0, 3), CalSp2(4, 2)); + printf(" S4p: %8.4f| S4n: %8.4f| \n", CalSp(4, 0), CalSp(0, 4)); + + }else{ + printf("Error %6.0f, no nucleus with (Z,A) = (%3d,%3d). \n", Mass, Z, A); + } + + +} + +#endif diff --git a/cleopatra/ClassKnockout.h b/cleopatra/ClassKnockout.h new file mode 100644 index 0000000..3edd24d --- /dev/null +++ b/cleopatra/ClassKnockout.h @@ -0,0 +1,301 @@ +#ifndef knockout_h +#define knockout_h + + +//======================================================= +//####################################################### +// Class for Knockout Reaction +// A(a,12)B, A = B + b, a->1, b->2 +// incident particle is A +// the calculation: 1) go to A's rest frame +// 2) calculate the b = A - B +// 3) go to CM frame +//======================================================= +class Knockout{ +public: + Knockout(); + ~Knockout(); + + void SetA(int A, int Z){ + Isotope temp(A,Z); + mA = temp.Mass; + AA = A; + ZA = Z; + nameA = temp.Name; + } + + void SetExA(double Ex){ + this->ExA = Ex; + } + + void Seta(int A, int Z){ + Isotope temp(A,Z); + ma = temp.Mass; + Aa = A; + Za = Z; + m1 = ma; + A1 = A; + Z1 = Z; + namea = temp.Name; + name1 = temp.Name; + } + + void Set2(int A, int Z){ + Isotope temp(A,Z); + m2 = temp.Mass; + A2 = A; + Z2 = Z; + name2 = temp.Name; + + AB = AA + Aa - A1 - A2; + ZB = ZA + Za - Z1 - Z2; + Isotope temp2(AB,ZB); + mB0 = temp2.Mass; + nameB = temp2.Name; + + } + + void SetBSpk(double S, double kb, double thetab, double phib){ + this->S = S; + AB = AA + Aa - A1 - A2; + ZB = ZA + Za - Z1 - Z2; + Isotope temp(AB,ZB); + mB0 = temp.Mass; + nameB = temp.Name; + this->kb = kb; + this->thetab = thetab; + this->phib = phib; + + mB = mA + ExA - m2 + S; + + ExB = mB - mB0; + + if( ExB < 0 && !isOverRideExNegative ){ + printf(" seperation energy is too small. \n"); + } + } + + void OverRideExNegative(bool YN){ + isOverRideExNegative = YN; + } + + TString GetReactionName(){ + TString rName; + + TString normInv; + if( isNormalKinematics ){ + normInv = "Normal Kinematics"; + }else{ + normInv = "Inverse Kinematics"; + } + + rName.Form("%s(%s,%s%s)%s, %s", nameA.c_str(), namea.c_str(), name1.c_str(), name2.c_str(), nameB.c_str(), normInv.Data()); + + return rName; + } + + void SetIncidentEnergyAngle(double KEA, double theta, double phi){ + this->KEA = KEA; + this->thetaIN = theta; + this->phiIN = phi; + } + + void CalIncidentChannel(bool isNormalKinematics); + void CalReactionConstant(bool isNormalKinematics); + void Event(double thetaCM, double phCM); + + double GetMass_A(){return mA;} + double GetMass_a(){return ma;} + double GetMass_b(){return mb;} + double GetMass_B(){return mB;} + double GetMass_Bgs(){return mB0;} + double GetMass_1(){return m1;} + double GetMass_2(){return m2;} + + TLorentzVector GetPA(){return PA;} + TLorentzVector GetPa(){return Pa;} + TLorentzVector GetPb(){return Pb;} + TLorentzVector GetPB(){return PB;} + TLorentzVector GetP1(){return P1;} + TLorentzVector GetP2(){return P2;} + + double GetMomentumbNN(){return p;} + double GetReactionBeta(){return beta;} + double GetReactionGamma(){return gamma;} + double GetNNTotalEnergy(){return Etot;} + + double GetNNTotalKE() {return Etot - mb - ma;} + double GetQValue() {return mA + ExA - m2 - mB;} + double GetMaxExB() {return Etot - mb - mB0;} + +private: + int AA, Aa, A1, A2, AB; + int ZA, Za, Z1, Z2, ZB; + double mA, ma, m1, m2, mB, mB0, mb; + string nameA, namea, name1, name2, nameB; + + double S; // separation energy + double kb; // momentum of b + double thetab, phib;// direction of b + + TLorentzVector PA, Pa, P1, P2, PB, Pb; // lab + + double KEA, thetaIN, phiIN; + double T; + + double k, beta, gamma, Etot, p; // reaction constant, in NN frame + double ExA, ExB; + + bool isNormalKinematics; + bool isOverRideExNegative; + +}; + +Knockout::Knockout(){ + TLorentzVector temp(0,0,0,0); + + PA = temp; + Pa = temp; + P1 = temp; + P2 = temp; + PB = temp; + Pb = temp; + + SetA(12,6); + Seta(1,1); + Set2(1,1); + + SetBSpk(1000, 0, 0, 0); + SetIncidentEnergyAngle(10, 0, 0); + + ExA = 0; + + isNormalKinematics = false; + isOverRideExNegative = false; +} + +Knockout::~Knockout(){ + +} + +void Knockout::CalIncidentChannel(bool isNormalKinematics){ + if( ExB < 0 && !isOverRideExNegative) return; + + this->isNormalKinematics = isNormalKinematics; + + if(!isNormalKinematics){ + //===== construct Lab frame 4-momentum + this->T = KEA * AA; + double kA = TMath::Sqrt(TMath::Power(mA + ExA + T, 2) - (mA + ExA) * (mA + ExA)); + PA.SetXYZM(0, 0, kA, mA + ExA); + PA.RotateY(thetaIN); + PA.RotateZ(phiIN); + + Pa.SetXYZM(0,0,0,ma); + + }else{ + //===== construct 4-momentum + this->T = KEA * Aa; + double ka = TMath::Sqrt(TMath::Power(ma + T, 2) - (ma) * (ma)); + Pa.SetXYZM(0, 0, ka, ma); + Pa.RotateY(thetaIN); + Pa.RotateZ(phiIN); + + PA.SetXYZM(0, 0, 0, mA + ExA); + } + +} + +void Knockout::CalReactionConstant(bool isNormalKinematics){ + if( ExB < 0 && !isOverRideExNegative) return; + + this->isNormalKinematics = isNormalKinematics; + + CalIncidentChannel(isNormalKinematics); + + if(!isNormalKinematics){ + + //===== change to A's rest frame + TVector3 bA = PA.BoostVector(); + PA.Boost(-bA); + + //===== constructe bounded nucleus b + PB.SetXYZM(0, 0, -kb, mB); + PB.RotateY(thetab); + PB.RotateZ(phib); + + Pb = PA - PB; + mb = Pb.M(); + + //===== change to Lab frame + Pb.Boost(bA); + PA.Boost(bA); + PB.Boost(bA); + + }else{ + + //===== constructe bounded nucleus b + PB.SetXYZM(0, 0, -kb, mB); + PB.RotateY(thetab); + PB.RotateZ(phib); + + Pb = PA - PB; + mb = Pb.M(); + + } + + //====== reaction constant + k = (Pa+Pb).P(); + double E = (Pa+Pb).E(); + beta = (Pa+Pb).Beta(); + gamma = 1 / TMath::Sqrt(1- beta * beta); + Etot = TMath::Sqrt(TMath::Power(E,2) - k * k); + p = TMath::Sqrt( (Etot*Etot - TMath::Power(m1 + m2,2)) * (Etot*Etot - TMath::Power(m1 - m2 ,2)) ) / 2 / Etot; + + //if( TMath::IsNaN(p) ){ + // printf(" Mc: %f, m1+m2: %f, kb:%f, thetab:%f, phib:%f\n", Etot, m1+m2, kb, thetab, phib); + //} + +} + +void Knockout::Event(double thetaCM, double phiCM){ + if( ExB < 0 && !isOverRideExNegative ) return; + + //===== construct Pcm + TLorentzVector Pc = Pb + Pa; + TVector3 bc = Pc.BoostVector(); + + TLorentzVector Pac = Pa; + Pac.Boost(-bc); + TVector3 va = Pac.Vect(); + + TLorentzVector Pbc = Pb; + Pbc.Boost(-bc); + TVector3 vb = Pbc.Vect(); + + //--- from P1 + TVector3 v1 = va; + v1.SetMag(p); + + TVector3 u1 = va.Orthogonal(); + v1.Rotate(thetaCM, u1); + v1.Rotate(phiCM + TMath::PiOver2(), va); // somehow, the calculation turn the vector 90 degree. + + TLorentzVector P1c; + P1c.SetVectM(v1, m1); + + //--- from P2 + TLorentzVector P2c; + P2c.SetVectM(-v1, m2); + + //---- to Lab Frame + P1 = P1c; + P1.Boost(bc); + P2 = P2c; + P2.Boost(bc); + +} + + + +#endif \ No newline at end of file diff --git a/cleopatra/ClassSimPlotter.h b/cleopatra/ClassSimPlotter.h new file mode 100644 index 0000000..d209d46 --- /dev/null +++ b/cleopatra/ClassSimPlotter.h @@ -0,0 +1,503 @@ +#ifndef SimPlotter_h +#define SimPlotter_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../Armory/ClassDetGeo.h" +#include "../Armory/ClassReactionConfig.h" +#include "../Cleopatra/ClassIsotope.h" + +enum plotID { pEZ, /// 0 + pRecoilXY, /// 1 + pRecoilXY1, /// 2 + pRecoilXY2, /// 3 + pRecoilRZ, /// 4 + pRecoilRTR, /// 5 + pTDiffZ, /// 6 + pThetaCM, /// 7 + pThetaCM_Z, /// 8 + pExCal, /// 9 + pRecoilRThetaCM, /// 10 + pArrayXY, /// 11 + pInfo, /// 12 + pElum1XY, /// 13 + pEElum1R, /// 14 + pElum1RThetaCM, /// 15 + pEmpty }; /// 16 + +class Plotter{ +public: + Plotter(TTree * tree, short reactionID, std::string reactionName, DetGeo detGeo, ExcitedEnergies exList, TString gate, std::vector padPlotID); + ~Plotter(); + + void SetRanges(double zMin, double zMax, double eMax, double elumMax, double thetaCM_Max){ + this->zRange[0] = zMin; + this->zRange[1] = zMax; + this->eMax = eMax; + this->elumMax = elumMax; + this->thetaCM_Max = thetaCM_Max; + } + void SetCanvas( int colSize, int rowSize , int padSize, std::vector padPlotID ){ + cCheck = new TCanvas(Form("SimChecker-%d", rID), + "Simulation Checker", + 200 * rID, + 200 * rID, + padSize*colSize, + padSize*rowSize); + + if(cCheck->GetShowEditor() ) cCheck->ToggleEditor(); + if(cCheck->GetShowToolBar() )cCheck->ToggleToolBar(); + cCheck->Divide(colSize,rowSize); + + numPad = colSize * rowSize; + } + + void Plot(); + +private: + + TTree * tree; + DetGeo detGeo; + std::string reactionName; + short rID; + ExcitedEnergies exList; + int numEx; + TString gate; + TString gateTrue; + std::vector padPlotID; + + double zRange[2]; + double eMax; + double recoilOut; + double recoilIn; + double elumMax; + double thetaCM_Max; + + int numPad; + TCanvas * cCheck; + TH2F * hez; + TH2F * hArrayXY; + TH2F * heavyXY; + TH2F * hElum1XY; + TH1F ** hThetaCM; + TH1F * hExCal; + TH1F * hHit; + TH2F * hRecoilXY1; + TH2F * hRecoilXY2; + TH2F * hTDiffZ; + TH2F * hRecoilRThetaCM; + TH2F * hRecoilRZ; + TH2F * hEElum1Rho; + TH2F * hRecoilRTR; + TH2F * hElum1RThetaCM; + TH2F * hThetaCM_Z; + + Isotope heavy; + + std::vector FindRange(TString branch); + +}; + +Plotter::Plotter(TTree * tree, short reactionID, std::string reactionName, DetGeo detGeo, ExcitedEnergies exList, TString gate, std::vector padPlotID){ + this->tree = tree; + this->rID = reactionID; + this->reactionName = reactionName; + this->exList = exList; + numEx = this->exList.ExList.size(); + + this->detGeo = detGeo; + + this->recoilOut = detGeo.aux[rID].outerRadius; + this->recoilIn = detGeo.aux[rID].innerRadius; + + this->gate = gate; + this->gateTrue = gate + Form(" && rID == %d", rID); + + this->padPlotID = padPlotID; + + cCheck = nullptr; + hez = nullptr; + hArrayXY = nullptr; + heavyXY = nullptr; + hElum1XY = nullptr; + hThetaCM = nullptr; + hExCal = nullptr; + hHit = nullptr; + hRecoilXY1 = nullptr; + hRecoilXY2 = nullptr; + hTDiffZ = nullptr; + hRecoilRThetaCM = nullptr; + hRecoilRZ = nullptr; + hEElum1Rho = nullptr; + hRecoilRTR = nullptr; + hElum1RThetaCM = nullptr; + hThetaCM_Z = nullptr; + + std::size_t pos1 = reactionName.find(")") + 1; + std::size_t pos2 = reactionName.find(" ", pos1); + std::string result = reactionName.substr(pos1, pos2 - pos1); + + pos1 = result.find("{") + 1; + pos2 = result.find("}", pos1); + + std::string massHeavy = result.substr(pos1, pos2-pos1); + std::string symHeavy = result.substr(pos2+1); + + heavy.SetIsoByName(massHeavy + symHeavy); + +} + +Plotter::~Plotter(){ + + if( cCheck ) delete cCheck; + if( hez ) delete hez; + if( hArrayXY ) delete hArrayXY; + if( heavyXY ) delete heavyXY; + if( hElum1XY ) delete hElum1XY; + if( hExCal ) delete hExCal; + if( hRecoilXY1 ) delete hRecoilXY1; + if( hRecoilXY2 ) delete hRecoilXY2; + if( hTDiffZ ) delete hTDiffZ; + if( hRecoilRThetaCM ) delete hRecoilRThetaCM; + if( hRecoilRZ ) delete hRecoilRZ; + if( hEElum1Rho ) delete hEElum1Rho; + if( hRecoilRTR ) delete hRecoilRTR; + if( hElum1RThetaCM ) delete hElum1RThetaCM; + if( hThetaCM_Z ) delete hThetaCM_Z; + + if(hThetaCM ){ + for( int i = 0; i < numEx; i++) delete [] hThetaCM[i]; + delete [] hThetaCM; + } + +} + +inline void Plotter::Plot(){ + + for( int i = 1; i <= numPad; i++ ){ + cCheck->cd(i); + plotID pID = padPlotID[i-1]; + + //&======================================= 0 + if( pID == pEZ){ + hez = new TH2F(Form("hez%d",rID), //need unqie name in root. + Form("e-z [gated] @ %5.0f mm; z [mm]; e [MeV]", detGeo.array[rID].firstPos), + 400, zRange[0], zRange[1], + 400, 0, eMax); + + tree->Draw(Form("e:z>>hez%d", rID), gateTrue , "colz"); + } + + //&======================================= 1 + if( pID == pRecoilXY ){ + heavyXY = new TH2F(Form("heavyXY%d",rID), + Form("RecoilXY [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[rID].detPos ), + 400, -recoilOut, recoilOut, + 400, -recoilOut, recoilOut); + tree->Draw(Form("yRecoil:xRecoil>>heavyXY%d", rID), gateTrue, "colz"); + + // printf("%f, %f\n", recoilOut, recoilIn); + TArc * detArc1 = new TArc(0, 0, recoilOut); + detArc1->SetLineColor(kBlue-8); + detArc1->SetFillStyle(0); + detArc1->Draw("same"); + TArc * detArc2 = new TArc(0, 0, recoilIn); + detArc2->SetLineColor(kBlue-8); + detArc2->SetFillStyle(0); + detArc2->Draw("same"); + + // if( reactionConfig.beamX != 0. || reactionConfig.beamY != 0. ){ + // TArc * arc = new TArc(reactionConfig.beamX, reactionConfig.beamY, 1); + // arc->SetLineColor(2); + // detArc1->SetFillStyle(0); + // arc->Draw("same"); + // } + } + + //&======================================= 2 + if( pID == pThetaCM ){ + hThetaCM = new TH1F *[numEx]; + TLegend * legend = new TLegend(0.8,0.2,0.99,0.8); + double maxCount = 0; + for( int h = 0; h < numEx; h++){ + hThetaCM[h] = new TH1F(Form("hThetaCM%d-%d", rID, h), Form("thetaCM [gated] (ExID=%d); thetaCM [deg]; count", h), 200, 0, thetaCM_Max); + hThetaCM[h]->SetLineColor(h+1); + hThetaCM[h]->SetFillColor(h+1); + hThetaCM[h]->SetFillStyle(3000+h); + tree->Draw(Form("thetaCM>>hThetaCM%d-%d", rID, h), gateTrue + Form("&& ExID==%d", h), ""); + legend->AddEntry(hThetaCM[h], Form("Ex=%5.1f MeV", exList.ExList[h].Ex)); + double max = hThetaCM[h]->GetMaximum(); + if( max > maxCount ) maxCount = max; + } + + for( int h = 0; h < numEx; h++){ + hThetaCM[h]->GetYaxis()->SetRangeUser(1, maxCount * 1.2); + if( h == 0 ) { + hThetaCM[h]->Draw(); + }else{ + hThetaCM[h]->Draw("same"); + } + } + legend->Draw(); + } + + //&======================================= 3 + if( pID == pExCal ){ + double exMin = 9999; + double exMax = -1; + for( size_t k = 0 ; k < exList.ExList.size(); k++){ + double kuku = exList.ExList[k].Ex; + if( kuku > exMax ) exMax = kuku; + if( kuku < exMin ) exMin = kuku; + } + + double exPadding = (exMax - exMin) < 1 ? 1 : (exMax - exMin) * 0.3; + + exMin = exMin - exPadding ; + exMax = exMax + exPadding ; + + hExCal = new TH1F(Form("hExCal%d",rID), + Form("calculated Ex [gated]; Ex [MeV]; count / %.2f keV", (exMax-exMin)/400.*1000), + 400, exMin, exMax); + tree->Draw(Form("ExCal>>hExCal%d", rID), gateTrue, ""); + + + double Sn = heavy.CalSp(0,1); + double Sp = heavy.CalSp(1,0); + double Sa = heavy.CalSp2(4,2); + double S2n = heavy.CalSp(0, 2); + + printf("======= Heavy recoil: %s \n", heavy.Name.c_str()); + printf("Sn : %6.2f MeV/u \n", Sn); + printf("Sp : %6.2f MeV/u \n", Sp); + printf("Sa : %6.2f MeV/u \n", Sa); + printf("S2n : %6.2f MeV/u \n", S2n); + + double yMax = hExCal->GetMaximum(); + TLatex * text = new TLatex(); + text->SetTextFont(82); + text->SetTextSize(0.06); + + if( Sn < exMax ) {TLine * lineSn = new TLine(Sn, 0, Sn, yMax); lineSn->SetLineColor(2); lineSn->Draw(""); text->SetTextColor(2); text->DrawLatex(Sn, yMax*0.9, "S_{n}");} + if( Sp < exMax ) {TLine * lineSp = new TLine(Sp, 0, Sp, yMax); lineSp->SetLineColor(4); lineSp->Draw("same"); text->SetTextColor(4); text->DrawLatex(Sp, yMax*0.9, "S_{p}");} + if( Sa < exMax ) {TLine * lineSa = new TLine(Sa, 0, Sa, yMax); lineSa->SetLineColor(6); lineSa->Draw("same"); text->SetTextColor(6); text->DrawLatex(Sa, yMax*0.9, "S_{a}");} + if( S2n < exMax ) {TLine * lineS2n = new TLine(S2n, 0, S2n, yMax); lineS2n->SetLineColor(8); lineS2n->Draw("same"); text->SetTextColor(8); text->DrawLatex(S2n, yMax*0.9, "S_{2n}");} + + } + + //&======================================= 4 + if( pID == pArrayXY ){ + + hArrayXY = new TH2F(Form("hArrayXY%d", rID), + "Array-XY [gated]; X [mm]; Y [mm]", + 400, -detGeo.array[rID].detPerpDist*1.5, detGeo.array[rID].detPerpDist*1.5, + 400, -detGeo.array[rID].detPerpDist*1.5, detGeo.array[rID].detPerpDist*1.5); + tree->Draw(Form("yArray:xArray>>hArrayXY%d", rID), gateTrue, "colz"); + } + + //&======================================= 5 + if( pID == pInfo ){ + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.06); + text.SetTextColor(2); + + text.DrawLatex(0., 0.9, reactionName.c_str()); + text.DrawLatex(0., 0.8, detGeo.Bfield > 0 ? "out of plan" : "into plan"); + text.SetTextColor(1); + text.DrawLatex(0., 0.7, "gate:"); + + text.SetTextColor(2); + //check gate text length, if > 30, break by "&&" + int ll = gate.Length(); + if( ll > 30 ) { + std::vector strList = AnalysisLib::SplitStr( (std::string) gate.Data(), "&&"); + for( int i = 0; i < strList.size(); i++){ + text.DrawLatex(0., 0.6 - 0.05*i, (TString) strList[i]); + } + }else{ + text.DrawLatex(0., 0.6, gate); + } + + // if( reactionConfig.beamX != 0.0 || reactionConfig.beamY != 0.0 ){ + // text.DrawLatex(0.0, 0.1, Form("Bema pos: (%4.1f, %4.1f) mm", reactionConfig.beamX, reactionConfig.beamY)); + // } + } + + //&======================================= 6 + if( pID == pElum1XY ){ + hElum1XY = new TH2F(Form("hElum1XY%d", rID), + Form("Elum-1 XY [gated] @ %.0f mm ; X [mm]; Y [mm]", detGeo.aux[rID].elumPos1), + 400, -elumMax, elumMax, + 400, -elumMax, elumMax); + tree->Draw(Form("yElum1:xElum1>>hElum1XY%d", rID), gateTrue, "colz"); + + double count = hElum1XY->GetEntries(); + if( count < 2000. ) { + hElum1XY->SetMarkerStyle(7); + if( count < 500. ) hElum1XY->SetMarkerStyle(3); + hElum1XY->Draw("scat"); + } + } + + //&======================================= 7 + if( pID == pRecoilXY1 ){ + TH2F * hRecoilXY1 = new TH2F(Form("hRecoilXY1-%d", rID), + Form("RecoilXY-1 [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[rID].detPos1 ), + 400, -detGeo.aux[rID].outerRadius, detGeo.aux[rID].outerRadius, + 400, -detGeo.aux[rID].outerRadius, detGeo.aux[rID].outerRadius); + tree->Draw(Form("yRecoil1:xRecoil1>>hRecoilXY1-%d", rID), gateTrue, "colz"); + } + + //&======================================= 8 + if( pID == pRecoilXY2 ){ + hRecoilXY2 = new TH2F(Form("hRecoilXY2=%d", rID), + Form("RecoilXY-2 [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[rID].detPos2 ), + 400, -detGeo.aux[rID].outerRadius, detGeo.aux[rID].outerRadius, + 400, -detGeo.aux[rID].outerRadius, detGeo.aux[rID].outerRadius); + tree->Draw(Form("yRecoil2:xRecoil2>>hRecoilXY2-%d", rID), gate, "colz"); + } + + //&======================================= 9 + if( pID == pTDiffZ ){ + std::vector tDiffRange = FindRange("t-tB"); + hTDiffZ = new TH2F(Form("hTDiffZ%d", rID), + "time(Array) - time(Recoil) vs Z [gated]; z [mm]; time diff [ns]", + 400, zRange[0], zRange[1], + 400, tDiffRange[0], tDiffRange[1]); + tree->Draw(Form("t - tB : z >> hTDiffZ%d", rID), gateTrue, "colz"); + } + + //&======================================= 10 + if( pID == pRecoilRThetaCM ){ + hRecoilRThetaCM = new TH2F(Form("hRecoilRThetaCM%d", rID), + "RecoilR - thetaCM [gated]; thetaCM [deg]; RecoilR [mm]", + 400, 0, 60, + 400, 0, detGeo.aux[rID].outerRadius); + tree->Draw(Form("rhoRecoil:thetaCM>>hRecoilRThetaCM%d", rID), gateTrue, "colz"); + } + + //&======================================= 11 + if( pID == pRecoilRZ ){ + hRecoilRZ = new TH2F(Form("hRecoilRZ%d", rID), + "RecoilR - Z [gated]; z [mm]; RecoilR [mm]", + 400, zRange[0], zRange[1], + 400,0, detGeo.aux[rID].outerRadius); + tree->Draw(Form("rhoRecoil:z>>hRecoilRZ%d", rID), gateTrue, "colz"); + } + + //&======================================= 12 + if( pID == pEElum1R ){ + hEElum1Rho = new TH2F(Form("hEElum1Rho%d", rID), + "Elum-1 E-R [gated]; R[mm]; Energy[MeV]", + 400, 0, elumMax, + 400, 0, eMax); + tree->Draw(Form("Tb:rhoElum1>>hEElum1Rho%d", rID), gateTrue, "colz"); + } + + //&======================================= 13 + if( pID == pRecoilRTR ){ + std::vector recoilERange = FindRange("TB"); + hRecoilRTR = new TH2F(Form("hRecoilRTR%d", rID), + "RecoilR - recoilE [gated]; recoil Energy [MeV]; RecoilR [mm]", + 500, recoilERange[0], recoilERange[1], + 500, 0, detGeo.aux[rID].outerRadius); + tree->Draw(Form("rhoRecoil:TB>>hRecoilRTR%d", rID), gateTrue, "colz"); + } + + //&======================================= 14 + if( pID == pThetaCM_Z ){ + hThetaCM_Z = new TH2F(Form("hThetaCM_Z%d", rID), + "ThetaCM vs Z ; Z [mm]; thetaCM [deg]", + 400, zRange[0], zRange[1], + 400, 0, thetaCM_Max); + tree->Draw(Form("thetaCM:z>>hThetaCM_Z%d", rID), gateTrue,"col"); + } + + //&======================================= 15 + if( pID == pElum1RThetaCM){ + int angBin = 400; + + hElum1RThetaCM = new TH2F(Form("hElum1RThetaCM%d", rID), + "Elum-1 rho vs ThetaCM [gated]; thatCM [deg]; Elum- rho [mm]", + angBin, 0, thetaCM_Max, + 400, 0, elumMax); + tree->Draw(Form("rhoElum1:thetaCM>>hElum1RThetaCM%d", rID), gateTrue, "colz"); + + TH1F * htemp = (TH1F *) hElum1RThetaCM->ProjectionX("htemp"); + + double rel = (thetaCM_Max)*1.0/angBin; + printf("angular resolution : %f deg \n", rel); + + std::vector xList; + double old_y = 0; + for( int i = 1; i <= angBin; i++){ + double y = htemp->GetBinContent(i); + if( old_y == 0 && y > 0) xList.push_back(htemp->GetBinCenter(i)); + if( old_y > 0 && y == 0 ) xList.push_back(htemp->GetBinCenter(i)); + old_y = y; + } + + printf("list of gaps :\n"); + for( int i = 0; i < (int) xList.size(); i+=2){ + printf("%d | %.3f - %.3f deg\n", i, xList[i], xList[i+1]); + } + + TF1 f1("f1", "sin(x)"); + double acceptance = 0; + double err1 = 0; + double err2 = 0; + for( int i = 0; i < (int) xList.size(); i += 2 ){ + acceptance += f1.Integral(xList[i] * TMath::DegToRad(), xList[i+1] * TMath::DegToRad() ) * TMath::TwoPi(); + err1 += f1.Integral((xList[i]-rel) * TMath::DegToRad(), (xList[i+1] + rel) * TMath::DegToRad() ) * TMath::TwoPi(); + err2 += f1.Integral((xList[i]+rel) * TMath::DegToRad(), (xList[i+1] - rel) * TMath::DegToRad() ) * TMath::TwoPi(); + } + printf("acceptance = %f sr +- %f \n", acceptance, (err1-err2)/2); + + TLatex text; + text.SetTextFont(82); + text.SetTextSize(0.06); + text.SetTextColor(2); + text.SetTextAngle(90); + + for( int i = 0; i < (int) xList.size(); i++){ + text.DrawLatex(xList[i], elumMax/2, Form("%.2f", xList[i])); + } + + text.SetNDC(); + text.SetTextAngle(0); + text.DrawLatex(0.15, 0.15, Form("accp. = %.2f(%.2f) msr", acceptance * 1000., (err1-err2)*1000./2)); + + delete htemp; + + } + + }///===== end of pad loop + + cCheck->Update(); +} + +std::vector Plotter::FindRange(TString branch){ + + tree->Draw(Form("%s>>temp1", branch.Data()), gateTrue); + TH1F * temp1 = (TH1F *) gROOT->FindObjectAny("temp1"); + + std::vector output; + if( temp1 != nullptr){ + output.push_back( temp1->GetXaxis()->GetXmax() ); + output.push_back( temp1->GetXaxis()->GetXmin() ); + delete temp1; + } + return output; +} + + +#endif \ No newline at end of file diff --git a/cleopatra/ClassTargetScattering.h b/cleopatra/ClassTargetScattering.h new file mode 100644 index 0000000..969608f --- /dev/null +++ b/cleopatra/ClassTargetScattering.h @@ -0,0 +1,202 @@ +#ifndef targetScattering_h +#define targetScattering_h + +#include +#include +#include + +#include "../Armory/AnalysisLib.h" + +//======================================================= +//####################################################### +// Class for multi-scattering of the beam inside target +// using SRIM to generate stopping power +// input : TLorentzVector, data_files +// output : scattered TLorentzVector +//======================================================= +class TargetScattering{ + +public: + TargetScattering(); + ~TargetScattering(); + + double GetKE0(){return KE0;} + double GetKE() {return KE;} + double GetKELoss() {return KE0-KE;} + double GetDepth() {return depth;} + double GetPathLength() {return length;} + + void LoadStoppingPower(std::string file); + + void SetTarget(double density, double depth){ + this->density = density; + this->depth = depth; + isTargetSet = true; + //printf("===== Target, density: %f g/cm3, depth: %f um \n", density, depth * 1e+4 ); + } + + TLorentzVector Scattering(TLorentzVector P){ + double mass = P.M(); + KE0 = (P.E() - mass); + KE = KE0; + double theta = P.Theta(); + this->length = TMath::Abs(depth/TMath::Cos(theta)); + //printf("------- theta: %f deg, length: %f um, KE: %f MeV \n", theta * TMath::RadToDeg(), this->length * 1e+4, KE); + + //integrate the energy loss within the depth of A + double dx = length/100.; // in cm + double x = 0; + double densityUse = density; + if( unitID == 0 ) densityUse = 1.; + do{ + //assume the particle will not be stopped + //printf(" x: %f, KE: %f, S: %f \n", x, KE, gA->Eval(KE)); + KE = KE - densityUse * gA->Eval(KE) * 10 * dx ; // factor 10, convert MeV/cm -> MeV/cm + + //angular Straggling, assume (Lateral Straggling)/(Projected range) + + + x = x + dx; + }while(x < length && KE > 0 ); + + //printf(" depth: %f cm = %f um, KE : %f -> %f MeV , dE = %f MeV \n", depth, depth * 1e+4, KE0, KE, KE0 - KE); + double newk = 0; + + TLorentzVector Pnew; + TVector3 vb(0,0,0); + + if( KE < 0 ) { + KE = 0.0; // somehow, when KE == 0 , the program has problem to rotate the 4-vector + }else{ + newk = TMath::Sqrt(TMath::Power(mass+KE,2) - mass * mass); + vb = P.Vect(); + vb.SetMag(newk); + } + Pnew.SetVectM(vb,mass); + + return Pnew; + } + +private: + bool isTargetSet; + double density; // density [mg/cm2] + int unitID; // 0 = MeV /mm or keV/um , 1 = MeV / (ug/cm2) + + double depth; // depth in target [cm] + double length; // total path length in target [cm] + double KE0, KE; + + TGraph * gA; // stopping power of A, b, B, in unit of MeV/(mg/cm2) + TGraph * gB; // projection range [nm] + TGraph * gC; // parallel Straggling [nm] + TGraph * gD; // perpendicular Straggling [nm] + +}; + +inline TargetScattering::TargetScattering(){ + isTargetSet = false; + density = 1; // mg/cm2 + unitID = 0; + KE0 = 0; + KE = 0; + depth = 0; + length = 0; + gA = NULL; + gB = NULL; + gC = NULL; + gD = NULL; +} + +inline TargetScattering::~TargetScattering(){ + delete gA; +} + +inline void TargetScattering::LoadStoppingPower(std::string filename){ + + printf("loading Stopping power: %s.", filename.c_str()); + + std::ifstream file; + file.open(filename.c_str()); + + std::vector energy; + std::vector stopping; + std::vector projRange; + std::vector paraStraggling; + std::vector prepStraggling; + + if( file.is_open() ){ + printf("... OK\n"); + char lineChar[16635]; + std::string line; + while( !file.eof() ){ + file.getline(lineChar, 16635, '\n'); + line = lineChar; + + size_t found = line.find("Target Density"); + if( found != std::string::npos ){ + printf(" %s\n", line.c_str()); + } + + found = line.find("Stopping Units ="); + if( found != std::string::npos){ + printf(" %s\n", line.c_str()); + if( line.find("MeV / mm") != std::string::npos ) { + unitID = 0; + }else if( line.find("keV / micron") != std::string::npos ){ + unitID = 0; + }else if( line.find("MeV / (mg/cm2)") != std::string::npos ) { + unitID = 1; + }else{ + printf("please using MeV/mm, keV/um, or MeV/(mg/cm2) \n"); + } + } + + size_t foundkeV = line.find("keV "); + size_t foundMeV = line.find("MeV "); + size_t foundGeV = line.find("GeV "); + if ( foundkeV != std::string::npos || foundMeV != std::string::npos || foundGeV != std::string::npos ){ + std::vector haha = AnalysisLib::SplitStr(line, " "); + //for( int i = 0 ; i < (int) haha.size()-1; i++){ + // printf("%d,%s|", i, haha[i].c_str()); + //} + //printf("\n"); + + found = haha[0].find("keV"); if( found != std::string::npos ) energy.push_back(atof(haha[0].substr(0, found).c_str()) * 0.001); + found = haha[0].find("MeV"); if( found != std::string::npos ) energy.push_back(atof(haha[0].substr(0, found).c_str()) * 1.); + found = haha[0].find("GeV"); if( found != std::string::npos ) energy.push_back(atof(haha[0].substr(0, found).c_str()) * 1000.); + + double a = atof(haha[1].c_str()); + double b = atof(haha[2].c_str()); + stopping.push_back(a+b); + + found = haha[3].find("A") ; if( found != std::string::npos ) projRange.push_back(atof(haha[3].substr(0, found).c_str()) * 0.1); + found = haha[3].find("um"); if( found != std::string::npos ) projRange.push_back(atof(haha[3].substr(0, found).c_str()) * 1000.); + found = haha[3].find("mm"); if( found != std::string::npos ) projRange.push_back(atof(haha[3].substr(0, found).c_str()) * 1e6); + + found = haha[4].find("A") ; if( found != std::string::npos ) paraStraggling.push_back(atof(haha[4].substr(0, found).c_str()) * 0.1); + found = haha[4].find("um"); if( found != std::string::npos ) paraStraggling.push_back(atof(haha[4].substr(0, found).c_str()) * 1e3); + found = haha[4].find("mm"); if( found != std::string::npos ) paraStraggling.push_back(atof(haha[4].substr(0, found).c_str()) * 1e6); + + found = haha[5].find("A") ; if( found != std::string::npos ) prepStraggling.push_back(atof(haha[5].substr(0, found).c_str()) * 0.1); + found = haha[5].find("um"); if( found != std::string::npos ) prepStraggling.push_back(atof(haha[5].substr(0, found).c_str()) * 1e3); + found = haha[5].find("mm"); if( found != std::string::npos ) prepStraggling.push_back(atof(haha[5].substr(0, found).c_str()) * 1e6); + + //printf(" %f, %f, %f, %f, %f \n", energy.back(), stopping.back(), projRange.back(), paraStraggling.back(), prepStraggling.back()); + } + + + } + + }else{ + printf("... fail\n"); + } + + gA = new TGraph(energy.size(), &energy[0], &stopping[0]); + + gB = new TGraph(energy.size(), &energy[0], &projRange[0]); + gC = new TGraph(energy.size(), &energy[0], ¶Straggling[0]); + gD = new TGraph(energy.size(), &energy[0], &prepStraggling[0]); + +} + +#endif \ No newline at end of file diff --git a/cleopatra/ClassTransfer.h b/cleopatra/ClassTransfer.h new file mode 100644 index 0000000..a54511c --- /dev/null +++ b/cleopatra/ClassTransfer.h @@ -0,0 +1,593 @@ +#ifndef Transfer_h +#define Transfer_h + +#include "utility" + +#include "ClassIsotope.h" +#include "../Armory/AnalysisLib.h" +#include "../Armory/ClassReactionConfig.h" + +#include "TLorentzVector.h" +#include "TMath.h" +#include "TF1.h" +#include "TMacro.h" + +//======================================================= +//####################################################### +// Class for Transfer Reaction +// reaction notation A(a,b)B +// A = incident particle +// a = target +// b = light scattered particle +// B = heavy scattered particle +//======================================================= +class TransferReaction { +public: + TransferReaction(){Inititization();}; + TransferReaction(ReactionConfig config, unsigned short ID = 0); + TransferReaction(std::string configFile, unsigned short ID = 0); + TransferReaction(TMacro configMarco, unsigned short ID = 0); + TransferReaction(int beamA, int beamZ, + int targetA, int targetZ, + int recoilA, int recoilZ, float beamEnergy_AMeV); + + ~TransferReaction(); + + void SetA(int A, int Z, double Ex = 0); + void Seta(int A, int Z); + void Setb(int A, int Z); + void SetB(int A, int Z); + void SetIncidentEnergyAngle(double KEA, double theta, double phi); + + void SetReactionFromReactionConfigClass(ReactionConfig reactConfigClassObject, unsigned short ID = 0); + void SetReactionFromFile(std::string configFile, unsigned short ID = 0); + void SetReactionFromTMacro(TMacro configMacro, unsigned short ID = 0); + void SetReactionSimple(int beamA, int beamZ, + int targetA, int targetZ, + int recoilA, int recoilZ, float beamEnergy_AMeV); + + void SetExA(double Ex); + void SetExB(double Ex); + + TString GetReactionName() const; + TString GetReactionName_Latex(); + + ReactionConfig GetRectionConfig() { return config;} + Recoil GetRecoil() { return recoil;} + ExcitedEnergies * GetExList() { return &exList;} + + double GetMass_A() const {return mA + ExA;} + double GetMass_a() const {return ma;} + double GetMass_b() const {return mb;} + double GetMass_B() const {return mB + ExB;} + + double GetCMTotalKE() {return Etot - mA - ma;} + double GetQValue() {return mA + ExA + ma - mb - mB - ExB;} + double GetMaxExB() {return Etot - mb - mB;} + + TLorentzVector GetPA() const {return PA;} + TLorentzVector GetPa() const {return Pa;} + TLorentzVector GetPb() const {return Pb;} + TLorentzVector GetPB() const {return PB;} + + void PrintFourVectors() const; + void PrintReaction(bool withEx = true) const; + + double CalkCM(double ExB); //momentum at CM frame + void CalReactionConstant(); + std::pair CalExThetaCM(double e, double z, double Bfield, double a); + void Event(double thetaCM_rad, double phiCM_rad); + + double GetMomentumbCM() {return p;} + double GetReactionBeta() {return beta;} + double GetReactionGamma() {return gamma;} + double GetCMTotalEnergy() {return Etot;} + double GetEZSlope(double BField) {return 299.792458 * recoil.lightZ * abs(BField) / TMath::TwoPi() * beta / 1000.;} // MeV/mm + + + void CreateExDistribution(); + int GetRandomExID(){ + if( exDistribution ) { + return exDistribution->GetRandom(); + } + return 0; + } + double GetRandomEx(){ + if( exDistribution ) { + int exID = exDistribution->GetRandom(); + return exList.ExList[exID].Ex; + } + return TMath::QuietNaN(); + } + +private: + + ExcitedEnergies exList; + Recoil recoil; + ReactionConfig config; + + std::string nameA, namea, nameb, nameB; + double thetaIN, phiIN; + double mA, ma, mb, mB; + + double TA, T; // TA = KE of A pre u, T = total energy + double ExA, ExB; + + bool isReady; + bool isBSet; + + double k; // CM Boost momentum + double beta, gamma; //CM boost beta + double Etot; + double p; // CM frame momentum of b, B + double slope; // slope of the + + TLorentzVector PA, Pa, Pb, PB; + + TString format(TString name); + + void Inititization(); + + TF1 * exDistribution; + + static double exDistFunc(Double_t *x, Double_t * par){ + return par[(int) x[0]]; + } + +}; + +TransferReaction::TransferReaction(ReactionConfig config, unsigned short ID){ + Inititization(); + + SetA(config.beamA, config.beamZ); + Seta(config.targetA, config.targetZ); + + SetExA(config.beamEx); + + recoil = config.recoil[ID]; + exList = config.exList[ID]; + + Setb(recoil.lightA, recoil.lightZ); + SetB(recoil.heavyA, recoil.heavyZ); + SetIncidentEnergyAngle(config.beamEnergy, 0, 0); + + CalReactionConstant(); + +} + +TransferReaction::TransferReaction(std::string configFile, unsigned short ID){ + Inititization(); + SetReactionFromFile(configFile, ID); +} + +TransferReaction::TransferReaction(TMacro configMarco, unsigned short ID){ + Inititization(); + SetReactionFromTMacro(configMarco, ID); +} + +TransferReaction::TransferReaction(int beamA, int beamZ, + int targetA, int targetZ, + int recoilA, int recoilZ, + float beamEnergy_AMeV){ + Inititization(); + SetReactionSimple(beamA, beamZ, + targetA, targetZ, + recoilA, recoilZ, + beamEnergy_AMeV); +} + +void TransferReaction::Inititization(){ + + thetaIN = 0.; + phiIN = 0.; + SetA(12, 6, 0); + Seta(2,1); + Setb(1,1); + SetB(13,6); + TA = 6; + T = TA * config.beamA; + + exDistribution = nullptr; + + ExA = 0; + ExB = 0; + + CalReactionConstant(); + + TLorentzVector temp (0,0,0,0); + PA = temp; + Pa = temp; + Pb = temp; + PB = temp; + +} + +TransferReaction::~TransferReaction(){ + delete exDistribution; +} + +void TransferReaction::SetA(int A, int Z, double Ex){ + Isotope temp (A, Z); + mA = temp.Mass; + config.beamA = A; + config.beamZ = Z; + ExA = Ex; + nameA = temp.Name; + isReady = false; + isBSet = true; +} + +void TransferReaction::Seta(int A, int Z){ + Isotope temp (A, Z); + ma = temp.Mass; + config.targetA = A; + config.targetZ = Z; + namea = temp.Name; + isReady = false; + isBSet = false; +} +void TransferReaction::Setb(int A, int Z){ + Isotope temp (A, Z); + mb = temp.Mass; + recoil.lightA = A; + recoil.lightZ = Z; + nameb = temp.Name; + isReady = false; + isBSet = false; +} +void TransferReaction::SetB(int A, int Z){ + Isotope temp (A, Z); + mB = temp.Mass; + recoil.heavyA = A; + recoil.heavyZ = Z; + nameB = temp.Name; + isReady = false; + isBSet = true; +} + +void TransferReaction::SetIncidentEnergyAngle(double KEA, double theta, double phi){ + this->TA = KEA; + this->T = TA * config.beamA; + this->thetaIN = theta; + this->phiIN = phi; + isReady = false; +} + +void TransferReaction::SetReactionSimple(int beamA, int beamZ, + int targetA, int targetZ, + int recoilA, int recoilZ, + float beamEnergy_AMeV){ + + config.SetReactionSimple(beamA, beamZ, + targetA, targetZ, + recoilA, recoilZ, beamEnergy_AMeV); + + recoil = config.recoil[0]; + + SetA(config.beamA, config.beamZ); + Seta(config.targetA, config.targetZ); + Setb(recoil.lightA, recoil.lightZ); + SetB(recoil.heavyA, recoil.heavyZ); + SetIncidentEnergyAngle(config.beamEnergy, 0, 0); + + CalReactionConstant(); + +} + +void TransferReaction::SetExA(double Ex){ + this->ExA = Ex; + isReady = false; +} + +void TransferReaction::SetExB(double Ex){ + this->ExB = Ex; + isReady = false; +} + +void TransferReaction::SetReactionFromReactionConfigClass(ReactionConfig reactConfigClassObject, unsigned short ID){ + + config = reactConfigClassObject; + SetA(config.beamA, config.beamZ); + Seta(config.targetA, config.targetZ); + + SetExA(config.beamEx); + + if( ID > config.recoil.size() ){ + printf("Reaction Config only has %zu recoil settings. input is %u. Abort.\n", config.recoil.size(), ID); + return; + } + + recoil = config.recoil[ID]; + exList = config.exList[ID]; + + Setb(recoil.lightA, recoil.lightZ); + SetB(recoil.heavyA, recoil.heavyZ); + SetIncidentEnergyAngle(config.beamEnergy, 0, 0); + + CalReactionConstant(); + +} + +void TransferReaction::SetReactionFromFile(std::string configFile, unsigned short ID){ + + if( config.LoadReactionConfig(configFile) ){ + + SetA(config.beamA, config.beamZ); + Seta(config.targetA, config.targetZ); + + SetExA(config.beamEx); + + if( ID > config.recoil.size() ){ + printf("Reaction Config only has %zu recoil settings. input is %u. Abort.\n", config.recoil.size(), ID); + return; + } + + recoil = config.recoil[ID]; + exList = config.exList[ID]; + + Setb(recoil.lightA, recoil.lightZ); + SetB(recoil.heavyA, recoil.heavyZ); + SetIncidentEnergyAngle(config.beamEnergy, 0, 0); + + CalReactionConstant(); + + }else{ + printf("cannot read file %s.\n", configFile.c_str()); + isReady = false; + } + +} + +void TransferReaction::SetReactionFromTMacro(TMacro configMacro, unsigned short ID){ + + if( config.LoadReactionConfig(&configMacro) ){ + + SetA(config.beamA, config.beamZ); + Seta(config.targetA, config.targetZ); + + SetExA(config.beamEx); + + if( ID > config.recoil.size() ){ + printf("Reaction Config only has %zu recoil settings. input is %u. Abort.\n", config.recoil.size(), ID); + return; + } + + recoil = config.recoil[ID]; + exList = config.exList[ID]; + + Setb(recoil.lightA, recoil.lightZ); + SetB(recoil.heavyA, recoil.heavyZ); + SetIncidentEnergyAngle(config.beamEnergy, 0, 0); + + CalReactionConstant(); + + }else{ + printf("cannot read TMacro %s.\n", configMacro.GetName()); + isReady = false; + } + +} + +TString TransferReaction::GetReactionName() const{ + TString rName; + rName.Form("%s(%s,%s)%s", nameA.c_str(), namea.c_str(), nameb.c_str(), nameB.c_str()); + return rName; +} + +TString TransferReaction::format(TString name){ + if( name.IsAlpha() ) return name; + int len = name.Length(); + TString temp = name; + TString temp2 = name; + if( temp.Remove(0, len-2).IsAlpha()){ + temp2.Remove(len-2); + }else{ + temp = name; + temp.Remove(0, len-1); + temp2.Remove(len-1); + } + return "^{"+temp2+"}"+temp; +} + +TString TransferReaction::GetReactionName_Latex(){ + TString rName; + rName.Form("%s(%s,%s)%s @ %.2f MeV/u", format(nameA).Data(), format(namea).Data(), format(nameb).Data(), format(nameB).Data(), config.beamEnergy); + return rName; +} + +double TransferReaction::CalkCM(double ExB){ + if( !isBSet || !isReady) return TMath::QuietNaN(); + return TMath::Sqrt( (Etot*Etot - TMath::Power(mb + mB + ExB,2)) * (Etot*Etot - TMath::Power(mb - mB - ExB,2)) ) / 2 / Etot; +} + +void TransferReaction::CalReactionConstant(){ + if( !isBSet){ + recoil.heavyA = config.beamA + config.targetA - recoil.lightA; + recoil.heavyZ = config.beamZ + config.targetZ - recoil.lightZ; + Isotope temp (recoil.heavyA, recoil.heavyZ); + mB = temp.Mass; + isBSet = true; + } + + k = TMath::Sqrt(TMath::Power(mA + ExA + T, 2) - (mA + ExA) * (mA + ExA)); + beta = k / (mA + ExA + ma + T); + gamma = 1 / TMath::Sqrt(1- beta * beta); + Etot = TMath::Sqrt(TMath::Power(mA + ExA + ma + T,2) - k * k); + + PA.SetXYZM(0, 0, k, mA + ExA); + PA.RotateY(thetaIN); + PA.RotateZ(phiIN); + Pa.SetXYZM(0,0,0,ma); + + PA.SetUniqueID(config.beamZ); + Pa.SetUniqueID(config.targetZ); + Pb.SetUniqueID(recoil.lightZ); + PB.SetUniqueID(recoil.heavyZ); + + isReady = true; + p = CalkCM(ExB); + +} + +void TransferReaction::PrintFourVectors() const { + + printf("A : %10.2f %10.2f %10.2f %10.2f\n", PA.E(), PA.Px(), PA.Py(), PA.Pz()); + printf("a : %10.2f %10.2f %10.2f %10.2f\n", Pa.E(), Pa.Px(), Pa.Py(), Pa.Pz()); + printf("b : %10.2f %10.2f %10.2f %10.2f\n", Pb.E(), Pb.Px(), Pb.Py(), Pb.Pz()); + printf("B : %10.2f %10.2f %10.2f %10.2f\n", PB.E(), PB.Px(), PB.Py(), PB.Pz()); + printf("-------------------------------------------------------\n"); + printf("B : %10.2f %10.2f %10.2f %10.2f\n", + PA.E() + Pa.E() - Pb.E() - PB.E(), + PA.Px() + Pa.Px() - Pb.Px() - PB.Px(), + PA.Py() + Pa.Py() - Pb.Py() - PB.Py(), + PA.Pz() + Pa.Pz() - Pb.Pz() - PB.Pz()); + +} + +void TransferReaction::PrintReaction(bool withEx) const { + + printf("=====================================================\n"); + printf("\e[1m\e[33m %s \e[0m\n", GetReactionName().Data()); + printf("=====================================================\n"); + printf("------------------------------ Beam\n"); + printf(" beam : A = %3d, Z = %2d, Ex = %.2f MeV\n", config.beamA, config.beamZ, config.beamEx); + printf(" beam Energy : %.2f +- %.2f MeV/u, dE/E = %5.2f %%\n", config.beamEnergy, config.beamEnergySigma, config.beamEnergySigma/config.beamEnergy); + printf(" Angle : %.2f +- %.2f mrad\n", config.beamTheta, config.beamThetaSigma); + printf(" offset : (x,y) = (%.2f, %.2f) mmm \n", config.beamX, config.beamY); + + printf("------------------------------ Target\n"); + printf(" target : A = %3d, Z = %2d \n", config.targetA, config.targetZ); + + printf("------------------------------ Recoil\n"); + printf(" light : A = %3d, Z = %2d \n", recoil.lightA, recoil.lightZ); + printf(" heavy : A = %3d, Z = %2d \n", recoil.heavyA, recoil.heavyZ); + printf("=====================================================\n"); + + if( withEx ) { + exList.Print(); + printf("=====================================================\n"); + } +} + +void TransferReaction::Event(double thetaCM_rad, double phiCM_rad){ + + if( !isReady ) CalReactionConstant(); + + //---- to CM frame + TLorentzVector Pc = PA + Pa; + TVector3 b = Pc.BoostVector(); + + TVector3 vb(0,0,0); + + if( b.Mag() > 0 ){ + TVector3 v0 (0,0,0); + TVector3 nb = v0 - b; + + TLorentzVector PAc = PA; + PAc.Boost(nb); + TVector3 vA = PAc.Vect(); + + TLorentzVector Pac = Pa; + Pac.Boost(nb); + TVector3 va = Pac.Vect(); + + //--- construct vb + vb = va; + vb.SetMag(p); + + TVector3 ub = vb.Orthogonal(); + vb.Rotate(thetaCM_rad, ub); + vb.Rotate(phiCM_rad + TMath::PiOver2(), va); // somehow, the calculation turn the vector 90 degree. + //vb.Rotate(phiCM , va); // somehow, the calculation turn the vector 90 degree. + } + + //--- from Pb + TLorentzVector Pbc; + Pbc.SetVectM(vb, mb); + + //--- from PB + TLorentzVector PBc; + //PBc.SetVectM(vB, mB + ExB); + PBc.SetVectM(-vb, mB + ExB); + + //---- to Lab Frame + Pb = Pbc; Pb.Boost(b); + PB = PBc; PB.Boost(b); + +} + +std::pair TransferReaction::CalExThetaCM(double e, double z, double Bfield, double perpDist){ + + double Ex = TMath::QuietNaN(); + double thetaCM = TMath::QuietNaN(); + + double mass = mb; + double massB = mB; + double y = e + mass; + double slope = 299.792458 * recoil.lightZ * abs(Bfield) / TMath::TwoPi() * beta / 1000.; // MeV/mm; + double alpha = slope/beta; + double G = alpha * gamma * beta * perpDist ; + double Z = alpha * gamma * beta * z; + double H = TMath::Sqrt(TMath::Power(gamma * beta,2) * (y*y - mass * mass) ) ; + double Et = Etot; + + if( TMath::Abs(Z) < H ) { + //using Newton's method to solve 0 == H * sin(phi) - G * tan(phi) - Z = f(phi) + double tolerrence = 0.001; + double phi = 0; //initial phi = 0 -> ensure the solution has f'(phi) > 0 + double nPhi = 0; // new phi + + int iter = 0; + do{ + phi = nPhi; + nPhi = phi - (H * TMath::Sin(phi) - G * TMath::Tan(phi) - Z) / (H * TMath::Cos(phi) - G /TMath::Power( TMath::Cos(phi), 2)); + iter ++; + if( iter > 10 || TMath::Abs(nPhi) > TMath::PiOver2()) break; + }while( TMath::Abs(phi - nPhi ) > tolerrence); + + phi = nPhi; + + // check f'(phi) > 0 + double Df = H * TMath::Cos(phi) - G / TMath::Power( TMath::Cos(phi),2); + if( Df > 0 && TMath::Abs(phi) < TMath::PiOver2() ){ + double K = H * TMath::Sin(phi); + double x = TMath::ACos( mass / ( y * gamma - K)); + double k = mass * TMath::Tan(x); // momentum of particel b or B in CM frame + double EB = TMath::Sqrt(mass*mass + Et*Et - 2*Et*TMath::Sqrt(k*k + mass * mass)); + Ex = EB - massB; + + double hahaha1 = gamma* TMath::Sqrt(mass * mass + k * k) - y; + double hahaha2 = gamma* beta * k; + thetaCM = TMath::ACos(hahaha1/hahaha2) * TMath::RadToDeg(); + + //double pt = k * TMath::Sin(thetaCM * TMath::DegToRad()); + //double pp = gamma*beta*TMath::Sqrt(mass*mass + k*k) - gamma * k * TMath::Cos(thetaCM * TMath::DegToRad()); + //thetaLab = TMath::ATan(pt/pp) * TMath::RadToDeg(); + + }else{ + Ex = TMath::QuietNaN(); + thetaCM = TMath::QuietNaN(); + //thetaLab = TMath::QuietNaN(); + } + + }else{ + Ex = TMath::QuietNaN(); + thetaCM = TMath::QuietNaN(); + //thetaLab = TMath::QuietNaN(); + } + + return std::make_pair(Ex, thetaCM); +} + +void TransferReaction::CreateExDistribution(){ + + int numEx = exList.ExList.size(); + + exDistribution = new TF1("exDistribution", TransferReaction::exDistFunc, 0, numEx, numEx); + for(int q = 0; q < numEx; q++){ + exDistribution->SetParameter(q, exList.ExList[q].xsec*exList.ExList[q].SF); + } + +} + +#endif \ No newline at end of file diff --git a/cleopatra/Cleopatra.C b/cleopatra/Cleopatra.C new file mode 100644 index 0000000..8649b09 --- /dev/null +++ b/cleopatra/Cleopatra.C @@ -0,0 +1,111 @@ +/*********************************************************************** + * + * This is Cleopatra, a sucessor of Ptolemy + * only for (d,p), (d,p), (d,d), or (p,p) + * + * 1) it read a simple infile.in from reaction_setting file + * 2) use Ptolemy to calculate the the creation + * 3) extract the cross sec distribution into txt and root file + * + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ cleopatra.C -o cleopatra `root-config --cflags --glibs` + * + *------------------------------------------------------ + * The reaction_setting file is simple like: + * + * 206Hg(d,p)207Hg(1s1/2 0.000) 10MeV/u AK + * + * the first is similar to usual reaction setting, the word AK is a + * short name for Optical Potential, user can put as many line as + * they like, Cleopatra can create the suitable infile.in for Ptolomy + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "InFileCreator.h" +#include "ExtractXSec.h" +#include +#include "PlotTGraphTObjArray.h" + +int main (int argc, char *argv[]) { //TODO add angle range + + printf("=================================================================\n"); + printf("===== Cleopatra, Ptolemy for (d,p),(p,d), (p,p) and (d,d) =====\n"); + printf("=================================================================\n"); + + if(argc < 2 || argc > 5) { + printf("Usage: ./Cleopatra input_file (angMin = 0 deg, angMax = 180 deg, angStep = 1 deg)\n"); + printf("Usage: ./Cleopatra input_file angMin angMax (angStep = 1 deg)\n"); + printf("Usage: ./Cleopatra input_file angMin angMax angStep\n"); + exit(0); + }else{ + printf("From file : %s \n", argv[1]); + } + + //================= read infile. extract the reactions, write pptolemy infile for each reaction + std::string readFile = argv[1]; + double angMin = 0.; + double angMax = 180.; + double angStep = 1.; + if( argc >= 4 ){ + angMin = atof(argv[2]); + angMax = atof(argv[3]); + } + if( argc == 5 ){ + angStep = atof(argv[4]); + } + + std::string ptolemyInFileName = argv[1]; + ptolemyInFileName += ".in"; + printf("=================== Create InFile\n"); + InFileCreator( readFile, ptolemyInFileName, angMin, angMax, angStep); + + //================= run ptolemy + std::string ptolemyOutFileName = argv[1]; + ptolemyOutFileName += ".out"; + std::ostringstream commandStream; + #if defined(__linux__) + commandStream << "../Cleopatra/ptolemy <" << ptolemyInFileName << "> " << ptolemyOutFileName; + #elif defined(__APPLE__) && defined(__MACH__) + commandStream << "../Cleopatra/ptolemy_mac <" << ptolemyInFileName << "> " << ptolemyOutFileName; + #endif + std::string command = commandStream.str(); + + printf("=================== Run Ptolemy\n"); + printf("%s \n", command.c_str()); + + int result = std::system(command.c_str()); + if (result == -1) { + std::cerr << "Error executing system command." << std::endl; + return 1; + } + + //================= extract the Xsec and save as txt and root + printf("=================== Extract Cross-section\n"); + ExtractXSec(ptolemyOutFileName); + + //================= Call root to plot the d.s.c. + printf("=================== Plot Result using ROOT.\n"); + std::string rootFileName = argv[1]; + rootFileName += ".root"; + TApplication app ("app", &argc, argv); + PlotTGraphTObjArray(rootFileName); + app.Run(); //nothing run after + return 0; +} diff --git a/cleopatra/ExtractXSec.C b/cleopatra/ExtractXSec.C new file mode 100644 index 0000000..ff82cc7 --- /dev/null +++ b/cleopatra/ExtractXSec.C @@ -0,0 +1,48 @@ +/*********************************************************************** + * + * This is ExtractXSec for *.out for Ptolemy + * + * This program will extract cross section distribution from Ptolmey output. + * save as *.Xsec.txt and *.root for distribution + * + * save ExPtolemy.txt for excitation energies and total X-section + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ ExtractXSec.C -o ExtractXSec `root-config --cflags --glibs` + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include "ExtractXSec.h" + +using namespace std; + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("========== Extract Cross-Section From Ptolemy out file ==========\n"); + printf("=================================================================\n"); + + if(argc < 2 || argc > 3) { + printf("Usage: ./ExtractXSec input_file \n"); + printf(" ElasticFlag = 1 , default, extarct Ratio to Rutherford\n"); + printf(" ElasticFlag = 2 , extarct Total Xsec\n"); + printf(" ElasticFlag = 3 , Rutherford\n"); + exit(0); + }else{ + printf("From file : %s \n", argv[1]); + } + + string readFile = argv[1]; + int ElasticFlag = 1; + if( argc == 3 ){ + ElasticFlag = atoi(argv[2]); + } + ExtractXSec(readFile, ElasticFlag); + +} diff --git a/cleopatra/ExtractXSec.h b/cleopatra/ExtractXSec.h new file mode 100644 index 0000000..f73a487 --- /dev/null +++ b/cleopatra/ExtractXSec.h @@ -0,0 +1,546 @@ +/*********************************************************************** + * + * This is ExtractXSec for *.out for Ptolemy + * + * This program will extract cross section distribution from Ptolmey output. + * save as *.Xsec.txt and *.root for distribution + * + * save ExPtolemy.txt for excitation energies and total X-section + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ ExtractXSec.C -o ExtractXSec `root-config --cflags --glibs` + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../Armory/AnalysisLib.h" + +using namespace std; + +TObjArray * gList = NULL; +double distfunct(double *x, double *par){ + + TGraph * gTemp = (TGraph *) gList->At(par[0]); + + return (gTemp->Eval(x[0]))* sin(x[0] * TMath::DegToRad()); +} + +bool isFloat( string str ) { + int length = str.length(); + for( int i = 0; i < length; i++){ + string it = str.substr(i,1); + if( it == " " || it == "."|| it == "1"|| it == "2"|| + it == "3"|| it == "4"|| it == "5"|| it == "6"|| it == "7"|| it == "8"|| it == "9"|| it == "0"){ + continue; + }else{ + return false; + } + } + return true; +} + +int ExtractXSec (string readFile, int indexForElastic=1) { + + //indexForElastic = 1 ; for Ratio + //indexForElastic = 2 ; for Total + //indexForElastic = 3 ; for Rutherford + + //--- open file.out + ifstream file_in; + file_in.open(readFile.c_str(), ios::in); + if( !file_in){ + printf("Unable to open %s \n", readFile.c_str()); + exit(1); + } + + //---- variable for Xsec + vector title; + vector> dataMatrix; + vector angle; + vector Ex; + vector totalXsec; + vector reaction; + double angleMin = 0; + double angleMax = 0; + double angleStep = -1; + + //================================== read file.out + string line; + int lineNum = 0; + vector dataXsec; + bool startExtract = false; + bool angleFilled = false; + int numCal = 0; + int reactionFlag = 0; + bool preFindForElastic = false; + printf("======================================================\n"); + while(getline(file_in, line)){ + lineNum ++; + //printf("%d , %s\n", lineNum, line.c_str()); + + size_t pos; + string findStr; + int findLen; + + //---- find Title + findStr = "$============================================"; + findLen = findStr.length(); + pos = line.find(findStr); + if( pos != string::npos){ + title.push_back(line.substr(pos + findLen+1)); + + pos = title.back().find("("); + string ex = title.back().substr(3, pos-3); + Ex.push_back( atof(ex.c_str()) ); + + //clear dataXsex for new data set + dataXsec.clear(); + + numCal ++; + continue; + } + + //---- find Reaction + findStr = "0INPUT... CHANNEL"; + findLen = findStr.length(); + pos = line.find(findStr); + if( pos != string::npos ) { + reaction.push_back( line.substr(pos + findLen + 1) ); + reactionFlag = 1; // 1 for (d,d) or (p,p) + ///printf("%d |----------- (d,d), %d\n", lineNum, reactionFlag); + continue; // nextline + } + + findStr = "REACTION:"; + findLen = findStr.length(); + pos = line.find(findStr); + if( pos != string::npos ) { + reaction.push_back( line.substr(pos + findLen + 1) ); + reactionFlag = 2; // 2 for (d,p) or (p,d) + ///printf("%d |----------- (d,p), %d\n", lineNum, reactionFlag); + continue; // nextline + } + + //----- pre find for Elastic scattering + findStr = "0 OPTICAL MODEL SCATTERING FOR THE OUTGOING CHANNEL"; + pos = line.find(findStr); + if( pos != string::npos ) { + preFindForElastic = true; + ///printf("%d |----------- pre Elastics Flag : %d\n", lineNum, preFindForElastic); + continue; + } + + //----- find angle stetting when not known + if( angleStep == -1 ){ + + findStr = "anglemin="; + findLen = findStr.length(); + pos = line.find(findStr); + if( pos != string::npos){ + + size_t pos1 = line.find("anglemax="); + angleMin = atof( line.substr(pos+findLen, pos1 - pos - findLen).c_str() ); + + pos = pos1; + pos1 = line.find("anglestep="); + angleMax = atof( line.substr(pos+findLen, pos1 - pos - findLen).c_str() ); + + angleStep = atof( line.substr(pos1 + findLen+1).c_str() ); + + //printf("%d |---- angle range found.\n", lineNum); + + } + continue; //nextline + } + + //----- check if start extracting Xsec or not + findStr = "dumpdumpdump"; + if( reactionFlag == 1 && preFindForElastic ){ + findStr = "C.M. LAB RUTHERFORD"; + } + if( reactionFlag == 2 ){ + findStr = "0 C.M. REACTION REACTION LOW L HIGH L % FROM"; + } + pos = line.find(findStr); + if( pos != string::npos ) { + startExtract = true; + //printf("%d |----- start extraction \n", lineNum); + continue; + } + + //----- start extracting Xsec + if( startExtract ){ + + if( line.length() < 20 ) continue; + + ///printf("%d |%s \n", line.length(), line.c_str()); + double numAngle, numXsec; + if( reactionFlag == 1 ){ // Elastics (d,d) or (p,p) + numAngle = atof( line.substr(0, 7).c_str()); + if( indexForElastic == 1 ){ + numXsec = atof( line.substr(15, 15).c_str()); + }else if( indexForElastic == 2 ){ + if ( line.length() > 60 ) { + numXsec = atof( line.substr(30, 13).c_str()); + }else{ + numXsec = -404; + } + }else{ + if ( line.length() > 60 ) { + numXsec = atof( line.substr(57, 14).c_str()); + }else{ + numXsec = -404; + } + } + } + + if( reactionFlag == 2 ){ // InElastics (d,p) or (p,d) + if( isFloat( line.substr(0, 7) ) ){ + numAngle = atof( line.substr(0, 7).c_str()); + numXsec = atof( line.substr(7, 19).c_str()); + }else{ + numAngle = -1.0; + numXsec = -1.0; + } + } + + if( numAngle != numXsec && numXsec > 0. ){ + if( !angleFilled ) angle.push_back(numAngle); + dataXsec.push_back(numXsec); + + ///printf(" %f , %f \n", angle.back(), dataXsec.back()); + } + + + } + + //------ find total Xsec, if found stop extraction + findStr = "dumpdumpdump"; + if( reactionFlag == 1 && preFindForElastic){ + findStr = "0TOTAL REACTION CROSS SECTION ="; + } + if( reactionFlag == 2){ + findStr = "0TOTAL:"; + } + findLen = findStr.length(); + pos = line.find(findStr); + + if( pos != string::npos ) { + + totalXsec.push_back( atof(line.substr(pos + findLen).c_str()) ); + + printf("%2d | %s | total Xsec(4pi): %f mb \n", numCal, title.back().c_str(), totalXsec.back()); + + //push back dataXsec to dataMatrix + dataMatrix.push_back(dataXsec); + + //printf("%d |----- end extraction \n", lineNum); + + angleFilled = true; + startExtract = false; + reactionFlag = 0; + preFindForElastic = false; + continue; + } + + } + file_in.close(); + + //================================== summary + printf("====================== Total number of line read : %d \n", lineNum); + printf("Angle : %5.2f, %5.2f | step : %5.2f \n", angleMin, angleMax, angleStep); + printf("Number of Angle read : %lu \n", angle.size()); + printf("Number of data read : %lu \n", dataXsec.size()); + printf("Number of Reaction : %lu \n", reaction.size()); + + + printf("----------------------------- list of Calculation \n"); + //... find suitable lenght for displaying reaction string + int reactionStrLen = 0; + for( int i = 0; i < numCal ; i++){ + int len = reaction[i].length(); + if( len > reactionStrLen ) reactionStrLen = len; + } + + vector partialXsec; + partialXsec.clear(); + for( int i = 0; i < numCal ; i++){ + + double partialSumXsec = 0.0; + for( int j = 0; j < (dataMatrix[i]).size() ; j++ ){ + //double theta = (angle[j] + angleStep/2.) * TMath::DegToRad(); + double theta = (angle[j]) * TMath::DegToRad(); + double dTheta = angleStep * TMath::DegToRad(); + double phi = TMath::TwoPi(); + partialSumXsec += dataMatrix[i][j] * sin( theta ) * dTheta * phi ; + } + partialXsec.push_back(partialSumXsec); + + size_t pos = title[i].find(")"); + printf("%*s| %s | Xsec(%3.0f-%3.0f deg) : %f mb\n", reactionStrLen + 3, reaction[i].c_str(), title[i].substr(pos+1).c_str(), angleMin, angleMax, partialSumXsec); + } + printf("---------------------------------------------------\n"); + + //================================== save file.Xsec.txt + string saveFileName = readFile; + int len = saveFileName.length(); + saveFileName = saveFileName.substr(0, len - 4); + saveFileName += ".Xsec.txt"; + printf("Output : %s \n", saveFileName.c_str()); + FILE * file_out; + file_out = fopen(saveFileName.c_str(), "w+"); + + for( int i = 0; i < numCal ; i++){ + fprintf(file_out, "#%14s\n", reaction[i].c_str()); + } + + int space = 19; + fprintf(file_out, "%8s\t", "Angle"); + for( int i = 0; i < numCal ; i++){ + fprintf(file_out, "%*s", space, title[i].c_str()); + } + fprintf(file_out, "\n"); + + for( int i = 0; i < angle.size() ; i ++){ + fprintf(file_out, "%8.3f\t", angle[i]); + for( int j = 0; j < numCal ; j++){ + fprintf(file_out, "%*f", space, dataMatrix[j][i]); + } + fprintf(file_out, "\n"); + } + fclose(file_out); + + //================================== Make TMacro for ExList + + TMacro ExList; + TMacro ReactList; + ExList.AddLine("#---Ex relative_xsec SF sigma_in_MeV"); + for( int i = 0; i < numCal ; i++){ + ExList.AddLine(Form("%9.5f %9.5f 1.0 0.000", Ex[i], partialXsec[i])); + ReactList.AddLine(reaction[i].c_str()); + } + + //================================== Save in ROOT + len = saveFileName.length(); + saveFileName = saveFileName.substr(0, len - 9); + TString fileName = saveFileName; + fileName += ".root"; + printf("Output : %s \n", fileName.Data()); + + TFile * fileOut = new TFile(fileName, "RECREATE" ); + gList = new TObjArray(); ///no SetTitle() method for TObjArray + gList->SetName("TGraph of d.s.c"); + TObjArray * fList = new TObjArray(); + fList->SetName("TF1 of distributions = d.s.c. * sin()"); + + TGraph ** gGraph = new TGraph *[numCal]; + TF1 ** dist = new TF1*[numCal]; + + for( int i = 0; i < numCal ; i++){ + gGraph[i] = new TGraph(); + TString name = reaction[i]; + name += "|"; + name += title[i]; + gGraph[i]->SetName(name); + for( int j = 0; j < angle.size() ; j++){ + gGraph[i]->SetPoint(j, angle[j], dataMatrix[i][j]); + } + gList->Add(gGraph[i]); + + name.Form("dist%d", i); + dist[i] = new TF1(name, distfunct, angleMin, angleMax, 1 ); + dist[i]->SetParameter(0, i); + + fList->Add(dist[i]); + + } + gList->Write("thetaCM_TGraph", 1); + fList->Write("thetaCM_TF1", 1); + + ExList.Write("ExList"); + ReactList.Write("ReactionList"); + + fileOut->Write(); + fileOut->Close(); + printf("---------------------------------------------------\n"); + + return 0; +} + +int ExtractXSecFromText(string readFile){ + + //read file + ifstream file_in; + file_in.open(readFile.c_str(), ios::in); + if( !file_in){ + printf("Unable to open %s \n", readFile.c_str()); + exit(1); + } + + //---- variable for Xsec + vector> dataMatrix; + vector angle; + vector Ex; + + //================================== read file.out + string line; + int lineNum = 0; + vector dataXsec; + + int numCal = 0; + printf("======================================================\n"); + + bool headerDone = false; + + while(getline(file_in, line)){ + lineNum ++; + + if( line.substr(0,1) == "#" ) continue; + + //printf("%d | %s\n", lineNum, line.c_str()); + + //after the comment line, the next line must be column name + vector header= AnalysisLib::SplitStr(line, " "); + //printf("---%lu #", header.size()); + //for( int i = 0; i < header.size(); i++){ + // printf("%s|", header[i].c_str()); + //} + //printf("\n"); + + if ( !headerDone ) { + for( int i = 1 ; i < header.size(); i++){ + string energy = header[i].substr(3, header[i].length()); + Ex.push_back(atof(energy.c_str())); + //printf("%f---\n", Ex.back()); + } + headerDone = true; + }else{ + + vector temp; + for( int i = 0; i < header.size(); i++){ + if( i == 0 ) angle.push_back(atof(header[i].c_str())); + if( i > 0 ) temp.push_back(atof(header[i].c_str())); + } + dataMatrix.push_back(temp); + + } + + } + file_in.close(); + + double angleMin = angle.front(); + double angleMax = angle.back(); + double angleStep = (angleMax - angleMin)/(angle.size()-1); + + //------ print out read data + printf("====================== data read as:\n"); + printf("%5s, ", "Ex"); + for(int i = 0; i < Ex.size(); i++){ + printf("%6.3f|", Ex[i]); + } + printf("\n"); + for(int i = 0; i < dataMatrix.size(); i++){ + printf("%5.2f, ", angle[i]); + for( int j = 0; j < dataMatrix[i].size(); j++) printf("%6.3f|", dataMatrix[i][j]); + printf("\n"); + } + printf("---------------------------------\n"); + printf("angle min :%f\n", angleMin); + printf("angle max :%f\n", angleMax); + printf("angle step:%f\n", angleStep); + printf("---------------------------------\n"); + + //------- calculate summed cross section + vector partialXsec(Ex.size()); + for( int i = 0; i < dataMatrix.size() ; i++){ + for( int j = 0; j < (dataMatrix[i]).size() ; j++ ){ + //double theta = (angle[j] + angleStep/2.) * TMath::DegToRad(); + double theta = (angle[i]) * TMath::DegToRad(); + double dTheta = angleStep * TMath::DegToRad(); + double phi = TMath::TwoPi(); + partialXsec[j] += dataMatrix[i][j] * sin( theta ) * dTheta * phi ; + } + } + for(int i = 0; i < Ex.size(); i++){ + printf("Ex=%6.3f| Xsec(%3.0f-%3.0f deg) : %f mb\n", Ex[i] , angleMin, angleMax, partialXsec[i]); + } + printf("---------------------------------------------------\n"); + + //================================== save *.Ex.txt + string saveExName = readFile; + int len = saveExName.length(); + saveExName = saveExName.substr(0, len - 4); + saveExName += ".Ex.txt"; + printf("Output : %s \n", saveExName.c_str()); + FILE * file_Ex; + file_Ex = fopen(saveExName.c_str(), "w+"); + fprintf(file_Ex, "//Generated_by_ExtractXsec.h___Ex___Xsec___SF____sigma\n"); + for( int i = 0; i < Ex.size() ; i++){ + fprintf(file_Ex, "%9.5f %9.5f 1.0 0.000\n", Ex[i], partialXsec[i]); + } + fprintf(file_Ex, "#=====End_of_File\n"); + fclose(file_Ex); + + + //================================== Save in ROOT + string saveFileName = readFile; + len = saveFileName.length(); + saveFileName = saveFileName.substr(0, len - 4); + TString fileName = saveFileName; + fileName += ".root"; + printf("Output : %s \n", fileName.Data()); + TFile * fileOut = new TFile(fileName, "RECREATE" ); + + gList = new TObjArray(); + gList->SetName("TGraph of d.s.c"); + TObjArray * fList = new TObjArray(); + fList->SetName("TF1 of distributions = d.s.c. * sin()"); + + TGraph ** gGraph = new TGraph *[numCal]; + TF1 ** dist = new TF1*[numCal]; + + for( int i = 0; i < Ex.size() ; i++){ + gGraph[i] = new TGraph(); + TString name ; + name.Form("Ex=%6.3f MeV", Ex[i]); + gGraph[i]->SetName(name); + for( int j = 0; j < angle.size() ; j++){ + gGraph[i]->SetPoint(j, angle[j], dataMatrix[j][i]); + } + gList->Add(gGraph[i]); + + name.Form("dist%d", i); + dist[i] = new TF1(name, distfunct, angleMin, angleMax, 1 ); + dist[i]->SetParameter(0, i); + + fList->Add(dist[i]); + + //delete tempFunc; + + } + gList->Write("qList", 1); + fList->Write("pList", 1); + + + fileOut->Write(); + fileOut->Close(); + printf("---------------------------------------------------\n"); + + + return 0; + +} + diff --git a/cleopatra/ExtractXSecFromText.C b/cleopatra/ExtractXSecFromText.C new file mode 100644 index 0000000..fd685b0 --- /dev/null +++ b/cleopatra/ExtractXSecFromText.C @@ -0,0 +1,41 @@ +/*********************************************************************** + * + * This is ExtractXSecFromText for *.txt file + * + * This program will extract cross section distribution + * save as *.root for distribution + * + * save *.Ex.txt for excitation energies and total X-section + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ ExtractXSecFromText.C -o ExtractXSecFromText `root-config --cflags --glibs` + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Dec-29, 2019 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include "ExtractXSec.h" + +using namespace std; + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("========== Extract Cross-Section From text file ==========\n"); + printf("=================================================================\n"); + + if(argc < 2 ) { + printf("Usage: ./ExtractXSecFromText input_file\n"); + exit(0); + }else{ + printf("From file : %s \n", argv[1]); + } + + string readFile = argv[1]; + ExtractXSecFromText(readFile); + +} diff --git a/cleopatra/FindThetaCM.C b/cleopatra/FindThetaCM.C new file mode 100644 index 0000000..db33abc --- /dev/null +++ b/cleopatra/FindThetaCM.C @@ -0,0 +1,56 @@ +/*********************************************************************** + * + * This is FindThetaCM.C, To calculate the thetaCM convrage for each detector + * + * This required two inout files: basicReactionConfig.txt + * detectorGeo.txt + * + *------------------------------------------------------- + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include /* atof */ +#include +#include +#include "FindThetaCM.h" + +int main(int argc, char *argv[]){ + + printf("=================================================================\n"); + printf("=== Find ThetaCM convrage for each detector at Ex ====\n"); + printf("=================================================================\n"); + + if(argc < 2 || argc > 7) { + printf("Usage: ./FindThetaCM Ex\n"); + printf("Usage: ./FindThetaCM Ex nDiv\n"); + printf("Usage: ./FindThetaCM Ex nDiv X-Ratio\n"); + printf("Usage: ./FindThetaCM Ex nDiv X-Ratio reactionTxt detGeoTxt ID\n"); + printf(" * default is the first settings from reaction and detGeo.\n"); + exit(0); + } + + double Ex = 0; + double xRatio = 0.95; + int nDiv = 1; + std::string reactionTxt = "reactionConfig.txt"; + std::string detGeoTxt = "detectorGeo.txt"; + int ID = 0; + + if ( argc >= 2 ) Ex = atof(argv[1]); + if ( argc >= 3 ) nDiv = atoi(argv[2]); + if ( argc >= 4 ) xRatio = atof(argv[3]); + if ( argc >= 5 ) reactionTxt = argv[4]; + if ( argc >= 6 ) detGeoTxt = argv[5]; + if ( argc >= 6 ) ID = atoi(argv[6]); + + if( nDiv < 1 ) { + printf(" nDiv must be >= 1 \n"); + return -1; + } + + FindThetaCM(Ex, nDiv, xRatio, reactionTxt, detGeoTxt, ID); + + return 0; +} diff --git a/cleopatra/FindThetaCM.h b/cleopatra/FindThetaCM.h new file mode 100644 index 0000000..93256df --- /dev/null +++ b/cleopatra/FindThetaCM.h @@ -0,0 +1,143 @@ +/*********************************************************************** + * + * This is FindThetaCM.h, To calculate the thetaCM convrage for each detector + * + * This required two inout files: basicReactionConfig.txt + * detectorGeo.txt + * + *------------------------------------------------------- + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include "TFile.h" +#include "TTree.h" +#include "TF1.h" +#include "TMacro.h" +#include "TObjArray.h" +#include "TGraph.h" +#include "../Cleopatra/ClassHelios.h" +#include "../Cleopatra/ClassTransfer.h" + +void FindThetaCM(double Ex, int nDivision=1, double XRATION = 0.95, + std::string reactionConfigFileName="reactionConfig.txt", + std::string detGeoFileName = "detectorGeo.txt", unsigned short ID = 0){ + + + ///========================================================= load files + + TransferReaction reaction(reactionConfigFileName, ID); + reaction.SetExB(Ex); + reaction.CalReactionConstant(); + reaction.PrintReaction(false); + ReactionConfig reConfig = reaction.GetRectionConfig(); + Recoil recoil = reaction.GetRecoil(); + + HELIOS helios(detGeoFileName, ID); + helios.PrintGeometry(); + DetGeo detGeo = helios.GetDetectorGeometry(); + Array array = helios.GetArrayGeometry(); + + //calculate a TGraph for thetaCM vs z + const int nData = 170; + double px[nData]; + double py[nData]; + + double mb = reaction.GetMass_b(); + double kCM = reaction.GetMomentumbCM(); + double q = TMath::Sqrt(mb*mb + kCM * kCM ); + double beta = reaction.GetReactionBeta() ; + double BField = detGeo.Bfield; + double slope = reaction.GetEZSlope(BField); + double gamma = reaction.GetReactionGamma(); + double perpDist = array.detPerpDist; + + for(int i = 0; i < nData; i++){ + double thetacm = (i + 5.) * TMath::DegToRad(); + double temp = TMath::TwoPi() * slope / beta / kCM * perpDist / TMath::Sin(thetacm); + px[i] = beta /slope * (gamma * beta * q - gamma * kCM * TMath::Cos(thetacm)) * (1 - TMath::ASin(temp)/TMath::TwoPi()); + py[i] = thetacm * TMath::RadToDeg(); + } + + //find minimum z position + TGraph * xt = new TGraph(100, py, px); + xt->SetName("xt"); + ///double zMin0 = xt->Eval(0); + ///printf("z for thetaCM = 0 : %f mm \n", zMin0); + + ///xt->Draw("AC*"); + + /// find the minimum z position and the corresponding theta + double zMin0 = 99999999; + double tMin0 = 99999999; + for( double ttt = 3 ; ttt < 20 ; ttt += 0.1 ){ + double zzz = xt->Eval(ttt); + if( zzz < zMin0 ) { + zMin0 = zzz; + tMin0 = ttt; + } + } + printf(" z min %f mm at thetaCM %f deg \n", zMin0, tMin0); + + TGraph * tx = new TGraph(nData, px, py); + tx->SetName(Form("tx")); + tx->SetLineColor(4); + + //Remove nan data + for( int i = tx->GetN() -1 ; i >= 0 ; i--){ + if( TMath::IsNaN(tx->GetPointX(i)) ) tx->RemovePoint(i); + } + + // tx->Draw("AC"); + + ///========================================================= result + + int iDet = array.colDet; + double length = array.detLength; + std::vector midPos; + + for(int i = 0; i < iDet; i++){ + if( array.firstPos > 0 ){ + midPos.push_back(array.detPos[i]+length/2.); + }else{ + midPos.push_back(array.detPos[i]-length/2.); + } + // printf("%2d | %f \n", i, midPos.back()); + } + + printf("==== ThetaCM in degree =================\n"); + printf(" x-ratio : %f, number of division : %d \n", XRATION, nDivision); + printf("\n"); + for( int j = 0; j < nDivision + 1; j++) printf("%5.2f ", -XRATION + 2*XRATION/nDivision*j); + printf(" <<-- in X \n"); + for( int j = 0; j < nDivision + 1; j++) printf("%5s ", " | "); + printf("\n"); + for( int j = 0; j < nDivision + 1; j++) printf("%5.2f ", length/2 -length*XRATION/2 + length*XRATION/nDivision*j); + printf(" <<-- in mm \n\n"); + printf("========================= Ex : %6.4f MeV\n", Ex); + printf(" %6s - %6s | %6s, %6s, %6s\n", "Min", "Max", "Mean", "Dt", "sin(x)dx * 180/pi"); + printf("-------------------------------------------------\n"); + for( int i = 0; i < iDet; i++){ + double zMin = midPos[i]-length*XRATION/2.; + double zMax = midPos[i]+length*XRATION/2.; + double zLength = zMax - zMin; + double zStep = zLength/(nDivision); + for( int j = 0 ; j < nDivision ; j++){ + + double tMin = (zMin + j*zStep > zMin0) ? tx->Eval(zMin + j*zStep) : TMath::QuietNaN(); + double tMax = (zMin + (j+1)*zStep > zMin0) ? tx->Eval(zMin + (j+1)*zStep) : TMath::QuietNaN(); + + double tMean = (tMax + tMin)/2.; + double dt = (tMax - tMin); + + double sintdt = TMath::Sin(tMean * TMath::DegToRad()) * dt ; + + + printf(" det-%d[%d]: %6.2f - %6.2f | %6.2f, %6.2f, %6.4f\n", i, j, tMin, tMax, tMean, dt, sintdt); + + } + if( nDivision > 0 ) printf("--------------\n"); + } + printf("================================================= \n"); + +} diff --git a/cleopatra/InFileCreator.C b/cleopatra/InFileCreator.C new file mode 100644 index 0000000..d5057ee --- /dev/null +++ b/cleopatra/InFileCreator.C @@ -0,0 +1,68 @@ +/*********************************************************************** + * + * This is InFileCreator, To creator the in-file for Ptolemy + * only for (d,p), (d,p), (d,d), or (p,p) + * + * It read a simple infile.in from reaction_setting file + * + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ InFileCreator.C -o InFileCreator `root-config --cflags --glibs` + * + *------------------------------------------------------ + * The reaction_setting file is simple like: + * + * 206Hg(d,p)207Hg(1s1/2 0.000) 10MeV/u AK + * + * the first is similar to usual reaction setting, the word AK is a + * short name for Optical Potential, user can put as many line as + * they like, Cleopatra can create the suitable infile.in for Ptolomy + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include /* atof */ +#include +#include +#include "InFileCreator.h" + +using namespace std; + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("=== InfileCreator, Ptolemy for p,d,t,3He ====\n"); + printf("=================================================================\n"); + + if(argc < 2 || argc > 5) { + printf("Usage: ./InfileCreator input_file (angMin = 0 deg, angMax = 180 deg, angStep = 1 deg)\n"); + printf("Usage: ./InfileCreator input_file angMin angMax (angStep = 1 deg)\n"); + printf("Usage: ./InfileCreator input_file angMin angMax angStep\n"); + exit(0); + }else{ + printf("From file : %s \n", argv[1]); + } + + //================= read infile. extract the reactions, write pptolemy infile for each reaction + string readFile = argv[1]; + double angMin = 0.; + double angMax = 180.; + double angStep = 1.; + if( argc >= 4 ){ + angMin = atof(argv[2]); + angMax = atof(argv[3]); + } + if( argc == 5 ){ + angStep = atof(argv[4]); + } + + string ptolemyInFileName = argv[1]; + ptolemyInFileName += ".in"; + + InFileCreator( readFile, ptolemyInFileName, angMin, angMax, angStep); + +} diff --git a/cleopatra/InFileCreator.h b/cleopatra/InFileCreator.h new file mode 100644 index 0000000..68571a7 --- /dev/null +++ b/cleopatra/InFileCreator.h @@ -0,0 +1,404 @@ +/*********************************************************************** + * + * This is InFileCreator, To creator the in-file for Ptolemy + * only for (x,y), x or y = n, p, d, t, 3He + * + * It read a simple infile.in from reaction_setting file + * + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ InFileCreator.C -o InFileCreator `root-config --cflags --glibs` + * + *------------------------------------------------------ + * The reaction_setting file is simple like: + * + * 206Hg(d,p)207Hg(1s1/2 0.000) 10MeV/u AK + * + * the first is similar to usual reaction setting, the word AK is a + * short name for Optical Potential, user can put as many line as + * they like, Cleopatra can create the suitable infile.in for Ptolomy + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include /* atof */ +#include +#include "../Cleopatra/ClassIsotope.h" // for geting Z +#include "potentials.h" +#include "../Armory/AnalysisLib.h" + +using namespace std; + +int GetLValue(string spdf){ + + if( spdf == "s" ) return 0; + if( spdf == "p" ) return 1; + if( spdf == "d" ) return 2; + if( spdf == "f" ) return 3; + if( spdf == "g" ) return 4; + if( spdf == "h" ) return 5; + if( spdf == "i" ) return 6; + if( spdf == "j" ) return 7; + return -1; +} + + +int InFileCreator(string readFile, string infile, double angMin, double angMax, double angStep) { + + //================= read infile. extract the reactions, write pptolemy infile for each reaction + ifstream file_in; + file_in.open(readFile.c_str(), ios::in); + + if( !file_in ){ + printf(" cannot read file. \n"); + return 0 ; + } + + printf("Save to infile : %s \n", infile.c_str()); + FILE * file_out; + file_out = fopen (infile.c_str(), "w+"); + + printf("Angle setting (%5.2f, %5.2f) deg | Step : %5.2f deg\n", angMin, angMax, angStep); + printf("---------------------------\n"); + + //extract information + int numOfReaction = 0; + while( file_in.good() ) { + string tempLine; + getline(file_in, tempLine ); + + if( tempLine.substr(0, 1) == "#" ) continue; + if( tempLine.size() < 5 ) continue; + + //split line using space + vector str0 = AnalysisLib::SplitStr(tempLine, " "); + if ( str0.size() == 0 ) continue; + + printf(" %s\n", tempLine.c_str()); + + ///for( int i = 0 ; i < str0.size() ; i++){ + /// printf(" str0[%d] %s \n", i, str0[i].c_str()); + ///} + + vector str1 = AnalysisLib::SplitStr(str0[0], "(", 0); + vector str2 = AnalysisLib::SplitStr(str1[1], ")", 1); + + str2[0] = "(" + str2[0]; + + int lenStr20 = str2[0].length(); + size_t posTemp1 = str2[0].find(","); + string mass_a = str2[0].substr(1, posTemp1-1); + size_t posTemp2 = str2[0].find(")"); + string mass_b = str2[0].substr(posTemp1+1, posTemp2-posTemp1-1); + ///printf(" mass_a : |%s| , mass_b : |%s| \n", mass_a.c_str(), mass_b.c_str()); + Isotope iso_a(mass_a); + Isotope iso_b(mass_b); + + // Check is the Reaction supported + bool isReactionSupported = false; + bool isTransferReaction = true; + + if( iso_a.A <= 4 && iso_a.Z <= 2 && iso_b.A <=4 && iso_b.Z <=2 ) isReactionSupported = true; + + ///======= elastics-ish scattering + if( iso_a.Mass == iso_b.Mass ) isTransferReaction = false; + + ///======= p/n-exchange is not supported + if( iso_a.A == iso_b.A && iso_a.Z != iso_b.Z ) isReactionSupported = false; + + ///======= 3-nucleons transfer is not supported. e.g. (n,a), (p,a), (a,n), (a,p) + int numNucleonsTransfer = iso_a.A - iso_b.A; + if( abs(numNucleonsTransfer) >= 3 ) isReactionSupported = false; + + if( isReactionSupported == false ){ + printf(" ===> Ignored. Reaction type not supported. \n"); + continue; + } + + // Continues to decode the input string + string gsSpinA = str0[1]; + string orbital = str0[2]; + + string spinParity = str0[3]; + int lenSpinParity = spinParity.length(); + string spin = spinParity.substr(0, lenSpinParity-1); + string parity = spinParity.substr(lenSpinParity-1); + + string Ex = str0[4]; + string reactionEnergy = str0[5]; + string potential = str0[6]; + + string isoA = str1[0]; + string isoB = str2[1]; + string reactionType = str2[0]; + + Isotope iso_A(str1[0]); + Isotope iso_B(str2[1]); + + /// check is iso_A or iso_B exist in the mass table + if( iso_A.Mass == -404 || iso_B.Mass == -404 ){ + printf(" ===> Error! mass does not found. \n"); + continue; + } + + /// check reaction valid by balancing the A and Z number; + if( iso_A.A + iso_a.A != iso_B.A + iso_b.A || iso_A.Z + iso_a.Z != iso_B.Z + iso_b.Z ) { + printf("====> ERROR! A-number or Z-number not balanced. \n"); + Isotope isotopeK(iso_A.A + iso_a.A - iso_b.A, iso_A.Z + iso_a.Z - iso_b.Z); + printf(" try : %s(%s,%s)%s ??\n", iso_A.Name.c_str(), iso_a.Name.c_str(), iso_b.Name.c_str(), isotopeK.Name.c_str()); + continue; + } + + if( isTransferReaction && potential.length() != 2 ){ + printf("====> ERROR! Potential input should be 2 charaters! skipped. \n"); + continue; + } + + string node ; + string jValue ; + string lValue ; + int spdf = -1; + + if( isTransferReaction ) { + ///printf("------------ %d nucleon(s) transfer \n", abs(iso_a.A - iso_b.A)); + node = orbital.substr(0,1); + + // single nucleon transfer + if( abs(iso_a.A - iso_b.A) == 1 ){ + lValue = orbital.substr(1,1); + jValue = orbital.substr(2); + ///printf(" l : %s, j : %s \n", lValue.c_str(), jValue.c_str()); + spdf = GetLValue(lValue); + } + + // two-nucleons transfer + if( abs(iso_a.A - iso_b.A) == 2 ){ + size_t posEq = orbital.find('='); + lValue = orbital.substr(posEq+1,1); + spdf=atoi(lValue.c_str()); + } + + if( abs(iso_a.A - iso_b.A) == 0 ){ + printf(" ===? skipped. p-n exchange reaction does not support. \n"); + } + + if( spdf == -1 ){ + printf(" ===> skipped. Not reconginzed orbital-label. (user input : l=%s | %s) \n", lValue.c_str(), orbital.c_str()); + continue; + } + } + + //get Beam energy, distingusih MeV or MeV/u + int pos = reactionEnergy.length() - 1; + for( int i = pos; i >= 0 ; i--){ + if( isdigit(reactionEnergy[i]) ) { + pos = i; + break; + } + } + string unit = reactionEnergy.substr(pos+1); + int factor = 1; + if( unit == "MeV/u") factor = iso_a.A; + double totalBeamEnergy = atof(reactionEnergy.substr(0, pos+1).c_str()) * factor; + + ///printf("unit : |%s| , %f\n", unit.c_str(), totalBeamEnergy); + ///printf(" target nucleus : %s \n", isoA.c_str()); + ///printf(" reaction : %s \n", reactionType.c_str()); + ///printf(" remain : %s \n", isoB.c_str()); + ///printf(" reaction energy : %s \n", reactionEnergy.c_str()); + ///printf(" Potential : %s \n", potential.c_str()); + ///printf(" orbital : %s \n", orbital.c_str()); + ///printf(" Ex [MeV] : %s \n", Ex.c_str()); + + double Qvalue = iso_a.Mass + iso_A.Mass - iso_b.Mass - iso_B.Mass; + ///printf("Q-Value = %f MeV\n", Qvalue); + + //########################################################## + //============ write ptolmey infile + numOfReaction ++ ; + + //================ elastic-ish transfer + if( isTransferReaction == false ){ + if ( atof(Ex.c_str()) == 0.0 ) { + fprintf(file_out, "$============================================ ELab=%5.2f(%s+%s)%s\n", + totalBeamEnergy, mass_a.c_str(), isoA.c_str(), potential.c_str()); + fprintf(file_out, "reset\n"); + fprintf(file_out, "CHANNEL %s + %s\n", mass_a.c_str(), isoA.c_str()); + fprintf(file_out, "r0target\n"); + fprintf(file_out, "ELAB = %f\n", totalBeamEnergy); + fprintf(file_out, "JBIGA=%s\n", gsSpinA.c_str()); + string pot1Name = potential.substr(0,1); + string pot1Ref = potentialRef(pot1Name); + fprintf(file_out, "$%s\n", pot1Ref.c_str()); + CallPotential(pot1Name, iso_A.A, iso_A.Z, totalBeamEnergy, iso_a.Z); + fprintf(file_out, "v = %7.3f r0 = %7.3f a = %7.3f\n", v, r0, a); + fprintf(file_out, "vi = %7.3f ri0 = %7.3f ai = %7.3f\n", vi, ri0, ai); + fprintf(file_out, "vsi = %7.3f rsi0 = %7.3f asi = %7.3f\n", vsi, rsi0, asi); + fprintf(file_out, "vso = %7.3f rso0 = %7.3f aso = %7.3f\n", vso, rso0, aso); + fprintf(file_out, "vsoi = %7.3f rsoi0 = %7.3f asoi = %7.3f rc0 = %7.3f\n", vsoi, rsoi0, asoi, rc0); + fprintf(file_out, "ELASTIC SCATTERING\n"); + fprintf(file_out, ";\n"); + }else{ + fprintf(file_out, "$============================================ Ex=%s(%s+%s|%s%s)%s,ELab=%5.2f\n", + Ex.c_str(), mass_a.c_str(), isoA.c_str(), spin.c_str(), parity.c_str(), potential.c_str(),totalBeamEnergy); + fprintf(file_out, "reset\n"); + fprintf(file_out, "REACTION: %s%s%s(%s%s %s) ELAB=%7.3f\n", + isoA.c_str(), reactionType.c_str(), isoB.c_str(), spin.c_str(), parity.c_str(), Ex.c_str(), totalBeamEnergy); + fprintf(file_out, "PARAMETERSET ineloca2 r0target\n"); + fprintf(file_out, "JBIGA=%s\n", gsSpinA.c_str()); + if( str0.size() >= 8 ){ + fprintf(file_out, "BETA=%s\n", str0[7].c_str()); //deformation length + } + string pot1Name = potential.substr(0,1); + string pot1Ref = potentialRef(pot1Name); + fprintf(file_out, "$%s\n", pot1Ref.c_str()); + CallPotential(pot1Name, iso_A.A, iso_A.Z, totalBeamEnergy, iso_a.Z); + fprintf(file_out, "INCOMING\n"); + fprintf(file_out, "v = %7.3f r0 = %7.3f a = %7.3f\n", v, r0, a); + fprintf(file_out, "vi = %7.3f ri0 = %7.3f ai = %7.3f\n", vi, ri0, ai); + fprintf(file_out, "vsi = %7.3f rsi0 = %7.3f asi = %7.3f rc0 = %7.3f\n", vsi, rsi0, asi, rc0); + ///fprintf(file_out, "vso = %7.3f rso0 = %7.3f aso = %7.3f\n", vso, rso0, aso); + ///fprintf(file_out, "vsoi = %7.3f rsoi0 = %7.3f asoi = %7.3f rc0 = %7.3f\n", vsoi, rsoi0, asoi, rc0); + fprintf(file_out, ";\n"); + + fprintf(file_out, "OUTGOING\n"); + fprintf(file_out, "$%s\n", pot1Ref.c_str()); + CallPotential(pot1Name, iso_A.A, iso_A.Z, totalBeamEnergy - atof(Ex.c_str()), iso_a.Z); + fprintf(file_out, "v = %7.3f r0 = %7.3f a = %7.3f\n", v, r0, a); + fprintf(file_out, "vi = %7.3f ri0 = %7.3f ai = %7.3f\n", vi, ri0, ai); + fprintf(file_out, "vsi = %7.3f rsi0 = %7.3f asi = %7.3f rc0 = %7.3f\n", vsi, rsi0, asi, rc0); + ///fprintf(file_out, "vsi = %7.3f rsi0 = %7.3f asi = %7.3f\n", vsi, rsi0, asi); + ///fprintf(file_out, "vso = %7.3f rso0 = %7.3f aso = %7.3f\n", vso, rso0, aso); + ///fprintf(file_out, "vsoi = %7.3f rsoi0 = %7.3f asoi = %7.3f rc0 = %7.3f\n", vsoi, rsoi0, asoi, rc0); + fprintf(file_out, ";\n"); + } + } + + //================ Transfer reaction + if( isTransferReaction ){ + fprintf(file_out, "$============================================ Ex=%s(%s)%s\n", Ex.c_str(), orbital.c_str(), potential.c_str()); + fprintf(file_out, "reset\n"); + fprintf(file_out, "REACTION: %s%s%s(%s%s %s) ELAB=%7.3f\n", + isoA.c_str(), reactionType.c_str(), isoB.c_str(), spin.c_str(), parity.c_str(), Ex.c_str(), totalBeamEnergy); + + //-------- Projectile (the light particle) + if( abs(numNucleonsTransfer) == 1 ){ + if( iso_a.A <= 2 && iso_a.Z <= 1 && iso_b.A <=2 && iso_b.Z <= 1){ // incoming d or p + fprintf(file_out, "PARAMETERSET dpsb r0target \n"); + fprintf(file_out, "lstep=1 lmin=0 lmax=30 maxlextrap=0 asymptopia=50 \n"); + fprintf(file_out, "\n"); + fprintf(file_out, "PROJECTILE \n"); + fprintf(file_out, "wavefunction av18 \n"); + fprintf(file_out, "r0=1 a=0.5 l=0 rc0=1.2\n"); + } + + if( (3 <= iso_a.A && iso_a.A <= 4) || (3 <= iso_b.A && iso_b.A <= 4) ){ + fprintf(file_out, "PARAMETERSET alpha3 r0target \n"); + fprintf(file_out, "lstep=1 lmin=0 lmax=30 maxlextrap=0 asymptopia=50 \n"); + fprintf(file_out, "\n"); + fprintf(file_out, "PROJECTILE \n"); + fprintf(file_out, "wavefunction phiffer \n"); + + if( iso_a.Z + iso_b.Z == 2){ // (t,d) or (d,t) + fprintf(file_out, "nodes=0 l=0 jp=1/2 spfacp=1.30 v=172.88 r=0.56 a=0.69 param1=0.64 param2=1.15 rc=2.0\n"); + } + + if( iso_a.Z + iso_b.Z == 3){ // (3He,d) or (d, 3He) + fprintf(file_out, "nodes=0 l=0 jp=1/2 spfacp=1.31 v=179.94 r=0.54 a=0.68 param1=0.64 param2=1.13 rc=2.0\n"); + } + + if( iso_b.A == 4 ){ + fprintf(file_out, "nodes=0 l=0 jp=1/2 spfacp=1.61 v=202.21 r=.93 a=.66 param1=.81 param2=.87 rc=2.0 $ rc=2 is a quirk\n"); + } + } + }else if( abs(numNucleonsTransfer) == 2 ){ // 2 nucleons transfer + fprintf(file_out, "PARAMETERSET alpha3 r0target\n"); + fprintf(file_out, "lstep=1 lmin=0 lmax=30 maxlextrap=0 ASYMPTOPIA=40\n"); + fprintf(file_out, "\n"); + fprintf(file_out, "PROJECTILE\n"); + fprintf(file_out, "wavefunction phiffer\n"); + fprintf(file_out, "L = 0 NODES=0 R0 = 1.25 A = .65 RC0 = 1.25\n"); + } + fprintf(file_out, ";\n"); + + //===== TARGET + fprintf(file_out, "TARGET\n"); + ///check Ex is above particle threshold + double nThreshold = iso_B.CalSp(0,1); + double pThreshold = iso_B.CalSp(1,0); + bool isAboveThreshold = false; + double ExEnergy = atof(Ex.c_str()); + if( ExEnergy > nThreshold || ExEnergy > pThreshold ) { + isAboveThreshold = true; + printf(" Ex = %.3f MeV is above thresholds; Sp = %.3f MeV, Sn = %.3f MeV\n", ExEnergy, pThreshold, nThreshold); + } + + if( abs(iso_a.A-iso_b.A) == 1 ){ + fprintf(file_out, "JBIGA=%s\n", gsSpinA.c_str()); + if( isAboveThreshold ) { + fprintf(file_out, "nodes=%s l=%d jp=%s E=-.2 $node is n-1, set binding 200 keV \n", node.c_str(), spdf, jValue.c_str()); + }else{ + fprintf(file_out, "nodes=%s l=%d jp=%s $node is n-1 \n", node.c_str(), spdf, jValue.c_str()); + } + fprintf(file_out, "r0=1.25 a=.65 \n"); + fprintf(file_out, "vso=6 rso0=1.10 aso=.65 \n"); + fprintf(file_out, "rc0=1.3 \n"); + } + + if( abs(iso_a.A-iso_b.A) == 2 ){ + fprintf(file_out, "JBIGA=%s\n", gsSpinA.c_str()); + if( isAboveThreshold ){ + fprintf(file_out, "nodes=%s L=%d E=-.2 $node is n-1, binding by 200 keV \n", node.c_str(), spdf); + }else{ + fprintf(file_out, "nodes=%s L=%d $node is n-1 \n", node.c_str(), spdf); + } + } + + fprintf(file_out, ";\n"); + + //===== POTENTIAL + string pot1Name = potential.substr(0,1); + string pot1Ref = potentialRef(pot1Name); + fprintf(file_out, "INCOMING $%s\n", pot1Ref.c_str()); + CallPotential(pot1Name, iso_A.A, iso_A.Z, totalBeamEnergy, iso_a.Z); + fprintf(file_out, "v = %7.3f r0 = %7.3f a = %7.3f\n", v, r0, a); + fprintf(file_out, "vi = %7.3f ri0 = %7.3f ai = %7.3f\n", vi, ri0, ai); + fprintf(file_out, "vsi = %7.3f rsi0 = %7.3f asi = %7.3f\n", vsi, rsi0, asi); + fprintf(file_out, "vso = %7.3f rso0 = %7.3f aso = %7.3f\n", vso, rso0, aso); + fprintf(file_out, "vsoi = %7.3f rsoi0 = %7.3f asoi = %7.3f rc0 = %7.3f\n", vsoi, rsoi0, asoi, rc0); + fprintf(file_out, ";\n"); + + string pot2Name = potential.substr(1,1); + string pot2Ref = potentialRef(pot2Name); + fprintf(file_out, "OUTGOING $%s\n", pot2Ref.c_str()); + //printf(" total Beam Energy : %f | Qvalue : %f | Ex : %f \n", totalBeamEnergy, Qvalue, atof(Ex.c_str())); + double eBeam = totalBeamEnergy + Qvalue - atof(Ex.c_str()); + CallPotential(pot2Name, iso_B.A, iso_B.Z, eBeam, iso_b.Z); + fprintf(file_out, "v = %7.3f r0 = %7.3f a = %7.3f\n", v, r0, a); + fprintf(file_out, "vi = %7.3f ri0 = %7.3f ai = %7.3f\n", vi, ri0, ai); + fprintf(file_out, "vsi = %7.3f rsi0 = %7.3f asi = %7.3f\n", vsi, rsi0, asi); + fprintf(file_out, "vso = %7.3f rso0 = %7.3f aso = %7.3f\n", vso, rso0, aso); + fprintf(file_out, "vsoi = %7.3f rsoi0 = %7.3f asoi = %7.3f rc0 = %7.3f\n", vsoi, rsoi0, asoi, rc0); + fprintf(file_out, ";\n"); + } + + + + + fprintf(file_out, "anglemin=%f anglemax=%f anglestep=%f\n", angMin, angMax, angStep); + fprintf(file_out, ";\n"); + + } + + printf("================= end of input. Number of Reaction : %d \n", numOfReaction); + + fprintf(file_out, "end $================================== end of input\n"); + file_in.close(); + fclose(file_out); + + return 1; + +} diff --git a/cleopatra/Isotope.C b/cleopatra/Isotope.C new file mode 100644 index 0000000..d100516 --- /dev/null +++ b/cleopatra/Isotope.C @@ -0,0 +1,64 @@ +/*********************************************************************** + * + * This is Isotope.C for isotope mass-related quatilies + * + * ----------------------------------------------------- + * To compile + * + * g++ Isotope.C -o Isotope + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Feb-20, 2021 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include "ClassIsotope.h" + +using namespace std; + +void Usage(){ + cout << "./Isotope Sym" << endl; + cout << "./Isotope A Z" << endl; + ///cout << "./Isotope A Z A' Z'" << endl; + ///cout << " Opt = rkm, e.g. 001 only calculate mass" << endl; + ///cout << " |||_ mass " << endl; + ///cout << " ||__ kinematics " << endl; + ///cout << " |___ reaction kinematics " << endl; + exit(0); +} + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("========== Isotope mass-related quantities ==========\n"); + printf("=================================================================\n"); + + if ( argc != 2 && argc != 3 && argc != 6) Usage(); + + Isotope iso1, iso2; + int Z, A, Za, Aa; + //string Opt = argv[1]; + + if (argc == 2){ + iso1.SetIsoByName(argv[1]); + } + if (argc == 3){ + A= atoi(argv[1]); + Z= atoi(argv[2]); + iso1.SetIso(A, Z); + //}else if ( argc == 6){ + // A= atoi(argv[2]); + // Z= atoi(argv[3]); + // Aa= atoi(argv[4]); + // Za= atoi(argv[5]); + // iso1.SetIso(A, Z); + // iso2.SetIso(Aa,Za); + } + + iso1.Print(); + + iso1.ListShell(); + +} diff --git a/cleopatra/PlotTGraphTObjArray.C b/cleopatra/PlotTGraphTObjArray.C new file mode 100644 index 0000000..c65fbdc --- /dev/null +++ b/cleopatra/PlotTGraphTObjArray.C @@ -0,0 +1,58 @@ +/*********************************************************************** + * + * This is PlotResultInRoot.C for ExtractXSec *.root output + * + * The Xsec are stored in (TObjArray *) gList + * + * This program is simple get plot all the member in the gList + * + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ PlotResultInROOT.C -o PlotResultInROOT `root-config --cflags --glibs` + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include +#include "PlotTGraphTObjArray.h" +using namespace std; + + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("==================== Plot Results in ROOT =======================\n"); + printf("=================================================================\n"); + + if(argc < 2) { + printf("Usage: ./PlotTGraphTObjArray root_file [savePNG]\n"); + printf(" savePNG : 1 or 0, default is 0\n"); + exit(0); + }else{ + printf("From file : %s \n", argv[1]); + printf("=========== Press Ctrl+C to end.\n"); + } + + string readFile = argv[1]; + bool isSavePNG = false; + if( argc >= 3) isSavePNG = atoi(argv[2]); + + if( isSavePNG ){ + + PlotTGraphTObjArray(readFile, true); + + }else{ + TApplication app ("app", &argc, argv); + + PlotTGraphTObjArray(readFile); + + app.Run(); //anything after this line is not running + } + return 0; + +} diff --git a/cleopatra/PlotTGraphTObjArray.h b/cleopatra/PlotTGraphTObjArray.h new file mode 100644 index 0000000..ea3b14e --- /dev/null +++ b/cleopatra/PlotTGraphTObjArray.h @@ -0,0 +1,101 @@ +/*********************************************************************** + * + * This is PlotResultInRoot.C for ExtractXSec *.root output + * + * The Xsec are stored in (TObjArray *) gList + * + * This program is simple get plot all the member in the gList + * + * ----------------------------------------------------- + * This program will call the root library and compile in g++ + * compilation: + * g++ PlotResultInROOT.C -o PlotResultInROOT `root-config --cflags --glibs` + * + * ------------------------------------------------------ + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void PlotTGraphTObjArray(TString rootFileName, bool isSavePNG = false){ + + TFile * file = new TFile(rootFileName, "READ"); + + TObjArray * gList = (TObjArray *) file->FindObjectAny("thetaCM_TGraph"); + + if( gList == NULL ) { + printf("No Result was found.\n"); + return; + } + + TCanvas * cPlots = new TCanvas("cPlots", "Ptolemy Results", 0, 0, 800, 600); + cPlots->SetLogy(); + + TLegend * legend = new TLegend( 0.6, 0.6, 0.9, 0.9); //x1, y1, x2, y2 + + const int n = gList->GetLast() + 1 ; + + TGraph ** gr = new TGraph *[n]; + + //Get minimum, maximum Y + double maxY = 0; + double minY = 10000000; + for ( int i = 0; i < n ; i++){ + + gr[i] = (TGraph *) gList->At(i); + gr[i]->SetLineColor(i+1); + gr[i]->GetXaxis()->SetTitle("#theta_{CM} [deg]"); + gr[i]->GetYaxis()->SetTitle("d#sigma/d#Omega [mb/sr]"); + + TString name = gr[i]->GetName(); + int pos = name.First("|"); + name.Remove(0, pos+1); + legend->AddEntry(gr[i], name); + + double miny = gr[i]->GetHistogram()->GetMinimum(); + double maxy = gr[i]->GetHistogram()->GetMaximum(); + + if( miny < minY ) minY = miny; + if( maxy > maxY ) maxY = maxy; + } + + + + for ( int i = 0; i < n ; i++){ + gr[i]->Draw("same"); + + if( i == 0 ){ + gr[i]->Draw(); + gr[i]->GetYaxis()->SetRangeUser(minY * 0.8, maxY * 1.2); + }else{ + gr[i]->Draw("same"); + } + } + legend->Draw(); + + cPlots->Update(); + cPlots->Draw(); + + if( isSavePNG ){ + TDatime dateTime; + TString outPNGName = Form("Xsec_%d%02d%02d_%06d.png", dateTime.GetYear(), dateTime.GetMonth(), dateTime.GetDay(), dateTime.GetTime()); + + cPlots->SaveAs(outPNGName); + printf("%s\n", outPNGName.Data()); + + gROOT->ProcessLine(".q"); + } + + for( int i = 0; i < n; i++) delete gr[i]; + delete [] gr; + +} diff --git a/cleopatra/PySimHelper.py b/cleopatra/PySimHelper.py new file mode 100755 index 0000000..70b439b --- /dev/null +++ b/cleopatra/PySimHelper.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +#============== experimental Simulation Helper using PyROOT and PyQT +# +# need pip install PyQt6 +# need to make at Cleopatra +# +#===================================================== + +import sys +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QPushButton, QVBoxLayout, QPlainTextEdit, QGroupBox, QGridLayout +import subprocess +import ROOT +import webbrowser + +def SaveTxtFromEditor(): + if presentFileName != "" : + with open(presentFileName, "w") as f: + f.write(editor.toPlainText()) + +def LoadTxtToEditor(txtFileName): + global presentFileName + SaveTxtFromEditor() + + presentFileName = txtFileName + with open(txtFileName) as f: + text = f.read() + editor.setPlainText(text) + +def RunSimulation(): + SaveTxtFromEditor() + bash_command = "../Cleopatra/SimTransfer reactionConfig.txt detectorGeo.txt 0 '' transfer.root" + process = subprocess.Popen(bash_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, error = process.communicate() + if process.returncode != 0: + print("Error:", error.decode()) + else: + print("Output:", output.decode()) + + +def OpenHttpServer(): + global ser, file, tree + file = ROOT.TFile("transfer.root", "read") + tree = file.Get("tree") + + hEZ = ROOT.TH2F("hEZ", "E - Z; z[mm]; e[MeV]", 400, -600, 0, 400, 0, 10) + hXY = ROOT.TH2F("hXY", "Array; X[mm]; Y[MeV]", 200, -20, 20, 200, -20, 20) + hRecoilXY = ROOT.TH2F("hRecoilXY", "Recoil; X[mm]; Y[MeV]", 400, -60, 60, 400, -60, 60) + hThetaCMZ = ROOT.TH2F("hThetaCMZ", "TheatCM - Z; X[mm]; thetaCM [deg]", 400, -600, 0, 400, 0, 60) + hExCal = ROOT.TH1F("hExCal", "ExCal; MeV", 400, -1, 5) + + + for event in tree: + if( event.hit != 1 or event.thetaCM < 10 or event.loop != 1) : continue + + hEZ.Fill(event.array_hit_z, event.energy_light) # x, y + hXY.Fill(event.xArray, event.yArray) + hRecoilXY.Fill(event.xRecoil, event.yRecoil) + hThetaCMZ.Fill(event.array_hit_z, event.thetaCM) + hExCal.Fill(event.ExCal) + + + ser = ROOT.THttpServer("http:9876") + # ser.SetJSROOT("https://root.cern.ch/js/latest/") + + ser.Register("/", hEZ) + ser.Register("/", hXY) + ser.Register("/", hRecoilXY) + ser.Register("/", hThetaCMZ) + ser.Register("/", hExCal) + + ser.SetItemField("/","_layout","grid4x4") + ser.SetItemField("/","_drawitem","[hEZ, hRecoilXY, hExCal, hThetaCM]") + + webbrowser.open("http://localhost:9876/") + + +######################################################## +if __name__ == "__main__": + + app = QApplication(sys.argv) + editor = QPlainTextEdit() + + presentFileName = "" + + ser = None + file = None + tree = None + + window = QMainWindow() + window.setWindowTitle("Simulation Helper") + window.setFixedSize(800, 1000) + + mainWidget = QWidget() + window.setCentralWidget(mainWidget) + + layout = QGridLayout() + mainWidget.setLayout(layout) + + reactionGroup = QGroupBox("Reaction", window) + layout.addWidget(reactionGroup, 0, 0) + reactionLayout = QVBoxLayout(reactionGroup) + + bDetGeo = QPushButton("Detector Geo", reactionGroup) + reactionLayout.addWidget(bDetGeo) + bDetGeo.clicked.connect(lambda : LoadTxtToEditor("detectorGeo.txt")) + + bReactionConfig = QPushButton("Reaction Config", reactionGroup) + reactionLayout.addWidget(bReactionConfig) + bReactionConfig.clicked.connect(lambda : LoadTxtToEditor("reactionConfig.txt")) + + bSim = QPushButton("Simulation", reactionGroup) + reactionLayout.addWidget(bSim) + bSim.clicked.connect(RunSimulation) + + bTest = QPushButton("Open Browser", reactionGroup) + reactionLayout.addWidget(bTest) + bTest.clicked.connect(OpenHttpServer) + + layout.addWidget(editor, 0, 1, 5, 5) + LoadTxtToEditor("detectorGeo.txt") + + # # Create PyQtGraph plot + # plot = PlotWidget() + # plot_item = plot.getPlotItem() + # plot_item.plot(x=[1, 2, 3], y=[4, 6, 2]) + # layout.addWidget(plot) + + # Show the window and start the event loop + window.show() + sys.exit(app.exec()) \ No newline at end of file diff --git a/cleopatra/SimAlpha.C b/cleopatra/SimAlpha.C new file mode 100644 index 0000000..f01795b --- /dev/null +++ b/cleopatra/SimAlpha.C @@ -0,0 +1,181 @@ +#include "../Cleopatra/ClassHelios.h" +#include "TROOT.h" +#include "TBenchmark.h" +#include "TLorentzVector.h" +#include "TMath.h" +#include "TFile.h" +#include "TF1.h" +#include "TTree.h" +#include "TRandom.h" +#include +#include +#include +#include + +//----------- usage +// $root transfer.C+ | tee output.txt +// this will same the massage to output.txt + +const double ma = 3727.3792; // alpha mass + +void alpha( int numEvent = 100000){ + + //================================================= User Setting + std::string heliosDetGeoFile = "detectorGeo.txt"; + int geoID = 0; + + //std::vector energy = {3.18, 5.16, 5.49, 5.81}; + std::vector energy = {5.34, 5.42, 5.68, 6.05, 6.23, 6.77, 8.78}; //228Th + + //---- Over-ride HELIOS detector geometry + // double BField = 2.5; // T + // double BFieldTheta = 0.; // direction of B-field + // bool isCoincidentWithRecoil = false; + // double eSigma = 0.040 ; // detector energy sigma MeV + // double zSigma = 0.500 ; // detector position sigma mm + + //---- save root file name + TString saveFileName = "SimAlpha.root"; + + //============================================================= + //============================================================= + + printf("===================================================\n"); + printf("============= Alpha source in HELIOS ============\n"); + printf("===================================================\n"); + + int numEnergy = energy.size(); + printf("========= Alpha Enegry : \n"); + for( int i = 0; i < numEnergy ; i++){ + printf("%2d | %6.2f MeV\n", i, energy[i]); + } + + + //======== Set HELIOS + printf("############################################## HELIOS configuration\n"); + HELIOS helios; + // helios.OverrideMagneticFieldDirection(BFieldTheta); + // helios.OverrideFirstPos(-700); + //helios.OverrideDetectorDistance(5); + // bool sethelios = helios.SetDetectorGeometry(heliosDetGeoFile, geoID); + // if( !sethelios){ + // helios.OverrideMagneticField(BField); + // printf("======== B-field : %5.2f T, Theta : %6.2f deg\n", BField, BFieldTheta); + // } + // helios.SetCoincidentWithRecoil(isCoincidentWithRecoil); + // printf("========== energy resol.: %f MeV\n", eSigma); + // printf("=========== pos-Z resol.: %f mm \n", zSigma); + helios.SetDetectorGeometry(heliosDetGeoFile, geoID); + helios.PrintGeometry(); + + //====================== build tree + TFile * saveFile = new TFile(saveFileName, "recreate"); + TTree * tree = new TTree("tree", "tree"); + + double theta, phi, T; + + int hit; // the output of Helios.CalHit + double e, z, x, t; + int loop, detID; + double dphi, rho; //rad of rotation, and radius + int energyID; + double xHit, yHit; + + tree->Branch("hit", &hit, "hit/I"); + tree->Branch("theta", &theta, "theta/D"); + tree->Branch("phi", &phi, "phi/D"); + tree->Branch("T", &T, "T/D"); + tree->Branch("energy", &energy, "energy/D"); + tree->Branch("energyID", &energyID, "energyID/I"); + + tree->Branch("e", &e, "e/D"); + tree->Branch("z", &z, "z/D"); + tree->Branch("t", &t, "t/D"); + tree->Branch("detID", &detID, "detID/I"); + tree->Branch("loop", &loop, "loop/I"); + tree->Branch("dphi", &dphi, "dphi/D"); + tree->Branch("rho", &rho, "rho/D"); + tree->Branch("xHit", &xHit, "xHit/D"); + tree->Branch("yHit", &yHit, "yHit/D"); + + //========timer + TBenchmark clock; + bool shown ; + clock.Reset(); + clock.Start("timer"); + shown = false; + printf("############################################## generating %d events \n", numEvent); + + //====================================================== calculate + int count = 0; + TLorentzVector P; + TVector3 v; + for( int i = 0; i < numEvent; i++){ + //==== generate alpha + theta = TMath::ACos(2 * gRandom->Rndm() - 1) ; + phi = TMath::TwoPi() * gRandom->Rndm(); + + energyID = gRandom->Integer(numEnergy); + T = energy[energyID]; + + double p = TMath::Sqrt( ( ma + T )*(ma + T) - ma* ma); + + v.SetMagThetaPhi(p, theta, phi); + + P.SetVectM(v, ma); + P.SetUniqueID(2); //alpha particle has charge 2 + + //################################### tree branches + + //==== Helios + helios.CalArrayHit(P); + hit = helios.CheckDetAcceptance(); + + e = helios.GetEnergy() + gRandom->Gaus(0, helios.GetDetectorGeometry().array[geoID].eSigma); + + trajectory orb = helios.GetTrajectory_b(); + + z = orb.z + gRandom->Gaus(0, helios.GetDetectorGeometry().array[geoID].zSigma); + t = orb.t; + loop = orb.effLoop; + detID = orb.detID; + dphi = orb.phi; + rho = orb.rho; + xHit = orb.x; + yHit = orb.y; + + if( hit == 1) { + count ++; + } + + tree->Fill(); + + //#################################################################### Timer + clock.Stop("timer"); + Double_t time = clock.GetRealTime("timer"); + clock.Start("timer"); + + if ( !shown ) { + if (fmod(time, 10) < 1 ){ + printf( "%10d[%2d%%]| %8.2f sec | expect: %5.1f min \n", i, TMath::Nint((i+1)*100./numEvent), time , numEvent*time/(i+1)/60); + shown = 1; + } + }else{ + if (fmod(time, 10) > 9 ){ + shown = 0; + } + } + } + + saveFile->Write(); + saveFile->Close(); + + printf("=============== done. saved as %s. count(hit==1) : %d\n", saveFileName.Data(), count); + gROOT->ProcessLine(".q"); +} + +int main(){ + + alpha(); + return 0; +} \ No newline at end of file diff --git a/cleopatra/SimChecker.C b/cleopatra/SimChecker.C new file mode 100644 index 0000000..32c324f --- /dev/null +++ b/cleopatra/SimChecker.C @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../Armory/AnalysisLib.h" +#include "../Armory/ClassDetGeo.h" +#include "../Armory/ClassReactionConfig.h" +#include "../Cleopatra/ClassIsotope.h" +#include "../Cleopatra/ClassTransfer.h" +#include "../Cleopatra/ClassSimPlotter.h" +#include + +plotID StringToPlotID(TString str); + +void SimChecker(TString filename = "transfer.root", + TString configFile = "../working/SimCheckerConfig.txt", + Int_t padSize = 500, + bool outputCanvas = false){ + + printf("=================================================================\n"); + printf("==================== Simulate Checker ==================\n"); + printf("=================================================================\n"); + + TFile * file = new TFile(filename, "read"); + TTree * tree = (TTree*) file->Get("tree"); + + //*================= Get reactions and Ex + TMacro * ListOfReactions = (TMacro *) file->FindObjectAny("ListOfReactions"); + const short numReact = ListOfReactions->GetListOfLines()->GetEntries(); + + printf(">>>>> %d reactions found.\n", numReact); + + std::vector reactionList(numReact); + for( int i = 0; i < numReact; i++ ){ + std::string haha = ListOfReactions->GetListOfLines()->At(i)->GetName(); + std::vector kaka = AnalysisLib::SplitStr(haha, "|"); + reactionList[i]= kaka[1]; + } + + std::vector reactEx(numReact); //2-D array [i][j] = i-reaction, j-Ex + TMacro * AllExList = (TMacro *) file->FindObjectAny("AllExList"); + + TMacro * ExID_ReactID_List = (TMacro *) file->FindObjectAny("ExID_ReactID_List"); + const short numEx = ExID_ReactID_List->GetListOfLines()->GetEntries()-1; + + for( int i = 1; i <= numEx; i++){ + std::string haha = ExID_ReactID_List->GetListOfLines()->At(i)->GetName(); + std::vector kaka = AnalysisLib::SplitStr(haha, " "); + + std::string dudu = AllExList->GetListOfLines()->At(i)->GetName(); + std::vector dada = AnalysisLib::SplitStr(dudu, " "); + + short rID = atoi(kaka[1].c_str()); + reactEx[rID].Add(atof(dada[0].c_str()), + atof(dada[1].c_str()), + atof(dada[2].c_str()), + atof(dada[3].c_str())); + } + + for( int i = 0; i < numReact; i++ ){ + printf("=========== %s\n", reactionList[i].c_str()); + reactEx[i].Print(); + } + + //*================== detGeoID + TMacro * detGeotxt = (TMacro *) file->FindObjectAny("detGeo"); + DetGeo detGeo(detGeotxt); + detGeo.Print(true); + + //*================== Get EZ-curve + TObjArray * ezList = (TObjArray *) file->FindObjectAny("EZCurve"); + + //*================== Get thetaCM = 0 + TObjArray * thetaCM0List = (TObjArray *) file->FindObjectAny("thetaCM_Z"); + + //^################################################ Find e-range, z-range + + std::vector> zRange(numReact, std::vector(2)); + std::vector eMax(numReact); + + int count = 0; + for( int i = 0; i < numReact; i++ ){ + zRange[i][0] = detGeo.array[i].zMin-50; + zRange[i][1] = detGeo.array[i].zMax+50; + + eMax[i] = -1; + for( size_t j = 0; j < reactEx[i].ExList.size() ; j ++){ + TGraph * func = (TGraph *) ezList->At(count); + double aaa = func->Eval(zRange[i][1]); + // printf(" xxxxxxxxxxxx %d, %d | %d %.3f\n", i, j, count, aaa); + if( aaa > eMax[i] ) eMax[i] = aaa; + count++; + } + + eMax[i] = TMath::Ceil( eMax[i] * 1.1 ); + } + + // for( int i = 0; i < numReact; i++ ){ + // printf(" %d | eMax : %.2f, zRange : %.2f, %.2f \n", i, eMax[i], zRange[i][0], zRange[i][1]); + // } + + // //^################################################ + TMacro * config = new TMacro(configFile); + int numLine = config->GetListOfLines()->GetSize(); + + TString gate; + std::vector padPlotID; + + float elumMax = 60; + float thetaCMMax = 60; //TODO add thetaCM curves in transfer, so that it can be determinated automatically + + int rowCount = 0; + int colCount = 0; + + bool startCanvasConfig = false; + bool startGateConfig = false; + bool startExtra = false; + for( int i = 0; i < numLine ; i++){ + std::string haha = config->GetListOfLines()->At(i)->GetName(); + std::vector dudu = AnalysisLib::SplitStr(haha, ","); + TString lala = haha; + lala.Remove(3); + if( (lala == " " || lala == "// " || lala == "//=") && dudu.size() == 0) continue; + if( lala == "//#" ) break; + if( lala == "//*" ) { + startCanvasConfig = true; + // rowCount ++; + continue; + } + if( lala == "//^" ) { + startCanvasConfig = false; + startGateConfig = true; + continue; + } + if( lala == "//@" ) { + startGateConfig = false; + startExtra = true; + } + + if( startCanvasConfig ){ + rowCount ++; + // printf("|%s|\n", haha.c_str()); + if( dudu.size() > colCount ) colCount = dudu.size(); + + for( size_t k = 0; k < dudu.size() ; k++){ + padPlotID.push_back(StringToPlotID(dudu[k])); + } + } + + if( startGateConfig ){ + gate = haha; + } + + if( startExtra ){ + if( dudu[0] == "elum_Max" ) elumMax = atof(dudu[2].c_str()); + if( dudu[0] == "thetaCM_Max" ) thetaCMMax = atof(dudu[2].c_str()); + } + + } + + gStyle->SetOptStat(""); + gStyle->SetStatY(0.9); + gStyle->SetStatX(0.9); + gStyle->SetStatW(0.4); + gStyle->SetStatH(0.2); + gStyle->SetLabelSize(0.05, "XY"); + gStyle->SetTitleFontSize(0.1); + + printf(" Canvas division | col : %d, row : %d \n", colCount, rowCount); + count = 0; + for( int i = 0; i < rowCount; i++){ + for( int j = 0; j < colCount; j++){ + printf("%6d", padPlotID[count]); + count++; + } + printf("\n"); + } + + printf("Gate : %s \n", gate.Data()); + printf("elum Max : %.2f mm\n", elumMax); + printf("thetaCM Max : %.2f deg\n", thetaCMMax); + + printf("#####################################################\n"); + + Plotter ** plotter = new Plotter*[numReact]; + + for( int i = 0; i < numReact; i++){ + plotter[i] = new Plotter(tree, i, reactionList[i], detGeo, reactEx[i], gate, padPlotID); + plotter[i]->SetRanges(zRange[i][0], zRange[i][1], eMax[i], elumMax, thetaCMMax); + plotter[i]->SetCanvas(colCount, rowCount, 500, padPlotID); + plotter[i]->Plot(); + + } + + return; + +} + + +plotID StringToPlotID(TString str){ + + if( str == "pEZ") return plotID::pEZ; /// 0 + if( str == "pRecoilXY") return plotID::pRecoilXY; /// 1 + if( str == "pThetaCM" ) return plotID::pThetaCM; /// 2 + if( str == "pExCal" ) return plotID::pExCal; /// 3 + if( str == "pArrayXY" ) return plotID::pArrayXY; /// 4 + if( str == "pInfo" ) return plotID::pInfo; /// 5 + if( str == "pElum1XY" ) return plotID::pElum1XY; /// 6 + if( str == "pRecoilXY1" ) return plotID::pRecoilXY1; /// 7 + if( str == "pRecoilXY2" ) return plotID::pRecoilXY2; /// 8 + if( str == "pTDiffZ" ) return plotID::pTDiffZ; /// 9 + if( str == "pRecoilRThetaCM" ) return plotID::pRecoilRThetaCM; /// 10 + if( str == "pRecoilRZ" ) return plotID::pRecoilRZ; /// 11 + if( str == "pEElum1R" ) return plotID::pEElum1R; /// 12 + if( str == "pRecoilRTR" ) return plotID::pRecoilRTR; /// 13 + if( str == "pThetaCM_Z" ) return plotID::pThetaCM_Z; /// 14 + if( str == "pElum1RThetaCM" ) return plotID::pElum1RThetaCM; /// 15 + if( str == "pEmpty" ) return plotID::pEmpty ; /// 16 + + return plotID::pEmpty; +} \ No newline at end of file diff --git a/cleopatra/SimHelper.C b/cleopatra/SimHelper.C new file mode 100644 index 0000000..f3c6323 --- /dev/null +++ b/cleopatra/SimHelper.C @@ -0,0 +1,599 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "../Cleopatra/SimTransfer.C" +#include "../Cleopatra/InFileCreator.h" +#include "../Cleopatra/ExtractXSec.h" +#include "../Cleopatra/PlotTGraphTObjArray.h" +#include "../Armory/AutoFit.C" +#include "../Armory/AnalysisLib.h" +#include "../Cleopatra/SimChecker.C" + +#include +#include +#include +#include + +#ifdef __linux__ + #define OS_Type 1 +#elif __APPLE__ + #define OS_Type 0 +#endif + +TString isoFileName; + +class MyMainFrame { + RQ_OBJECT("MyMainFrame") + +private: + TGMainFrame *fMain; + + TGTextEdit * editor; + + TString fileName; + + TGLabel * fileLabel; + TGLabel * statusLabel; + + TGNumberEntry * angMin; + TGNumberEntry * angMax; + TGNumberEntry * angStep; + + TGCheckButton * withDWBA; + + TGCheckButton * isInFile; + TGCheckButton * isRun; + TGCheckButton * isExtract; + TGCheckButton * isPlot; + + TGComboBox * extractFlag; + + TGTextEntry * txtName ; + TGTextEntry * txtEx ; + +public: + MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h); + virtual ~MyMainFrame(); + void Command(int); + void OpenFile(int); + void GetData(); + bool IsFileExist(TString filename); + +}; + + +MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) { + // Create a main frame + fMain = new TGMainFrame(p,w,h); + + TGHorizontalFrame *hframe = new TGHorizontalFrame(fMain,600,600 ); + fMain->AddFrame(hframe, new TGLayoutHints(kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 2,2,2,2)); + + TGVerticalFrame *hframe1 = new TGVerticalFrame(fMain,600,600 ); + hframe->AddFrame(hframe1); + + TGVerticalFrame *hframe2 = new TGVerticalFrame(fMain,600,1000 ); + hframe->AddFrame(hframe2,new TGLayoutHints( kLHintsExpandX | kLHintsExpandY, 2,2,2,2)); + + fileName = "../working/detectorGeo.txt"; + + TGHorizontalFrame *hframe00 = new TGHorizontalFrame(hframe2,600,600 ); + hframe2->AddFrame(hframe00, new TGLayoutHints(kLHintsCenterX | kLHintsExpandX , 2,2,2,2)); + + fileLabel = new TGLabel(hframe00, ""); + fileLabel->SetWidth(370); + fileLabel->SetHeight(20); + fileLabel->SetTextColor(kRed); + fileLabel->ChangeOptions(kFixedSize | kSunkenFrame); + fileLabel->SetText(fileName); + hframe00->AddFrame(fileLabel, new TGLayoutHints(kLHintsLeft, 2,2,2,2)); + + TGTextButton *save = new TGTextButton(hframe00,"Save"); + save->SetWidth(100); + save->SetHeight(20); + save->ChangeOptions( save->GetOptions() | kFixedSize ); + save->Connect("Clicked()","MyMainFrame",this,"Command(=3)"); + hframe00->AddFrame(save, new TGLayoutHints(kLHintsLeft,5,5,3,4)); + + TGTextButton *help = new TGTextButton(hframe00, "Help"); + help->SetWidth(100); + help->SetHeight(20); + help->ChangeOptions( help->GetOptions() | kFixedSize ); + help->Connect("Clicked()","MyMainFrame",this,"Command(=4)"); + hframe00->AddFrame(help,new TGLayoutHints(kLHintsLeft, 5,5,3,4)); + + editor = new TGTextEdit(hframe2, 600, 700); + editor->LoadFile(fileName); + hframe2->AddFrame(editor, new TGLayoutHints(kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 2,2,2,2)); + + statusLabel = new TGLabel(hframe2, ""); + statusLabel->SetWidth(600); + statusLabel->SetHeight(20); + statusLabel->SetTextJustify(kTextLeft); + statusLabel->SetTextColor(1); + statusLabel->ChangeOptions(kFixedSize | kSunkenFrame); + hframe2->AddFrame(statusLabel, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 2,2,2,2)); + + {//================= Simulation group + TGGroupFrame * simFrame = new TGGroupFrame(hframe1, "Kinematics Simulation", kVerticalFrame); + hframe1->AddFrame(simFrame, new TGLayoutHints(kLHintsCenterX, 5,5,3,4)); + + TGTextButton *openDet = new TGTextButton(simFrame, "detector Geo."); + openDet->SetWidth(150); + openDet->SetHeight(20); + openDet->ChangeOptions( openDet->GetOptions() | kFixedSize ); + openDet->Connect("Clicked()","MyMainFrame",this, "OpenFile(=0)"); + simFrame->AddFrame(openDet,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + TGTextButton *openRec = new TGTextButton(simFrame, "reaction Config"); + openRec->SetWidth(150); + openRec->SetHeight(20); + openRec->ChangeOptions( openRec->GetOptions() | kFixedSize ); + openRec->Connect("Clicked()","MyMainFrame",this, "OpenFile(=1)"); + simFrame->AddFrame(openRec,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + withDWBA = new TGCheckButton(simFrame, "Sim with DWBA"); + withDWBA->SetWidth(140); + withDWBA->ChangeOptions(kFixedSize ); + simFrame->AddFrame(withDWBA, new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + TGTextButton *Sim = new TGTextButton(simFrame,"Simulate"); + Sim->SetWidth(150); + Sim->SetHeight(40); + Sim->ChangeOptions( Sim->GetOptions() | kFixedSize ); + Sim->Connect("Clicked()","MyMainFrame",this,"Command(=1)"); + simFrame->AddFrame(Sim, new TGLayoutHints(kLHintsRight,5,5,3,4)); + + TGTextButton *openSimChk = new TGTextButton(simFrame, "Config Simulation Plot"); + openSimChk->SetWidth(150); + openSimChk->SetHeight(20); + openSimChk->ChangeOptions( openSimChk->GetOptions() | kFixedSize ); + openSimChk->Connect("Clicked()","MyMainFrame",this, "OpenFile(=4)"); + simFrame->AddFrame(openSimChk,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + TGTextButton *SimChk = new TGTextButton(simFrame,"Re-Plot Simulation"); + SimChk->SetWidth(150); + //SimChk->SetHeight(40); + SimChk->ChangeOptions( SimChk->GetOptions() | kFixedSize ); + SimChk->Connect("Clicked()","MyMainFrame",this,"Command(=2)"); + simFrame->AddFrame(SimChk, new TGLayoutHints(kLHintsRight,5,5,3,4)); + + TGTextButton *autoFit = new TGTextButton(simFrame,"AutoFit ExCal"); + autoFit->SetWidth(150); + //autoFit->SetHeight(40); + autoFit->ChangeOptions( autoFit->GetOptions() | kFixedSize ); + autoFit->Connect("Clicked()","MyMainFrame",this,"Command(=5)"); + simFrame->AddFrame(autoFit, new TGLayoutHints(kLHintsRight,5,5,3,4)); + } + + {//================= DWBA group + TGGroupFrame * DWBAFrame = new TGGroupFrame(hframe1, "DWBA calculation", kVerticalFrame); + hframe1->AddFrame(DWBAFrame, new TGLayoutHints(kLHintsCenterX, 5,5,3,4)); + + TGTextButton *openDWBA = new TGTextButton(DWBAFrame, "DWBA setting"); + openDWBA->SetWidth(150); + openDWBA->SetHeight(20); + openDWBA->ChangeOptions( openDWBA->GetOptions() | kFixedSize ); + openDWBA->Connect("Clicked()","MyMainFrame",this, "OpenFile(=3)"); + DWBAFrame->AddFrame(openDWBA,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + TGTextButton *openInFile = new TGTextButton(DWBAFrame, "InFile"); + openInFile->SetWidth(150); + openInFile->SetHeight(20); + openInFile->ChangeOptions( openDWBA->GetOptions() | kFixedSize ); + openInFile->Connect("Clicked()","MyMainFrame",this, "OpenFile(=5)"); + DWBAFrame->AddFrame(openInFile,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + TGTextButton *openOutFile = new TGTextButton(DWBAFrame, "OutFile"); + openOutFile->SetWidth(150); + openOutFile->SetHeight(20); + openOutFile->ChangeOptions( openDWBA->GetOptions() | kFixedSize ); + openOutFile->Connect("Clicked()","MyMainFrame",this, "OpenFile(=6)"); + DWBAFrame->AddFrame(openOutFile,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + TGTextButton *xsecFile = new TGTextButton(DWBAFrame, "X-Sec"); + xsecFile->SetWidth(150); + xsecFile->SetHeight(20); + xsecFile->ChangeOptions( openDWBA->GetOptions() | kFixedSize ); + xsecFile->Connect("Clicked()","MyMainFrame",this, "OpenFile(=7)"); + DWBAFrame->AddFrame(xsecFile,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + + //-------- angle setting + TGHorizontalFrame * hframe000 = new TGHorizontalFrame(DWBAFrame, 150, 30, kFixedSize); + DWBAFrame->AddFrame(hframe000); + + TGLabel * lb1 = new TGLabel(hframe000, "angMin"); + lb1->SetWidth(50); lb1->ChangeOptions( kFixedSize); + hframe000->AddFrame(lb1, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 5, 5, 0, 0)); + + TGLabel * lb2 = new TGLabel(hframe000, "angMax"); + lb2->SetWidth(50); lb2->ChangeOptions( kFixedSize); + hframe000->AddFrame(lb2, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 5, 5, 0, 0)); + + TGLabel * lb3 = new TGLabel(hframe000, "angStep"); + lb3->SetWidth(50); lb3->ChangeOptions( kFixedSize); + hframe000->AddFrame(lb3, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 5, 5, 0, 0)); + + TGHorizontalFrame * hframe001 = new TGHorizontalFrame(DWBAFrame, 150, 30, kFixedSize); + DWBAFrame->AddFrame(hframe001); + + angMin = new TGNumberEntry(hframe001, 0, 0, 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); + angMin->SetWidth(50); + angMin->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, 180); + hframe001->AddFrame(angMin, new TGLayoutHints(kLHintsCenterX , 5, 5, 0, 0)); + + angMax = new TGNumberEntry(hframe001, 60, 0, 0, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative); + angMax->SetWidth(50); + angMax->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, 180); + hframe001->AddFrame(angMax, new TGLayoutHints(kLHintsCenterX , 5, 5, 0, 0)); + + angStep = new TGNumberEntry(hframe001, 1, 0, 0, TGNumberFormat::kNESRealOne, TGNumberFormat::kNEAPositive); + angStep->SetWidth(50); + angStep->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, 30); + hframe001->AddFrame(angStep, new TGLayoutHints(kLHintsCenterX, 5, 5, 0, 0)); + + //------- Check Boxes + isInFile = new TGCheckButton(DWBAFrame, "Create inFile"); + isInFile->SetWidth(100); + isInFile->ChangeOptions(kFixedSize ); + isInFile->SetState(kButtonDown); + DWBAFrame->AddFrame(isInFile, new TGLayoutHints(kLHintsLeft, 5,5,3,4)); + + isRun = new TGCheckButton(DWBAFrame, "Run Ptolemy"); + isRun->SetWidth(100); + isRun->ChangeOptions(kFixedSize ); + isRun->SetState(kButtonDown); + DWBAFrame->AddFrame(isRun, new TGLayoutHints(kLHintsLeft, 5,5,3,4)); + + isExtract = new TGCheckButton(DWBAFrame, "Extract Xsec"); + isExtract->SetWidth(100); + isExtract->ChangeOptions(kFixedSize ); + isExtract->SetState(kButtonDown); + DWBAFrame->AddFrame(isExtract, new TGLayoutHints(kLHintsLeft, 5,5,3,4)); + + isPlot = new TGCheckButton(DWBAFrame, "Plot"); + isPlot->SetWidth(100); + isPlot->ChangeOptions(kFixedSize ); + isPlot->SetState(kButtonDown); + DWBAFrame->AddFrame(isPlot, new TGLayoutHints(kLHintsLeft, 5,5,3,4)); + + extractFlag = new TGComboBox(DWBAFrame, 100); + extractFlag->SetWidth(130); + extractFlag->SetHeight(30); + + extractFlag->AddEntry("Xsec.", 2); + extractFlag->AddEntry("Ratio to Ruth.", 1); + extractFlag->AddEntry("Rutherford", 3); + extractFlag->Select(2); + DWBAFrame->AddFrame(extractFlag, new TGLayoutHints(kLHintsLeft, 5,5,3,4)); + + TGTextButton *DWBA = new TGTextButton(DWBAFrame, "DWBA"); + DWBA->SetWidth(150); + DWBA->SetHeight(40); + DWBA->ChangeOptions( DWBA->GetOptions() | kFixedSize ); + DWBA->Connect("Clicked()","MyMainFrame",this,"Command(=0)"); + DWBAFrame->AddFrame(DWBA,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + } + + + // {//====================== Nuclear data API + // TGGroupFrame * dataFrame = new TGGroupFrame(hframe1, "Nuclear Data", kVerticalFrame); + // hframe1->AddFrame(dataFrame, new TGLayoutHints(kLHintsCenterX, 5,5,3,4)); + + // TGHorizontalFrame * hfData = new TGHorizontalFrame(dataFrame); dataFrame->AddFrame(hfData, new TGLayoutHints(kLHintsNormal, 0, 0, 5, 0)); + + // TGVerticalFrame * vfLabel = new TGVerticalFrame(hfData, 200); hfData->AddFrame(vfLabel ); + // TGVerticalFrame * vfTxt = new TGVerticalFrame(hfData); hfData->AddFrame(vfTxt); + + // TGLayoutHints * haha = new TGLayoutHints(kLHintsRight | kLHintsCenterY, 5,5,5,2); + // TGLayoutHints * kaka = new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 5,5,0,0); + + // TGLabel * lb1 = new TGLabel(vfLabel, "Nuclear Name :"); vfLabel->AddFrame(lb1, haha); + // TGLabel * lb2 = new TGLabel(vfLabel, "Max Ex [MeV] :"); vfLabel->AddFrame(lb2, haha); + + + // txtName = new TGTextEntry(vfTxt, "25F"); vfTxt->AddFrame(txtName, kaka); txtName->Resize(50, 20); + // txtEx = new TGTextEntry(vfTxt, "0"); vfTxt->AddFrame(txtEx, kaka); txtEx->Resize(50, 20); + + // TGTextButton *GetData = new TGTextButton(dataFrame, "Get Data"); + // GetData->SetWidth(150); + // GetData->SetHeight(40); + // GetData->ChangeOptions( GetData->GetOptions() | kFixedSize ); + // GetData->Connect("Clicked()","MyMainFrame",this,"GetData()"); + // dataFrame->AddFrame(GetData,new TGLayoutHints(kLHintsRight, 5,5,3,4)); + // } + + TGTextButton *exit = new TGTextButton(hframe1,"Exit", "gApplication->Terminate(0)"); + exit->SetWidth(150); + exit->SetHeight(40); + exit->ChangeOptions( exit->GetOptions() | kFixedSize ); + hframe1->AddFrame(exit, new TGLayoutHints(kLHintsCenterX | kLHintsExpandX, 5,5,3,4)); + + // Set a name to the main frame + fMain->SetWindowName("Simulation Helper"); + + // Map all subwindows of main frame + fMain->MapSubwindows(); + + // Initialize the layout algorithm + fMain->Resize(fMain->GetDefaultSize()); + + // Map main frame + fMain->MapWindow(); + + int versionInt = gROOT->GetVersionInt(); + + if( versionInt < 62600 ) { + statusLabel->SetText(Form("Root version : %s. Please Update Root to v6.26/00",gROOT->GetVersion())); + }else{ + statusLabel->SetText(Form("Root version : %s",gROOT->GetVersion())); + } +} + +bool MyMainFrame::IsFileExist(TString filename){ + ifstream file (filename.Data()); + return file.is_open(); +} + + +void MyMainFrame::OpenFile(int ID){ + + editor->SaveFile(fileName); + + TString oldFileName = fileName; + + if ( ID == 0 ) fileName = "../working/detectorGeo.txt"; + + if ( ID == 1 ) fileName = "../working/reactionConfig.txt"; + if ( ID == 3 ) fileName = "../working/DWBA"; + if ( ID == 5 ) fileName = "../working/DWBA.in"; + if ( ID == 6 ) fileName = "../working/DWBA.out"; + if ( ID == 7 ) fileName = "../working/DWBA.Xsec.txt"; + + if ( ID == 4 ) fileName = "../working/SimCheckerConfig.txt"; + if ( ID == 8 ) fileName = isoFileName; + + //test if file exist + if ( IsFileExist(fileName) ){ + + fileLabel->SetText(fileName); + + editor->LoadFile(fileName); + + if( ID >= 6 ) { + editor->SetReadOnly(true); + }else{ + editor->SetReadOnly(false); + } + + editor->ShowBottom(); + + if( ID < 6){ + statusLabel->SetText(fileName + " opened."); + }else{ + statusLabel->SetText(fileName + " opened. (READ ONLY)"); + } + }else{ + + statusLabel->SetText(fileName + " not exist."); + fileName = oldFileName; + + } + +} + +void MyMainFrame::GetData(){ + + TString name = txtName->GetText(); + TString maxEx = txtEx->GetText(); + + TString cmd = "../Cleopatra/nuclear_data.py " + name + " " + maxEx; + + system(cmd.Data()); + + statusLabel->SetText("Check termial."); + + //isoFileName = name + ".txt"; + + //OpenFile(8); + +} + +void MyMainFrame::Command(int ID) { + + editor->SaveFile(fileName); + + if( ID == 0 ){ + + if( isInFile->GetState()) { + double aMin = angMin->GetNumber(); + double aMax = angMax->GetNumber(); + double aStep = angStep->GetNumber(); + statusLabel->SetText("Creating DWBA.in....."); + InFileCreator("DWBA", "DWBA.in", aMin, aMax, aStep); + statusLabel->SetText("in-file created."); + } + + bool isRunOK = true; + if( isRun->GetState() && IsFileExist("DWBA.in") ) { + //printf("run ptolemy...........\n"); + + statusLabel->SetText("Running Ptolemy....."); + int output = 1; + if( OS_Type == 1 ){ + output = system("../Cleopatra/ptolemy DWBA.out"); + }else{ + output = system("../Cleopatra/ptolemy_mac DWBA.out"); + } + + statusLabel->SetText("Check terminal, if no massage, Ptolemy run well."); + + printf("Ptolemy exist code : %d\n", output); + if( output == 0 ) { + isRunOK = true; + }else{ + isRunOK = false; + statusLabel->SetText("Ptolemy exist with problems."); + } + } + + if( isRunOK && isExtract->GetState() && IsFileExist("DWBA.out")){ + int ElasticFlag = 0; // 1 for ratio to Rutherford, 2 for total Xsec, 3 for (n,n) Xsec + ElasticFlag = extractFlag->GetSelected(); + statusLabel->SetText("Extracting X-sec....."); + ExtractXSec("DWBA.out", ElasticFlag); + statusLabel->SetText("X-sec Extracted."); + } + + if( isRunOK && isPlot->GetState() && IsFileExist("DWBA.root")){ + statusLabel->SetText("Plot X-sec....."); + PlotTGraphTObjArray("DWBA.root"); + statusLabel->SetText("Plotted X-sec."); + } + } + + if( ID == 1 ){ + + string basicConfig = "reactionConfig.txt"; + string heliosDetGeoFile = "detectorGeo.txt"; + TString ptolemyRoot = ""; // when no file, use isotropic distribution of thetaCM + TString saveFileName = "transfer.root"; + + if( withDWBA->GetState() ) { + ptolemyRoot = "DWBA.root"; + } + + basicConfig = "reactionConfig.txt"; + heliosDetGeoFile = "detectorGeo.txt"; + ptolemyRoot = ""; // when no file, use isotropic distribution of thetaCM + saveFileName = "transfer.root"; + + if( withDWBA->GetState() ) { + ptolemyRoot = "DWBA.root"; + } + + statusLabel->SetText("Running simulation......."); + + Transfer( basicConfig, heliosDetGeoFile, ptolemyRoot, saveFileName); + + statusLabel->SetText("Plotting simulation......."); + + SimChecker("transfer.root"); + + statusLabel->SetText("Plotted Simulation result"); + } + + if( ID == 2 ){ + SimChecker("transfer.root"); + statusLabel->SetText(" Run Simulation first."); + } + + if( ID == 3 ){ + if( fileName != "" ){ + statusLabel->SetText(fileName + " saved."); + }else{ + statusLabel->SetText("cannot save HELP page."); + } + } + + if( ID == 4 ){ + fileName = ""; + statusLabel->SetText("Help Page."); + editor->LoadBuffer("==================== For Simulation"); + editor->AddLine(""); + editor->AddLine("1) Make sure you check :"); + editor->AddLine(" a) reaction Config"); + editor->AddLine(" b) detector Geo."); + editor->AddLine(" c) Ex List"); + editor->AddLine(""); + editor->AddLine("2) Not need to save file, fiel save when any button (except the Exit) is pressed."); + editor->AddLine(""); + editor->AddLine("3) There is a checkbox for simulation with DWBA"); + editor->AddLine(" This requires the existance of DWBA.root and DWBA.Ex.txt"); + editor->AddLine(" These files can be generated by DWBA calculation."); + editor->AddLine(" Please change the angMin = 0 and angMax = 180."); + editor->AddLine(""); + editor->AddLine("4) After simulation, it will plot the result."); + editor->AddLine(" To change the plotting, Click on the Config Simulation Plot."); + editor->AddLine(""); + editor->AddLine("5) If the transfer.root is already here, simply Plot Simulation."); + editor->AddLine(""); + editor->AddLine("========================= For DWBA "); + editor->AddLine(""); + editor->AddLine("1) Only need to change the DWBA setting."); + editor->AddLine(""); + editor->AddLine("2) The GUI offer a view on the infile and outfile."); + editor->AddLine(""); + editor->AddLine("3) For elastics scattering, there is a checkbox for plotting the ratio to RutherFord."); + editor->AddLine(""); + editor->AddLine("4) The flow of the DWBA calculation is like this:"); + editor->AddLine(" a) read the DWBA file and convert to DWBA.in"); + editor->AddLine(" b) run Ptolemy from DWBA.in, and the output is DWBA.out"); + editor->AddLine(" c) extract the cross section from the DWBA.out, and save :"); + editor->AddLine(" * DWBA.Xsec.txt"); + editor->AddLine(" * DWBA.Ex.txt"); + editor->AddLine(" * DWBA.root"); + editor->AddLine(" d) Plot the cross section from the DWBA.root."); + editor->AddLine(""); + editor->AddLine("================ Tips for using the editor, both MAC or LINUX"); + editor->AddLine(""); + editor->AddLine("Ctrl+U | Delete current line. "); + editor->AddLine("Ctrl+C | Copy "); + editor->AddLine("Ctrl+V | Paste "); + editor->AddLine("=================================================== eof"); + + TString osTypeStr; + osTypeStr.Form("OS type is %s", (OS_Type == 0 ? "Mac" : "Linux")); + + editor->AddLine(osTypeStr); + + editor->AddLine(Form("Root version : %s",gROOT->GetVersion())); + int versionInt = gROOT->GetVersionInt(); + + if( versionInt < 62600 ) { + editor->AddLine("Please Update Root to v6.26/00"); + } + + } + + if( ID == 5) { + + //TODO fit all hExCal + TH1F * temp = (TH1F*) gROOT->FindObjectAny("hExCal0"); + + if( temp != NULL ){ + AutoFit::fitAuto(temp, -1); + statusLabel->SetText("Auto Fit hExCal"); + }else{ + statusLabel->SetText("Cannot find historgram hExCal0. Please Run Plot Simulation first."); + } + + //gROOT->ProcessLine("fitAuto(hExCal, -1)"); + + } + +} + +MyMainFrame::~MyMainFrame() { + // Clean up used widgets: frames, buttons, layout hints + fMain->Cleanup(); + delete fMain; +} + + +void SimHelper() { + + new MyMainFrame(gClient->GetRoot(),800,1000); +} diff --git a/cleopatra/SimKnockout.C b/cleopatra/SimKnockout.C new file mode 100644 index 0000000..75944c7 --- /dev/null +++ b/cleopatra/SimKnockout.C @@ -0,0 +1,507 @@ +#include "ClassHelio.h" +#include "TROOT.h" +#include "TBenchmark.h" +#include "TLorentzVector.h" +#include "TMath.h" +#include "TFile.h" +#include "TF1.h" +#include "TTree.h" +#include "TRandom.h" +#include "TClonesArray.h" +#include +#include + +//----------- usage +// $root sim.C+ | tee output.txt +// this will same the massage to output.txt + +void knockout(){ + + //================================================= User Setting + //---- reaction + int AA = 23, ZA = 9; + int Aa = 1, Za = 1; + int A2 = 1, Z2 = 1; + + bool isNormalKinematics = false; + bool isOverRideExNegative = true; + double maxkb = 200.; + + //---- beam + double KEAmean = 100; // MeV/u + const int nKEA = 1; + double KEAList[nKEA] = {300}; + + double KEAsigma = 0; //KEAmean*0.001; // MeV/u , assume Guassian + double thetaMean = 0.; // mrad + double thetaSigma = 0.; // mrad , assume Guassian due to small angle + + int numEvent = 100000; + + //---- HELIOS detector geometry + string heliosDetGeoFile = "";//"detectorGeo_upstream.txt"; + double BField = 4.0; // if not detector, must set B-field, else, this value is not used. + double BFieldTheta = 0.; // direction of B-field + double eSigma = 0.0001 ; // detector energy sigma MeV + double zSigma = 0.1 ; // detector position sigma mm + + //---- excitation of Beam + int nExA = 1; + double ExAList[nExA]; + ExAList[0] = 0.000; // MeV + //ExAList[1] = 1.567; + + //---- Separation energy + string separationFile = "separation_energies.txt"; + + //---- save root file name + TString saveFileName = "knockout.root"; + + //---- Auxiliary setting + bool isTargetScattering = false; + bool isDecay = false; + bool isReDo = false; // redo calculation until detected. + + //---- target + double density = 0.913; // 0.913 g/cm3 + double targetThickness = 2./2. * 2.2e-4; // 2.2 um = 201 ug/cm2 + string stoppingPowerForA = "208Pb_in_CD2.txt"; // generated by SRIM + string stoppingPowerForb = "1H_in_CD2.txt"; + string stoppingPowerForB = "209Pb_in_CD2.txt"; + + //============================================================= + //============================================================= + //============================================================= + //===== Set Reaction + Knockout reaction; + int AB = AA-A2, ZB = ZA-Z2; + int A1 = Aa , Z1 = Za; + reaction.SetA(AA,ZA); + reaction.Seta(Aa,Za); + reaction.Set2(A2,Z2); + reaction.SetIncidentEnergyAngle(KEAmean, 0, 0); + reaction.OverRideExNegative(isOverRideExNegative); + + printf("===================================================\n"); + printf("=========== %s ===========\n", reaction.GetReactionName().Data()); + printf("=========== KE: %9.4f +- %5.4f MeV/u, dp/p = %5.2f %% \n", KEAmean, KEAsigma, KEAsigma/KEAmean * 50.); + printf("======== theta: %9.4f +- %5.4f MeV/u \n", thetaMean, thetaSigma); + printf("===================================================\n"); + + + //======== Set HELIOS + printf("############################################## HELIOS configuration\n"); + HELIOS helios1; // for particle-1 + HELIOS helios2; // for particle-2 + helios1.SetMagneticFieldDirection(BFieldTheta); + helios2.SetMagneticFieldDirection(BFieldTheta); + bool sethelios1 = helios1.SetDetectorGeometry(heliosDetGeoFile); + bool sethelios2 = helios2.SetDetectorGeometry(heliosDetGeoFile); + if( sethelios1 && sethelios2 ) { + int rowDet = helios1.GetNumberOfDetectorsInSamePos(); + printf("========== energy resol.: %f MeV\n", eSigma); + printf("=========== pos-Z resol.: %f mm \n", zSigma); + }else{ + helios1.SetMagneticField(BField); + helios2.SetMagneticField(BField); + printf("======== B-field : %5.2f T, Theta: %5.2f deg\n", BField, BFieldTheta); + } + + //==== Target scattering, only energy loss + if(isTargetScattering) printf("############################################## Target Scattering\n"); + TargetScattering msA; + TargetScattering msB; + TargetScattering msb; + + if(isTargetScattering) printf("======== Target : (thickness : %6.2f um) x (density : %6.2f g/cm3) = %6.2f ug/cm2\n", + targetThickness * 1e+4, + density, + targetThickness * density * 1e+6); + + if( isTargetScattering ){ + msA.LoadStoppingPower(stoppingPowerForA); + msb.LoadStoppingPower(stoppingPowerForb); + msB.LoadStoppingPower(stoppingPowerForB); + } + + //======= Decay of particle-B + Decay decay; + decay.SetMotherDaugther(AB, ZB, AB-1,ZB); //neutron decay + + + //======= loading excitation energy + printf("############################################## excitation energies\n"); + vector SpList; + printf("----- loading separation energies."); + ifstream file; + file.open(separationFile.c_str()); + string isotopeName; + if( file.is_open() ){ + string line; + int i = 0; + while( file >> line){ + //printf("%d, %s \n", i, line.c_str()); + if( line.substr(0,2) == "//" ) continue; + if( i == 0 ) isotopeName = line; + if ( i >= 1 ){ + SpList.push_back(atof(line.c_str())); + } + i = i + 1; + } + file.close(); + printf("... done.\n"); + printf("========== %s\n", isotopeName.c_str()); + int n = SpList.size(); + for(int i = 0; i < n ; i++){ + if( isDecay ) { + TLorentzVector temp(0,0,0,0); + int decayID = decay.CalDecay(temp, SpList[i], 0); + if( decayID == 1) { + printf("%d, Sp: %6.2f MeV --> Decay. \n", i, SpList[i]); + }else{ + printf("%d, Sp: %6.2f MeV\n", i, SpList[i]); + } + }else{ + printf("%d, Sp: %6.2f MeV \n", i, SpList[i]); + } + } + }else{ + printf("... fail\n"); + return; + } + + //====================== build tree + TFile * saveFile = new TFile(saveFileName, "recreate"); + TTree * tree = new TTree("tree", "tree"); + + double thetaNN, phiNN; + double theta1, phi1, T1; + double theta2, phi2, T2; + double thetaB, TB; + double Sp, kb, thetab, phib; + int SpID; + + double ExA; + int ExAID; + double KEA, KEAscattered, theta, phi; + + double mB,mb; + + tree->Branch("theta1", &theta1, "theta1/D"); + tree->Branch("phi1", &phi1, "phi1/D"); + tree->Branch("T1", &T1, "T1/D"); + tree->Branch("theta2", &theta2, "theta2/D"); + tree->Branch("phi2", &phi2, "phi2/D"); + tree->Branch("T2", &T2, "T2/D"); + tree->Branch("thetaB", &thetaB, "thetaB/D"); + tree->Branch("TB", &TB, "TB/D"); + tree->Branch("thetaNN", &thetaNN, "thetaNN/D"); + tree->Branch("phiNN", &phiNN, "phiNN/D"); + tree->Branch("Sp", &Sp, "Sp/D"); + tree->Branch("kb", &kb, "kb/D"); + tree->Branch("thetab", &thetab, "thetab/D"); + tree->Branch("phib", &phib, "phib/D"); + + tree->Branch("SpID", &SpID, "SpID/I"); + + tree->Branch("ExAID", &ExAID, "ExAID/I"); + tree->Branch("KEA", &KEA, "KEA/D"); + if(isTargetScattering) tree->Branch("KEAscattered", &KEAscattered, "KEAscattered/D"); + tree->Branch("theta", &theta, "theta/D"); + tree->Branch("phi", &phi, "phi/D"); + + tree->Branch("mB", &mB, "mB/D"); + tree->Branch("mb", &mb, "mb/D"); + + tree->Branch("Bfield", &BField, "Bfield/D"); + + TClonesArray * arr = new TClonesArray("TLorentzVector"); + tree->Branch("fV", arr, 256000); + arr->BypassStreamer(); + + TClonesArray * arrN = new TClonesArray("TLorentzVector"); + tree->Branch("fVN", arrN, 256000); + arrN->BypassStreamer(); + + TLorentzVector* fourVector = NULL; + + // the output of Helios.CalHit + double e1, z1, t1, rho1, x1h, y1h, r1h; + double e2, z2, t2, rho2, x2h, y2h, r2h; + tree->Branch("e1", &e1, "e1/D"); + tree->Branch("z1", &z1, "z1/D"); + tree->Branch("t1", &t1, "t1/D"); + tree->Branch("x1h", &x1h, "x1h/D"); //at 200 mm downstream + tree->Branch("y1h", &y1h, "y1h/D"); + tree->Branch("r1h", &r1h, "r1h/D"); + tree->Branch("rho1", &rho1, "rho1/D"); + + tree->Branch("e2", &e2, "e2/D"); + tree->Branch("z2", &z2, "z2/D"); + tree->Branch("t2", &t2, "t2/D"); + tree->Branch("x2h", &x2h, "x2h/D"); //at 200 mm downstream + tree->Branch("y2h", &y2h, "y2h/D"); + tree->Branch("r2h", &r2h, "r2h/D"); + tree->Branch("rho2", &rho2, "rho2/D"); + + double Sp2; + tree->Branch("Sp2", &Sp2, "Sp2/D"); + + //different coordinate + double a0, a1, a2; // in k1-k2 coordinate + tree->Branch("a0", &a0, "a0/D"); + tree->Branch("a1", &a1, "a1/D"); + tree->Branch("a2", &a2, "a2/D"); + + double b; // in THREEDEE coordinate + tree->Branch("b", &b, "b/D"); + + //========timer + TBenchmark clock; + bool shown ; + clock.Reset(); + clock.Start("timer"); + shown = false; + printf("############################################## generating %d events \n", numEvent); + + //====================================================== calculate + int count = 0; + for( int i = 0; i < numEvent; i++){ + bool redoFlag = true; + if( !isReDo ) redoFlag = false; + do{ + + //==== Set Ex of A + ExAID = gRandom->Integer(nExA); + ExA = ExAList[ExAID]; + reaction.SetExA(ExA); + + //==== Set Sp of B + SpID = gRandom->Integer(SpList.size()); + Sp = SpList[SpID]; + + //==== Set incident beam + if( KEAsigma == 0 ){ + KEA = KEAmean; + }else{ + KEA = gRandom->Gaus(KEAmean, KEAsigma); + } + if( thetaSigma == 0 ){ + theta = thetaMean; + }else{ + theta = gRandom->Gaus(thetaMean, thetaSigma); + } + + int rKEA = gRandom->Integer(nKEA); + KEA = KEAList[rKEA]; + + /* + KEA = 300*gRandom->Rndm(); + BField = 4*gRandom->Rndm(); + helios1.SetMagneticField(BField); + helios2.SetMagneticField(BField); + */ + + reaction.SetIncidentEnergyAngle(KEA, theta, 0.); + + + /* + //For target scattering + reaction.CalIncidentChannel(isNormalKinematics); // but only need is PA + TLorentzVector PA = reaction.GetPA(); + + double depth = 0; + if( isTargetScattering ){ + //==== Target scattering, only energy loss + depth = targetThickness * gRandom->Rndm(); + msA.SetTarget(density, depth); + TLorentzVector PAnew = msA.Scattering(PA); + KEAscattered = msA.GetKE()/AA; + reaction.SetIncidentEnergyAngle(KEAscattered, theta, phi); + }*/ + + //==== Calculate reaction + thetaNN = TMath::ACos(2 * gRandom->Rndm() - 1) ; + phiNN = TMath::TwoPi() * gRandom->Rndm(); + + kb = maxkb * gRandom->Rndm(); + thetab = TMath::ACos(2 * gRandom->Rndm() - 1); + phib = TMath::TwoPi() * gRandom->Rndm(); + + reaction.SetBSpk(Sp, kb, thetab, phib); + reaction.CalReactionConstant(isNormalKinematics); + reaction.Event(thetaNN, phiNN); + + TLorentzVector PA = reaction.GetPA(); + TLorentzVector Pa = reaction.GetPa(); + + TLorentzVector P1 = reaction.GetP1(); + TLorentzVector P2 = reaction.GetP2(); + TLorentzVector Pb = reaction.GetPb(); + TLorentzVector PB = reaction.GetPB(); + + /* + //==== Calculate energy loss of scattered and recoil in target + if( isTargetScattering ){ + if( Pb.Theta() < TMath::PiOver2() ){ + msb.SetTarget(density, targetThickness - depth); + }else{ + msb.SetTarget(density, depth); + } + Pb = msb.Scattering(Pb); + TbLoss = msb.GetKELoss(); + msB.SetTarget(density, targetThickness - depth); + PB = msB.Scattering(PB); + }else{ + TbLoss = 0; + } + + //======= Decay of particle-B + if( isDecay){ + int decayID = decay.CalDecay(PB, Sp, 0); // decay to ground state + if( decayID == 1 ){ + PB = decay.GetDaugther_D(); + decayTheta = decay.GetAngleChange(); + }else{ + decayTheta = TMath::QuietNaN(); + } + } + */ + + //################################### tree branches + //===== reaction + theta1 = P1.Theta() * TMath::RadToDeg(); + theta2 = P2.Theta() * TMath::RadToDeg(); + thetaB = PB.Theta() * TMath::RadToDeg(); + + T1 = P1.E() - P1.M(); + T2 = P2.E() - P2.M(); + TB = PB.E() - PB.M(); + + phi1 = P1.Phi() * TMath::RadToDeg(); + phi2 = P2.Phi() * TMath::RadToDeg(); + + //--------- diff coordinate + b = TMath::ASin( TMath::Sin(P2.Theta()) * TMath::Sin(P1.Phi() - P2.Phi() )) * TMath::RadToDeg(); + + TVector3 kA = (PA.Vect()).Unit(); + TVector3 k1 = (P1.Vect()).Unit(); + TVector3 k2 = (P2.Vect()).Unit(); + TVector3 n = (k1.Cross(k2)).Unit(); + TVector3 j = (kA - (kA.Dot(n))*n).Unit(); + + a0 = TMath::ASin(n.Dot(kA)) * TMath::RadToDeg(); + a1 = TMath::ACos(k1.Dot(j)) * TMath::RadToDeg(); + a2 = TMath::ACos(k2.Dot(j)) * TMath::RadToDeg(); + + //----------- mass + mB = PB.M(); + mb = Pb.M(); + + TVector3 bA = PA.BoostVector(); + + for(int i = 0; i < 6 ; i++){ + TLorentzVector temp; + double xyzt[4]; + switch(i){ + case 0: temp = PA; break; + case 1: temp = Pa; break; + case 2: temp = P1; break; + case 3: temp = P2; break; + case 4: temp = PB; break; + case 5: temp = Pb; break; + } + + temp.GetXYZT(xyzt); + + fourVector = (TLorentzVector*) arr->ConstructedAt(i); + fourVector->SetXYZT(xyzt[0], xyzt[1], xyzt[2], xyzt[3]); + + //into normal kinematic + temp.Boost(-bA); + temp.GetXYZT(xyzt); + + fourVector = (TLorentzVector*) arrN->ConstructedAt(i); + fourVector->SetXYZT(xyzt[0], xyzt[1], xyzt[2], xyzt[3]); + + } + + + //==== Helios + int hit1 = helios1.CalHit(P1, Z1, PB, ZB); + int hit2 = helios2.CalHit(P2, Z2, PB, ZB); + + double recoilZ = 1000; + + e1 = helios1.GetEnergy() + gRandom->Gaus(0, eSigma); + z1 = helios1.GetZ() ; + t1 = helios1.GetTime(); + rho1 = helios1.GetRho(); + x1h = helios1.GetXPos(recoilZ); + y1h = helios1.GetYPos(recoilZ); + r1h = helios1.GetR(recoilZ); + + e2 = helios2.GetEnergy() + gRandom->Gaus(0, eSigma); + z2 = helios2.GetZ() ; + t2 = helios2.GetTime(); + rho2 = helios2.GetRho(); + x2h = helios2.GetXPos(recoilZ); + y2h = helios2.GetYPos(recoilZ); + r2h = helios2.GetR(recoilZ); + + double gammaA = PA.Gamma(); + double betaA = PA.Beta(); + + Sp2 = (1-gammaA)* 938.272 - gammaA*(e1+e2) + betaA*gammaA*(P1.Pz() + P2.Pz()) ; + + //printf("%f, %f | %f, %f \n", e1, z1, e2, z2); + + //change thetaNN into deg + thetaNN = thetaNN * TMath::RadToDeg(); + + if( hit1 == 1) { + count ++; + } + + if( isReDo ){ + if( hit1 == 1) { + redoFlag = false; + }else{ + redoFlag = true; + //printf("%d, %2d, thetaNN : %f, theta : %f, z0: %f \n", i, hit, thetaNN * TMath::RadToDeg(), thetab, helios.GetZ0()); + } + }else{ + redoFlag = false; + } + + + }while( redoFlag ); + tree->Fill(); + + //#################################################################### Timer + clock.Stop("timer"); + Double_t time = clock.GetRealTime("timer"); + clock.Start("timer"); + + if ( !shown ) { + if (fmod(time, 10) < 1 ){ + printf( "%10d[%2d%%]| %8.2f sec | expect: %5.1f min \n", i, TMath::Nint((i+1)*100./numEvent), time , numEvent*time/(i+1)/60); + shown = 1; + } + }else{ + if (fmod(time, 10) > 9 ){ + shown = 0; + } + } + } + + saveFile->Write(); + saveFile->Close(); + + printf("=============== done. saved as %s. count(hit==1) : %d\n", saveFileName.Data(), count); + + gROOT->ProcessLine(".q"); + + /**/ + +} diff --git a/cleopatra/SimTransfer.C b/cleopatra/SimTransfer.C new file mode 100644 index 0000000..25c70a3 --- /dev/null +++ b/cleopatra/SimTransfer.C @@ -0,0 +1,813 @@ +#include "TROOT.h" +#include "TBenchmark.h" +#include "TLorentzVector.h" +#include "TMath.h" +#include "TFile.h" +#include "TF1.h" +#include "TTree.h" +#include "TRandom.h" +#include "TGraph.h" +#include "TMacro.h" +#include +#include +#include +#include + +#include "../Armory/ClassDetGeo.h" +#include "ClassTargetScattering.h" +#include "ClassDecay.h" +#include "ClassTransfer.h" +#include "ClassHelios.h" + +void PrintEZPlotPara(TransferReaction tran, HELIOS helios){ + + printf("==================================== E-Z plot slope\n"); + double betaRect = tran.GetReactionBeta() ; + double gamma = tran.GetReactionGamma(); + double mb = tran.GetMass_b(); + double pCM = tran.GetMomentumbCM(); + double q = TMath::Sqrt(mb*mb + pCM*pCM); ///energy of light recoil in center of mass + double slope = tran.GetEZSlope(helios.GetBField()); /// MeV/mm + printf(" e-z slope : %f MeV/mm\n", slope); + // double intercept = q/gamma - mb; // MeV + // printf(" e-z intercept (ground state) : %f MeV\n", intercept); +} + +void Transfer( + std::string basicConfig = "reactionConfig.txt", + std::string detGeoFile = "detectorGeo.txt", + TString ptolemyRoot = "DWBA.root", + TString saveFileName = "transfer.root"){ + + //*############################################# Set Reaction + + // std::vector kbCM; /// momentum of b in CM frame + // TF1 * exDistribution = nullptr; + + DetGeo detGeoConfig; + ReactionConfig reactionConfig; + + detGeoConfig.LoadDetectorGeo(detGeoFile, false); + reactionConfig.LoadReactionConfig(basicConfig); + + const unsigned short numDetGeo = detGeoConfig.array.size(); + const unsigned short numReact = reactionConfig.recoil.size(); + + if( numDetGeo != numReact ){ + printf("\e[31m !!!!!! number of array is not equal to number of reaction.!!! \e[0m\n"); + printf("Abort\n"); + return; + } + + unsigned short numTransfer = 0; + + for( int i = 0; i < std::min(numDetGeo, numReact); i++){ + if( detGeoConfig.array[i].enable ) numTransfer ++; + } + + TransferReaction * transfer = new TransferReaction[numTransfer]; + Decay * decay = new Decay[numTransfer]; + HELIOS * helios = new HELIOS[numTransfer]; + + int count = 0; + for( unsigned short i = 0 ; i < numDetGeo; i++){ + if( detGeoConfig.array[i].enable ){ + transfer[count].SetReactionFromReactionConfigClass(reactionConfig, i); + if(transfer[count].GetRecoil().isDecay) { + decay[count].SetMotherDaugther(transfer[count].GetRecoil()); + } + helios[count].SetDetectorGeometry(detGeoFile, i); + + count ++; + } + } + + printf("----- loading reaction setting from %s. \n", basicConfig.c_str()); + printf("----- loading geometry setting from %s. \n", detGeoFile.c_str()); + + printf("\e[32m#################################### Reaction & HELIOS configuration\e[0m\n"); + + //*############################################# Load DWBAroot for thetaCM distribution + TFile * distFile = new TFile(ptolemyRoot, "read"); + TObjArray * distList = nullptr; + TMacro * dwbaExList = nullptr; + TMacro * dwbaReactList = nullptr; + + TMacro dwbaExList_Used; + TMacro dwbaReactList_Used; + + bool *useDWBA = new bool[numTransfer]; + for( int i = 0; i < numTransfer; i++ ) useDWBA[i] = false; + + if( distFile->IsOpen() ) { + printf("\e[32m#################################### Load DWBA input : %s \e[0m\n", ptolemyRoot.Data()); + printf("--------- Found DWBA thetaCM distributions.\n"); + printf(" Checking DWBA matches withe %s.\n", basicConfig.c_str()); + + distList = (TObjArray *) distFile->FindObjectAny("thetaCM_TF1"); // the function List + dwbaExList = (TMacro *) distFile->FindObjectAny("ExList"); + dwbaExList_Used.AddLine(dwbaExList->GetListOfLines()->At(0)->GetName()); + dwbaReactList = (TMacro *) distFile->FindObjectAny("ReactionList"); + + int numEx = dwbaExList->GetListOfLines()->GetSize() - 1 ; + + ExcitedEnergies * dwbaExTemp = new ExcitedEnergies[numTransfer]; + + for( int i = 1; i <= numEx ; i++){ + std::string reactionName = dwbaReactList->GetListOfLines()->At(i-1)->GetName(); + printf(" %d | Checking %s from DWBA \n", i, reactionName.c_str()); + for( int j = 0; j < numTransfer; j++){ + //Check DWBA reaction is same as transfer setting + if( reactionName.find( transfer[j].GetReactionName().Data() ) != std::string::npos) { + printf(" >>> found %s in %s\n", transfer[j].GetReactionName().Data(), basicConfig.c_str()); + std::string temp = dwbaExList->GetListOfLines()->At(i)->GetName(); + dwbaReactList_Used.AddLine((reactionName + " | " + std::to_string(j)).c_str()); + dwbaExList_Used.AddLine(temp.c_str()); + if( temp[0] == '/' ) continue; + std::vector tempStr = AnalysisLib::SplitStr(temp, " "); + dwbaExTemp[j].Add( atof(tempStr[0].c_str()), atof(tempStr[1].c_str()), 1.0, 0.00); + }else{ + printf(" XXX Not found\n"); + } + } + } + + for( int i = 0; i < numTransfer; i++ ){ + if( dwbaExTemp[i].ExList.size() > 0 ) { + transfer[i].GetExList()->Clear(); + for( size_t j = 0 ; j < dwbaExTemp[i].ExList.size(); j ++ ){ + transfer[i].GetExList()->Add( dwbaExTemp[i].ExList[j].Ex, dwbaExTemp[i].ExList[j].xsec, 1.0, 0.00); + } + useDWBA[i] = true; + }else{ + printf("Cannot match %s with DWBA, use Reaction Ex List\n", transfer[i].GetReactionName().Data()); + useDWBA[i] = false; + } + } + + delete [] dwbaExTemp; + + }else{ + printf("------- no DWBA input. Use the ExList from %s\n", basicConfig.c_str()); + } + + std::vector listOfTransfer(numTransfer, false); + + for( int i = 0; i < numTransfer; i++){ + if( transfer[i].GetExList()->ExList.size() > 0 ){ + + listOfTransfer[i] = true; + + transfer[i].PrintReaction(false); + transfer[i].GetExList()->Print(); + helios[i].PrintGeometry(); + transfer[i].CreateExDistribution(); + // PrintEZPlotPara(transfer[i], helios[i]); + }else{ + printf(" Reaction : %s has no excited energy. Skipped. \n", transfer[i].GetReactionName().Data()); + } + } + + //*############################################# build tree + printf("\e[32m#################################### building Tree in %s\e[0m\n", saveFileName.Data()); + TFile * saveFile = new TFile(saveFileName, "recreate"); + TTree * tree = new TTree("tree", "tree"); + + TMacro config(basicConfig.c_str()); + TMacro detGeoTxt(detGeoFile.c_str()); + config.SetName("ReactionConfig"); + config.Write("reactionConfig"); + detGeoTxt.Write("detGeo"); + + if( distList != NULL ) distList->Write("DWBA", 1); + if( dwbaExList != NULL ) { + dwbaExList_Used.Write("DWBA_ExList", 1); + dwbaReactList_Used.Write("DWBA_ReactionList", 1); + } + + TMacro allExList; + allExList.AddLine("#---Ex relative_xsec SF sigma_in_MeV"); + TMacro exIDReactIDList; //list of all ex and corresponding Reaction ID + exIDReactIDList.AddLine("#-- ExID ReactionID"); + for( int i = 0; i < numTransfer; i++){ + std::vector tempExList = transfer[i].GetExList()->ExList; + for( size_t j = 0; j < tempExList.size(); j++){ + allExList.AddLine(Form("%9.5f %9.5f %3.1f %5.3f", tempExList[j].Ex, tempExList[j].xsec, tempExList[j].SF, tempExList[j].sigma)); + exIDReactIDList.AddLine(Form("%ld %d", j, i)); + } + } + + allExList.Write("AllExList"); + exIDReactIDList.Write("ExID_ReactID_List"); + + TMacro hitMeaning; + hitMeaning.AddLine("======================= meaning of Hit\n"); + for( int code = -15 ; code <= 1; code ++ ){ + hitMeaning.AddLine( Form( "%4d = %s", code, helios[0].AcceptanceCodeToMsg(code).Data() )); + } + hitMeaning.AddLine(" other = unknown\n"); + hitMeaning.AddLine("===========================================\n"); + hitMeaning.Write("hitMeaning"); + + int hit; /// the output of Helios.CalHit + tree->Branch("hit", &hit, "hit/I"); + + int rID; /// reaction ID + tree->Branch("rID", &rID, "reactionID/I"); + + double thetab, phib, Tb; + double thetaB, phiB, TB; + tree->Branch("thetab", &thetab, "thetab/D"); + tree->Branch("phib", &phib, "phib/D"); + tree->Branch("Tb", &Tb, "Tb/D"); + tree->Branch("thetaB", &thetaB, "thetaB/D"); + tree->Branch("phiB", &phiB, "phiB/D"); + tree->Branch("TB", &TB, "TB/D"); + + double thetaCM; + tree->Branch("thetaCM", &thetaCM, "thetaCM/D"); + + double e, z, detX, t, z0, tB; + tree->Branch("e", &e, "energy_light/D"); + tree->Branch("x", &detX, "detector_x/D"); + tree->Branch("z", &z, "array_hit_z/D"); + tree->Branch("z0", &z0, "z-cycle/D"); + tree->Branch("t", &t, "cycle_time_light/D"); + tree->Branch("tB", &tB, "recoil_hit_time/D"); /// hit time for recoil on the recoil detector + + int loop, detID, detRowID; + tree->Branch("detID", &detID, "detID/I"); + tree->Branch("detRowID", &detRowID, "detRowID/I"); + tree->Branch("loop", &loop, "loop/I"); + + double rho, rhoB; ///orbit radius + tree->Branch("rho", &rho, "orbit_radius_light/D"); + tree->Branch("rhoB", &rhoB, "orbit_radius_heavy/D"); + + int ExID; + double Ex; + tree->Branch("ExID", &ExID, "ExID/I"); + tree->Branch("Ex", &Ex, "Ex/D"); + + double ExCal, thetaCMCal; + tree->Branch("ExCal", &ExCal, "ExCal/D"); + tree->Branch("thetaCMCal", &thetaCMCal, "thetaCMCal/D"); + + // double TbLoss; /// energy loss of particle-b from target scattering + // double KEAnew; ///beam energy after target scattering + // double depth; /// reaction depth; + // double Ecm; + // if( reactConfig.isTargetScattering ){ + // tree->Branch("depth", &depth, "depth/D"); + // tree->Branch("TbLoss", &TbLoss, "TbLoss/D"); + // tree->Branch("KEAnew", &KEAnew, "KEAnew/D"); + // tree->Branch("Ecm", &Ecm, "Ecm/D"); + // } + + double decayTheta; /// the change of thetaB due to decay + double xRecoil_d, yRecoil_d, rhoRecoil_d, Td; + + bool isAnyDecay = false; + for( int i = 0; i < numTransfer; i++ ){ + if( !listOfTransfer[i] ) continue; + isAnyDecay |= transfer[i].GetRecoil().isDecay; + } + + if( isAnyDecay ) { + tree->Branch("decayTheta", &decayTheta, "decayTheta/D"); + tree->Branch("xRecoil_d", &xRecoil_d, "xRecoil_d/D"); + tree->Branch("yRecoil_d", &yRecoil_d, "yRecoil_d/D"); + tree->Branch("rhoRecoil_d", &rhoRecoil_d, "rhoRecoil_d/D"); + tree->Branch("Td", &Td, "Td/D"); + } + + double xArray, yArray, rhoArray; ///x, y, rho positon of particle-b on PSD + tree->Branch("xArray", &xArray, "xArray/D"); + tree->Branch("yArray", &yArray, "yArray/D"); + tree->Branch("rhoArray", &rhoArray, "rhoArray/D"); + + double xRecoil, yRecoil, rhoRecoil; /// x, y, rho position of particle-B on recoil-detector + tree->Branch("xRecoil", &xRecoil, "xRecoil/D"); + tree->Branch("yRecoil", &yRecoil, "yRecoil/D"); + tree->Branch("rhoRecoil", &rhoRecoil, "rhoRecoil/D"); + + + ///in case need ELUM + double xElum1, yElum1, rhoElum1; + bool isAnyElum1 = false; + for( int i = 0; i < numTransfer; i++ ){ + if( !listOfTransfer[i] ) continue; + isAnyElum1 |= (helios[i].GetAuxGeometry().elumPos1 != 0); + } + if( isAnyElum1 ) { + tree->Branch("xElum1", &xElum1, "xElum1/D"); + tree->Branch("yElum1", &yElum1, "yElum1/D"); + tree->Branch("rhoElum1", &rhoElum1, "rhoElum1/D"); + } + + double xElum2, yElum2, rhoElum2; + bool isAnyElum2 = false; + for( int i = 0; i < numTransfer; i++ ){ + if( !listOfTransfer[i] ) continue; + isAnyElum2 |= (helios[i].GetAuxGeometry().elumPos2 != 0); + } + if( isAnyElum2 ) { + tree->Branch("xElum2", &xElum2, "xElum2/D"); + tree->Branch("yElum2", &yElum2, "yElum2/D"); + tree->Branch("rhoElum2", &rhoElum2, "rhoElum2/D"); + } + + ///in case need other recoil detector. + double xRecoil1, yRecoil1, rhoRecoil1; + bool isAnyRecoil1 = false; + for( int i = 0; i < numTransfer; i++ ){ + if( !listOfTransfer[i] ) continue; + isAnyRecoil1 |= (helios[i].GetAuxGeometry().detPos1 != 0); + } + if( isAnyRecoil1 != 0 ){ + tree->Branch("xRecoil1", &xRecoil1, "xRecoil1/D"); + tree->Branch("yRecoil1", &yRecoil1, "yRecoil1/D"); + tree->Branch("rhoRecoil1", &rhoRecoil1, "rhoRecoil1/D"); + } + + double xRecoil2, yRecoil2, rhoRecoil2; + bool isAnyRecoil2 = false; + for( int i = 0; i < numTransfer; i++ ){ + if( !listOfTransfer[i] ) continue; + isAnyRecoil2 |= (helios[i].GetAuxGeometry().detPos2 != 0); + } + if( isAnyRecoil2 != 0 ){ + tree->Branch("xRecoil2", &xRecoil2, "xRecoil2/D"); + tree->Branch("yRecoil2", &yRecoil2, "yRecoil2/D"); + tree->Branch("rhoRecoil2", &rhoRecoil2, "rhoRecoil2/D"); + } + + //======= list of reaction used. + TMacro listOfReaction; + for( int i = 0; i < numTransfer ; i++){ + if( !listOfTransfer[i] ) continue; + listOfReaction.AddLine(Form("%2d | %s", i, transfer[i].GetReactionName_Latex().Data())); + } + + listOfReaction.Write("ListOfReactions"); + + //======= function for e-z plot for ideal case + printf("++++ generate functions\n"); + TObjArray * gList = new TObjArray(); + gList->SetName("Constant thetaCM = 0 lines"); + const int gxSize = numTransfer; + TF1 ** gx = new TF1*[gxSize]; + TString name; + + for( int i = 0; i < gxSize; i++){ + double mb = transfer[i].GetMass_b(); + double betaRect = transfer[i].GetReactionBeta(); + double gamma = transfer[i].GetReactionGamma(); + double slope = transfer[i].GetEZSlope(helios[0].GetBField()); /// MeV/mm + + name.Form("g%d", i); + gx[i] = new TF1(name, "([0]*TMath::Sqrt([1]+[2]*x*x)+[5]*x)/([3]) - [4]", -1000, 1000); + double thetacm = i * TMath::DegToRad(); + double gS2 = TMath::Power(TMath::Sin(thetacm)*gamma,2); + gx[i]->SetParameter(0, TMath::Cos(thetacm)); + gx[i]->SetParameter(1, mb*mb*(1-gS2)); + gx[i]->SetParameter(2, TMath::Power(slope/betaRect,2)); + gx[i]->SetParameter(3, 1-gS2); + gx[i]->SetParameter(4, mb); + gx[i]->SetParameter(5, -gS2*slope); + gx[i]->SetNpx(1000); + gList->Add(gx[i]); + printf("/"); + if( i > 1 && i % 40 == 0 ) printf("\n"); + } + gList->Write("EZ_thetaCM", TObject::kSingleKey); + printf(" %d constant thetaCM functions\n", gxSize); + + for( int i = 0; i < gxSize; i++){ + delete gx[i]; + } + delete [] gx; + delete gList; + + //--- cal E-Z curve with finite detector correction + int numEx = 0; + for( int i = 0; i < numTransfer; i++){ + if( !listOfTransfer[i] ) continue; + numEx += transfer[i].GetExList()->ExList.size(); + } + + TObjArray * fxList = new TObjArray(); + TGraph ** fx = new TGraph*[numEx]; + std::vector px, py; + int countfx = 0; + + count = 0; + for( int i = 0; i < numTransfer; i++ ){ + if( !listOfTransfer[i] ) continue; + double mb = transfer[i].GetMass_b(); + double betaRect = transfer[i].GetReactionBeta(); + double gamma = transfer[i].GetReactionGamma(); + double slope = transfer[i].GetEZSlope(helios[0].GetBField()); /// MeV/mm + + for( size_t j = 0 ; j < transfer[i].GetExList()->ExList.size(); j++){ + double Ex = transfer[i].GetExList()->ExList[j].Ex; + double kbCM = transfer[i].CalkCM(Ex); + double a = helios[i].GetDetRadius(); + double q = TMath::Sqrt(mb*mb + kbCM * kbCM ); + px.clear(); + py.clear(); + countfx = 0; + for(int i = 0; i < 100; i++){ + double thetacm = TMath::Pi()/TMath::Log(100) * (TMath::Log(100) - TMath::Log(100-i)) ;//using log scale, for more point in small angle. + double temp = TMath::TwoPi() * slope / betaRect / kbCM * a / TMath::Sin(thetacm); + double pxTemp = betaRect /slope * (gamma * betaRect * q - gamma * kbCM * TMath::Cos(thetacm)) * (1 - TMath::ASin(temp)/TMath::TwoPi()) ; + double pyTemp = gamma * q - mb - gamma * betaRect * kbCM * TMath::Cos(thetacm); + if( TMath::IsNaN(pxTemp) || TMath::IsNaN(pyTemp) ) continue; + px.push_back(pxTemp); + py.push_back(pyTemp); + countfx ++; + } + + fx[count] = new TGraph(countfx, &px[0], &py[0]); + name.Form("fx%d_%ld", i, j); + fx[count]->SetName(name); + fx[count]->SetLineColor(4); + fxList->Add(fx[count]); + printf(","); + count ++; + } + } + fxList->Write("EZCurve", TObject::kSingleKey); + printf(" %d (%d) e-z finite-size detector functions\n", numEx, count); + + for( int i = 0 ; i < numEx; i++) delete fx[i]; + delete [] fx; + delete fxList; + + // //--- cal modified thetaCM vs z + // TObjArray * txList = new TObjArray(); + // TGraph ** tx = new TGraph*[numEx]; + // for( int j = 0 ; j < numEx; j++){ + // double a = helios.GetDetRadius(); + // double q = TMath::Sqrt(mb*mb + kbCM[j] * kbCM[j] ); + // px.clear(); + // py.clear(); + // countfx = 0; + // for(int i = 0; i < 100; i++){ + // double thetacm = (i + 8.) * TMath::DegToRad(); + // double temp = TMath::TwoPi() * slope / betaRect / kbCM[j] * a / TMath::Sin(thetacm); + // double pxTemp = betaRect /slope * (gamma * betaRect * q - gamma * kbCM[j] * TMath::Cos(thetacm)) * (1 - TMath::ASin(temp)/TMath::TwoPi()); + // double pyTemp = thetacm * TMath::RadToDeg(); + // if( TMath::IsNaN(pxTemp) || TMath::IsNaN(pyTemp) ) continue; + // px.push_back(pxTemp); + // py.push_back(pyTemp); + // countfx ++; + // } + + // tx[j] = new TGraph(countfx, &px[0], &py[0]); + // name.Form("tx%d", j); + // tx[j]->SetName(name); + // tx[j]->SetLineColor(4); + // txList->Add(tx[j]); + // printf("*"); + // } + // txList->Write("thetaCM_Z", TObject::kSingleKey); + // printf(" %d thetaCM-z for finite-size detector functions\n", numEx); + + //========timer + TBenchmark clock; + bool shown ; + clock.Reset(); + clock.Start("timer"); + shown = false; + + //change the number of event into human easy-to-read form + int numEvent = reactionConfig.numEvents; + int digitLen = TMath::Floor(TMath::Log10(numEvent)); + TString numEventStr; + if( 3 <= digitLen && digitLen < 6 ){ + numEventStr.Form("%5.1f kilo", numEvent/1000.); + }else if ( 6<= digitLen && digitLen < 9 ){ + numEventStr.Form("%6.2f million", numEvent/1e6); + }else if ( 9<= digitLen ){ + numEventStr.Form("%6.2f billion", numEvent/1e9); + } + printf("\e[32m#################################### generating %s events \e[0m\n", numEventStr.Data()); + + double KEA = reactionConfig.beamEnergy; + double theta = reactionConfig.beamTheta; + double phi = 0.0; + + TF1 * angDist = nullptr; + + //*====================================================== calculate event + count = 0; + for( int i = 0; i < numEvent; i++){ + bool redoFlag = true; + if( !reactionConfig.isRedo ) redoFlag = false; + do{ + + rID = gRandom->Integer( numTransfer ); + if( !listOfTransfer[rID] ) continue; + + //==== Set Ex of B + ExID = transfer[rID].GetRandomExID(); + double sigma = transfer[rID].GetExList()->ExList[ExID].sigma; + Ex = transfer[rID].GetExList()->ExList[ExID].Ex + gRandom->Gaus(0, sigma); + + transfer[rID].SetExB(Ex); + + //==== Set incident beam + if( reactionConfig.beamEnergySigma != 0 ){ + KEA = gRandom->Gaus(reactionConfig.beamEnergy, reactionConfig.beamEnergySigma); + } + if( reactionConfig.beamThetaSigma != 0 ){ + theta = gRandom->Gaus(reactionConfig.beamTheta, reactionConfig.beamThetaSigma); + } + + //==== for taregt scattering + transfer[rID].SetIncidentEnergyAngle(KEA, theta, 0.); + transfer[rID].CalReactionConstant(); + + // TLorentzVector PA = transfer.GetPA(); + //depth = 0; + // if( isTargetScattering ){ + // //==== Target scattering, only energy loss + // depth = targetThickness * gRandom->Rndm(); + // msA.SetTarget(density, depth); + // TLorentzVector PAnew = msA.Scattering(PA); + // KEAnew = msA.GetKE()/reactConfig.beamA; + // transfer.SetIncidentEnergyAngle(KEAnew, theta, phi); + // transfer.CalReactionConstant(); + // Ecm = transfer.GetCMTotalKE(); + // } + + //==== Calculate thetaCM, phiCM + if( distFile->IsOpen() && useDWBA[rID] ){ + angDist = (TF1 *) distList->At(ExID); + thetaCM = angDist->GetRandom() / 180. * TMath::Pi(); + }else{ + thetaCM = TMath::ACos(2 * gRandom->Rndm() - 1) ; + } + + double phiCM = TMath::TwoPi() * gRandom->Rndm(); + + //==== Calculate reaction + transfer[rID].Event(thetaCM, phiCM); + TLorentzVector Pb = transfer[rID].GetPb(); + TLorentzVector PB = transfer[rID].GetPB(); + + // //==== Calculate energy loss of scattered and recoil in target + // if( isTargetScattering ){ + // if( Pb.Theta() < TMath::PiOver2() ){ + // msb.SetTarget(density, targetThickness - depth); + // }else{ + // msb.SetTarget(density, depth); + // } + // Pb = msb.Scattering(Pb); + // TbLoss = msb.GetKELoss(); + // msB.SetTarget(density, targetThickness - depth); + // PB = msB.Scattering(PB); + // }else{ + // TbLoss = 0; + // } + + //======= Decay of particle-B + int decayID = 0; + if( transfer[rID].GetRecoil().isDecay){ + + decayID = decay[rID].CalDecay(PB, Ex, 0, phiCM + TMath::Pi()/2); // decay to ground state + if( decayID == 1 ){ + PB = decay[rID].GetDaugther_D(); + //decayTheta = decay.GetAngleChange(); + decayTheta = decay[rID].GetThetaCM(); + PB.SetUniqueID(transfer[rID].GetRecoil().decayZ); + }else{ + decayTheta = TMath::QuietNaN(); + } + } + + //################################### tree branches + //===== reaction + thetab = Pb.Theta() * TMath::RadToDeg(); + thetaB = PB.Theta() * TMath::RadToDeg(); + + Tb = Pb.E() - Pb.M(); + TB = PB.E() - PB.M(); + + phib = Pb.Phi() * TMath::RadToDeg(); + phiB = PB.Phi() * TMath::RadToDeg(); + + //==== Helios + + // printf(" thetaCM : %f, Tb : %f\n", thetaCM * TMath::RadToDeg(), Pb.M()); + + if( Tb > 0 || TB > 0 ){ + + helios[rID].CalArrayHit(Pb); + helios[rID].CalRecoilHit(PB); + hit = 2; + while( hit > 1 ){ hit = helios[rID].CheckDetAcceptance(); } /// while hit > 1, goto next loop; + + trajectory orb_b = helios[rID].GetTrajectory_b(); + trajectory orb_B = helios[rID].GetTrajectory_B(); + + e = helios[rID].GetEnergy() + gRandom->Gaus(0, helios[rID].GetArrayGeometry().eSigma ); + + double ranX = gRandom->Gaus(0, helios[rID].GetArrayGeometry().zSigma); + z = orb_b.z + ranX; + detX = helios[rID].GetDetX() + ranX; + + z0 = orb_b.z0; + t = orb_b.t; + loop = orb_b.loop; + detID = orb_b.detID; + detRowID = orb_b.detRowID; + rho = orb_b.rho; + rhoArray = orb_b.R; + + xArray = orb_b.x; + yArray = orb_b.y; + + //ELUM + double elumPos1 = helios[rID].GetAuxGeometry().elumPos1; + if( elumPos1 != 0 ){ + xElum1 = helios[rID].GetXPos(elumPos1); + yElum1 = helios[rID].GetYPos(elumPos1); + rhoElum1 = helios[rID].GetR (elumPos1); + } + double elumPos2 = helios[rID].GetAuxGeometry().elumPos2; + if( elumPos2 ){ + xElum2 = helios[rID].GetXPos(elumPos2); + yElum2 = helios[rID].GetYPos(elumPos2); + rhoElum2 = helios[rID].GetR (elumPos2); + } + + //Recoil + rhoRecoil = orb_B.R; + tB = orb_B.t; + xRecoil = orb_B.x; + yRecoil = orb_B.y; + rhoB = orb_B.rho; + + //other recoil detectors + double recoilPos1 = helios[rID].GetAuxGeometry().detPos1; + if ( recoilPos1 != 0 ){ + xRecoil1 = helios[rID].GetRecoilXPos(recoilPos1); + yRecoil1 = helios[rID].GetRecoilYPos(recoilPos1); + rhoRecoil1 = helios[rID].GetRecoilR (recoilPos1); + } + double recoilPos2 = helios[rID].GetAuxGeometry().detPos2; + if ( recoilPos2 != 0 ){ + xRecoil2 = helios[rID].GetRecoilXPos(recoilPos2); + yRecoil2 = helios[rID].GetRecoilYPos(recoilPos2); + rhoRecoil2 = helios[rID].GetRecoilR (recoilPos2); + } + + std::pair ExThetaCM = transfer[rID].CalExThetaCM(e, z, helios[rID].GetBField(), helios[rID].GetDetRadius()); + ExCal = ExThetaCM.first; + thetaCMCal = ExThetaCM.second; + + //change thetaCM into deg + thetaCM = thetaCM * TMath::RadToDeg(); + + //if decay, get the light decay particle on the recoil; + if( transfer[rID].GetRecoil().isDecay ){ + if( decayID == 1 ){ + TLorentzVector Pd = decay[rID].GetDaugther_d(); + + Td = Pd.E() - Pd.M(); + + helios[rID].CalRecoilHit(Pd); + + trajectory orb_d = helios[rID].GetTrajectory_B(); + rhoRecoil_d = orb_d.R; + xRecoil_d = orb_d.x; + yRecoil_d = orb_d.y; + + }else{ + rhoRecoil_d = TMath::QuietNaN(); + xRecoil_d = TMath::QuietNaN(); + yRecoil_d = TMath::QuietNaN(); + } + } + + }else{ + hit = -404; + } + + if( hit == 1) count ++; + + if( reactionConfig.isRedo ){ + if( hit == 1) { + redoFlag = false; + }else{ + redoFlag = true; + //printf("%d, %2d, thetaCM : %f, theta : %f, z0: %f \n", i, hit, thetaCM * TMath::RadToDeg(), thetab, helios.GetZ0()); + } + }else{ + redoFlag = false; + } + + }while( redoFlag ); + tree->Fill(); + + //#################################################################### Timer + clock.Stop("timer"); + Double_t time = clock.GetRealTime("timer"); + clock.Start("timer"); + + if ( !shown ) { + if (fmod(time, 10) < 1 ){ + printf( "%10d[%2d%%]| %8.2f sec | expect: %5.1f min \n", i, TMath::Nint((i+1)*100./numEvent), time , numEvent*time/(i+1)/60); + shown = 1; + } + }else{ + if (fmod(time, 10) > 9 ){ + shown = 0; + } + } + + } + + saveFile->Write(); + saveFile->Close(); + + distFile->Close(); + delete angDist; + + printf("=============== done. saved as %s. count(hit==1) : %d\n", saveFileName.Data(), count); + //gROOT->ProcessLine(".q"); + + delete [] transfer; + delete [] decay; + delete [] helios; + delete [] useDWBA; + + distFile->Close(); + delete distFile; + delete distList; + delete dwbaExList; + delete dwbaReactList; + + return; + +} + + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("========== Simulate Transfer reaction in HELIOS ==========\n"); + printf("=================================================================\n"); + + if(argc == 2 || argc > 6 ) { + printf("Usage: ./Transfer [1] [2] [3] [4] [5]\n"); + printf(" default file name \n"); + printf(" [1] reactionConfig.txt (input) reaction Setting \n"); + printf(" [2] detectorGeo.txt (input) detector Setting \n"); + printf(" [3] DWBA.root (input) thetaCM distribution from DWBA \n"); + printf(" [4] transfer.root (output) rootFile name for output \n"); + printf(" [5] 1 (input) 0 = no plot, 1 = plot \n"); + + printf("-----------------------------------------------------------------\n"); + printf(" When DWBA.root provided.\n"); + printf(" The excitation energies from the DWBA are used.\n"); + printf(" And the excitation energies in reactionConfig.txt will be ignored\n"); + printf("=================================================================\n"); + return 0 ; + } + + std::string basicConfig = "reactionConfig.txt"; + std::string detGeoFile = "detectorGeo.txt"; + TString ptolemyRoot = "DWBA.root"; // when no file, use isotropic distribution of thetaCM + TString saveFileName = "transfer.root"; + bool isPlot = true; + + if( argc >= 2) basicConfig = argv[1]; + if( argc >= 3) detGeoFile = argv[2]; + if( argc >= 4) ptolemyRoot = argv[3]; + if( argc >= 5) saveFileName = argv[4]; + if( argc >= 6) isPlot = atoi(argv[5]); + + Transfer( basicConfig, detGeoFile, ptolemyRoot, saveFileName); + + //run Cleopatra/SimChecker.C + if( isPlot ){ + std::ifstream file_in; + file_in.open("../Cleopatra/SimChecker.C", std::ios::in); + if( file_in){ + printf("---- running ../Cleopatra/SimChecker.C on %s \n", saveFileName.Data()); + TString cmd; + cmd.Form("root -l '../Cleopatra/SimChecker.C(\"%s\")'", saveFileName.Data()); + + system(cmd.Data()); + }else{ + printf("cannot find ../Cleopatra/SimChecker.C \n"); + } + } + + return 0; + +} + diff --git a/cleopatra/SimTransfer_single.C b/cleopatra/SimTransfer_single.C new file mode 100644 index 0000000..65d08a4 --- /dev/null +++ b/cleopatra/SimTransfer_single.C @@ -0,0 +1,722 @@ +#include "TROOT.h" +#include "TBenchmark.h" +#include "TLorentzVector.h" +#include "TMath.h" +#include "TFile.h" +#include "TF1.h" +#include "TTree.h" +#include "TRandom.h" +#include "TGraph.h" +#include "TMacro.h" +#include +#include +#include +#include + +#include "../Armory/ClassDetGeo.h" +#include "ClassTargetScattering.h" +#include "ClassDecay.h" +#include "ClassTransfer.h" +#include "ClassHelios.h" + +double exDistFunc(Double_t *x, Double_t * par){ + return par[(int) x[0]]; +} + +void PrintEZPlotPara(TransferReaction tran, HELIOS helios){ + + printf("==================================== E-Z plot slope\n"); + double betaRect = tran.GetReactionBeta() ; + double gamma = tran.GetReactionGamma(); + double mb = tran.GetMass_b(); + double pCM = tran.GetMomentumbCM(); + double q = TMath::Sqrt(mb*mb + pCM*pCM); ///energy of light recoil in center of mass + double slope = tran.GetEZSlope(helios.GetBField()); /// MeV/mm + printf(" e-z slope : %f MeV/mm\n", slope); + double intercept = q/gamma - mb; // MeV + printf(" e-z intercept (ground state) : %f MeV\n", intercept); + +} + +void Transfer( + std::string basicConfig = "reactionConfig.txt", + std::string heliosDetGeoFile = "detectorGeo.txt", + unsigned short ID = 0, // this is the ID for the array + TString ptolemyRoot = "DWBA.root", + TString saveFileName = "transfer.root"){ + + //*############################################# Set Reaction + TransferReaction transfer; + HELIOS helios; + Decay decay; + + std::vector kbCM; /// momentum of b in CM frame + TF1 * exDist = nullptr; + + transfer.SetReactionFromFile(basicConfig, ID); + helios.SetDetectorGeometry(heliosDetGeoFile, ID); + + printf("*****************************************************************\n"); + printf("*\e[1m\e[33m %27s \e[0m*\n", transfer.GetReactionName().Data()); + printf("*****************************************************************\n"); + printf("----- loading reaction setting from %s. \n", basicConfig.c_str()); + printf("----- loading geometry setting from %s. \n", heliosDetGeoFile.c_str()); + + printf("\e[32m#################################### Reaction & HELIOS configuration\e[0m\n"); + + transfer.PrintReaction(false); + + if(transfer.GetRecoil().isDecay) { + decay.SetMotherDaugther(transfer.GetRecoil()); + } + + helios.PrintGeometry(); + PrintEZPlotPara(transfer, helios); + + + DetGeo detGeo = helios.GetDetectorGeometry(); + Array array = helios.GetArrayGeometry(); + Auxillary aux = helios.GetAuxGeometry(); + ReactionConfig reactConfig = transfer.GetRectionConfig(); + Recoil recoil = transfer.GetRecoil(); + + //*############################################# save reaction.dat + // if( filename != "" ) { + // FILE * keyParaOut; + // keyParaOut = fopen (filename.Data(), "w+"); + + // printf("=========== save key reaction constants to %s \n", filename.Data()); + // fprintf(keyParaOut, "%-15.4f //%s\n", transfer.GetMass_b(), "mass_b"); + // fprintf(keyParaOut, "%-15d //%s\n", reactConfig.recoilLightZ, "charge_b"); + // fprintf(keyParaOut, "%-15.8f //%s\n", transfer.GetReactionBeta(), "betaCM"); + // fprintf(keyParaOut, "%-15.4f //%s\n", transfer.GetCMTotalEnergy(), "Ecm"); + // fprintf(keyParaOut, "%-15.4f //%s\n", transfer.GetMass_B(), "mass_B"); + // fprintf(keyParaOut, "%-15.4f //%s\n", slope/betaRect, "alpha=slope/betaRect"); + + // fflush(keyParaOut); + // fclose(keyParaOut); + // } + + //*############################################# Target scattering, only energy loss + // bool isTargetScattering = reactConfig.isTargetScattering; + // float density = reactConfig.targetDensity; + // float targetThickness = reactConfig.targetThickness; + + // if(isTargetScattering) printf("\e[32m#################################### Target Scattering\e[0m\n"); + // TargetScattering msA; + // TargetScattering msB; + // TargetScattering msb; + + // if(reactConfig.isTargetScattering) printf("======== Target : (thickness : %6.2f um) x (density : %6.2f g/cm3) = %6.2f ug/cm2\n", + // targetThickness * 1e+4, + // density, + // targetThickness * density * 1e+6); + + // if( reactConfig.isTargetScattering ){ + // msA.LoadStoppingPower(reactConfig.beamStoppingPowerFile); + // msb.LoadStoppingPower(reactConfig.recoilLightStoppingPowerFile); + // msB.LoadStoppingPower(reactConfig.recoilHeavyStoppingPowerFile); + // } + + ExcitedEnergies exList = transfer.GetRectionConfig().exList[ID]; + + //*############################################# Load DWBAroot for thetaCM distribution + printf("\e[32m#################################### Load DWBA input : %s \e[0m\n", ptolemyRoot.Data()); + TF1 * dist = NULL; + TFile * distFile = new TFile(ptolemyRoot, "read"); + TObjArray * distList = nullptr; + TMacro * dwbaExList = nullptr; + TMacro * dwbaReactList = nullptr; + + TMacro dwbaExList_Used; + + if( distFile->IsOpen() ) { + printf("--------- Found DWBA thetaCM distributions. Use the ExList from DWBA.\n"); + + distList = (TObjArray *) distFile->FindObjectAny("thetaCM_TF1"); // the function List + dwbaExList = (TMacro *) distFile->FindObjectAny("ExList"); + dwbaExList_Used.AddLine(dwbaExList->GetListOfLines()->At(0)->GetName()); + dwbaReactList = (TMacro *) distFile->FindObjectAny("ReactionList"); + exList.Clear(); + + int numEx = dwbaExList->GetListOfLines()->GetSize() - 1 ; + for(int i = 1; i <= numEx ; i++){ + std::string reactionName = dwbaReactList->GetListOfLines()->At(i-1)->GetName(); + if( reactionName.find( transfer.GetReactionName().Data() ) != std::string::npos) { + std::string temp = dwbaExList->GetListOfLines()->At(i)->GetName(); + dwbaExList_Used.AddLine(temp.c_str()); + if( temp[0] == '/' ) continue; + std::vector tempStr = AnalysisLib::SplitStr(temp, " "); + exList.Add( atof(tempStr[0].c_str()), atof(tempStr[1].c_str()), 1.0, 0.00); + } + } + + }else{ + printf("------- no DWBA input. Use the ExList from %s\n", basicConfig.c_str()); + } + + + printf("------------------------------ Heavy Recoil excitation\n"); + printf("Energy[MeV] Rel.Xsec SF sigma\n"); + + int numEx = exList.ExList.size(); + + for( int j = 0; j < numEx; j++){ + double ex = exList.ExList[j].Ex; + kbCM.push_back(transfer.CalkCM(ex)); + int decayID = decay.CalDecay(TLorentzVector (0,0,0,0), ex, 0); + exList.ExList[j].Print(decayID == 1 ? "-->Decay" : "\n"); + } + + //---- create Ex-distribution + if( exList.ExList.size() > 1 ) { + printf("---- creating Ex-distribution \n"); + exDist = new TF1("exDist", exDistFunc, 0, numEx, numEx); + for(int q = 0; q < numEx; q++){ + exDist->SetParameter(q, exList.ExList[q].xsec*exList.ExList[q].SF); + } + } + + //*############################################# build tree + printf("\e[32m#################################### building Tree in %s\e[0m\n", saveFileName.Data()); + TFile * saveFile = new TFile(saveFileName, "recreate"); + TTree * tree = new TTree("tree", "tree"); + + TMacro config(basicConfig.c_str()); + TMacro detGeoTxt(heliosDetGeoFile.c_str()); + config.SetName(transfer.GetReactionName_Latex().Data()); + config.Write("reactionConfig"); + detGeoTxt.Write("detGeo"); + + if( distList != NULL ) distList->Write("DWBA", 1); + if( dwbaExList != NULL ) dwbaExList_Used.Write("DWBA_ExList", 1); + + + TMacro idMacro; + idMacro.AddLine(Form("%d", ID)); + idMacro.Write("detGeoID"); + + TMacro hitMeaning; + hitMeaning.AddLine("======================= meaning of Hit\n"); + for( int code = -15 ; code <= 1; code ++ ){ + hitMeaning.AddLine( Form( "%4d = %s", code, helios.AcceptanceCodeToMsg(code).Data() )); + } + hitMeaning.AddLine(" other = unknown\n"); + hitMeaning.AddLine("===========================================\n"); + hitMeaning.Write("hitMeaning"); + + int hit; /// the output of Helios.CalHit + tree->Branch("hit", &hit, "hit/I"); + + double thetab, phib, Tb; + double thetaB, phiB, TB; + tree->Branch("thetab", &thetab, "thetab/D"); + tree->Branch("phib", &phib, "phib/D"); + tree->Branch("Tb", &Tb, "Tb/D"); + tree->Branch("thetaB", &thetaB, "thetaB/D"); + tree->Branch("phiB", &phiB, "phiB/D"); + tree->Branch("TB", &TB, "TB/D"); + + double thetaCM; + tree->Branch("thetaCM", &thetaCM, "thetaCM/D"); + + double e, z, detX, t, z0, tB; + tree->Branch("e", &e, "energy_light/D"); + tree->Branch("x", &detX, "detector_x/D"); + tree->Branch("z", &z, "array_hit_z/D"); + tree->Branch("z0", &z0, "z-cycle/D"); + tree->Branch("t", &t, "cycle_time_light/D"); + tree->Branch("tB", &tB, "recoil_hit_time/D"); /// hit time for recoil on the recoil detector + + int loop, detID, detRowID; + tree->Branch("detID", &detID, "detID/I"); + tree->Branch("detRowID", &detRowID, "detRowID/I"); + tree->Branch("loop", &loop, "loop/I"); + + double rho, rhoB; ///orbit radius + tree->Branch("rho", &rho, "orbit_radius_light/D"); + tree->Branch("rhoB", &rhoB, "orbit_radius_heavy/D"); + + int ExID; + double Ex; + tree->Branch("ExID", &ExID, "ExID/I"); + tree->Branch("Ex", &Ex, "Ex/D"); + + double ExCal, thetaCMCal; + tree->Branch("ExCal", &ExCal, "ExCal/D"); + tree->Branch("thetaCMCal", &thetaCMCal, "thetaCMCal/D"); + + // double TbLoss; /// energy loss of particle-b from target scattering + // double KEAnew; ///beam energy after target scattering + // double depth; /// reaction depth; + // double Ecm; + // if( reactConfig.isTargetScattering ){ + // tree->Branch("depth", &depth, "depth/D"); + // tree->Branch("TbLoss", &TbLoss, "TbLoss/D"); + // tree->Branch("KEAnew", &KEAnew, "KEAnew/D"); + // tree->Branch("Ecm", &Ecm, "Ecm/D"); + // } + + double decayTheta; /// the change of thetaB due to decay + double xRecoil_d, yRecoil_d, rhoRecoil_d, Td; + if( recoil.isDecay ) { + tree->Branch("decayTheta", &decayTheta, "decayTheta/D"); + tree->Branch("xRecoil_d", &xRecoil_d, "xRecoil_d/D"); + tree->Branch("yRecoil_d", &yRecoil_d, "yRecoil_d/D"); + tree->Branch("rhoRecoil_d", &rhoRecoil_d, "rhoRecoil_d/D"); + tree->Branch("Td", &Td, "Td/D"); + } + + double xArray, yArray, rhoArray; ///x, y, rho positon of particle-b on PSD + tree->Branch("xArray", &xArray, "xArray/D"); + tree->Branch("yArray", &yArray, "yArray/D"); + tree->Branch("rhoArray", &rhoArray, "rhoArray/D"); + + double xRecoil, yRecoil, rhoRecoil; /// x, y, rho position of particle-B on recoil-detector + tree->Branch("xRecoil", &xRecoil, "xRecoil/D"); + tree->Branch("yRecoil", &yRecoil, "yRecoil/D"); + tree->Branch("rhoRecoil", &rhoRecoil, "rhoRecoil/D"); + + + ///in case need ELUM + double xElum1, yElum1, rhoElum1; + if( aux.elumPos1 != 0 ) { + tree->Branch("xElum1", &xElum1, "xElum1/D"); + tree->Branch("yElum1", &yElum1, "yElum1/D"); + tree->Branch("rhoElum1", &rhoElum1, "rhoElum1/D"); + } + + double xElum2, yElum2, rhoElum2; + if( aux.elumPos2 != 0 ) { + tree->Branch("xElum2", &xElum2, "xElum2/D"); + tree->Branch("yElum2", &yElum2, "yElum2/D"); + tree->Branch("rhoElum2", &rhoElum2, "rhoElum2/D"); + } + + ///in case need other recoil detector. + double xRecoil1, yRecoil1, rhoRecoil1; + if( aux.detPos1 != 0 ){ + tree->Branch("xRecoil1", &xRecoil1, "xRecoil1/D"); + tree->Branch("yRecoil1", &yRecoil1, "yRecoil1/D"); + tree->Branch("rhoRecoil1", &rhoRecoil1, "rhoRecoil1/D"); + } + double xRecoil2, yRecoil2, rhoRecoil2; + if( aux.detPos2 != 0 ){ + tree->Branch("xRecoil2", &xRecoil2, "xRecoil2/D"); + tree->Branch("yRecoil2", &yRecoil2, "yRecoil2/D"); + tree->Branch("rhoRecoil2", &rhoRecoil2, "rhoRecoil2/D"); + } + //======= function for e-z plot for ideal case + printf("++++ generate functions\n"); + TObjArray * gList = new TObjArray(); + gList->SetName("Constant thetaCM lines"); + const int gxSize = 50; + TF1 ** gx = new TF1*[gxSize]; + TString name; + + double mb = transfer.GetMass_b(); + double betaRect = transfer.GetReactionBeta(); + double gamma = transfer.GetReactionGamma(); + double slope = transfer.GetEZSlope(helios.GetBField()); /// MeV/mm + + for( int i = 0; i < gxSize; i++){ + name.Form("g%d", i); + gx[i] = new TF1(name, "([0]*TMath::Sqrt([1]+[2]*x*x)+[5]*x)/([3]) - [4]", -1000, 1000); + double thetacm = i * TMath::DegToRad(); + double gS2 = TMath::Power(TMath::Sin(thetacm)*gamma,2); + gx[i]->SetParameter(0, TMath::Cos(thetacm)); + gx[i]->SetParameter(1, mb*mb*(1-gS2)); + gx[i]->SetParameter(2, TMath::Power(slope/betaRect,2)); + gx[i]->SetParameter(3, 1-gS2); + gx[i]->SetParameter(4, mb); + gx[i]->SetParameter(5, -gS2*slope); + gx[i]->SetNpx(1000); + gList->Add(gx[i]); + printf("/"); + if( i > 1 && i % 40 == 0 ) printf("\n"); + } + gList->Write("EZ_thetaCM", TObject::kSingleKey); + printf(" %d constant thetaCM functions\n", gxSize); + + //--- cal modified f + TObjArray * fxList = new TObjArray(); + TGraph ** fx = new TGraph*[numEx]; + std::vector px, py; + int countfx = 0; + for( int j = 0 ; j < numEx; j++){ + double a = helios.GetDetRadius(); + double q = TMath::Sqrt(mb*mb + kbCM[j] * kbCM[j] ); + px.clear(); + py.clear(); + countfx = 0; + for(int i = 0; i < 100; i++){ + double thetacm = TMath::Pi()/TMath::Log(100) * (TMath::Log(100) - TMath::Log(100-i)) ;//using log scale, for more point in small angle. + double temp = TMath::TwoPi() * slope / betaRect / kbCM[j] * a / TMath::Sin(thetacm); + double pxTemp = betaRect /slope * (gamma * betaRect * q - gamma * kbCM[j] * TMath::Cos(thetacm)) * (1 - TMath::ASin(temp)/TMath::TwoPi()) ; + double pyTemp = gamma * q - mb - gamma * betaRect * kbCM[j] * TMath::Cos(thetacm); + if( TMath::IsNaN(pxTemp) || TMath::IsNaN(pyTemp) ) continue; + px.push_back(pxTemp); + py.push_back(pyTemp); + countfx ++; + } + + fx[j] = new TGraph(countfx, &px[0], &py[0]); + name.Form("fx%d", j); + fx[j]->SetName(name); + fx[j]->SetLineColor(4); + fxList->Add(fx[j]); + printf(","); + } + fxList->Write("EZCurve", TObject::kSingleKey); + printf(" %d e-z finite-size detector functions\n", numEx); + + //--- cal modified thetaCM vs z + TObjArray * txList = new TObjArray(); + TGraph ** tx = new TGraph*[numEx]; + for( int j = 0 ; j < numEx; j++){ + double a = helios.GetDetRadius(); + double q = TMath::Sqrt(mb*mb + kbCM[j] * kbCM[j] ); + px.clear(); + py.clear(); + countfx = 0; + for(int i = 0; i < 100; i++){ + double thetacm = (i + 8.) * TMath::DegToRad(); + double temp = TMath::TwoPi() * slope / betaRect / kbCM[j] * a / TMath::Sin(thetacm); + double pxTemp = betaRect /slope * (gamma * betaRect * q - gamma * kbCM[j] * TMath::Cos(thetacm)) * (1 - TMath::ASin(temp)/TMath::TwoPi()); + double pyTemp = thetacm * TMath::RadToDeg(); + if( TMath::IsNaN(pxTemp) || TMath::IsNaN(pyTemp) ) continue; + px.push_back(pxTemp); + py.push_back(pyTemp); + countfx ++; + } + + tx[j] = new TGraph(countfx, &px[0], &py[0]); + name.Form("tx%d", j); + tx[j]->SetName(name); + tx[j]->SetLineColor(4); + txList->Add(tx[j]); + printf("*"); + } + txList->Write("thetaCM_Z", TObject::kSingleKey); + printf(" %d thetaCM-z for finite-size detector functions\n", numEx); + + //========timer + TBenchmark clock; + bool shown ; + clock.Reset(); + clock.Start("timer"); + shown = false; + + //change the number of event into human easy-to-read form + int numEvent = reactConfig.numEvents; + int digitLen = TMath::Floor(TMath::Log10(numEvent)); + TString numEventStr; + if( 3 <= digitLen && digitLen < 6 ){ + numEventStr.Form("%5.1f kilo", numEvent/1000.); + }else if ( 6<= digitLen && digitLen < 9 ){ + numEventStr.Form("%6.2f million", numEvent/1e6); + }else if ( 9<= digitLen ){ + numEventStr.Form("%6.2f billion", numEvent/1e9); + } + printf("\e[32m#################################### generating %s events \e[0m\n", numEventStr.Data()); + + double KEA = reactConfig.beamEnergy; + double theta = reactConfig.beamTheta; + double phi = 0.0; + + //*====================================================== calculate event + int count = 0; + for( int i = 0; i < numEvent; i++){ + bool redoFlag = true; + if( !reactConfig.isRedo ) redoFlag = false; + do{ + + //==== Set Ex of B + if( numEx == 1 ) { + ExID = 0; + Ex = exList.ExList[0].Ex + (exList.ExList[0].sigma == 0 ? 0 : gRandom->Gaus(0, exList.ExList[0].sigma)); + }else{ + ExID = exDist->GetRandom(); + Ex = exList.ExList[ExID].Ex + (exList.ExList[ExID].sigma == 0 ? 0 : gRandom->Gaus(0, exList.ExList[ExID].sigma)); + } + transfer.SetExB(Ex); + + //==== Set incident beam + if( reactConfig.beamEnergySigma != 0 ){ + KEA = gRandom->Gaus(reactConfig.beamEnergy, reactConfig.beamEnergySigma); + } + if( reactConfig.beamThetaSigma != 0 ){ + theta = gRandom->Gaus(reactConfig.beamTheta, reactConfig.beamThetaSigma); + } + + //==== for taregt scattering + transfer.SetIncidentEnergyAngle(KEA, theta, 0.); + transfer.CalReactionConstant(); + + // TLorentzVector PA = transfer.GetPA(); + //depth = 0; + // if( isTargetScattering ){ + // //==== Target scattering, only energy loss + // depth = targetThickness * gRandom->Rndm(); + // msA.SetTarget(density, depth); + // TLorentzVector PAnew = msA.Scattering(PA); + // KEAnew = msA.GetKE()/reactConfig.beamA; + // transfer.SetIncidentEnergyAngle(KEAnew, theta, phi); + // transfer.CalReactionConstant(); + // Ecm = transfer.GetCMTotalKE(); + // } + + //==== Calculate thetaCM, phiCM + if( distFile->IsOpen()){ + dist = (TF1 *) distList->At(ExID); + thetaCM = dist->GetRandom() / 180. * TMath::Pi(); + }else{ + thetaCM = TMath::ACos(2 * gRandom->Rndm() - 1) ; + } + + double phiCM = TMath::TwoPi() * gRandom->Rndm(); + + //==== Calculate reaction + transfer.Event(thetaCM, phiCM); + TLorentzVector Pb = transfer.GetPb(); + TLorentzVector PB = transfer.GetPB(); + + // //==== Calculate energy loss of scattered and recoil in target + // if( isTargetScattering ){ + // if( Pb.Theta() < TMath::PiOver2() ){ + // msb.SetTarget(density, targetThickness - depth); + // }else{ + // msb.SetTarget(density, depth); + // } + // Pb = msb.Scattering(Pb); + // TbLoss = msb.GetKELoss(); + // msB.SetTarget(density, targetThickness - depth); + // PB = msB.Scattering(PB); + // }else{ + // TbLoss = 0; + // } + + //======= Decay of particle-B + int decayID = 0; + if( recoil.isDecay){ + + decayID = decay.CalDecay(PB, Ex, 0, phiCM + TMath::Pi()/2); // decay to ground state + if( decayID == 1 ){ + PB = decay.GetDaugther_D(); + //decayTheta = decay.GetAngleChange(); + decayTheta = decay.GetThetaCM(); + PB.SetUniqueID(recoil.decayZ); + }else{ + decayTheta = TMath::QuietNaN(); + } + } + + //################################### tree branches + //===== reaction + thetab = Pb.Theta() * TMath::RadToDeg(); + thetaB = PB.Theta() * TMath::RadToDeg(); + + Tb = Pb.E() - Pb.M(); + TB = PB.E() - PB.M(); + + phib = Pb.Phi() * TMath::RadToDeg(); + phiB = PB.Phi() * TMath::RadToDeg(); + + //==== Helios + + // printf(" thetaCM : %f, Tb : %f\n", thetaCM * TMath::RadToDeg(), Pb.M()); + + if( Tb > 0 || TB > 0 ){ + + helios.CalArrayHit(Pb); + helios.CalRecoilHit(PB); + hit = 2; + while( hit > 1 ){ hit = helios.CheckDetAcceptance(); } /// while hit > 1, goto next loop; + + trajectory orb_b = helios.GetTrajectory_b(); + trajectory orb_B = helios.GetTrajectory_B(); + + e = helios.GetEnergy() + gRandom->Gaus(0, array.eSigma ); + + double ranX = gRandom->Gaus(0, array.zSigma); + z = orb_b.z + ranX; + detX = helios.GetDetX() + ranX; + + z0 = orb_b.z0; + t = orb_b.t; + loop = orb_b.loop; + detID = orb_b.detID; + detRowID = orb_b.detRowID; + rho = orb_b.rho; + rhoArray = orb_b.R; + + xArray = orb_b.x; + yArray = orb_b.y; + + + //ELUM + if( aux.elumPos1 != 0 ){ + xElum1 = helios.GetXPos(aux.elumPos1); + yElum1 = helios.GetYPos(aux.elumPos1); + rhoElum1 = helios.GetR(aux.elumPos1); + } + if( aux.elumPos2 != 0 ){ + xElum2 = helios.GetXPos(aux.elumPos2); + yElum2 = helios.GetYPos(aux.elumPos2); + rhoElum2 = helios.GetR(aux.elumPos2); + } + + //Recoil + rhoRecoil = orb_B.R; + tB = orb_B.t; + xRecoil = orb_B.x; + yRecoil = orb_B.y; + rhoB = orb_B.rho; + + //other recoil detectors + if ( aux.detPos1 != 0 ){ + xRecoil1 = helios.GetRecoilXPos(aux.detPos1); + yRecoil1 = helios.GetRecoilYPos(aux.detPos1); + rhoRecoil1 = helios.GetRecoilR(aux.detPos1); + } + if ( aux.detPos2 != 0 ){ + xRecoil2 = helios.GetRecoilXPos(aux.detPos2); + yRecoil2 = helios.GetRecoilYPos(aux.detPos2); + rhoRecoil2 = helios.GetRecoilR(aux.detPos2); + } + + std::pair ExThetaCM = transfer.CalExThetaCM(e, z, helios.GetBField(), helios.GetDetRadius()); + ExCal = ExThetaCM.first; + thetaCMCal = ExThetaCM.second; + + //change thetaCM into deg + thetaCM = thetaCM * TMath::RadToDeg(); + + //if decay, get the light decay particle on the recoil; + if( recoil.isDecay ){ + if( decayID == 1 ){ + TLorentzVector Pd = decay.GetDaugther_d(); + + Td = Pd.E() - Pd.M(); + + helios.CalRecoilHit(Pd); + + trajectory orb_d = helios.GetTrajectory_B(); + rhoRecoil_d = orb_d.R; + xRecoil_d = orb_d.x; + yRecoil_d = orb_d.y; + + }else{ + rhoRecoil_d = TMath::QuietNaN(); + xRecoil_d = TMath::QuietNaN(); + yRecoil_d = TMath::QuietNaN(); + } + } + + }else{ + hit = -404; + } + + if( hit == 1) count ++; + + if( reactConfig.isRedo ){ + if( hit == 1) { + redoFlag = false; + }else{ + redoFlag = true; + //printf("%d, %2d, thetaCM : %f, theta : %f, z0: %f \n", i, hit, thetaCM * TMath::RadToDeg(), thetab, helios.GetZ0()); + } + }else{ + redoFlag = false; + } + + }while( redoFlag ); + tree->Fill(); + + //#################################################################### Timer + clock.Stop("timer"); + Double_t time = clock.GetRealTime("timer"); + clock.Start("timer"); + + if ( !shown ) { + if (fmod(time, 10) < 1 ){ + printf( "%10d[%2d%%]| %8.2f sec | expect: %5.1f min \n", i, TMath::Nint((i+1)*100./numEvent), time , numEvent*time/(i+1)/60); + shown = 1; + } + }else{ + if (fmod(time, 10) > 9 ){ + shown = 0; + } + } + + } + + saveFile->Write(); + saveFile->Close(); + + distFile->Close(); + delete exDist; + + printf("=============== done. saved as %s. count(hit==1) : %d\n", saveFileName.Data(), count); + //gROOT->ProcessLine(".q"); + + return; + +} + + +int main (int argc, char *argv[]) { + + printf("=================================================================\n"); + printf("========== Simulate Transfer reaction in HELIOS ==========\n"); + printf("=================================================================\n"); + + if(argc == 2 || argc > 7) { + printf("Usage: ./Transfer [1] [2] [3] [4] [5] [6]\n"); + printf(" default file name \n"); + printf(" [1] reactionConfig.txt (input) reaction Setting \n"); + printf(" [2] detectorGeo.txt (input) detector Setting \n"); + printf(" [3] ID (input) detector & reaction ID (default = 0 ) \n"); + printf(" [4] DWBA.root (input) thetaCM distribution from DWBA \n"); + printf(" [5] transfer.root (output) rootFile name for output \n"); + printf(" [6] plot (input) will it plot stuffs [1/0] \n"); + + printf("------------------------------------------------------\n"); + return 0 ; + } + + std::string basicConfig = "reactionConfig.txt"; + std::string heliosDetGeoFile = "detectorGeo.txt"; + int ID = 0; + TString ptolemyRoot = "DWBA.root"; // when no file, use isotropic distribution of thetaCM + TString saveFileName; // format based on ID; + bool isPlot = false; + + if( argc >= 2) basicConfig = argv[1]; + if( argc >= 3) heliosDetGeoFile = argv[2]; + if( argc >= 4) ID = atoi(argv[3]); + if( argc >= 5) ptolemyRoot = argv[4]; + if( argc >= 6) saveFileName = argv[5]; + if( argc >= 7) isPlot = atoi(argv[7]); + + saveFileName = Form("transfer_%d.root", ID); + + Transfer( basicConfig, heliosDetGeoFile, ID, ptolemyRoot, saveFileName); + + //run Armory/Check_Simulation + if( isPlot ){ + std::ifstream file_in; + file_in.open("../Cleopatra/Check_Simulation.C", std::ios::in); + if( file_in){ + printf("---- running ../Cleopatra/Check_Simulation.C on %s \n", saveFileName.Data()); + TString cmd; + cmd.Form("root -l '../Cleopatra/Check_Simulation.C(\"%s\")'", saveFileName.Data()); + + system(cmd.Data()); + }else{ + printf("cannot find ../Cleopatra/Check_Simulation.C \n"); + } + } + +} + diff --git a/cleopatra/SimulationChecker.C b/cleopatra/SimulationChecker.C new file mode 100644 index 0000000..4358047 --- /dev/null +++ b/cleopatra/SimulationChecker.C @@ -0,0 +1,240 @@ +#include "TString.h" +#include "TFile.h" +#include "TTree.h" +#include "TH2.h" +#include "TStyle.h" +#include "TCanvas.h" +#include "TArc.h" +#include "TLine.h" +#include "TLatex.h" +#include "TMacro.h" + +#include "../Armory/AnalysisLib.h" +#include "../Armory/ClassDetGeo.h" +#include "../Armory/ClassReactionConfig.h" +#include "../Cleopatra/ClassIsotope.h" +#include "../Cleopatra/ClassTransfer.h" + +void SimulationChecker(TString transferRoot = "transfer.root"){ + + gStyle->SetOptStat(""); + gStyle->SetStatY(0.9); + gStyle->SetStatX(0.9); + gStyle->SetStatW(0.4); + gStyle->SetStatH(0.2); + gStyle->SetLabelSize(0.05, "XY"); + gStyle->SetTitleFontSize(0.1); + + TFile * file = new TFile(transferRoot, "read"); + TTree * tree = (TTree*) file->Get("tree"); + + TObjArray * fxList = (TObjArray *) file->FindObjectAny("EZCurve"); + + //*================================== List Of Reactions + TMacro * listOfReaction = (TMacro *) file->FindObjectAny("ListOfReactions"); + + int numReaction = listOfReaction->GetListOfLines()->GetSize(); + + std::vector reactionIDList(numReaction, -1); + std::vector reactionNameList(numReaction, ""); + for( int i = 0; i < numReaction; i++){ + std::vector tempStr = AnalysisLib::SplitStr(listOfReaction->GetListOfLines()->At(i)->GetName(), "|"); + reactionIDList[i] = atoi(tempStr[0].c_str()); + reactionNameList[i] = tempStr[1]; + } + + // for( int i = 0; i < numReaction; i++) printf("%2d | %s\n", reactionIDList[i], reactionNameList[i].Data()); + + //*================================== DWBA, if any + TMacro * dwbaReaction = (TMacro *) file->FindObjectAny("DWBA_ReactionList"); + TMacro * dwbaExList = (TMacro *) file->FindObjectAny("DWBA_ExList"); + // dwbaReaction->Print(); + // dwbaExList->Print(); + + + //*================================== reactionConfig + TMacro * reactionConfigTxt = (TMacro *) file->FindObjectAny("reactionConfig"); + + ReactionConfig reactionConfig(reactionConfigTxt); + + int nEvent = reactionConfig.numEvents; + printf("number of events generated : %d \n", nEvent); + + //=== clear the Ex in reactionCondig if DWBA_ReactionList + if( dwbaReaction || listOfReaction ){ + for( int i = 0; i < numReaction; i ++){ + reactionConfig.exList[reactionIDList[i]].Clear(); + + for( int j = 0; j < dwbaReaction->GetListOfLines()->GetSize(); j++){ + std::vector haha = AnalysisLib::SplitStr(dwbaReaction->GetListOfLines()->At(j)->GetName(), "|"); + + if( atoi(haha[1].c_str()) == reactionIDList[i] ) { + std::vector dudu = AnalysisLib::SplitStr(dwbaExList->GetListOfLines()->At(j+1)->GetName(), " "); + + reactionConfig.exList[reactionIDList[i]].Add(atof(dudu[0].c_str()), atof(dudu[1].c_str()), 1.0, 0.00); + + } + + } + + reactionConfig.Print(reactionIDList[i]); + } + } + + + + //*================================== detector Geometry + printf("=================================\n"); + printf(" loading detector Geometry.\n"); + TMacro * detGeoTxt = (TMacro *) file->FindObjectAny("detGeo"); + + DetGeo detGeo(detGeoTxt); + + detGeo.Print(true); + + printf("%f %f \n", detGeo.array[0].zMin, detGeo.array[0].zMax); + + printf("=================================\n"); + + //*================================== + + int padSize = 500; + int Div[2] = {5, numReaction}; + Int_t size[2] = {padSize,padSize}; ///x,y, single Canvas size + TCanvas * cCheck = new TCanvas("cCheck", "Check For Simulation", 0, 0, size[0]*Div[0], size[1]*Div[1]); + if(cCheck->GetShowEditor() )cCheck->ToggleEditor(); + if(cCheck->GetShowToolBar() )cCheck->ToggleToolBar(); + cCheck->Divide(Div[0],Div[1]); + + bool shownKELines = true; + TString gate = "hit == 1 && loop <= 1 && thetaCM > 10"; + + //^------------------------------- + cCheck->cd(1); + { + TH2F * hez = new TH2F("hez", Form("e-z [gated] @ %5.0f mm; z [mm]; e [MeV]", detGeo.array[0].firstPos), + 400, detGeo.array[0].zMin, detGeo.array[0].zMax, + 400, 0, 10); + + tree->Draw("e:z>>hez", gate + " && rID == 0", "colz"); + } + + //^------------------------------- + cCheck->cd(2); + { + TH2F * hRecoilXY = new TH2F("hRecoilXY", Form("RecoilXY [gated] @ %4.0f mm; X [mm]; Y [mm]", detGeo.aux[0].detPos ), + 400, -detGeo.aux[0].outerRadius, detGeo.aux[0].outerRadius, + 400, -detGeo.aux[0].outerRadius, detGeo.aux[0].outerRadius); + tree->Draw("yRecoil:xRecoil>>hRecoilXY", gate + " && rID == 0", "colz"); + TArc * detArc1 = new TArc(0,0, detGeo.aux[0].outerRadius); + detArc1->SetLineColor(kBlue-8); + detArc1->SetFillStyle(0); + detArc1->Draw("same"); + TArc * detArc2 = new TArc(0,0, detGeo.aux[0].innerRadius); + detArc2->SetLineColor(kBlue-8); + detArc2->SetFillStyle(0); + detArc2->Draw("same"); + + if( reactionConfig.beamX != 0. || reactionConfig.beamY != 0. ){ + TArc * arc = new TArc(reactionConfig.beamX, reactionConfig.beamY, 1); + arc->SetLineColor(2); + detArc1->SetFillStyle(0); + arc->Draw("same"); + } + } + //^------------------------------- + cCheck->cd(3); + { + // TH1F * hThetaCM[numEx]; + // TLegend * legend = new TLegend(0.8,0.2,0.99,0.8); + // double maxCount = 0; + // int startID = 0; // set the start ExID + // for( int i = startID; i < numEx; i++){ + // hThetaCM[i] = new TH1F(Form("hThetaCM%d", i), Form("thetaCM [gated] (ExID=%d); thetaCM [deg]; count", i), 200, thetaCMRange[0], thetaCMRange[1]); + // hThetaCM[i]->SetLineColor(i+1-startID); + // hThetaCM[i]->SetFillColor(i+1-startID); + // hThetaCM[i]->SetFillStyle(3000+i-startID); + // tree->Draw(Form("thetaCM>>hThetaCM%d", i), gate + Form("&& ExID==%d", i), ""); + // legend->AddEntry(hThetaCM[i], Form("Ex=%5.1f MeV", exList.ExList[i].Ex)); + // double max = hThetaCM[i]->GetMaximum(); + // if( max > maxCount ) maxCount = max; + // } + + // for( int i = startID; i < numEx; i++){ + // hThetaCM[i]->GetYaxis()->SetRangeUser(1, maxCount * 1.2); + // if( i == startID ) { + // hThetaCM[i]->Draw(); + // }else{ + // hThetaCM[i]->Draw("same"); + // } + // } + // legend->Draw(); + } + + //^------------------------------- + cCheck->cd(4); + { + TLatex text; + text.SetNDC(); + text.SetTextFont(82); + text.SetTextSize(0.06); + text.SetTextColor(2); + + text.DrawLatex(0., 0.9, reactionNameList[0]); + text.DrawLatex(0., 0.8, detGeo.Bfield > 0 ? "out of plan" : "into plan"); + text.SetTextColor(1); + text.DrawLatex(0., 0.7, "gate:"); + + text.SetTextColor(2); + //check gate text length, if > 30, break by "&&" + int ll = gate.Length(); + if( ll > 30 ) { + std::vector strList = AnalysisLib::SplitStr( (std::string) gate.Data(), "&&"); + for( int i = 0; i < strList.size(); i++){ + text.DrawLatex(0., 0.6 - 0.05*i, (TString) strList[i]); + } + }else{ + text.DrawLatex(0., 0.6, gate); + } + + if( reactionConfig.beamX != 0.0 || reactionConfig.beamY != 0.0 ){ + text.DrawLatex(0.0, 0.1, Form("Bema pos: (%4.1f, %4.1f) mm", reactionConfig.beamX, reactionConfig.beamY)); + } + } + //^------------------------------- + cCheck->cd(5); + { + TH1F * hExCal = new TH1F("hExCal", Form("calculated Ex [gated]; Ex [MeV]; count / %.2f keV", 10.), 400, -1, 3); + tree->Draw("ExCal>>hExCal", gate + " && rID == 0", ""); + Isotope hRecoil(reactionConfig.recoil[0].heavyA, reactionConfig.recoil[0].heavyZ); + double Sn = hRecoil.CalSp(0,1); + double Sp = hRecoil.CalSp(1,0); + double Sa = hRecoil.CalSp2(4,2); + double S2n = hRecoil.CalSp(0, 2); + + printf("Heavy recoil: %s \n", hRecoil.Name.c_str()); + printf("Sn : %f MeV/u \n", Sn); + printf("Sp : %f MeV/u \n", Sp); + printf("Sa : %f MeV/u \n", Sa); + printf("S2n : %f MeV/u \n", S2n); + + double yMax = hExCal->GetMaximum(); + TLine * lineSn = new TLine(Sn, 0, Sn, yMax); lineSn->SetLineColor(2); lineSn->Draw(""); + TLine * lineSp = new TLine(Sp, 0, Sp, yMax); lineSp->SetLineColor(4); lineSp->Draw("same"); + TLine * lineSa = new TLine(Sa, 0, Sa, yMax); lineSa->SetLineColor(6); lineSa->Draw("same"); + TLine * lineS2n = new TLine(S2n, 0, S2n, yMax); lineS2n->SetLineColor(8); lineS2n->Draw("same"); + + TLatex * text = new TLatex(); + text->SetTextFont(82); + text->SetTextSize(0.06); + text->SetTextColor(2); text->DrawLatex(Sn, yMax*0.9, "S_{n}"); + text->SetTextColor(4); text->DrawLatex(Sp, yMax*0.9, "S_{p}"); + text->SetTextColor(6); text->DrawLatex(Sa, yMax*0.9, "S_{a}"); + text->SetTextColor(8); text->DrawLatex(S2n, yMax*0.9, "S_{2n}"); + + } + + cCheck->Modified(); + cCheck->Update(); + +} \ No newline at end of file diff --git a/cleopatra/constant.h b/cleopatra/constant.h new file mode 100644 index 0000000..4f80d8b --- /dev/null +++ b/cleopatra/constant.h @@ -0,0 +1,71 @@ +/*********************************************************************** + * + * This is constant.h, to provide various physical constants. + * + *------------------------------------------------------- + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + + +#ifndef constant +#define constant +#include + +const double pi = acos(-1.0); +const double E = 2.718281828459 ; +const double hbar_SI = 1.054571628e-34; //Js +const double kB = 1.3806504e-23; //JK^-1 +const double e = 1.602176487e-19; //C +const double c_SI = 299792458; //ms^-1 +const double me_SI = 9.10938215e-31 ; //kg +const double mp_SI = 1.672621637e-27 ; //kg +const double mn_SI = 1.67492729e-27 ; //kg +const double NA = 6.022141e+23 ; //mol^-1 + +const double deg2rad = pi/180 ; +const double rad2deg = 180/pi ; + + +//====================================================================== +const double amu = 931.49432; // MeV/c^2 +const double hbarc = 197.326979; // MeV fm; +const double c = 299.792458; // mm/ns; +const double ee = 1.439964454; // MeV.fm + +//====================================================================== +double kg2MeV(double m){ + return m*c_SI*c_SI/e/1e6; +} + +double T2Brho(double mass, int Z, int A, double T){ + //mass in MeV + // Z in e + // T in MeV/A + double gamma = (T*A + mass)/mass; + double beta = sqrt(1-1/gamma/gamma); + return mass*beta*gamma/Z/c; +} + +double Brho2T(double mass, int Z, int A, double Brho){ + //mass in MeV + // Z in e + return (sqrt(pow(Brho*Z*c,2)+mass*mass)-mass)/A; +} + +double T2beta(double mass, int A, double T){ + double gamma = 1.0 + T*A/mass; + return sqrt(1-1/gamma/gamma); +} + +double ev2nm(double eV){ + // photon energy to nm + return hbarc/2/pi/eV; +} + +//====================================================================== +const double mp = kg2MeV(mp_SI); +const double mn = kg2MeV(mn_SI); +const double hbar = 197.326979; + +#endif diff --git a/cleopatra/makefile b/cleopatra/makefile new file mode 100644 index 0000000..70b796d --- /dev/null +++ b/cleopatra/makefile @@ -0,0 +1,41 @@ +CC = g++ +CFLAG = -O2 + +depend = ClassTransfer.h ClassHelios.h ClassIsotope.h ClassDecay.h constant.h potentials.h + +ALL = Isotope InFileCreator ExtractXSec ExtractXSecFromText PlotTGraphTObjArray Cleopatra FindThetaCM SimTransfer SimAlpha + +all: $(ALL) + +Isotope: ClassIsotope.h Isotope.C + $(CC) $(CFLAG) Isotope.C -o Isotope + +InFileCreator: InFileCreator.C InFileCreator.h $(depend) + $(CC) $(CFLAG) InFileCreator.C -o InFileCreator `root-config --cflags --glibs` + +ExtractXSec: ExtractXSec.C ExtractXSec.h + $(CC) $(CFLAG) ExtractXSec.C -o ExtractXSec `root-config --cflags --glibs` + +ExtractXSecFromText: ExtractXSecFromText.C ExtractXSec.h + $(CC) $(CFLAG) ExtractXSecFromText.C -o ExtractXSecFromText `root-config --cflags --glibs` + +PlotTGraphTObjArray: PlotTGraphTObjArray.C PlotTGraphTObjArray.h + $(CC) $(CFLAG) PlotTGraphTObjArray.C -o PlotTGraphTObjArray `root-config --cflags --glibs` + +Cleopatra: Cleopatra.C InFileCreator.h ExtractXSec.h + $(CC) $(CFLAG) Cleopatra.C -o Cleopatra `root-config --cflags --glibs` + +FindThetaCM: FindThetaCM.C FindThetaCM.h $(depend) + $(CC) $(CFLAG) FindThetaCM.C -o FindThetaCM `root-config --cflags --glibs` + +SimTransfer: SimTransfer.C ClassTransfer.h $(depend) ../Armory/ClassReactionConfig.h ../Armory/ClassDetGeo.h + $(CC) $(CFLAG) SimTransfer.C -o SimTransfer `root-config --cflags --glibs` + +SimTransfer_single: SimTransfer_single.C $(depend) ../Armory/ClassReactionConfig.h ../Armory/ClassDetGeo.h + $(CC) $(CFLAG) SimTransfer_single.C -o SimTransfer_single `root-config --cflags --glibs` + +SimAlpha: SimAlpha.C ClassHelios.h + $(CC) $(CFLAG) SimAlpha.C -o SimAlpha `root-config --cflags --glibs` + +clean: + /bin/rm -f $(ALL) \ No newline at end of file diff --git a/cleopatra/nuclear_data.py b/cleopatra/nuclear_data.py new file mode 100755 index 0000000..63fe7a6 --- /dev/null +++ b/cleopatra/nuclear_data.py @@ -0,0 +1,153 @@ +#!/usr/local/bin/python3 + +################################################ +import sys + +if len(sys.argv) == 1 : + print( "usage :" ) + print( "%s AZ [maxEx]" % sys.argv[0] ) + print( "e.g. %s 17O --> 17O ground state data" % sys.argv[0]) + print( "e.g. %s 20O 5 --> 20O ground state data and excited state < 5 MeV" % sys.argv[0]) + exit() + +################################################ +import pandas as pd + +# the API webpage +# https://www-nds.iaea.org/relnsd/vcharthtml/api_v0_guide.html#examples + +# the service URL +livechart = "https://nds.iaea.org/relnsd/v0/data?" + +import urllib.request + +def lc_read_csv(url): + req = urllib.request.Request(url) + req.add_header('User-Agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0') + return pd.read_csv(urllib.request.urlopen(req)) + +haha = lc_read_csv(livechart + 'fields=ground_states&nuclides=all') + +mp = 938.27208816; #MeV/c^2 +mn = 939.56542052; + +def FindZ(AZ): + query = livechart + "fields=ground_states&nuclides=" + AZ + temp = lc_read_csv(query); + try : + return temp['z'] + except : + return 'na' +def FindSym(Z): + try: + return (haha['symbol'][haha['z']==Z]).iloc[0] + except: + return 'na' +def Mass(A, Z): + try : + BEA = float(haha['binding'][haha['z']==Z][haha['n']==(A-Z)].iloc[0])/1000 + return (A-Z)*mn + Z*mp - A * BEA + except : + return -404 +def MassSym(AZ): + query = livechart + "fields=ground_states&nuclides=" + AZ + temp = lc_read_csv(query); + Z = temp['z'] + N = temp['n'] + try : + return Z*mp + N*mn - (Z+N)*temp['binding']/1000 + except: + return -404 +def Sp(A,Z,a,z): + mA = Mass(A,Z) + mB = Mass(A-a, Z-z) + if z == 0 : + mb = a * mn + elif a == z : + mb = a * mp + else : + mb = Mass(a,z) + if (mB == -404 or mb == -404 or mA == -404) : + return -404 + else: + return mB + mb - mA +def Ex(AZ, maxMeV): + query = livechart + "fields=levels&nuclides=" + AZ + tempEx = lc_read_csv(query); + try : + return tempEx[['energy', 'jp']][tempEx['energy']<= maxMeV * 1000] + except: + return -404 + +def Info(AZ): + query = livechart + "fields=ground_states&nuclides=" + AZ + temp = lc_read_csv(query); + + print("============================================== " + AZ ) + try : + Z = temp['z'][0] + N = temp['n'][0] + mass = float(Z*mp + N*mn - (Z+N)*temp['binding'].iloc[0]/1000) + halfLife = temp['half_life_sec'][0] + print(" A : %3d, Z : %3d, N : %3d, Mass : %.4f MeV" % (Z+N, Z, N, mass)) + print("Jpi : %3s, half-live : %s sec" % (temp['jp'][0], halfLife)) + print("Sn : %8.3f MeV, Sp : %8.3f MeV" % (Sp(Z+N,Z, 1, 0), Sp(Z+N,Z, 1, 1))) + print("S2n : %8.3f MeV, S2p : %8.3f MeV, Sd : %8.3f MeV" % (Sp(Z+N,Z, 2, 0), Sp(Z+N,Z, 2, 2), Sp(Z+N, Z, 2, 1))) + print("S3n : %8.3f MeV, S3p : %8.3f MeV, St : %8.3f MeV, S(3He) : %8.3f MeV" % (Sp(Z+N,Z, 3, 0), Sp(Z+N,Z, 3, 3), Sp(Z+N, Z, 3, 1), Sp(Z+N, Z, 3, 2))) + print("S4n : %8.3f MeV, S4p : %8.3f MeV, Sa : %8.3f MeV" % (Sp(Z+N,Z, 4, 0), Sp(Z+N,Z, 4, 4), Sp(Z+N, Z, 4, 2))) + print(" magnetic dipole : " + temp['magnetic_dipole'][0] + " mu.N") + print("electric quadruple : " + temp['electric_quadrupole'][0] + " barn") + if halfLife > 0 : + print('------------ decay mode:') + for i in range(1, 4) : + print("%5s %s %%" % (temp["decay_%d" % i][0], temp["decay_%d_%%" % i][0])) + print('--------------------------') + except : + dummy = 1 + print("====================================================\n") + + #outfile = open("%s.txt" % AZ, "w") + #outfile.write("============================================== " + AZ + "\n") + #try : + # Z = temp['z'][0] + # N = temp['n'][0] + # mass = Z*mp + N*mn - (Z+N)*temp['binding']/1000 + # halfLife = temp['half_life_sec'][0] + # outfile.write(" A : %3d, Z : %3d, N : %3d, Mass : %.4f MeV \n" % (Z+N, Z, N, mass)) + # outfile.write("Jpi : %3s, half-live : %s sec \n" % (temp['jp'][0], halfLife)) + # outfile.write("Sn : %8.3f MeV, Sp : %8.3f MeV \n" % (Sp(Z+N,Z, 1, 0), Sp(Z+N,Z, 1, 1))) + # outfile.write("S2n : %8.3f MeV, S2p : %8.3f MeV, Sd : %8.3f MeV \n" % (Sp(Z+N,Z, 2, 0), Sp(Z+N,Z, 2, 2), Sp(Z+N, Z, 2, 1))) + # outfile.write("S3n : %8.3f MeV, S3p : %8.3f MeV, St : %8.3f MeV, S(3He) : %8.3f MeV \n" % (Sp(Z+N,Z, 3, 0), Sp(Z+N,Z, 3, 3), Sp(Z+N, Z, 3, 1), Sp(Z+N, Z, 3, 2))) + # outfile.write("S4n : %8.3f MeV, S4p : %8.3f MeV, Sa : %8.3f MeV \n" % (Sp(Z+N,Z, 4, 0), Sp(Z+N,Z, 4, 4), Sp(Z+N, Z, 4, 2))) + # outfile.write(" magnetic dipole : " + temp['magnetic_dipole'][0] + " mu.N\n") + # outfile.write("electric quadruple : " + temp['electric_quadrupole'][0] + " barn \n") + # if halfLife > 0 : + # outfile.write('------------ decay mode: \n') + # for i in range(1, 4) : + # outfile.write("%5s %s %% \n" % (temp["decay_%d" % i][0], temp["decay_%d_%%" % i][0])) + # outfile.write('-------------------------\n') + #except : + # dummy = 1 + #outfile.write("====================================================\n") + #outfile.close(); + # + #infile = open("%s.txt" % AZ, "r") + #Lines = infile.readlines() + # + #for line in Lines: + # print(line.strip("\n")) + # + #infile.close(); + + +################################################ +AZ = sys.argv[1]; +maxEx = 0; +if len(sys.argv) > 2 : + maxEx = float(sys.argv[2]); + +Info(AZ) + +if maxEx > 0 : + print( Ex(AZ, float(maxEx)) ) + diff --git a/cleopatra/potentials.h b/cleopatra/potentials.h new file mode 100644 index 0000000..e39c935 --- /dev/null +++ b/cleopatra/potentials.h @@ -0,0 +1,1073 @@ +/*********************************************************************** + * + * This is potenital.h, To calculate optical potenital + * It contains various optical potential for proton and deuteron + * It is as same as Kay Ben's globals_beta_v5 + * + *------------------------------------------------------- + * created by Ryan (Tsz Leung) Tang, Nov-18, 2018 + * email: goluckyryan@gmail.com + * ********************************************************************/ + +//golbal varibale for Optical Potential +double v, r0, a; +double vi, ri0, ai; +double vsi, rsi0, asi; +double vso, rso0, aso; +double vsoi, rsoi0, asoi, rc0; + +void PrintPotential(){ + printf("v = %7.3f r0 = %7.3f a = %7.3f\n", v, r0, a); + printf("vi = %7.3f ri0 = %7.3f ai = %7.3f\n", vi, ri0, ai); + printf("vsi = %7.3f rsi0 = %7.3f asi = %7.3f\n", vsi, rsi0, asi); + printf("vso = %7.3f rso0 = %7.3f aso = %7.3f\n", vso, rso0, aso); + printf("vsoi = %7.3f rsoi0 = %7.3f asoi = %7.3f rc0 = %7.3f\n", vsoi, rsoi0, asoi, rc0); +} + +/// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z +/// 1 1 1 1 0 0 1 1 0 0 1 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 +std::string potentialRef(std::string name){ + + //======== Deuteron + if( name == "A" ){ + return "An and Cai (2006) E < 183 | 12 < A < 238 | http://dx.doi.org/10.1103/PhysRevC.73.054605"; + } + if( name == "H" ){ + return "Han, Shi, Shen (2006) E < 200 | 12 < A < 209 | http://dx.doi.org/10.1103/PhysRevC.74.044615"; + } + if( name == "B" ){ + return "Bojowald et al.(1988) 50 < E < 80 | 27 < A < 208 | http://dx.doi.org/10.1103/PhysRevC.38.1153"; + } + if( name == "D" ){ + return "Daehnick, Childs, Vrcelj (1980) 11.8 < E < 80 | 27 < A < 238 (REL) | http://dx.doi.org/10.1103/PhysRevC.21.2253"; + } + if( name == "C" ){ + return "Daehnick, Childs, Vrcelj (1980) 11.8 < E < 80 | 27 < A < 238 (NON-REL) | http://dx.doi.org/10.1103/PhysRevC.21.2253"; + } + if( name == "L" ){ + return "Lohr and Haeberli (1974) 9 < E < 13 | 40 < A | http://dx.doi.org/10.1016/0375-9474(74)90627-7"; + } + if( name == "Q" ){ + return "Perey and Perey (1963) 12 < E < 25 | 40 < A | http://dx.doi.org/10.1016/0370-1573(91)90039-O"; + } + + if( name == "Z" ){ + return "Zhang, Pang, Lou (2016) 5 < E < 170 | A < 18 | https://doi.org/10.1103/PhysRevC.94.014619"; + } + + //======= Proton + if( name == "K" ){ + return "Koning and Delaroche (2009) 0.001 < E < 200 | 24 < A < 209 | Iso. Dep. | http://dx.doi.org/10.1016/S0375-9474(02)01321-0"; + } + if( name == "V" ){ + return "Varner et al., (CH89) (1991) 16 < E < 65 | 4 < A < 209 | http://dx.doi.org/10.1016/0370-1573(91)90039-O"; + } + if( name == "M" ){ + return "Menet et al. (1971) 30 < E < 60 | 40 < A | http://dx/doi.org/10.1016/0092-640X(76)90007-3"; + } + if( name == "G" ){ + return "Becchetti and Greenlees (1969) E < 50 | 40 < A | http://dx.doi.org/10.1103/PhysRev.182.1190"; + } + if( name == "P" ){ + return "Perey (1963) E < 20 | 30 < A < 100 | http://dx/doi.org/10.1016/0092-640X(76)90007-3"; + } + +/// a b c d e f g h i j k l m n o p q r s t u v w x y z +/// 1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 1 1 0 0 0 1 0 0 + //====== A = 3 + if( name == "x" ){ + return "XU, GUO, HAN, SHEN (2011) E < 250 | 20 < A < 209 | http://dx.doi.org/10.1007/s11433-011-4488-5"; + } + if( name == "l" ){ + return "Liang, Li, Cai (2009) E < 270 | All masses | http://dx.doi.org/10.1088/0954-3899/36/8/085104"; + } + if( name == "p" ){ + return "Pang et al., (2009) All E | All masses | Isospin dep. | http://dx.doi.org/10.1103/PhysRevC.79.024615"; + } + if( name == "c" ){ + return "Li, Liang, Cai, (2007) E < 40 | All masses | 48 < A < 232 | Tritons | http://dx.doi.org/10.1016/j.nuclphysa.2007.03.004"; + } + if( name == "t" ){ + return "Trost et al., (1987) 10 < E < 220 | 10 < A < 208 | http://dx.doi.org/10.1016/0375-9474(87)90551-3"; + } + if( name == "h" ){ + return "Hyakutake et al., (1980) 90 < E < 120 | About 58 < A < 92 | http://dx.doi.org/10.1016/0375-9474(80)90013-5"; + } + if( name == "b" ){ + return "Becchetti and Greenlees, (1971) E < 40 | 40 < A | Iso. Dep."; + } + + //======= alpha + if( name == "s"){ + return "Su and Han, (2015) E < 398 | 20 < A < 209 | http://dx.doi/org/10.1142/S0218301315500925"; + } + if( name == "a"){ + return "Avrigeanu et al., (2009) E ??? | A ??? | http://dx.doi/org/10.1016/j.adt.2009.02.001"; + } + if( name == "f"){ + return "(FIXED) Bassani and Picard, (1969) 24 < E < 31 | A = 90 | https://doi.org/10.1016/0375-9474(69)90601-0"; + } + + //====== custom + if( name == "Y"){ + return "Bardayan Parameters PRC 78 052801(R) (2008)"; + } + if( name == "X"){ + return "Bardayan Parameters PRC 78 052801(R) (2008)"; + } + + return ""; +} + + +bool CustomXPotential(int A, int Z, double E){ + +v = 54.19 ; +r0 = 1.25 ; +a = 0.65 ; +vi = 0.0 ; +ri0 = 1.25 ; +ai = 0.65 ; +vsi = 13.5 ; +rsi0 = 1.25 ; +asi = 0.47 ; +vso = 7.5 ; +rso0 = 1.25 ; +aso = 0.47 ; +vsoi = 0.0 ; +rsoi0 = 1.25 ; +asoi = 0.47 ; +rc0 = 1.25 ; + + return true; +} + +bool CustomYPotential(int A, int Z, double E){ + + v = 85.31; + r0 = 1.15; + a = 0.81; + + vi = 0.0; + ri0 = 1.15; + ai = 0.81; + + vsi = 16.0; + rsi0 = 1.34; + asi = 0.68; + + vso = 0.0; + rso0 = 1.0; + aso = 1.0; + + vsoi = 0.0; + rsoi0 = 1.0; + asoi = 1.0; + + rc0 = 1.15; + + return true; +} +//======================== deuteron +bool AnCaiPotential(int A, int Z, double E){ + // d + A(Z) + // E < 183 or 81.5 MeV/u + // 12 < A < 238 + // http://dx.doi.org/10.1103/PhysRevC.73.054605 + + //if( !(12 <= A && A <= 238 ) ) return false; + //if( E > 183 ) return false; + + double A3 = pow(A, 1./3.); + + v = 91.85 - 0.249*E + 0.000116*pow(E,2) + 0.642 * Z / A3; + r0 = 1.152 - 0.00776 / A3; + a = 0.719 + 0.0126 * A3; + + vi = 1.104 + 0.0622 * E; + ri0 = 1.305 + 0.0997 / A3; + ai = 0.855 - 0.1 * A3; + + vsi = 10.83 - 0.0306 * E; + rsi0 = 1.334 + 0.152 / A3; + asi = 0.531 + 0.062 * A3; + + vso = 3.557; + rso0 = 0.972; + aso = 1.011; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.303; + + return true; +} + +bool HSSPotential(int A, int Z, double E){ + // d + A(Z) + // E < 200 or 100 MeV/u + // 12 < A < 209 + // http://dx.doi.org/10.1103/PhysRevC.73.054605 + + //if( !(12 <= A && A <= 209 ) ) return false; + //if( E > 200 ) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double VIcond = -4.916 + (0.0555*E) + 0.0000442 * pow(E,2) + 35. * (N-Z)/A; + + v = 82.18 - 0.148 * E - 0.000886 * pow(E,2) - 34.811*(N-Z)/A + 1.058*Z/A3; + r0 = 1.174; + a = 0.809; + + vi = VIcond > 0 ? VIcond : 0 ; + ri0 = VIcond > 0 ? 1.563 : 0; + ai = VIcond > 0 ? 0.7 + 0.045 * A3 : 0; + + vsi = 20.968 - 0.0794 * E - 43.398 * (N-Z)/A; + rsi0 = 1.328; + asi = 0.465 + 0.045*A3; + + vso = 3.703; + rso0 = 1.234; + aso = 0.813; + + vsoi = -0.206; + rsoi0 = 1.234; + asoi = 0.813; + + rc0 = 1.698; + + return true; +} + +bool BojowaldPotential(int A, int Z, double E){ + // d + A(Z) + // 50 < E < 80 or 25, 40 MeV/u + // 27 < A < 208 + // http://dx.doi.org/10.1103/PhysRevC.38.1153 + + //if( !(27 <= A && A <= 208 ) ) return false; + //if( E > 80 || E < 27) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double VIcond = 0.132 * (E - 45.); + + v = 81.33 - 0.24 * E + 1.43 * Z / A3; + r0 = 1.18; + a = 0.636 + 0.035 * A3; + + vi = VIcond > 0 ? VIcond : 0 ; + ri0 = 1.27; + ai = 0.768 + 0.021 * A3; + + vsi = 7.8 + 1.04 * A3 - 0.712 * vi; + rsi0 = 1.27; + asi = 0.768 + 0.021 * A3; + + vso = 6.0; + rso0 = 0.78 + 0.038 * A3; + aso = 0.78 + 0.038 * A3; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.3; + + return true; +} + +bool DaehnickPotential(int A, int Z, double E){ + // d + A(Z) + // 11.8 < E < 80 or 5.4, 40 MeV/u + // 27 < A < 238 + // http://dx.doi.org/10.1103/PhysRevC.21.2253 + + //if( !(27 <= A && A <= 238 ) ) return false; + //if( E > 80 || E < 11.8) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double beta = -1.* pow(E/100.,2); + + double MU1 = exp(-1*pow((8. - N)/2.,2)); + double MU2 = exp(-1*pow((20. - N)/2.,2)); + double MU3 = exp(-1*pow((28. - N)/2.,2)); + double MU4 = exp(-1*pow((50. - N)/2.,2)); + double MU5 = exp(-1*pow((82. - N)/2.,2)); + double MU6 = exp(-1*pow((126. - N)/2.,2)); + + double MU = MU1 + MU2 + MU3 + MU4 + MU5 + MU6; + + v = 88. - 0.283 * E + 0.88 * Z / A3; + r0 = 1.17; + a = 0.717 + 0.0012 * E; + + vi = (12. + 0.031 * E )*(1 - exp(beta)); + ri0 = 1.376 - 0.01 * sqrt(E); + ai = 0.52 + 0.07 * A3 - 0.04 * MU; + + vsi = (12. + 0.031 * E) * exp(beta); + rsi0 = ri0; + asi = ai; + + vso = 7.2 - 0.032 * E; + rso0 = 1.07; + aso = 0.66; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.3; + + return true; +} + +bool LohrPotential(int A, int Z, double E){ + // d + A(Z) + // 9 < E < 13 or 4.5, 6.5 MeV/u + // 40 < A + // http://dx.doi.org/10.1016/0375-9474(74)90627-7 + + //if( !(40 <= A ) ) return false; + //if( E > 13 || E < 9) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 91.13 + 2.2 * Z / A3; + r0 = 1.05; + a = 0.86; + + vi = 0; + ri0 = 0; + ai = 0; + + vsi = 218./pow(A,2./3.); + rsi0 = 1.43; + asi = 0.5 + 0.013 * pow(A,2./3.); + + vso = 7; + rso0 = 0.75; + aso = 0.5; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.3; + + return true; +} + +bool PereyPereyPotential(int A, int Z, double E){ + // d + A(Z) + // 12 < E < 25 or 6, 12.5 MeV/u + // 40 < A + // http://dx.doi.org/10.1016/0375-9474(74)90627-7 + + //if( !(40 <= A ) ) return false; + //if( E > 25 || E < 12) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 81 - 0.22*E + 2 * Z / A3; + r0 = 1.15; + a = 0.81; + + vi = 0; + ri0 = 0; + ai = 0; + + vsi = 14.4 + 0.24 * E; + rsi0 = 1.34; + asi = 0.68; + + vso = 0.; + rso0 = 0.; + aso = 0.; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.15; + + return true; +} + +bool ZhangPangLouPotential(int A, int Z, double E, double Zproj){ + + vso = 0; + rso0 = 0; + aso = 0; + vsoi = 0; + rsoi0 = 0; + rc0 = 1.3; + + double A3 = pow(A, 1./3.); + + double RC = rc0 * A3; + double Ec = 6 * Zproj * Z * 1.44 / 5 / RC; + + if( A == 6 && Z == 3 ){ + r0 = 1.62 - 0.0122 * (E - Ec) / A3; + ri0 = 2.83 - 0.0911 * (E - Ec) / A3; + rsi0 = ri0; + + a = 0.876; + ai = 0.27; + asi = ai; + + v = 47.9 + 2.37 * (E - Ec); + vi = 0; + vsi = 11.3 + 3.44 * (E - Ec); + + }else if( A == 7 && Z == 3 ){ + r0 = 1.45 + 0.097 * (E - Ec) / A3; + ri0 = 2.12 + 0.022 * (E - Ec) / A3; + rsi0 = ri0; + + a = 0.844; + ai = 0.261; + asi = ai; + + v = 26.1 + 1.19 * (E - Ec); + vi = 0; + vsi = 215.0 - 16.1 * (E - Ec); + + }else{ + r0 = 1.11 - 0.167 / A3 + 0.00117 * (E - Ec) / A3; + ri0 = 0.561 + 3.07 / A3 - 0.00449 * (E - Ec) / A3; + rsi0 = ri0; + + a = 0.776; + ai = 0.744; + asi = ai; + + v = 98.9 - 0.279 * (E - Ec); + vi = 11.5 / ( 1 + exp((18.1 - (E - Ec))/5.97)); + vsi = 7.56 / ( 1 + exp(((E - Ec) - 14.3)/4.55)); + + } + + return true; +} + +//======================== proton +bool KoningPotential(int A, int Z, double E, double Zproj){ + // p + A(Z) + // E < 200 or 200 MeV/u + // 24 < A < 209 + // http://dx.doi.org/10.1016/S0375-9474(02)01321-0 + + //if( !(24 <= A && A <= 209 ) ) return false; + //if( E > 200 ) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double vp1 = 59.3 + 21.*(N-Z)/A - 0.024*A; + double vn1 = 59.3 - 21.*(N-Z)/A - 0.024*A; + + double vp2 = 0.007067 + 0.00000423*A; + double vn2 = 0.007228 - 0.00000148*A; + + double vp3 = 0.00001729 + 0.00000001136 * A; + double vn3 = 0.00001994 - 0.00000002 * A; + + double vp4 = 7e-9; // = vn4 + double vn4 = vp4; + + double wp1 = 14.667 + 0.009629*A; + double wn1 = 12.195 + 0.0167*A; + + double wp2 = 73.55 + 0.0795*A; // = wn2 + double wn2 = wp2; + + double dp1 = 16 + 16.*(N-Z)/A; + double dn1 = 16 - 16.*(N-Z)/A; + + double dp2 = 0.018 + 0.003802/(1 + exp((A-156.)/8)); // = dn2 + double dn2 = dp2; + + double dp3 = 11.5 ; // = dn3 + double dn3 = dp3; + + double vso1 = 5.922 + 0.003 * A; + double vso2 = 0.004; + + double wso1 = -3.1; + double wso2 = 160; + + double epf = -8.4075 + 0.01378 *A; + double enf = -11.2814 + 0.02646 *A; + + double rc = 1.198 + 0.697/pow(A3,2) + 12.995/pow(A3,5); + double vc = 1.73/rc * Z / A3; + + v = vp1*(1 - vp2*(E-epf) + vp3*pow(E-epf,2) - vp4*pow(E-epf,3)) + vc * vp1 * (vp2 - 2*vp3*(E-epf) + 3*vp4*pow(E-epf,2)); + //neutron + if( Zproj == 0 ) v = vn1*(1 - vn2*(E-enf) + vn3*pow(E-enf,2) - vn4*pow(E-enf,3)); + + + r0 = 1.3039 - 0.4054 / A3; + a = 0.6778 - 0.000148 * A; + + vi = wp1 * pow(E-epf,2)/(pow(E-epf,2) + pow(wp2,2)); + if( Zproj == 0 ) vi = wn1 * pow(E-enf,2)/(pow(E-enf,2) + pow(wn2,2)); + + ri0 = 1.3039 - 0.4054 / A3; + ai = 0.6778 - 0.000148 * A; + + vsi = dp1 * pow(E-epf,2)/(pow(E-epf,2)+pow(dp3,2)) * exp(-dp2*(E-epf)); + if( Zproj == 0 ) vsi = dn1 * pow(E-enf,2)/(pow(E-enf,2)+pow(dn3,2)) * exp(-dn2*(E-enf)); + + rsi0 = 1.3424 - 0.01585 * A3; + asi = 0.5187 + 0.0005205 * A; + if( Zproj == 0 ) asi = 0.5446 - 0.0001656 * A; + + vso = vso1 * exp(-vso2 * (E-epf)); + if( Zproj == 0 ) vso = vso1 * exp(-vso2 * (E-enf)); + + rso0 = 1.1854 - 0.647/A3; + aso = 0.59; + + vsoi = wso1 * pow(E-epf,2)/(pow(E-epf,2)+pow(wso2,2)); + if ( Zproj == 0 ) vsoi = wso1 * pow(E-enf,2)/(pow(E-enf,2)+pow(wso2,2)); + + rsoi0 = 1.1854 - 0.647/A3; + asoi = 0.59; + + rc0 = rc; + + return true; +} + +bool VarnerPotential(int A, int Z, double E){ + // p + A(Z) + // 16 < E < 65 or 65 MeV/u + // 4 < A < 209 + // http://dx.doi.org/10.1016/0370-1573(91)90039-O + + //if( !(4 <= A && A <= 209 ) ) return false; + //if( E > 65 || E < 16 ) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double Rc = 1.24 * A3 + 0.12; + double EC = 1.73 * Z / Rc; + double ETA = 1.0*(N-Z)/A; + + v = 52.9 + 13.1 * (N-Z)/A - 0.299 * (E - EC); + r0 = 1.25 - 0.225/A3; + a = 0.690; + + vi = 7.8/(1 + exp((35. - E + EC)/16.) ); + ri0 = 1.33 - 0.42/A3; + ai = 0.69; + + vsi = (10 + 18.*(N-Z)/A)/(1+exp((E-EC - 36.)/37.)); + rsi0 = 1.33 - 0.42/A3; + asi = 0.69; + + vso = 5.9; + rso0 = 1.34 - 1.2/A3; + aso = 0.63; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = Rc/A3; + + return true; +} + +bool MenetPotential(int A, int Z, double E){ + // p + A(Z) + // 30 < E < 60 or 60 MeV/u + // 40 < A + // http://dx.doi.org/10.1016/0370-1573(91)90039-O + + //if( !(40 <= A ) ) return false; + //if( E > 60 || E < 30 ) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 49.9 - 0.22 * E + 26.4 * (N-Z) / A + 0.4 * Z / A3; + r0 = 1.16; + a = 0.75; + + vi = 1.2 + 0.09 * E; + ri0 = 1.37; + ai = 0.74 - 0.008 * E + 1.*(N-Z)/A; + + vsi = 4.2 - 0.05 * E + 15.5 * (N-Z)/A; + rsi0 = 1.37; + asi = 0.74 - 0.008 * E + 1.*(N-Z)/A; + + vso = 6.04; + rso0 = 1.064; + aso = 0.78; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.25; + + return true; +} + +bool BecchettiPotential(int A, int Z, double E){ + // p + A(Z) + // E < 50 or 60 MeV/u + // 40 < A + // http://dx.doi.org/10.1103/PhysRev.182.1190 + + //if( !(40 <= A ) ) return false; + //if( E > 60 || E < 30 ) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 54 - 0.32 * E + 24. * (N-Z) / A + 0.4 * Z / A3; + r0 = 1.17; + a = 0.75; + + vi = 0.22 * E - 2.7 < 0 ? 0 : 0.22 * E - 2.7; + ri0 = 1.32; + ai = 0.51 + 0.7 * (N-Z)/A; + + vsi = 11.8 - 0.258 * E + 12. * (N-Z)/A; + if( vsi < 0 ) { + vsi = 0; + } + rsi0 = 1.320; + asi = 0.51 + 0.7 * (N-Z)/A; + + vso = 6.2; + rso0 = 1.1; + aso = 0.75; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.3; + + return true; +} + +bool PereyPotential(int A, int Z, double E){ + // p + A(Z) + // E < 20 or 20 MeV/u + // 30 < A < 100 + // http://dx.doi.org/10.1103/PhysRev.182.1190 + + //if( !(40 <= A && A <= 100 ) ) return false; + //if( E > 20 ) return false; + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 53.3 - 0.55 * E + 27. * (N-Z) / A + 0.4 * Z / A3; + r0 = 1.25; + a = 0.65; + + vi = 0.; + ri0 = 0.; + ai = 0.; + + vsi = 13.5; + rsi0 = 1.25; + asi = 0.47; + + vso = 7.5; + rso0 = 1.25; + aso = 0.47; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.25; + + return true; +} + +bool XuPotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double vsiTest = 33.26647 - 0.16975 * E - 12.0 * (N-Z)/A; + double viTest = -2 + 0.10645*E - 0.00016156 * pow(E,2); + + v = 136.34988 - 0.20315 * E - 0.00030147 * pow(E,2) - 24.0 * (N-Z) / A + 0.4 * Z / A3; + r0 = 1.14963; + a = 0.78836; + + vi = 0.0; if( viTest > 0 ) vi = viTest; + ri0 = 1.61807; + ai = 0.66485; + + vsi = 0.0; if( vsiTest > 0 ) vsi = vsiTest; + rsi0 = 1.20655; + asi = 0.73593; + + vso = 3.0; + rso0 = 1.26864; + aso = 0.89999; + + vsoi = 0; + rsoi0 = 0; + asoi = 0; + + rc0 = 1.25; + + return true; +} + +bool LiangPotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 118.36 - 0.2071 * E + 0.000063961 * pow(E,2) + 26.001 * (N-Z) / A + 0.5668 * Z / A3; + r0 = 1.1657 + 0.0401 / A3; + a = 0.6641 + 0.0305 * A3; + + vi = -6.8871 + 0.3115 * E - 0.00068096 * pow(E,2); + ri0 = 1.4022 + 0.0418 / A3; + ai = 0.7732 + 0.0219 * A3; + + vsi = 20.119 - 0.1626 * E - 5.4067 * (N-Z) / A + 1.2087 * A3; + rsi0 = 1.1802 + 0.0587 / A3; + asi = 0.6292 + 0.0657 * A3; + + vso = 2.0491 + 0.0099804 * A3; + rso0 = 0.7211 + 0.0586 / A3; + aso = 0.7643 + 0.0535 * A3; + + vsoi = -1.1591; + rsoi0 = 0.7211 + 0.0586 * A3; + asoi = 0.7643 + 0.0535 * A3; + + rc0 = 1.289; + + return true; +} + +bool PangPotential(int A, int Z, double E, int Zproj){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double rc = 1.24 * A3 + 0.12; + double EC = 1.728 * Z * Zproj / rc; + double ETA = 1.0 * (N-Z) / A; + double vsiAsym = 35.0 - 34.2 * ETA; + if( Zproj == 2.0 ) vsiAsym = 35 + 34.2* ETA; + + v = 118.3 - 0.13 * (E - EC); + r0 = 1.3 - 0.48 / A3; + a = 0.82; + + vi = 38.5/(1.0 + exp( (156.1 - E + EC)/52.4 )); + ri0 = 1.31 - 0.13 / A3; + ai = 0.84; + + vsi = vsiAsym / ( 1.0 + exp( (E - EC - 30.8) / 106.4 )); + rsi0 = 1.31 - 0.13 / A3; + asi = 0.84; + + vso = 0; + if( E < 85 ) vso = 1.7 - 0.02 * E; + rso0 = 0.64 + 1.18 / A3; + aso = 0.13; + + vsoi = 0.; + rsoi0 = 0.; + asoi = 0.; + + rc0 = rc/ A3; + + return true; +} + +bool LiLiangCaiPotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 137.6 - 0.1456 * E + 0.0436 * pow(E,2) + 4.3751 * (N-Z) / A + 1.0474 * Z / A3; + r0 = 1.1201 - 0.1504 / A3; + a = 0.6833 + 0.0191 * A3; + + vi = 7.383 + 0.5025 * E - 0.0097 * pow(E,2); + ri0 = 1.3202 - 0.1776 / A3; + ai = 1.119 + 0.01913 * A3; + + vsi = 37.06 - 0.6451 * E - 47.19 * (N-Z) / A; + rsi0 = 1.251 - 0.4622 / A3; + asi = 0.8114 + 0.01159 * A3; + + vso = 1.9029; + rso0 = 0.46991 + 0.1294 / A3; + aso = 0.3545 - 0.0522 * A3; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.422; + + return true; +} + +bool TrostPotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double JR = 272.33 * (1.0 + 0.002029 * A) * ( 1.0 - 0.001453 * E ) * (1.0 + 3.4931 * pow(A3,-2)) * ( 1.0+(-0.825165+exp(0.92059-0.079154*A))*exp(-0.065066*E) ); + double AP = 3 ; + + r0 = 1.150; + double RR = A3 * r0; + a = 0.64*(1+(0.0004*A))*(1+0.25*(1-exp(-0.2*A))*(1-exp(-0.06*E))); + double pi = 3.141592653589793; + v = 3.0/(4 * pi) * JR * AP * A * pow(RR, -3.0) / (1 + pow((pi * a)/RR,2) ); + + vi = 0.0; + ri0 = 0.0; + ai = 0.0; + + vsi = 24.5*(1+(1-(0.011*A))*(-0.0018)*E)*(1-exp(-(1.0+(0.003*E))*0.1*A))*(1-exp(-0.1*E)); + rsi0 = 1.26*(1-(0.00055*E))*(1+exp(-0.9163-(0.005*A))*exp(-0.09*E)); + asi = 0.8; + + vso = 0.0; + rso0 = 0.0; + aso = 0.0; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.4; + + return true; +} + +bool HyakutakePotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 111.4 - 0.173 * E + 14.9 * (N-Z) / A + 1.1 * Z / A3; + r0 = 1.21; + a = 0.76; + + vi = 0.0; + ri0 = 0.0; + ai = 0.0; + + vsi = 24.8 - 0.028 * E; + rsi0 = 1.17; + asi = 0.754 + 0.78 * (N-Z) / A; + + vso = 0.0; + rso0 = 0.0; + aso = 0.0; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.300; + + return true; +} + +bool BecchettiA3Potential(int A, int Z, double E, int Zproj){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + v = 165 - 0.17 * E - 6.4 * (N-Z) / A; + if( Zproj == 2 ) v = 151.9 - 0.17 * E + 50. * (N-Z) / A; + + r0 = 1.20; + a = 0.72; + + vi = 46.0 - 0.33 * E - 110. * (N-Z) / A; + if( Zproj == 2 ) vi = 41.7 - 0.33 * E + 44.0 * (N-Z) / A; + ri0 = 1.4; + ai = 0.84; + if( Zproj == 2 ) ai = 0.88; + + vsi = 0.0; + rsi0 = 0.0; + asi = 0.0; + + vso = 2.5; + rso0 = 1.2; + aso = 0.72; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.300; + + return true; +} + +//=============================== alpha + +bool SuAndHanPotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double vsiCOND = 27.5816 - 0.0797 * E + 48.0*(N-Z)/A; + double viCOND = -4.0174 + 0.1409 * E ; + + v = 175.0881 - 0.6236 * E + 0.0006*E*E + 30.*(N-Z)/A - 0.236 * Z/A3; + r0 = 1.3421; + a = 0.6578; + + vi = viCOND; if( viCOND < 0 ) vi = 0.0; + ri0 = 1.4259; + ai = 0.6578; + + vsi = vsiCOND; if (vsiCOND < 0 ) vsi = 0.0; + rsi0 = 1.2928; + asi = 0.6359; + + vso = 0.0; + rso0 = 1.2686; + aso = 0.85; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.350; + + return true; +} + +bool AvrigeanuPotential(int A, int Z, double E){ + + int N = A-Z; + double A3 = pow(A, 1./3.); + + double e3 = 23.6 + 0.181 * Z/A3; + double e2 = (2.59 + 10.4/A)*Z/(2.66+1.36*A3); + double e1 = -3.03 + 0.762 * A3 + 0.24 + e2; + + v = 116.5 + 0.337 * Z /A3 + 0.453*E; + if( E < e3 ) v = 168 + 0.733 * Z / A3 - 2.64 *E; + r0 = 0.00; + a = 0.00; + + vi = 2.73 - 2.88 * A3 + 1.11*E; + ri0 = 0.00; + ai = 0.00; + + vsi = 0.0; + rsi0 = 0.0; + asi = 0.0; + + vso = 0.0; + rso0 = 0.0; + aso = 0.0; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.300; + + return true; +} + +bool BassaniPicardPotential(int A, int Z, double E){ + + v = 207; + r0 = 1.3; + a = 0.65; + + vi = 28; + ri0 = 1.3; + ai = 0.52; + + vsi = 0.0; + rsi0 = 0.0; + asi = 0.0; + + vso = 0.0; + rso0 = 0.0; + aso = 0.0; + + vsoi = 0.0; + rsoi0 = 0.0; + asoi = 0.0; + + rc0 = 1.400; + + return true; +} + +bool CallPotential(std::string potName, int A, int Z, double E, int Zproj){ + bool okFlag = false; + + if( potName == "A") okFlag = AnCaiPotential(A, Z, E); + if( potName == "H") okFlag = HSSPotential(A, Z, E); + if( potName == "B") okFlag = BojowaldPotential(A, Z, E); + if( potName == "D") okFlag = DaehnickPotential(A, Z, E); + if( potName == "L") okFlag = LohrPotential(A, Z, E); + if( potName == "Q") okFlag = PereyPereyPotential(A, Z, E); + if( potName == "Z") okFlag = ZhangPangLouPotential(A, Z, E, Zproj); + + if( potName == "K") okFlag = KoningPotential(A, Z, E, Zproj); + if( potName == "V") okFlag = VarnerPotential(A, Z, E); + if( potName == "M") okFlag = MenetPotential(A, Z, E); + if( potName == "G") okFlag = BecchettiPotential(A, Z, E); + if( potName == "P") okFlag = PereyPotential(A, Z, E); + + if( potName == "x") okFlag = XuPotential(A, Z, E); + if( potName == "l") okFlag = LiangPotential(A, Z, E); + if( potName == "p") okFlag = PangPotential(A, Z, E, Zproj); + if( potName == "c") okFlag = LiLiangCaiPotential(A, Z, E); + if( potName == "t") okFlag = TrostPotential(A, Z, E); + if( potName == "h") okFlag = HyakutakePotential(A, Z, E); + if( potName == "b") okFlag = BecchettiA3Potential(A, Z, E, Zproj); + + if( potName == "s") okFlag = SuAndHanPotential(A, Z, E); + if( potName == "a") okFlag = AvrigeanuPotential(A, Z, E); + if( potName == "f") okFlag = BassaniPicardPotential(A, Z, E); + + if( potName == "X") okFlag = CustomXPotential(A, Z, E); + if( potName == "Y") okFlag = CustomYPotential(A, Z, E); + + //printf(" Potenital : %s | A : %d | Z : %d | E : %f\n", potName.c_str(), A, Z, E); + //PrintPotential(); + + return okFlag; +} diff --git a/cleopatra/ptolemy b/cleopatra/ptolemy new file mode 100755 index 0000000..29da4b0 Binary files /dev/null and b/cleopatra/ptolemy differ diff --git a/cleopatra/ptolemy_mac b/cleopatra/ptolemy_mac new file mode 100755 index 0000000..ae6ccfb --- /dev/null +++ b/cleopatra/ptolemy_mac @@ -0,0 +1,2 @@ +#!/bin/bash +docker run --rm --platform linux/amd64 -i -w $PWD tehatanlgov/ptolemy diff --git a/working/reactionConfig.txt b/working/reactionConfig.txt index bfde1b9..eb5f0d8 100644 --- a/working/reactionConfig.txt +++ b/working/reactionConfig.txt @@ -36,7 +36,7 @@ false //isDacay #0.000 1.0 1.0 0.01 #1.000 1.0 1.0 0.01 #2.000 1.0 1.0 0.01 -1.000 1.0 1.0 0.01 +0.000 1.0 1.0 0.01 IAEA + 10 0.01 #==================_reaction_for_2nd_Array_use_ony_when_2nd_array_used