TParallelCoordVar.cxx

Go to the documentation of this file.
00001 // @(#)root/treeviewer:$Id: TParallelCoordVar.cxx 35768 2010-09-27 08:06:29Z couet $
00002 // Author: Bastien Dalla Piazza  02/08/2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TParallelCoordVar.h"
00013 #include "TParallelCoord.h"
00014 #include "TParallelCoordRange.h"
00015 
00016 #include "Riostream.h"
00017 #include "TROOT.h"
00018 #include "TLatex.h"
00019 #include "TLine.h"
00020 #include "TVirtualPad.h"
00021 #include "TMath.h"
00022 #include "TH1.h"
00023 #include "TStyle.h"
00024 #include "TBox.h"
00025 #include "TCollection.h"
00026 #include "TList.h"
00027 #include "TFrame.h"
00028 #include "TCanvas.h"
00029 #include "TMarker.h"
00030 
00031 ClassImp(TParallelCoordVar)
00032 
00033 //______________________________________________________________________________
00034 /* Begin_Html
00035 <center><h2>Axes:</h2></center>
00036 <p>
00037 Class containing a variable for the TParallelCoord.
00038 <p>
00039 Options can be defined each axis separatly using the right mouse click. These options can be applied to every axes using the editor.
00040 <ul>
00041 <li>Axis width: If set to 0, the axis is simply a line. If higher, a color histogram is drawn on the axis.</li>
00042 <li>Axis histogram height: If not 0, a usual bar histogram is drawn on the plot.</li>
00043 </ul>
00044 <p>
00045 The order in which the variables are drawn is essential to see the clusters. The axes can be dragged to change their position. A zoom is also available. The logarithm scale is also available by right clicking on the axis.
00046 End_Html
00047 */
00048 
00049 //______________________________________________________________________________
00050 TParallelCoordVar::TParallelCoordVar()
00051    :TNamed(), TAttLine(), TAttFill(kOrange+9,0)
00052 {
00053    // Default constructor.
00054 
00055    Init();
00056 }
00057 
00058 
00059 //______________________________________________________________________________
00060 TParallelCoordVar::~TParallelCoordVar()
00061 {
00062    //Destructor.
00063 
00064    if (fHistogram) delete fHistogram;
00065    if (fRanges){
00066       TIter next(fRanges);
00067       TParallelCoordRange* range;
00068       while((range = (TParallelCoordRange*)next())) fParallel->CleanUpSelections(range);
00069       fRanges->Delete();
00070       delete fRanges;
00071    }
00072    if (fVal) delete [] fVal;
00073 }
00074 
00075 
00076 //______________________________________________________________________________
00077 TParallelCoordVar::TParallelCoordVar(Double_t *val, const char* title, Int_t id, TParallelCoord* parallel)
00078    :TNamed(title,title), TAttLine(1,1,1), TAttFill(kOrange+9,3001)
00079 {
00080    // Normal constructor. By default, the title and the name are the expression given to TTree::Draw. The name
00081    // can be changed by the user (the label on the plot) but not the title.
00082 
00083    Init();
00084    fId = id;
00085    fParallel      = parallel;
00086    fRanges        = new TList();
00087    fNentries       = fParallel->GetNentries();
00088 
00089    fVal = new Double_t[fParallel->GetNentries()];
00090 
00091    for(Long64_t ui = 0;ui<fParallel->GetNentries();++ui) fVal[ui]=val[ui];
00092 
00093    GetMinMaxMean();
00094    GetHistogram();
00095    GetQuantiles();
00096 }
00097 
00098 
00099 //______________________________________________________________________________
00100 void TParallelCoordVar::AddRange(TParallelCoordRange* range)
00101 {
00102    // Add a range to the current selection on the axis.
00103 
00104    if (!range) {
00105       TParallelCoordSelect *select = fParallel->GetCurrentSelection();
00106       if (select) {
00107          range = new TParallelCoordRange(this,0,0,select);
00108          fRanges->Add(range);
00109          range->GetSelection()->Add(range);
00110          range->Draw();
00111       } else {
00112          Error("AddRange","You must create a selection before adding ranges.");
00113       }
00114    } else {
00115       fRanges->Add(range);
00116       range->GetSelection()->Add(range);
00117       range->Draw();
00118    }
00119 }
00120 
00121 
00122 //______________________________________________________________________________
00123 void TParallelCoordVar::DeleteVariable()
00124 {
00125    // Delete variables.
00126 
00127    fParallel->RemoveVariable(this);
00128    delete this;
00129 }
00130 
00131 
00132 //______________________________________________________________________________
00133 Int_t TParallelCoordVar::DistancetoPrimitive(Int_t px, Int_t py)
00134 {
00135    // Computes the distance from the axis.
00136 
00137    if(!gPad) return 9999;
00138    Double_t xx = gPad->AbsPixeltoX(px);
00139    Double_t yy = gPad->AbsPixeltoY(py);
00140    Double_t dist = 9999;
00141 
00142    if (fX1==fX2) {
00143       if (yy>fY1+0.01 && yy<fY2-0.01) dist = TMath::Abs(xx - fX1);
00144    } else {
00145       if (xx>fX1+0.01 && xx<fX2-0.01) dist = TMath::Abs(yy - fY1);
00146    }
00147    if (dist<=0.005) return 0;
00148    else             return 9999;
00149 }
00150 
00151 
00152 //______________________________________________________________________________
00153 void TParallelCoordVar::Draw(Option_t *option)
00154 {
00155    // Draw the axis.
00156 
00157    TIter next(fRanges);
00158    TParallelCoordRange* range;
00159    while ((range = (TParallelCoordRange*)next())) range->Draw();
00160    AppendPad(option);
00161 }
00162 
00163 
00164 //______________________________________________________________________________
00165 Bool_t TParallelCoordVar::Eval(Long64_t evtidx, TParallelCoordSelect *select)
00166 {
00167    // Check if the entry is within the range(s) of "select". Two ranges on a single
00168    // axis are conjugated as a "or": to be selected, the entry must be in one of
00169    // the ranges.
00170 
00171    if (fRanges->GetSize() > 0){
00172       TIter next(fRanges);
00173       Bool_t inarange = kFALSE;
00174       Bool_t noOwnedRange = kTRUE;
00175       TParallelCoordRange *range;
00176       while ((range = (TParallelCoordRange*)next())){
00177          if(select->Contains(range)) {
00178             noOwnedRange = kFALSE;
00179             if(range->IsIn(fVal[evtidx])) inarange = kTRUE;
00180          }
00181       }
00182       if (noOwnedRange) return kTRUE;
00183       else return inarange;
00184    }
00185    else return kTRUE;
00186 }
00187 
00188 
00189 //______________________________________________________________________________
00190 void TParallelCoordVar::ExecuteEvent(Int_t entry, Int_t px, Int_t py)
00191 {
00192    // Execute the corresponding entry.
00193 
00194    if (!gPad) return;
00195    if (!gPad->IsEditable() && entry!=kMouseEnter) return;
00196 
00197    static Int_t pxold, pyold;
00198    static Int_t zoom; // -1:nothing zoomed or translated, 0:translating the axis, 1:zooming
00199    static Int_t pzoomold;
00200    static Bool_t first = kTRUE;
00201 
00202    Int_t px1,px2,py1,py2,n=-1;
00203    px1 = gPad->XtoAbsPixel(fX1);
00204    px2 = gPad->XtoAbsPixel(fX2);
00205    py1 = gPad->YtoAbsPixel(fY1);
00206    py2 = gPad->YtoAbsPixel(fY2);
00207 
00208    if(fX1 == fX2) {
00209       if(gPad->AbsPixeltoX(px)-fX1 > 0) gPad->SetCursor(kArrowVer);
00210       else                              gPad->SetCursor(kArrowHor);
00211    } else {
00212       if(gPad->AbsPixeltoY(py)-fY1 > 0) gPad->SetCursor(kArrowHor);
00213       else                              gPad->SetCursor(kArrowVer);
00214    }
00215 
00216    gVirtualX->SetLineColor(-1);
00217    switch (entry) {
00218       case kButton1Down:
00219          if (fX1==fX2){
00220             ((TCanvas*)gPad)->Selected(gPad,fParallel,1);
00221             if(gPad->AbsPixeltoX(px)-fX1 > 0){
00222                zoom = 1;
00223                gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),py,gPad->XtoAbsPixel(fX1+0.05),py);
00224                first = kTRUE;
00225                pzoomold = py;
00226             } else {
00227                zoom = 0;
00228                gVirtualX->DrawLine(px,py1,px,py2);
00229             }
00230          } else {
00231             if(gPad->AbsPixeltoY(py)-fY1 > 0){
00232                zoom = 1;
00233                gVirtualX->DrawLine(px,gPad->YtoAbsPixel(fY1-0.05),px,gPad->YtoAbsPixel(fY1+0.05));
00234                first=kTRUE;
00235                pzoomold = px;
00236             } else {
00237                zoom = 0;
00238                gVirtualX->DrawLine(px1,py,px2,py);
00239             }
00240          }
00241          pxold = px;
00242          pyold = py;
00243          break;
00244       case kButton1Up: {
00245          Double_t xx = gPad->AbsPixeltoX(px);
00246          Double_t yy = gPad->AbsPixeltoY(py);
00247          TFrame *frame = gPad->GetFrame();
00248          if (fX1==fX2) {
00249             if(zoom == 0){
00250                Double_t axisSpace = (frame->GetX2() - frame->GetX1())/(fParallel->GetNvar() - 1);
00251                Double_t pos = (xx - frame->GetX1())/axisSpace;
00252                if (pos < 0) n = -1;
00253                else         n = (Int_t)pos;
00254             } else {
00255                Double_t min = GetValuefromXY(xx,yy);
00256                Double_t max = GetValuefromXY(xx,gPad->AbsPixeltoY(pzoomold));
00257                if(TMath::Abs(min-max) < 0.00001) return;       // Avoid zooming if the axis is just clicked.
00258                if (fParallel->TestBit(TParallelCoord::kGlobalScale)) {
00259                   if (min>max) {
00260                      Double_t mem = min;
00261                      min = max; max = mem;
00262                   }
00263                   fParallel->SetGlobalMin(min);
00264                   fParallel->SetGlobalMax(max);
00265                } else {
00266                   SetCurrentLimits(min,max);
00267                }
00268             }
00269          } else {
00270             if(zoom == 0) {
00271                Double_t axisSpace = (frame->GetY2() - frame->GetY1())/(fParallel->GetNvar() - 1);
00272                Double_t pos = (yy-frame->GetY1())/axisSpace;
00273                if (pos < 0) n= -1;
00274                else         n = (Int_t)pos;
00275             } else {
00276                Double_t min = GetValuefromXY(xx,yy);
00277                Double_t max = GetValuefromXY(gPad->AbsPixeltoX(pzoomold),yy);
00278                SetCurrentLimits(min,max);
00279             }
00280          }
00281          if(zoom == 0){
00282             if (n>=0 && (UInt_t)n>=fParallel->GetNvar()) --n;
00283             else if (n<fParallel->GetVarList()->IndexOf(this)) ++n;
00284             fParallel->GetVarList()->Remove(this);
00285             fParallel->GetVarList()->AddAt(this,n);
00286          }
00287          gPad->Modified();
00288          break;
00289       }
00290       case kMouseMotion:
00291          pxold=px;
00292          pyold=py;
00293          break;
00294       case kButton1Motion:
00295          if(fX1==fX2){
00296             if(zoom==0){
00297                gPad->SetCursor(kArrowHor);
00298                gVirtualX->DrawLine(pxold,py1,pxold,py2);
00299                gVirtualX->DrawLine(px,py1,px,py2);
00300             } else if(zoom==1) {
00301                gPad->SetCursor(kArrowVer);
00302                if(!first) gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),pyold,gPad->XtoAbsPixel(fX1+0.05),pyold);
00303                gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),py,gPad->XtoAbsPixel(fX1+0.05),py);
00304                first = kFALSE;
00305             }
00306          } else {
00307             if(zoom==0){
00308                gPad->SetCursor(kArrowVer);
00309                gVirtualX->DrawLine(px1,pyold,px2,pyold);
00310                gVirtualX->DrawLine(px1,py,px2,py);
00311             } else if(zoom==1){
00312                gPad->SetCursor(kArrowHor);
00313                if(!first) gVirtualX->DrawLine(pxold,gPad->YtoAbsPixel(fY1-0.05),pxold,gPad->YtoAbsPixel(fY1+0.05));
00314                gVirtualX->DrawLine(px,gPad->YtoAbsPixel(fY1-0.05),px,gPad->YtoAbsPixel(fY1+0.05));
00315                first = kFALSE;
00316             }
00317          }
00318          pxold = px;
00319          pyold = py;
00320          break;
00321    }
00322 }
00323 
00324 
00325 //______________________________________________________________________________
00326 void TParallelCoordVar::GetEntryXY(Long64_t n, Double_t & x, Double_t & y)
00327 {
00328    // Get the position of the variable on the graph for the n'th entry.
00329 
00330    if(fX1==fX2){
00331       x = fX1;
00332       if (fMinCurrent != fMaxCurrent) {
00333          if (TestBit(kLogScale)) y = fY1 + (fY2 - fY1) *
00334                                     (TMath::Log10(fVal[n]/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00335          else                    y = fY1 + (fY2 - fY1) *
00336                                     (fVal[n] - fMinCurrent) / (fMaxCurrent - fMinCurrent);
00337       } else {
00338          y = fY1 + 0.5*(fY2-fY1);
00339       }
00340    } else {
00341       y = fY1;
00342       if (fMinCurrent != fMaxCurrent) {
00343          if (TestBit(kLogScale)) x = fX1 + (fX2 - fX1) *
00344                                     (TMath::Log10(fVal[n]/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00345          else                    x = fX1 + (fX2 - fX1) *
00346                                     (fVal[n] - fMinCurrent) / (fMaxCurrent - fMinCurrent);
00347       } else {
00348          x = fX1 + 0.5*(fX2-fX1);
00349       }
00350    }
00351 }
00352 
00353 
00354 //______________________________________________________________________________
00355 Int_t TParallelCoordVar::GetEntryWeight(Long64_t evtidx)
00356 {
00357    // Get the entry weight: The weight of an entry for a given variable
00358    // is the bin content of the histogram bin the entry is going through.
00359 
00360    Int_t bin = 1 + (Int_t)((fVal[evtidx] - fMinCurrent)/((fMaxCurrent-fMinCurrent)/fNbins));
00361    return (Int_t)fHistogram->GetBinContent(bin);
00362 }
00363 
00364 
00365 //______________________________________________________________________________
00366 TH1F* TParallelCoordVar::GetHistogram()
00367 {
00368    // Create or recreate the histogram.
00369 
00370    if (fHistogram) delete fHistogram;
00371    fHistogram = NULL;
00372    fHistogram = new TH1F("hpa", "hpa", fNbins, fMinCurrent, fMaxCurrent+0.0001*(fMaxCurrent-fMinCurrent));
00373    fHistogram->SetDirectory(0);
00374    Long64_t first = fParallel->GetCurrentFirst();
00375    Long64_t nentries = fParallel->GetCurrentN();
00376    for(Long64_t li=first; li<first+nentries;++li) {
00377       if(fVal[li] >= fMinCurrent && fVal[li] <= fMaxCurrent) fHistogram->Fill(fVal[li]);
00378    }
00379    return fHistogram;
00380 }
00381 
00382 
00383 //______________________________________________________________________________
00384 void TParallelCoordVar::GetMinMaxMean()
00385 {
00386    //Get mean, min and max of thos variable
00387    Double_t min,max,ave = 0;
00388    min = FLT_MAX;
00389    max = -FLT_MAX;
00390    Long64_t first,nentries;
00391    first = fParallel->GetCurrentFirst();
00392    nentries = fParallel->GetCurrentN();
00393    for(Long64_t li=first; li<first+nentries;++li){
00394       if(fVal[li]<min) min = fVal[li];
00395       if(fVal[li]>max) max = fVal[li];
00396       ave+=fVal[li];
00397    }
00398 
00399    fMean = ave/((Double_t)nentries);
00400    fMinCurrent = fMinInit = min;
00401    fMaxCurrent = fMaxInit = max;
00402 }
00403 
00404 
00405 //______________________________________________________________________________
00406 char* TParallelCoordVar::GetObjectInfo(Int_t px, Int_t py) const
00407 {
00408    // Returns info about this axis.
00409 
00410    static char info[128];
00411    info[0] = 0;
00412 
00413    if (!gPad) return info;
00414    Double_t xx = gPad->AbsPixeltoX(px);
00415    Double_t yy = gPad->AbsPixeltoY(py);
00416    if (fX1 == fX2) {
00417       if (yy<fY1) {
00418          snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent);
00419       } else if (yy>fY2) {
00420          snprintf(info,128,"%s = %f", GetTitle(), fMaxCurrent);
00421       } else {
00422          Double_t axislength = fY2-fY1;
00423          Double_t pos = (yy-fY1)/axislength;
00424          snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent + pos*(fMaxCurrent-fMinCurrent));
00425       }
00426    } else {
00427       if (xx<fX1) {
00428          snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent);
00429       } else if(xx>fX2) {
00430          snprintf(info,128,"%s = %f", GetTitle(), fMaxCurrent);
00431       } else {
00432          Double_t axislength = fX2-fX1;
00433          Double_t pos = (xx-fX1)/axislength;
00434          snprintf(info,128,"%s = %f", GetTitle(), pos*(fMaxCurrent-fMinCurrent));
00435       }
00436    }
00437    return info;
00438 }
00439 
00440 
00441 //______________________________________________________________________________
00442 void TParallelCoordVar::GetQuantiles()
00443 {
00444    // Get the box plot values (quantiles).
00445 
00446    Double_t *quantiles = new Double_t[3];
00447    Double_t *prob = new Double_t[3];
00448    prob[0]=0.25; prob[1]=0.5; prob[2] = 0.75;
00449    Long64_t first = fParallel->GetCurrentFirst();
00450    Long64_t nentries = fParallel->GetCurrentN();
00451    if (!TestBit(kLogScale) && first==0 && nentries==fNentries) TMath::Quantiles(fNentries,3,fVal,quantiles,prob,kFALSE);
00452    else {
00453       Double_t* val = new Double_t[nentries];
00454       Int_t selected = 0;
00455       if(fMinInit<=0) {
00456          for (Long64_t n=first;n<first+nentries;++n) {
00457             if (fVal[n] >= fMinCurrent) {
00458                if (TestBit(kLogScale)) val[selected] = TMath::Log10(fVal[n]);
00459                else                    val[selected] = fVal[n];
00460                ++selected;
00461             }
00462          }
00463       } else {
00464          for (Long64_t n=first;n<first+nentries;++n) {
00465             if (TestBit(kLogScale)) val[selected] = TMath::Log10(fVal[n]);
00466             else                    val[selected] = fVal[n];
00467             ++selected;
00468          }
00469       }
00470       TMath::Quantiles(selected,3,val,quantiles,prob,kFALSE);
00471       delete [] val;
00472    }
00473    fQua1 = quantiles[0];
00474    fMed = quantiles[1];
00475    fQua3 = quantiles[2];
00476    delete [] quantiles;
00477    delete [] prob;
00478 }
00479 
00480 
00481 //______________________________________________________________________________
00482 Double_t TParallelCoordVar::GetValuefromXY(Double_t x,Double_t y)
00483 {
00484    // Get the value corresponding to the posiiton.
00485 
00486    Double_t pos;
00487    if (fMinCurrent == fMaxCurrent) return fMinCurrent;
00488    if (fX1 == fX2) {
00489       if (y<=fY1)      pos = fMinCurrent;
00490       else if (y>=fY2) pos = fMaxCurrent;
00491       else             pos = fMinCurrent + ((y-fY1)/(fY2-fY1))*(fMaxCurrent-fMinCurrent);
00492    } else {
00493       if (x<=fX1)      pos = fMinCurrent;
00494       else if (x>=fX2) pos = fMaxCurrent;
00495       else             pos = fMinCurrent + ((x-fX1)/(fX2-fX1))*(fMaxCurrent-fMinCurrent);
00496    }
00497    return pos;
00498 }
00499 
00500 
00501 //______________________________________________________________________________
00502 void TParallelCoordVar::GetXYfromValue(Double_t value, Double_t & x, Double_t & y)
00503 {
00504    // Get a position corresponding to the value on the axis.
00505 
00506    if(value < fMinCurrent || value > fMaxCurrent) return;
00507 
00508    if (fX1==fX2) {
00509       x = fX1;
00510       if (fMinCurrent != fMaxCurrent) {
00511          if (TestBit(kLogScale)) y = fY1 + (fY2 - fY1) *
00512                                     (TMath::Log10(value/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00513          else                    y = fY1 + (fY2 - fY1) *
00514                                     (value - fMinCurrent) / (fMaxCurrent - fMinCurrent);
00515       } else {
00516          y = fY1 + 0.5*(fY2-fY1);
00517       }
00518    } else {
00519       y = fY1;
00520       if (fMinCurrent != fMaxCurrent) {
00521          if (TestBit(kLogScale)) x = fX1 + (fX2 - fX1) *
00522                                     (TMath::Log10(value/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00523          else                    x = fX1 + (fX2 - fX1) *
00524                                     (value - fMinCurrent) / (fMaxCurrent - fMinCurrent);
00525       } else {
00526          x = fX1 + 0.5*(fX2-fX1);
00527       }
00528    }
00529 }
00530 
00531 
00532 //______________________________________________________________________________
00533 void TParallelCoordVar::Init()
00534 {
00535    // Initialise the TParallelVar variables.
00536 
00537    fX1         = 0;
00538    fX2         = 0;
00539    fY1         = 0;
00540    fY2         = 0;
00541    fId         = 0;
00542    fVal        = NULL;
00543    fMean       = 0;
00544    fMinInit    = 0;
00545    fMinCurrent = 0;
00546    fMaxInit    = 0;
00547    fMaxCurrent = 0;
00548    fMed        = 0;
00549    fQua1       = 0;
00550    fQua3       = 0;
00551    fNentries   = 0;
00552    fParallel   = NULL;
00553    fHistogram  = NULL;
00554    fNbins      = 100;
00555    fHistoLW    = 2;
00556    fHistoHeight     = 0.5;
00557    fRanges     = NULL;
00558    SetBit(kLogScale,kFALSE);
00559    SetBit(kShowBox,kFALSE);
00560    SetBit(kShowBarHisto,kTRUE);
00561 }
00562 
00563 
00564 //______________________________________________________________________________
00565 void TParallelCoordVar::Paint(Option_t* /*option*/)
00566 {
00567    // Paint the axis.
00568 
00569    PaintHistogram();
00570    if (TestBit(kShowBox)) PaintBoxPlot();
00571    PaintLabels();
00572 }
00573 
00574 
00575 //______________________________________________________________________________
00576 void TParallelCoordVar::PaintBoxPlot()
00577 {
00578    // Paint the boxes in the case of a candle chart.
00579 
00580    TLine *line = new TLine();
00581    line->SetLineColor(GetLineColor());
00582    line->SetLineWidth(1);
00583    TBox *box = new TBox();
00584    box->SetLineWidth(1);
00585    box->SetLineColor(GetLineColor());
00586    box->SetLineStyle(1);
00587    box->SetFillStyle(0);
00588 
00589    TFrame* frame = gPad->GetFrame();
00590 
00591    Double_t boxSize;
00592    if (fParallel->GetNvar() > 1) {
00593       if (fX1==fX2) boxSize = fHistoHeight*((frame->GetY2()-frame->GetY1())/(fParallel->GetNvar()-1));
00594       else          boxSize = fHistoHeight*((frame->GetX2()-frame->GetX1())/(fParallel->GetNvar()-1));
00595       if (boxSize >= 0.03) boxSize = 0.03;
00596    }
00597    else boxSize = 0.03;
00598 
00599    Double_t qua1,med,qua3,max,min;
00600    Double_t a,b,maxinit,mininit;
00601    if (TestBit(kLogScale)) {
00602       a = TMath::Log10(fMinCurrent);
00603       b = TMath::Log10(fMaxCurrent/fMinCurrent);
00604       if(fMinInit > 0) mininit = TMath::Log10(fMinInit);
00605       else             mininit = TMath::Log10(fMinCurrent);
00606       maxinit = TMath::Log10(fMaxInit);
00607    } else {
00608       a = fMinCurrent;
00609       b = fMaxCurrent-fMinCurrent;
00610       mininit = fMinInit;
00611       maxinit = fMaxInit;
00612    }
00613    if(fX1==fX2) {
00614       qua1 = fY1 + ((fQua1-a)/b)*(fY2-fY1);
00615       qua3 = fY1 + ((fQua3-a)/b)*(fY2-fY1);
00616       med  = fY1 + ((fMed-a)/b)*(fY2-fY1);
00617       max  = fY1 + ((maxinit-a)/b)*(fY2-fY1);
00618       min  = fY1 + ((mininit-a)/b)*(fY2-fY1);
00619    } else {
00620       qua1 = fX1 + ((fQua1-a)/b)*(fX2-fX1);
00621       qua3 = fX1 + ((fQua3-a)/b)*(fX2-fX1);
00622       med  = fX1 + ((fMed-a)/b)*(fX2-fX1);
00623       max  = fX1 + ((maxinit-a)/b)*(fX2-fX1);
00624       min  = fX1 + ((mininit-a)/b)*(fX2-fX1);
00625    }
00626 
00627    // min and max lines.
00628    if (fX1==fX2) {
00629       line->PaintLine(fX1-boxSize,min,fX1+boxSize,min);
00630       line->PaintLine(fX2-boxSize,max,fX2+boxSize,max);
00631    } else {
00632       line->PaintLine(min,fY1-boxSize,min,fY1+boxSize);
00633       line->PaintLine(max,fY2-boxSize,max,fY2+boxSize);
00634    }
00635 
00636    // lines from min and max to the box.
00637    line->SetLineStyle(7);
00638    if (fX1==fX2) {
00639       if (min<frame->GetY1()) min = frame->GetY1();
00640       if (max>frame->GetY2()) max = frame->GetY2();
00641       line->PaintLine(fX1,min,fX1,qua1);
00642       line->PaintLine(fX1,qua3,fX1,max);
00643    } else {
00644       if (min<frame->GetX1()) min = frame->GetX1();
00645       if (max>frame->GetX2()) max = frame->GetX2();
00646       line->PaintLine(min,fY1,qua1,fY2);
00647       line->PaintLine(qua3,fY1,max,fY2);
00648    }
00649 
00650    // Box
00651    if(fX1==fX2) box->PaintBox(fX1-boxSize,qua1,fX1+boxSize,qua3);
00652    else box->PaintBox(qua1,fY1-boxSize,qua3,fY1+boxSize);
00653 
00654    // Median line
00655    line->SetLineStyle(1);
00656    if(fX1==fX2) line->PaintLine(fX1-boxSize,med,fX1+boxSize,med);
00657    else line->PaintLine(med,fY1-boxSize,med,fY1+boxSize);
00658 
00659    // Paint average
00660    if (!TestBit(kLogScale) || (TestBit(kLogScale) && fMean > 0)) {
00661       Double_t mean;
00662       if (TestBit(kLogScale)) mean = TMath::Log10(fMean);
00663       else mean = fMean;
00664       TMarker *mark = NULL;
00665       if(fX1==fX2) mark = new TMarker(fX1,fY1 + ((mean-a)/b)*(fY2-fY1),24);
00666       else         mark = new TMarker(fX1 + ((mean-a)/b)*(fX2-fX1),fY1,24);
00667       mark->Paint();
00668       delete mark;
00669    }
00670 
00671    delete line;
00672    delete box;
00673 }
00674 
00675 
00676 //______________________________________________________________________________
00677 void TParallelCoordVar::PaintHistogram()
00678 {
00679    // Paint the histogram on the axis.
00680 
00681    Int_t i;
00682 
00683    TFrame *frame = gPad->GetFrame();
00684 
00685    if (!fHistogram) GetHistogram();
00686 
00687    // Paint the axis body.
00688    if (fHistoHeight!=0 && TestBit(kShowBarHisto)) {
00689       // Paint the axis body using bar chart.
00690       TBox *b = new TBox();
00691       b->SetFillStyle(GetFillStyle());
00692       b->SetFillColor(GetFillColor());
00693       b->SetLineStyle(1);
00694       b->SetLineColor(GetFillColor());
00695       b->SetLineWidth(1);
00696       Double_t hmin = fHistogram->GetMinimum();
00697       Double_t hmax = fHistogram->GetMaximum();
00698       if (fX1 == fX2) {
00699          // Vertical case.
00700          Double_t dy = (fY2-fY1)/fNbins;
00701          Double_t dv = (fMaxCurrent - fMinCurrent)/fNbins;
00702          Double_t v = fMinCurrent;
00703          Double_t y1 = fY1,x2,y2;
00704          for (i=1; i<=fNbins; i++) {
00705             x2 = fX1+((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*fHistoHeight*
00706                  ((frame->GetX2()-frame->GetX1())/(fParallel->GetNvar()-1));
00707             if(TestBit(kLogScale)) y2 = fY1 + (fY2-fY1)*(TMath::Log10((v+dv)/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00708             else y2=y1+dy;
00709             b->PaintBox(fX1,y1,x2,y2,"l");
00710             y1=y2;
00711             v += dv;
00712          }
00713       } else {
00714          // Horizontal case.
00715          Double_t dx = (fX2-fX1)/fNbins;
00716          Double_t dv = (fMaxCurrent - fMinCurrent)/fNbins;
00717          Double_t v = fMinCurrent;
00718          Double_t x1 = fX1,x2,y2;
00719          for (i=1; i<=fNbins; i++) {
00720             y2 = fY1+((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*fHistoHeight*((frame->GetY2()-frame->GetY1())/(fParallel->GetNvar()-1));
00721             if(TestBit(kLogScale)) x2 = fX1 + (fX2-fX1)*(TMath::Log10((v+dv)/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00722             else x2=x1+dx;
00723             b->PaintBox(x1,fY1,x2,y2,"l");
00724             x1=x2;
00725             v+=dv;
00726          }
00727       }
00728       delete b;
00729    }
00730    if (fHistoLW==0 && !TestBit(kShowBox)) {
00731       // Paint the axis body as a simple line.
00732       TLine* l = new TLine(fX1,fY1,fX2,fY2);
00733       l->SetLineWidth(GetLineWidth());
00734       l->SetLineColor(GetLineColor());
00735       l->SetLineStyle(GetLineColor());
00736       l->Paint();
00737       delete l;
00738    } else if (fHistoLW!=0){
00739       // Paint the axis body using the color palette.
00740       TLine *lb = new TLine();
00741       lb->SetLineWidth(fHistoLW);
00742       Double_t hmin = fHistogram->GetMinimum();
00743       Double_t hmax = fHistogram->GetMaximum();
00744       Int_t theColor;
00745       Int_t ncolors = gStyle->GetNumberOfColors();
00746       if (fX1 == fX2) {
00747          // Vertical case.
00748          Double_t dy = (fY2-fY1)/fNbins;
00749          Double_t y1 = fY1,y2;
00750          Double_t dv = (fMaxCurrent - fMinCurrent)/fNbins;
00751          Double_t v = fMinCurrent;
00752          for (i=1; i<=fNbins; i++) {
00753             theColor = (Int_t)( ((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*(ncolors-1) );
00754             if(TestBit(kLogScale)) y2 = fY1 + (fY2-fY1)*(TMath::Log10((v+dv)/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00755             else y2=y1+dy;
00756             lb->SetLineColor(gStyle->GetColorPalette(theColor));
00757             lb->PaintLine(fX1,y1,fX1,y2);
00758             y1=y2;
00759             v+=dv;
00760          }
00761       } else {
00762          // Horizontal case.
00763          Double_t dx = (fX2-fX1)/fNbins;
00764          Double_t dv = (fMaxCurrent - fMinCurrent)/fNbins;
00765          Double_t v = fMinCurrent;
00766          Double_t x1 = fX1,x2;
00767          for (i=1; i<=fNbins; i++) {
00768             theColor = (Int_t)( ((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*(ncolors-1) );
00769             lb->SetLineColor(gStyle->GetColorPalette(theColor));
00770             if(TestBit(kLogScale)) x2 = fX1 + (fX2-fX1)*(TMath::Log10((v+dv)/fMinCurrent)) / (TMath::Log10(fMaxCurrent/fMinCurrent));
00771             else x2=x1+dx;
00772             lb->PaintLine(x1,fY1,x2,fY1);
00773             x1=x2;
00774             v+=dv;
00775          }
00776       }
00777       delete lb;
00778    }
00779 }
00780 
00781 
00782 //______________________________________________________________________________
00783 void TParallelCoordVar::PaintLabels()
00784 {
00785    // Paint the axis labels and titles.
00786 
00787    TLatex* t = new TLatex();
00788    TFrame *frame = gPad->GetFrame();
00789    t->SetTextSize(0.03);
00790    if (fX1==fX2) {
00791       t->SetText(fX1,frame->GetY1() - 0.04 - t->GetTextSize(),GetName());
00792       Double_t tlength = t->GetXsize();
00793       if (fX1-0.5*tlength<0.01) {
00794          t->SetTextAlign(11);
00795          t->SetText(0.01, frame->GetY1() - 0.04 - t->GetTextSize(), GetName());
00796          t->Paint();
00797       } else if (fX1+0.5*tlength > 0.99) {
00798          t->SetTextAlign(31);
00799          t->SetText(0.99,frame->GetY1() - 0.04 - t->GetTextSize(),GetName());
00800          t->Paint();
00801       } else {
00802          t->SetTextAlign(21);
00803          t->PaintLatex(fX1,frame->GetY1() - 0.04 - t->GetTextSize(),0,0.03,GetName());
00804       }
00805       if (!fParallel->TestBit(TParallelCoord::kCandleChart)) {
00806          t->SetTextAlign(21);
00807          t->PaintLatex(fX1,frame->GetY2() + 0.005,0,0.025,Form("%6.4f",fMaxCurrent));
00808          t->SetTextAlign(23);
00809          t->PaintLatex(fX1,frame->GetY1() - 0.005,0,0.025,Form("%6.4f",fMinCurrent));
00810       }
00811    } else {
00812       t->SetText(fX1-0.04,fY1+0.02,GetName());
00813       t->SetTextSize(0.03);
00814       Double_t tlength = t->GetXsize();
00815       if (fX1-0.04-tlength<0.01) {
00816          t->SetTextAlign(12);
00817          t->SetText(0.01,fY1+0.02,GetName());
00818          t->Paint();
00819       } else {
00820          t->SetTextAlign(32);
00821          t->PaintLatex(fX1-0.04,fY1+0.02,0,0.03,GetName());
00822       }
00823       if (!fParallel->TestBit(TParallelCoord::kCandleChart)) {
00824          t->SetTextAlign(12);
00825          t->PaintLatex(0.01,fY1-0.02,0,0.025,Form("%6.4f",fMinCurrent));
00826          t->SetTextAlign(32);
00827          t->PaintLatex(0.99,fY1-0.02,0,0.025,Form("%6.4f",fMaxCurrent));
00828       }
00829    }
00830    delete t;
00831 }
00832 
00833 
00834 //______________________________________________________________________________
00835 void TParallelCoordVar::Print(Option_t* /*option*/) const
00836 {
00837    // Print the axis main datas.
00838 
00839    printf("**************variable #%d**************\n",fParallel->GetVarList()->IndexOf(this));
00840    printf("at x1=%f, y1=%f, x2=%f, y2=%f.\n",fX1,fY1,fX2,fY2);
00841    printf("min = %f, Q1 = %f, Med = %f, Q3 = %f, Max = %f\n", fMinInit, fQua1, fMed, fQua3, fMaxInit);
00842 }
00843 
00844 
00845 //______________________________________________________________________________
00846 void TParallelCoordVar::SavePrimitive(ostream & out, Option_t* options)
00847 {
00848    // Save the TParallelCoordVar as a macro. Can be used only in the context
00849    // of TParallelCoord::SavePrimitive (pointer "TParallelCoord* para" is
00850    // defined in TParallelCoord::SavePrimitive) with the option "pcalled".
00851 
00852    TString opt = options;
00853    if (opt.Contains("pcalled")) {
00854       out<<"   var->SetBit(TParallelCoordVar::kLogScale,"<<TestBit(kLogScale)<<");"<<endl;
00855       out<<"   var->SetBit(TParallelCoordVar::kShowBox,"<<TestBit(kShowBox)<<");"<<endl;
00856       out<<"   var->SetBit(TParallelCoordVar::kShowBarHisto,"<<TestBit(kShowBarHisto)<<");"<<endl;
00857       out<<"   var->SetHistogramBinning("<<fNbins<<");"<<endl;
00858       out<<"   var->SetHistogramLineWidth("<<fHistoLW<<");"<<endl;
00859       out<<"   var->SetInitMin("<<fMinInit<<");"<<endl;
00860       out<<"   var->SetInitMax("<<fMaxInit<<");"<<endl;
00861       out<<"   var->SetHistogramHeight("<<fHistoHeight<<");"<<endl;
00862       out<<"   var->GetMinMaxMean();"<<endl;
00863       out<<"   var->GetHistogram();"<<endl;
00864       out<<"   var->SetFillStyle("<<GetFillStyle()<<");"<<endl;
00865       out<<"   var->SetFillColor("<<GetFillColor()<<");"<<endl;
00866       out<<"   var->SetLineColor("<<GetLineColor()<<");"<<endl;
00867       out<<"   var->SetLineWidth("<<GetLineWidth()<<");"<<endl;
00868       out<<"   var->SetLineStyle("<<GetLineStyle()<<");"<<endl;
00869       if (TestBit(kShowBox)) out<<"   var->GetQuantiles();"<<endl;
00870       TIter next(fRanges);
00871       TParallelCoordRange* range;
00872       Int_t i = 1;
00873       while ((range = (TParallelCoordRange*)next())) {
00874          out<<"   //***************************************"<<endl;
00875          out<<"   // Create the "<<i<<"th range owned by the axis \""<<GetTitle()<<"\"."<<endl;
00876          out<<"   TParallelCoordSelect* sel = para->GetSelection(\""<<range->GetSelection()->GetTitle()<<"\");"<<endl;
00877          out<<"   TParallelCoordRange* newrange = new TParallelCoordRange(var,"<<range->GetMin()<<","<<range->GetMax()<<",sel);"<<endl;
00878          out<<"   var->AddRange(newrange);"<<endl;
00879          out<<"   sel->Add(newrange);"<<endl;
00880          ++i;
00881       }
00882    }
00883 }
00884 
00885 
00886 //______________________________________________________________________________
00887 void TParallelCoordVar::SetBoxPlot(Bool_t box)
00888 {
00889    // Set the axis to display a candle.
00890 
00891    SetBit(kShowBox,box);
00892    if (box) SetHistogramHeight(0.5);
00893    else {
00894       SetHistogramHeight(0);
00895       SetHistogramLineWidth(2);
00896    }
00897 }
00898 
00899 
00900 //______________________________________________________________________________
00901 void TParallelCoordVar::SetHistogramBinning(Int_t n)
00902 {
00903    // Set the histogram binning.
00904 
00905    if (n < 0 || n == fNbins) return;
00906    fNbins = n;
00907    GetHistogram();
00908 }
00909 
00910 
00911 //______________________________________________________________________________
00912 void TParallelCoordVar::SetHistogramHeight(Double_t h)
00913 {
00914    // Set the height of the bar histogram.
00915 
00916    fHistoHeight = h;
00917    if (!fParallel->TestBit(TParallelCoord::kCandleChart)){
00918       if(h!=0) SetBit(kShowBarHisto,kTRUE);
00919       else SetBit(kShowBarHisto,kFALSE);
00920    }
00921 }
00922 
00923 
00924 //______________________________________________________________________________
00925 void TParallelCoordVar::SetCurrentMin(Double_t min)
00926 {
00927    // Set the current minimum of the axis.
00928 
00929    fMinCurrent = min;
00930 }
00931 
00932 
00933 //______________________________________________________________________________
00934 void TParallelCoordVar::SetCurrentMax(Double_t max)
00935 {
00936    // Set the current maximum of the axis.
00937 
00938    fMaxCurrent = max;
00939 }
00940 
00941 
00942 //______________________________________________________________________________
00943 void TParallelCoordVar::SetCurrentLimits(Double_t min, Double_t max)
00944 {
00945    // Set the limits within which one the entries must be painted.
00946 
00947    if (min>max) {
00948       Double_t mem = min;
00949       min = max;
00950       max = mem;
00951    }
00952    if(TestBit(kLogScale) && max<=0) return;
00953    if(TestBit(kLogScale) && min<=0) min = 0.00001*max;
00954    fMinCurrent = min;
00955    fMaxCurrent = max;
00956 
00957    delete fHistogram;
00958    fHistogram = NULL;
00959    GetHistogram();
00960 
00961    if (fParallel->TestBit(TParallelCoord::kGlobalScale)) {
00962       fParallel->SetGlobalMin(min);
00963       fParallel->SetGlobalMax(max);
00964    }
00965 }
00966 
00967 
00968 //______________________________________________________________________________
00969 void TParallelCoordVar::SetLiveRangesUpdate(Bool_t on)
00970 {
00971    // If true, the pad is updated while the motion of a dragged range.
00972 
00973    TIter next(fRanges);
00974    TParallelCoordRange* range;
00975    while ((range = (TParallelCoordRange*)next())) range->SetBit(TParallelCoordRange::kLiveUpdate,on);
00976 }
00977 
00978 
00979 //______________________________________________________________________________
00980 void TParallelCoordVar::SetLogScale(Bool_t log)
00981 {
00982    // Set the axis in logscale.
00983 
00984    if (log == TestBit (kLogScale)) return;
00985    if (fMaxInit < 0)             SetBit(kLogScale,kFALSE);
00986    else if (log) {
00987       if (fMaxCurrent < 0 ) fMaxCurrent = fMaxInit;
00988       if (fMinCurrent < 0 ) fMinCurrent = 0.00001*fMaxCurrent;
00989       SetBit(kLogScale,kTRUE);
00990       SetCurrentMin(fMinCurrent);
00991       SetCurrentMax(fMaxCurrent);
00992    } else {
00993       SetBit(kLogScale,kFALSE);
00994       SetCurrentMin(fMinInit);
00995       SetCurrentMax(fMaxInit);
00996    }
00997    GetQuantiles();
00998    GetHistogram();
00999 }
01000 
01001 
01002 //______________________________________________________________________________
01003 void TParallelCoordVar::SetValues(Long64_t length, Double_t* val)
01004 {
01005    // Set the variable values.
01006 
01007    if (fVal) delete [] fVal;
01008    fVal = new Double_t[length];
01009    fNentries = length;
01010    for (Long64_t li = 0; li < length; ++li) fVal[li] = val[li];
01011    GetMinMaxMean();
01012    GetHistogram();
01013    if (TestBit(kShowBox)) GetQuantiles();
01014 }
01015 
01016 
01017 //______________________________________________________________________________
01018 void TParallelCoordVar::SetX(Double_t x, Bool_t gl)
01019 {
01020    // Set the X position of the axis in the case of a vertical axis.
01021    // and rotate the axis if it was horizontal.
01022 
01023    TFrame *frame = gPad->GetFrame();
01024    if (!gl) {
01025       fY1 = frame->GetY1();
01026       fY2 = frame->GetY2();
01027    } else {
01028       Double_t gmin = fParallel->GetGlobalMin();
01029       Double_t gmax = fParallel->GetGlobalMax();
01030       fY1 = frame->GetY1() + ((fMinCurrent-gmin)/(gmax-gmin))*(frame->GetY2()-frame->GetY1());
01031       fY2 = frame->GetY1() + ((fMaxCurrent-gmin)/(gmax-gmin))*(frame->GetY2()-frame->GetY1());
01032    }
01033    fX1 = fX2 = x;
01034 }
01035 
01036 
01037 //______________________________________________________________________________
01038 void TParallelCoordVar::SetY(Double_t y, Bool_t gl)
01039 {
01040    // Set the Y position of the axis in the case of a horizontal axis.
01041    // and rotate the axis if it was vertical.
01042 
01043    TFrame *frame = gPad->GetFrame();
01044    if (!gl) {
01045       fX1 = frame->GetX1();
01046       fX2 = frame->GetX2();
01047    } else {
01048       Double_t gmin = fParallel->GetGlobalMin();
01049       Double_t gmax = fParallel->GetGlobalMax();
01050       fX1 = frame->GetX1() + ((fMinCurrent-gmin)/(gmax-gmin))*(frame->GetX2()-frame->GetX1());
01051       fX2 = frame->GetX1() + ((fMaxCurrent-gmin)/(gmax-gmin))*(frame->GetX2()-frame->GetX1());
01052    }
01053    fY1 = fY2 = y;
01054 }

Generated on Tue Jul 5 15:43:45 2011 for ROOT_528-00b_version by  doxygen 1.5.1