Logo ROOT  
Reference Guide
RooAbsRealLValue.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooAbsRealLValue.cxx
19\class RooAbsRealLValue
20\ingroup Roofitcore
21
22RooAbsRealLValue is the common abstract base class for objects that represent a
23real value that may appear on the left hand side of an equation ('lvalue').
24Each implementation must provide a setVal() member to allow direct modification
25of the value. RooAbsRealLValue may be derived, but its functional relation
26to other RooAbsArg must be invertible
27
28This class has methods that export the defined range of the lvalue,
29but doesn't hold its values because these limits may be derived
30from limits of client object. The range serve as integration
31range when interpreted as a observable and a boundaries when
32interpreted as a parameter.
33**/
34
35#include "RooAbsRealLValue.h"
36
37#include "RooFit.h"
38#include "RooStreamParser.h"
39#include "RooRandom.h"
40#include "RooPlot.h"
41#include "RooArgList.h"
43#include "RooBinning.h"
44#include "RooUniformBinning.h"
45#include "RooCmdConfig.h"
46#include "RooAbsData.h"
47#include "RooRealVar.h"
48#include "RooMsgService.h"
49#include "RooHelpers.h"
50
51#include "TObjString.h"
52#include "TTree.h"
53#include "TH1.h"
54#include "TH2.h"
55#include "TH3.h"
56
57#include <math.h>
58
59using namespace std;
60
62
63////////////////////////////////////////////////////////////////////////////////
64/// Constructor
65
66RooAbsRealLValue::RooAbsRealLValue(const char *name, const char *title, const char *unit) :
67 RooAbsReal(name, title, 0, 0, unit)
68{
69}
70
71
72
73////////////////////////////////////////////////////////////////////////////////
74/// Copy constructor
75
77 RooAbsReal(other,name), RooAbsLValue(other)
78{
79}
80
81
82////////////////////////////////////////////////////////////////////////////////
83/// Destructor
84
86{
87}
88
89
90
91////////////////////////////////////////////////////////////////////////////////
92/// Return kTRUE if the input value is within our fit range. Otherwise, return
93/// kFALSE and write a clipped value into clippedValPtr if it is non-zero.
94
95Bool_t RooAbsRealLValue::inRange(Double_t value, const char* rangeName, Double_t* clippedValPtr) const
96{
97 // Double_t range = getMax() - getMin() ; // ok for +/-INIFINITY
98 Double_t clippedValue(value);
99 Bool_t isInRange(kTRUE) ;
100
101 const RooAbsBinning& binning = getBinning(rangeName) ;
102 Double_t min = binning.lowBound() ;
103 Double_t max = binning.highBound() ;
104
105 // test this value against our upper fit limit
106 if(!RooNumber::isInfinite(max) && value > (max+1e-6)) {
107 clippedValue = max;
108 isInRange = kFALSE ;
109 }
110 // test this value against our lower fit limit
111 if(!RooNumber::isInfinite(min) && value < min-1e-6) {
112 clippedValue = min ;
113 isInRange = kFALSE ;
114 }
115
116 if (clippedValPtr) *clippedValPtr=clippedValue ;
117
118 return isInRange ;
119}
120
121
122
123////////////////////////////////////////////////////////////////////////////////
124/// Check if given value is valid
125
127{
128 if (!inRange(value,0)) {
129 if (verbose)
130 coutI(InputArguments) << "RooRealVar::isValid(" << GetName() << "): value " << value
131 << " out of range (" << getMin() << " - " << getMax() << ")" << endl ;
132 return kFALSE ;
133 }
134 return kTRUE ;
135}
136
137
138
139////////////////////////////////////////////////////////////////////////////////
140/// Read object contents from given stream
141
142Bool_t RooAbsRealLValue::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/)
143{
144 return kTRUE ;
145}
146
147
148
149////////////////////////////////////////////////////////////////////////////////
150/// Write object contents to given stream
151
152void RooAbsRealLValue::writeToStream(ostream& /*os*/, Bool_t /*compact*/) const
153{
154}
155
156
157
158////////////////////////////////////////////////////////////////////////////////
159/// Assignment operator from a Double_t
160
162{
163 Double_t clipValue ;
164 // Clip
165 inRange(newValue,0,&clipValue) ;
166 setVal(clipValue) ;
167
168 return *this ;
169}
170
171
172////////////////////////////////////////////////////////////////////////////////
173/// Assignment operator from other RooAbsReal
174
176{
177 return operator=(arg.getVal()) ;
178}
179
180
181
182////////////////////////////////////////////////////////////////////////////////
183/// Create a new RooPlot on the heap with a drawing frame initialized for this
184/// object, but no plot contents. Use x.frame() as the first argument to a
185/// y.plotOn(...) method, for example. The caller is responsible for deleting
186/// the returned object.
187///
188/// <table>
189/// <tr><th> Optional arguments <th>
190/// <tr><td> Range(double lo, double hi) <td> Make plot frame for the specified range
191/// <tr><td> Range(const char* name) <td> Make plot frame for range with the specified name
192/// <tr><td> Bins(Int_t nbins) <td> Set default binning for datasets to specified number of bins
193/// <tr><td> AutoRange(const RooAbsData& data, double margin) <td> Specifies range so that all points in given data set fit
194/// inside the range with given margin.
195/// <tr><td> AutoSymRange(const RooAbsData& data, double margin) <td> Specifies range so that all points in given data set fit
196/// inside the range and center of range coincides with mean of distribution in given dataset.
197/// <tr><td> Name(const char* name) <td> Give specified name to RooPlot object
198/// <tr><td> Title(const char* title) <td> Give specified title to RooPlot object
199/// </table>
200///
201RooPlot* RooAbsRealLValue::frame(const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, const RooCmdArg& arg4,
202 const RooCmdArg& arg5, const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const
203{
204 RooLinkedList cmdList ;
205 cmdList.Add(const_cast<RooCmdArg*>(&arg1)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg2)) ;
206 cmdList.Add(const_cast<RooCmdArg*>(&arg3)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg4)) ;
207 cmdList.Add(const_cast<RooCmdArg*>(&arg5)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg6)) ;
208 cmdList.Add(const_cast<RooCmdArg*>(&arg7)) ; cmdList.Add(const_cast<RooCmdArg*>(&arg8)) ;
209
210 return frame(cmdList) ;
211}
212
213
214
215////////////////////////////////////////////////////////////////////////////////
216/// Back-end function for named argument frame() method
217
219{
220 // Define configuration for this method
221 RooCmdConfig pc(Form("RooAbsRealLValue::frame(%s)",GetName())) ;
222 pc.defineDouble("min","Range",0,getMin()) ;
223 pc.defineDouble("max","Range",1,getMax()) ;
224 pc.defineInt("nbins","Bins",0,getBins()) ;
225 pc.defineString("rangeName","RangeWithName",0,"") ;
226 pc.defineString("name","Name",0,"") ;
227 pc.defineString("title","Title",0,"") ;
228 pc.defineMutex("Range","RangeWithName","AutoRange") ;
229 pc.defineObject("rangeData","AutoRange",0,0) ;
230 pc.defineDouble("rangeMargin","AutoRange",0,0.1) ;
231 pc.defineInt("rangeSym","AutoRange",0,0) ;
232
233 // Process & check varargs
234 pc.process(cmdList) ;
235 if (!pc.ok(kTRUE)) {
236 return 0 ;
237 }
238
239 // Extract values from named arguments
241 if (pc.hasProcessed("Range")) {
242 xmin = pc.getDouble("min") ;
243 xmax = pc.getDouble("max") ;
244 if (xmin==xmax) {
245 xmin = getMin() ;
246 xmax = getMax() ;
247 }
248 } else if (pc.hasProcessed("RangeWithName")) {
249 const char* rangeName=pc.getString("rangeName",0,kTRUE) ;
250 xmin = getMin(rangeName) ;
251 xmax = getMax(rangeName) ;
252 } else if (pc.hasProcessed("AutoRange")) {
253 auto rangeData = static_cast<RooAbsData*>(pc.getObject("rangeData")) ;
254 const bool error = rangeData->getRange(*this,xmin,xmax);
255 if (error) {
256 xmin = getMin();
257 xmax = getMax();
258 }
259 if (pc.getInt("rangeSym")==0) {
260 // Regular mode: range is from xmin to xmax with given extra margin
261 Double_t margin = pc.getDouble("rangeMargin")*(xmax-xmin) ;
262 xmin -= margin ;
263 xmax += margin ;
264 if (xmin<getMin()) xmin = getMin() ;
265 if (xmin>getMax()) xmax = getMax() ;
266 } else {
267 // Symmetric mode: range is centered at mean of distribution with enough width to include
268 // both lowest and highest point with margin
269 Double_t dmean = rangeData->moment((RooRealVar&)*this,1) ;
270 Double_t ddelta = ((xmax-dmean)>(dmean-xmin)?(xmax-dmean):(dmean-xmin))*(1+pc.getDouble("rangeMargin")) ;
271 xmin = dmean-ddelta ;
272 xmax = dmean+ddelta ;
273 if (xmin<getMin()) xmin = getMin() ;
274 if (xmin>getMax()) xmax = getMax() ;
275 }
276 } else {
277 xmin = getMin() ;
278 xmax = getMax() ;
279 }
280
281 Int_t nbins = pc.getInt("nbins") ;
282 const char* name = pc.getString("name",0,kTRUE) ;
283 const char* title = pc.getString("title",0,kTRUE) ;
284
285 RooPlot* theFrame = new RooPlot(*this,xmin,xmax,nbins) ;
286
287 if (name) {
288 theFrame->SetName(name) ;
289 }
290 if (title) {
291 theFrame->SetTitle(title) ;
292 }
293
294 return theFrame ;
295}
296
297
298
299////////////////////////////////////////////////////////////////////////////////
300/// Create a new RooPlot on the heap with a drawing frame initialized for this
301/// object, but no plot contents. Use x.frame() as the first argument to a
302/// y.plotOn(...) method, for example. The caller is responsible for deleting
303/// the returned object.
304
306{
307 return new RooPlot(*this,xlo,xhi,nbins);
308}
309
310
311
312////////////////////////////////////////////////////////////////////////////////
313/// Create a new RooPlot on the heap with a drawing frame initialized for this
314/// object, but no plot contents. Use x.frame() as the first argument to a
315/// y.plotOn(...) method, for example. The caller is responsible for deleting
316/// the returned object.
317
319{
320 return new RooPlot(*this,xlo,xhi,getBins());
321}
322
323
324
325////////////////////////////////////////////////////////////////////////////////
326/// Create a new RooPlot on the heap with a drawing frame initialized for this
327/// object, but no plot contents. Use x.frame() as the first argument to a
328/// y.plotOn(...) method, for example. The caller is responsible for deleting
329/// the returned object.
330///
331/// The current fit range may not be open ended or empty.
332
334{
335 // Plot range of variable may not be infinite or empty
336 if (getMin()==getMax()) {
337 coutE(InputArguments) << "RooAbsRealLValue::frame(" << GetName() << ") ERROR: empty fit range, must specify plot range" << endl ;
338 return 0 ;
339 }
341 coutE(InputArguments) << "RooAbsRealLValue::frame(" << GetName() << ") ERROR: open ended fit range, must specify plot range" << endl ;
342 return 0 ;
343 }
344
345 return new RooPlot(*this,getMin(),getMax(),nbins);
346}
347
348
349
350////////////////////////////////////////////////////////////////////////////////
351/// Create a new RooPlot on the heap with a drawing frame initialized for this
352/// object, but no plot contents. Use x.frame() as the first argument to a
353/// y.plotOn(...) method, for example. The caller is responsible for deleting
354/// the returned object.
355///
356/// The current fit range may not be open ended or empty.
357
359{
360 // Plot range of variable may not be infinite or empty
361 if (getMin()==getMax()) {
362 coutE(InputArguments) << "RooAbsRealLValue::frame(" << GetName() << ") ERROR: empty fit range, must specify plot range" << endl ;
363 return 0 ;
364 }
366 coutE(InputArguments) << "RooAbsRealLValue::frame(" << GetName() << ") ERROR: open ended fit range, must specify plot range" << endl ;
367 return 0 ;
368 }
369
370 return new RooPlot(*this,getMin(),getMax(),getBins());
371}
372
373
374
375////////////////////////////////////////////////////////////////////////////////
376/// Copy cache of another RooAbsArg to our cache
377
378void RooAbsRealLValue::copyCache(const RooAbsArg* source, Bool_t valueOnly, Bool_t setValDirty)
379{
380 RooAbsReal::copyCache(source,valueOnly,setValDirty) ;
381 setVal(_value) ; // force back-propagation
382}
383
384
385////////////////////////////////////////////////////////////////////////////////
386/// Structure printing
387
389{
391 os << indent << "--- RooAbsRealLValue ---" << endl;
392 TString unit(_unit);
393 if(!unit.IsNull()) unit.Prepend(' ');
394 os << indent << " Fit range is [ ";
395 if(hasMin()) {
396 os << getMin() << unit << " , ";
397 }
398 else {
399 os << "-INF , ";
400 }
401 if(hasMax()) {
402 os << getMax() << unit << " ]" << endl;
403 }
404 else {
405 os << "+INF ]" << endl;
406 }
407}
408
409
410
411////////////////////////////////////////////////////////////////////////////////
412/// Set a new value sampled from a uniform distribution over the fit range.
413/// Prints a warning and does nothing if the fit range is not finite.
414
415void RooAbsRealLValue::randomize(const char* rangeName)
416{
417 RooAbsBinning& binning = getBinning(rangeName) ;
418 Double_t min = binning.lowBound() ;
419 Double_t max = binning.highBound() ;
420
422 setValFast(min + RooRandom::uniform()*(max-min));
423 }
424 else {
425 coutE(Generation) << fName << "::" << ClassName() << ":randomize: fails with unbounded fit range" << endl;
426 }
427}
428
429
430
431////////////////////////////////////////////////////////////////////////////////
432/// Set value to center of bin 'ibin' of binning 'rangeName' (or of
433/// default binning if no range is specified)
434
435void RooAbsRealLValue::setBin(Int_t ibin, const char* rangeName)
436{
437 // Check range of plot bin index
438 if (ibin<0 || ibin>=numBins(rangeName)) {
439 coutE(InputArguments) << "RooAbsRealLValue::setBin(" << GetName() << ") ERROR: bin index " << ibin
440 << " is out of range (0," << getBins(rangeName)-1 << ")" << endl ;
441 return ;
442 }
443
444 // Set value to center of requested bin
445 setVal(getBinning(rangeName).binCenter(ibin)) ;
446}
447
448
449
450
451
452////////////////////////////////////////////////////////////////////////////////
453/// Set value to center of bin 'ibin' of binning 'binning'
454
456{
457 // Set value to center of requested bin
458 setVal(binning.binCenter(ibin)) ;
459}
460
461
462
463
464
465////////////////////////////////////////////////////////////////////////////////
466/// Set a new value sampled from a uniform distribution over the fit range.
467/// Prints a warning and does nothing if the fit range is not finite.
468
470{
471 Double_t range= binning.highBound() - binning.lowBound() ;
472 setVal(binning.lowBound() + RooRandom::uniform()*range);
473}
474
475
476
477
478
479////////////////////////////////////////////////////////////////////////////////
480/// Set value to center of bin 'ibin' of binning 'rangeName' (or of
481/// default binning if no range is specified)
482
484{
485 // Set value to center of requested bin
486 setValFast(binning.binCenter(ibin)) ;
487}
488
489
490
491////////////////////////////////////////////////////////////////////////////////
492/// Check if fit range is usable as plot range, i.e. it is neither
493/// open ended, nor empty
494
496{
497 return (hasMin() && hasMax() && (getMin()!=getMax())) ;
498}
499
500
501
502////////////////////////////////////////////////////////////////////////////////
503/// Check if current value is inside range with given name. Multiple comma-separated
504/// ranges can be passed. In this case, it will be checked if the value is in any of
505/// these ranges.
507{
508 const double val = getVal() ;
509 const double epsilon = 1e-8 * fabs(val) ;
510 if (!name || name[0] == '\0') {
511 const auto minMax = getRange(nullptr);
512 return minMax.first - epsilon <= val && val <= minMax.second + epsilon;
513 }
514
515 const auto& ranges = RooHelpers::tokenise(name, ",");
516 return std::any_of(ranges.begin(), ranges.end(), [val,epsilon,this](const std::string& range){
517 const auto minMax = this->getRange(range.c_str());
518 return minMax.first - epsilon <= val && val <= minMax.second + epsilon;
519 });
520}
521
522
523
524////////////////////////////////////////////////////////////////////////////////
525
526TH1* RooAbsRealLValue::createHistogram(const char *name, const RooCmdArg& arg1, const RooCmdArg& arg2,
527 const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5,
528 const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const
529
530 // Create an empty ROOT histogram TH1,TH2 or TH3 suitabe to store information represent by the RooAbsRealLValue
531 //
532 // This function accepts the following arguments
533 //
534 // name -- Name of the ROOT histogram
535 //
536 // Binning(const char* name) -- Apply binning with given name to x axis of histogram
537 // Binning(RooAbsBinning& binning) -- Apply specified binning to x axis of histogram
538 // Binning(int_t nbins) -- Apply specified binning to x axis of histogram
539 // Binning(int_t nbins, double lo, double hi) -- Apply specified binning to x axis of histogram
540 // ConditionalObservables(const RooArgSet& set) -- Do not normalized PDF over following observables when projecting PDF into histogram
541 //
542 // YVar(const RooAbsRealLValue& var,...) -- Observable to be mapped on y axis of ROOT histogram
543 // ZVar(const RooAbsRealLValue& var,...) -- Observable to be mapped on z axis of ROOT histogram
544 //
545 // The YVar() and ZVar() arguments can be supplied with optional Binning() arguments to control the binning of the Y and Z axes, e.g.
546 // createHistogram("histo",x,Binning(-1,1,20), YVar(y,Binning(-1,1,30)), ZVar(z,Binning("zbinning")))
547 //
548 // The caller takes ownership of the returned histogram
549{
551 l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
552 l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
553 l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
554 l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
555
556 return createHistogram(name,l) ;
557}
558
559
560
561////////////////////////////////////////////////////////////////////////////////
562/// Create empty 1,2 or 3D histogram
563/// Arguments recognized
564///
565/// YVar() -- RooRealVar defining Y dimension with optional range/binning
566/// ZVar() -- RooRealVar defining Z dimension with optional range/binning
567/// AxisLabel() -- Vertical axis label
568/// Binning() -- Range/Binning specification of X axis
569
570TH1* RooAbsRealLValue::createHistogram(const char *name, const RooLinkedList& cmdList) const
571{
572 // Define configuration for this method
573 RooCmdConfig pc(Form("RooAbsRealLValue::createHistogram(%s)",GetName())) ;
574
575 pc.defineObject("xbinning","Binning",0,0) ;
576 pc.defineString("xbinningName","BinningName",0,"") ;
577 pc.defineInt("nxbins","BinningSpec",0) ;
578 pc.defineDouble("xlo","BinningSpec",0,0) ;
579 pc.defineDouble("xhi","BinningSpec",1,0) ;
580
581 pc.defineObject("yvar","YVar",0,0) ;
582 pc.defineObject("ybinning","YVar::Binning",0,0) ;
583 pc.defineString("ybinningName","YVar::BinningName",0,"") ;
584 pc.defineInt("nybins","YVar::BinningSpec",0) ;
585 pc.defineDouble("ylo","YVar::BinningSpec",0,0) ;
586 pc.defineDouble("yhi","YVar::BinningSpec",1,0) ;
587
588 pc.defineObject("zvar","ZVar",0,0) ;
589 pc.defineObject("zbinning","ZVar::Binning",0,0) ;
590 pc.defineString("zbinningName","ZVar::BinningName",0,"") ;
591 pc.defineInt("nzbins","ZVar::BinningSpec",0) ;
592 pc.defineDouble("zlo","ZVar::BinningSpec",0,0) ;
593 pc.defineDouble("zhi","ZVar::BinningSpec",1,0) ;
594
595 pc.defineString("axisLabel","AxisLabel",0,"Events") ;
596
597 pc.defineDependency("ZVar","YVar") ;
598
599 // Process & check varargs
600 pc.process(cmdList) ;
601 if (!pc.ok(kTRUE)) {
602 return 0 ;
603 }
604
605 // Initialize arrays for call to implementation version of createHistogram
606 const char* axisLabel = pc.getString("axisLabel") ;
607 const RooAbsBinning* binning[3] ;
608 Bool_t ownBinning[3] = { kFALSE, kFALSE, kFALSE } ;
609 RooArgList vars ;
610
611 // Prepare X dimension
612 vars.add(*this) ;
613 if (pc.hasProcessed("Binning")) {
614 binning[0] = static_cast<RooAbsBinning*>(pc.getObject("xbinning")) ;
615 } else if (pc.hasProcessed("BinningName")) {
616 binning[0] = &getBinning(pc.getString("xbinningName",0,kTRUE)) ;
617 } else if (pc.hasProcessed("BinningSpec")) {
618 Double_t xlo = pc.getDouble("xlo") ;
619 Double_t xhi = pc.getDouble("xhi") ;
620 binning[0] = new RooUniformBinning((xlo==xhi)?getMin():xlo,(xlo==xhi)?getMax():xhi,pc.getInt("nxbins")) ;
621 ownBinning[0] = kTRUE ;
622 } else {
623 binning[0] = &getBinning() ;
624 }
625
626 if (pc.hasProcessed("YVar")) {
627 RooAbsRealLValue& yvar = *static_cast<RooAbsRealLValue*>(pc.getObject("yvar")) ;
628 vars.add(yvar) ;
629 if (pc.hasProcessed("YVar::Binning")) {
630 binning[1] = static_cast<RooAbsBinning*>(pc.getObject("ybinning")) ;
631 } else if (pc.hasProcessed("YVar::BinningName")) {
632 binning[1] = &yvar.getBinning(pc.getString("ybinningName",0,kTRUE)) ;
633 } else if (pc.hasProcessed("YVar::BinningSpec")) {
634 Double_t ylo = pc.getDouble("ylo") ;
635 Double_t yhi = pc.getDouble("yhi") ;
636 binning[1] = new RooUniformBinning((ylo==yhi)?yvar.getMin():ylo,(ylo==yhi)?yvar.getMax():yhi,pc.getInt("nybins")) ;
637 ownBinning[1] = kTRUE ;
638 } else {
639 binning[1] = &yvar.getBinning() ;
640 }
641 }
642
643 if (pc.hasProcessed("ZVar")) {
644 RooAbsRealLValue& zvar = *static_cast<RooAbsRealLValue*>(pc.getObject("zvar")) ;
645 vars.add(zvar) ;
646 if (pc.hasProcessed("ZVar::Binning")) {
647 binning[2] = static_cast<RooAbsBinning*>(pc.getObject("zbinning")) ;
648 } else if (pc.hasProcessed("ZVar::BinningName")) {
649 binning[2] = &zvar.getBinning(pc.getString("zbinningName",0,kTRUE)) ;
650 } else if (pc.hasProcessed("ZVar::BinningSpec")) {
651 Double_t zlo = pc.getDouble("zlo") ;
652 Double_t zhi = pc.getDouble("zhi") ;
653 binning[2] = new RooUniformBinning((zlo==zhi)?zvar.getMin():zlo,(zlo==zhi)?zvar.getMax():zhi,pc.getInt("nzbins")) ;
654 ownBinning[2] = kTRUE ;
655 } else {
656 binning[2] = &zvar.getBinning() ;
657 }
658 }
659
660
661 TH1* ret = createHistogram(name, vars, axisLabel, binning) ;
662
663 if (ownBinning[0]) delete binning[0] ;
664 if (ownBinning[1]) delete binning[1] ;
665 if (ownBinning[2]) delete binning[2] ;
666
667 return ret ;
668}
669
670
671
672////////////////////////////////////////////////////////////////////////////////
673/// Create an empty 1D-histogram with appropriate scale and labels for this variable.
674/// This method uses the default plot range which can be changed using the
675/// setPlotMin(),setPlotMax() methods, and the default binning which can be
676/// changed with setPlotBins(). The caller takes ownership of the returned
677/// object and is responsible for deleting it.
678
679TH1F *RooAbsRealLValue::createHistogram(const char *name, const char *yAxisLabel) const
680{
681 // Check if the fit range is usable as plot range
682 if (!fitRangeOKForPlotting()) {
683 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
684 << ") ERROR: fit range empty or open ended, must explicitly specify range" << endl ;
685 return 0 ;
686 }
687
688 RooArgList list(*this) ;
689 Double_t xlo = getMin() ;
690 Double_t xhi = getMax() ;
691 Int_t nbins = getBins() ;
692
693 // coverity[ARRAY_VS_SINGLETON]
694 return (TH1F*)createHistogram(name, list, yAxisLabel, &xlo, &xhi, &nbins);
695}
696
697
698
699////////////////////////////////////////////////////////////////////////////////
700/// Create an empty 1D-histogram with appropriate scale and labels for this variable.
701/// This method uses the default plot range which can be changed using the
702/// setPlotMin(),setPlotMax() methods, and the default binning which can be
703/// changed with setPlotBins(). The caller takes ownership of the returned
704/// object and is responsible for deleting it.
705
706TH1F *RooAbsRealLValue::createHistogram(const char *name, const char *yAxisLabel, Double_t xlo, Double_t xhi, Int_t nBins) const
707{
708 RooArgList list(*this) ;
709
710 // coverity[ARRAY_VS_SINGLETON]
711 return (TH1F*)createHistogram(name, list, yAxisLabel, &xlo, &xhi, &nBins);
712}
713
714
715
716////////////////////////////////////////////////////////////////////////////////
717/// Create an empty 1D-histogram with appropriate scale and labels for this variable.
718
719TH1F *RooAbsRealLValue::createHistogram(const char *name, const char *yAxisLabel, const RooAbsBinning& bins) const
720{
721 RooArgList list(*this) ;
722 const RooAbsBinning* pbins = &bins ;
723
724 // coverity[ARRAY_VS_SINGLETON]
725 return (TH1F*)createHistogram(name, list, yAxisLabel, &pbins);
726}
727
728
729
730////////////////////////////////////////////////////////////////////////////////
731/// Create an empty 2D-histogram with appropriate scale and labels for this variable (x)
732/// and the specified y variable. This method uses the default plot ranges for x and y which
733/// can be changed using the setPlotMin(),setPlotMax() methods, and the default binning which
734/// can be changed with setPlotBins(). The caller takes ownership of the returned object
735/// and is responsible for deleting it.
736
737TH2F *RooAbsRealLValue::createHistogram(const char *name, const RooAbsRealLValue &yvar, const char *zAxisLabel,
738 Double_t* xlo, Double_t* xhi, Int_t* nBins) const
739{
740 if ((!xlo && xhi) || (xlo && !xhi)) {
741 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
742 << ") ERROR must specify either no range, or both limits" << endl ;
743 return 0 ;
744 }
745
746 Double_t xlo_fit[2] ;
747 Double_t xhi_fit[2] ;
748 Int_t nbins_fit[2] ;
749
750 Double_t *xlo2 = xlo;
751 Double_t *xhi2 = xhi;
752 Int_t *nBins2 = nBins;
753
754 if (!xlo2) {
755
756 if (!fitRangeOKForPlotting()) {
757 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
758 << ") ERROR: fit range empty or open ended, must explicitly specify range" << endl ;
759 return 0 ;
760 }
761 if (!yvar.fitRangeOKForPlotting()) {
762 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
763 << ") ERROR: fit range of " << yvar.GetName() << " empty or open ended, must explicitly specify range" << endl ;
764 return 0 ;
765 }
766
767 xlo_fit[0] = getMin() ;
768 xhi_fit[0] = getMax() ;
769
770 xlo_fit[1] = yvar.getMin() ;
771 xhi_fit[1] = yvar.getMax() ;
772
773 xlo2 = xlo_fit ;
774 xhi2 = xhi_fit ;
775 }
776
777 if (!nBins2) {
778 nbins_fit[0] = getBins() ;
779 nbins_fit[1] = yvar.getBins() ;
780 nBins2 = nbins_fit ;
781 }
782
783
784 RooArgList list(*this,yvar) ;
785 // coverity[OVERRUN_STATIC]
786 return (TH2F*)createHistogram(name, list, zAxisLabel, xlo2, xhi2, nBins2);
787}
788
789
790
791////////////////////////////////////////////////////////////////////////////////
792/// Create an empty 2D-histogram with appropriate scale and labels for this variable (x)
793/// and the specified y variable.
794
796 const char *zAxisLabel, const RooAbsBinning** bins) const
797{
798 RooArgList list(*this,yvar) ;
799 return (TH2F*)createHistogram(name, list, zAxisLabel, bins);
800}
801
802
803
804////////////////////////////////////////////////////////////////////////////////
805/// Create an empty 3D-histogram with appropriate scale and labels for this variable (x)
806/// and the specified y,z variables. This method uses the default plot ranges for x,y,z which
807/// can be changed using the setPlotMin(),setPlotMax() methods, and the default binning which
808/// can be changed with setPlotBins(). The caller takes ownership of the returned object
809/// and is responsible for deleting it.
810
812 const char *tAxisLabel, Double_t* xlo, Double_t* xhi, Int_t* nBins) const
813{
814 if ((!xlo && xhi) || (xlo && !xhi)) {
815 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
816 << ") ERROR must specify either no range, or both limits" << endl ;
817 return 0 ;
818 }
819
820 Double_t xlo_fit[3] ;
821 Double_t xhi_fit[3] ;
822 Int_t nbins_fit[3] ;
823
824 Double_t *xlo2 = xlo;
825 Double_t *xhi2 = xhi;
826 Int_t* nBins2 = nBins;
827 if (!xlo2) {
828
829 if (!fitRangeOKForPlotting()) {
830 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
831 << ") ERROR: fit range empty or open ended, must explicitly specify range" << endl ;
832 return 0 ;
833 }
834 if (!yvar.fitRangeOKForPlotting()) {
835 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
836 << ") ERROR: fit range of " << yvar.GetName() << " empty or open ended, must explicitly specify range" << endl ;
837 return 0 ;
838 }
839 if (!zvar.fitRangeOKForPlotting()) {
840 coutE(InputArguments) << "RooAbsRealLValue::createHistogram(" << GetName()
841 << ") ERROR: fit range of " << zvar.GetName() << " empty or open ended, must explicitly specify range" << endl ;
842 return 0 ;
843 }
844
845 xlo_fit[0] = getMin() ;
846 xhi_fit[0] = getMax() ;
847
848 xlo_fit[1] = yvar.getMin() ;
849 xhi_fit[1] = yvar.getMax() ;
850
851 xlo_fit[2] = zvar.getMin() ;
852 xhi_fit[2] = zvar.getMax() ;
853
854 xlo2 = xlo_fit ;
855 xhi2 = xhi_fit ;
856 }
857
858 if (!nBins2) {
859 nbins_fit[0] = getBins() ;
860 nbins_fit[1] = yvar.getBins() ;
861 nbins_fit[2] = zvar.getBins() ;
862 nBins2 = nbins_fit ;
863 }
864
865 RooArgList list(*this,yvar,zvar) ;
866 return (TH3F*)createHistogram(name, list, tAxisLabel, xlo2, xhi2, nBins2);
867}
868
869
871 const char* tAxisLabel, const RooAbsBinning** bins) const
872{
873 // Create an empty 3D-histogram with appropriate scale and labels for this variable (x)
874 // and the specified y,z variables.
875
876 RooArgList list(*this,yvar,zvar) ;
877 return (TH3F*)createHistogram(name, list, tAxisLabel, bins);
878}
879
880
881
882
883////////////////////////////////////////////////////////////////////////////////
884/// Create 1-, 2- or 3-d ROOT histogram with labels taken
885/// from the variables in 'vars' and the with range and binning
886/// specified in xlo,xhi and nBins. The dimensions of the arrays xlo,xhi,
887/// nBins should match the number of objects in vars.
888
889TH1 *RooAbsRealLValue::createHistogram(const char *name, RooArgList &vars, const char *tAxisLabel,
890 Double_t* xlo, Double_t* xhi, Int_t* nBins)
891{
892 const RooAbsBinning* bin[3] ;
893 Int_t ndim = vars.getSize() ;
894 bin[0] = new RooUniformBinning(xlo[0],xhi[0],nBins[0]) ;
895 bin[1] = (ndim>1) ? new RooUniformBinning(xlo[1],xhi[1],nBins[1]) : 0 ;
896 bin[2] = (ndim>2) ? new RooUniformBinning(xlo[2],xhi[2],nBins[2]) : 0 ;
897
898 TH1* ret = createHistogram(name,vars,tAxisLabel,bin) ;
899
900 if (bin[0]) delete bin[0] ;
901 if (bin[1]) delete bin[1] ;
902 if (bin[2]) delete bin[2] ;
903 return ret ;
904}
905
906
907
908////////////////////////////////////////////////////////////////////////////////
909/// Create a 1,2, or 3D-histogram with appropriate scale and labels.
910/// Binning and ranges are taken from the variables themselves and can be changed by
911/// calling their setPlotMin/Max() and setPlotBins() methods. A histogram can be filled
912/// using RooAbsReal::fillHistogram() or RooTreeData::fillHistogram().
913/// The caller takes ownership of the returned object and is responsible for deleting it.
914
915TH1 *RooAbsRealLValue::createHistogram(const char *name, RooArgList &vars, const char *tAxisLabel, const RooAbsBinning** bins)
916{
917 // Check that we have 1-3 vars
918 Int_t dim= vars.getSize();
919 if(dim < 1 || dim > 3) {
920 oocoutE((TObject*)0,InputArguments) << "RooAbsReal::createHistogram: dimension not supported: " << dim << endl;
921 return 0;
922 }
923
924 // Check that all variables are AbsReals and prepare a name of the form <name>_<var1>_...
925 TString histName(name);
926 histName.Append("_");
927 const RooAbsRealLValue *xyz[3];
928
929 Int_t index;
930 for(index= 0; index < dim; index++) {
931 const RooAbsArg *arg= vars.at(index);
932 xyz[index]= dynamic_cast<const RooAbsRealLValue*>(arg);
933 if(!xyz[index]) {
934 oocoutE((TObject*)0,InputArguments) << "RooAbsRealLValue::createHistogram: variable is not real lvalue: " << arg->GetName() << endl;
935 return 0;
936 }
937 histName.Append("_");
938 histName.Append(arg->GetName());
939 }
940 TString histTitle(histName);
941 histTitle.Prepend("Histogram of ");
942
943 // Create the histogram
944 TH1 *histogram = 0;
945 switch(dim) {
946 case 1:
947 if (bins[0]->isUniform()) {
948 histogram= new TH1F(histName.Data(), histTitle.Data(),
949 bins[0]->numBins(),bins[0]->lowBound(),bins[0]->highBound());
950 } else {
951 histogram= new TH1F(histName.Data(), histTitle.Data(),
952 bins[0]->numBins(),bins[0]->array());
953 }
954 break;
955 case 2:
956 if (bins[0]->isUniform() && bins[1]->isUniform()) {
957 histogram= new TH2F(histName.Data(), histTitle.Data(),
958 bins[0]->numBins(),bins[0]->lowBound(),bins[0]->highBound(),
959 bins[1]->numBins(),bins[1]->lowBound(),bins[1]->highBound());
960 } else {
961 histogram= new TH2F(histName.Data(), histTitle.Data(),
962 bins[0]->numBins(),bins[0]->array(),
963 bins[1]->numBins(),bins[1]->array());
964 }
965 break;
966 case 3:
967 if (bins[0]->isUniform() && bins[1]->isUniform() && bins[2]->isUniform()) {
968 histogram= new TH3F(histName.Data(), histTitle.Data(),
969 bins[0]->numBins(),bins[0]->lowBound(),bins[0]->highBound(),
970 bins[1]->numBins(),bins[1]->lowBound(),bins[1]->highBound(),
971 bins[2]->numBins(),bins[2]->lowBound(),bins[2]->highBound()) ;
972 } else {
973 histogram= new TH3F(histName.Data(), histTitle.Data(),
974 bins[0]->numBins(),bins[0]->array(),
975 bins[1]->numBins(),bins[1]->array(),
976 bins[2]->numBins(),bins[2]->array()) ;
977 }
978 break;
979 }
980 if(!histogram) {
981 oocoutE((TObject*)0,InputArguments) << "RooAbsReal::createHistogram: unable to create a new histogram" << endl;
982 return 0;
983 }
984
985 // Set the histogram coordinate axis labels from the titles of each variable, adding units if necessary.
986 for(index= 0; index < dim; index++) {
987 TString axisTitle(xyz[index]->getTitle(kTRUE));
988 switch(index) {
989 case 0:
990 histogram->SetXTitle(axisTitle.Data());
991 break;
992 case 1:
993 histogram->SetYTitle(axisTitle.Data());
994 break;
995 case 2:
996 histogram->SetZTitle(axisTitle.Data());
997 break;
998 default:
999 assert(0);
1000 break;
1001 }
1002 }
1003
1004 // Set the t-axis title if given one
1005 if((0 != tAxisLabel) && (0 != strlen(tAxisLabel))) {
1006 TString axisTitle(tAxisLabel);
1007 axisTitle.Append(" / ( ");
1008 for(Int_t index2= 0; index2 < dim; index2++) {
1009 Double_t delta= bins[index2]->averageBinWidth() ; // xyz[index2]->getBins();
1010 if(index2 > 0) axisTitle.Append(" x ");
1011 axisTitle.Append(Form("%g",delta));
1012 if(strlen(xyz[index2]->getUnit())) {
1013 axisTitle.Append(" ");
1014 axisTitle.Append(xyz[index2]->getUnit());
1015 }
1016 }
1017 axisTitle.Append(" )");
1018 switch(dim) {
1019 case 1:
1020 histogram->SetYTitle(axisTitle.Data());
1021 break;
1022 case 2:
1023 histogram->SetZTitle(axisTitle.Data());
1024 break;
1025 case 3:
1026 // not supported in TH1
1027 break;
1028 default:
1029 assert(0);
1030 break;
1031 }
1032 }
1033
1034 return histogram;
1035}
1036
1037
1039{
1040 // Interface function to indicate that this lvalue
1041 // has a unit or constant jacobian terms with respect to
1042 // the observable passed as argument. This default implementation
1043 // always returns true (i.e. jacobian is constant)
1044 return kTRUE ;
1045}
#define e(i)
Definition: RSha256.hxx:103
#define coutI(a)
Definition: RooMsgService.h:30
#define oocoutE(o, a)
Definition: RooMsgService.h:48
#define coutE(a)
Definition: RooMsgService.h:33
int Int_t
Definition: RtypesCore.h:43
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
double Double_t
Definition: RtypesCore.h:57
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition: TGX11.cxx:109
float xmin
Definition: THbookFile.cxx:93
float xmax
Definition: THbookFile.cxx:93
char * Form(const char *fmt,...)
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:73
RooAbsBinning is the abstract base class for RooRealVar binning definitions This class defines the in...
Definition: RooAbsBinning.h:26
virtual Double_t * array() const =0
Int_t numBins() const
Definition: RooAbsBinning.h:37
virtual Double_t highBound() const =0
virtual Double_t binCenter(Int_t bin) const =0
virtual Double_t lowBound() const =0
virtual Double_t averageBinWidth() const =0
Int_t getSize() const
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:44
Bool_t getRange(const RooAbsRealLValue &var, Double_t &lowest, Double_t &highest, Double_t marginFrac=0, Bool_t symMode=kFALSE) const
Fill Doubles 'lowest' and 'highest' with the lowest and highest value of observable 'var' in this dat...
Abstract base class for objects that are lvalues, i.e.
Definition: RooAbsLValue.h:26
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
virtual Double_t getMax(const char *name=0) const
Get maximum of currently defined range.
Bool_t hasMax(const char *name=0) const
Check if variable has an upper bound.
void copyCache(const RooAbsArg *source, Bool_t valueOnly=kFALSE, Bool_t setValDirty=kTRUE)
Copy cache of another RooAbsArg to our cache.
virtual const RooAbsBinning & getBinning(const char *name=0, Bool_t verbose=kTRUE, Bool_t createOnTheFly=kFALSE) const =0
Retrive binning configuration with given name or default binning.
std::pair< double, double > getRange(const char *name=0) const
Get low and high bound of the variable.
virtual Bool_t isValidReal(Double_t value, Bool_t printError=kFALSE) const
Check if given value is valid.
virtual void printMultiline(std::ostream &os, Int_t contents, Bool_t verbose=kFALSE, TString indent="") const
Structure printing.
virtual void setBin(Int_t ibin, const char *rangeName=0)
Set value to center of bin 'ibin' of binning 'rangeName' (or of default binning if no range is specif...
virtual void setVal(Double_t value)=0
virtual Int_t numBins(const char *rangeName=0) const
virtual Bool_t readFromStream(std::istream &is, Bool_t compact, Bool_t verbose=kFALSE)
Read object contents from given stream.
virtual void randomize(const char *rangeName=0)
Set a new value sampled from a uniform distribution over the fit range.
RooPlot * frame() const
Create a new RooPlot on the heap with a drawing frame initialized for this object,...
TH1 * createHistogram(const char *name, const RooCmdArg &arg1=RooCmdArg::none(), const RooCmdArg &arg2=RooCmdArg::none(), const RooCmdArg &arg3=RooCmdArg::none(), const RooCmdArg &arg4=RooCmdArg::none(), const RooCmdArg &arg5=RooCmdArg::none(), const RooCmdArg &arg6=RooCmdArg::none(), const RooCmdArg &arg7=RooCmdArg::none(), const RooCmdArg &arg8=RooCmdArg::none()) const
virtual void writeToStream(std::ostream &os, Bool_t compact) const
Write object contents to given stream.
virtual Bool_t inRange(const char *name) const
Check if current value is inside range with given name.
virtual Bool_t isJacobianOK(const RooArgSet &depList) const
virtual Int_t getBins(const char *name=0) const
Get number of bins of currently defined range.
virtual void setValFast(Double_t value)
RooAbsRealLValue & operator=(const RooAbsRealLValue &)=default
Bool_t hasMin(const char *name=0) const
Check if variable has a lower bound.
virtual ~RooAbsRealLValue()
Destructor.
virtual Double_t getMin(const char *name=0) const
Get miniminum of currently defined range.
Bool_t fitRangeOKForPlotting() const
Check if fit range is usable as plot range, i.e.
virtual void setBinFast(Int_t ibin, const RooAbsBinning &binning)
Set value to center of bin 'ibin' of binning 'rangeName' (or of default binning if no range is specif...
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:60
TString getTitle(Bool_t appendUnit=kFALSE) const
Return this variable's title string.
Definition: RooAbsReal.cxx:252
virtual void copyCache(const RooAbsArg *source, Bool_t valueOnly=kFALSE, Bool_t setValDirty=kTRUE)
Copy the cached value of another RooAbsArg to our cache.
TString _unit
Value storage for batches of events.
Definition: RooAbsReal.h:451
Double_t _value
Definition: RooAbsReal.h:449
virtual void printMultiline(std::ostream &os, Int_t contents, Bool_t verbose=kFALSE, TString indent="") const
Structure printing.
Definition: RooAbsReal.cxx:475
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition: RooAbsReal.h:90
const Text_t * getUnit() const
Definition: RooAbsReal.h:118
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgList.h:21
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition: RooArgList.h:74
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:28
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition: RooCmdArg.h:28
Class RooCmdConfig is a configurable parser for RooCmdArg named arguments.
Definition: RooCmdConfig.h:27
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
virtual void Add(TObject *arg)
Definition: RooLinkedList.h:62
static Int_t isInfinite(Double_t x)
Return true if x is infinite by RooNumBer internal specification.
Definition: RooNumber.cxx:58
A RooPlot is a plot frame and a container for graphics objects within that frame.
Definition: RooPlot.h:44
void SetTitle(const char *name)
Set the title of the RooPlot to 'title'.
Definition: RooPlot.cxx:1258
void SetName(const char *name)
Set the name of the RooPlot to 'name'.
Definition: RooPlot.cxx:1236
static Double_t uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1)
Definition: RooRandom.cxx:83
RooRealVar represents a variable that can be changed from the outside.
Definition: RooRealVar.h:35
RooUniformBinning is an implementation of RooAbsBinning that provides a uniform binning in 'n' bins b...
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:571
The TH1 histogram class.
Definition: TH1.h:56
virtual void SetXTitle(const char *title)
Definition: TH1.h:409
virtual void SetZTitle(const char *title)
Definition: TH1.h:411
virtual void SetYTitle(const char *title)
Definition: TH1.h:410
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:251
3-D histogram with a float per channel (see TH1 documentation)}
Definition: TH3.h:267
TString fName
Definition: TNamed.h:32
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Basic string class.
Definition: TString.h:131
const char * Data() const
Definition: TString.h:364
TString & Prepend(const char *cs)
Definition: TString.h:656
Bool_t IsNull() const
Definition: TString.h:402
TString & Append(const char *cs)
Definition: TString.h:559
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
@ Generation
Definition: RooGlobalFunc.h:67
@ InputArguments
Definition: RooGlobalFunc.h:68
std::vector< std::string > tokenise(const std::string &str, const std::string &delims, bool returnEmptyToken=true)
Tokenise the string by splitting at the characters in delims.
Definition: RooHelpers.cxx:62
static constexpr double pc
auto * l
Definition: textangle.C:4
REAL epsilon
Definition: triangle.c:617