StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PeakWindow.cxx
1 #include "PeakWindow.h"
2 
3 ClassImp(PeakWindow)
4 
5 PeakWindow::PeakWindow():mStartX(0),mEndX(1),mStartY(0),mEndY(0),mP_Peak(-1),mPeakX(-1),mPeakY(-1),mStartLine(0),mPeakMarker(0),mEndLine(0)
6 {
7 }
8 
9 PeakWindow::PeakWindow(Double_t start, Double_t end):PeakWindow()
10 {
11  if( start<end ){
12  mStartX=start;
13  mEndX=end;
14  mPeakX=start-1;//In order for PeakAna algorithm for finding peaks to work peak x-value must be less than start
15  }
16 }
17 
19 {
20  oldpeak.Copy(*this);
21 }
22 
24 {
25  if( this == &rhs ){ return *this; }
26  rhs.Copy(*this);
27 
28  return *this;
29 }
30 
31 
32 //Note that this does not copy the TLine objects. Use TObject::Clone()
33 void PeakWindow::Copy(TObject& obj) const
34 {
35  TObject::Copy(obj);//Copy TObject bits
36 
37  ((PeakWindow&)obj).mStartX = mStartX;
38  ((PeakWindow&)obj).mEndX = mEndX;
39  ((PeakWindow&)obj).mStartY = mStartY;
40  ((PeakWindow&)obj).mEndY = mEndY;
41  ((PeakWindow&)obj).mP_Peak = mP_Peak;
42  ((PeakWindow&)obj).mPeakX = mPeakX;
43  ((PeakWindow&)obj).mPeakY = mPeakY;
44 
45  ((PeakWindow&)obj).mStartLine = 0;
46  ((PeakWindow&)obj).mPeakMarker = 0;
47  ((PeakWindow&)obj).mEndLine = 0;
48 }
49 
50 //Note that this does not copy the TLine objects. Use TObject::Clone()
51 TObject* PeakWindow::Clone(const char* newname) const
52 {
53  PeakWindow* window = new PeakWindow();
54  Copy(*window);
55  //Also copy color, style, and size?
56  if( mStartLine!=0 ){ window->GetStartLine( mStartLine->GetY1(), mStartLine->GetY2()); }
57  if( mPeakMarker!=0 ){ window->GetPeakMarker(); }
58  if( mEndLine!=0 ) { window->GetEndLine( mEndLine->GetY1(), mStartLine->GetY2()); }
59 
60  return window;
61 }
62 
64 {
65  delete mStartLine;
66  delete mPeakMarker;
67  delete mEndLine;
68 }
69 
70 void PeakWindow::SetWindow(Double_t s, Double_t e)
71 {
72  mStartX=s;
73  mEndX=e;
74 }
75 
76 void PeakWindow::GetWindow(Double_t &s, Double_t &e) const
77 {s=mStartX;e=mEndX;}
78 
79 void PeakWindow::Reset(Double_t start, Double_t end)
80 {
81  if( start<end ){
82  mStartX=start;
83  mEndX=end;
84  }
85  else{
86  mStartX = 0;
87  mEndX = 1;
88  }
89  mStartY = 0;
90  mEndY = 0;
91  mP_Peak=-1;
92  mPeakX=start-1;
93  mPeakY = -1;
94 }
95 
96 void PeakWindow::Print(Option_t* opt)const
97 {
98  TString option(opt);
99  option.ToLower();
100  if( option.EqualTo("debug") ){
101  LOG_DEBUG <<"|Start:("<<mStartX<<","<<mStartY<<")"
102  <<"|End:("<<mEndX<<","<<mEndY<<")"
103  <<"|Ppeak:"<<mP_Peak<<"|Peak:("<<mPeakX<<","<<mPeakY<<")";
104  }
105  else{
106  std::cout <<"|Start:("<<mStartX<<","<<mStartY<<")"
107  <<"|End:("<<mEndX<<","<<mEndY<<")"
108  <<"|Ppeak:"<<mP_Peak<<"|Peak:("<<mPeakX<<","<<mPeakY<<")";
109  }
110 }
111 
112 void PeakWindow::SetPeak(TGraph* gdata)
113 {
114  if(mP_Peak<0){return;}
115  if(mP_Peak>=gdata->GetN()){return;}
116  Double_t x2=0; Double_t y2=0;
117  gdata->GetPoint(mP_Peak,x2,y2);
118  if( mP_Peak==0 || mP_Peak==gdata->GetN()-1 ){
119  mPeakX = x2;
120  mPeakY = y2;
121  return;
122  }
123  Double_t x1=0; Double_t y1=0;
124  Double_t x3=0; Double_t y3=0;
125  gdata->GetPoint(mP_Peak-1,x1,y1);
126  gdata->GetPoint(mP_Peak+1,x3,y3);
127  Double_t x00 = (x1+x2)/2.0;
128  Double_t x11 = (x2+x3)/2.0;
129  Double_t PosSlope = (y2-y1)/(x2-x1);
130  Double_t NegSlope = (y3-y2)/(x3-x2);
131  mPeakX = (x00*NegSlope-x11*PosSlope)/(NegSlope-PosSlope);//Formula for x-intercept of a line with points (x00,PosSlope) and (x11,NegSlope)
132  mPeakY = y2;
133 
134  return;
135 }
136 
137 void PeakWindow::Combine( const PeakWindow &other, bool keepthis )
138 {
139  //Assuming mStartX<mEndX for either peak then leftmost start value should be the lower of the two start values
140  if( mStartX>other.mStartX ){
141  mStartX = other.mStartX;
142  mStartY = other.mStartY;
143  }
144  //Same assumption as above then rightmost end value should be the greater of the two end values
145  if( mEndX<other.mEndX ){
146  mEndX = other.mEndX;
147  mEndY = other.mEndY;
148  }
149  if( !keepthis ){
150  mP_Peak = other.mP_Peak;
151  mPeakX = other.mPeakX;
152  mPeakY = other.mPeakY;
153  }
154 }
155 
156 PeakWindow PeakWindow::Combine(const PeakWindow &leftpeak, const PeakWindow &rightpeak, bool keepleft)
157 {
158  PeakWindow comb(leftpeak.mStartX,rightpeak.mEndX);//short for combined
159  comb.mStartY = leftpeak.mStartY;
160  comb.mEndY = rightpeak.mEndY;
161  if( keepleft ){
162  comb.mP_Peak = leftpeak.mP_Peak;
163  comb.mPeakX = leftpeak.mPeakX;
164  comb.mPeakY = leftpeak.mPeakY;
165  }
166  else{
167  comb.mP_Peak = rightpeak.mP_Peak;
168  comb.mPeakX = rightpeak.mPeakX;
169  comb.mPeakY = rightpeak.mPeakY;
170  }
171  return comb;
172 }
173 
175 {
176  Double_t xdiff = mEndX-mStartX;
177  Double_t ydiff = mEndY-mStartY;
178  return ydiff/xdiff; //slope of the line formed by the point (mStartX,mStartY) and (mEndX,mEndY)
179 }
180 
181 Double_t PeakWindow::StartEndSlopeUncertainty(Double_t sigma) const
182 {
183  sigma = fabs(sigma);//take positive
184  Double_t xdiff = mEndX-mStartX;//Assume error is only in y position so need to scale uncertainty by xdiff
185  Double_t ydiff_sigma = TMath::Sqrt2()*sigma;//assuming symmetric error for start and end y points
186  return ydiff_sigma/xdiff; //slope of the line formed by the point (mStartX,mStartY) and (mEndX,mEndY)
187 }
188 
190 {
191  return mStartY - (StartEndLineSlope()*mStartX);
192 }
193 
194 Double_t PeakWindow::MidPoint(TGraph* graph) const
195 {
196  Double_t xdiff = mEndX-mStartX;
197  Double_t ydiff = mEndY-mStartY;
198  Double_t mslope = ydiff/xdiff; //slope of the line formed by the point (mStartX,mStartY) and (mEndX,mEndY)
199  Double_t yint = mStartY-mslope*mStartX;//y-intercept of the line above "^"
200  //y-value at peak x value for the line defined above "^"
201  if( graph!=0 ){
202  Double_t peakx=0; Double_t peaky=0;
203  graph->GetPoint(mP_Peak,peakx,peaky);
204  return mslope*peakx+yint;
205  }
206  else{return mslope*mPeakX+yint;}
207 }
208 
209 Double_t PeakWindow::SlopeChirality(Double_t scale) const
210 {
211  //[Feb 28, 2022]>Use small fluctation around zero to return 0??
212  Double_t slope = StartEndLineSlope();
213  if( slope<0 ){ return -1.0*cosh(scale*slope); }
214  else{ return cosh(scale*slope); }
215 }
216 
217 Double_t PeakWindow::PeakChirality(Double_t slopescale, Double_t scale) const
218 {
219  if( scale==0 ){scale=1;}
220  if( scale<0 ){ scale = fabs(scale); }
221  Double_t startendslope = StartEndLineSlope();
222  Double_t peakstartslope = (mPeakY-mStartY)/(mPeakX-mStartX);
223  Double_t peakendslope = (mPeakY-mEndY)/(mPeakX-mEndX);
224 
225  Double_t deltaps = peakstartslope-startendslope;
226  Double_t deltape = peakendslope-startendslope;
227  //scale==1 peak center is exactly halfway between StartX and EndX
228  //if scale>1 peak center i.e. Chirality==0 is towards StartX
229  //if scale<1 peak center i.e. Chirality==0 is towards EndX
230  return this->SlopeChirality(slopescale*startendslope)*((deltape*deltape)-(deltaps*deltaps)/(scale*scale));
231  //return this->SlopeChirality(slopescale*startendslope);
232 }
233 
234 Double_t PeakWindow::PeakChiralityProb(Double_t probscale,Double_t chirality) const
235 {
236  if( probscale<0 ){ probscale = fabs(probscale); }
237  //Probability is 1/(chir^2+1). This was chosen because 1/x^2+1 "falls softer" than e^-|x|. This returns a probabilty to NOT merge a peak meaning if the chirality is 0 then should return 1 and when chirality is +-inf should return 0.
238  return static_cast<Double_t>(1)/(probscale*chirality*chirality+static_cast<Double_t>(1));
239 }
240 
241 Double_t PeakWindow::PeakChiralityProb(Double_t probscale, Double_t peakscale, Double_t chirscale ) const
242 {
243  Double_t chir = PeakChirality(peakscale, chirscale);
244  return this->PeakChiralityProb(peakscale,chir);
245 }
246 
247 Double_t PeakWindow::PeakTunnelProb(TGraph* graph, Double_t scale, Double_t sigma) const
248 {
249  if( sigma<0 ){sigma = fabs(sigma);}
250  else if(sigma==0){LOG_ERROR << "PeakWindow::PeakTunnelProb - ERROR:sigma cannot be 0 - Returning probability of 0" << endm; return 0;}
251  Double_t xdiff = mEndX-mStartX;
252  Double_t ydiff = mEndY-mStartY;
253  Double_t mslope = ydiff/xdiff; //slope of the line formed by the point (mStartX,mStartY) and (mEndX,mEndY)
254  Double_t yint = mStartY-mslope*mStartX;//y-intercept of the line above "^"
255  Double_t peakx=0; Double_t peaky=0;
256  graph->GetPoint(mP_Peak,peakx,peaky);
257  Double_t yline = mslope*peakx+yint;//y-value at peak x value, use mPeak instead(may not be set so check and pick)??
258  Double_t heightdiff = peaky-yline;
259  //return 1.0/scale*exp(-1.0*scale*heightdiff*xdiff);//Alternative probablity that is not so easy to normalize
260  if( heightdiff<=0 ){ return 1; }//if peak value is less than the line value automatically tunnel
261  else{
262  //return TMath::Exp(-1.0*fabs(scale)*fabs(xdiff)) * (TMath::Erfc((heightdiff)/(TMath::Sqrt2()*sigma)));
263  return (1.0/(scale*xdiff*xdiff+1.0))*(TMath::Erfc((heightdiff)/(TMath::Sqrt2()*sigma)));
264  }
265  //The idea for this probablity distribution (not probability density function) comes from two assumptions about the underlying data
266  //1. As the distance between the start and end x-values increases the probability of tunneling through will decrease exponentially with some scale that must be determined based on the input data. One-tenth of the difference in x-values may work.
267  //2. There is some noise in the y-value of the data that follows a Normal distribution. The mean ('yline') will be the y-value of the line connecting the start and end points evaluated at the x-value of the peak. The sigma should be the noise level of the data. The cumulative distribution function (which is the actual probability) for a Normal Distribution is the complimentary error function (Erfc). Note that the normalization constant of 1/2 has been removed since this is a probability distribution not a probability density function and hence does not need to be normalized as long as the value returned is between 0 and 1. This is true for Erfc as long as 'peaky'>='yline' which is the case here.
268  //The total proability of tunneling is then (@1)*(@2) with two free parameters the scale and the sigma. Note the scale and sigma must be positive
269 }
270 
271 UShort_t PeakWindow::CompareTo(const PeakWindow& other) const
272 {
273  UShort_t check = 0;
274  if( mStartX == other.mStartX ){
275  if( mEndX == other.mEndX ){ check = 1; }
276  }
277  if( check>0 && mP_Peak == other.mP_Peak ){check=2;}
278  if( check>1 && mStartY == other.mStartY ){
279  if( mEndY == other.mEndY ){
280  check = 3;
281  }
282  }
283  if( check>2 && mPeakX == other.mPeakX ){ check = 4;}
284  if( check>3 && mPeakY == other.mPeakY ){ check = 5;}
285  return check;
286 }
287 
288 void PeakWindow::Draw(Option_t* opt)
289 {
290  AppendPad(opt);
291 }
292 
293 void PeakWindow::Paint(Option_t* opt)
294 {
295  TString option(opt);
296  option.ToLower();
297  bool drawstart = false;
298  bool drawpeak = false;
299  bool drawend = false;
300 
301  if( option.Length()==0 ){
302  drawstart=true;
303  drawpeak=true;
304  drawend=true;
305  }
306  else{
307  if( option.Contains("s") ){ drawstart = true; }
308  if( option.Contains("p") ){ drawpeak = true; }
309  if( option.Contains("e") ){ drawend = true; }
310  }
311 
312  if( drawstart ){GetStartLine()->Paint();}
313  if( drawpeak ){GetPeakMarker()->Paint();}
314  if( drawend ){GetEndLine()->Paint();}
315 }
316 
317 TLine* PeakWindow::GetStartLine(Double_t ymin, Double_t ymax)
318 {
319  if( mStartLine==0 ){
320  if( ymin==ymax ){
321  if( mStartY<mEndY ){ymin=mStartY; ymax=mEndY; }
322  else if(mStartY==mEndY){ ymin=mStartY; ymax=mPeakY; }
323  else{ ymin=mEndY; ymax=mStartY; }
324  }
325  mStartLine = new TLine(mStartX,ymin,mStartX,ymax);
326  mStartLine->SetLineColor(kGreen);
327  }
328  else{
329  mStartLine->SetX1(mStartX);
330  mStartLine->SetX2(mStartX);
331  if( ymin==ymax ){ return mStartLine; }
332  mStartLine->SetY1(ymin);
333  mStartLine->SetY2(ymax);
334  }
335  return mStartLine;
336 }
337 
338 Color_t PeakWindow::GetStartLineColor() const
339 { if( mStartLine!=0 ){return mStartLine->GetLineColor(); } return 0; }
340 Style_t PeakWindow::GetStartLineStyle() const
341 { if( mStartLine!=0 ){return mStartLine->GetLineStyle(); } return 0; }
342 Width_t PeakWindow::GetStartLineWidth() const
343 { if( mStartLine!=0 ){return mStartLine->GetLineWidth(); } return 0; }
344 void PeakWindow::SetStartLineColor(Color_t color){ GetStartLine()->SetLineColor(color); }
345 void PeakWindow::SetStartLineColorAlpha(Color_t color,Float_t alpha){ GetStartLine()->SetLineColorAlpha(color,alpha); }
346 void PeakWindow::SetStartLineStyle(Style_t style){ GetStartLine()->SetLineStyle(style); }
347 void PeakWindow::SetStartLineWidth(Width_t width){ GetStartLine()->SetLineWidth(width); }
348 
350 {
351  if( mPeakMarker==0 ){
352  mPeakMarker = new TMarker(mPeakX,mPeakY,4);//Default style is open circle
353  mPeakMarker->SetMarkerColor(kGreen+1);//Default color is the green color that is between the green colors of start and end
354  }
355  else{
356  mPeakMarker->SetX(mPeakX);
357  mPeakMarker->SetY(mPeakY);
358  }
359  return mPeakMarker;
360 }
361 
362 Color_t PeakWindow::GetPeakMarkerColor() const
363 { if( mPeakMarker!=0 ){return mPeakMarker->GetMarkerColor(); } return 0; }
364 Style_t PeakWindow::GetPeakMarkerStyle() const
365 { if( mPeakMarker!=0 ){return mPeakMarker->GetMarkerStyle(); } return 0; }
366 Size_t PeakWindow::GetPeakMarkerSize() const
367 { if( mPeakMarker!=0 ){return mPeakMarker->GetMarkerSize(); } return 0; }
368 void PeakWindow::SetPeakMarkerColor(Color_t color){ GetPeakMarker()->SetMarkerColor(color); }
369 void PeakWindow::SetPeakMarkerColorAlpha(Color_t color, Float_t alpha){ GetPeakMarker()->SetMarkerColorAlpha(color,alpha); }
370 void PeakWindow::SetPeakMarkerStyle(Style_t style){ GetPeakMarker()->SetMarkerStyle(style); }
371 void PeakWindow::SetPeakMarkerSize(Size_t size){ GetPeakMarker()->SetMarkerSize(size); }
372 
373 TLine* PeakWindow::GetEndLine(Double_t ymin, Double_t ymax)
374 {
375  if( mEndLine==0 ){
376  if( ymin==ymax ){
377  if( mStartY<mEndY ){ymin=mStartY; ymax=mEndY; }
378  else if(mStartY==mEndY){ ymin=mStartY; ymax=mPeakY; }
379  else{ ymin=mEndY; ymax=mStartY; }
380  }
381  mEndLine = new TLine(mEndX,ymin,mEndX,ymax);
382  mEndLine->SetLineColor(kGreen+2);
383  }
384  else{
385  mEndLine->SetX1(mEndX);
386  mEndLine->SetX2(mEndX);
387  if( ymin==ymax ){ return mEndLine; }
388  mEndLine->SetY1(ymin);
389  mEndLine->SetY2(ymax);
390  }
391  return mEndLine;
392 }
393 
394 Color_t PeakWindow::GetEndLineColor() const
395 { if( mEndLine!=0 ){ return mEndLine->GetLineColor(); } return 0; }
396 Style_t PeakWindow::GetEndLineStyle() const
397 { if( mEndLine!=0 ){ return mEndLine->GetLineStyle(); } return 0; }
398 Width_t PeakWindow::GetEndLineWidth() const
399 { if( mEndLine!=0 ){ return mEndLine->GetLineWidth();} return 0; }
400 void PeakWindow::SetEndLineColor(Color_t color){ GetEndLine()->SetLineColor(color); }
401 void PeakWindow::SetEndLineColorAlpha(Color_t color,Float_t alpha){ GetEndLine()->SetLineColorAlpha(color,alpha); }
402 void PeakWindow::SetEndLineStyle(Style_t style){ GetEndLine()->SetLineStyle(style); }
403 void PeakWindow::SetEndLineWidth(Width_t width){ GetEndLine()->SetLineWidth(width); }
404 
static PeakWindow Combine(const PeakWindow &leftpeak, const PeakWindow &rightpeak, bool keepleft=true)
combine two PeakWindow objects
Definition: PeakWindow.cxx:156
PeakWindow & operator=(const PeakWindow &rhs)
Assignment operator.
Definition: PeakWindow.cxx:23
TLine * GetStartLine(Double_t ymin=0, Double_t ymax=0)
Create and return a TLine for the start of the peak window.
Definition: PeakWindow.cxx:317
TLine * mStartLine
TLine for drawing the start of the peak window.
Definition: PeakWindow.h:191
void SetWindow(Double_t s, Double_t e)
Definition: PeakWindow.cxx:70
PeakWindow()
Default Constructor.
Definition: PeakWindow.cxx:5
Double_t StartEndLineYint() const
Computes the y-intercept of the line formed by the points (mStartX,mStartY) and (mEndX,mEndY)
Definition: PeakWindow.cxx:189
virtual void Copy(TObject &obj) const
Only copies variables, to copy TLines use Clone()
Definition: PeakWindow.cxx:33
Double_t StartEndLineSlope() const
Computes the slope of the line formed by the points (mStartX,mStartY) and (mEndX,mEndY) ...
Definition: PeakWindow.cxx:174
TMarker * GetPeakMarker()
Create and return a TMarker to mark the location of the peak.
Definition: PeakWindow.cxx:349
Double_t mPeakX
x-value of peak position as determined by SetPeak()
Definition: PeakWindow.h:76
virtual ~PeakWindow()
Destructor.
Definition: PeakWindow.cxx:63
virtual TObject * Clone(const char *newname="") const
Clone whole object, name is irrelevant.
Definition: PeakWindow.cxx:51
Int_t mP_Peak
Point Number of peak in a TGraph object (P for point), point is such that slope with previous point w...
Definition: PeakWindow.h:75
virtual void Print(Option_t *opt="") const
Prints information about PeakWindow.
Definition: PeakWindow.cxx:96
void GetWindow(Double_t &s, Double_t &e) const
Definition: PeakWindow.cxx:76
Double_t StartEndSlopeUncertainty(Double_t sigma) const
Uncertainty int the slope of the line formed by the points (mStartX,mStartY) and (mEndX,mEndY)
Definition: PeakWindow.cxx:181
TLine * mEndLine
TLine for drawing the end of the peak window.
Definition: PeakWindow.h:193
virtual void Reset(Double_t start, Double_t end)
Reset PeakWindow to constructor state.
Definition: PeakWindow.cxx:79
Double_t mStartY
y value associated with mStartX
Definition: PeakWindow.h:73
Double_t MidPoint(TGraph *graph=0) const
Computes the the line formed by the points (mStartX,mStartY) and (mEndX,mEndY) and evaluates that lin...
Definition: PeakWindow.cxx:194
Double_t mStartX
x value for start of the peak window
Definition: PeakWindow.h:71
void SetPeak(TGraph *gdata)
sets mPeakX based on mP_Peak using line of slopes from points (mP_Peak-1,mP_Peak) and (mP_Peak...
Definition: PeakWindow.cxx:112
virtual void Paint(Option_t *opt="")
paint method see Draw() for options
Definition: PeakWindow.cxx:293
virtual UShort_t CompareTo(const PeakWindow &other) const
compare two PeakWindow objects
Definition: PeakWindow.cxx:271
Double_t mEndX
x value for end of the peak window
Definition: PeakWindow.h:72
virtual void Draw(Option_t *opt="")
Draw the PeakWindow.
Definition: PeakWindow.cxx:288
Double_t mEndY
y value associated with mEndX
Definition: PeakWindow.h:74
Double_t mPeakY
y-value at mP_Peak
Definition: PeakWindow.h:77
TLine * GetEndLine(Double_t ymin=0, Double_t ymax=0)
Create and return a TLine for the end of the peak window.
Definition: PeakWindow.cxx:373
virtual Double_t PeakTunnelProb(TGraph *graph, Double_t scale=1.0, Double_t sigma=1.0) const
Compute probablity that a given PeakWindow is a real peak.
Definition: PeakWindow.cxx:247
TMarker * mPeakMarker
TMarker for drawing the peak location.
Definition: PeakWindow.h:192