#include "AliRunLoader.h"
#include "EveBase/AliEveEventManager.h"
#include "AliEveFMDLoader.h"
#include "../FMD/AliFMDUShortMap.h"
#include "../FMD/AliFMDBoolMap.h"
#include "../FMD/AliFMDGeometry.h"
#include "../FMD/AliFMDParameters.h"
#include "../FMD/AliFMDDetector.h"
#include "../FMD/AliFMDRing.h"
#include "../FMD/AliFMDBaseDigit.h"
#include "../FMD/AliFMDDigit.h"
#include "../FMD/AliFMDRawReader.h"
#include "../FMD/AliFMDHit.h"
#include "AliESDEvent.h"
#include "AliESDFMD.h"
#include "AliLog.h"
#include "AliRawReader.h"
#include <TClonesArray.h>
#include <TTree.h>
#include <TGeoShape.h>
#include <TGeoManager.h>
#include <TEveGeoNode.h>
#include <TEveBoxSet.h>
#include <TEveQuadSet.h>
#include <TEveManager.h>
#include <TEveUtil.h>
#include <TStyle.h>
#include <TMath.h>
#include <iostream>
namespace
{
const Char_t* kDetector = "FMD%d";
const Char_t* kRing = "FMD%d%c";
const Char_t* kModule = "FMD%d%c[%02d-%02d]";
const Char_t* kSector = "FMD%d%c[%02d] %s";
const Char_t* kHits = "Hits";
const Char_t* kDigits = "Digits";
const Char_t* kRaw = "Raw";
const Char_t* kESD = "ESD";
}
AliEveFMDLoader* AliEveFMDLoader::fgInstance = 0;
AliEveFMDLoader* AliEveFMDLoader::Instance()
{
if (!fgInstance)
fgInstance = new AliEveFMDLoader();
return fgInstance;
}
AliEveFMDLoader::AliEveFMDLoader(const char* name, Bool_t useBoxes,
Bool_t )
: TEveElementList(name, 0),
fHitPalette(0, 1000),
fDigitPalette(0, 1023),
fMultPalette(0, 20),
fUseBoxDigits(useBoxes),
fHitCache("AliFMDHit",0),
fDigitCache("AliFMDDigit", 0),
fRawCache("AliFMDDigit", 0)
{
IncDenyDestroy();
fHitPalette.IncRefCount();
fDigitPalette.IncRefCount();
fMultPalette.IncRefCount();
TGeoManager* geoMan = AliEveEventManager::AssertGeometry();
if (!geoMan) return;
geoMan->GetTopVolume()->cd(0);
AliFMDGeometry* geom = AliFMDGeometry::Instance();
geom->Init();
geom->InitTransformations();
AliFMDParameters* pars = AliFMDParameters::Instance();
pars->Init(kFALSE, 0);
TGeoShape* inner = static_cast<TGeoShape*>(gGeoManager->GetListOfShapes()
->FindObject("FMDI_physical_sensor"));
if (!inner) throw TEveException("Shape of inner type sensors not found");
TGeoShape* outer = static_cast<TGeoShape*>(gGeoManager->GetListOfShapes()
->FindObject("FMDO_physical_sensor"));
if (!outer) throw TEveException("Shape of outer type sensors not found");
inner->SetUniqueID(1000);
outer->SetUniqueID(1000);
for (UShort_t d = 1; d <= 3; d++) {
AliFMDDetector* detector = geom->GetDetector(d);
if (!detector) continue;
TEveElementList* ed = new TEveElementList(Form(kDetector,
detector->GetId()));
AddElement(ed);
ed->IncDenyDestroy();
ed->SetUserData(detector);
Char_t rings[] = { 'I', 'O', 0 };
Char_t* pr = &(rings[0]);
while (*pr) {
AliFMDRing* ring = detector->GetRing(*pr);
pr++;
if (!ring) continue;
TEveElementList* er = new TEveElementList(Form(kRing,
detector->GetId(),
ring->GetId()));
ed->AddElement(er);
er->IncDenyDestroy();
er->SetUserData(ring);
UShort_t nmod = ring->GetNModules();
for (UShort_t m = 0; m < nmod; m++) {
TEveGeoShape* em = new TEveGeoShape(Form(kModule,
detector->GetId(),
ring->GetId(),
2*m, 2*m+1));
er->AddElement(em);
em->SetTransMatrix(*(detector->FindTransform(ring->GetId(), 2*m)));
em->SetShape(ring->GetId() == 'I' ? inner : outer);
em->SetMainColor(Color_t(kGray));
em->SetMainTransparency(32);
em->IncDenyDestroy();
ModuleData* data = new ModuleData;
data->fScaledSum = 0;
em->SetUserData(data);
#if 0
for (UShort_t s = 2*m; s < 2*m+2 && s < nsec; s++) {
TEveDigitSet* eb = MakeDigitSet(Form(kSector,
detector->GetId(),
ring->GetId(), s), nstr);
em->AddElement(eb);
eb->SetEmitSignals(kFALSE);
eb->SetPickable(kTRUE);
}
#endif
}
}
}
}
AliEveFMDLoader::~AliEveFMDLoader()
{
AliWarning("AliEveFMDLoader being destroyed!");
}
Int_t
AliEveFMDLoader::RemoveFromListTrees(TEveElement* el)
{
ClearDigitSets("All");
return TEveElementList::RemoveFromListTrees(el);
}
void
AliEveFMDLoader::RemoveParent(TEveElement* el)
{
TEveElementList::RemoveParent(el);
}
TEveDigitSet*
AliEveFMDLoader::MakeDigitSet(const char* name, UShort_t nstr)
{
TEveDigitSet* ret = 0;
if (fUseBoxDigits) {
TEveBoxSet* boxes = new TEveBoxSet(name);
boxes->Reset(TEveBoxSet::kBT_FreeBox, kFALSE, nstr);
ret = boxes;
}
else {
TEveQuadSet* quads = new TEveQuadSet(name);
quads->Reset(TEveQuadSet::kQT_RectangleXY, kFALSE, nstr);
ret = quads;
}
return ret;
}
void
AliEveFMDLoader::ClearDigitSets(const char* type)
{
TString stype(type);
for (TEveElement::List_i di = BeginChildren();
di != EndChildren(); ++di) {
for (TEveElement::List_i ri = (*di)->BeginChildren();
ri != (*di)->EndChildren(); ++ri) {
for (TEveElement::List_i mi = (*ri)->BeginChildren();
mi != (*ri)->EndChildren(); ++mi) {
ModuleData* data = static_cast<ModuleData*>((*mi)->GetUserData());
data->fScaledSum = 0;
(*mi)->SetMainColor(Color_t(kGray));
if (stype == "All") {
(*mi)->RemoveElements();
continue;
}
for (TEveElement::List_i si = (*mi)->BeginChildren();
si != (*mi)->EndChildren(); ++si) {
TEveDigitSet* signals = static_cast<TEveDigitSet*>((*si));
if (!signals) continue;
TString s(signals->GetName());
if (!s.Contains(type)) continue;
(*mi)->RemoveElement(signals);
}
}
}
}
}
TEveDigitSet*
AliEveFMDLoader::FindDigitSet(const char* t, UShort_t d, Char_t r, UShort_t s)
{
TEveElement* detector = FindChild(Form(kDetector, d));
if (!detector) {
AliError(Form("Detector %s not found", Form(kDetector, d)));
return 0;
}
TEveElement* ring = detector->FindChild(Form(kRing, d, r));
if (!ring) {
AliError(Form("Ring %s not found", Form(kRing, d, r)));
return 0;
}
Int_t mod = 2*(s/2);
TEveElement* module = ring->FindChild(Form(kModule, d, r, mod, mod+1));
if (!module) {
AliError(Form("Module %s not found", Form(kModule, d, r, s, s+1)));
return 0;
}
TEveElement* sector = module->FindChild(Form(kSector, d, r, s, t));
TEveDigitSet* signal = static_cast<TEveDigitSet*>(sector);
if (!sector) {
AliFMDRing* rng = AliFMDGeometry::Instance()->GetRing(r);
signal = MakeDigitSet(Form(kSector, d, r, s, t), rng->GetNStrips());
module->AddElement(signal);
signal->SetEmitSignals(kFALSE);
signal->SetPickable(kTRUE);
TString st(t);
if (t == kHits) signal->SetPalette(&fHitPalette);
else if (t == kDigits) signal->SetPalette(&fDigitPalette);
else if (t == kRaw) signal->SetPalette(&fDigitPalette);
else if (t == kESD) {
signal->SetPalette(&fMultPalette);
signal->SetOwnIds(kTRUE);
}
}
return signal;
}
void
AliEveFMDLoader::AddSignal(const char* t,
UShort_t det, Char_t rng, UShort_t sec,
UShort_t str, Float_t signal, Float_t min,
Float_t max, TObject* ref)
{
AliFMDGeometry* geom = AliFMDGeometry::Instance();
Double_t x, y, z;
geom->Detector2XYZ(det, rng, sec, str, x, y, z);
AddSignal(t, det, rng, sec, str, x, y, z, signal, min, max, ref);
}
void
AliEveFMDLoader::AddSignal(const char* t,
UShort_t det, Char_t rng, UShort_t sec,
UShort_t str, Double_t x, Double_t y, Double_t z,
Float_t signal, Float_t min, Float_t max,
TObject* ref)
{
AliFMDGeometry* geom = AliFMDGeometry::Instance();
AliFMDRing* ring = geom->GetRing(rng);
if (!ring) return;
TEveDigitSet* signals = FindDigitSet(t, det, rng, sec);
if (!signals) {
AliWarning(Form("No signal (%s) found for FMD%d%c[%02d,%03d]",
t, det, rng, sec, str));
return;
}
Float_t scaled = TMath::Min((signal - min) / (max - min) * 10., 10.);
if ((scaled - min) < 1e-6) {
AliDebug(10, Form("Skipping small %s signal at FMD%d%c[%02d,%03d]=%f (s-min=%f<1e-6)",
t, det, rng, sec, str, signal, scaled-min));
return;
}
Double_t w = 2*ring->GetPitch();
Int_t value = int(TMath::Nint(signal));
AliDebug(5, Form("New %s signal at FMD%d%c[%02d,%03d]=%f (v=%d, s=%f)",
t, det, rng, sec, str, signal, value, scaled));
AddDigit(signals, x, y, z, w, scaled, value, ref);
}
void
AliEveFMDLoader::AddDigit(TEveDigitSet* signals,
Double_t x, Double_t y, Double_t z,
Double_t w, Float_t scaled, Int_t value,
TObject* ref)
{
if (fUseBoxDigits) {
TEveBoxSet* boxes = static_cast<TEveBoxSet*>(signals);
Float_t fw = w;
Float_t zc = (z > 0 ? -1 : 1) * scaled + z;
Float_t vs[] = { -fw, -5*fw, zc-scaled,
+fw, -5*fw, zc-scaled,
+fw, +5*fw, zc-scaled,
-fw, +5*fw, zc-scaled,
-fw, -5*fw, zc+scaled,
+fw, -5*fw, zc+scaled,
+fw, +5*fw, zc+scaled,
-fw, +5*fw, zc+scaled };
Float_t ang = TMath::ATan2(y,x);
for (size_t i = 0; i < 8; i++) {
Float_t bx = vs[3*i+0];
Float_t by = vs[3*i+1];
Float_t ca = TMath::Cos(ang);
Float_t sa = TMath::Sin(ang);
vs[3*i+0] = bx * ca - by * sa + x;
vs[3*i+1] = bx * sa + by * ca + y;
}
boxes->AddBox(vs);
boxes->DigitValue(value);
if (ref) boxes->DigitId(ref);
}
else {
TEveQuadSet* quads = static_cast<TEveQuadSet*>(signals);
quads->AddQuad(x,y,z,w,w);
quads->QuadValue(value);
if (ref) quads->QuadId(ref);
}
TEveElement* par = *(signals->BeginParents());
ModuleData* data = static_cast<ModuleData*>(par->GetUserData());
int maxD = 0;
switch (signals->GetName()[4]) {
case 'I': case 'i': maxD = 2 * 512; break;
case 'O': case 'o': maxD = 2 * 256; break;
default: return;
}
data->fScaledSum += scaled / maxD;
}
void
AliEveFMDLoader::SummarizeModule(TEveElement* module)
{
ModuleData* data = static_cast<ModuleData*>(module->GetUserData());
Float_t sum = data->fScaledSum / module->NumChildren();
if (sum <= 1e-6) {
module->SetMainColor(Color_t(kGray));
module->SetMainAlpha(0);
return;
}
int min = fMultPalette.GetMinVal();
int max = fMultPalette.GetMaxVal();
int cidx = int(sum/10 * (max-min) + min);
UChar_t pix[3];
fMultPalette.ColorFromValue(cidx, pix, false);
module->SetMainColorRGB(pix[0], pix[1], pix[2]);
module->SetMainAlpha(0.33);
}
void
AliEveFMDLoader::SummarizeModules()
{
for (TEveElement::List_i di = BeginChildren();
di != EndChildren(); ++di) {
for (TEveElement::List_i ri = (*di)->BeginChildren();
ri != (*di)->EndChildren(); ++ri) {
for (TEveElement::List_i mi = (*ri)->BeginChildren();
mi != (*ri)->EndChildren(); ++mi) {
TEveElement* module = *mi;
SummarizeModule(module);
}
}
}
}
void
AliEveFMDLoader::CheckAdd()
{
TEveElement* event = gEve->GetCurrentEvent();
SummarizeModules();
if (event && event->FindChild(GetName())) return;
gEve->AddElement(this);
}
void
AliEveFMDLoader::LoadHits()
{
ClearDigitSets(kHits);
AliRunLoader* rl = AliEveEventManager::AssertRunLoader();
if (!rl) {
AliError("No run loader");
return;
}
rl->LoadHits("FMD");
TTree* ht = rl->GetTreeH("FMD", false);
if (!ht) {
AliError("No FMD tree");
return;
}
TClonesArray* hits = &fHitCache;
fHitCache.Clear();
ht->SetBranchAddress("FMD", &hits);
Float_t min = fHitPalette.GetMinVal();
Float_t max = fHitPalette.GetMaxVal();
Int_t nTracks = ht->GetEntriesFast();
for (Int_t i = 0; i < nTracks; i++) {
Int_t hitRead = ht->GetEntry(i);
if (hitRead <= 0) continue;
Int_t nHit = hits->GetEntriesFast();
if (nHit <= 0) continue;
for (Int_t j = 0; j < nHit; j++) {
AliFMDHit* hit = static_cast<AliFMDHit*>(hits->At(j));
if (!hit) continue;
AddSignal(kHits,
hit->Detector(), hit->Ring(), hit->Sector(), hit->Strip(),
hit->X(), hit->Y(), hit->Z(), int(hit->Edep()*1000),
min, max, hit);
}
}
CheckAdd();
}
void
AliEveFMDLoader::DoLoadDigits(const char* t, TClonesArray* digits)
{
Float_t min = fDigitPalette.GetMinVal();
Float_t max = fDigitPalette.GetMaxVal();
Int_t n = digits->GetEntriesFast();
for (Int_t i = 0; i < n; i++) {
AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
if (!digit) return;
AddSignal(t, digit->Detector(), digit->Ring(), digit->Sector(),
digit->Strip(), digit->Counts(), min, max, digit);
}
CheckAdd();
}
void
AliEveFMDLoader::LoadDigits()
{
ClearDigitSets(kDigits);
AliRunLoader* rl = AliEveEventManager::AssertRunLoader();
if (!rl) {
AliError("No run-loader");
return;
}
rl->LoadDigits("FMD");
TTree* dt = rl->GetTreeD("FMD", false);
if (!dt) {
AliError("No FMD tree");
return;
}
TClonesArray* digits = &fDigitCache;
fDigitCache.Clear();
dt->SetBranchAddress("FMD", &digits);
Int_t read = dt->GetEntry(0);
if (read <= 0) {
AliWarning("Nothing read");
return;
}
DoLoadDigits(kDigits, digits);
}
void
AliEveFMDLoader::LoadRaw()
{
ClearDigitSets(kRaw);
AliRawReader* rr = AliEveEventManager::AssertRawReader();
if (!rr) {
AliError("No raw-reader");
return;
}
rr->Reset();
AliFMDRawReader* fr = new AliFMDRawReader(rr, 0);
TClonesArray* digits = &fRawCache;
fRawCache.Clear();
fr->ReadAdcs(digits);
DoLoadDigits(kRaw, digits);
}
void
AliEveFMDLoader::LoadESD()
{
ClearDigitSets(kESD);
AliESDEvent* esd = AliEveEventManager::AssertESD();
if (!esd) {
AliError("No ESD");
return;
}
AliESDFMD* fmd = esd->GetFMDData();
if (!fmd) {
AliError("No FMD ESD data");
return;
}
Float_t min = fMultPalette.GetMinVal();
Float_t max = fMultPalette.GetMaxVal();
for (UShort_t det = 1; det <= 3; det++) {
Char_t rings[] = { 'I', (det == 1 ? '\0' : 'O'), '\0' };
for (Char_t* rng = rings; *rng != '\0'; rng++) {
UShort_t nsec = (*rng == 'I' ? 20 : 40);
UShort_t nstr = (*rng == 'I' ? 512 : 256);
for (UShort_t sec = 0; sec < nsec; sec++) {
for (UShort_t str = 0; str < nstr; str++) {
Float_t mult = fmd->Multiplicity(det,*rng,sec,str);
if (mult == AliESDFMD::kInvalidMult) continue;
Float_t eta = fmd->Eta(det,*rng,sec,str);
TNamed *tmpNamed = new TNamed(Form("FMD%d%c[%02d,%03d]", det, *rng, sec, str),Form("Mch=%f, eta=%f", mult, eta));
AddSignal(kESD, det, *rng, sec, str, mult, min, max,tmpNamed);
if(tmpNamed)delete tmpNamed;
}
}
}
}
CheckAdd();
}