// ESAF : Euso Simulation and Analysis Framework
// $Id: EFocalSurfacePainter.cc,v 1.53 2005/11/11 10:37:00 pesce Exp $
// Author A.Thea Jun, 28 2004
/*****************************************************************************
* ESAF: Euso Simulation and Analysis Framework *
* *
* Id: FocalSurfacePainter *
* Package: EventViewer *
* Coordinator: Alessandro.Thea *
* *
*****************************************************************************/
//______________________________________________________________________________
//
// EFocalSurfacePainter
//
// A painter to show the development of the signal on the focal surface.
//
// Setters:
//
// ViewNspread
// MaxColors
//
//
// TO BE DONE
#include "EFocalSurfacePainter.hh"
#include "EEvent.hh"
#include "EDetector.hh"
#include "EElectronics.hh"
#include "EFee.hh"
#include "EAFee.hh"
#include "EMacroCellHit.hh"
#include "EChipTriggPars.hh"
#include "Etypes.hh"
#include "ERunParameters.hh"
#include "ESystemOfUnits.hh"
#include "Riostream.h"
#include "TCanvas.h"
#include "TList.h"
#include "TStyle.h"
#include "TVector3.h"
#include "TH1.h"
#include "TGString.h"
#include <TSystem.h>
using namespace TMath;
using namespace sou;
ClassImp(EFocalSurfacePainter)
ClassImp(EPolygon)
//_____________________________________________________________________________
EFocalSurfacePainter::EFocalSurfacePainter() : fDetector(0), fRunPars(0),
fH1Hits(0), fHitsStyle(0), fH1SigProfile(0), fH1SigMaxProfile(0), fH1NoiseMaxProfile(0),
fH1NoiseMinProfile(0), fH1NoiseMeanProfile(0), fH1HitsMaxProfile(0), fLines(0) {
//
// Default constructor
//
}
//_____________________________________________________________________________
EFocalSurfacePainter::EFocalSurfacePainter( EEvent* ev ) : fH1Hits(0),
fHitsStyle(0), fH1SigProfile(0), fH1SigMaxProfile(0), fH1NoiseMaxProfile(0),
fH1NoiseMinProfile(0), fH1NoiseMeanProfile(0), fH1HitsMaxProfile(0), fLines(0) {
//
//
//
fDetector = ev->GetDetector();
fRunPars = ev->GetRunPars();
Constructor();
}
//_____________________________________________________________________________
EFocalSurfacePainter::EFocalSurfacePainter( EDetector* det, ERunParameters* runpars) :
fH1Hits(0), fHitsStyle(0), fH1SigProfile(0), fH1SigMaxProfile(0), fH1NoiseMaxProfile(0),
fH1NoiseMinProfile(0), fH1NoiseMeanProfile(0), fH1HitsMaxProfile(0), fLines(0) {
//
//
//
fDetector = det;
fRunPars = runpars;
Constructor();
}
//______________________________________________________________________________
void EFocalSurfacePainter::Constructor() {
//
// Constructor
//
fLines = new TList;
fXaxis.SetTitle("X [mm]");
fXaxis.SetLabelFont(42);
fXaxis.SetTextFont(52);
fYaxis.SetTitle("Y [mm]");
fYaxis.SetLabelFont(42);
fYaxis.SetTextFont(52);
fHaxis.SetTitle("Rate");
fHaxis.SetLabelFont(42);
fHaxis.SetTextFont(52);
fHaxis.SetTitleOffset(0.75);
fGtu = -1;
fModified = kFALSE;
// graphics options
fViewRange = 5.;
fViewThreshold = 4;
fViewBorder = 0.2;
fAutoThreshold = kTRUE;
fGifCanvasW = 600;
fGifCanvasH = 600;
fTxtCounter.SetTextAlign(13);
fTxtCounter.SetTextSize(0.05);
fTxtCounter.SetTextFont(52);
fTxtSum.SetTextAlign(13);
fTxtSum.SetTextSize(0.05);
fTxtSum.SetTextFont(52);
fShowAxis = kTRUE;
fShowOffPixels = kFALSE;
fShowEmptyPixels = kFALSE;
fShowGtuCounter = kTRUE;
fDrawNightGlow = kFALSE;
fIntegral = kIntNone;
fAutoRadius = kTRUE;
fMoveView = kFALSE;
fAlpha = 0;
fApplyThreshold = kFALSE;
fAbsoluteThreshold = kFALSE;
fTriggers.clear();
fHasTriggersFilled = kFALSE;
fX1 = 0;
fX2 = 0;
fY1 = 0;
fY2 = 0;
fXmin = 0;
fXmax = 0;
fYmin = 0;
fYmax = 0;
fNumColors = 50;
fPaletteOffset = 51;
fMaxCounts = 30;
fStdPalette = kFALSE;
fPixelColorOff = kBlack;
fPixelColorEmpty = kWhite;
fPmtColorEmpty = 49;
fPmtColorHit = 27;
fCacheCode = 0;
fCurrentMapID = kFeeSignals;
fCurrentTrigger = 0;
if ( !fDetector || !fRunPars ) {
Info("EFocalSurfacePainter","Either Event or RunParameters is not defined. Painter made zombie.");
MakeZombie();
return;
}
Load();
Modified();
FindView( kFeeHits );
fAutoRadius = kFALSE;
UpdateHist();
}
//_____________________________________________________________________________
EFocalSurfacePainter::~EFocalSurfacePainter() {
//
// Destructor
//
Clear();
SafeDelete(fLines);
SafeDelete(fH1Hits);
SafeDelete(fHitsStyle);
SafeDelete(fH1SigProfile);
SafeDelete(fH1SigMaxProfile);
SafeDelete(fH1NoiseMaxProfile);
SafeDelete(fH1NoiseMinProfile);
SafeDelete(fH1NoiseMeanProfile);
SafeDelete(fH1HitsMaxProfile);
}
//_____________________________________________________________________________
void EFocalSurfacePainter::Clear( Option_t *opt ) {
//
// Clear all temporay containers
//
TString option(opt);
ClearPolyLines();
fPmtsToPaint.clear();
fCache.clear();
fPmtLines.clear();
fPixelLines.clear();
fFrontEndHits.clear();
fFrontEndSignals.clear();
fFrontEndNoises.clear();
fMacroCellHits.clear();
fSelFrontEndHits.clear();
fECHits.clear();
// fIntegralFrontEndHits.clear();
// fIntegralFrontEndSignals.clear();
// fIntegralMacroCellHits.clear();
if ( fH1Hits ) fH1Hits->Clear();
if ( fH1SigProfile ) fH1SigProfile->Clear();
if ( fH1SigMaxProfile ) fH1SigMaxProfile->Clear();
if ( fH1NoiseMaxProfile ) fH1NoiseMaxProfile->Clear();
if ( fH1NoiseMinProfile ) fH1NoiseMinProfile->Clear();
if ( fH1NoiseMeanProfile ) fH1NoiseMeanProfile->Clear();
if ( fH1HitsMaxProfile ) fH1HitsMaxProfile->Clear();
}
//_____________________________________________________________________________
void EFocalSurfacePainter::Draw( Option_t *opt ) {
//
// Build polylines and then append the FSP to pad
//
if ( IsZombie() ) return;
TString options(opt);
// rebuild the lines if needed FIXME
if ( fPixelLines.empty() ) BuildPolyLines();
AppendPad(opt);
}
//______________________________________________________________________________
void EFocalSurfacePainter::UpdateHist( Bool_t force ) {
//
//
//
if ( !fH1Hits) {
fH1Hits = new TH1F("HitsOnScreen","Hits on screen",1,1,10);
fH1Hits->SetDirectory(0);
fH1Hits->GetXaxis()->SetTitle("Gtu");
fH1Hits->GetYaxis()->SetTitle("Signals hits");
}
if ( force || (fMaxCounts > 0 || fMaxCounts != (UInt_t)fH1Hits->GetNbinsX()) ) {
//
// resize the histogram
//
fH1Hits->SetBins( fMaxCounts, -.5, fMaxCounts+.5);
if ( fHitsStyle ) {
TStyle *savesty = gStyle;
gStyle = fHitsStyle;
fH1Hits->UseCurrentStyle();
gStyle = savesty;
}
}
}
//_____________________________________________________________________________
void EFocalSurfacePainter::Paint( Option_t *opt ) {
//
// Options:
//
// ng: paints pmts with a different colors according to the simulated bg
// rate
//
// hits: paints the electronics hits on the focal surface
//
TString options(opt);
if ( (fGtu < fFirstGtu || fGtu > fLastGtu) && fGtu != -1 ) return;
// something has changed, find the viewport again
if ( fModified ) FindView( kFeeHits );
// calculate frame
Float_t viewWidth = fViewRange;
if ( viewWidth < fRunPars->GetPmtData().GetPadSide() ) return;
Float_t padHeight = gPad->GetWh()*gPad->GetHNDC();
Float_t padWidth = gPad->GetWw()*gPad->GetWNDC();
Float_t padMin = TMath::Min(padHeight, padWidth);
Float_t expand = 1+fViewBorder;
fXmin = -( viewWidth*padWidth/padMin )+fViewCenter.X();
fYmin = -( viewWidth*padHeight/padMin )+fViewCenter.Y();
fXmax = ( viewWidth*padWidth/padMin )+fViewCenter.X();
fYmax = ( viewWidth*padHeight/padMin )+fViewCenter.Y();
// reset the box size
fX1 = ( fXmin-fViewCenter.X() )*expand+fViewCenter.X();
fX2 = ( fXmax-fViewCenter.X() )*expand+fViewCenter.X();
fY1 = ( fYmin-fViewCenter.Y() )*expand+fViewCenter.Y();
fY2 = ( fYmax-fViewCenter.Y() )*expand+fViewCenter.Y();
gPad->Range( fX1, fY1, fX2, fY2);
FindPmtsToPaint( fXmin, fYmin, fXmax, fYmax);
if ( options == "ng" || fDrawNightGlow )
PaintNightGlowRate();
else
PaintHits();
}
//______________________________________________________________________________
Int_t EFocalSurfacePainter::GetColorPalette( Int_t theColor) const {
//
// -1 pixel color empty
// -2 pixel color off
// -3 pmt empty
// -4 pmt hit
// 0-n palette color
//
Int_t ncols;
if ( fStdPalette ) {
switch(theColor) {
case kColorPixelEmpty:
case kColorPixelOff:
case kColorPmtEmpty:
case kColorPmtHit:
return 0;
default:
ncols = gStyle->GetNumberOfColors();
if ( theColor >= ncols ) theColor = ncols-1;
return gStyle->GetColorPalette(theColor);
}
} else {
switch(theColor) {
case kColorPixelEmpty:
return fPixelColorEmpty;
case kColorPixelOff:
return fPixelColorOff;
case kColorPmtEmpty:
return fPmtColorEmpty;
case kColorPmtHit:
return fPmtColorHit;
default:
ncols = fNumColors;
if ( theColor >= ncols ) theColor = ncols-1;
return fPaletteOffset+theColor;
}
}
}
//______________________________________________________________________________
Int_t EFocalSurfacePainter::GetNormColorPalette(Float_t theColor ) const {
//
// convert 0-1 to mincol-maxcol
//
return GetColorPalette(Nint(theColor*GetPaletteNumColors()));
}
//_____________________________________________________________________________
void EFocalSurfacePainter::PaintHits() {
//
// Paint the
//
const Counts_t* pixels = MapToPaint();
if (!pixels) return; //FIXME or paint "No hits"?
UInt_t sum(0);
Int_t nPmtPads = fRunPars->GetPmtData().GetNumPads();
fH1Hits->Reset();
for(UInt_t i(0); i< fPmtsToPaint.size(); i++){
// check if this pmt is empty
Bool_t isEmpty = kTRUE;
Int_t suid = fRunPars->GetPmtGeo( fPmtsToPaint[i] )->GetStartUniqueId();
for( Int_t k(0); k < nPmtPads; k++)
isEmpty &= pixels->count(suid+k) == 0;
// draw the pmt
EPolygon *p = GetPmtLine( fPmtsToPaint[i] );
p->SetFillColor( GetColorPalette( isEmpty ? kColorPmtEmpty : kColorPmtHit ) );
p->Paint("f");
p->Paint();
// paint the pixels
for( Int_t k(0); k < nPmtPads; k++) {
Int_t uid = suid+k;
Color_t c = -1;
if ( pixels->count(uid) == 0 ) {
if ( fShowOffPixels )
c = GetColorPalette(kColorPixelOff);
} else {
Counts_t::const_iterator
UInt_t counts = it != pixels->end() ? it->second : 0;
// apply the pixel threshold
if ( fApplyThreshold ) {
Double_t thres = 0;
if ( !fAbsoluteThreshold ) {
Double_t rate = fRunPars->GetNightGlowRateByUId(uid)/microsecond
*fRunPars->GetPmtData().GetGtuLength();
thres = rate+fAlpha*Sqrt(rate);
} else {
thres = fAlpha;
}
if ( counts > (UInt_t)Nint(Ceil(thres)) )
counts -= Nint(Ceil(thres));
else counts = 0;
}
if ( counts == 0 ) {
if ( fShowEmptyPixels || fCurrentMapID == kCellHits )
// draw always empty hits in case for macrocells
c = GetColorPalette(kColorPixelEmpty);
} else {
sum += counts;
fH1Hits->Fill(counts);
if ( counts < fMaxCounts ) {
c = GetNormColorPalette(0.99*counts/(Float_t)fMaxCounts);
// c = fPaletteOffset+Nint(0.99*((Float_t)fNumColors/(Float_t)fMaxCounts)*counts);
} else {
// c = fPaletteOffset+fNumColors;
c = GetNormColorPalette(1.);
}
}
}
if ( c < 0 ) continue;
p = GetPixelLine( uid );
p->SetFillColor(c);
p->Paint("f");
p->Paint();
}
}
if ( fShowGtuCounter ) {
if ( fGtu == -1 )
fTxtCounter.SetText( 0.1*(fXmax-fXmin)+fXmin, fYmax, Form("Gtus %d-%d",fFirstGtu,fLastGtu));
else
fTxtCounter.SetText( 0.1*(fXmax-fXmin)+fXmin, fYmax, Form("Gtu %d",fGtu));
fTxtCounter.Paint();
fTxtSum.SetText( 0.5*(fXmax-fXmin)+fXmin, fYmax, Form("Hits on screen: %d",sum));
fTxtSum.Paint();
}
if ( fShowAxis ) {
Int_t ndiv = 510;
Int_t nColors = GetPaletteNumColors();
Double_t xmin = fXmin;
Double_t xmax = fXmax;
fXaxis.PaintAxis(fXmin, fYmin, fXmax, fYmin, xmin, xmax, ndiv);
fYaxis.PaintAxis(fXmin, fYmin, fXmin, fYmax, xmin, xmax, ndiv);
Float_t w = (fXmax-fXmin)/25.;
Float_t h = (fYmax-fYmin)/nColors;
TPave pave(fXmax-w/2,fYmin,fXmax+w/2,fYmax,0);
for( Int_t i(0); i < nColors; i++) {
pave.SetFillColor(GetColorPalette(i));
pave.PaintPave(fXmax-w/2,fYmin+i*h,fXmax+w/2,fYmin+(i+1)*h,0);
}
Double_t axMin = 0;
Double_t axMax = fMaxCounts;
fHaxis.PaintAxis(fXmax+w/2,fYmin,fXmax+w/2,fYmax,axMin,axMax,ndiv,"+L");
}
}
//_____________________________________________________________________________
void EFocalSurfacePainter::PaintNightGlowRate() {
//
// Paint the elementary cells with color depending on the ng rate.
//
fDrawNightGlow = kTRUE;
Double_t rmax = fRunPars->GetMaxNightGlowRate();
Double_t rmin = fRunPars->GetMinNightGlowRate();
Int_t ndiv = 10;
EPolygon *p;
for(UInt_t i(0); i< fPmtsToPaint.size(); i++){
// check if this pmt is empty
Int_t suid = fRunPars->GetPmtGeo( fPmtsToPaint[i] )->GetStartUniqueId();
// draw the pmt
p = GetPmtLine( fPmtsToPaint[i] );
Int_t chipId = fRunPars->FrontEndChip(suid);
Double_t rate = fRunPars->GetNightGlowRate(chipId);
p->SetFillColor( GetNormColorPalette((rate-rmin)/(rmax-rmin)) );
p->Paint("f");
p->Paint();
}
Int_t nColors = GetPaletteNumColors();
Float_t w = (fXmax-fXmin)/15.;
Float_t h = (fYmax-fYmin)/nColors;
TPave pave(fXmax-w,fYmin,fXmax,fYmax,0);
for( Int_t i(0); i < nColors; i++) {
pave.SetFillColor(GetColorPalette(i));
pave.PaintPave(fXmax-w,fYmin+i*h,fXmax,fYmin+(i+1)*h,0);
}
fHaxis.PaintAxis(fXmax,fYmin,fXmax,fYmax,rmin,rmax,ndiv,"+L");
}
//______________________________________________________________________________
Int_t EFocalSurfacePainter::DistancetoPrimitive(Int_t px, Int_t py) {
//
//
//
Int_t pxl, pyl, pxt, pyt;
Int_t px1 = gPad->XtoAbsPixel(fX1);
Int_t py1 = gPad->YtoAbsPixel(fY1);
Int_t px2 = gPad->XtoAbsPixel(fX2);
Int_t py2 = gPad->YtoAbsPixel(fY2);
if (px1 < px2) {pxl = px1; pxt = px2;}
else {pxl = px2; pxt = px1;}
if (py1 < py2) {pyl = py1; pyt = py2;}
else {pyl = py2; pyt = py1;}
if ( (px >= pxl && px <= pxt) && (py >= pyl && py <= pyt) ) return 0;
else return 9999;
}
//______________________________________________________________________________
void EFocalSurfacePainter::ExecuteEvent(Int_t event, Int_t px, Int_t py) {
//
// Execute an event when the mouse moves in the display active region
//
switch (event) {
case kMouseMotion:
break;
case kButton1Up:
if ( fMoveView ) {
SetViewCenter(gPad->AbsPixeltoX(px),gPad->AbsPixeltoY(py));
gPad->Modified();
gPad->Update();
fMoveView = kFALSE;
}
break;
default:
break;
}
}
//______________________________________________________________________________
char* EFocalSurfacePainter::GetObjectInfo(Int_t px, Int_t py) const {
//
// Redefines TObject::GetObjectInfo.
//
if (!gPad) return (char*)"";
static char info[64];
Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));//+fViewCenter.X();
Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));//+fViewCenter.Y();
Int_t pmtId=-1;
Int_t pxUID=-1;
size_t j;
for (j=0; j<fPmtsToPaint.size(); j++) {
if ( FindPmtLine(fPmtsToPaint[j])->DistancetoPrimitive(px,py) == 0 ) {
pmtId = fPmtsToPaint[j];
break;
}
}
if ( pmtId == -1 ) {
sprintf(info,"(x=%g, y=%g, no pixel)",x,y);
} else {
Int_t nPmtPads = fRunPars->GetPmtData().GetNumPads();
// take the first uid in the mapmt
Int_t suid = fRunPars->GetPmtGeo( pmtId )->GetStartUniqueId();
for( Int_t k(0); k < nPmtPads; k++) {
Int_t uid = suid+k;
if ( fPixelLines.count(uid) == 0 ) break;
map<Int_t, EPolygon* >::const_iterator it = fPixelLines.find(uid);
if ( it->second->DistancetoPrimitive(px,py) == 0 ) {
pxUID = uid;
break;
}
}
Counts_t* mMap;
if ( pxUID != -1 && (mMap=(Counts_t*)MapToPaint())) {
Int_t counts = (*mMap)[pxUID];
if ( fApplyThreshold ) {
Double_t thres = 0;
if (!fAbsoluteThreshold) {
Double_t rate = fRunPars->GetNightGlowRateByUId(pxUID)/microsecond
*fRunPars->GetPmtData().GetGtuLength();
thres = rate+fAlpha*Sqrt(rate);
} else {
thres = fAlpha;
}
if ( counts > Nint(Ceil(thres)) )
counts -= Nint(Ceil(thres));
else counts = 0;
}
sprintf(info,"(x=%g, y=%g, pmt id=%d, px id=%d, counts=%d)",x,y,pmtId,pxUID,counts);
} else {
sprintf(info,"(x=%g, y=%g, pmt id=%d, no pixel)",x,y,pmtId);
}
}
return info;
}
//_____________________________________________________________________________
Bool_t EFocalSurfacePainter::FindView( Int_t id ) {
//
// calculates center, spread and orientation of the viewport
//
if ( IsZombie() ) return kFALSE;
Modified( kFALSE );
// define range
Int_t nPixelsOn(0);
TVector3 vSum2(0.,0.,0.);
fViewCenter.SetXYZ(0.,0.,0.);
fSpread.SetXYZ(0.,0.,0.);
Int_t nCountsOverThres(0);
GtuCounts_t& mViewMap = fFrontEndSignals;
// find view center and axis
GtuCounts_t::iterator
Counts_t::iterator
Int_t threshold;
for( threshold = fViewThreshold ; threshold>0; threshold--) {
// start to chech if the viewport can be defined by pixels over threshold fViewThreshold;
nCountsOverThres = 0;
for(itGtu = mViewMap.begin(); itGtu != mViewMap.end(); itGtu++)
for( itUId = (itGtu->second).begin(); itUId != (itGtu->second.end()); itUId++){
if ( itUId->second == 0 ) continue;
nPixelsOn += itUId->second;
if ( itUId->second < threshold ) continue;
// Pmt normals are downward oriented, while Z axis must be upward oriented
TVector3 dummy = fRunPars->PixelCenter(itUId->first);
fViewCenter += dummy*itUId->second;
nCountsOverThres+= itUId->second;
}
if ( nCountsOverThres || !fAutoThreshold ) break;
}
Info("FindView","%d pixels to draw, %d over threshold %d", nPixelsOn, nCountsOverThres, threshold);
if ( !nCountsOverThres ) {
Warning("FindView","Not possible to find the center. Try to Lower the threshold");
const EPmtGeo* pmt = fRunPars->GetPmtGeoByUId(1);
fViewCenter = pmt->GetCenter();
} else {
fViewCenter *= 1./(Float_t)nCountsOverThres;
// calculate spread along the axis
for(itGtu = mViewMap.begin(); itGtu != mViewMap.end(); itGtu++)
for( itUId = (itGtu->second).begin(); itUId != (itGtu->second.end()); itUId++){
if ( itUId->second == 0 ) continue;
if ( itUId->second < threshold ) continue;
TVector3 dummy = fRunPars->PixelCenter(itUId->first)-fViewCenter;
fSpread[0] += TMath::Power((dummy.X()),2)*itUId->second;
fSpread[1] += TMath::Power((dummy.Y()),2)*itUId->second;
fSpread[2] += TMath::Power((dummy.Z()),2)*itUId->second;
}
}
for(Int_t i(0); i<3; i++) {
fSpread[i] = TMath::Sqrt(fSpread[i]/(Float_t)nCountsOverThres);
fSpread[i] = TMath::Max(fSpread[i],(Double_t)fRunPars->GetPmtData().GetPadSide());
}
if ( fAutoRadius ) fViewRange = fSpread.Mag()*5;
BuildPolyLines();
return kTRUE;
}
//______________________________________________________________________________
void EFocalSurfacePainter::CenterViewOnPmt( Int_t pmtid){
//
//
//
fViewCenter = fRunPars->GetPmtGeo(pmtid)->GetCenter();
}
//_____________________________________________________________________________
void EFocalSurfacePainter::BuildPolyLines() {
//
// Creates all the polylines for all the hits in the event
//
if ( !fDetector ) {
Error("BuildPolyLines","No Event defined");
return;
}
ClearPolyLines();
// parse all maps and build all the pixels and the pmts
GtuCounts_t::iterator
Counts_t::iterator
for(itGtu = fFrontEndHits.begin(); itGtu != fFrontEndHits.end(); itGtu++)
for( itUId = itGtu->second.begin(); itUId != itGtu->second.end(); itUId++) {
Int_t uid = itUId->first;
GetPixelLine( uid );
// associated pmt
Int_t id = fRunPars->Pmt(uid);
GetPmtLine( id );
}
}
//______________________________________________________________________________
void EFocalSurfacePainter::ClearPolyLines() {
//
// remove all the polylines stored in memory
//
fLines->Clear();
fPmtLines.clear();
fPixelLines.clear();
}
//_____________________________________________________________________________
Bool_t EFocalSurfacePainter::Load() {
//
// Load data and fills GtuCounts from the event and the runparameters
//
Clear();
fFirstGtu = kMaxInt;
fLastGtu = -kMaxInt;
if ( !fDetector->GetNumFee() ) {
Info("Load","No EFee in EDetector object. Painter made zombie.");
MakeZombie();
return kFALSE;
}
FillChipTriggers();
map<Int_t,Bool_t> microcells; // id of microcells with at least a signal
// read EFee from event
for(Int_t i(0); i<fDetector->GetNumFee(); i++) {
EFee *dfee = fDetector->GetFee(i);
Int_t uid = dfee->GetChUId();
Int_t gtu = dfee->GetGtu();
Int_t fee_id = fRunPars->FrontEndChip(uid);
if ( fFrontEndHits[gtu].count( uid ) == 0 )
fFrontEndHits[gtu][uid] = 0;
fFrontEndHits[gtu][uid] += dfee->GetNumHits();
if ( fFrontEndSignals.count( uid ) == 0 )
fFrontEndSignals[gtu][uid] = 0;
fFrontEndSignals[gtu][uid] += dfee->GetNumSignals();
if ( dfee->GetNumSignals()>0 ) {
microcells[fee_id] = kTRUE;
if ( fSelFrontEndHits[gtu].count( uid ) == 0 )
fSelFrontEndHits[gtu][uid] = 0;
fSelFrontEndHits[gtu][uid] += dfee->GetNumHits();
}
if ( fECHits[gtu].count( fee_id ) == 0 )
fECHits[gtu][fee_id] = 0;
fECHits[gtu][fee_id] += dfee->GetNumHits();
// look for first and last gtu
if ( gtu < fFirstGtu ) fFirstGtu = gtu;
if ( gtu > fLastGtu ) fLastGtu = gtu;
}
//read the front end (background) hits in the elementary cells with at least a signal
for(Int_t i(0); i<fDetector->GetNumFee(); i++) {
EFee *dfee = fDetector->GetFee(i);
Int_t uid = dfee->GetChUId();
Int_t gtu = dfee->GetGtu();
Int_t fee_id = fRunPars->FrontEndChip(uid);
if ( microcells.count(fee_id)==0 ) continue;
if ( fFrontEndNoises[gtu].count( uid) == 0 )
fFrontEndNoises[gtu][uid] = 0;
fFrontEndNoises[gtu][uid] += ( dfee->GetNumHits() - dfee->GetNumSignals() );
}
// read CellHits from event
for(Int_t i(0); i<fDetector->GetNumCellHits(); i++) {
EMacroCellHit* mchit = fDetector->GetMacroCellHit(i);
Int_t uid = mchit->GetChUId();
Int_t gtu = mchit->GetGtu();
if ( fMacroCellHits[gtu].count( uid ) == 0 )
fMacroCellHits[gtu][uid] = 0;
fMacroCellHits[gtu][uid] += mchit->GetCounts();
// look for first and last gtu
if ( gtu < fFirstGtu ) fFirstGtu = gtu;
if ( gtu > fLastGtu ) fLastGtu = gtu;
}
Bool_t adddir = TH1::AddDirectoryStatus();
TH1::AddDirectory(kFALSE);
fH1SigProfile = new TH1F("SignalTimeProfile","Signal Hits",
fLastGtu-fFirstGtu+1,fFirstGtu-0.5,fLastGtu+0.5);
fH1SigProfile->SetXTitle("Gtu");
fH1SigProfile->SetYTitle("N_{hits}");
fH1SigMaxProfile = new TH1F("SignalMaxTimeProfile","Maximum of signal hits per pixel",
fLastGtu-fFirstGtu+1,fFirstGtu-0.5,fLastGtu+0.5);
fH1SigMaxProfile->SetXTitle("Gtu");
fH1SigMaxProfile->SetYTitle("N_{hits}");
fH1SigMaxProfile->SetMinimum(0);
fH1NoiseMaxProfile = new TH1F("NoiseMaxTimeProfile","Maximum of background hits per pixel",
fLastGtu-fFirstGtu+1,fFirstGtu-0.5,fLastGtu+0.5);
fH1NoiseMaxProfile->SetXTitle("Gtu");
fH1NoiseMaxProfile->SetYTitle("N_{hits}");
fH1NoiseMaxProfile->SetMinimum(0);
fH1NoiseMinProfile = new TH1F("NoiseMinTimeProfile","Minimum of background hits per pixel",
fLastGtu-fFirstGtu+1,fFirstGtu-0.5,fLastGtu+0.5);
fH1NoiseMinProfile->SetXTitle("Gtu");
fH1NoiseMinProfile->SetYTitle("N_{hits}");
fH1NoiseMinProfile->SetMinimum(0);
fH1NoiseMeanProfile = new TH1F("NoiseMeanTimeProfile","Mean background hits per pixel",
fLastGtu-fFirstGtu+1,fFirstGtu-0.5,fLastGtu+0.5);
fH1NoiseMeanProfile->SetXTitle("Gtu");
fH1NoiseMeanProfile->SetYTitle("N_{hits}");
fH1NoiseMeanProfile->SetMinimum(0);
fH1HitsMaxProfile = new TH1F("HitsMaxTimeProfile","Maximum of hits per pixel",
fLastGtu-fFirstGtu+1,fFirstGtu-0.5,fLastGtu+0.5);
fH1HitsMaxProfile->SetXTitle("Gtu");
fH1HitsMaxProfile->SetYTitle("N_{hits}");
fH1HitsMaxProfile->SetMinimum(0);
TH1::AddDirectory(adddir);
GtuCounts_t::const_iterator
Counts_t::const_iterator
for(itGtu = fFrontEndSignals.begin(); itGtu!=fFrontEndSignals.end(); itGtu++) {
Int_t sigMax = 0;
for(itPx = itGtu->second.begin(); itPx!=itGtu->second.end(); itPx++) {
fH1SigProfile->Fill(itGtu->first,itPx->second);
sigMax = Max(sigMax,itPx->second);
}
fH1SigMaxProfile->Fill(itGtu->first,sigMax);
}
for(itGtu = fFrontEndNoises.begin(); itGtu!=fFrontEndNoises.end(); itGtu++) {
Int_t noiseMax = 0;
Int_t noiseMin = 9999;
for(itPx = itGtu->second.begin(); itPx!=itGtu->second.end(); itPx++) {
noiseMax = Max(noiseMax,itPx->second);
noiseMin = Min(noiseMin,itPx->second);
}
fH1NoiseMaxProfile->Fill(itGtu->first,noiseMax);
fH1NoiseMinProfile->Fill(itGtu->first,noiseMin);
}
for(itGtu = fECHits.begin(); itGtu!=fECHits.end(); itGtu++) {
Int_t hitsMax = 0;
Int_t ECMaxId = -1;
for(itPx = itGtu->second.begin(); itPx!=itGtu->second.end(); itPx++) {
hitsMax = Max(hitsMax,itPx->second);
ECMaxId = itPx->first;
}
Float_t mean = (fRunPars->GetNightGlowRate(ECMaxId))*(fRunPars->GetPmtData().GetGtuLength())/microsecond;
fH1NoiseMeanProfile->Fill(itGtu->first,Ceil(mean));
}
for(itGtu = fSelFrontEndHits.begin(); itGtu!=fSelFrontEndHits.end(); itGtu++) {
Int_t hitsMax = 0;
for(itPx = itGtu->second.begin(); itPx!=itGtu->second.end(); itPx++) {
hitsMax = Max(hitsMax,itPx->second);
}
fH1HitsMaxProfile->Fill(itGtu->first,hitsMax);
}
return kTRUE;
}
//_____________________________________________________________________________
void EFocalSurfacePainter::ApplyTriggerThreshold( ETriggerTypeIdentifier id ) {
//
// Apply a threshold on the pixels according to the trigger threshold
//
if (!fHasTriggersFilled) FillChipTriggers();
if ( id==(ETriggerTypeIdentifier)0 ) {
fAlpha = 0;
fApplyThreshold = kFALSE;
fAbsoluteThreshold = kTRUE;
fCurrentTrigger = 0;
} else {
if ( !(fTriggers.count(id)) ) {
Info("ApplyTriggerThreshold","Trigger not found in event.");
return;
}
fApplyThreshold = kTRUE;
fAlpha = Abs(fTriggers[id]);
if ( fTriggers[id]<0 ) fAbsoluteThreshold = kTRUE;
else fAbsoluteThreshold = kFALSE;
fCurrentTrigger = id;
}
PaintHits();
}
//_____________________________________________________________________________
void EFocalSurfacePainter::FillChipTriggers() {
//
// Fill the map with the chip tracking trigger thresholds
//
// search for the various type of chip tracking trigger
// if there is a trigger engine active fill fTriggers with his own fAlpha
// if the threshold is absolute put a - sign
EChipTriggPars *fTriggPars = 0;
if ( fRunPars->GetTriggPars(kChipTrackingTrigger) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kChipTrackingTrigger);
fTriggers[kChipTrackingTrigger] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kChipTrackingTrigger] *= -1;
}
if ( fRunPars->GetTriggPars(kChipTrackingTrigger0) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kChipTrackingTrigger0);
fTriggers[kChipTrackingTrigger0] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kChipTrackingTrigger0] *= -1;
}
if ( fRunPars->GetTriggPars(kChipTrackingTrigger1) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kChipTrackingTrigger1);
fTriggers[kChipTrackingTrigger1] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kChipTrackingTrigger1] *= -1;
}
if ( fRunPars->GetTriggPars(kChipTrackingTrigger2) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kChipTrackingTrigger2);
fTriggers[kChipTrackingTrigger2] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kChipTrackingTrigger2] *= -1;
}
if ( fRunPars->GetTriggPars(kChipTrackingTrigger3) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kChipTrackingTrigger3);
fTriggers[kChipTrackingTrigger3] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kChipTrackingTrigger3] *= -1;
}
if ( fRunPars->GetTriggPars(kChipTrackingTrigger4) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kChipTrackingTrigger4);
fTriggers[kChipTrackingTrigger4] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kChipTrackingTrigger4] *= -1;
}
if ( fRunPars->GetTriggPars(kSignalChipTrackingTrigger) ) {
fTriggPars = (EChipTriggPars*)fRunPars->GetTriggPars(kSignalChipTrackingTrigger);
fTriggers[kSignalChipTrackingTrigger] = fTriggPars->GetThresholdNumber();
if ( !fTriggPars->HasRelativeThreshold() ) fTriggers[kSignalChipTrackingTrigger] *= -1;
}
fHasTriggersFilled = kTRUE;
}
//_____________________________________________________________________________
Bool_t EFocalSurfacePainter::IsTriggerEnabled( ETriggerTypeIdentifier id ) {
//
// Check if a given trigger is enabled
//
if (!fHasTriggersFilled) FillChipTriggers();
return (fTriggers.count(id)!=0);
}
//_____________________________________________________________________________
EPolygon* EFocalSurfacePainter::GetPixelLine( Int_t uid ) {
//
// Returns a EPolygon corresponding to uid if doesn't exist.
// If doesn't exists yet in fPixelLines creates a new one.
//
if ( fPixelLines.count(uid) != 0 )
return fPixelLines[uid];
// projections of the axis of the geometry
Float_t x[5], y[5];
for(Int_t iCorner(0); iCorner<4; iCorner++){
TVector3 dummy = fRunPars->PixelCorner(uid,iCorner);//-fViewCenter;
x[iCorner] = dummy.X();//*fXaxis;
y[iCorner] = dummy.Y();//*fYaxis;
}
x[4] = x[0];
y[4] = y[0];
EPolygon *p = new EPolygon(5,x,y);
fPixelLines[uid] = p;
fLines->Add(p);
fPixelLines[uid] = p;
fLines->Add(p);
return p;
}
//_____________________________________________________________________________
EPolygon* EFocalSurfacePainter::FindPmtLine( Int_t id ) const {
//
// Lookf for EPolygon corresponding to id among the ones already created
//
EPolygon *pol = 0;
if ( fPmtLines.count( id ) != 0 ) pol = fPmtLines.find(id)->second;
return pol;
}
//_____________________________________________________________________________
EPolygon* EFocalSurfacePainter::GetPmtLine( Int_t id ) {
//
// Returns a EPolygon corresponding to id if doesn't exist.
// If doesn't exists yet in fPmtLines creates a new one.
//
if ( fPmtLines.count( id ) != 0 )
return fPmtLines[id];
// this pmt doesn't exists. make new polyline
Float_t x[5], y[5];
for(Int_t iCorner(0); iCorner<4; iCorner++){
TVector3 dummy = fRunPars->PmtCorner(id, iCorner);
x[iCorner] = dummy.X();
y[iCorner] = dummy.Y();
}
x[4] = x[0];
y[4] = y[0];
EPolygon *p = new EPolygon(5,x,y);
fPmtLines[id] = p;
fLines->Add(p);
return p;
}
//_____________________________________________________________________________
void EFocalSurfacePainter::FindPmtsToPaint( Float_t xmin, Float_t ymin, Float_t xmax, Float_t ymax ) {
//
// Looks for Pmts which centers are in the viewport.
// Fills fPmtsToPaint and fPixelsToPaint
//
fPmtsToPaint.clear();
for( Int_t i(1); i <= fRunPars->GetNumPmts(); i++) {
TVector3 dummy = fRunPars->GetPmtGeo(i)->GetCenter();
if ( dummy.X() < xmin || dummy.X() > xmax ||
dummy.Y() < ymin || dummy.Y() > ymax )
continue;
// add the polyline to the list
GetPmtLine(i);
fPmtsToPaint.push_back(i);
}
}
//_____________________________________________________________________________
void EFocalSurfacePainter::Play( Option_t *opt ) {
//
// Start the movie
//
if ( gPad ) gPad->Clear();
TString option(opt);
Draw( option );
fTimer->Connect("Timeout()","EFocalSurfacePainter", this, "Animate()" );
Rewind();
Info("Play","Animation started");
fTimer->TurnOn();
}
//_____________________________________________________________________________
void EFocalSurfacePainter::Animate() {
//
// Move to next animation step and increase the counter
//
if ( IsEnded() ) {
// leave the last frame to be painted
fGtu = fLastGtu;
Stop();
return;
}
NextFrame();
if ( gPad ) {
gPad->Modified();
gPad->Update();
}
}
//_____________________________________________________________________________
void EFocalSurfacePainter::NextFrame() {
//
// Move the internal counter to the next frame
//
if ( fGtu < fLastGtu ) fGtu++;
}
//_____________________________________________________________________________
void EFocalSurfacePainter::MakeGifSequence(const char *option, const char *path) {
//
// Build a sequence of gifs inside a dedicated canvas.
// Gifs are created with opt options
//
TString opt(option);
TCanvas *display = new TCanvas("MakeGifDisplay","MakeGifDisplay",
fGifCanvasW, fGifCanvasH);
fGtu = -1;
display->GetListOfPrimitives()->Add(this,opt);
display->Modified(kTRUE);
display->SaveAs("AnimHead.gif");
for( fGtu = fFirstGtu; fGtu <= fLastGtu; fGtu++) {
display->Modified();
display->Update();
display->SaveAs(Form("%s%.3d.gif",path,fGtu));
}
fGtu = -1;
display->Modified();
display->SaveAs("AnimTail.gif");
delete display;
}
//_____________________________________________________________________________
const Counts_t* EFocalSurfacePainter::MapToPaint() const {
Counts_t* m;
const GtuCounts_t *pMap = GtuCountsToPaint();
if (!pMap) return 0;
GtuCounts_t::const_iterator
if (fGtu == -1 ) {
// paint all hits superimposed
fCountsSum.clear();
for( itGtu = pMap->begin(); itGtu != pMap->end(); itGtu++)
switch (fIntegral) {
case kIntMax:
fCountsSum |= (itGtu->second);
break;
case kIntSum:
default:
fCountsSum += (itGtu->second);
}
m = &fCountsSum;
} else if ( fIntegral != kIntNone ) {
// draw superposition of all hits from first gtu to the current one.
// check cache content
if ( fCacheCode != CurrentCode() ) CacheIntegral();
// look for the right entry
if ( (itGtu = fCache.find(fGtu)) != fCache.end() )
m = (Counts_t*)&(itGtu->second);
} else {
// draw just a gtu
itGtu = pMap->find(fGtu);
if ( itGtu != pMap->end() ) m = (Counts_t*)&(itGtu->second);
}
return m;
}
//_____________________________________________________________________________
const GtuCounts_t* EFocalSurfacePainter::GtuCountsToPaint() const {
switch( fCurrentMapID ) {
case kFeeHits:
return &fFrontEndHits;
case kFeeSignals:
return &fFrontEndSignals;
case kCellHits:
return &fMacroCellHits;
default:
Error("MapToPaint","bad id in fCurrentMapID, returning 0");
}
return 0;
}
//_____________________________________________________________________________
void EFocalSurfacePainter::CacheIntegral() const {
// cache data to speed-up animation
Counts_t dummy;
const GtuCounts_t *map = GtuCountsToPaint();
if ( !map ) return;
fCache.clear();
GtuCounts_t::const_iterator
for( Int_t gtu = fFirstGtu; gtu <= fLastGtu; gtu++ ) {
if ( (itGtu = map->find(gtu)) != map->end())
switch( fIntegral ) {
case kIntMax:
dummy |= (itGtu->second);
break;
case kIntSum:
default:
dummy += (itGtu->second);
}
fCache[gtu] = dummy;
}
fCacheCode = CurrentCode();
}
//______________________________________________________________________________
const Counts_t operator+(const Counts_t& a, const Counts_t& b){
Counts_t::iterator
Counts_t::const_iterator
Counts_t tmp = a;
for( itB = b.begin(); itB != b.end(); itB++) {
if ( (itA = tmp.find(itB->first) ) == tmp.end() )
tmp[itB->first] = itB->second;
else
itA->second += itB->second;
}
return tmp;
}
//______________________________________________________________________________
Counts_t& operator+=( Counts_t& a, const Counts_t& b){
Counts_t::iterator
Counts_t::const_iterator
for( itB = b.begin(); itB != b.end(); itB++) {
if ( (itA = a.find(itB->first) ) == a.end() )
a[itB->first] = itB->second;
else
itA->second += itB->second;
}
return a;
}
//______________________________________________________________________________
const Counts_t operator|(const Counts_t& a, const Counts_t& b){
Counts_t::iterator
Counts_t::const_iterator
Counts_t tmp = a;
for( itB = b.begin(); itB != b.end(); itB++) {
if ( (itA = tmp.find(itB->first) ) == tmp.end() )
tmp[itB->first] = itB->second;
else
itA->second = Max(itA->second,itB->second);
}
return tmp;
}
//______________________________________________________________________________
Counts_t& operator|=( Counts_t& a, const Counts_t& b){
Counts_t::iterator
Counts_t::const_iterator
for( itB = b.begin(); itB != b.end(); itB++) {
if ( (itA = a.find(itB->first) ) == a.end() )
a[itB->first] = itB->second;
else
itA->second = Max(itA->second, itB->second);
}
return a;
}
//______________________________________________________________________________
EPolygon::EPolygon( Int_t n, Float_t *x, Float_t *y ) : TPolyLine( n, x, y ) {
//
// Constructor
//
}
//______________________________________________________________________________
EPolygon::~EPolygon() {
//
// Destructor
//
}
//______________________________________________________________________________
void EPolygon::ExecuteEvent(Int_t event, Int_t px, Int_t py) {
TPolyLine::ExecuteEvent(event, px, py);
}
//______________________________________________________________________________
Int_t EPolygon::DistancetoPrimitive(Int_t px, Int_t py) {
Int_t distance= 999999;
if (TMath::IsInside(gPad->AbsPixeltoX(px),gPad->AbsPixeltoY(py),fLastPoint+1,fX,fY)) distance = 0;
return distance;
}