GRSISort
Created by P.C. Bender
Developement Team: P.C. Bender, R. Dunlop, V. Bildstein
An extension of the ROOT analysis Framework
Deadtime.cxx
Go to the documentation of this file.
1 // To compile:
2 // Note: GRSISort looks for .cxx extensions when compiling (for example it looks in the myAnalysis directory)
3 // Alternatively you may use the following to compile:
4 // g++ myanalysis.cxx -o myanalysis -std=c++0x -I$GRSISYS/GRSISort/include/ `grsi-config --cflags --all-libs --root`
5 
6 #include <fstream>
7 #include <cstdlib>
8 #include <cstring>
9 #include <algorithm>
10 #include <iostream>
11 #include <functional>
12 #include <iomanip>
13 #include <string>
14 #include <cmath>
15 #include <cstdio>
16 #include <cmath> /* round, floor, ceil, trunc */
17 #include <ctime>
18 
19 #include "TF1.h"
20 #include "TMath.h"
21 #include "TH1.h"
22 #include "TH1F.h"
23 #include "THStack.h"
24 #include "TString.h"
25 #include "TCanvas.h"
26 #include "TPad.h"
27 #include "TFile.h"
28 //#include "TFileIter.h"
29 #include "TKey.h"
30 #include "TTree.h"
31 #include "TH2F.h"
32 #include "TROOT.h"
33 #include "TPPG.h"
34 #include "TScaler.h"
35 #include "TApplication.h"
36 #include "TLeaf.h"
37 
38 #ifndef __CINT__
39 #include "TGriffin.h"
40 #include "TSceptar.h"
41 #endif
42 
43 void Printaddress(int* channel);
44 void MakeSpectra(const char*& filename, int& prog, const char*& fname, int& nsclr, int& ncycle, double* rate,
45  int* channel, int& index, int* trun, double& thresh);
46 void CheckFile(const char*& fname);
47 void DoAnalysis(const char*& fname, int& nfile, double* rate, int& nsclr, int& patlen, int& ncycle, int* trun,
48  double& eor, const char*& hname, const char*& iname, const char*& jname, const char*& kname,
49  const char*& lname, const char*& mname, const char*& nname, int& nscaler);
50 
51 int main(int argc, char* argv[])
52 {
53  TApplication theApp("Analysis", &argc, argv);
54  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~USER
55  //INPUTS
56  std::ifstream filelist("/home/mbowry/Documents/ROOT/Backup/newfilelist_hs.txt"); // input file(s) DATA
57  std::ifstream ODBlist("/home/mbowry/Documents/ROOT/Backup/ODBlist_hs.txt"); // input file(s) ODB (runinfo)
58  const char* fname = "viewscaler.root"; // output file (scaler spectra)
59  const char* hname = "random_counts.txt"; // output file (frequency histograms, source)
60  const char* iname = "combined_counts.txt"; // output file (frequency histograms, source+pulser)
61  const char* jname = "random_seed.txt"; // output file (check random number generation)
62  const char* kname = "RESULTS.txt"; // output file (deadtime results)
63  const char* lname = "asymmetric_error.txt"; // output file (error combination histogram)
64  const char* mname = "random_deadtime.txt"; // output file (random deadtime histogram)
65  const char* nname = "accepted_rand.txt"; // output file (accepted random rate histogram)
66  int nsclr = 9; // total number of pulser inputs
67  int addr[9] = {0x0000, 0x000d, 0x0101, 0x0107, 0x020b,
68  0x020c, 0x0302, 0x030c, 0x030d}; // addresses with pulser inputs
69  double freq[4] = {2.e3, 5.e3, 1.e4, 2.e4}; // precision pulser rates (2,5,10,20 kHz)
70  int patlen = 10; // pattern length in seconds
71  int ncycle = 1; // read out period of scalers (seconds);
72  int scaleri = 0; // scaler# START
73  int scalerf = 3; // scaler# END (0->3 = all scalers)
74  double thresh = 0.3; // threshold for rejection of spurious scaler events
75  double eor = 0.3; // threshold for end-of-run cut off
76  int specoff = 1; // temporary flag: if =1, only analysis performed
77  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~DEFINITIONS
78  int tdiff[4] = {0, 0, 0, 0}; // run time extracted from ODB
79  int* td = &tdiff[0];
80  int* p = &addr[0];
81  double* q = &freq[0];
82  int counter = 0;
83  int nds = 0;
84  int nscaler = 0;
85  int len = 70;
86  auto* line = new char[len];
87  auto* odb = new char[len];
88  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*
89  if(!(filelist.is_open())) {
90  std::cerr<<"Failed to open filelist. Check path. "<<std::endl;
91  exit(EXIT_FAILURE);
92  } else if(!(ODBlist.is_open())) {
93  std::cerr<<"Failed to open ODBlist. Check path. "<<std::endl;
94  exit(EXIT_FAILURE);
95  }
96  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*
97  // in the ODB file there are the lines:
98  // Start time binary = DWORD : 1445453916
99  // Stop time binary = DWORD : 1445454042
100  // the difference (stop-start) equals the run time in seconds. Useful for histogram binning purposes.
101  size_t posa;
102  size_t posb;
103  int sub = 28;
104  const char* starttime = "Start time binary";
105  const char* stoptime = "Stop time binary";
106  int tstart = 0;
107  int tend = 0;
108  int runtime = 0;
109  int nppg = 0;
110  std::string odbline;
111  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*
112  int line_count = std::count( // read in number of lines(files)
113  std::istreambuf_iterator<char>(filelist), std::istreambuf_iterator<char>(), '\n');
114  printf(DMAGENTA "-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/" RESET_COLOR
115  "\n");
116  printf(DGREEN "Started Deadtime v1 / 04-Mar-2016 / mbowry@triumf.ca" RESET_COLOR "\n");
117  printf(DBLUE "Calculates deadtime on a channel-by-channel basis using precision scaler data" RESET_COLOR "\n");
118  printf(DBLUE "Sub-runs must be merged (e.g. using gadd) before running this program" RESET_COLOR "\n");
119  printf(DBLUE "A list of fragments (run files) and their corresponding ODB files must be provided" RESET_COLOR "\n");
120  printf(DGREEN "Number of files loaded: %i" RESET_COLOR "\n", line_count);
121  printf(DBLUE "Spectra are saved in %s" RESET_COLOR "\n", fname);
122  printf(DBLUE "Deadtime results are recorded in %s" RESET_COLOR "\n", kname);
123  printf(DMAGENTA "-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/" RESET_COLOR
124  "\n");
125  printf(DBLUE "Working, be patient .. " RESET_COLOR "\n");
126  printf("\n");
127  filelist.clear();
128  filelist.seekg(0, std::ios::beg);
129  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*
130  Printaddress(p); // Credit to to E.Kwan for this part
131  p = &addr[0];
132  while(counter < line_count) {
133  filelist.getline(line, len, '\n');
134  const char* filename = line;
135  //-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/ODB STUFF
136  ODBlist.getline(odb, len, '\n'); //<retreive ODB file name ('odb' assigned here)
137  std::ifstream InFile(odb); //<set the I/O stream to the current file
138  while(InFile.good()) {
139  getline(InFile, odbline);
140  posa = odbline.find(starttime);
141  posb = odbline.find(stoptime);
142  if(posa != std::string::npos && odbline.size() > static_cast<size_t>(sub)) {
143  odbline = odbline.substr(sub);
144  tstart = std::stoi(odbline, nullptr, 10);
145  } else if(posb != std::string::npos && odbline.size() > static_cast<size_t>(sub - 1)) {
146  odbline = odbline.substr((sub - 1));
147  tend = std::stoi(odbline, nullptr, 10);
148  }
149  }
150  runtime = tend - tstart;
151  nppg = floor(runtime / patlen);
152  tdiff[counter] = runtime;
153  std::cout<<"\n";
154  if(runtime <= 600) {
155  printf(DBLUE "Read ODB %s : run time = %i seconds / %i transitions" RESET_COLOR "\n", odb, runtime, nppg);
156  } else if(runtime > 600) {
157  printf(DBLUE "Read ODB %s : run time = %i minutes / %i transitions" RESET_COLOR "\n", odb, (runtime / 60),
158  nppg);
159  }
160  //-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-
161  for(int index = scaleri; index < (scalerf + 1); index++) {
162  if(specoff == 1) {
163  printf(DMAGENTA "Creation of histograms suppressed .. performing analysis step only." RESET_COLOR "\n");
164  } else {
165  MakeSpectra(filename, counter, fname, nsclr, ncycle, q, p, index, td, thresh);
166  }
167  p = &addr[0];
168  nds += 1;
169  }
170  counter++;
171  q++; // these two lines had a de-reference which makes no sense (and makes the compiler complain)
172  td++; // unless this was meant to increment the value the pointers are pointing to (in which case it should read
173  // (*q)++); VB
174  tstart = tend = 0;
175  }
176  delete[] line;
177  delete[] odb;
178  q = &freq[0];
179  td = &tdiff[0];
180  if(counter > 0) {
181  nscaler = nds / counter;
182  }
183  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*
184  CheckFile(fname);
185  DoAnalysis(fname, line_count, q, nsclr, patlen, ncycle, td, eor, hname, iname, jname, kname, lname, mname, nname,
186  nscaler);
187  printf(DBLUE "Spectra are saved in %s" RESET_COLOR "\n", fname);
188  printf(DBLUE "Deadtime results are %s" RESET_COLOR "\n", kname);
189  printf(DBLUE "Done. Control-c to exit." RESET_COLOR "\n");
190  theApp.Run(kTRUE);
191 
192  return EXIT_SUCCESS;
193 }
194 
195 void Printaddress(int* channel)
196 {
197  printf(DBLUE "Addresses with both source and pulser inputs:" RESET_COLOR "\n");
198  for(int i = 0; i < 10; ++i) {
199  printf(DBLUE "%04x " RESET_COLOR, *channel);
200  channel++;
201  }
202  printf("\n");
203 }
204 
205 void MakeSpectra(const char*& filename, int& prog, const char*& fname, int& nsclr, int& ncycle, double*, int* channel,
206  int& index, int* trun, double&)
207 {
208  int nsc = nsclr;
209 
210  // define spectra
211  auto** grif = new TH1D*[nsc];
212  // define file pointer
213  TFile* vs;
214 
215  // make spectra
216  auto* rf = new TFile(filename, "read");
217  TTree* maple = dynamic_cast<TTree*>(rf->Get("ScalerTree")); // Scaler data
218 
219  int nofBins = *trun / ncycle;
220  double xaxis = 0;
221  double yaxis = 0;
222  double prev = 0;
223  double xpast = 0;
224  int j = 0;
225  int k = 0;
226  double clk = 20e-9; // 2 clock tics (20ns)
227 
228  while(j < nsc) {
229  grif[j] =
230  new TH1D(Form("grif%d_0x%04x_%d", prog, *channel, index),
231  Form("Address 0x%04x, scaler %i vs time in cycle; time [s]; counts/%d s", *channel, index, ncycle),
232  nofBins, 0., *trun);
233  j++;
234  channel++; // used to have a de-reference, see comments above; VB
235  }
236 
237  TScalerData* scaler = nullptr;
238  TScaler(maple).Clear();
239  maple->SetBranchAddress("TScalerData", &scaler);
240  Long64_t nentries = maple->GetEntries();
241 
242  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*
243  // Build histograms directly from trees
244  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*
245  if(prog == 0 && index == 0) {
246  vs = new TFile(fname, "recreate");
247  } else {
248  vs = new TFile(fname, "update");
249  }
250  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*
251  for(int i = 0; i < nsc; i++) {
252  channel--; // used to have a de-reference, see comments above; VB
253  }
254  while(k < nsc) {
255  for(Long64_t e = 0; e < nentries; e++) {
256  maple->GetEntry(e);
257  if(scaler->GetAddress() == static_cast<UInt_t>(*channel)) {
258  xaxis = (scaler->GetTimeStamp() / 1e9);
259  // we check both the value of the scaler and the timestamp (ts difference should be = readout time)
260  if(prev != 0 && prev < scaler->GetScaler(index) && (xaxis - xpast) <= (double(ncycle) + clk)) {
261  yaxis = (scaler->GetScaler(index) - prev);
262  grif[k]->Fill(xaxis, yaxis);
263  }
264  prev = scaler->GetScaler(index);
265  xpast = xaxis;
266  }
267  }
268  k++;
269  channel++;
270  prev = xpast = 0;
271  }
272 
273  printf(DGREEN "Created histograms for scaler %i : file = %s" RESET_COLOR "\n", index, filename);
274  // write hists
275  for(int i = 0; i < nsc; i++) {
276  grif[i]->Write();
277  }
278  vs->Close();
279 }
280 
281 void CheckFile(const char*& fname)
282 {
283  TFile f(fname);
284  if(f.IsZombie()) {
285  printf("\n");
286  printf(DRED "Error opening ROOT file %s" RESET_COLOR "\n", fname);
287  exit(-1);
288  } else {
289  printf("\n");
290  printf(DBLUE "ROOT file %s opens with no problems.." RESET_COLOR "\n", fname);
291  }
292  return;
293 }
294 
295 void DoAnalysis(const char*& fname, int& nfile, double* rate, int& nsclr, int& patlen, int&, int* trun, double& eor,
296  const char*& hname, const char*& iname, const char*& jname, const char*& kname, const char*& lname,
297  const char*& mname, const char*& nname, int& nscaler)
298 {
299 
300  auto* vs = new TFile(fname, "read");
301  std::ofstream ofile;
302  ofile.open("diagnostic.txt");
303  FILE* random = fopen(hname, "w");
304  FILE* combine = fopen(iname, "w");
305  FILE* rng = fopen(jname, "w");
306  FILE* deadtime = fopen(kname, "w");
307  FILE* asymerror = fopen(lname, "w");
308  FILE* randdt = fopen(mname, "w");
309  FILE* randw = fopen(nname, "w");
310  ofile.precision(4);
311 
312  int nsc = nsclr;
313  int cnt = 0;
314  int ppgstat[2] = {0, 0};
315  // generate random seed from system time for use in error analysis
316  time_t timer;
317  timer = time(nullptr);
318  srand(timer);
319 
320  TFile f(fname);
321  TIter next(f.GetListOfKeys());
322  TKey* key;
323  auto** spec = new TH1D*[nfile * (nsc * nscaler)];
324 
325  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~USER EDITABLE
326  // limits for deadtime matrices [us]
327  // NOTE: The order of the limits (rp1,rp2 etc.) MUST be identical to the file order
328  double rp1[8] = {-15, 15, -15, 15, 0, 20, 85, 115}; // 2kHz, scaler0-3
329  double rp2[8] = {-15, 15, -15, 15, 0, 20, 85, 115}; // 5kHz, scaler0-3
330  double rp3[8] = {-15, 15, -15, 15, 0, 20, 170, 230}; // 10kHz, scaler0-3
331  double rp4[8] = {-15, 15, -15, 15, 0, 20, 200, 300}; // 20kHz, scaler0-3
332  double* lowrtau = &rp1[0]; // internal pointers: points to correction coefficients in each array
333  double* upprtau = &rp1[1]; //
334  int cflag = 0; // counter
335  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~
336 
337  std::cout<<"\n";
338  // output headers
339  fprintf(deadtime, "#np=pulser,nr=source,nrp=source+pulser,tau=deadtime,erb=FWHM est. err,erf=full range "
340  "err,erp=standard err propagation");
341  fprintf(deadtime, "\n");
342  fprintf(deadtime, "%s\t\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", "#spec", "chan", "np", "nr", "+/-",
343  "nrp", "+", "-", "tau", "+erb", "-erb", "+erf", "-erf", "+/-erp");
344  fprintf(deadtime, "\n");
345  fprintf(deadtime, "%s\t\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", "#", "-", "kHz", "kHz", "kHz", "kHz",
346  "kHz", "kHz", "us", "us", "us", "us", "us", "us");
347  fprintf(deadtime, "\n");
348  fprintf(randdt, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", "#rc", "rr", "rc-rr", "rtau", "lim1", "lim2", "flag",
349  "err(rc-rr)");
350  fprintf(randdt, "\n");
351 
352  while((key = dynamic_cast<TKey*>(next())) != nullptr) {
353  int numpat = floor(*trun / patlen); // minimum number of expected transitions based on run time
354  const char* sname = key->GetName();
355  spec[cnt] = dynamic_cast<TH1D*>(vs->Get(sname));
356 
357  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~*~*~*variables
358  double wcomb = 0;
359  double ncomb = 0;
360  double rcomb = 0;
361  double sdcomb = 0;
362  double wrand = 0;
363  double nrand = 0;
364  double rrand = 0;
365  double sdrand = 0;
366  double sum = 0, sumc = 0;
367  double maxl = 0;
368  double minl = 1e6;
369  double x = 0;
370  double w = 0;
371  double diff = 0;
372  double rcmin = 0;
373  int minb = 0;
374  double lbd;
375  double ubd;
376  double rmax = 0;
377  int flag = 0;
378  double z = 0;
379  double y = 0;
380  double v = 0;
381  double dz = 0;
382  double dv = 0;
383  double d2z = 0;
384  int fbin = 10;
385  double max = 0;
386  double dlim = 0;
387  int nt = 0;
388  int ord = 0;
389  int sref = 0;
390  int pref = 0;
391  int chop = 2; //'chop'= ignore first/last two bins of each pattern
392  auto** ppg = new int*[numpat];
393  for(int i = 0; i < numpat; ++i) {
394  ppg[i] = new int[2];
395  };
396  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*find PPG transition boundaries
397  // run through and find boundaries (pulser on/off etc.)
398  //'ord' defines increase (1) or decrease (0) in rate
399  int xbins = *trun;
400  auto** trans = new double*[xbins];
401  for(int i = 0; i < xbins; ++i) {
402  trans[i] = new double[3];
403  };
404  auto** freq = new double*[fbin];
405  for(int i = 0; i < fbin; ++i) {
406  freq[i] = new double[2];
407  };
408  auto** bnd = new int*[numpat];
409  for(int i = 0; i < numpat; ++i) {
410  bnd[i] = new int[2];
411  };
412  // initialise the bnd matrix (prevents the program from hanging up later!)
413  for(int i = 0; i < numpat; i++) {
414  bnd[i][0] = 0;
415  bnd[i][1] = 0;
416  }
417  // find change in counts between bins
418  // we always look at the relative change transitioning 'up' (OFF->ON), even if we are transitioning 'down'
419  // we don't want to misidentify gaps in spectrum as transitions! (& vice versa)
420  for(int i = 0; i <= xbins; i++) {
421  x = spec[cnt]->GetBinContent(i);
422  if(w > 0 && x > 0 && x > w) {
423  diff = ((x - w) / w);
424  ord = 1;
425  } else if(w > 0 && x > 0 && x < w) {
426  diff = ((w - x) / x);
427  ord = 0;
428  } else if(x > 0 && w == 0) {
429  // this statement deals with gaps in spectrum
430  // we look at earlier bins and calculate difference compared to the current bin (up to t=0)
431  for(int j = (i - 1); j >= 0; j--) {
432  z = spec[cnt]->GetBinContent(j);
433  if(z > 0 && x > z) {
434  diff = ((x - z) / z);
435  ord = 1;
436  break;
437  } else if(z > 0 && x < z) {
438  diff = ((z - x) / x);
439  ord = 0;
440  break;
441  // what if there are no earlier bins >0? (rare, unless at very start of run)
442  }
443  }
444  } else if(w > 0 && x == 0) {
445  // we look at later bins and calculate difference compared to the current bin (up to t=trun)
446  // what if there are no later bins with counts >0? (rare, unless at very end of run)
447  for(int j = (i + 1); j <= *trun; j++) {
448  z = spec[cnt]->GetBinContent(j);
449  if(z > 0) {
450  diff = 0;
451  break;
452  }
453  }
454  if(z == 0) {
455  for(int j = *trun; j >= (*trun - (int(0.7 * patlen))); j--) {
456  y = spec[cnt]->GetBinContent(j);
457  if(y > 0 && v > 0) {
458  dz = (abs(y - v) / v);
459  if(dz > 0 && dv > 0) {
460  d2z = abs(dz - dv);
461  }
462  }
463  if(d2z > eor) {
464  flag += 1;
465  diff = 0;
466  break;
467  }
468  v = spec[cnt]->GetBinContent(j);
469  dv = dz;
470  }
471  if(flag == 0) {
472  diff = (0.9 * rmax);
473  }
474  flag = 0;
475  }
476  } else if(x == w) {
477  diff = 0;
478  } else if(x == 0 && w == 0) {
479  diff = 0;
480  }
481  trans[i][0] = i;
482  trans[i][1] = diff;
483  trans[i][2] = ord;
484  w = spec[cnt]->GetBinContent(i);
485  if(abs(diff) > rmax) {
486  rmax = diff;
487  }
488  }
489  rmax = rmax + (0.1 * rmax);
490  // set up the frequency histogram
491  for(int i = 0; i <= xbins; i++) {
492  for(int j = 0; j < fbin; j++) {
493  if(i == 1) {
494  freq[j][0] = (0. + (double(j) * (rmax / double(fbin))));
495  freq[j][1] = 0;
496  }
497  if(abs(trans[i][1]) > (0. + (double(j) * (rmax / double(fbin)))) &&
498  abs(trans[i][1]) <= (rmax / double(fbin)) + (double(j) * (rmax / double(fbin)))) {
499  freq[j][1] = freq[j][1] + 1;
500  }
501  }
502  }
503  // set transition limit using histogram
504  for(int j = 0; j < fbin; j++) {
505  if(freq[j][1] > max) {
506  max = freq[j][1];
507  dlim = (2 * ((rmax / double(fbin)) + (double(j) * (rmax / double(fbin)))));
508  }
509  }
510  // std::cout<<"PPG transitions assumed above "<<(dlim*100.)<<" % change in rate.."<<std::endl;
511  for(int i = 0; i <= xbins; i++) {
512  if(abs(trans[i][1]) > dlim) {
513  nt += 1;
514  if(nt > numpat) {
515  printf(DRED "Warning: Found more PPG transition(s) than expected in spectrum %s (%i/%i)" RESET_COLOR
516  "\n",
517  sname, nt, numpat);
518  // std::cout<<"(see bin number "<<i<<" in spectrum "<<sname<<")"<<std::endl;
519  ppgstat[1] += 1;
520  break;
521  } else {
522  bnd[nt - 1][0] = i;
523  bnd[nt - 1][1] = trans[i][2];
524  }
525  }
526  }
527  if(nt == numpat) {
528  printf(DGREEN "Found correct number of PPG transitions in spectrum %s (%i/%i)" RESET_COLOR "\n", sname, nt,
529  numpat);
530  ppgstat[0] += 1;
531  } else if(nt < numpat) {
532  printf(DRED "Warning: Found too few PPG transitions in spectrum %s (%i/%i)" RESET_COLOR "\n", sname, nt,
533  numpat);
534  ppgstat[1] += 1;
535  }
536  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
537  // DECIDE THE PPG ORDER (PULSER OFF/PULSER ON)
538  ppg[0][0] = 0;
539  for(int i = 0; i < numpat; i++) {
540  ppg[i + 1][0] = bnd[i][0];
541  ppg[i][1] = (bnd[i][0]) - 1;
542  }
543  if(bnd[0][1] == 0) { // pulser must be first (first transition is pulser OFF)
544  sref = 1;
545  pref = 0;
546  } else if(bnd[0][1] == 1) { // source must be first (first transition is pulser ON)
547  sref = 0;
548  pref = 1;
549  }
550  // diagnostic only
551  if(cnt % nsc == 0) {
552  for(int i = 0; i < numpat; i++) {
553  ofile<<ppg[i][0]<<"\t"<<ppg[i][1]<<std::endl;
554  }
555  ofile<<"/"<<std::endl;
556  }
557  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
558  // SOURCE ONLY
559  for(int i = sref; i < numpat; i += 2) {
560  for(int j = (ppg[i][0] + chop); j <= (ppg[i][1] - chop); j++) {
561  x = spec[cnt]->GetBinContent(j);
562  if(x != 0) {
563  wrand = wrand + x;
564  nrand += 1;
565  }
566  }
567  }
568  rrand = (wrand / nrand); // mean
569  // diagnostic spectrum (dspec) parameters
570  int lim1 = rrand - (0.5 * dlim * rrand);
571  int lim2 = rrand + (0.5 * dlim * rrand);
572  int dsbin = (lim2 - lim1) / 20;
573  auto** dspec = new int*[dsbin];
574  for(int i = 0; i < dsbin; ++i) {
575  dspec[i] = new int[2];
576  };
577  for(int i = 0; i < dsbin; i++) {
578  dspec[i][0] = lim1 + (i * ((lim2 - lim1) / dsbin));
579  dspec[i][1] = 0;
580  }
581  // standard deviation / increment dspec
582  for(int i = sref; i < numpat; i += 2) {
583  for(int j = (ppg[i][0] + chop); j <= (ppg[i][1] - chop); j++) {
584  x = spec[cnt]->GetBinContent(j);
585  if(cnt % nsc == 0) { // dspec for channel 0 only
586  for(int k = 0; k < dsbin; k++) {
587  if(x >= dspec[k][0] && x < dspec[k + 1][0]) {
588  dspec[k][1] += 1;
589  }
590  }
591  }
592  if(x != 0) {
593  sum = sum + pow((x - rrand), 2);
594  }
595  }
596  }
597  sdrand = sqrt(sum / (nrand - 1)); // standard deviation
598  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~FREQUENCY HISTOGRAM
599  if(cnt % nsc == 0) {
600  for(int i = 0; i < dsbin; i++) { // dspec
601  fprintf(random, "%i \t %i", dspec[i][0], dspec[i][1]);
602  fprintf(random, "\n");
603  }
604  fprintf(random, "/");
605  fprintf(random, "\n");
606  }
607  // std::cout<<"Mean = "<<rrand<<", standard deviation = "<<sdrand<<std::endl;
608  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
609  // SOURCE+PULSER
610  for(int i = pref; i < numpat; i += 2) {
611  for(int j = (ppg[i][0] + chop); j <= (ppg[i][1] - chop); j++) {
612  x = spec[cnt]->GetBinContent(j);
613  if(x != 0) {
614  wcomb = wcomb + x;
615  ncomb += 1;
616  } else {
617  continue;
618  }
619  }
620  }
621  rcomb = (wcomb / ncomb); // mean
622  // now calculate max. likelihood
623  for(int i = pref; i < numpat; i += 2) {
624  for(int j = (ppg[i][0] + chop); j <= (ppg[i][1] - chop); j++) {
625  x = spec[cnt]->GetBinContent(j);
626  if(x != 0) {
627  maxl = (0.5 * (pow((x - rcomb), 2))) / x;
628  if(maxl < minl) {
629  minl = maxl;
630  minb = j;
631  }
632  } else {
633  continue;
634  }
635  }
636  }
637  rcmin = spec[cnt]->GetBinContent(minb);
638  lbd = rcmin;
639  ubd = rcmin;
640  // find min/max values of parabola with respect to minimum
641  for(int i = pref; i < numpat; i += 2) {
642  for(int j = (ppg[i][0] + chop); j <= (ppg[i][1] - chop); j++) {
643  x = spec[cnt]->GetBinContent(j);
644  if(x != 0) {
645  maxl = (0.5 * (pow((x - rcmin), 2))) / x;
646  // ofile<<j<<"\t"<<x<<"\t"<<maxl<<std::endl;
647  if(maxl <= (minl + 0.5) && x < rcmin && x < lbd) { // fixed
648  lbd = x;
649  }
650  if(maxl <= (minl + 0.5) && x > rcmin && x > ubd) { // fixed
651  ubd = x;
652  }
653  } else {
654  continue;
655  }
656  }
657  }
658  // diagnostic spectrum (dspec) parameters (re-define for source+pulser)
659  lim1 = lbd - (2.0 * abs(rcmin - lbd));
660  lim2 = ubd + (2.0 * abs(rcmin - ubd));
661  // std::cout<<lim1<<"\t"<<lim2<<"\t"<<rcmin<<std::endl;
662  dsbin = (lim2 - lim1) / 20; // dspec[dsbin][2]; What was this statement supposed to do? It has no effect; VB
663  for(int i = 0; i < dsbin; i++) {
664  dspec[i][0] = lim1 + (i * ((lim2 - lim1) / dsbin));
665  dspec[i][1] = 0;
666  }
667  // standard deviation / increment dspec
668  for(int i = pref; i < numpat; i += 2) {
669  for(int j = (ppg[i][0] + chop); j <= (ppg[i][1] - chop); j++) {
670  x = spec[cnt]->GetBinContent(j);
671  if(cnt % nsc == 0) { // dspec for channel 0 only
672  for(int k = 0; k < dsbin; k++) {
673  if(x >= dspec[k][0] && x < dspec[k + 1][0]) {
674  dspec[k][1] += 1;
675  }
676  }
677  }
678  if(x != 0) {
679  sumc = sumc + pow((x - rcomb), 2);
680  }
681  }
682  }
683  sdcomb = sqrt(sumc / (ncomb - 1)); // standard deviation (not strictly applicable to source+pulser data)
684  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~FREQUENCY HISTOGRAM
685  if(cnt % nsc == 0) {
686  for(int i = 0; i < dsbin; i++) { // dspec
687  fprintf(combine, "%i \t %i", dspec[i][0], dspec[i][1]);
688  fprintf(combine, "\n");
689  }
690  fprintf(combine, "/");
691  fprintf(combine, "\n");
692  }
693  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
694  // To find the error in (rcmin-rrand), we generate a likelihood curve using an iterative procedure
695  // Ref. "Asymmetric Statistical Errors", Roger Barlow, http://arxiv.org/pdf/physics/0406120.pdf
696  // WARNING: u must be given a reasonable range. This is assumed to be ~1.5*max(a1,a2)
697 
698  double a1 = abs(rcmin - ubd);
699  double a2 = abs(rcmin - lbd);
700  double maxa = std::max(a1, a2);
701  double uhi = (1.5 * maxa);
702  double ulo = -uhi;
703  double du = (uhi - ulo) / 1e3;
704  double u = ulo;
705  int itr = 0;
706  int umin = 0;
707  double w1;
708  double x1;
709  double x2;
710  int nrow = int((uhi - ulo) / du);
711  double w2 = pow((pow(sdrand, 2)), 2) / ((2. * pow(sdrand, 2))); // const.
712  minl = -1e6;
713  auto** array = new double*[nrow];
714  for(int i = 0; i < nrow; ++i) {
715  array[i] = new double[2];
716  }
717  double sigm;
718  double sigp;
719  double lnl;
720 
721  while(itr < nrow) {
722  if(itr == 0) {
723  x1 = 0.;
724  x2 = 0.;
725  } else {
726  x1 = (u * w1) / (w1 + w2);
727  x2 = (u * w2) / (w1 + w2);
728  }
729  w1 = pow(((a1 * a2) + ((a1 - a2) * x1)), 2) / ((2. * (a1 * a2)) + ((a1 - a2) * x1));
730  lnl = -0.5 * ((pow(x1, 2) / ((a1 * a2) + ((a1 - a2) * x1))) + (pow(x2, 2) / (pow(sdrand, 2))));
731  if(lnl <= 0.) { // reject positive likelihoods (these tend occur at large +/- values of u)
732  if(itr > 0 && lnl > minl) { // mean value
733  minl = lnl;
734  umin = itr;
735  }
736  array[itr][0] = u;
737  array[itr][1] = lnl;
738  u += du;
739  itr++;
740  } else {
741  u += du;
742  }
743  }
744  // determine upper/lower limits
745  sigm = array[umin][0];
746  sigp = array[umin][0];
747  for(int i = 1; i < nrow; i++) {
748  if(array[i][1] >= (minl - 0.5) && array[i][0] < array[umin][0] && array[i][0] < sigm) {
749  sigm = array[i][0];
750  }
751  if(array[i][1] >= (minl - 0.5) && array[i][0] > array[umin][0] && array[i][0] > sigp) {
752  sigp = array[i][0];
753  }
754  }
755  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*PARABOLA HISTOGRAM
756  if(cnt % nsc == 0) {
757  fprintf(asymerror, "%s\t %s\t %s", "#chan", "Err[Hz]", "Ln(L)");
758  fprintf(asymerror, "\n");
759  for(int i = 1; i < nrow; i++) {
760  fprintf(asymerror, "%i \t %.4E \t %.4E", cnt % nsc, array[i][0], array[i][1]);
761  fprintf(asymerror, "\n");
762  }
763  fprintf(asymerror, "/");
764  fprintf(asymerror, "\n");
765  }
766  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
767  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
768  double tau = ((1.0 / rrand) * (1.0 - sqrt((rcmin - rrand) / (*rate)))) * 1.0e6; // deadtime (us)
769  double rtau = 0;
770  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
771  // FINAL ERROR ANALYSIS*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
772  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
773  // Idea: now that the error boundaries are known for rrand, rcmin and (rcmin-rrand), generate a random number
774  // which chooses a value within these boundaries - the resulting tau is plotted and the range gives the error in
775  // tau
776 
777  int iter = 1e4, bin = 10;
778  double tempa, tempb;
779  double var1, var2, var3;
780  double l1, l2;
781  int wbin = 40;
782  int wrow = 0, wsize = int(pow(wbin, 2));
783  auto** randcheck = new double*[bin];
784  for(int i = 0; i < bin; ++i) {
785  randcheck[i] = new double[2];
786  }
787  auto** randtau = new double*[iter];
788  for(int i = 0; i < iter; ++i) {
789  randtau[i] = new double[2];
790  }
791  auto** wspec = new double*[wsize];
792  for(int i = 0; i < wsize; ++i) {
793  wspec[i] = new double[3];
794  }
795  int flagc = 0;
796  int binsize = 3;
797 
798  // Check the "randomness" of the random number generator **RCHECK**
799  for(int i = 0; i < bin; i++) {
800  randcheck[i][0] = 0 + (double(i) * (1 / double(bin)));
801  randcheck[i][1] = 0;
802  }
803  // initialise matrix to get final uncertainty
804  for(int i = 0; i < wbin; i++) {
805  for(int j = 0; j < wbin; j++) {
806  wspec[wrow][0] = ((rcmin - rrand) + sigm) + (double(i) * ((sigp - sigm) / double(wbin))); // x,
807  // (rcmin-rrand)
808  wspec[wrow][1] = (*lowrtau) + (double(j) * ((*upprtau - *lowrtau) / double(wbin))); // y, (rtau);
809  wspec[wrow][2] = 0; // z, frequency
810  wrow += 1;
811  }
812  }
813  // generate all possible guesses for rcmin and rrand to satisfy test value of (rcmin-rrand) in the limits l1,l2
814  int i = 0;
815  while(i < (nrow - binsize)) {
816  if(array[i][0] >= sigm && array[i][0] <= sigp) {
817  l1 = ((rcmin - rrand) + array[i][0]);
818  l2 = ((rcmin - rrand) + array[i + binsize][0]);
819 
820  for(int j = 0; j < iter; j++) {
821  tempa = rand() / double(RAND_MAX);
822  var1 = ((tempa * (a1 + a2)) + (rcmin - a2));
823  tempb = rand() / double(RAND_MAX);
824  var2 = ((tempb * (2.e0 * sdrand)) + (rrand - sdrand));
825  var3 = (var1 - var2);
826  //~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~'good'
827  //events
828  if(var3 >= l1 && var3 <= l2) {
829  flagc++;
830  // calculate deadtime using var3(rcmin-rrand), var2(rrand)
831  rtau = ((1.0 / var2) * (1.0 - sqrt(var3 / (*rate)))) * 1.0e6;
832  // build wspec matrix
833  for(int k = 0; k < wsize; k++) {
834  if(var3 >= wspec[k][0] && var3 < wspec[k + wbin][0] && rtau >= wspec[k][1] &&
835  rtau < wspec[k + 1][1]) {
836  wspec[k][2] += 1; // this seems to work now
837  }
838  }
839  //~*~*~*~*~*~*~*~*~*~*~*~~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~
840  } else {
841  continue;
842  }
843  }
844  i += binsize;
845  flagc = 0;
846  } else {
847  i += 1;
848  continue;
849  }
850  }
851  // diagnostic
852  // printf(DMAGENTA "(comb-rand)= %f, sigp= %f, sigm= %f, rand= %f, sdrand= %f" RESET_COLOR
853  // "\n",(rcmin-rrand),sigp,sigm,rrand,sdrand);
854  //~*~*~*~*~*~*~*~*~*~*~*~~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~
855  // Determine final error bounds using wspec matrix
856  double gmax = 0, hmax = 0;
857  double erbp = 0, erbm = 0, erfp = 0, erfm = 0;
858  double frmin = 1e6, frmax = 0, srmin = 1e6, srmax = 0;
859 
860  for(i = 0; i < wsize; i++) {
861  if(wspec[i][2] > gmax) {
862  gmax = wspec[i][2];
863  hmax = (gmax / 2);
864  }
865  }
866  // calculate max/min range (select above half the height of 'peak')
867  for(i = 0; i < wsize; i++) {
868  if(wspec[i][1] > srmax && wspec[i][2] > hmax) {
869  srmax = wspec[i][1];
870  }
871  if(wspec[i][1] < srmin && wspec[i][2] > hmax) {
872  srmin = wspec[i][1];
873  }
874  }
875  // calculate max/min range (only select above zero)
876  for(i = 0; i < wsize; i++) {
877  if(wspec[i][1] > frmax && wspec[i][2] > 0) {
878  frmax = wspec[i][1];
879  }
880  if(wspec[i][1] < frmin && wspec[i][2] > 0) {
881  frmin = wspec[i][1];
882  }
883  }
884  // final errors: b=best estimate, f=full range
885  erbm = abs(tau - srmin);
886  erbp = abs(tau - srmax);
887  erfm = abs(tau - frmin);
888  erfp = abs(tau - frmax);
889  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*STANDARD ERROR PROPAGATION
890  double p1 = sqrt(pow(sdcomb, 2) + pow(sdrand, 2));
891  double p1r = p1 / (rcmin - rrand);
892  double p2 = (rcmin - rrand) / (*rate);
893  // Here we assume that sqrt(rel.err.) ~ 0.5 * rel.err. This is approximately true where the +/- uncertainties are
894  // similar.
895  double p3 = (0.5 * p1r * p2);
896  double eprop = tau * (sqrt(pow((p3 / (1 - sqrt(p2))), 2) + pow((sdrand / rrand), 2)));
897  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*RANDOM TAU HISTOGRAM
898  // if(cnt%nsc==0){
899  fprintf(randdt, "%i \t %.2f \t %.2f \t %.2f \t %.2f", cnt, srmin, srmax, frmin, frmax);
900  // fprintf(randdt, "#//end channel 0");
901  fprintf(randdt, "\n");
902  //}
903  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~WIDTH HISTOGRAM
904  if(cnt % nsc == 0) {
905  for(i = 0; i < wsize; i++) {
906  fprintf(randw, "%.2f \t %.2f \t %.2f", wspec[i][0], wspec[i][1], wspec[i][2]);
907  fprintf(randw, "\n");
908  }
909  fprintf(randw, "//end channel 0");
910  fprintf(randw, "\n");
911  }
912  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~RCHECK HISTOGRAM
913  // print random number generator results to file for a single spectrum
914  /*if(cnt%nsc==0){
915  for (i=0; i<bin; i++){
916  fprintf(rng, "%f \t %f", randcheck[i][0], randcheck[i][1]);
917  fprintf(rng, "\n");
918  }
919  fprintf(rng, "//end channel 0");
920  fprintf(rng, "\n");
921  }*/
922  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~PRINT FINAL RESULTS TO FILE
923  fprintf(deadtime, "%s\t%i\t%.1f\t%.1f\t%.2f\t%.1f\t%.2f\t%.2f\t %.1f\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", sname,
924  (cnt % nsc), ((*rate) / 1e3), (rrand / 1e3), (sdrand / 1e3), (rcmin / 1e3), (abs(rcmin - ubd) / 1e3),
925  (abs(rcmin - lbd) / 1e3), tau, erbp, erbm, erfp, erfm, eprop);
926  fprintf(deadtime, "\n");
927  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
928  cnt++;
929  // change pulser rate and runtime accordingly for each file
930  if(cnt % (nsc * nscaler) == 0) {
931  rate++; // used to have a de-reference, see comments above; VB
932  trun++; // used to have a de-reference, see comments above; VB
933  }
934  // change limits accordingly for each scaler in each file
935  if(cnt % (nsc) == 0) {
936  for(i = 0; i < 2; i++) {
937  lowrtau++; // used to have a de-reference, see comments above; VB
938  upprtau++; // used to have a de-reference, see comments above; VB
939  }
940  }
941  if(cnt % (nsc) == 0 && cnt % (nsc * nscaler) == 0) {
942  cflag++;
943  if(cflag == 1) {
944  lowrtau = &rp2[0];
945  upprtau = &rp2[1];
946  } else if(cflag == 2) {
947  lowrtau = &rp3[0];
948  upprtau = &rp3[1];
949  } else if(cflag == 3) {
950  lowrtau = &rp4[0];
951  upprtau = &rp4[1];
952  }
953  }
954  } // END SPECTRUM ANALYSIS LOOP
955  //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~**~*~*~*~*~*~**~*~*~*~*~*~*
956  delete[] spec;
957  ofile.close();
958  fclose(random);
959  fclose(combine);
960  fclose(rng);
961  fclose(deadtime);
962  fclose(asymerror);
963  fclose(randdt);
964  fclose(randw);
965  int good = ppgstat[0];
966  printf("\n");
967  // info/warnings
968  if(good < cnt) {
969  printf(DRED "Correct # of PPG transitions obtained for %i out of %i spectra" RESET_COLOR "\n", good, cnt);
970  } else {
971  printf(DBLUE "Correct # of PPG transitions obtained for %i out of %i spectra" RESET_COLOR "\n", good, cnt);
972  }
973  return;
974 }
void CheckFile(const char *&fname)
Definition: Deadtime.cxx:281
#define DRED
Definition: Globals.h:17
#define RESET_COLOR
Definition: Globals.h:4
std::vector< UInt_t > GetScaler() const
Definition: TScaler.h:63
#define DGREEN
Definition: Globals.h:16
ULong64_t GetTimeStamp() const
Definition: TScaler.h:73
void Printaddress(int *channel)
Definition: Deadtime.cxx:195
void MakeSpectra(const char *&filename, int &prog, const char *&fname, int &nsclr, int &ncycle, double *rate, int *channel, int &index, int *trun, double &thresh)
Definition: Deadtime.cxx:205
UInt_t GetAddress() const
Definition: TScaler.h:59
void Clear(Option_t *opt="") override
Definition: TScaler.cxx:239
void DoAnalysis(const char *&fname, int &nfile, double *rate, int &nsclr, int &patlen, int &ncycle, int *trun, double &eor, const char *&hname, const char *&iname, const char *&jname, const char *&kname, const char *&lname, const char *&mname, const char *&nname, int &nscaler)
Definition: Deadtime.cxx:295
int main(int argc, char *argv[])
Definition: Deadtime.cxx:51
#define DMAGENTA
Definition: Globals.h:19
#define DBLUE
Definition: Globals.h:14