#include "TEveCalo.h"
#include "TEveCaloData.h"
#include "TEveProjections.h"
#include "TEveProjectionManager.h"
#include "TEveRGBAPalette.h"
#include "TEveText.h"
#include "TEveTrans.h"
#include "TClass.h"
#include "TMathBase.h"
#include "TMath.h"
#include "TAxis.h"
#include "TGLUtil.h"
#include <cassert>
ClassImp(TEveCaloViz);
TEveCaloViz::TEveCaloViz(TEveCaloData* data, const char* n, const char* t) :
TEveElement(),
TNamed(n, t),
TEveProjectable(),
fData(0),
fCellIdCacheOK(kFALSE),
fEtaMin(-10),
fEtaMax(10),
fPhi(0.),
fPhiOffset(TMath::Pi()),
fAutoRange(kTRUE),
fBarrelRadius(-1.f),
fEndCapPos(-1.f),
fPlotEt(kTRUE),
fMaxTowerH(100),
fScaleAbs(kFALSE),
fMaxValAbs(100),
fValueIsColor(kFALSE),
fPalette(0)
{
fPickable = kTRUE;
SetElementNameTitle(n, t);
SetData(data);
}
TEveCaloViz::~TEveCaloViz()
{
if (fPalette) fPalette->DecRefCount();
}
Float_t TEveCaloViz::GetDataSliceThreshold(Int_t slice) const
{
return fData->RefSliceInfo(slice).fThreshold;
}
TEveElement* TEveCaloViz::ForwardSelection()
{
return fData;
}
TEveElement* TEveCaloViz::ForwardEdit()
{
return this;
}
void TEveCaloViz::SetDataSliceThreshold(Int_t slice, Float_t val)
{
fData->SetSliceThreshold(slice, val);
}
Color_t TEveCaloViz::GetDataSliceColor(Int_t slice) const
{
return fData->RefSliceInfo(slice).fColor;
}
void TEveCaloViz::SetDataSliceColor(Int_t slice, Color_t col)
{
fData->SetSliceColor(slice, col);
}
void TEveCaloViz::SetEta(Float_t l, Float_t u)
{
fEtaMin=l;
fEtaMax=u;
InvalidateCellIdCache();
}
void TEveCaloViz::SetPlotEt(Bool_t isEt)
{
fPlotEt=isEt;
if (fPalette)
fPalette->SetLimits(0, TMath::CeilNint(GetMaxVal()));
InvalidateCellIdCache();
}
Float_t TEveCaloViz::GetMaxVal() const
{
return fData->GetMaxVal(fPlotEt);
}
void TEveCaloViz::SetPhiWithRng(Float_t phi, Float_t rng)
{
using namespace TMath;
fPhi = phi;
fPhiOffset = rng;
InvalidateCellIdCache();
}
Float_t TEveCaloViz::GetTransitionTheta() const
{
return TMath::ATan(fBarrelRadius/fEndCapPos);
}
Float_t TEveCaloViz::GetTransitionEta() const
{
using namespace TMath;
Float_t t = GetTransitionTheta()*0.5f;
return -Log(Tan(t));
}
void TEveCaloViz::SetData(TEveCaloData* data)
{
if (data == fData) return;
if (fData) fData->RemoveElement(this);
fData = data;
if (fData)
{
fData->AddElement(this);
DataChanged();
}
}
void TEveCaloViz::DataChanged()
{
Double_t min, max, delta;
fData->GetEtaLimits(min, max);
if (fAutoRange) {
fEtaMin = min;
fEtaMax = max;
} else {
if (fEtaMin < min) fEtaMin = min;
if (fEtaMax > max) fEtaMax = max;
}
fData->GetPhiLimits(min, max);
delta = 0.5*(max - min);
if (fAutoRange || fPhi < min || fPhi > max) {
fPhi = 0.5*(max + min);
fPhiOffset = delta;
} else {
if (fPhiOffset > delta) fPhiOffset = delta;
}
if (fPalette)
{
Int_t hlimit = TMath::CeilNint(GetMaxVal());
fPalette->SetLimits(0, hlimit);
fPalette->SetMin(0);
fPalette->SetMax(hlimit);
}
InvalidateCellIdCache();
}
Bool_t TEveCaloViz::AssertCellIdCache() const
{
TEveCaloViz* cv = const_cast<TEveCaloViz*>(this);
if (!fCellIdCacheOK) {
cv->BuildCellIdCache();
return kTRUE;
} else {
return kFALSE;
}
}
Bool_t TEveCaloViz::CellInEtaPhiRng(TEveCaloData::CellData_t& cellData) const
{
if (cellData.EtaMin() >= fEtaMin && cellData.EtaMax() <= fEtaMax)
{
if (TEveUtil::IsU1IntervalContainedByMinMax
(fPhi-fPhiOffset, fPhi+fPhiOffset, cellData.PhiMin(), cellData.PhiMax()))
return kTRUE;
}
return kFALSE;
}
void TEveCaloViz::AssignCaloVizParameters(TEveCaloViz* m)
{
SetData(m->fData);
fEtaMin = m->fEtaMin;
fEtaMax = m->fEtaMax;
fPhi = m->fPhi;
fPhiOffset = m->fPhiOffset;
fBarrelRadius = m->fBarrelRadius;
fEndCapPos = m->fEndCapPos;
if (m->fPalette)
{
TEveRGBAPalette& mp = * m->fPalette;
if (fPalette) fPalette->DecRefCount();
fPalette = new TEveRGBAPalette(mp.GetMinVal(), mp.GetMaxVal(), mp.GetInterpolate());
fPalette->SetDefaultColor(mp.GetDefaultColor());
}
}
void TEveCaloViz::SetPalette(TEveRGBAPalette* p)
{
if ( fPalette == p) return;
if (fPalette) fPalette->DecRefCount();
fPalette = p;
if (fPalette) fPalette->IncRefCount();
}
Float_t TEveCaloViz::GetValToHeight() const
{
if (fScaleAbs)
{
return fMaxTowerH/fMaxValAbs;
}
else
{
if (fData->Empty())
return 1;
return fMaxTowerH/fData->GetMaxVal(fPlotEt);
}
}
TEveRGBAPalette* TEveCaloViz::AssertPalette()
{
if (fPalette == 0) {
fPalette = new TEveRGBAPalette;
fPalette->SetDefaultColor((Color_t)4);
Int_t hlimit = TMath::CeilNint(GetMaxVal());
fPalette->SetLimits(0, hlimit);
fPalette->SetMin(0);
fPalette->SetMax(hlimit);
}
return fPalette;
}
void TEveCaloViz::Paint(Option_t* )
{
if (fData)
{
PaintStandard(this);
}
}
TClass* TEveCaloViz::ProjectedClass(const TEveProjection*) const
{
return TEveCalo2D::Class();
}
void TEveCaloViz::SetupColorHeight(Float_t value, Int_t slice, Float_t& outH) const
{
if (fValueIsColor)
{
outH = GetValToHeight()*fData->GetMaxVal(fPlotEt);
UChar_t c[4];
fPalette->ColorFromValue((Int_t)value, c);
c[3] = fData->GetSliceTransparency(slice);
TGLUtil::Color4ubv(c);
}
else
{
TGLUtil::ColorTransparency(fData->GetSliceColor(slice), fData->GetSliceTransparency(slice));
outH = GetValToHeight()*value;
}
}
ClassImp(TEveCalo3D);
TEveCalo3D::TEveCalo3D(TEveCaloData* d, const char* n, const char* t):
TEveCaloViz(d, n, t),
fRnrEndCapFrame (kTRUE),
fRnrBarrelFrame (kTRUE),
fFrameWidth (0.5),
fFrameColor (kGray+1),
fFrameTransparency (80)
{
fCanEditMainColor = kTRUE;
fCanEditMainTransparency = kTRUE;
fMainColorPtr = &fFrameColor;
}
void TEveCalo3D::BuildCellIdCache()
{
fCellList.clear();
fData->GetCellList(GetEta(), GetEtaRng(), GetPhi(), GetPhiRng(), fCellList);
fCellIdCacheOK = kTRUE;
}
void TEveCalo3D::ComputeBBox()
{
BBoxInit();
Float_t th = (fData) ? GetValToHeight() * fData->GetMaxVal(fPlotEt) : 0;
fBBox[0] = -fBarrelRadius - th;
fBBox[1] = fBarrelRadius + th;
fBBox[2] = fBBox[0];
fBBox[3] = fBBox[1];
fBBox[4] = -fEndCapPos - th;
fBBox[5] = fEndCapPos + th;
}
ClassImp(TEveCalo2D);
TEveCalo2D::TEveCalo2D(const char* n, const char* t):
TEveCaloViz(0, n, t),
TEveProjected(),
fOldProjectionType(TEveProjection::kPT_Unknown),
fMaxESumBin( 0),
fMaxEtSumBin(0)
{
}
TEveCalo2D::~TEveCalo2D()
{
TEveCaloData::vCellId_t* cids;
UInt_t n;
n = fCellListsSelected.size();
for(UInt_t i = 0; i < n; ++i) {
cids = fCellListsSelected[i];
if (cids) {
cids->clear(); delete cids;
}
}
fCellListsSelected.clear();
n = fCellLists.size();
for(UInt_t i = 0; i < n; ++i) {
cids = fCellLists[i];
if (cids) {
cids->clear(); delete cids;
}
}
fCellLists.clear();
}
void TEveCalo2D::UpdateProjection()
{
if (fManager->GetProjection()->GetType() != fOldProjectionType)
{
fCellIdCacheOK=kFALSE;
fOldProjectionType = fManager->GetProjection()->GetType();
}
ComputeBBox();
}
void TEveCalo2D::SetProjection(TEveProjectionManager* mng, TEveProjectable* model)
{
TEveProjected::SetProjection(mng, model);
TEveCaloViz* viz = dynamic_cast<TEveCaloViz*>(model);
AssignCaloVizParameters(viz);
}
void TEveCalo2D::BuildCellIdCache()
{
for (vBinCells_i it = fCellLists.begin(); it != fCellLists.end(); it++)
{
if (*it)
{
(*it)->clear();
delete *it;
}
}
fCellLists.clear();
fCellLists.push_back(0);
TEveProjection::EPType_e pt = fManager->GetProjection()->GetType();
TEveCaloData::vCellId_t* clv;
Bool_t isRPhi = (pt == TEveProjection::kPT_RPhi);
const TAxis* axis = isRPhi ? fData->GetPhiBins() : fData->GetEtaBins();
Int_t nBins = axis->GetNbins();
Float_t min, max;
if (isRPhi)
{
min = GetPhiMin() - fData->GetEps();
max = GetPhiMax() + fData->GetEps();
for (Int_t ibin = 1; ibin <= nBins; ++ibin) {
clv = 0;
if ( TEveUtil::IsU1IntervalOverlappingByMinMax
(min, max, axis->GetBinLowEdge(ibin), axis->GetBinUpEdge(ibin)))
{
clv = new TEveCaloData::vCellId_t();
fData->GetCellList(GetEta(), GetEtaRng(), axis->GetBinCenter(ibin), axis->GetBinWidth(ibin), *clv);
if (!clv->size()) {
delete clv; clv = 0;
}
}
fCellLists.push_back(clv);
}
}
else
{
min = GetEtaMin() - fData->GetEps();
max = GetEtaMax() + fData->GetEps();
for (Int_t ibin = 1; ibin <= nBins; ++ibin) {
clv = 0;
Float_t low = axis->GetBinLowEdge(ibin);
Float_t up = axis->GetBinUpEdge(ibin) ;
if (low >= min && up <= max)
{
clv = new TEveCaloData::vCellId_t();
fData->GetCellList(axis->GetBinCenter(ibin), axis->GetBinWidth(ibin), fPhi, GetPhiRng(), *clv);
if (!clv->size()) {
delete clv; clv = 0;
}
}
fCellLists.push_back(clv);
}
}
if (!fScaleAbs)
{
fMaxESumBin = 0;
fMaxEtSumBin = 0;
Float_t sumE = 0;
Float_t sumEt = 0;
TEveCaloData::CellData_t cellData;
for (Int_t ibin = 1; ibin <= nBins; ++ibin) {
TEveCaloData::vCellId_t* cids = fCellLists[ibin];
if (cids)
{
sumE = 0; sumEt = 0;
for (TEveCaloData::vCellId_i it = cids->begin(); it != cids->end(); it++)
{
fData->GetCellData(*it, cellData);
sumE += cellData.Value(kFALSE);
sumEt += cellData.Value(kTRUE);
}
fMaxESumBin = TMath::Max(fMaxESumBin, sumE);
fMaxEtSumBin = TMath::Max(fMaxEtSumBin, sumEt);
}
}
ComputeBBox();
}
fCellIdCacheOK= kTRUE;
}
void TEveCalo2D::CellSelectionChanged()
{
CellSelectionChangedInternal(fData->GetCellsSelected(), fCellListsSelected);
CellSelectionChangedInternal(fData->GetCellsHighlighted(), fCellListsHighlighted);
}
void TEveCalo2D::CellSelectionChangedInternal(TEveCaloData::vCellId_t& inputCells, std::vector<TEveCaloData::vCellId_t*>& outputCellLists)
{
Bool_t isRPhi = (fManager->GetProjection()->GetType() == TEveProjection::kPT_RPhi);
const TAxis* axis = isRPhi ? fData->GetPhiBins() : fData->GetEtaBins();
for (vBinCells_i it = outputCellLists.begin(); it != outputCellLists.end(); it++)
{
if (*it)
{
(*it)->clear();
delete *it;
}
}
outputCellLists.clear();
UInt_t nBins = axis->GetNbins();
outputCellLists.resize(nBins+1);
for (UInt_t b = 0; b <= nBins; ++b)
outputCellLists[b] = 0;
for(UInt_t bin = 1; bin <= nBins; ++bin)
{
TEveCaloData::vCellId_t* idsInBin = fCellLists[bin];
if (!idsInBin)
continue;
for (TEveCaloData::vCellId_i i = idsInBin->begin(); i != idsInBin->end(); i++)
{
for (TEveCaloData::vCellId_i j = inputCells.begin(); j != inputCells.end(); j++)
{
if( (*i).fTower == (*j).fTower && (*i).fSlice == (*j).fSlice)
{
if (!outputCellLists[bin])
outputCellLists[bin] = new TEveCaloData::vCellId_t();
outputCellLists[bin]->push_back(TEveCaloData::CellId_t((*i).fTower, (*i).fSlice, (*i).fFraction));
}
}
}
}
}
void TEveCalo2D::SetScaleAbs(Bool_t sa)
{
TEveCaloViz::SetScaleAbs(sa);
BuildCellIdCache();
}
Float_t TEveCalo2D::GetValToHeight() const
{
AssertCellIdCache();
if (fScaleAbs)
{
return fMaxTowerH/fMaxValAbs;
}
else
{
if (fData->Empty())
return 1;
if (fPlotEt)
return fMaxTowerH/fMaxEtSumBin;
else
return fMaxTowerH/fMaxESumBin;
}
}
void TEveCalo2D::ComputeBBox()
{
BBoxZero();
Float_t x, y, z;
Float_t th = fMaxTowerH ;
Float_t r = fBarrelRadius + th;
Float_t ze = fEndCapPos + th;
x = r, y = 0, z = 0;
fManager->GetProjection()->ProjectPoint(x, y, z, fDepth);
BBoxCheckPoint(x, y, z);
x = -r, y = 0, z = 0;
fManager->GetProjection()->ProjectPoint(x, y, z, fDepth);
BBoxCheckPoint(x, y, z);
x = 0, y = 0, z = ze;
fManager->GetProjection()->ProjectPoint(x, y, z, fDepth);
BBoxCheckPoint(x, y, z);
x = 0, y = 0, z = -ze;
fManager->GetProjection()->ProjectPoint(x, y, z, fDepth);
BBoxCheckPoint(x, y, z);
x = 0, y = r, z = 0;
fManager->GetProjection()->ProjectPoint(x, y, z, fDepth);
BBoxCheckPoint(x, y, z);
x = 0, y = -r, z = 0;
fManager->GetProjection()->ProjectPoint(x, y, z, fDepth);
BBoxCheckPoint(x, y, z);
}
ClassImp(TEveCaloLego);
TEveCaloLego::TEveCaloLego(TEveCaloData* d, const char* n, const char* t):
TEveCaloViz(d, n, t),
fFontColor(-1),
fGridColor(-1),
fPlaneColor(kRed-5),
fPlaneTransparency(60),
fNZSteps(6),
fZAxisStep(0.f),
fAutoRebin(kTRUE),
fPixelsPerBin(12),
fNormalizeRebin(kFALSE),
fProjection(kAuto),
f2DMode(kValSize),
fBoxMode(kBack),
fDrawHPlane(kFALSE),
fHPlaneVal(0),
fHasFixedHeightIn2DMode(kFALSE),
fFixedHeightValIn2DMode(0.f),
fDrawNumberCellPixels(18),
fCellPixelFontSize(12)
{
fMaxTowerH = 1;
SetElementNameTitle("TEveCaloLego", "TEveCaloLego");
}
void TEveCaloLego::SetData(TEveCaloData* data)
{
TEveCaloViz::SetData(data);
}
void TEveCaloLego::BuildCellIdCache()
{
fCellList.clear();
fData->GetCellList(GetEta(), GetEtaRng(), GetPhi(), GetPhiRng(), fCellList);
fCellIdCacheOK = kTRUE;
}
void TEveCaloLego::ComputeBBox()
{
BBoxZero();
Float_t ex = 1.2;
Float_t a = 0.5*ex;
fBBox[0] = -a;
fBBox[1] = a;
fBBox[2] = -a;
fBBox[3] = a;
Double_t em, eM, pm, pM;
fData->GetEtaLimits(em, eM);
fData->GetPhiLimits(pm, pM);
Double_t r = (eM-em)/(pM-pm);
if (r<1)
{
fBBox[2] /= r;
fBBox[3] /= r;
}
else
{
fBBox[0] *= r;
fBBox[1] *= r;
}
fBBox[4] = 0;
if (fScaleAbs && !fData->Empty())
fBBox[5] = GetMaxVal()*GetValToHeight();
else
fBBox[5] = fMaxTowerH;
}