MiniballSort
Loading...
Searching...
No Matches
mb_angle_fit.cc
Go to the documentation of this file.
1// My code include.
2#include "Settings.hh"
3#include "Calibration.hh"
4#include "MidasConverter.hh"
5#include "MbsConverter.hh"
6#include "EventBuilder.hh"
7#include "Reaction.hh"
8#include "Histogrammer.hh"
9#include "DataSpy.hh"
10#include "MbsFormat.hh"
11#include "MiniballGUI.hh"
12
13// C++ includes
14#include <iostream>
15
16// ROOT includes
17#include "TCanvas.h"
18#include "TGraph.h"
19#include "TMultiGraph.h"
20#include "TGraphErrors.h"
21#include "TF1.h"
22#include "TLegend.h"
23#include "Math/Functor.h"
24#include "Math/Factory.h"
25#include "Math/Minimizer.h"
26#include "Math/MinimizerOptions.h"
27
28class FitFunc {
29public:
30 int present[8][3][7];
31 double energy[8][3][7];
32 double err[8][3][7];
33 int cluster[8];
34 std::shared_ptr<MiniballSettings> myset;
35 std::shared_ptr<MiniballCalibration> mycal;
36 std::shared_ptr<MiniballReaction> myreact;
37 double user_z = 0;
38 double eref = 440.2;
39
41 for (int clu = 0; clu < 8; ++clu) {
42 cluster[clu] = 0;
43 for (int cry = 0; cry < 3; ++cry) {
44 for (int seg = 0; seg < 7; ++seg) {
45 present[clu][cry][seg] = 0;
46 energy[clu][cry][seg] = 0;
47 err[clu][cry][seg] = 0;
48 }
49 }
50 }
51 }
52
53 FitFunc(std::string settings_file, std::string reaction_file) {
54 for (int clu = 0; clu < 8; ++clu) {
55 cluster[clu] = 0;
56 for (int cry = 0; cry < 3; ++cry) {
57 for (int seg = 0; seg < 7; ++seg) {
58 present[clu][cry][seg] = 0;
59 energy[clu][cry][seg] = 0;
60 err[clu][cry][seg] = 0;
61 }
62 }
63 }
64
65 myset = std::make_shared<MiniballSettings>(settings_file);
66 myreact = std::make_shared<MiniballReaction>(reaction_file, myset);
67 }
68
69 void LoadExpEnergies(std::string energy_file) {
70 std::ifstream energyfile(energy_file);
71 int cl,cr,sg;
72 double en,er;
73 while (energyfile >> cl >> cr >> sg >> en >> er) {
74 present[cl][cr][sg] = 1;
75 energy[cl][cr][sg] = en;
76 err[cl][cr][sg] = er;
77 cluster[cl] = 1;
78 }
79 energyfile.close();
80 }
81
82 double operator() (const double *p) {
83 //change angles
84 //p[0] = beta
85 //p[1] = theta1, p[2] = phi1, p[3] = alpha1, p[4] = r1,
86 //p[5] = theta2, p[6] = phi2, p[7] = alpha2, p[8] = r2, etc.
87 int indx = 1;
88 for (int clu=0; clu<8; ++clu) {
89 if (cluster[clu] == 0) { continue; }
90 myreact->SetupCluster(clu, p[indx], p[indx+1], p[indx+2], p[indx+3], user_z);
91 indx += 4;
92 }
93
94 double chisq = 0;
95
96 for (int clu = 0; clu < 8; ++clu) {
97 for (int cry = 0; cry < 3; ++cry) {
98 for (int seg = 0; seg < 7; ++seg) {
99 if (present[clu][cry][seg] == 0) { continue; }
100 double theta = myreact->GetGammaTheta(clu ,cry, seg);
101 double beta = p[0];
102 double corr = 1. - beta * std::cos(theta);
103 corr *= 1./(std::sqrt(1.-std::pow(beta, 2.)));
104 double edop = eref/corr;
105 chisq += std::pow((energy[clu][cry][seg] - edop)/err[clu][cry][seg], 2);
106 }
107 }
108 }
109 return chisq;
110 }
111
112};
113
114
115int main( int argc, char *argv[] ) {
116
117 if( argc < 4 ) {
118 std::cout << "usage: mb_angle_fit <settings_file> <reaction_file> <centroids_file>" << std::endl << std::endl;
119 std::cout << "where centroids_file contains the un-doppler corrected centroids for cores gated on each segment" << std::endl;
120 std::cout << "for some reference transition. The format for centroids_file is" << std::endl << std::endl;
121 std::cout << "cluster crystal segment energy uncertainty" << std::endl << std::endl;
122 std::cout << "beta (v/c), as well as the theta, phi, alpha, and R values for each detector present are varied." << std::endl;
123 std::cout << "The reference energy is set at 440.2 keV, this can be varied but will need to be recompiled." << std::endl;
124 return -1;
125 }
126 FitFunc ff(argv[1], argv[2]);
127 ff.LoadExpEnergies(argv[3]);
128 ff.eref = 440.2;
129
130 TFile *file = new TFile("MiniballAngleFits.root", "recreate");
131
132 // set up parameters, bounds
133 std::vector<double> pars(1+7*4);
134 std::vector<std::string> names(1+7*4);
135 std::vector<double> LL(1+7*4);
136 std::vector<double> UL(1+7*4);
137
138 pars[0] = ff.myreact->GetBeta();
139 names[0] = "beta";
140 LL[0] = 0.01;
141 UL[0] = 0.5;
142 //set initial guesses
143 TEnv *config = new TEnv( argv[2] );
144 int indx = 1;
145 int nClusters = 0;
146 for( unsigned int clu=0; clu<8; ++clu ) {
147 //skip clusters for which we have no data
148 if (ff.cluster[clu] == 0) { continue; }
149 ++nClusters;
150 //get starting guesses from the reaction file
151 pars[indx] = config->GetValue( Form( "MiniballCluster_%d.Theta", clu ), 0. );
152 pars[indx+1] = config->GetValue( Form( "MiniballCluster_%d.Phi", clu ), 0. );
153 pars[indx+2] = config->GetValue( Form( "MiniballCluster_%d.Alpha", clu ), 0. );
154 pars[indx+3] = config->GetValue( Form( "MiniballCluster_%d.R", clu ), 0. );
155
156 names[indx] = "theta"+std::to_string(clu);
157 names[indx+1] = "phi"+std::to_string(clu);
158 names[indx+2] = "alpha"+std::to_string(clu);
159 names[indx+3] = "r"+std::to_string(clu);
160
161 //these may cause issue if we need to cross over the 0/360 boundary
162 LL[indx] = 0.0;
163 LL[indx+1] = 0.0;
164 LL[indx+2] = 0.0;
165 LL[indx+3] = 10.0;
166
167 UL[indx] = 180.0;
168 UL[indx+1] = 360.0;
169 UL[indx+2] = 360.0;
170 UL[indx+3] = 400.0;
171
172 indx += 4;
173 }
174
175 //create minimizer
176 ROOT::Math::Minimizer *min =
177 ROOT::Math::Factory::CreateMinimizer("Minuit2", "Migrad");
178
179 ROOT::Math::Functor f_init(ff,4*nClusters+1);
180
181 min->SetErrorDef(1.);
182 min->SetMaxFunctionCalls(1000);
183 min->SetMaxIterations(1000);
184 min->SetTolerance(0.001);
185 min->SetPrecision(1e-6);
186 min->SetFunction(f_init);
187
188 for( unsigned int i = 0; i < pars.size(); ++i ) {
189 min->SetLimitedVariable(i, names.at(i), pars.at(i), 0.0001, LL.at(i), UL.at(i));
190 min->SetVariableStepSize(i, 1.0);
191 }
192 min->SetVariableStepSize(0, 0.001);
193
194 min->Minimize();
195
196 min->PrintResults();
197 //minimization finished
198
199 //copy results into reaction object
200 indx = 1;
201 for( unsigned int clu = 0; clu < 8 ; ++clu ) {
202 if (ff.cluster[clu] == 0) { continue; }
203 ff.myreact->SetupCluster(clu, min->X()[indx], min->X()[indx+1], min->X()[indx+2], min->X()[indx+3], 0.0);
204 indx += 4;
205 }
206
207 //print fit + residuals to pdf
208 TGraphErrors *engraph = new TGraphErrors();
209 engraph->SetName("engraph; Experimental energies; Channel index; Energy [keV]");
210 TGraph *calcgraph = new TGraph();
211 calcgraph->SetName("calcgraph; Calculated energies; Channel index; Energy [keV]");
212 TGraphErrors *resgraph = new TGraphErrors();
213 resgraph->SetName("resgraph; Residuals; Channel index; Energy [keV]"");");
214 TGraphErrors *corrgraph = new TGraphErrors();
215 corrgraph->SetName("corrgraph; Doppler-corrected energies; Channel index; Energy [keV]"");");
216
217
218 engraph->GetXaxis()->SetTitle("Channel index");
219 engraph->GetYaxis()->SetTitle("Energy [keV]");
220
221 corrgraph->GetXaxis()->SetTitle("Channel index");
222 corrgraph->GetYaxis()->SetTitle("Doppler-corrected energy [keV]");
223
224 resgraph->GetXaxis()->SetTitle("Channel index");
225 resgraph->GetYaxis()->SetTitle("Energy Residual [keV]");
226
227 indx = 0;
228 for( unsigned int clu = 0; clu < 8; ++clu ) {
229 for( unsigned int cry = 0; cry < 3; ++cry ) {
230 for( unsigned int seg = 0; seg < 7; ++seg ) {
231 ++indx;
232 if (ff.present[clu][cry][seg] == 0) { continue; }
233 double beta = min->X()[0];
234 double theta = ff.myreact->GetGammaTheta(clu ,cry, seg);
235 double corr = 1. - beta * std::cos(theta);
236 corr *= 1./(std::sqrt(1.-std::pow(beta, 2.)));
237 double edop = ff.eref/corr;
238
239 engraph->AddPoint(indx, ff.energy[clu][cry][seg]);
240 engraph->SetPointError(engraph->GetN()-1, 0, ff.err[clu][cry][seg]);
241
242 corrgraph->AddPoint(indx, ff.energy[clu][cry][seg]*corr);
243 corrgraph->SetPointError(engraph->GetN()-1, 0, ff.err[clu][cry][seg]);
244
245 calcgraph->AddPoint(indx, edop);
246 resgraph->AddPoint(indx, edop - ff.energy[clu][cry][seg]);
247 resgraph->SetPointError(resgraph->GetN()-1, 0, ff.err[clu][cry][seg]);
248 }
249 }
250 }
251
252 TCanvas *c1 = new TCanvas();
253 engraph->SetMarkerStyle(kFullCircle);
254 engraph->SetMarkerSize(0.5);
255 engraph->SetMarkerColor(kRed);
256 engraph->SetLineColor(kRed);
257 engraph->Draw("AP");
258 engraph->Write();
259 calcgraph->SetMarkerStyle(kFullCircle);
260 calcgraph->SetMarkerSize(0.5);
261 calcgraph->Draw("P");
262 calcgraph->Write();
263
264 TLegend *leg = new TLegend(0.1,0.75,0.3,0.9);
265 leg->AddEntry(engraph, "Experimental energies");
266 leg->AddEntry(calcgraph, "Calculated energies");
267 leg->Draw();
268
269 c1->Print("position_cal.pdf(");
270
271 resgraph->SetMarkerStyle(kFullCircle);
272 resgraph->SetMarkerSize(0.5);
273 resgraph->Draw("AP");
274 resgraph->Write();
275 TF1 *func = new TF1("func", "[0]", 0, 168);
276 func->SetParameter(0, 0.0);
277 func->Draw("same");
278
279 c1->Print("position_cal.pdf");
280
281 corrgraph->SetMarkerStyle(kFullCircle);
282 corrgraph->SetMarkerSize(0.5);
283 corrgraph->Draw("AP");
284 corrgraph->Write();
285 func->SetParameter(0, ff.eref);
286 func->Draw("same");
287
288 c1->Print("position_cal.pdf");
289
290 //print theta-phi map of crystals + segments
291
292 int colors[8] = {632, 416, 600, 400, 616, 432, 800, 900};
293
294 TMultiGraph *tp_mg = new TMultiGraph();
295 tp_mg->SetName("theta_phi_map");
296 TGraph *theta_phi[8][3];
297 for( unsigned int clu = 0; clu < 8; ++clu ) {
298 if (ff.cluster[clu] == 0) { continue; }
299 for( unsigned int cry = 0; cry < 3; ++cry ) {
300 theta_phi[clu][cry] = new TGraph();
301 for( unsigned int seg = 0; seg < 7; ++seg ) {
302 double theta = ff.myreact->GetGammaTheta(clu,cry,seg)*180./TMath::Pi();
303 double phi = ff.myreact->GetGammaPhi(clu,cry,seg)*180./TMath::Pi();
304 theta_phi[clu][cry]->AddPoint(theta, phi);
305 }
306 theta_phi[clu][cry]->SetMarkerSize(1.0);
307 theta_phi[clu][cry]->SetMarkerStyle(kFullCircle);
308 theta_phi[clu][cry]->SetMarkerColor(colors[clu]+cry);
309 tp_mg->Add(theta_phi[clu][cry]);
310 }
311 }
312 tp_mg->Draw("AP");
313 tp_mg->GetXaxis()->SetLimits(0,180);
314 tp_mg->GetYaxis()->SetLimits(-180,180);
315 tp_mg->GetXaxis()->SetTitle("Reaction Theta [deg]");
316 tp_mg->GetYaxis()->SetTitle("Reaction Phi [deg]");
317 tp_mg->Write();
318 c1->Print("position_cal.pdf");
319
320 TMultiGraph *xy_f_mg = new TMultiGraph();
321 TMultiGraph *xy_b_mg = new TMultiGraph();
322 TMultiGraph *xz_r_mg = new TMultiGraph();
323 TMultiGraph *xz_l_mg = new TMultiGraph();
324 xy_f_mg->SetName("xy_f_mg");
325 xy_b_mg->SetName("xy_b_mg");
326 xz_r_mg->SetName("xz_r_mg");
327 xz_l_mg->SetName("xz_l_mg");
328 TGraph *xy_f[8][3];
329 TGraph *xy_b[8][3];
330 TGraph *xz_l[8][3];
331 TGraph *xz_r[8][3];
332 for( unsigned int clu = 0; clu < 8; ++clu ) {
333 if (ff.cluster[clu] == 0) { continue; }
334 for( unsigned int cry = 0; cry < 3; ++cry ) {
335 xy_f[clu][cry] = new TGraph();
336 xy_b[clu][cry] = new TGraph();
337 xz_r[clu][cry] = new TGraph();
338 xz_l[clu][cry] = new TGraph();
339 for( unsigned int seg = 0; seg < 7; ++seg ) {
340 double x = ff.myreact->GetGammaX(clu,cry,seg);
341 double y = ff.myreact->GetGammaY(clu,cry,seg);
342 double z = ff.myreact->GetGammaZ(clu,cry,seg);
343 if (z > 0) {
344 xy_f[clu][cry]->AddPoint(y,x);
345 }
346 else {
347 xy_b[clu][cry]->AddPoint(y,x);
348 }
349
350 if (y > 0) {
351 xz_r[clu][cry]->AddPoint(z,x);
352 }
353 else {
354 xz_l[clu][cry]->AddPoint(z,x);
355 }
356 }
357 xy_f[clu][cry]->SetMarkerSize(1.0);
358 xy_f[clu][cry]->SetMarkerStyle(kFullCircle);
359 xy_f[clu][cry]->SetMarkerColor(colors[clu]+cry);
360 xy_b[clu][cry]->SetMarkerSize(1.0);
361 xy_b[clu][cry]->SetMarkerStyle(kFullCircle);
362 xy_b[clu][cry]->SetMarkerColor(colors[clu]+cry);
363 xz_r[clu][cry]->SetMarkerSize(1.0);
364 xz_r[clu][cry]->SetMarkerStyle(kFullCircle);
365 xz_r[clu][cry]->SetMarkerColor(colors[clu]+cry);
366 xz_l[clu][cry]->SetMarkerSize(1.0);
367 xz_l[clu][cry]->SetMarkerStyle(kFullCircle);
368 xz_l[clu][cry]->SetMarkerColor(colors[clu]+cry);
369
370 xy_f_mg->Add(xy_f[clu][cry]);
371 xy_b_mg->Add(xy_b[clu][cry]);
372 xz_r_mg->Add(xz_r[clu][cry]);
373 xz_l_mg->Add(xz_l[clu][cry]);
374 }
375 }
376 xy_f_mg->Draw("AP");
377 xy_f_mg->GetYaxis()->SetTitle("x [mm]");
378 xy_f_mg->GetXaxis()->SetTitle("y [mm]");
379 xy_f_mg->Write();
380 c1->Print("position_cal.pdf");
381
382 xy_b_mg->Draw("AP");
383 xy_b_mg->GetYaxis()->SetTitle("x [mm]");
384 xy_b_mg->GetXaxis()->SetTitle("y [mm]");
385 xy_b_mg->Write();
386 c1->Print("position_cal.pdf");
387
388 xz_r_mg->Draw("AP");
389 xz_r_mg->GetYaxis()->SetTitle("x [mm]");
390 xz_r_mg->GetXaxis()->SetTitle("z [mm]");
391 xz_r_mg->Write();
392 c1->Print("position_cal.pdf");
393
394 xz_l_mg->Draw("AP");
395 xz_l_mg->GetYaxis()->SetTitle("x [mm]");
396 xz_l_mg->GetXaxis()->SetTitle("z [mm]");
397 xz_l_mg->Write();
398 c1->Print("position_cal.pdf)");
399
400 file->Write();
401 file->Close();
402
403 //print final results to terminal
404 std::cout << "fitted beta = " << min->X()[0] << std::endl;
405 indx = 1;
406 printf(" theta phi alpha R\n");
407 for( unsigned int clu = 0; clu < 8 ; ++clu ) {
408 if (ff.cluster[clu] == 0) { continue; }
409 printf("Cl%i %6.2f %6.2f %6.2f %6.2f\n", clu, min->X()[indx], min->X()[indx+1], min->X()[indx+2], min->X()[indx+3]);
410 indx += 4;
411 }
412 std::cout << std::endl << std::endl;
413 indx = 1;
414 for( unsigned int clu = 0; clu < 8 ; ++clu ) {
415 if (ff.cluster[clu] == 0) { continue; }
416 printf("MiniballCluster_%d.Theta %6.2f\n", clu, min->X()[indx]);
417 printf("MiniballCluster_%d.Phi %6.2f\n", clu, min->X()[indx+1]);
418 printf("MiniballCluster_%d.Alpha %6.2f\n", clu, min->X()[indx+2]);
419 printf("MiniballCluster_%d.R %6.2f\n", clu, min->X()[indx+3]);
420 indx += 4;
421 }
422
423}
424
double energy[8][3][7]
int cluster[8]
std::shared_ptr< MiniballSettings > myset
double eref
double operator()(const double *p)
std::shared_ptr< MiniballReaction > myreact
FitFunc(std::string settings_file, std::string reaction_file)
void LoadExpEnergies(std::string energy_file)
double user_z
double err[8][3][7]
std::shared_ptr< MiniballCalibration > mycal
int present[8][3][7]
int main(int argc, char *argv[])