// @(#)root/gl:$Id$
// Author: Timur Pocheptsov  2009
/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
#include <stdexcept>

#include "TTreeFormula.h"
#include "TTree.h"
#include "TMath.h"
#include "TH3.h"

#include "TGLPlotCamera.h"
#include "TGL5DPainter.h"
#include "TGL5D.h"

ClassImp(TGL5DDataSet)

namespace {

void FindRange(Long64_t size, const Double_t *src, Rgl::Range_t &range);

}

//______________________________________________________________________________
TGL5DDataSet::TGL5DDataSet(TTree *tree)
               : TNamed("TGL5DataSet", "TGL5DataSet"),
                 fNP(0),
                 fV1(0), fV2(0), fV3(0), fV4(0), fV5(0),
                 fV1Range(1.), fV2Range(1.), fV3Range(1.),
                 fV4IsString(kFALSE)
{
   //Constructor. Reads data from TTree,
   //estimates ranges, creates a painter.
   if (!tree) {
      Error("TGL5Data", "Null pointer tree.");
      throw std::runtime_error("");
   }

   fNP = tree->GetSelectedRows();

   Info("TGL5DDataSet", "Number of selected rows: %d", Int_t(fNP))   ;
   //Now, let's access the data and find ranges.
   fV1 = tree->GetVal(0);
   fV2 = tree->GetVal(1);
   fV3 = tree->GetVal(2);
   fV4 = tree->GetVal(3);
   fV5 = tree->GetVal(4);
   //
   fV4IsString = tree->GetVar(3)->IsString();
   //
   if (!fV1 || !fV2 || !fV3 || !fV4 || !fV5) {
      Error("TGL5DDataSet", "One or all of vN is a null pointer.");
      throw std::runtime_error("");
   }
   //
   FindRange(fNP, fV1, fV1MinMax);
   FindRange(fNP, fV2, fV2MinMax);
   FindRange(fNP, fV3, fV3MinMax);
   FindRange(fNP, fV4, fV4MinMax);
   FindRange(fNP, fV5, fV5MinMax);
   //
   const Double_t v1Add = 0.1 * (fV1MinMax.second - fV1MinMax.first);
   const Double_t v2Add = 0.1 * (fV2MinMax.second - fV2MinMax.first);
   const Double_t v3Add = 0.1 * (fV3MinMax.second - fV3MinMax.first);
   //Adjust ranges.
   fV1MinMax.first  -= v1Add, fV1MinMax.second += v1Add;
   fV1Range = fV1MinMax.second - fV1MinMax.first;
   fV2MinMax.first  -= v2Add, fV2MinMax.second += v2Add;
   fV2Range = fV2MinMax.second - fV2MinMax.first;
   fV3MinMax.first  -= v3Add, fV3MinMax.second += v3Add;
   fV3Range = fV3MinMax.second - fV3MinMax.first;
   //Set axes.
   TH3F hist("tmp", "tmp", 2, -1., 1., 2, -1., 1., 2, -1., 1.);
   //TAxis has a lot of attributes, defaults, set by ctor,
   //are not enough to be correctly painted by TGaxis object.
   //To simplify their initialization - I use temporary histogram.
   hist.GetXaxis()->Copy(fXAxis);
   hist.GetYaxis()->Copy(fYAxis);
   hist.GetZaxis()->Copy(fZAxis);

   fXAxis.Set(kDefaultNB, fV1MinMax.first, fV1MinMax.second);
   fYAxis.Set(kDefaultNB, fV2MinMax.first, fV2MinMax.second);
   fZAxis.Set(kDefaultNB, fV3MinMax.first, fV3MinMax.second);

   fPainter.reset(new TGLHistPainter(this));
   SetBit(kCanDelete);//TPad will delete this object when closed.
}

//______________________________________________________________________________
Int_t TGL5DDataSet::DistancetoPrimitive(Int_t px, Int_t py)
{
   //Check, if the object is under cursor.
   return fPainter->DistancetoPrimitive(px, py);
}

//______________________________________________________________________________
void TGL5DDataSet::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
   //Action.
   return fPainter->ExecuteEvent(event, px, py);
}

//______________________________________________________________________________
char *TGL5DDataSet::GetObjectInfo(Int_t /*px*/, Int_t /*py*/) const
{
   //Info for status bar.
   static char mess[] = {"5d data set"};
   return mess;
}

//______________________________________________________________________________
void TGL5DDataSet::Paint(Option_t * /*option*/)
{
   //Paint.
   fPainter->Paint("dummyoption");
}

//______________________________________________________________________________
TGL5DPainter *TGL5DDataSet::GetRealPainter()const
{
   //Get access to painter (for GUI-editor).
   return static_cast<TGL5DPainter *>(fPainter->GetRealPainter());
}

//______________________________________________________________________________
void TGL5DDataSet::SelectPoints(Double_t v4Level, Double_t range)
{
   //"Select" sub-range from source data
   //- remember indices of "good" points.
   fIndices.clear();

   for (Int_t i = 0; i < fNP; ++i)
      if (TMath::Abs(fV4[i] - v4Level) < range)
         fIndices.push_back(i);
}

//______________________________________________________________________________
UInt_t TGL5DDataSet::SelectedSize()const
{
   //Size of selected sub-range.
   return UInt_t(fIndices.size());
}

//______________________________________________________________________________
Double_t TGL5DDataSet::V1(UInt_t ind)const
{
   //V1 from sub-range, converted to unit cube.
   return V1ToUnitCube(fV1[fIndices[ind]]);
}

//______________________________________________________________________________
Double_t TGL5DDataSet::V2(UInt_t ind)const
{
   //V2 from sub-range, converted to unit cube.
   return V2ToUnitCube(fV2[fIndices[ind]]);
}

//______________________________________________________________________________
Double_t TGL5DDataSet::V3(UInt_t ind)const
{
   //V3 from sub-range, converted to unit cube.
   return V3ToUnitCube(fV3[fIndices[ind]]);
}

//______________________________________________________________________________
TAxis *TGL5DDataSet::GetXAxis()const
{
   //X axis for plot.
   return &fXAxis;
}

//______________________________________________________________________________
TAxis *TGL5DDataSet::GetYAxis()const
{
   //Y axis for plot.
   return &fYAxis;
}

//______________________________________________________________________________
TAxis *TGL5DDataSet::GetZAxis()const
{
   //Z axis for plot.
   return &fZAxis;
}

//______________________________________________________________________________
const Rgl::Range_t &TGL5DDataSet::GetXRange()const
{
   //V1 range (X).
   return fV1MinMax;
}

//______________________________________________________________________________
const Rgl::Range_t &TGL5DDataSet::GetYRange()const
{
   //V2 range (Y).
   return fV2MinMax;
}

//______________________________________________________________________________
const Rgl::Range_t &TGL5DDataSet::GetZRange()const
{
   //V3 range (Z).
   return fV3MinMax;
}

//______________________________________________________________________________
const Rgl::Range_t &TGL5DDataSet::GetV4Range()const
{
   //V4 range.
   return fV4MinMax;
}

//______________________________________________________________________________
Double_t TGL5DDataSet::V1ToUnitCube(Double_t v1)const
{
   //V1 to unit cube.
   return (v1 - fV1MinMax.first) / fV1Range;
}

//______________________________________________________________________________
Double_t TGL5DDataSet::V2ToUnitCube(Double_t v2)const
{
   //V2 to unit cube.
   return (v2 - fV2MinMax.first) / fV2Range;
}

//______________________________________________________________________________
Double_t TGL5DDataSet::V3ToUnitCube(Double_t v3)const
{
   //V3 to unit cube.
   return (v3 - fV3MinMax.first) / fV3Range;
}

namespace {

//______________________________________________________________________________
void FindRange(Long64_t size, const Double_t *src, Rgl::Range_t &range)
{
   //Find both min and max on a range in one pass through sequence.
   range.first  = src[0];
   range.second = src[0];

   for (Long64_t i = 1; i < size; ++i) {
      range.first  = TMath::Min(range.first,  src[i]);
      range.second = TMath::Max(range.second, src[i]);
   }
}

}
 TGL5D.cxx:1
 TGL5D.cxx:2
 TGL5D.cxx:3
 TGL5D.cxx:4
 TGL5D.cxx:5
 TGL5D.cxx:6
 TGL5D.cxx:7
 TGL5D.cxx:8
 TGL5D.cxx:9
 TGL5D.cxx:10
 TGL5D.cxx:11
 TGL5D.cxx:12
 TGL5D.cxx:13
 TGL5D.cxx:14
 TGL5D.cxx:15
 TGL5D.cxx:16
 TGL5D.cxx:17
 TGL5D.cxx:18
 TGL5D.cxx:19
 TGL5D.cxx:20
 TGL5D.cxx:21
 TGL5D.cxx:22
 TGL5D.cxx:23
 TGL5D.cxx:24
 TGL5D.cxx:25
 TGL5D.cxx:26
 TGL5D.cxx:27
 TGL5D.cxx:28
 TGL5D.cxx:29
 TGL5D.cxx:30
 TGL5D.cxx:31
 TGL5D.cxx:32
 TGL5D.cxx:33
 TGL5D.cxx:34
 TGL5D.cxx:35
 TGL5D.cxx:36
 TGL5D.cxx:37
 TGL5D.cxx:38
 TGL5D.cxx:39
 TGL5D.cxx:40
 TGL5D.cxx:41
 TGL5D.cxx:42
 TGL5D.cxx:43
 TGL5D.cxx:44
 TGL5D.cxx:45
 TGL5D.cxx:46
 TGL5D.cxx:47
 TGL5D.cxx:48
 TGL5D.cxx:49
 TGL5D.cxx:50
 TGL5D.cxx:51
 TGL5D.cxx:52
 TGL5D.cxx:53
 TGL5D.cxx:54
 TGL5D.cxx:55
 TGL5D.cxx:56
 TGL5D.cxx:57
 TGL5D.cxx:58
 TGL5D.cxx:59
 TGL5D.cxx:60
 TGL5D.cxx:61
 TGL5D.cxx:62
 TGL5D.cxx:63
 TGL5D.cxx:64
 TGL5D.cxx:65
 TGL5D.cxx:66
 TGL5D.cxx:67
 TGL5D.cxx:68
 TGL5D.cxx:69
 TGL5D.cxx:70
 TGL5D.cxx:71
 TGL5D.cxx:72
 TGL5D.cxx:73
 TGL5D.cxx:74
 TGL5D.cxx:75
 TGL5D.cxx:76
 TGL5D.cxx:77
 TGL5D.cxx:78
 TGL5D.cxx:79
 TGL5D.cxx:80
 TGL5D.cxx:81
 TGL5D.cxx:82
 TGL5D.cxx:83
 TGL5D.cxx:84
 TGL5D.cxx:85
 TGL5D.cxx:86
 TGL5D.cxx:87
 TGL5D.cxx:88
 TGL5D.cxx:89
 TGL5D.cxx:90
 TGL5D.cxx:91
 TGL5D.cxx:92
 TGL5D.cxx:93
 TGL5D.cxx:94
 TGL5D.cxx:95
 TGL5D.cxx:96
 TGL5D.cxx:97
 TGL5D.cxx:98
 TGL5D.cxx:99
 TGL5D.cxx:100
 TGL5D.cxx:101
 TGL5D.cxx:102
 TGL5D.cxx:103
 TGL5D.cxx:104
 TGL5D.cxx:105
 TGL5D.cxx:106
 TGL5D.cxx:107
 TGL5D.cxx:108
 TGL5D.cxx:109
 TGL5D.cxx:110
 TGL5D.cxx:111
 TGL5D.cxx:112
 TGL5D.cxx:113
 TGL5D.cxx:114
 TGL5D.cxx:115
 TGL5D.cxx:116
 TGL5D.cxx:117
 TGL5D.cxx:118
 TGL5D.cxx:119
 TGL5D.cxx:120
 TGL5D.cxx:121
 TGL5D.cxx:122
 TGL5D.cxx:123
 TGL5D.cxx:124
 TGL5D.cxx:125
 TGL5D.cxx:126
 TGL5D.cxx:127
 TGL5D.cxx:128
 TGL5D.cxx:129
 TGL5D.cxx:130
 TGL5D.cxx:131
 TGL5D.cxx:132
 TGL5D.cxx:133
 TGL5D.cxx:134
 TGL5D.cxx:135
 TGL5D.cxx:136
 TGL5D.cxx:137
 TGL5D.cxx:138
 TGL5D.cxx:139
 TGL5D.cxx:140
 TGL5D.cxx:141
 TGL5D.cxx:142
 TGL5D.cxx:143
 TGL5D.cxx:144
 TGL5D.cxx:145
 TGL5D.cxx:146
 TGL5D.cxx:147
 TGL5D.cxx:148
 TGL5D.cxx:149
 TGL5D.cxx:150
 TGL5D.cxx:151
 TGL5D.cxx:152
 TGL5D.cxx:153
 TGL5D.cxx:154
 TGL5D.cxx:155
 TGL5D.cxx:156
 TGL5D.cxx:157
 TGL5D.cxx:158
 TGL5D.cxx:159
 TGL5D.cxx:160
 TGL5D.cxx:161
 TGL5D.cxx:162
 TGL5D.cxx:163
 TGL5D.cxx:164
 TGL5D.cxx:165
 TGL5D.cxx:166
 TGL5D.cxx:167
 TGL5D.cxx:168
 TGL5D.cxx:169
 TGL5D.cxx:170
 TGL5D.cxx:171
 TGL5D.cxx:172
 TGL5D.cxx:173
 TGL5D.cxx:174
 TGL5D.cxx:175
 TGL5D.cxx:176
 TGL5D.cxx:177
 TGL5D.cxx:178
 TGL5D.cxx:179
 TGL5D.cxx:180
 TGL5D.cxx:181
 TGL5D.cxx:182
 TGL5D.cxx:183
 TGL5D.cxx:184
 TGL5D.cxx:185
 TGL5D.cxx:186
 TGL5D.cxx:187
 TGL5D.cxx:188
 TGL5D.cxx:189
 TGL5D.cxx:190
 TGL5D.cxx:191
 TGL5D.cxx:192
 TGL5D.cxx:193
 TGL5D.cxx:194
 TGL5D.cxx:195
 TGL5D.cxx:196
 TGL5D.cxx:197
 TGL5D.cxx:198
 TGL5D.cxx:199
 TGL5D.cxx:200
 TGL5D.cxx:201
 TGL5D.cxx:202
 TGL5D.cxx:203
 TGL5D.cxx:204
 TGL5D.cxx:205
 TGL5D.cxx:206
 TGL5D.cxx:207
 TGL5D.cxx:208
 TGL5D.cxx:209
 TGL5D.cxx:210
 TGL5D.cxx:211
 TGL5D.cxx:212
 TGL5D.cxx:213
 TGL5D.cxx:214
 TGL5D.cxx:215
 TGL5D.cxx:216
 TGL5D.cxx:217
 TGL5D.cxx:218
 TGL5D.cxx:219
 TGL5D.cxx:220
 TGL5D.cxx:221
 TGL5D.cxx:222
 TGL5D.cxx:223
 TGL5D.cxx:224
 TGL5D.cxx:225
 TGL5D.cxx:226
 TGL5D.cxx:227
 TGL5D.cxx:228
 TGL5D.cxx:229
 TGL5D.cxx:230
 TGL5D.cxx:231
 TGL5D.cxx:232
 TGL5D.cxx:233
 TGL5D.cxx:234
 TGL5D.cxx:235
 TGL5D.cxx:236
 TGL5D.cxx:237
 TGL5D.cxx:238
 TGL5D.cxx:239
 TGL5D.cxx:240
 TGL5D.cxx:241
 TGL5D.cxx:242
 TGL5D.cxx:243
 TGL5D.cxx:244
 TGL5D.cxx:245
 TGL5D.cxx:246
 TGL5D.cxx:247
 TGL5D.cxx:248
 TGL5D.cxx:249
 TGL5D.cxx:250
 TGL5D.cxx:251
 TGL5D.cxx:252
 TGL5D.cxx:253
 TGL5D.cxx:254
 TGL5D.cxx:255