ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TSpectrum2.cxx
Go to the documentation of this file.
1 // @(#)root/spectrum:$Id$
2 // Author: Miroslav Morhac 17/01/2006
3 
4 /** \class TSpectrum2
5  \ingroup Spectrum
6  \brief Advanced 2-dimensional spectra processing
7  \author Miroslav Morhac
8 
9  This class contains advanced spectra processing functions.
10 
11  - One-dimensional background estimation functions
12  - Two-dimensional background estimation functions
13  - One-dimensional smoothing functions
14  - Two-dimensional smoothing functions
15  - One-dimensional deconvolution functions
16  - Two-dimensional deconvolution functions
17  - One-dimensional peak search functions
18  - Two-dimensional peak search functions
19 
20  The algorithms in this class have been published in the following references:
21 
22  1. M.Morhac et al.: Background elimination methods for multidimensional coincidence gamma-ray spectra. Nuclear Instruments and Methods in Physics Research A 401 (1997) 113-132.
23  2. M.Morhac et al.: Efficient one- and two-dimensional Gold deconvolution and its application to gamma-ray spectra decomposition. Nuclear Instruments and Methods in Physics Research A 401 (1997) 385-408.
24  3. M.Morhac et al.: Identification of peaks in multidimensional coincidence gamma-ray spectra. Nuclear Instruments and Methods in Research Physics A 443(2000), 108-125.
25 
26  These NIM papers are also available as doc or ps files from:
27 
28  - [SpectrumDec.ps.gz](ftp://root.cern.ch/root/SpectrumDec.ps.gz)
29  - [SpectrumSrc.ps.gz](ftp://root.cern.ch/root/SpectrumSrc.ps.gz)
30  - [SpectrumBck.ps.gz](ftp://root.cern.ch/root/SpectrumBck.ps.gz)
31 
32  All the figures in this page were prepared using the DaqProVis
33  system, Data Acquisition, Processing and Visualization system,
34  developed at the Institute of Physics, Slovak Academy of Sciences, Bratislava,
35  Slovakia.
36 */
37 
38 #include "TSpectrum2.h"
39 #include "TPolyMarker.h"
40 #include "TList.h"
41 #include "TH1.h"
42 #include "TMath.h"
43 #define PEAK_WINDOW 1024
44 
47 
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Constructor.
52 
53 TSpectrum2::TSpectrum2() :TNamed("Spectrum", "Miroslav Morhac peak finder")
54 {
55  Int_t n = 100;
56  fMaxPeaks = n;
57  fPosition = new Double_t[n];
58  fPositionX = new Double_t[n];
59  fPositionY = new Double_t[n];
60  fResolution = 1;
61  fHistogram = 0;
62  fNPeaks = 0;
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// - maxpositions: maximum number of peaks
67 /// - resolution: determines resolution of the neighbouring peaks
68 /// default value is 1 correspond to 3 sigma distance
69 /// between peaks. Higher values allow higher resolution
70 /// (smaller distance between peaks.
71 /// May be set later through SetResolution.
72 
73 TSpectrum2::TSpectrum2(Int_t maxpositions, Double_t resolution) :TNamed("Spectrum", "Miroslav Morhac peak finder")
74 {
75  Int_t n = maxpositions;
76  fMaxPeaks = n;
77  fPosition = new Double_t[n];
78  fPositionX = new Double_t[n];
79  fPositionY = new Double_t[n];
80  fHistogram = 0;
81  fNPeaks = 0;
82  SetResolution(resolution);
83 }
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Destructor.
87 
89 {
90  delete [] fPosition;
91  delete [] fPositionX;
92  delete [] fPositionY;
93  delete fHistogram;
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// static function: Set average window of searched peaks
98 /// see TSpectrum2::SearchHighRes
99 
101 {
102  fgAverageWindow = w;
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// static function: Set max number of decon iterations in deconvolution operation
107 /// see TSpectrum2::SearchHighRes
108 
110 {
111  fgIterations = n;
112 }
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// This function calculates the background spectrum in the input histogram h.
116 /// The background is returned as a histogram.
117 ///
118 /// Function parameters:
119 /// - h: input 2-d histogram
120 /// - numberIterations, (default value = 20)
121 /// Increasing numberIterations make the result smoother and lower.
122 /// - option: may contain one of the following options
123 /// - to set the direction parameter
124 /// "BackIncreasingWindow". By default the direction is BackDecreasingWindow
125 /// - filterOrder-order of clipping filter. Possible values:
126 /// - "BackOrder2" (default)
127 /// - "BackOrder4"
128 /// - "BackOrder6"
129 /// - "BackOrder8"
130 /// - "nosmoothing"- if selected, the background is not smoothed
131 /// By default the background is smoothed.
132 /// - smoothWindow-width of smoothing window. Possible values:
133 /// - "BackSmoothing3" (default)
134 /// - "BackSmoothing5"
135 /// - "BackSmoothing7"
136 /// - "BackSmoothing9"
137 /// - "BackSmoothing11"
138 /// - "BackSmoothing13"
139 /// - "BackSmoothing15"
140 /// - "Compton" if selected the estimation of Compton edge
141 /// will be included.
142 /// - "same" : if this option is specified, the resulting background
143 /// histogram is superimposed on the picture in the current pad.
144 ///
145 /// NOTE that the background is only evaluated in the current range of h.
146 /// ie, if h has a bin range (set via h->GetXaxis()->SetRange(binmin,binmax),
147 /// the returned histogram will be created with the same number of bins
148 /// as the input histogram h, but only bins from binmin to binmax will be filled
149 /// with the estimated background.
150 
151 TH1 *TSpectrum2::Background(const TH1 * h, Int_t number_of_iterations,
152  Option_t * option)
153 {
154  Error("Background","function not yet implemented: h=%s, iter=%d, option=%sn"
155  , h->GetName(), number_of_iterations, option);
156  return 0;
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Print the array of positions.
161 
163 {
164  printf("\nNumber of positions = %d\n",fNPeaks);
165  for (Int_t i=0;i<fNPeaks;i++) {
166  printf(" x[%d] = %g, y[%d] = %g\n",i,fPositionX[i],i,fPositionY[i]);
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// This function searches for peaks in source spectrum in hin
172 /// The number of found peaks and their positions are written into
173 /// the members fNpeaks and fPositionX.
174 /// The search is performed in the current histogram range.
175 ///
176 /// Function parameters:
177 /// - hin: pointer to the histogram of source spectrum
178 /// - sigma: sigma of searched peaks, for details we refer to manual
179 /// - threshold: (default=0.05) peaks with amplitude less than
180 /// threshold*highest_peak are discarded. 0<threshold<1
181 ///
182 /// By default, the background is removed before deconvolution.
183 /// Specify the option "nobackground" to not remove the background.
184 ///
185 /// By default the "Markov" chain algorithm is used.
186 /// Specify the option "noMarkov" to disable this algorithm
187 /// Note that by default the source spectrum is replaced by a new spectrum
188 ///
189 /// By default a polymarker object is created and added to the list of
190 /// functions of the histogram. The histogram is drawn with the specified
191 /// option and the polymarker object drawn on top of the histogram.
192 /// The polymarker coordinates correspond to the npeaks peaks found in
193 /// the histogram.
194 /// A pointer to the polymarker object can be retrieved later via:
195 /// ~~~ {cpp}
196 /// TList *functions = hin->GetListOfFunctions();
197 /// TPolyMarker *pm = (TPolyMarker*)functions->FindObject("TPolyMarker")
198 /// ~~~
199 /// Specify the option "goff" to disable the storage and drawing of the
200 /// polymarker.
201 
203  Option_t * option, Double_t threshold)
204 {
205  if (hin == 0)
206  return 0;
207  Int_t dimension = hin->GetDimension();
208  if (dimension != 2) {
209  Error("Search", "Must be a 2-d histogram");
210  return 0;
211  }
212 
213  TString opt = option;
214  opt.ToLower();
216  if (opt.Contains("nobackground")) {
217  background = kFALSE;
218  opt.ReplaceAll("nobackground","");
219  }
220  Bool_t markov = kTRUE;
221  if (opt.Contains("nomarkov")) {
222  markov = kFALSE;
223  opt.ReplaceAll("nomarkov","");
224  }
225 
226  Int_t sizex = hin->GetXaxis()->GetNbins();
227  Int_t sizey = hin->GetYaxis()->GetNbins();
228  Int_t i, j, binx,biny, npeaks;
229  Double_t ** source = new Double_t*[sizex];
230  Double_t ** dest = new Double_t*[sizex];
231  for (i = 0; i < sizex; i++) {
232  source[i] = new Double_t[sizey];
233  dest[i] = new Double_t[sizey];
234  for (j = 0; j < sizey; j++) {
235  source[i][j] = hin->GetBinContent(i + 1, j + 1);
236  }
237  }
238  //npeaks = SearchHighRes(source, dest, sizex, sizey, sigma, 100*threshold, kTRUE, 3, kTRUE, 10);
239  //the smoothing option is used for 1-d but not for 2-d histograms
240  npeaks = SearchHighRes(source, dest, sizex, sizey, sigma, 100*threshold, background, fgIterations, markov, fgAverageWindow);
241 
242  //The logic in the loop should be improved to use the fact
243  //that fPositionX,Y give a precise position inside a bin.
244  //The current algorithm takes the center of the bin only.
245  for (i = 0; i < npeaks; i++) {
246  binx = 1 + Int_t(fPositionX[i] + 0.5);
247  biny = 1 + Int_t(fPositionY[i] + 0.5);
248  fPositionX[i] = hin->GetXaxis()->GetBinCenter(binx);
249  fPositionY[i] = hin->GetYaxis()->GetBinCenter(biny);
250  }
251  for (i = 0; i < sizex; i++) {
252  delete [] source[i];
253  delete [] dest[i];
254  }
255  delete [] source;
256  delete [] dest;
257 
258  if (opt.Contains("goff"))
259  return npeaks;
260  if (!npeaks) return 0;
261  TPolyMarker * pm = (TPolyMarker*)hin->GetListOfFunctions()->FindObject("TPolyMarker");
262  if (pm) {
263  hin->GetListOfFunctions()->Remove(pm);
264  delete pm;
265  }
266  pm = new TPolyMarker(npeaks, fPositionX, fPositionY);
267  hin->GetListOfFunctions()->Add(pm);
268  pm->SetMarkerStyle(23);
269  pm->SetMarkerColor(kRed);
270  pm->SetMarkerSize(1.3);
271  ((TH1*)hin)->Draw(option);
272  return npeaks;
273 }
274 
275 ////////////////////////////////////////////////////////////////////////////////
276 /// resolution: determines resolution of the neighboring peaks
277 /// default value is 1 correspond to 3 sigma distance
278 /// between peaks. Higher values allow higher resolution
279 /// (smaller distance between peaks.
280 /// May be set later through SetResolution.
281 
283 {
284  if (resolution > 1)
285  fResolution = resolution;
286  else
287  fResolution = 1;
288 }
289 
290 ////////////////////////////////////////////////////////////////////////////////
291 /// This function calculates background spectrum from source spectrum.
292 /// The result is placed to the array pointed by spectrum pointer.
293 ///
294 /// Function parameters:
295 /// - spectrum-pointer to the array of source spectrum
296 /// - ssizex-x length of spectrum
297 /// - ssizey-y length of spectrum
298 /// - numberIterationsX-maximal x width of clipping window
299 /// - numberIterationsY-maximal y width of clipping window
300 /// for details we refer to manual
301 /// - direction- direction of change of clipping window
302 /// - possible values=kBackIncreasingWindow
303 /// kBackDecreasingWindow
304 /// - filterType-determines the algorithm of the filtering
305 /// - possible values=kBackSuccessiveFiltering
306 /// kBackOneStepFiltering
307 ///
308 /// ### Background estimation
309 ///
310 /// Goal: Separation of useful information (peaks) from useless information (background)
311 ///
312 /// - method is based on Sensitive Nonlinear Iterative Peak (SNIP) clipping algorithm [1]
313 ///
314 /// - there exist two algorithms for the estimation of new value in the channel \f$ i_1,i_2\f$
315 ///
316 /// Algorithm based on Successive Comparisons:
317 ///
318 /// It is an extension of one-dimensional SNIP algorithm to another dimension. For
319 /// details we refer to [2].
320 ///
321 /// Algorithm based on One Step Filtering:
322 ///
323 /// New value in the estimated channel is calculated as:
324 /// \f[ a = \nu_{p-1}(i_1,i_2)\f]
325 /// \f[
326 /// b = \frac{\nu_{p-1}(i_1-p,i_2-p) - 2\nu_{p-1}(i_1-p,i_2) + \nu_{p-1}(i_1-p,i_2+p) - 2\nu_{p-1}(i_1,i_2-p)}{4} +
327 /// \f]
328 /// \f[
329 /// \frac{-2\nu_{p-1}(i_1,i_2+p) + \nu_{p-1}(i_1+p,i_2-p) - 2\nu_{p-1}(i_1+p,i_2) + \nu_{p-1}(i_1+p,i_2+p)}{4}
330 /// \f]
331 /// \f[ \nu_{p-1}(i_1,i_2) = min(a,b)\f]
332 /// where p = 1, 2, ..., number_of_iterations.
333 ///
334 /// #### References:
335 ///
336 /// [1] C. G Ryan et al.: SNIP, a statistics-sensitive background treatment for the
337 /// quantitative analysis of PIXE spectra in geoscience applications. NIM, B34 (1988), 396-402.
338 ///
339 /// [2] M. Morhac;, J. Kliman, V.
340 /// Matouoek, M. Veselsky, I. Turzo.:
341 /// Background elimination methods for multidimensional gamma-ray spectra. NIM,
342 /// A401 (1997) 113-132.
343 ///
344 /// ### Example 1 - script Back_gamma64.c
345 ///
346 /// \image html TSpectrum2_Background1.jpg Fig. 1 Original two-dimensional gamma-gamma-ray spectrum
347 /// \image html TSpectrum2_Background2.jpg Fig. 2 Background estimated from data from Fig. 1 using decreasing clipping window with widths 4, 4 and algorithm based on successive comparisons. The estimate includes not only continuously changing background but also one-dimensional ridges.
348 /// \image html TSpectrum2_Background3.jpg Fig. 3 Resulting peaks after subtraction of the estimated background (Fig. 2) from original two-dimensional gamma-gamma-ray spectrum (Fig. 1).
349 ///
350 /// #### Script:
351 ///
352 /// Example to illustrate the background estimator (class TSpectrum). To execute this example, do:
353 ///
354 /// `root > .x Back_gamma64.C`
355 ///
356 /// ~~~ {.cpp}
357 /// #include <TSpectrum>
358 /// void Back_gamma64() {
359 /// Int_t i, j;
360 /// Double_t nbinsx = 64;
361 /// Double_t nbinsy = 64;
362 /// Double_t xmin = 0;
363 /// Double_t xmax = (Double_t)nbinsx;
364 /// Double_t ymin = 0;
365 /// Double_t ymax = (Double_t)nbinsy;
366 /// Double_t ** source = new Double_t*[nbinsx];
367 /// for (i=0;i<nbinsx;i++)
368 /// source[i]=new Double_t[nbinsy];
369 /// TH2F *back = new TH2F("back","Background estimation",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
370 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
371 /// back=(TH2F*) f->Get("back1;1");
372 /// TCanvas *Background = new TCanvas("Background","Estimation of background with increasing window",10,10,1000,700);
373 /// TSpectrum *s = new TSpectrum();
374 /// for (i = 0; i < nbinsx; i++){
375 /// for (j = 0; j < nbinsy; j++){
376 /// source[i][j] = back->GetBinContent(i + 1,j + 1);
377 /// }
378 /// }
379 /// s->Background(source,nbinsx,nbinsy,4,4,kBackDecreasingWindow,kBackSuccessiveFiltering);
380 /// for (i = 0; i < nbinsx; i++){
381 /// for (j = 0; j < nbinsy; j++)
382 /// back->SetBinContent(i + 1,j + 1, source[i][j]);
383 /// }
384 /// back->Draw("SURF");
385 /// }
386 /// ~~~
387 ///
388 /// ### Example 2- script Back_gamma256.c
389 ///
390 /// \image html TSpectrum2_Background4.jpg Fig. 4 Original two-dimensional gamma-gamma-ray spectrum 256x256 channels
391 /// \image html TSpectrum2_Background5.jpg Fig. 5 Peaks after subtraction of the estimated background (increasing clipping window with widths 8, 8 and algorithm based on successive comparisons) from original two-dimensional gamma-gamma-ray spectrum (Fig. 4).
392 ///
393 /// #### Script:
394 ///
395 // Example to illustrate the background estimator (class TSpectrum).
396 /// To execute this example, do
397 ///
398 /// `root > .x Back_gamma256.C`
399 ///
400 /// ~~~ {.cpp}
401 /// #include <TSpectrum>
402 /// void Back_gamma256() {
403 /// Int_t i, j;
404 /// Double_t nbinsx = 64;
405 /// Double_t nbinsy = 64;
406 /// Double_t xmin = 0;
407 /// Double_t xmax = (Double_t)nbinsx;
408 /// Double_t ymin = 0;
409 /// Double_t ymax = (Double_t)nbinsy;
410 /// Double_t** source = new Double_t*[nbinsx];
411 /// for (i=0;i<nbinsx;i++)
412 /// source[i]=new Double_t[nbinsy];
413 /// TH2F *back = new TH2F("back","Background estimation",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
414 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
415 /// back=(TH2F*) f->Get("back2;1");
416 /// TCanvas *Background = new TCanvas("Background","Estimation of background with increasing window",10,10,1000,700);
417 /// TSpectrum *s = new TSpectrum();
418 /// for (i = 0; i < nbinsx; i++){
419 /// for (j = 0; j < nbinsy; j++){
420 /// source[i][j] = back->GetBinContent(i + 1,j + 1);
421 /// }
422 /// }
423 /// s->Background(source,nbinsx,nbinsy,8,8,kBackIncreasingWindow,kBackSuccessiveFiltering);
424 /// for (i = 0; i < nbinsx; i++){
425 /// for (j = 0; j < nbinsy; j++)
426 /// back->SetBinContent(i + 1,j + 1, source[i][j]);
427 /// }
428 /// back->Draw("SURF");
429 /// }
430 /// ~~~
431 ///
432 /// Example 3- script Back_synt256.c
433 ///
434 /// \image html TSpectrum2_Background6.jpg Fig. 6 Original two-dimensional synthetic spectrum 256x256 channels
435 /// \image html TSpectrum2_Background7.jpg Fig. 7 Peaks after subtraction of the estimated background (increasing clipping window with widths 8, 8 and algorithm based on successive comparisons) from original two-dimensional gamma-gamma-ray spectrum (Fig. 6). One can observe artefacts (ridges) around the peaks due to the employed algorithm.
436 /// \image html TSpectrum2_Background8.jpg Fig. 8 Peaks after subtraction of the estimated background (increasing clipping window with widths 8, 8 and algorithm based on one step filtering) from original two-dimensional gamma-gamma-ray spectrum (Fig. 6). The artefacts from the above given Fig. 7 disappeared.
437 ///
438 /// #### Script:
439 ///
440 /// Example to illustrate the background estimator (class TSpectrum).
441 /// To execute this example, do
442 ///
443 /// `root > .x Back_synt256.C`
444 ///
445 /// ~~~ {.cpp}
446 /// #include <TSpectrum>
447 /// void Back_synt256() {
448 /// Int_t i, j;
449 /// Double_t nbinsx = 64;
450 /// Double_t nbinsy = 64;
451 /// Double_t xmin = 0;
452 /// Double_t xmax = (Double_t)nbinsx;
453 /// Double_t ymin = 0;
454 /// Double_t ymax = (Double_t)nbinsy;
455 /// Double_t** source = new Double_t*[nbinsx];
456 /// for (i=0;i<nbinsx;i++)
457 /// source[i]=new Double_t[nbinsy];
458 /// TH2F *back = new TH2F("back","Background estimation",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
459 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
460 /// back=(TH2F*) f->Get("back3;1");
461 /// TCanvas *Background = new TCanvas("Background","Estimation of background with increasing window",10,10,1000,700);
462 /// TSpectrum *s = new TSpectrum();
463 /// for (i = 0; i < nbinsx; i++){
464 /// for (j = 0; j < nbinsy; j++){
465 /// source[i][j] = back->GetBinContent(i + 1,j + 1);
466 /// }
467 /// }
468 /// s->Background(source,nbinsx,nbinsy,8,8,
469 /// kBackIncreasingWindow,kBackSuccessiveFiltering);//kBackOneStepFiltering
470 /// for (i = 0; i < nbinsx; i++){
471 /// for (j = 0; j < nbinsy; j++)
472 /// back->SetBinContent(i + 1,j + 1, source[i][j]);
473 /// }
474 /// back->Draw("SURF");
475 /// }
476 /// ~~~
477 
478 const char *TSpectrum2::Background(Double_t **spectrum,
479  Int_t ssizex, Int_t ssizey,
480  Int_t numberIterationsX,
481  Int_t numberIterationsY,
482  Int_t direction,
483  Int_t filterType)
484 {
485  Int_t i, x, y, sampling, r1, r2;
486  Double_t a, b, p1, p2, p3, p4, s1, s2, s3, s4;
487  if (ssizex <= 0 || ssizey <= 0)
488  return "Wrong parameters";
489  if (numberIterationsX < 1 || numberIterationsY < 1)
490  return "Width of Clipping Window Must Be Positive";
491  if (ssizex < 2 * numberIterationsX + 1
492  || ssizey < 2 * numberIterationsY + 1)
493  return ("Too Large Clipping Window");
494  Double_t **working_space = new Double_t*[ssizex];
495  for (i = 0; i < ssizex; i++)
496  working_space[i] = new Double_t[ssizey];
497  sampling =
498  (Int_t) TMath::Max(numberIterationsX, numberIterationsY);
499  if (direction == kBackIncreasingWindow) {
500  if (filterType == kBackSuccessiveFiltering) {
501  for (i = 1; i <= sampling; i++) {
502  r1 = (Int_t) TMath::Min(i, numberIterationsX), r2 =
503  (Int_t) TMath::Min(i, numberIterationsY);
504  for (y = r2; y < ssizey - r2; y++) {
505  for (x = r1; x < ssizex - r1; x++) {
506  a = spectrum[x][y];
507  p1 = spectrum[x - r1][y - r2];
508  p2 = spectrum[x - r1][y + r2];
509  p3 = spectrum[x + r1][y - r2];
510  p4 = spectrum[x + r1][y + r2];
511  s1 = spectrum[x][y - r2];
512  s2 = spectrum[x - r1][y];
513  s3 = spectrum[x + r1][y];
514  s4 = spectrum[x][y + r2];
515  b = (p1 + p2) / 2.0;
516  if (b > s2)
517  s2 = b;
518  b = (p1 + p3) / 2.0;
519  if (b > s1)
520  s1 = b;
521  b = (p2 + p4) / 2.0;
522  if (b > s4)
523  s4 = b;
524  b = (p3 + p4) / 2.0;
525  if (b > s3)
526  s3 = b;
527  s1 = s1 - (p1 + p3) / 2.0;
528  s2 = s2 - (p1 + p2) / 2.0;
529  s3 = s3 - (p3 + p4) / 2.0;
530  s4 = s4 - (p2 + p4) / 2.0;
531  b = (s1 + s4) / 2.0 + (s2 + s3) / 2.0 + (p1 + p2 +
532  p3 +
533  p4) / 4.0;
534  if (b < a && b > 0)
535  a = b;
536  working_space[x][y] = a;
537  }
538  }
539  for (y = r2; y < ssizey - r2; y++) {
540  for (x = r1; x < ssizex - r1; x++) {
541  spectrum[x][y] = working_space[x][y];
542  }
543  }
544  }
545  }
546 
547  else if (filterType == kBackOneStepFiltering) {
548  for (i = 1; i <= sampling; i++) {
549  r1 = (Int_t) TMath::Min(i, numberIterationsX), r2 =
550  (Int_t) TMath::Min(i, numberIterationsY);
551  for (y = r2; y < ssizey - r2; y++) {
552  for (x = r1; x < ssizex - r1; x++) {
553  a = spectrum[x][y];
554  b = -(spectrum[x - r1][y - r2] +
555  spectrum[x - r1][y + r2] + spectrum[x + r1][y -
556  r2]
557  + spectrum[x + r1][y + r2]) / 4 +
558  (spectrum[x][y - r2] + spectrum[x - r1][y] +
559  spectrum[x + r1][y] + spectrum[x][y + r2]) / 2;
560  if (b < a && b > 0)
561  a = b;
562  working_space[x][y] = a;
563  }
564  }
565  for (y = i; y < ssizey - i; y++) {
566  for (x = i; x < ssizex - i; x++) {
567  spectrum[x][y] = working_space[x][y];
568  }
569  }
570  }
571  }
572  }
573 
574  else if (direction == kBackDecreasingWindow) {
575  if (filterType == kBackSuccessiveFiltering) {
576  for (i = sampling; i >= 1; i--) {
577  r1 = (Int_t) TMath::Min(i, numberIterationsX), r2 =
578  (Int_t) TMath::Min(i, numberIterationsY);
579  for (y = r2; y < ssizey - r2; y++) {
580  for (x = r1; x < ssizex - r1; x++) {
581  a = spectrum[x][y];
582  p1 = spectrum[x - r1][y - r2];
583  p2 = spectrum[x - r1][y + r2];
584  p3 = spectrum[x + r1][y - r2];
585  p4 = spectrum[x + r1][y + r2];
586  s1 = spectrum[x][y - r2];
587  s2 = spectrum[x - r1][y];
588  s3 = spectrum[x + r1][y];
589  s4 = spectrum[x][y + r2];
590  b = (p1 + p2) / 2.0;
591  if (b > s2)
592  s2 = b;
593  b = (p1 + p3) / 2.0;
594  if (b > s1)
595  s1 = b;
596  b = (p2 + p4) / 2.0;
597  if (b > s4)
598  s4 = b;
599  b = (p3 + p4) / 2.0;
600  if (b > s3)
601  s3 = b;
602  s1 = s1 - (p1 + p3) / 2.0;
603  s2 = s2 - (p1 + p2) / 2.0;
604  s3 = s3 - (p3 + p4) / 2.0;
605  s4 = s4 - (p2 + p4) / 2.0;
606  b = (s1 + s4) / 2.0 + (s2 + s3) / 2.0 + (p1 + p2 +
607  p3 +
608  p4) / 4.0;
609  if (b < a && b > 0)
610  a = b;
611  working_space[x][y] = a;
612  }
613  }
614  for (y = r2; y < ssizey - r2; y++) {
615  for (x = r1; x < ssizex - r1; x++) {
616  spectrum[x][y] = working_space[x][y];
617  }
618  }
619  }
620  }
621 
622  else if (filterType == kBackOneStepFiltering) {
623  for (i = sampling; i >= 1; i--) {
624  r1 = (Int_t) TMath::Min(i, numberIterationsX), r2 =
625  (Int_t) TMath::Min(i, numberIterationsY);
626  for (y = r2; y < ssizey - r2; y++) {
627  for (x = r1; x < ssizex - r1; x++) {
628  a = spectrum[x][y];
629  b = -(spectrum[x - r1][y - r2] +
630  spectrum[x - r1][y + r2] + spectrum[x + r1][y -
631  r2]
632  + spectrum[x + r1][y + r2]) / 4 +
633  (spectrum[x][y - r2] + spectrum[x - r1][y] +
634  spectrum[x + r1][y] + spectrum[x][y + r2]) / 2;
635  if (b < a && b > 0)
636  a = b;
637  working_space[x][y] = a;
638  }
639  }
640  for (y = i; y < ssizey - i; y++) {
641  for (x = i; x < ssizex - i; x++) {
642  spectrum[x][y] = working_space[x][y];
643  }
644  }
645  }
646  }
647  }
648  for (i = 0; i < ssizex; i++)
649  delete[]working_space[i];
650  delete[]working_space;
651  return 0;
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 /// This function calculates smoothed spectrum from source spectrum
656 /// based on Markov chain method.
657 /// The result is placed in the array pointed by source pointer.
658 ///
659 /// Function parameters:
660 /// - source-pointer to the array of source spectrum
661 /// - ssizex-x length of source
662 /// - ssizey-y length of source
663 /// - averWindow-width of averaging smoothing window
664 ///
665 /// ### Smoothing
666 ///
667 /// Goal: Suppression of statistical fluctuations the algorithm is based on discrete
668 /// Markov chain, which has very simple invariant distribution
669 /// \f[
670 /// U_2 = \frac{p_{1.2}}{p_{2,1}}U_1, U_3 = \frac{p_{2,3}}{p_{3,2}}U_2 U_1, ... , U_n = \frac{p_{n-1,n}}{p_{n,n-1}}U_{n-1} ... U_2 U_1
671 /// \f]
672 /// \f$U_1\f$ being defined from the normalization condition \f$ \sum_{i=1}^{n} U_i = 1\f$
673 /// n is the length of the smoothed spectrum and
674 /// \f[
675 /// p_{i,i\pm1} = A_i \sum_{k=1}^{m} exp\left[\frac{y(i\pm k)-y(i)}{y(i\pm k)+y(i)}\right]
676 /// \f]
677 /// is the probability of the change of the peak position from channel i to the channel i+1.
678 /// \f$A_i\f$ is the normalization constant so that\f$ p_{i,i-1}+p_{i,i+1}=1\f$ and m is a width
679 /// of smoothing window. We have extended this algorithm to two dimensions.
680 ///
681 /// #### Reference:
682 ///
683 /// [1] Z.K. Silagadze, A new algorithm for automatic photopeak searches. NIM A 376 (1996), 451.
684 ///
685 /// ### Example 4 - script Smooth.c
686 ///
687 /// \image html TSpectrum2_Smoothing1.jpg Fig. 9 Original noisy spectrum.
688 /// \image html TSpectrum2_Smoothing2.jpg Fig. 10 Smoothed spectrum m=3 Peaks can hardly be observed. Peaks become apparent.
689 /// \image html TSpectrum2_Smoothing3.jpg Fig. 11 Smoothed spectrum m=5
690 /// \image html TSpectrum2_Smoothing4.jpg Fig.12 Smoothed spectrum m=7
691 ///
692 /// #### Script:
693 ///
694 /// Example to illustrate the Markov smoothing (class TSpectrum).
695 /// To execute this example, do
696 ///
697 /// `root > .x Smooth.C`
698 ///
699 /// ~~~ {.cpp}
700 /// #include <TSpectrum>
701 /// void Smooth() {
702 /// Int_t i, j;
703 /// Double_t nbinsx = 256;
704 /// Double_t nbinsy = 256;
705 /// Double_t xmin = 0;
706 /// Double_t xmax = (Double_t)nbinsx;
707 /// Double_t ymin = 0;
708 /// Double_t ymax = (Double_t)nbinsy;
709 /// Double_t** source = new Double_t*[nbinsx];
710 /// for (i=0;i<nbinsx;i++)
711 /// source[i] = new Double_t[nbinsy];
712 /// TH2F *smooth = new TH2F("smooth","Background estimation",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
713 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
714 /// smooth=(TH2F*) f->Get("smooth1;1");
715 /// TCanvas *Smoothing = new TCanvas("Smoothing","Markov smoothing",10,10,1000,700);
716 /// TSpectrum *s = new TSpectrum();
717 /// for (i = 0; i < nbinsx; i++){
718 /// for (j = 0; j < nbinsy; j++){
719 /// source[i][j] = smooth->GetBinContent(i + 1,j + 1);
720 /// }
721 /// }
722 /// s->SmoothMarkov(source,nbinsx,nbinsx,3); //5,7
723 /// for (i = 0; i < nbinsx; i++){
724 /// for (j = 0; j < nbinsy; j++)
725 /// smooth->SetBinContent(i + 1,j + 1, source[i][j]);
726 /// }
727 /// smooth->Draw("SURF");
728 /// }
729 /// ~~~
730 
731 const char* TSpectrum2::SmoothMarkov(Double_t **source, Int_t ssizex, Int_t ssizey, Int_t averWindow)
732 {
733 
734  Int_t xmin, xmax, ymin, ymax, i, j, l;
735  Double_t a, b, maxch;
736  Double_t nom, nip, nim, sp, sm, spx, spy, smx, smy, plocha = 0;
737  if(averWindow <= 0)
738  return "Averaging Window must be positive";
739  Double_t **working_space = new Double_t*[ssizex];
740  for(i = 0; i < ssizex; i++)
741  working_space[i] = new Double_t[ssizey];
742  xmin = 0;
743  xmax = ssizex - 1;
744  ymin = 0;
745  ymax = ssizey - 1;
746  for(i = 0, maxch = 0; i < ssizex; i++){
747  for(j = 0; j < ssizey; j++){
748  working_space[i][j] = 0;
749  if(maxch < source[i][j])
750  maxch = source[i][j];
751 
752  plocha += source[i][j];
753  }
754  }
755  if(maxch == 0) {
756  delete [] working_space;
757  return 0;
758  }
759 
760  nom = 0;
761  working_space[xmin][ymin] = 1;
762  for(i = xmin; i < xmax; i++){
763  nip = source[i][ymin] / maxch;
764  nim = source[i + 1][ymin] / maxch;
765  sp = 0,sm = 0;
766  for(l = 1; l <= averWindow; l++){
767  if((i + l) > xmax)
768  a = source[xmax][ymin] / maxch;
769 
770  else
771  a = source[i + l][ymin] / maxch;
772  b = a - nip;
773  if(a + nip <= 0)
774  a = 1;
775 
776  else
777  a = TMath::Sqrt(a + nip);
778  b = b / a;
779  b = TMath::Exp(b);
780  sp = sp + b;
781  if(i - l + 1 < xmin)
782  a = source[xmin][ymin] / maxch;
783 
784  else
785  a = source[i - l + 1][ymin] / maxch;
786  b = a - nim;
787  if(a + nim <= 0)
788  a = 1;
789 
790  else
791  a = TMath::Sqrt(a + nim);
792  b = b / a;
793  b = TMath::Exp(b);
794  sm = sm + b;
795  }
796  a = sp / sm;
797  a = working_space[i + 1][ymin] = a * working_space[i][ymin];
798  nom = nom + a;
799  }
800  for(i = ymin; i < ymax; i++){
801  nip = source[xmin][i] / maxch;
802  nim = source[xmin][i + 1] / maxch;
803  sp = 0,sm = 0;
804  for(l = 1; l <= averWindow; l++){
805  if((i + l) > ymax)
806  a = source[xmin][ymax] / maxch;
807 
808  else
809  a = source[xmin][i + l] / maxch;
810  b = a - nip;
811  if(a + nip <= 0)
812  a = 1;
813 
814  else
815  a = TMath::Sqrt(a + nip);
816  b = b / a;
817  b = TMath::Exp(b);
818  sp = sp + b;
819  if(i - l + 1 < ymin)
820  a = source[xmin][ymin] / maxch;
821 
822  else
823  a = source[xmin][i - l + 1] / maxch;
824  b = a - nim;
825  if(a + nim <= 0)
826  a = 1;
827 
828  else
829  a = TMath::Sqrt(a + nim);
830  b = b / a;
831  b = TMath::Exp(b);
832  sm = sm + b;
833  }
834  a = sp / sm;
835  a = working_space[xmin][i + 1] = a * working_space[xmin][i];
836  nom = nom + a;
837  }
838  for(i = xmin; i < xmax; i++){
839  for(j = ymin; j < ymax; j++){
840  nip = source[i][j + 1] / maxch;
841  nim = source[i + 1][j + 1] / maxch;
842  spx = 0,smx = 0;
843  for(l = 1; l <= averWindow; l++){
844  if(i + l > xmax)
845  a = source[xmax][j] / maxch;
846 
847  else
848  a = source[i + l][j] / maxch;
849  b = a - nip;
850  if(a + nip <= 0)
851  a = 1;
852 
853  else
854  a = TMath::Sqrt(a + nip);
855  b = b / a;
856  b = TMath::Exp(b);
857  spx = spx + b;
858  if(i - l + 1 < xmin)
859  a = source[xmin][j] / maxch;
860 
861  else
862  a = source[i - l + 1][j] / maxch;
863  b = a - nim;
864  if(a + nim <= 0)
865  a = 1;
866 
867  else
868  a = TMath::Sqrt(a + nim);
869  b = b / a;
870  b = TMath::Exp(b);
871  smx = smx + b;
872  }
873  spy = 0,smy = 0;
874  nip = source[i + 1][j] / maxch;
875  nim = source[i + 1][j + 1] / maxch;
876  for (l = 1; l <= averWindow; l++) {
877  if (j + l > ymax) a = source[i][ymax]/maxch;
878  else a = source[i][j + l] / maxch;
879  b = a - nip;
880  if (a + nip <= 0) a = 1;
881  else a = TMath::Sqrt(a + nip);
882  b = b / a;
883  b = TMath::Exp(b);
884  spy = spy + b;
885  if (j - l + 1 < ymin) a = source[i][ymin] / maxch;
886  else a = source[i][j - l + 1] / maxch;
887  b = a - nim;
888  if (a + nim <= 0) a = 1;
889  else a = TMath::Sqrt(a + nim);
890  b = b / a;
891  b = TMath::Exp(b);
892  smy = smy + b;
893  }
894  a = (spx * working_space[i][j + 1] + spy * working_space[i + 1][j]) / (smx +smy);
895  working_space[i + 1][j + 1] = a;
896  nom = nom + a;
897  }
898  }
899  for(i = xmin; i <= xmax; i++){
900  for(j = ymin; j <= ymax; j++){
901  working_space[i][j] = working_space[i][j] / nom;
902  }
903  }
904  for(i = 0;i < ssizex; i++){
905  for(j = 0; j < ssizey; j++){
906  source[i][j] = plocha * working_space[i][j];
907  }
908  }
909  for (i = 0; i < ssizex; i++)
910  delete[]working_space[i];
911  delete[]working_space;
912  return 0;
913 }
914 
915 ////////////////////////////////////////////////////////////////////////////////
916 /// This function calculates deconvolution from source spectrum
917 /// according to response spectrum
918 /// The result is placed in the matrix pointed by source pointer.
919 ///
920 /// Function parameters:
921 /// - source-pointer to the matrix of source spectrum
922 /// - resp-pointer to the matrix of response spectrum
923 /// - ssizex-x length of source and response spectra
924 /// - ssizey-y length of source and response spectra
925 /// - numberIterations, for details we refer to manual
926 /// - numberRepetitions, for details we refer to manual
927 /// - boost, boosting factor, for details we refer to manual
928 ///
929 /// ### Deconvolution
930 ///
931 /// Goal: Improvement of the resolution in spectra, decomposition of multiplets
932 ///
933 /// Mathematical formulation of the 2-dimensional convolution system is
934 ///
935 ///\f[
936 /// y(i_1,i_2) = \sum_{k_1=0}^{N_1-1} \sum_{k_2=0}^{N_2-1} h(i_1-k_1,i_2-k_2)x(k_1,k_2)
937 ///\f]
938 ///\f[
939 /// i_1 = 0,1,2, ... ,N_1-1, i_2 = 0,1,2, ... ,N_2-1
940 ///\f]
941 ///
942 /// where h(i,j) is the impulse response function, x, y are input and output
943 /// matrices, respectively, \f$ N_1, N_2\f$ are the lengths of x and h matrices
944 ///
945 /// - let us assume that we know the response and the output matrices (spectra) of the above given system.
946 /// - the deconvolution represents solution of the overdetermined system of linear equations, i.e., the
947 /// calculation of the matrix x.
948 /// - from numerical stability point of view the operation of deconvolution is
949 /// extremely critical (ill-posed problem) as well as time consuming operation.
950 /// - the Gold deconvolution algorithm proves to work very well even for 2-dimensional
951 /// systems. Generalisation of the algorithm for 2-dimensional systems was presented in [1], [2].
952 /// - for Gold deconvolution algorithm as well as for boosted deconvolution algorithm we refer also to TSpectrum
953 ///
954 /// #### References:
955 ///
956 /// [1] M. Morhac;, J. Kliman, V. Matouoek, M. Veselsky, I. Turzo.:
957 /// Efficient one- and two-dimensional Gold deconvolution and its application to
958 /// gamma-ray spectra decomposition. NIM, A401 (1997) 385-408.
959 ///
960 /// [2] Morhac; M., Matouoek V., Kliman J., Efficient algorithm of multidimensional
961 /// deconvolution and its application to nuclear data processing, Digital Signal
962 /// Processing 13 (2003) 144.
963 ///
964 /// ### Example 5 - script Decon.c
965 ///
966 /// response function (usually peak) should be shifted to the beginning of the coordinate system (see Fig. 13)
967 ///
968 /// \image html TSpectrum2_Deconvolution1.jpg Fig. 13 2-dimensional response spectrum
969 /// \image html TSpectrum2_Deconvolution2.jpg Fig. 14 2-dimensional gamma-gamma-ray input spectrum (before deconvolution)
970 /// \image html TSpectrum2_Deconvolution3.jpg Fig. 15 Spectrum from Fig. 14 after deconvolution (1000 iterations)
971 ///
972 /// #### Script:
973 ///
974 /// Example to illustrate the Gold deconvolution (class TSpectrum2).
975 /// To execute this example, do
976 ///
977 /// `root > .x Decon.C`
978 ///
979 /// ~~~ {.cpp}
980 /// #include <TSpectrum2>
981 /// void Decon() {
982 /// Int_t i, j;
983 /// Double_t nbinsx = 256;
984 /// Double_t nbinsy = 256;
985 /// Double_t xmin = 0;
986 /// Double_t xmax = (Double_t)nbinsx;
987 /// Double_t ymin = 0;
988 /// Double_t ymax = (Double_t)nbinsy;
989 /// Double_t** source = new Double_t*[nbinsx];
990 /// for (i=0;i<nbinsx;i++)
991 /// source[i]=new Double_t[nbinsy];
992 /// TH2F *decon = new TH2F("decon","Gold deconvolution",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
993 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
994 /// decon=(TH2F*) f->Get("decon1;1");
995 /// Double_t** response = new Double_t*[nbinsx];
996 /// for (i=0;i<nbinsx;i++)
997 /// response[i]=new Double_t[nbinsy];
998 /// TH2F *resp = new TH2F("resp","Response matrix",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
999 /// resp=(TH2F*) f->Get("resp1;1");
1000 /// TCanvas *Deconvol = new TCanvas("Deconvolution","Gold deconvolution",10,10,1000,700);
1001 /// TSpectrum *s = new TSpectrum();
1002 /// for (i = 0; i < nbinsx; i++){
1003 /// for (j = 0; j < nbinsy; j++){
1004 /// source[i][j] = decon->GetBinContent(i + 1,j + 1);
1005 /// }
1006 /// }
1007 /// for (i = 0; i < nbinsx; i++){
1008 /// for (j = 0; j < nbinsy; j++){
1009 /// response[i][j] = resp->GetBinContent(i + 1,j + 1);
1010 /// }
1011 /// }
1012 /// s->Deconvolution(source,response,nbinsx,nbinsy,1000,1,1);
1013 /// for (i = 0; i < nbinsx; i++){
1014 /// for (j = 0; j < nbinsy; j++)
1015 /// decon->SetBinContent(i + 1,j + 1, source[i][j]);
1016 /// }
1017 /// decon->Draw("SURF");
1018 /// }
1019 /// ~~~
1020 ///
1021 /// ### Example 6 - script Decon2.c
1022 ///
1023 /// \image html TSpectrum2_Deconvolution4.jpg Fig. 16 Response spectrum
1024 /// \image html TSpectrum2_Deconvolution5.jpg Fig. 17 Original synthetic input spectrum (before deconvolution). It is composed of 17 peaks. 5 peaks are overlapping in the outlined multiplet and two peaks in doublet.
1025 /// \image html TSpectrum2_Deconvolution6.jpg Fig. 18 Spectrum from Fig. 17 after deconvolution (1000 iterations). Resolution is improved but the peaks in multiplet remained unresolved.
1026 ///
1027 /// #### Script:
1028 ///
1029 /// Example to illustrate the Gold deconvolution (class TSpectrum2).
1030 /// To execute this example, do
1031 ///
1032 /// `root > .x Decon2.C`
1033 ///
1034 /// ~~~ {.cpp}
1035 /// #include <TSpectrum2>
1036 /// void Decon2() {
1037 /// Int_t i, j;
1038 /// Double_t nbinsx = 64;
1039 /// Double_t nbinsy = 64;
1040 /// Double_t xmin = 0;
1041 /// Double_t xmax = (Double_t)nbinsx;
1042 /// Double_t ymin = 0;
1043 /// Double_t ymax = (Double_t)nbinsy;
1044 /// Double_t** source = new Double_t*[nbinsx];
1045 /// for (i=0;i<nbinsx;i++)
1046 /// source[i]=new Double_t[nbinsy];
1047 /// TH2F *decon = new TH2F("decon","Gold deconvolution",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1048 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1049 /// decon=(TH2F*) f->Get("decon2;1");
1050 /// Double_t** response = new Double_t*[nbinsx];
1051 /// for (i=0;i<nbinsx;i++)
1052 /// response[i]=new Double_t[nbinsy];
1053 /// TH2F *resp = new TH2F("resp","Response matrix",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1054 /// resp=(TH2F*) f->Get("resp2;1");
1055 /// TCanvas *Deconvol = new TCanvas("Deconvolution","Gold deconvolution",10,10,1000,700);
1056 /// TSpectrum *s = new TSpectrum();
1057 /// for (i = 0; i < nbinsx; i++){
1058 /// for (j = 0; j < nbinsy; j++){
1059 /// source[i][j] = decon->GetBinContent(i + 1,j + 1);
1060 /// }
1061 /// }
1062 /// for (i = 0; i < nbinsx; i++){
1063 /// for (j = 0; j < nbinsy; j++){
1064 /// response[i][j] = resp->GetBinContent(i + 1,j + 1);
1065 /// }
1066 /// }
1067 /// s->Deconvolution(source,response,nbinsx,nbinsy,1000,1,1);
1068 /// for (i = 0; i < nbinsx; i++){
1069 /// for (j = 0; j < nbinsy; j++)
1070 /// decon->SetBinContent(i + 1,j + 1, source[i][j]);
1071 /// }
1072 /// decon->Draw("SURF");
1073 /// }
1074 /// ~~~
1075 ///
1076 /// ### Example 7 - script Decon2HR.c
1077 ///
1078 /// \image html TSpectrum2_Deconvolution7.jpg Fig. 19 Spectrum from Fig. 17 after boosted deconvolution (50 iterations repeated 20 times, boosting coefficient was 1.2). All the peaks in multiplet as well as in doublet are completely decomposed.
1079 ///
1080 /// #### Script:
1081 ///
1082 /// Example to illustrate boosted Gold deconvolution (class TSpectrum2).
1083 /// To execute this example, do
1084 ///
1085 /// `root > .x Decon2HR.C`
1086 ///
1087 /// ~~~ {.cpp}
1088 /// #include <TSpectrum2>
1089 /// void Decon2HR() {
1090 /// Int_t i, j;
1091 /// Double_t nbinsx = 64;
1092 /// Double_t nbinsy = 64;
1093 /// Double_t xmin = 0;
1094 /// Double_t xmax = (Double_t)nbinsx;
1095 /// Double_t ymin = 0;
1096 /// Double_t ymax = (Double_t)nbinsy;
1097 /// Double_t** source = new Double_t*[nbinsx];
1098 /// for (i=0;i<nbinsx;i++)
1099 /// source[i]=new Double_t[nbinsy];
1100 /// TH2F *decon = new TH2F("decon","Boosted Gold deconvolution",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1101 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1102 /// decon=(TH2F*) f->Get("decon2;1");
1103 /// Double_t** response = new Double_t*[nbinsx];
1104 /// for (i=0;i<nbinsx;i++)
1105 /// response[i]=new Double_t[nbinsy];
1106 /// TH2F *resp = new TH2F("resp","Response matrix",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1107 /// resp=(TH2F*) f->Get("resp2;1");
1108 /// TCanvas *Deconvol = new TCanvas("Deconvolution","Gold deconvolution",10,10,1000,700);
1109 /// TSpectrum *s = new TSpectrum();
1110 /// for (i = 0; i < nbinsx; i++){
1111 /// for (j = 0; j < nbinsy; j++){
1112 /// source[i][j] = decon->GetBinContent(i + 1,j + 1);
1113 /// }
1114 /// }
1115 /// for (i = 0; i < nbinsx; i++){
1116 /// for (j = 0; j < nbinsy; j++){
1117 /// response[i][j] = resp->GetBinContent(i + 1,j + 1);
1118 /// }
1119 /// }
1120 /// s->Deconvolution(source,response,nbinsx,nbinsy,1000,1,1);
1121 /// for (i = 0; i < nbinsx; i++){
1122 /// for (j = 0; j < nbinsy; j++)
1123 /// dec on->SetBinContent(i + 1,j + 1, source[i][j]);
1124 /// }
1125 /// decon->Draw("SURF");
1126 /// }
1127 /// ~~~
1128 
1129 const char *TSpectrum2::Deconvolution(Double_t **source, Double_t **resp,
1130  Int_t ssizex, Int_t ssizey,
1131  Int_t numberIterations,
1132  Int_t numberRepetitions,
1133  Double_t boost)
1134 {
1135  Int_t i, j, lhx, lhy, i1, i2, j1, j2, k1, k2, lindex, i1min, i1max,
1136  i2min, i2max, j1min, j1max, j2min, j2max, positx = 0, posity = 0, repet;
1137  Double_t lda, ldb, ldc, area, maximum = 0;
1138  if (ssizex <= 0 || ssizey <= 0)
1139  return "Wrong parameters";
1140  if (numberIterations <= 0)
1141  return "Number of iterations must be positive";
1142  if (numberRepetitions <= 0)
1143  return "Number of repetitions must be positive";
1144  Double_t **working_space = new Double_t *[ssizex];
1145  for (i = 0; i < ssizex; i++)
1146  working_space[i] = new Double_t[5 * ssizey];
1147  area = 0;
1148  lhx = -1, lhy = -1;
1149  for (i = 0; i < ssizex; i++) {
1150  for (j = 0; j < ssizey; j++) {
1151  lda = resp[i][j];
1152  if (lda != 0) {
1153  if ((i + 1) > lhx)
1154  lhx = i + 1;
1155  if ((j + 1) > lhy)
1156  lhy = j + 1;
1157  }
1158  working_space[i][j] = lda;
1159  area = area + lda;
1160  if (lda > maximum) {
1161  maximum = lda;
1162  positx = i, posity = j;
1163  }
1164  }
1165  }
1166  if (lhx == -1 || lhy == -1) {
1167  delete [] working_space;
1168  return ("Zero response data");
1169  }
1170 
1171 //calculate ht*y and write into p
1172  for (i2 = 0; i2 < ssizey; i2++) {
1173  for (i1 = 0; i1 < ssizex; i1++) {
1174  ldc = 0;
1175  for (j2 = 0; j2 <= (lhy - 1); j2++) {
1176  for (j1 = 0; j1 <= (lhx - 1); j1++) {
1177  k2 = i2 + j2, k1 = i1 + j1;
1178  if (k2 >= 0 && k2 < ssizey && k1 >= 0 && k1 < ssizex) {
1179  lda = working_space[j1][j2];
1180  ldb = source[k1][k2];
1181  ldc = ldc + lda * ldb;
1182  }
1183  }
1184  }
1185  working_space[i1][i2 + ssizey] = ldc;
1186  }
1187  }
1188 
1189 //calculate matrix b=ht*h
1190  i1min = -(lhx - 1), i1max = lhx - 1;
1191  i2min = -(lhy - 1), i2max = lhy - 1;
1192  for (i2 = i2min; i2 <= i2max; i2++) {
1193  for (i1 = i1min; i1 <= i1max; i1++) {
1194  ldc = 0;
1195  j2min = -i2;
1196  if (j2min < 0)
1197  j2min = 0;
1198  j2max = lhy - 1 - i2;
1199  if (j2max > lhy - 1)
1200  j2max = lhy - 1;
1201  for (j2 = j2min; j2 <= j2max; j2++) {
1202  j1min = -i1;
1203  if (j1min < 0)
1204  j1min = 0;
1205  j1max = lhx - 1 - i1;
1206  if (j1max > lhx - 1)
1207  j1max = lhx - 1;
1208  for (j1 = j1min; j1 <= j1max; j1++) {
1209  lda = working_space[j1][j2];
1210  if (i1 + j1 < ssizex && i2 + j2 < ssizey)
1211  ldb = working_space[i1 + j1][i2 + j2];
1212  else
1213  ldb = 0;
1214  ldc = ldc + lda * ldb;
1215  }
1216  }
1217  working_space[i1 - i1min][i2 - i2min + 2 * ssizey ] = ldc;
1218  }
1219  }
1220 
1221 //initialization in x1 matrix
1222  for (i2 = 0; i2 < ssizey; i2++) {
1223  for (i1 = 0; i1 < ssizex; i1++) {
1224  working_space[i1][i2 + 3 * ssizey] = 1;
1225  working_space[i1][i2 + 4 * ssizey] = 0;
1226  }
1227  }
1228 
1229  //START OF ITERATIONS
1230  for (repet = 0; repet < numberRepetitions; repet++) {
1231  if (repet != 0) {
1232  for (i = 0; i < ssizex; i++) {
1233  for (j = 0; j < ssizey; j++) {
1234  working_space[i][j + 3 * ssizey] =
1235  TMath::Power(working_space[i][j + 3 * ssizey], boost);
1236  }
1237  }
1238  }
1239  for (lindex = 0; lindex < numberIterations; lindex++) {
1240  for (i2 = 0; i2 < ssizey; i2++) {
1241  for (i1 = 0; i1 < ssizex; i1++) {
1242  ldb = 0;
1243  j2min = i2;
1244  if (j2min > lhy - 1)
1245  j2min = lhy - 1;
1246  j2min = -j2min;
1247  j2max = ssizey - i2 - 1;
1248  if (j2max > lhy - 1)
1249  j2max = lhy - 1;
1250  j1min = i1;
1251  if (j1min > lhx - 1)
1252  j1min = lhx - 1;
1253  j1min = -j1min;
1254  j1max = ssizex - i1 - 1;
1255  if (j1max > lhx - 1)
1256  j1max = lhx - 1;
1257  for (j2 = j2min; j2 <= j2max; j2++) {
1258  for (j1 = j1min; j1 <= j1max; j1++) {
1259  ldc = working_space[j1 - i1min][j2 - i2min + 2 * ssizey];
1260  lda = working_space[i1 + j1][i2 + j2 + 3 * ssizey];
1261  ldb = ldb + lda * ldc;
1262  }
1263  }
1264  lda = working_space[i1][i2 + 3 * ssizey];
1265  ldc = working_space[i1][i2 + 1 * ssizey];
1266  if (ldc * lda != 0 && ldb != 0) {
1267  lda = lda * ldc / ldb;
1268  }
1269 
1270  else
1271  lda = 0;
1272  working_space[i1][i2 + 4 * ssizey] = lda;
1273  }
1274  }
1275  for (i2 = 0; i2 < ssizey; i2++) {
1276  for (i1 = 0; i1 < ssizex; i1++)
1277  working_space[i1][i2 + 3 * ssizey] =
1278  working_space[i1][i2 + 4 * ssizey];
1279  }
1280  }
1281  }
1282  for (i = 0; i < ssizex; i++) {
1283  for (j = 0; j < ssizey; j++)
1284  source[(i + positx) % ssizex][(j + posity) % ssizey] =
1285  area * working_space[i][j + 3 * ssizey];
1286  }
1287  for (i = 0; i < ssizex; i++)
1288  delete[]working_space[i];
1289  delete[]working_space;
1290  return 0;
1291 }
1292 
1293 ////////////////////////////////////////////////////////////////////////////////
1294 /// This function searches for peaks in source spectrum
1295 /// It is based on deconvolution method. First the background is
1296 /// removed (if desired), then Markov spectrum is calculated
1297 /// (if desired), then the response function is generated
1298 /// according to given sigma and deconvolution is carried out.
1299 ///
1300 /// Function parameters:
1301 /// - source-pointer to the matrix of source spectrum
1302 /// - dest-pointer to the matrix of resulting deconvolved spectrum
1303 /// - ssizex-x length of source spectrum
1304 /// - ssizey-y length of source spectrum
1305 /// - sigma-sigma of searched peaks, for details we refer to manual
1306 /// - threshold-threshold value in % for selected peaks, peaks with
1307 /// amplitude less than threshold*highest_peak/100
1308 /// are ignored, see manual
1309 /// - backgroundRemove-logical variable, set if the removal of
1310 /// background before deconvolution is desired
1311 /// - deconIterations-number of iterations in deconvolution operation
1312 /// - markov-logical variable, if it is true, first the source spectrum
1313 /// is replaced by new spectrum calculated using Markov
1314 /// chains method.
1315 /// - averWindow-averaging window of searched peaks, for details
1316 /// we refer to manual (applies only for Markov method)
1317 ///
1318 /// ### Peaks searching
1319 ///
1320 /// Goal: to identify automatically the peaks in spectrum with the presence of the
1321 /// continuous background, one-fold coincidences (ridges) and statistical
1322 /// fluctuations - noise.
1323 ///
1324 /// The common problems connected with correct peak identification in two-dimensional coincidence spectra are
1325 ///
1326 /// - non-sensitivity to noise, i.e., only statistically relevant peaks should be identified
1327 /// - non-sensitivity of the algorithm to continuous background
1328 /// - non-sensitivity to one-fold coincidences (coincidences peak - background in both dimensions) and their crossings
1329 /// - ability to identify peaks close to the edges of the spectrum region. Usually peak finders fail to detect them
1330 /// - resolution, decomposition of doublets and multiplets. The algorithm should be able to recognise close positioned peaks.
1331 /// - ability to identify peaks with different sigma
1332 ///
1333 /// #### References:
1334 ///
1335 /// [1] M.A. Mariscotti: A method for identification of peaks in the presence of
1336 /// background and its application to spectrum analysis. NIM 50 (1967), 309-320.
1337 ///
1338 /// [2] M. Morhac;, J. Kliman, V. Matouoek, M. Veselsky, I. Turzo.:Identification
1339 /// of peaks in multidimensional coincidence gamma-ray spectra. NIM, A443 (2000)
1340 /// 108-125.
1341 ///
1342 /// [3] Z.K. Silagadze, A new algorithm for automatic photopeak searches. NIM A 376
1343 /// (1996), 451.
1344 ///
1345 /// ### Examples of peak searching method
1346 ///
1347 /// SearchHighRes function provides users with the possibility
1348 /// to vary the input parameters and with the access to the output deconvolved data
1349 /// in the destination spectrum. Based on the output data one can tune the
1350 /// parameters.
1351 ///
1352 /// ### Example 8 - script Src.c
1353 ///
1354 /// \image html TSpectrum2_Searching1.jpg Fig. 20 Two-dimensional spectrum with found peaks denoted by markers (sigma=2, threshold=5%, 3 iterations steps in the deconvolution)
1355 /// \image html TSpectrum2_Searching3.jpg Fig. 21 Spectrum from Fig. 20 after background elimination and deconvolution
1356 ///
1357 /// #### Script:
1358 ///
1359 /// Example to illustrate high resolution peak searching function (class TSpectrum).
1360 /// To execute this example, do
1361 ///
1362 /// `root > .x Src.C
1363 ///
1364 /// ~~~ {.cpp}
1365 /// #include <TSpectrum2>
1366 /// void Src() {
1367 /// Int_t i, j, nfound;
1368 /// Double_t nbinsx = 64;
1369 /// Double_t nbinsy = 64;
1370 /// Double_t xmin = 0;
1371 /// Double_t xmax = (Double_t)nbinsx;
1372 /// Double_t ymin = 0;
1373 /// Double_t ymax = (Double_t)nbinsy;
1374 /// Double_t** source = new Double_t*[nbinsx];
1375 /// for (i=0;i<nbinsx;i++)
1376 /// source[i]=new Double_t[nbinsy];
1377 /// Double_t** dest = new Double_t*[nbinsx];
1378 /// for (i=0;i<nbinsx;i++)
1379 /// dest[i]=new Double_t[nbinsy];
1380 /// TH2F *search = new TH2F("search","High resolution peak searching",nbinsx,xmin,xmax,nbinsy,ymin,ymax);/
1381 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1382 /// search=(TH2F*) f->Get("search4;1");
1383 /// TCanvas *Searching = new TCanvas("Searching","High resolution peak searching",10,10,1000,700);
1384 /// TSpectrum2 *s = new TSpectrum2();
1385 /// for (i = 0; i < nbinsx; i++){
1386 /// for (j = 0; j < nbinsy; j++){
1387 /// source[i][j] = search->GetBinContent(i + 1,j + 1);
1388 /// }
1389 /// }
1390 /// nfound = s->SearchHighRes(source, dest, nbinsx, nbinsy, 2, 5, kTRUE, 3, kFALSE, 3);
1391 /// printf("Found %d candidate peaks\n",nfound);
1392 /// for(i=0;i<nfound;i++)
1393 /// printf("posx= %d, posy= %d, value=%d\n",(Int_t)(fPositionX[i]+0.5), (Int_t)(fPositionY[i]+0.5),
1394 /// (Int_t)source[(Int_t)(fPositionX[i]+0.5)][(Int_t)(fPositionY[i]+0.5)]);
1395 /// }
1396 /// ~~~
1397 ///
1398 /// ### Example 9 - script Src2.c
1399 ///
1400 /// \image html TSpectrum2_Searching4.jpg Fig. 22 Two-dimensional noisy spectrum with found peaks denoted by markers (sigma=2, threshold=10%, 10 iterations steps in the deconvolution). One can observe that the algorithm is insensitive to the crossings of one-dimensional ridges. It identifies only two-coincidence peaks.
1401 /// \image html TSpectrum2_Searching5.jpg Fig. 23 Spectrum from Fig. 22 after background elimination and deconvolution
1402 ///
1403 /// #### Script:
1404 ///
1405 /// Example to illustrate high resolution peak searching function (class TSpectrum).
1406 /// To execute this example, do
1407 ///
1408 /// `root > .x Src2.C`
1409 ///
1410 /// ~~~ {.cpp}
1411 /// #include <TSpectrum2>
1412 /// void Src2() {
1413 /// Int_t i, j, nfound;
1414 /// Double_t nbinsx = 256;
1415 /// Double_t nbinsy = 256;
1416 /// Double_t xmin = 0;
1417 /// Double_t xmax = (Double_t)nbinsx;
1418 /// Double_t ymin = 0;
1419 /// Double_t ymax = (Double_t)nbinsy;
1420 /// Double_t** source = new Double_t*[nbinsx];
1421 /// for (i=0;i<nbinsx;i++)
1422 /// source[i]=new Double_t[nbinsy];
1423 /// Double_t** dest = new Double_t*[nbinsx];
1424 /// for (i=0;i<nbinsx;i++)
1425 /// dest[i]=new Double_t[nbinsy];
1426 /// TH2F *search = new TH2F("search","High resolution peak searching",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1427 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1428 /// search=(TH2F*) f->Get("back3;1");
1429 /// TCanvas *Searching = new TCanvas("Searching","High resolution peak searching",10,10,1000,700);
1430 /// TSpectrum2 *s = new TSpectrum2();
1431 /// for (i = 0; i < nbinsx; i++){
1432 /// for (j = 0; j < nbinsy; j++){
1433 /// source[i][j] = search->GetBinContent(i + 1,j + 1);
1434 /// }
1435 /// }
1436 /// nfound = s->SearchHighRes(source, dest, nbinsx, nbinsy, 2, 10, kTRUE, 10, kFALSE, 3);
1437 /// printf("Found %d candidate peaks\n",nfound);
1438 /// for(i=0;i<nfound;i++)
1439 /// printf("posx= %d, posy= %d, value=%d\n",(Int_t)(fPositionX[i]+0.5), (Int_t)(fPositionY[i]+0.5),
1440 /// (Int_t)source[(Int_t)(fPositionX[i]+0.5)][(Int_t)(fPositionY[i]+0.5)]);
1441 /// }
1442 /// ~~~
1443 ///
1444 /// ### Example 10 - script Src3.c
1445 ///
1446 /// \image html TSpectrum2_Searching6.jpg Fig. 24 Two-dimensional spectrum with 15 found peaks denoted by markers. Some peaks are positioned close to each other. It is necessary to increase number of iterations in the deconvolution. In next 3 Figs. we shall study the influence of this parameter.
1447 /// \image html TSpectrum2_Searching7.jpg Fig. 25 Spectrum from Fig. 24 after deconvolution (# of iterations = 3). Number of identified peaks = 13.
1448 /// \image html TSpectrum2_Searching8.jpg Fig. 26 Spectrum from Fig. 24 after deconvolution (# of iterations = 10). Number of identified peaks = 13.
1449 /// \image html TSpectrum2_Searching9.jpg Fig. 27 Spectrum from Fig. 24 after deconvolution (# of iterations = 100). Number of identified peaks = 15. Now the algorithm is able to decompose two doublets in the spectrum.
1450 ///
1451 /// #### Script:
1452 ///
1453 /// Example to illustrate high resolution peak searching function (class TSpectrum).
1454 /// To execute this example, do
1455 ///
1456 /// `root > .x Src3.C`
1457 ///
1458 /// ~~~ {.cpp}
1459 /// #include <TSpectrum2>
1460 /// void Src3() {
1461 /// Int_t i, j, nfound;
1462 /// Double_t nbinsx = 64;
1463 /// Double_t nbinsy = 64;
1464 /// Double_t xmin = 0;
1465 /// Double_t xmax = (Double_t)nbinsx;
1466 /// Double_t ymin = 0;
1467 /// Double_t ymax = (Double_t)nbinsy;
1468 /// Double_t** source = new Double_t*[nbinsx];
1469 /// for (i=0;i<nbinsx;i++)
1470 /// source[i]=new Double_t[nbinsy];
1471 /// Double_t** dest = new Double_t*[nbinsx];
1472 /// for (i=0;i<nbinsx;i++)
1473 /// dest[i]=new Double_t[nbinsy];
1474 /// TH2F *search = new TH2F("search","High resolution peak searching",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1475 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1476 /// search=(TH2F*) f->Get("search1;1");
1477 /// TCanvas *Searching = new TCanvas("Searching","High resolution peak searching",10,10,1000,700);
1478 /// TSpectrum2 *s = new TSpectrum2();
1479 /// for (i = 0; i < nbinsx; i++){
1480 /// for (j = 0; j < nbinsy; j++){
1481 /// source[i][j] = search->GetBinContent(i + 1,j + 1);
1482 /// }
1483 /// }
1484 /// nfound = s->SearchHighRes(source, dest, nbinsx, nbinsy, 2, 2, kFALSE, 3, kFALSE, 1);//3, 10, 100
1485 /// printf("Found %d candidate peaks\n",nfound);
1486 /// for(i=0;i<nfound;i++)
1487 /// printf("posx= %d, posy= %d, value=%d\n",(Int_t)(fPositionX[i]+0.5), (Int_t)(fPositionY[i]+0.5),
1488 /// (Int_t)source[(Int_t)(fPositionX[i]+0.5)][(Int_t)(fPositionY[i]+0.5)]);
1489 /// }
1490 /// ~~~
1491 ///
1492 /// ### Example 11 - script Src4.c
1493 ///
1494 /// \image html TSpectrum2_Searching10.jpg Fig. 28 Two-dimensional spectrum with peaks with different sigma denoted by markers (sigma=3, threshold=5%, 10 iterations steps in the deconvolution, Markov smoothing with window=3)
1495 /// \image html TSpectrum2_Searching12.jpg Fig. 29 Spectrum from Fig. 28 after smoothing and deconvolution.
1496 ///
1497 /// #### Script:
1498 ///
1499 /// Example to illustrate high resolution peak searching function (class TSpectrum).
1500 /// To execute this example, do
1501 ///
1502 /// `root > .x Src4.C`
1503 ///
1504 /// ~~~ {.cpp}
1505 /// #include <TSpectrum2>
1506 /// void Src4() {
1507 /// Int_t i, j, nfound;
1508 /// Double_t nbinsx = 64;
1509 /// Double_t nbinsy = 64;
1510 /// Double_t xmin = 0;
1511 /// Double_t xmax = (Double_t)nbinsx;
1512 /// Double_t ymin = 0;
1513 /// Double_t ymax = (Double_t)nbinsy;
1514 /// Double_t** source = new Double_t*[nbinsx];
1515 /// for (i=0;i<nbinsx;i++)
1516 /// source[i]=new Double_t[nbinsy];
1517 /// Double_t** dest = new Double_t*[nbinsx];
1518 /// for (i=0;i<nbinsx;i++)
1519 /// dest[i]=new Double_t[nbinsy];
1520 /// TH2F *search = new TH2F("search","High resolution peak searching",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1521 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1522 /// search=(TH2F*) f->Get("search2;1");
1523 /// TCanvas *Searching = new TCanvas("Searching","High resolution peak searching",10,10,1000,700);
1524 /// TSpectrum2 *s = new TSpectrum2();
1525 /// for (i = 0; i < nbinsx; i++){
1526 /// for (j = 0; j < nbinsy; j++){
1527 /// source[i][j] = search->GetBinContent(i + 1,j + 1);
1528 /// }
1529 /// }
1530 /// nfound = s->SearchHighRes(source, dest, nbinsx, nbinsy, 3, 5, kFALSE, 10, kTRUE, 3);
1531 /// printf("Found %d candidate peaks\n",nfound);
1532 /// for(i=0;i<nfound;i++)
1533 /// printf("posx= %d, posy= %d, value=%d\n",(Int_t)(fPositionX[i]+0.5), (Int_t)(fPositionY[i]+0.5),
1534 /// (Int_t)source[(Int_t)(fPositionX[i]+0.5)][(Int_t)(fPositionY[i]+0.5)]);
1535 /// }
1536 /// ~~~
1537 ///
1538 /// ### Example 12 - script Src5.c`
1539 ///
1540 /// \image html TSpectrum2_Searching13.jpg Fig. 30 Two-dimensional spectrum with peaks positioned close to the edges denoted by markers (sigma=2, threshold=5%, 10 iterations steps in the deconvolution)
1541 /// \image html TSpectrum2_Searching14.jpg Fig. 31 Spectrum from Fig. 30 after deconvolution.
1542 ///
1543 /// #### Script:
1544 ///
1545 /// Example to illustrate high resolution peak searching function (class TSpectrum).
1546 /// To execute this example, do
1547 ///
1548 /// `root > .x Src5.C`
1549 ///
1550 /// ~~~ {.cpp}
1551 /// #include <TSpectrum2>
1552 /// void Src5() {
1553 /// Int_t i, j, nfound;
1554 /// Double_t nbinsx = 64;
1555 /// Double_t nbinsy = 64;
1556 /// Double_t xmin = 0;
1557 /// Double_t xmax = (Double_t)nbinsx;
1558 /// Double_t ymin = 0;
1559 /// Double_t ymax = (Double_t)nbinsy;
1560 /// Double_t** source = new Double_t*[nbinsx];
1561 /// for (i=0;i<nbinsx;i++)
1562 /// source[i]=new Double_t[nbinsy];
1563 /// Double_t** dest = new Double_t*[nbinsx];
1564 /// for (i=0;i<nbinsx;i++)
1565 /// dest[i]=new Double_t[nbinsy];
1566 /// TH2F *search = new TH2F("search","High resolution peak searching",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
1567 /// TFile *f = new TFile("spectra2/TSpectrum2.root");
1568 /// search=(TH2F*) f->Get("search3;1");
1569 /// TCanvas *Searching = new TCanvas("Searching","High resolution peak searching",10,10,1000,700);
1570 /// TSpectrum2 *s = new TSpectrum2();
1571 /// for (i = 0; i < nbinsx; i++){
1572 /// for (j = 0; j < nbinsy; j++){
1573 /// source[i][j] = search->GetBinContent(i + 1,j + 1);
1574 /// }
1575 /// }
1576 /// nfound = s->SearchHighRes(source, dest, nbinsx, nbinsy, 2, 5, kFALSE, 10, kFALSE, 1);
1577 /// printf("Found %d candidate peaks\n",nfound);
1578 /// for(i=0;i<nfound;i++)
1579 /// printf("posx= %d, posy= %d, value=%d\n",(Int_t)(fPositionX[i]+0.5), (Int_t)(fPositionY[i]+0.5),
1580 /// (Int_t)source[(Int_t)(fPositionX[i]+0.5)][(Int_t)(fPositionY[i]+0.5)]);
1581 /// }
1582 /// ~~~
1583 
1585  Double_t sigma, Double_t threshold,
1586  Bool_t backgroundRemove,Int_t deconIterations,
1587  Bool_t markov, Int_t averWindow)
1588 
1589 {
1590  Int_t number_of_iterations = (Int_t)(4 * sigma + 0.5);
1591  Int_t k, lindex, priz;
1592  Double_t lda, ldb, ldc, area, maximum;
1593  Int_t xmin, xmax, l, peak_index = 0, ssizex_ext = ssizex + 4 * number_of_iterations, ssizey_ext = ssizey + 4 * number_of_iterations, shift = 2 * number_of_iterations;
1594  Int_t ymin, ymax, i, j;
1595  Double_t a, b, ax, ay, maxch, plocha = 0;
1596  Double_t nom, nip, nim, sp, sm, spx, spy, smx, smy;
1597  Double_t p1, p2, p3, p4, s1, s2, s3, s4;
1598  Int_t x, y;
1599  Int_t lhx, lhy, i1, i2, j1, j2, k1, k2, i1min, i1max, i2min, i2max, j1min, j1max, j2min, j2max, positx, posity;
1600  if (sigma < 1) {
1601  Error("SearchHighRes", "Invalid sigma, must be greater than or equal to 1");
1602  return 0;
1603  }
1604 
1605  if(threshold<=0||threshold>=100){
1606  Error("SearchHighRes", "Invalid threshold, must be positive and less than 100");
1607  return 0;
1608  }
1609 
1610  j = (Int_t) (5.0 * sigma + 0.5);
1611  if (j >= PEAK_WINDOW / 2) {
1612  Error("SearchHighRes", "Too large sigma");
1613  return 0;
1614  }
1615 
1616  if (markov == true) {
1617  if (averWindow <= 0) {
1618  Error("SearchHighRes", "Averaging window must be positive");
1619  return 0;
1620  }
1621  }
1622  if(backgroundRemove == true){
1623  if(ssizex_ext < 2 * number_of_iterations + 1 || ssizey_ext < 2 * number_of_iterations + 1){
1624  Error("SearchHighRes", "Too large clipping window");
1625  return 0;
1626  }
1627  }
1628  i = (Int_t)(4 * sigma + 0.5);
1629  i = 4 * i;
1630  Double_t **working_space = new Double_t *[ssizex + i];
1631  for (j = 0; j < ssizex + i; j++) {
1632  Double_t *wsk = working_space[j] = new Double_t[16 * (ssizey + i)];
1633  for (k=0;k<16 * (ssizey + i);k++) wsk[k] = 0;
1634  }
1635  for(j = 0; j < ssizey_ext; j++){
1636  for(i = 0; i < ssizex_ext; i++){
1637  if(i < shift){
1638  if(j < shift)
1639  working_space[i][j + ssizey_ext] = source[0][0];
1640 
1641  else if(j >= ssizey + shift)
1642  working_space[i][j + ssizey_ext] = source[0][ssizey - 1];
1643 
1644  else
1645  working_space[i][j + ssizey_ext] = source[0][j - shift];
1646  }
1647 
1648  else if(i >= ssizex + shift){
1649  if(j < shift)
1650  working_space[i][j + ssizey_ext] = source[ssizex - 1][0];
1651 
1652  else if(j >= ssizey + shift)
1653  working_space[i][j + ssizey_ext] = source[ssizex - 1][ssizey - 1];
1654 
1655  else
1656  working_space[i][j + ssizey_ext] = source[ssizex - 1][j - shift];
1657  }
1658 
1659  else{
1660  if(j < shift)
1661  working_space[i][j + ssizey_ext] = source[i - shift][0];
1662 
1663  else if(j >= ssizey + shift)
1664  working_space[i][j + ssizey_ext] = source[i - shift][ssizey - 1];
1665 
1666  else
1667  working_space[i][j + ssizey_ext] = source[i - shift][j - shift];
1668  }
1669  }
1670  }
1671  if(backgroundRemove == true){
1672  for(i = 1; i <= number_of_iterations; i++){
1673  for(y = i; y < ssizey_ext - i; y++){
1674  for(x = i; x < ssizex_ext - i; x++){
1675  a = working_space[x][y + ssizey_ext];
1676  p1 = working_space[x - i][y + ssizey_ext - i];
1677  p2 = working_space[x - i][y + ssizey_ext + i];
1678  p3 = working_space[x + i][y + ssizey_ext - i];
1679  p4 = working_space[x + i][y + ssizey_ext + i];
1680  s1 = working_space[x][y + ssizey_ext - i];
1681  s2 = working_space[x - i][y + ssizey_ext];
1682  s3 = working_space[x + i][y + ssizey_ext];
1683  s4 = working_space[x][y + ssizey_ext + i];
1684  b = (p1 + p2) / 2.0;
1685  if(b > s2)
1686  s2 = b;
1687  b = (p1 + p3) / 2.0;
1688  if(b > s1)
1689  s1 = b;
1690  b = (p2 + p4) / 2.0;
1691  if(b > s4)
1692  s4 = b;
1693  b = (p3 + p4) / 2.0;
1694  if(b > s3)
1695  s3 = b;
1696  s1 = s1 - (p1 + p3) / 2.0;
1697  s2 = s2 - (p1 + p2) / 2.0;
1698  s3 = s3 - (p3 + p4) / 2.0;
1699  s4 = s4 - (p2 + p4) / 2.0;
1700  b = (s1 + s4) / 2.0 + (s2 + s3) / 2.0 + (p1 + p2 + p3 + p4) / 4.0;
1701  if(b < a)
1702  a = b;
1703  working_space[x][y] = a;
1704  }
1705  }
1706  for(y = i;y < ssizey_ext - i; y++){
1707  for(x = i; x < ssizex_ext - i; x++){
1708  working_space[x][y + ssizey_ext] = working_space[x][y];
1709  }
1710  }
1711  }
1712  for(j = 0;j < ssizey_ext; j++){
1713  for(i = 0; i < ssizex_ext; i++){
1714  if(i < shift){
1715  if(j < shift)
1716  working_space[i][j + ssizey_ext] = source[0][0] - working_space[i][j + ssizey_ext];
1717 
1718  else if(j >= ssizey + shift)
1719  working_space[i][j + ssizey_ext] = source[0][ssizey - 1] - working_space[i][j + ssizey_ext];
1720 
1721  else
1722  working_space[i][j + ssizey_ext] = source[0][j - shift] - working_space[i][j + ssizey_ext];
1723  }
1724 
1725  else if(i >= ssizex + shift){
1726  if(j < shift)
1727  working_space[i][j + ssizey_ext] = source[ssizex - 1][0] - working_space[i][j + ssizey_ext];
1728 
1729  else if(j >= ssizey + shift)
1730  working_space[i][j + ssizey_ext] = source[ssizex - 1][ssizey - 1] - working_space[i][j + ssizey_ext];
1731 
1732  else
1733  working_space[i][j + ssizey_ext] = source[ssizex - 1][j - shift] - working_space[i][j + ssizey_ext];
1734  }
1735 
1736  else{
1737  if(j < shift)
1738  working_space[i][j + ssizey_ext] = source[i - shift][0] - working_space[i][j + ssizey_ext];
1739 
1740  else if(j >= ssizey + shift)
1741  working_space[i][j + ssizey_ext] = source[i - shift][ssizey - 1] - working_space[i][j + ssizey_ext];
1742 
1743  else
1744  working_space[i][j + ssizey_ext] = source[i - shift][j - shift] - working_space[i][j + ssizey_ext];
1745  }
1746  }
1747  }
1748  }
1749  for(j = 0; j < ssizey_ext; j++){
1750  for(i = 0; i < ssizex_ext; i++){
1751  working_space[i][j + 15*ssizey_ext] = working_space[i][j + ssizey_ext];
1752  }
1753  }
1754  if(markov == true){
1755  for(i = 0;i < ssizex_ext; i++){
1756  for(j = 0; j < ssizey_ext; j++)
1757  working_space[i][j + 2 * ssizex_ext] = working_space[i][ssizey_ext + j];
1758  }
1759  xmin = 0;
1760  xmax = ssizex_ext - 1;
1761  ymin = 0;
1762  ymax = ssizey_ext - 1;
1763  for(i = 0, maxch = 0; i < ssizex_ext; i++){
1764  for(j = 0; j < ssizey_ext; j++){
1765  working_space[i][j] = 0;
1766  if(maxch < working_space[i][j + 2 * ssizey_ext])
1767  maxch = working_space[i][j + 2 * ssizey_ext];
1768  plocha += working_space[i][j + 2 * ssizey_ext];
1769  }
1770  }
1771  if(maxch == 0) {
1772  delete [] working_space;
1773  return 0;
1774  }
1775 
1776  nom=0;
1777  working_space[xmin][ymin] = 1;
1778  for(i = xmin; i < xmax; i++){
1779  nip = working_space[i][ymin + 2 * ssizey_ext] / maxch;
1780  nim = working_space[i + 1][ymin + 2 * ssizey_ext] / maxch;
1781  sp = 0,sm = 0;
1782  for(l = 1;l <= averWindow; l++){
1783  if((i + l) > xmax)
1784  a = working_space[xmax][ymin + 2 * ssizey_ext] / maxch;
1785 
1786  else
1787  a = working_space[i + l][ymin + 2 * ssizey_ext] / maxch;
1788 
1789  b = a - nip;
1790  if(a + nip <= 0)
1791  a = 1;
1792 
1793  else
1794  a=TMath::Sqrt(a + nip);
1795  b = b / a;
1796  b = TMath::Exp(b);
1797  sp = sp + b;
1798  if(i - l + 1 < xmin)
1799  a = working_space[xmin][ymin + 2 * ssizey_ext] / maxch;
1800 
1801  else
1802  a = working_space[i - l + 1][ymin + 2 * ssizey_ext] / maxch;
1803  b = a - nim;
1804  if(a + nim <= 0)
1805  a = 1;
1806 
1807  else
1808  a=TMath::Sqrt(a + nim);
1809  b = b / a;
1810  b = TMath::Exp(b);
1811  sm = sm + b;
1812  }
1813  a = sp / sm;
1814  a = working_space[i + 1][ymin] = a * working_space[i][ymin];
1815  nom = nom + a;
1816  }
1817  for(i = ymin; i < ymax; i++){
1818  nip = working_space[xmin][i + 2 * ssizey_ext] / maxch;
1819  nim = working_space[xmin][i + 1 + 2 * ssizey_ext] / maxch;
1820  sp = 0,sm = 0;
1821  for(l = 1; l <= averWindow; l++){
1822  if((i + l) > ymax)
1823  a = working_space[xmin][ymax + 2 * ssizey_ext] / maxch;
1824 
1825  else
1826  a = working_space[xmin][i + l + 2 * ssizey_ext] / maxch;
1827  b = a - nip;
1828  if(a + nip <= 0)
1829  a=1;
1830 
1831  else
1832  a=TMath::Sqrt(a + nip);
1833  b = b / a;
1834  b = TMath::Exp(b);
1835  sp = sp + b;
1836  if(i - l + 1 < ymin)
1837  a = working_space[xmin][ymin + 2 * ssizey_ext] / maxch;
1838 
1839  else
1840  a = working_space[xmin][i - l + 1 + 2 * ssizey_ext] / maxch;
1841  b = a - nim;
1842  if(a + nim <= 0)
1843  a = 1;
1844 
1845  else
1846  a=TMath::Sqrt(a + nim);
1847  b = b / a;
1848  b = TMath::Exp(b);
1849  sm = sm + b;
1850  }
1851  a = sp / sm;
1852  a = working_space[xmin][i + 1] = a * working_space[xmin][i];
1853  nom = nom + a;
1854  }
1855  for(i = xmin; i < xmax; i++){
1856  for(j = ymin; j < ymax; j++){
1857  nip = working_space[i][j + 1 + 2 * ssizey_ext] / maxch;
1858  nim = working_space[i + 1][j + 1 + 2 * ssizey_ext] / maxch;
1859  spx = 0,smx = 0;
1860  for(l = 1; l <= averWindow; l++){
1861  if(i + l > xmax)
1862  a = working_space[xmax][j + 2 * ssizey_ext] / maxch;
1863 
1864  else
1865  a = working_space[i + l][j + 2 * ssizey_ext] / maxch;
1866  b = a - nip;
1867  if(a + nip <= 0)
1868  a = 1;
1869 
1870  else
1871  a=TMath::Sqrt(a + nip);
1872  b = b / a;
1873  b = TMath::Exp(b);
1874  spx = spx + b;
1875  if(i - l + 1 < xmin)
1876  a = working_space[xmin][j + 2 * ssizey_ext] / maxch;
1877 
1878  else
1879  a = working_space[i - l + 1][j + 2 * ssizey_ext] / maxch;
1880  b = a - nim;
1881  if(a + nim <= 0)
1882  a=1;
1883 
1884  else
1885  a=TMath::Sqrt(a + nim);
1886  b = b / a;
1887  b = TMath::Exp(b);
1888  smx = smx + b;
1889  }
1890  spy = 0,smy = 0;
1891  nip = working_space[i + 1][j + 2 * ssizey_ext] / maxch;
1892  nim = working_space[i + 1][j + 1 + 2 * ssizey_ext] / maxch;
1893  for(l = 1; l <= averWindow; l++){
1894  if(j + l > ymax)
1895  a = working_space[i][ymax + 2 * ssizey_ext] / maxch;
1896 
1897  else
1898  a = working_space[i][j + l + 2 * ssizey_ext] / maxch;
1899  b = a - nip;
1900  if(a + nip <= 0)
1901  a = 1;
1902 
1903  else
1904  a=TMath::Sqrt(a + nip);
1905  b = b / a;
1906  b = TMath::Exp(b);
1907  spy = spy + b;
1908  if(j - l + 1 < ymin)
1909  a = working_space[i][ymin + 2 * ssizey_ext] / maxch;
1910 
1911  else
1912  a = working_space[i][j - l + 1 + 2 * ssizey_ext] / maxch;
1913  b=a-nim;
1914  if(a + nim <= 0)
1915  a = 1;
1916  else
1917  a=TMath::Sqrt(a + nim);
1918  b = b / a;
1919  b = TMath::Exp(b);
1920  smy = smy + b;
1921  }
1922  a = (spx * working_space[i][j + 1] + spy * working_space[i + 1][j]) / (smx + smy);
1923  working_space[i + 1][j + 1] = a;
1924  nom = nom + a;
1925  }
1926  }
1927  for(i = xmin; i <= xmax; i++){
1928  for(j = ymin; j <= ymax; j++){
1929  working_space[i][j] = working_space[i][j] / nom;
1930  }
1931  }
1932  for(i = 0; i < ssizex_ext; i++){
1933  for(j = 0; j < ssizey_ext; j++){
1934  working_space[i][j + ssizey_ext] = working_space[i][j] * plocha;
1935  working_space[i][2 * ssizey_ext + j] = working_space[i][ssizey_ext + j];
1936  }
1937  }
1938  }
1939  //deconvolution starts
1940  area = 0;
1941  lhx = -1,lhy = -1;
1942  positx = 0,posity = 0;
1943  maximum = 0;
1944  //generate response matrix
1945  for(i = 0; i < ssizex_ext; i++){
1946  for(j = 0; j < ssizey_ext; j++){
1947  lda = (Double_t)i - 3 * sigma;
1948  ldb = (Double_t)j - 3 * sigma;
1949  lda = (lda * lda + ldb * ldb) / (2 * sigma * sigma);
1950  k=(Int_t)(1000 * TMath::Exp(-lda));
1951  lda = k;
1952  if(lda != 0){
1953  if((i + 1) > lhx)
1954  lhx = i + 1;
1955 
1956  if((j + 1) > lhy)
1957  lhy = j + 1;
1958  }
1959  working_space[i][j] = lda;
1960  area = area + lda;
1961  if(lda > maximum){
1962  maximum = lda;
1963  positx = i,posity = j;
1964  }
1965  }
1966  }
1967  //read source matrix
1968  for(i = 0;i < ssizex_ext; i++){
1969  for(j = 0;j < ssizey_ext; j++){
1970  working_space[i][j + 14 * ssizey_ext] = TMath::Abs(working_space[i][j + ssizey_ext]);
1971  }
1972  }
1973  //calculate matrix b=ht*h
1974  i = lhx - 1;
1975  if(i > ssizex_ext)
1976  i = ssizex_ext;
1977 
1978  j = lhy - 1;
1979  if(j>ssizey_ext)
1980  j = ssizey_ext;
1981 
1982  i1min = -i,i1max = i;
1983  i2min = -j,i2max = j;
1984  for(i2 = i2min; i2 <= i2max; i2++){
1985  for(i1 = i1min; i1 <= i1max; i1++){
1986  ldc = 0;
1987  j2min = -i2;
1988  if(j2min < 0)
1989  j2min = 0;
1990 
1991  j2max = lhy - 1 - i2;
1992  if(j2max > lhy - 1)
1993  j2max = lhy - 1;
1994 
1995  for(j2 = j2min; j2 <= j2max; j2++){
1996  j1min = -i1;
1997  if(j1min < 0)
1998  j1min = 0;
1999 
2000  j1max = lhx - 1 - i1;
2001  if(j1max > lhx - 1)
2002  j1max = lhx - 1;
2003 
2004  for(j1 = j1min; j1 <= j1max; j1++){
2005  lda = working_space[j1][j2];
2006  ldb = working_space[i1 + j1][i2 + j2];
2007  ldc = ldc + lda * ldb;
2008  }
2009  }
2010  k = (i1 + ssizex_ext) / ssizex_ext;
2011  working_space[(i1 + ssizex_ext) % ssizex_ext][i2 + ssizey_ext + 10 * ssizey_ext + k * 2 * ssizey_ext] = ldc;
2012  }
2013  }
2014  //calculate at*y and write into p
2015  i = lhx - 1;
2016  if(i > ssizex_ext)
2017  i = ssizex_ext;
2018 
2019  j = lhy - 1;
2020  if(j > ssizey_ext)
2021  j = ssizey_ext;
2022 
2023  i2min = -j,i2max = ssizey_ext + j - 1;
2024  i1min = -i,i1max = ssizex_ext + i - 1;
2025  for(i2 = i2min; i2 <= i2max; i2++){
2026  for(i1=i1min;i1<=i1max;i1++){
2027  ldc=0;
2028  for(j2 = 0; j2 <= (lhy - 1); j2++){
2029  for(j1 = 0; j1 <= (lhx - 1); j1++){
2030  k2 = i2 + j2,k1 = i1 + j1;
2031  if(k2 >= 0 && k2 < ssizey_ext && k1 >= 0 && k1 < ssizex_ext){
2032  lda = working_space[j1][j2];
2033  ldb = working_space[k1][k2 + 14 * ssizey_ext];
2034  ldc = ldc + lda * ldb;
2035  }
2036  }
2037  }
2038  k = (i1 + ssizex_ext) / ssizex_ext;
2039  working_space[(i1 + ssizex_ext) % ssizex_ext][i2 + ssizey_ext + ssizey_ext + k * 3 * ssizey_ext] = ldc;
2040  }
2041  }
2042  //move matrix p
2043  for(i2 = 0; i2 < ssizey_ext; i2++){
2044  for(i1 = 0; i1 < ssizex_ext; i1++){
2045  k = (i1 + ssizex_ext) / ssizex_ext;
2046  ldb = working_space[(i1 + ssizex_ext) % ssizex_ext][i2 + ssizey_ext + ssizey_ext + k * 3 * ssizey_ext];
2047  working_space[i1][i2 + 14 * ssizey_ext] = ldb;
2048  }
2049  }
2050  //initialization in x1 matrix
2051  for(i2 = 0; i2 < ssizey_ext; i2++){
2052  for(i1 = 0; i1 < ssizex_ext; i1++){
2053  working_space[i1][i2 + ssizey_ext] = 1;
2054  working_space[i1][i2 + 2 * ssizey_ext] = 0;
2055  }
2056  }
2057  //START OF ITERATIONS
2058  for(lindex = 0; lindex < deconIterations; lindex++){
2059  for(i2 = 0; i2 < ssizey_ext; i2++){
2060  for(i1 = 0; i1 < ssizex_ext; i1++){
2061  lda = working_space[i1][i2 + ssizey_ext];
2062  ldc = working_space[i1][i2 + 14 * ssizey_ext];
2063  if(lda > 0.000001 && ldc > 0.000001){
2064  ldb=0;
2065  j2min=i2;
2066  if(j2min > lhy - 1)
2067  j2min = lhy - 1;
2068 
2069  j2min = -j2min;
2070  j2max = ssizey_ext - i2 - 1;
2071  if(j2max > lhy - 1)
2072  j2max = lhy - 1;
2073 
2074  j1min = i1;
2075  if(j1min > lhx - 1)
2076  j1min = lhx - 1;
2077 
2078  j1min = -j1min;
2079  j1max = ssizex_ext - i1 - 1;
2080  if(j1max > lhx - 1)
2081  j1max = lhx - 1;
2082 
2083  for(j2 = j2min; j2 <= j2max; j2++){
2084  for(j1 = j1min; j1 <= j1max; j1++){
2085  k = (j1 + ssizex_ext) / ssizex_ext;
2086  ldc = working_space[(j1 + ssizex_ext) % ssizex_ext][j2 + ssizey_ext + 10 * ssizey_ext + k * 2 * ssizey_ext];
2087  lda = working_space[i1 + j1][i2 + j2 + ssizey_ext];
2088  ldb = ldb + lda * ldc;
2089  }
2090  }
2091  lda = working_space[i1][i2 + ssizey_ext];
2092  ldc = working_space[i1][i2 + 14 * ssizey_ext];
2093  if(ldc * lda != 0 && ldb != 0){
2094  lda =lda * ldc / ldb;
2095  }
2096 
2097  else
2098  lda=0;
2099  working_space[i1][i2 + 2 * ssizey_ext] = lda;
2100  }
2101  }
2102  }
2103  for(i2 = 0; i2 < ssizey_ext; i2++){
2104  for(i1 = 0; i1 < ssizex_ext; i1++)
2105  working_space[i1][i2 + ssizey_ext] = working_space[i1][i2 + 2 * ssizey_ext];
2106  }
2107  }
2108  //looking for maximum
2109  maximum=0;
2110  for(i = 0; i < ssizex_ext; i++){
2111  for(j = 0; j < ssizey_ext; j++){
2112  working_space[(i + positx) % ssizex_ext][(j + posity) % ssizey_ext] = area * working_space[i][j + ssizey_ext];
2113  if(maximum < working_space[(i + positx) % ssizex_ext][(j + posity) % ssizey_ext])
2114  maximum = working_space[(i + positx) % ssizex_ext][(j + posity) % ssizey_ext];
2115 
2116  }
2117  }
2118  //searching for peaks in deconvolved spectrum
2119  for(i = 1; i < ssizex_ext - 1; i++){
2120  for(j = 1; j < ssizey_ext - 1; j++){
2121  if(working_space[i][j] > working_space[i - 1][j] && working_space[i][j] > working_space[i - 1][j - 1] && working_space[i][j] > working_space[i][j - 1] && working_space[i][j] > working_space[i + 1][j - 1] && working_space[i][j] > working_space[i + 1][j] && working_space[i][j] > working_space[i + 1][j + 1] && working_space[i][j] > working_space[i][j + 1] && working_space[i][j] > working_space[i - 1][j + 1]){
2122  if(i >= shift && i < ssizex + shift && j >= shift && j < ssizey + shift){
2123  if(working_space[i][j] > threshold * maximum / 100.0){
2124  if(peak_index < fMaxPeaks){
2125  for(k = i - 1,a = 0,b = 0; k <= i + 1; k++){
2126  a += (Double_t)(k - shift) * working_space[k][j];
2127  b += working_space[k][j];
2128  }
2129  ax=a/b;
2130  if(ax < 0)
2131  ax = 0;
2132 
2133  if(ax >= ssizex)
2134  ax = ssizex - 1;
2135 
2136  for(k = j - 1,a = 0,b = 0; k <= j + 1; k++){
2137  a += (Double_t)(k - shift) * working_space[i][k];
2138  b += working_space[i][k];
2139  }
2140  ay=a/b;
2141  if(ay < 0)
2142  ay = 0;
2143 
2144  if(ay >= ssizey)
2145  ay = ssizey - 1;
2146 
2147  if(peak_index == 0){
2148  fPositionX[0] = ax;
2149  fPositionY[0] = ay;
2150  peak_index = 1;
2151  }
2152 
2153  else{
2154  for(k = 0, priz = 0; k < peak_index && priz == 0; k++){
2155  if(working_space[shift+(Int_t)(ax+0.5)][15 * ssizey_ext + shift + (Int_t)(ay+0.5)] > working_space[shift+(Int_t)(fPositionX[k]+0.5)][15 * ssizey_ext + shift + (Int_t)(fPositionY[k]+0.5)])
2156  priz = 1;
2157  }
2158  if(priz == 0){
2159  if(k < fMaxPeaks){
2160  fPositionX[k] = ax;
2161  fPositionY[k] = ay;
2162  }
2163  }
2164 
2165  else{
2166  for(l = peak_index; l >= k; l--){
2167  if(l < fMaxPeaks){
2168  fPositionX[l] = fPositionX[l - 1];
2169  fPositionY[l] = fPositionY[l - 1];
2170  }
2171  }
2172  fPositionX[k - 1] = ax;
2173  fPositionY[k - 1] = ay;
2174  }
2175  if(peak_index < fMaxPeaks)
2176  peak_index += 1;
2177  }
2178  }
2179  }
2180  }
2181  }
2182  }
2183  }
2184  //writing back deconvolved spectrum
2185  for(i = 0; i < ssizex; i++){
2186  for(j = 0; j < ssizey; j++){
2187  dest[i][j] = working_space[i + shift][j + shift];
2188  }
2189  }
2190  i = (Int_t)(4 * sigma + 0.5);
2191  i = 4 * i;
2192  for (j = 0; j < ssizex + i; j++)
2193  delete[]working_space[j];
2194  delete[]working_space;
2195  fNPeaks = peak_index;
2196  return fNPeaks;
2197 }
2198 
2199 ////////////////////////////////////////////////////////////////////////////////
2200 /// static function (called by TH1), interface to TSpectrum2::Search
2201 
2203 {
2204  TSpectrum2 s;
2205  return s.Search(hist,sigma,option,threshold);
2206 }
2207 
2208 ////////////////////////////////////////////////////////////////////////////////
2209 /// static function (called by TH1), interface to TSpectrum2::Background
2210 
2211 TH1 *TSpectrum2::StaticBackground(const TH1 *hist,Int_t niter, Option_t *option)
2212 {
2213  TSpectrum2 s;
2214  return s.Background(hist,niter,option);
2215 }
const char * Deconvolution(Double_t **source, Double_t **resp, Int_t ssizex, Int_t ssizey, Int_t numberIterations, Int_t numberRepetitions, Double_t boost)
This function calculates deconvolution from source spectrum according to response spectrum The result...
TList * GetListOfFunctions() const
Definition: TH1.h:244
float xmin
Definition: THbookFile.cxx:93
ClassImp(TSpectrum2) TSpectrum2
Constructor.
Definition: TSpectrum2.cxx:48
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
static double p3(double t, double a, double b, double c, double d)
Double_t * fPositionY
[fNPeaks] Y position of peaks
Definition: TSpectrum2.h:26
const char Option_t
Definition: RtypesCore.h:62
void spy()
Definition: spy.C:175
Definition: Rtypes.h:61
float ymin
Definition: THbookFile.cxx:93
Advanced 2-dimensional spectra processing.
Definition: TSpectrum2.h:20
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
virtual Int_t GetDimension() const
Definition: TH1.h:283
TH1 * h
Definition: legend2.C:5
static Int_t fgAverageWindow
Average window of searched peaks.
Definition: TSpectrum2.h:29
TH1 * fHistogram
resulting histogram
Definition: TSpectrum2.h:28
Basic string class.
Definition: TString.h:137
static void SetDeconIterations(Int_t n=3)
static function: Set max number of decon iterations in deconvolution operation see TSpectrum2::Search...
Definition: TSpectrum2.cxx:109
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1075
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
Double_t fResolution
resolution of the neighboring peaks
Definition: TSpectrum2.h:27
void SetResolution(Double_t resolution=1)
resolution: determines resolution of the neighboring peaks default value is 1 correspond to 3 sigma d...
Definition: TSpectrum2.cxx:282
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:501
TSocket * s1
Definition: hserv2.C:36
Double_t x[n]
Definition: legend1.C:17
Int_t fNPeaks
number of peaks found
Definition: TSpectrum2.h:23
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
static double p2(double t, double a, double b, double c)
virtual void SetMarkerColor(Color_t mcolor=1)
Definition: TAttMarker.h:51
const Double_t sigma
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Int_t fMaxPeaks
Maximum number of peaks to be found.
Definition: TSpectrum2.h:22
Double_t * fPositionX
[fNPeaks] X position of peaks
Definition: TSpectrum2.h:25
float ymax
Definition: THbookFile.cxx:93
Int_t GetNbins() const
Definition: TAxis.h:125
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:675
unsigned int r1[N_CITIES]
Definition: simanTSP.cxx:321
static void SetAverageWindow(Int_t w=3)
static function: Set average window of searched peaks see TSpectrum2::SearchHighRes ...
Definition: TSpectrum2.cxx:100
LVector boost(const LVector &v, const BoostVector &b)
Boost a generic Lorentz Vector class using a generic 3D Vector class describing the boost The only re...
Definition: VectorUtil.h:329
tuple w
Definition: qtexample.py:51
TLine * l
Definition: textangle.C:4
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual void SetMarkerStyle(Style_t mstyle=1)
Definition: TAttMarker.h:53
TAxis * GetYaxis()
Definition: TH1.h:320
float xmax
Definition: THbookFile.cxx:93
static double p1(double t, double a, double b)
virtual void SetMarkerSize(Size_t msize=1)
Definition: TAttMarker.h:54
virtual void Print(Option_t *option="") const
Print the array of positions.
Definition: TSpectrum2.cxx:162
Double_t Exp(Double_t x)
Definition: TMath.h:495
static Int_t StaticSearch(const TH1 *hist, Double_t sigma=2, Option_t *option="goff", Double_t threshold=0.05)
static function (called by TH1), interface to TSpectrum2::Search
A PolyMarker is defined by an array on N points in a 2-D space.
Definition: TPolyMarker.h:37
Double_t * fPosition
[fNPeaks] array of current peak positions
Definition: TSpectrum2.h:24
TH1F * s2
Definition: threadsh2.C:15
double Double_t
Definition: RtypesCore.h:55
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
virtual ~TSpectrum2()
Destructor.
Definition: TSpectrum2.cxx:88
Double_t y[n]
Definition: legend1.C:17
The TH1 histogram class.
Definition: TH1.h:80
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:449
virtual void Add(TObject *obj)
Definition: TList.h:81
const char * SmoothMarkov(Double_t **source, Int_t ssizex, Int_t ssizey, Int_t averWindow)
This function calculates smoothed spectrum from source spectrum based on Markov chain method...
Definition: TSpectrum2.cxx:731
#define dest(otri, vertexptr)
Definition: triangle.c:1040
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
static TH1 * StaticBackground(const TH1 *hist, Int_t niter=20, Option_t *option="")
static function (called by TH1), interface to TSpectrum2::Background
virtual TH1 * Background(const TH1 *hist, Int_t niter=20, Option_t *option="")
This function calculates the background spectrum in the input histogram h.
Definition: TSpectrum2.cxx:151
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
const Bool_t kTRUE
Definition: Rtypes.h:91
Int_t SearchHighRes(Double_t **source, Double_t **dest, Int_t ssizex, Int_t ssizey, Double_t sigma, Double_t threshold, Bool_t backgroundRemove, Int_t deconIterations, Bool_t markov, Int_t averWindow)
This function searches for peaks in source spectrum It is based on deconvolution method.
const Int_t n
Definition: legend1.C:16
TH1F * background
Definition: fithist.C:4
#define PEAK_WINDOW
Definition: TSpectrum2.cxx:43
unsigned int r2[N_CITIES]
Definition: simanTSP.cxx:322
TAxis * GetXaxis()
Definition: TH1.h:319
static Int_t fgIterations
Maximum number of decon iterations (default=3)
Definition: TSpectrum2.h:30
virtual Int_t Search(const TH1 *hist, Double_t sigma=2, Option_t *option="", Double_t threshold=0.05)
This function searches for peaks in source spectrum in hin The number of found peaks and their positi...
Definition: TSpectrum2.cxx:202