Logo ROOT   6.18/05
Reference Guide
TGL5DPainter.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 28/07/2009
3
4/*************************************************************************
5 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TVirtualPad.h"
13#include "KeySymbols.h"
14#include "TVirtualX.h"
15#include "Buttons.h"
16#include "TString.h"
17#include "TError.h"
18#include "TROOT.h"
19#include "TMath.h"
20
21#include "TGLPlotCamera.h"
22#include "TGL5DPainter.h"
23#include "TGLPadUtils.h"
24#include "TGLIncludes.h"
25#include "TGL5D.h"
26
27/** \class TGL5DPainter
28\ingroup opengl
29TGL5DPainter implements "gl5d" option for TTree::Draw.
30Data (4D) is visualized as a set of iso-surfaces. 5D.
31*/
32
33////////////////////////////////////////////////////////////////////////////////
34///Constructor.
35
37 : TGLPlotPainter(data, camera, coord),
38 fMeshBuilder(kTRUE),//kTRUE == average normals.
39 fInit(kFALSE),
40 fData(data),
41 fShowSlider(kFALSE),
42 fAlpha(0.4),
43 fNContours(kNContours)
44{
45 if (fData->fV4IsString)
46 fNContours = Int_t(fData->fV4MinMax.second) - Int_t(fData->fV4MinMax.first) + 1;
47}
48
49////////////////////////////////////////////////////////////////////////////////
50///Try to add new iso-surface.
51///If something goes wrong, return
52///iterator to the end of fIsos.
53
56 Double_t range, Int_t lownps)
57{
58 fData->SelectPoints(v4, range);
59
60 if (fData->SelectedSize() < size_type(lownps)) {
61 Warning("TGL5DPainter::AddSurface", "Too little points: %d", Int_t(fData->SelectedSize()));
62 return fIsos.end();//This is a valid iterator, but an invalid surface.
63 } else {
64 Info("TGL5DPainter::AddSurface", "Selected %d points", Int_t(fData->SelectedSize()));
65 }
66
67 fKDE.BuildModel(fData, sigma);//Prepare density estimator.
68
69 Info("TGL5DPainter::AddSurface", "Building the mesh ...");
70 //Prepare grid parameters.
74 fCoord->GetZScale());
75 Mesh_t mesh;
76 fMeshBuilder.SetGeometry(fData);
77 //Build a new mesh.
78 fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, iso);
79
80 Info("TGL5DPainter::AddSurface", "Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
81
82 if (!mesh.fVerts.size())//I do not need an empty mesh.
83 return fIsos.end();
84 //Add surface with empty mesh and swap meshes.
85 fIsos.push_front(fDummy);
86
87 fIsos.front().fMesh.Swap(mesh);
88 fIsos.front().f4D = v4;
89 fIsos.front().fRange = range;
90 fIsos.front().fShowCloud = kFALSE;
91 fIsos.front().fHide = kFALSE;
92 fIsos.front().fColor = ci;
93
94 //Predictions for the 5-th variable.
95 //Not-implemented yet.
96 return fIsos.begin();
97}
98
99////////////////////////////////////////////////////////////////////////////////
100///Add new surface. Simplified version for ged.
101
103{
104 const Rgl::Range_t &v4R = fData->fV4MinMax;
105 const Bool_t isString = fData->fV4IsString;
106 const Double_t rms = TMath::RMS(fData->fNP, fData->fV4); //RMS of the N points.
107 const Double_t d = isString ? (v4R.second - v4R.first) / (fNContours - 1)
108 : 6 * rms / fNContours;
109 //alpha is in [0.1, 0.5], 1e-3 -s good for strings.
110 const Double_t range = isString ? 1e-3 : fAlpha * d;
111
112 AddSurface(v4, 1, 0.125, 0.05, range);
113}
114
115////////////////////////////////////////////////////////////////////////////////
116///Remove iso-surface.
117
119{
120 if (surf == fIsos.end()) {
121 Error("TGL5DPainter::RemoveSurface", "Invalid iterator, surface does not exist.");
122 return;
123 }
124
125 fIsos.erase(surf);
126}
127
128////////////////////////////////////////////////////////////////////////////////
129///Return info for plot part under cursor.
130
132{
133 static char mess[] = {"gl5d"};
134 return mess;
135}
136
137////////////////////////////////////////////////////////////////////////////////
138///Create mesh.
139///InitGeometry creates surfaces for auto-iso levels.
140///Called the first time and each time number of auto-levels is
141///reset via the editor.
142
144{
145 if (fInit)
146 return kTRUE;
147 //Only in cartesian.
149
151 return kFALSE;
152
153 fIsos.clear();
154
158 if (fCamera)
160
161 const Rgl::Range_t &v4R = fData->fV4MinMax;
162 const Bool_t isString = fData->fV4IsString;
163
164 //Rene's code to automatically find iso-levels.
165 const Double_t mean = TMath::Mean(fData->fNP, fData->fV4); //mean value of the NP points.
166 const Double_t rms = TMath::RMS(fData->fNP, fData->fV4); //RMS of the N points.
167 const Double_t min = isString ? v4R.first : mean - 3 * rms; //take a range +- 3*xrms
168 const Double_t d = isString ? (v4R.second - v4R.first) / (fNContours - 1)
169 : 6 * rms / fNContours;
170 //alpha is in [0.1, 0.5], 1e-3 -s good for strings.
171 const Double_t range = isString ? 1e-3 : fAlpha * d;
172
173 Info("InitGeometry", "min = %g, mean = %g, rms = %g, dx = %g", min, mean, rms, d);
174
175 for (Int_t j = 0; j < fNContours; ++j) {
176 const Double_t isoLevel = min + j * d;
177 Info("TGL5DPainter::InitGeometry", "Iso-level %g, range is %g ...", isoLevel, range);
178 const Color_t color = j * 6 + 1;
179 AddSurface(isoLevel, color, 0.125, 0.05, range);
180 }
181
182 if (fIsos.size())
184
185 return fInit = kTRUE;
186}
187
188////////////////////////////////////////////////////////////////////////////////
189///User clicks right mouse button (in a pad).
190
192{
193 fMousePosition.fX = px;
195 fCamera->StartPan(px, py);
197}
198
199////////////////////////////////////////////////////////////////////////////////
200///Mouse events handler.
201
203{
204 if (fSelectedPart >= fSelectionBase) {//Pan camera.
207
210 fCamera->Pan(px, py);
211
214 } else if (fSelectedPart > 0) {
215 //Convert py into bottom-top orientation.
216 py = fCamera->GetHeight() - py;
217
220
223
224 if (!fHighColor) {
227 }
228 }
229
232 }
233
236}
237
238////////////////////////////////////////////////////////////////////////////////
239///No additional options for TGL5DPainter.
240
241void TGL5DPainter::AddOption(const TString &/*option*/)
242{
243}
244
245////////////////////////////////////////////////////////////////////////////////
246
248{
249 //Change color scheme.
250 if (event == kKeyPress) {
251 if (py == kKey_c || py == kKey_C) {
252 if (fHighColor)
253 Info("ProcessEvent", "Cut box does not work in high color, please, switch to true color");
254 else {
257 }
258 }
259 } else if (event == kButton1Double && fBoxCut.IsActive()) {
260 if (fBoxCut.IsActive())
262 if (!gVirtualX->IsCmdThread())
263 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
264 else
265 Paint();
266 }
267}
268
269////////////////////////////////////////////////////////////////////////////////
270///Set selection range parameter.
271
273{
274 if (fAlpha != newVal && !fData->fV4IsString) {
275 fAlpha = newVal;
276 fInit = kFALSE;
277 InitGeometry();
278 }
279
280 if (fData->fV4IsString)
281 Warning("SetAlpha", "Alpha is not required for string data (your 4-th dimension is string).");
282}
283
284////////////////////////////////////////////////////////////////////////////////
285///Set the number of predefined contours.
286
288{
289 if (n <= 0) {
290 Warning("SetNContours", "Bad number of contours: %d", n);
291 return;
292 }
293
294 fNContours = n;
295 fInit = kFALSE;
296 InitGeometry();
297}
298
299////////////////////////////////////////////////////////////////////////////////
300///No need to create or delete meshes,
301///number of meshes (iso-levels) are
302///the same, but meshes must be rebuilt
303///in new ranges.
304///Only in cartesian.
305
307{
312 if (fCamera)
314 //Iterate through all surfaces and re-calculate them.
315 for (SurfIter_t surf = fIsos.begin(); surf != fIsos.end(); ++surf) {
316 fData->SelectPoints(surf->f4D, surf->fRange);
317 fKDE.BuildModel(fData, 0.05);//0.05 is sigma, will be controlled via GUI.
318 Info("TGL5DPainter::ResetGeometryRanges", "Building the mesh ...");
319 //Prepare grid parameters.
321 fCoord->GetXScale(),
322 fCoord->GetYScale(),
323 fCoord->GetZScale());
324 fMeshBuilder.SetGeometry(fData);
325 Mesh_t &mesh = surf->fMesh;
326 //Clear old data.
327 mesh.fVerts.clear();
328 mesh.fNorms.clear();
329 mesh.fTris.clear();
330 //Build new mesh.
331 fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, 0.125);//0.125 will be set via GUI.
332 Info("TGL5DPainter::AddSurface", "Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
333 }
334
336}
337
338////////////////////////////////////////////////////////////////////////////////
339///std::list::begin.
340
342{
343 return fIsos.begin();
344}
345
346////////////////////////////////////////////////////////////////////////////////
347///std::list::end.
348
350{
351 return fIsos.end();
352}
353
354////////////////////////////////////////////////////////////////////////////////
355///Initialize OpenGL state variables.
356
358{
359 glEnable(GL_LIGHTING);
360 glEnable(GL_LIGHT0);
361 glEnable(GL_DEPTH_TEST);
362 glDisable(GL_CULL_FACE);
363 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
364}
365
366////////////////////////////////////////////////////////////////////////////////
367///Return some gl states to original values.
368
370{
371 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
372 glDisable(GL_CULL_FACE);
373 glDisable(GL_DEPTH_TEST);
374 glDisable(GL_LIGHT0);
375 glDisable(GL_LIGHTING);
376}
377
378////////////////////////////////////////////////////////////////////////////////
379///Draw a set of meshes.
380
382{
383 //Shift plot to point of origin.
384 const Rgl::PlotTranslation trGuard(this);
385
387 //
388 if (!fIsos.size())
389 DrawCloud();
390 else {
391 //Two passes. First, non-transparent surfaces.
392 Bool_t needSecondPass = kFALSE;
393 for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
394 //
395 if (it->fHide)
396 continue;
397 if (it->fAlpha != 100) {
398 needSecondPass = kTRUE;
399 continue;
400 }
401 if (!fSelectionPass)
402 SetSurfaceColor(it);
403 glEnable(GL_POLYGON_OFFSET_FILL);
404 glPolygonOffset(1.f, 1.f);
405 DrawMesh(it);
406 glDisable(GL_POLYGON_OFFSET_FILL);
407
408 if (!fSelectionPass && it->fHighlight) {
409 const TGLDisableGuard lightGuard(GL_LIGHTING);
410 const TGLEnableGuard blendGuard(GL_BLEND);
411 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
412 glColor4d(1., 0.4, 0., 0.5);
413 DrawMesh(it);
414 }
415 }
416 //Second pass - semi-transparent surfaces.
417 if (needSecondPass) {
418 const TGLEnableGuard blendGuard(GL_BLEND);
419 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
420 glDepthMask(GL_FALSE);
421 for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
422 //
423 if (it->fAlpha == 100)
424 continue;
425 if (!fSelectionPass)
426 SetSurfaceColor(it);
427
428 glEnable(GL_POLYGON_OFFSET_FILL);
429 glPolygonOffset(1.f, 1.f);
430 DrawMesh(it);
431 glDisable(GL_POLYGON_OFFSET_FILL);
432
433 if (!fSelectionPass && it->fHighlight) {
434 const TGLDisableGuard lightGuard(GL_LIGHTING);
435 glColor4d(1., 0.4, 0., it->fAlpha / 150.);
436 DrawMesh(it);
437 }
438 }
439 glDepthMask(GL_TRUE);
440 }
441 }
442
443 if (fBoxCut.IsActive())
445}
446
447////////////////////////////////////////////////////////////////////////////////
448///Set the color for iso-surface.
449
451{
452 Color_t ind = it->fColor;
453 Float_t rgba[] = {0.f, 0.f, 0.f, static_cast<Float_t>(it->fAlpha / 100.)};
454 Rgl::Pad::ExtractRGBA(ind, rgba);
455 //Set color for surface.
456 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, rgba);
457 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
458 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
459 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.f);
460}
461
462////////////////////////////////////////////////////////////////////////////////
463///Draw full cloud of points.
464
466{
467 const TGLDisableGuard light(GL_LIGHTING);
468 const TGLDisableGuard depth(GL_DEPTH_TEST);
469
470 glColor3d(0.4, 0., 1.);
471 glPointSize(3.f);
472
473 glBegin(GL_POINTS);
474
475 const Double_t xs = fCoord->GetXScale();
476 const Double_t ys = fCoord->GetYScale();
477 const Double_t zs = fCoord->GetZScale();
478
479 for (Int_t i = 0; i < fData->fNP; ++i)
480 glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
481
482 glEnd();
483
484 glPointSize(1.f);
485}
486
487////////////////////////////////////////////////////////////////////////////////
488///Draw cloud for selected iso-surface.
489
491{
492 const TGLDisableGuard light(GL_LIGHTING);
493
494 Float_t rgba[4] = {};
495 Rgl::Pad::ExtractRGBA(ci, rgba);
496
497 glColor3fv(rgba);
498 glPointSize(3.f);
499
500 glBegin(GL_POINTS);
501
502 const Double_t xs = fCoord->GetXScale();
503 const Double_t ys = fCoord->GetYScale();
504 const Double_t zs = fCoord->GetZScale();
505
506 for (Int_t i = 0; i < fData->fNP; ++i)
507 if (TMath::Abs(fData->fV4[i] - v4) < range)
508 glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
509
510 glEnd();
511
512 glPointSize(1.f);
513}
514
515////////////////////////////////////////////////////////////////////////////////
516///Draw one iso-surface.
517
519{
520 const Mesh_t &m = surf->fMesh;
521
522 if (!fBoxCut.IsActive()) {
523 if (!fSelectionPass)
524 Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris);
525 else {
527 Rgl::DrawMesh(m.fVerts, m.fTris);
528 }
529 } else {
530 if (!fSelectionPass) {
531 Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris, fBoxCut);
532 } else {
534 Rgl::DrawMesh(m.fVerts, m.fTris, fBoxCut);
535 }
536 }
537}
@ kKeyPress
Definition: Buttons.h:20
@ kButton1Double
Definition: Buttons.h:24
@ kKey_C
Definition: KeySymbols.h:128
@ kKey_c
Definition: KeySymbols.h:160
#define d(i)
Definition: RSha256.hxx:102
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
short Color_t
Definition: RtypesCore.h:79
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
void Info(const char *location, const char *msgfmt,...)
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
@ kGLCartesian
Definition: TGLUtil.h:43
#define gROOT
Definition: TROOT.h:414
char * Form(const char *fmt,...)
#define gVirtualX
Definition: TVirtualX.h:345
std::vector< V > fVerts
Definition: TGLIsoMesh.h:81
std::vector< V > fNorms
Definition: TGLIsoMesh.h:82
std::vector< UInt_t > fTris
Definition: TGLIsoMesh.h:83
void BuildMesh(const DataSource *src, const TGridGeometry< ValueType > &geom, MeshType_t *mesh, ValueType iso)
Build iso-mesh using marching cubes.
void SelectPoints(Double_t v4Level, Double_t range)
"Select" sub-range from source data
Definition: TGL5D.cxx:144
Rgl::Range_t fV4MinMax
Definition: TGL5D.h:90
const Double_t * fV4
Definition: TGL5D.h:79
const Double_t * fV1
Definition: TGL5D.h:76
const Double_t * fV2
Definition: TGL5D.h:77
Bool_t fV4IsString
Definition: TGL5D.h:99
Long64_t fNP
Definition: TGL5D.h:75
UInt_t SelectedSize() const
Size of selected sub-range.
Definition: TGL5D.cxx:156
const Double_t * fV3
Definition: TGL5D.h:78
void StartPan(Int_t px, Int_t py)
User clicks right mouse button (in a pad).
void SetSurfaceColor(ConstSurfIter_t surf) const
Set the color for iso-surface.
void DrawMesh(ConstSurfIter_t surf) const
Draw one iso-surface.
SurfList_t fIsos
Definition: TGL5DPainter.h:71
void SetNContours(Int_t num)
Set the number of predefined contours.
void ResetGeometryRanges()
No need to create or delete meshes, number of meshes (iso-levels) are the same, but meshes must be re...
SurfList_t::iterator SurfIter_t
Definition: TGL5DPainter.h:61
SurfIter_t SurfacesBegin()
std::list::begin.
void RemoveSurface(SurfIter_t surf)
Remove iso-surface.
Rgl::Mc::TMeshBuilder< TKDEFGT, Float_t > fMeshBuilder
Definition: TGL5DPainter.h:66
SurfIter_t SurfacesEnd()
std::list::end.
char * GetPlotInfo(Int_t px, Int_t py)
Return info for plot part under cursor.
void DeInitGL() const
Return some gl states to original values.
void SetAlpha(Double_t newAlpha)
Set selection range parameter.
void DrawCloud() const
Draw full cloud of points.
SurfIter_t AddSurface(Double_t v4, Color_t ci, Double_t isoVal=1., Double_t sigma=1., Double_t range=1e-3, Int_t lowNumOfPoints=kNLowPts)
Try to add new iso-surface.
SurfList_t::const_iterator ConstSurfIter_t
Definition: TGL5DPainter.h:62
void AddOption(const TString &option)
No additional options for TGL5DPainter.
Int_t fNContours
Definition: TGL5DPainter.h:81
TKDEFGT fKDE
Definition: TGL5DPainter.h:65
void DrawSubCloud(Double_t v4, Double_t range, Color_t ci) const
Draw cloud for selected iso-surface.
Double_t fAlpha
Definition: TGL5DPainter.h:80
void Pan(Int_t px, Int_t py)
Mouse events handler.
void DrawPlot() const
Draw a set of meshes.
TGL5DPainter(TGL5DDataSet *data, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
Constructor.
std::vector< Double_t >::size_type size_type
Definition: TGL5DPainter.h:74
TGL5DDataSet * fData
Definition: TGL5DPainter.h:72
void ProcessEvent(Int_t event, Int_t px, Int_t py)
void InitGL() const
Initialize OpenGL state variables.
Bool_t fInit
Definition: TGL5DPainter.h:69
const Surf_t fDummy
Definition: TGL5DPainter.h:68
Bool_t InitGeometry()
Create mesh.
void MoveBox(Int_t px, Int_t py, Int_t axisID)
Move box cut along selected direction.
void DrawBox(Bool_t selectionPass, Int_t selected) const
Draw cut as a semi-transparent box.
void TurnOnOff()
Turn the box cut on/off.
void StartMovement(Int_t px, Int_t py)
Start cut's movement.
Bool_t IsActive() const
void ResetBoxGeometry()
Set geometry using plot's back box.
void SetPlotBox(const Rgl::Range_t &xRange, const Rgl::Range_t &yRange, const Rgl::Range_t &zRange)
Set up a frame box.
Definition: TGLPlotBox.cxx:198
const TGLVertex3 * Get3DBox() const
Get 3D box.
Definition: TGLPlotBox.cxx:303
void DrawBox(Int_t selectedPart, Bool_t selectionPass, const std::vector< Double_t > &zLevels, Bool_t highColor) const
Draw back box for a plot.
Definition: TGLPlotBox.cxx:184
Camera for TGLPlotPainter and sub-classes.
Definition: TGLPlotCamera.h:22
void StartPan(Int_t px, Int_t py)
User clicks somewhere (px, py).
void Apply(Double_t phi, Double_t theta) const
Applies rotations and translations before drawing.
void SetCamera() const
Viewport and projection.
void Pan(Int_t px, Int_t py)
Pan camera.
Int_t GetHeight() const
viewport[3]
void SetViewVolume(const TGLVertex3 *box)
'box' is the TGLPlotPainter's back box's coordinates.
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
Bool_t SetRanges(const TH1 *hist, Bool_t errors=kFALSE, Bool_t zBins=kFALSE)
Set bin ranges, ranges.
Double_t GetYScale() const
const Rgl::Range_t & GetXRangeScaled() const
Scaled range.
const Rgl::Range_t & GetYRangeScaled() const
Scaled range.
void SetCoordType(EGLCoordType type)
If coord type was changed, plot must reset sections (if any), set fModified.
Double_t GetXScale() const
Double_t GetZScale() const
const Rgl::Range_t & GetZRangeScaled() const
Scaled range.
Base class for plot-painters that provide GL rendering of various 2D and 3D histograms,...
Double_t fPadTheta
std::vector< Double_t > fZLevels
void RestoreModelviewMatrix() const
TGLBoxCut fBoxCut
virtual void Paint()
Draw lego/surf/whatever you can.
TGLPlotCoordinates * fCoord
TGLPlotBox fBackBox
void SaveProjectionMatrix() const
void SaveModelviewMatrix() const
Bool_t fUpdateSelection
TGLPlotCamera * fCamera
void RestoreProjectionMatrix() const
void BuildModel(const std::vector< Double_t > &sources, Double_t sigma=1., UInt_t dim=3, UInt_t p=8, UInt_t k=0)
Calculate coefficients for FGT.
Definition: TKDEFGT.cxx:55
SCoord_t fY
Definition: TPoint.h:36
SCoord_t fX
Definition: TPoint.h:35
Basic string class.
Definition: TString.h:131
const Double_t sigma
const Int_t n
Definition: legend1.C:16
void ExtractRGBA(Color_t colorIndex, Float_t *rgba)
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Definition: TGLUtil.cxx:2892
std::pair< Double_t, Double_t > Range_t
Definition: TGLUtil.h:1194
void DrawMesh(const std::vector< Float_t > &vs, const std::vector< Float_t > &ns, const std::vector< UInt_t > &ts)
Call function-template.
Definition: TGLIsoMesh.cxx:39
Double_t Mean(Long64_t n, const T *a, const Double_t *w=0)
Return the weighted mean of an array a with length n.
Definition: TMath.h:1061
Double_t RMS(Long64_t n, const T *a, const Double_t *w=0)
Return the Standard Deviation of an array a with length n.
Definition: TMath.h:1155
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
auto * m
Definition: textangle.C:8