/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz 05/2002 ! Author(s): Harald Kornmayer 1/2001 ! ! Copyright: MAGIC Software Development, 2000-2002 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MCamDisplay // // Camera Display. The Pixels are displayed in // contents/area [somthing/mm^2] // //////////////////////////////////////////////////////////////////////////// #include "MCamDisplay.h" #include #include #include #include #include #include #include //#include #include #include "MHexagon.h" #include "MGeomCam.h" #include "MCerPhotPix.h" #include "MCerPhotEvt.h" #include "MPedestalPix.h" #include "MPedestalCam.h" #include "MImgCleanStd.h" #define kItemsLegend 50 // see SetPalette(1,0) ClassImp(MCamDisplay); // ------------------------------------------------------------------------ // // default constructor // MCamDisplay::MCamDisplay(MGeomCam *geom) : fAutoScale(kTRUE), fW(0), fH(0), fDrawingPad(NULL), fIsAllocated(kFALSE) { fGeomCam = (MGeomCam*)geom; // FIXME: Clone doesn't work! (MGeomCam*)geom->Clone(); // // create the hexagons of the display // fNumPixels = geom->GetNumPixels(); fRange = geom->GetMaxRadius(); // // Construct all hexagons. Use new-operator with placement // // root 3.02 // * base/inc/TObject.h: // register BIT(8) as kNoContextMenu. If an object has this bit set it will // not get an automatic context menu when clicked with the right mouse button. fPixels = new TClonesArray("MHexagon", fNumPixels); for (UInt_t i=0; iSetFillColor(fColors[i]); newtxt->SetTextSize(0.025); newtxt->SetTextAlign(12); } fArrowX = new TArrow(-fRange*.9, -fRange*.9, -fRange*.6, -fRange*.9, 0.025); fArrowY = new TArrow(-fRange*.9, -fRange*.9, -fRange*.9, -fRange*.6, 0.025); TString text; text += (int)(fRange*.3); text += "mm"; fLegRadius = new TText(-fRange*.85, -fRange*.85, text); text = ""; text += (float)((int)(fRange*.3*geom->GetConvMm2Deg()*10))/10; text += "°"; text = text.Strip(TString::kLeading); fLegDegree = new TText(-fRange*.85, -fRange*.75, text); fLegRadius->SetTextSize(0.04); fLegDegree->SetTextSize(0.04); } // ------------------------------------------------------------------------ // // Destructor. Deletes TClonesArrays for hexagons and legend elements. // MCamDisplay::~MCamDisplay() { fPixels->Delete(); fLegend->Delete(); fLegText->Delete(); delete fPixels; delete fLegend; delete fLegText; delete fArrowX; delete fArrowY; delete fLegRadius; delete fLegDegree; // delete fGeomCam; // Not allocated by MCamDisplay or already deleted by the user if (!fIsAllocated || !gROOT->GetListOfCanvases()->FindObject(fDrawingPad)) return; // If it is not already removed make sure that nothing of this object // maybe be deleted automatically by the canvas destructor if (!fDrawingPad->GetListOfPrimitives()->FindObject(this)) return; fDrawingPad->RecursiveRemove(this); delete fDrawingPad; } inline void MCamDisplay::SetPixColor(const MCerPhotPix &pix, const UInt_t i, Float_t min, Float_t max) { if (i>=fNumPixels) return; // // Fixme: Use absolute value per mm^2. Needs another scaling algorithm. // const Float_t ratio = fGeomCam->GetPixRatio(i); const Float_t pnum = ratio*pix.GetNumPhotons(); (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum, min, max)); } inline void MCamDisplay::SetPixColorPedestal(const MPedestalPix &pix, const UInt_t i, Float_t min, Float_t max) { if (i>=fNumPixels) return; // // Fixme: Use absolute value per mm^2. Needs another scaling algorithm. // const Float_t ratio = fGeomCam->GetPixRatio(i); const Float_t pnum = ratio*pix.GetMean(); (*this)[i].SetFillColor(GetColor(pnum, min, max)); } inline void MCamDisplay::SetPixColorError(const MCerPhotPix &pix, const UInt_t i, Float_t min, Float_t max) { if (i>=fNumPixels) return; // // Fixme: Use absolute value per mm^2. Needs another scaling algorithm. // const Float_t ratio = fGeomCam->GetPixRatio(i); const Float_t pnum = sqrt(ratio)*pix.GetErrorPhot(); (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum, min, max)); } inline void MCamDisplay::SetPixColorRatio(const MCerPhotPix &pix, Float_t min, Float_t max) { // // Fixme: Use absolute value per mm^2. Needs another scaling algorithm. // const Float_t pnum = pix.GetNumPhotons()/pix.GetErrorPhot(); (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum, min, max)); } inline void MCamDisplay::SetPixColorLevel(const MCerPhotPix &pix, Float_t lvl1, Float_t lvl2) { const Int_t maxcolidx = kItemsLegend-1; MHexagon &hex = (*this)[pix.GetPixId()]; const Float_t r = pix.GetNumPhotons()/pix.GetErrorPhot(); if (r>lvl1) hex.SetFillColor(fColors[4*maxcolidx/5]); else if (r>lvl2) hex.SetFillColor(fColors[maxcolidx/2]); else hex.SetFillColor(fColors[maxcolidx/5]); } // ------------------------------------------------------------------------ // // This is called at any time the canvas should get repainted. // Here we maintain an aspect ratio of 5/4=1.15. This makes sure, // that the camera image doesn't get distorted by resizing the canvas. // void MCamDisplay::Paint(Option_t *opt) { const UInt_t w = (UInt_t)(gPad->GetWw()*gPad->GetAbsWNDC()); const UInt_t h = (UInt_t)(gPad->GetWh()*gPad->GetAbsHNDC()); // // Check for a change in width or height, and make sure, that the // first call also sets the range // if (w*fH == h*fW && fW && fH) return; // // Calculate aspect ratio (5/4=1.25 recommended) // const Double_t ratio = (Double_t)w/h; Float_t x; Float_t y; if (ratio>1.25) { x = (ratio*2-1)*fRange; y = fRange; } else { x = fRange*1.5; y = fRange*1.25/ratio; } fH = h; fW = w; // // Set new range // gPad->Range(-fRange, -y, x, y); // // Make sure, that the correct aspect is always displayed also // if - by chance - there is not update for the pad after the // Paint function was called. // gPad->Update(); } // ------------------------------------------------------------------------ // // With this function you can change the color palette. For more // information see TStyle::SetPalette. Only palettes with 50 colors // are allowed. // In addition you can use SetPalette(52, 0) to create an inverse // deep blue sea palette // void MCamDisplay::SetPalette(Int_t ncolors, Int_t *colors) { // // If not enough colors are specified skip this. // if (ncolors>1 && ncolors<50) { cout << "MCamDisplay::SetPalette: Only default palettes with 50 colors are allowed... ignored." << endl; return; } // // If ncolors==52 create a reversed deep blue sea palette // if (ncolors==52) { gStyle->SetPalette(51, NULL); Int_t c[50]; for (int i=0; i<50; i++) c[49-i] = gStyle->GetColorPalette(i); gStyle->SetPalette(50, c); } else gStyle->SetPalette(ncolors, colors); if (fDrawingPad) { // // Set the colors of the legend // for (int i=0; iGetFillColor(); // // Make sure, that the legend is already colored // if (col==10 || col==22) continue; GetBox(i)->SetFillColor(gStyle->GetColorPalette(i)); } // // Change the colors of the pixels // for (unsigned int i=0; iGetColorPalette(idx)); } // // Update the pad on the screen // fDrawingPad->Modified(); fDrawingPad->Update(); } // // Store the color palette used for a leter reverse lookup // for (int i=0; iGetColorPalette(i); } void MCamDisplay::SetPrettyPalette() { SetPalette(1, 0); } void MCamDisplay::SetDeepBlueSeaPalette() { SetPalette(51, 0); } void MCamDisplay::SetInvDeepBlueSeaPalette() { SetPalette(52, 0); } // ------------------------------------------------------------------------ // // Call this function to draw the camera layout into your canvas. // Setup a drawing canvas. Add this object and all child objects // (hexagons, etc) to the current pad. If no pad exists a new one is // created. // void MCamDisplay::Draw(Option_t *option) { // root 3.02: // gPad->SetFixedAspectRatio() if (fDrawingPad) return; // // if no canvas is yet existing to draw into, create a new one // if (!gPad) { fDrawingPad = new TCanvas("CamDisplay", "Magic Camera Display", 0, 0, 750, 600); fIsAllocated = kTRUE; } else { fDrawingPad = gPad; fIsAllocated = kFALSE; } // // Setup the correct environment // fDrawingPad->SetBorderMode(0); fDrawingPad->SetFillColor(22); // // Set the initial coordinate range // Paint(); /* // // Create and draw the buttons which allows changing the // color palette of the display // TButton *but; char txt[100]; sprintf(txt, "((MCamDisplay*)0x%lx)->SetPalette(1,0);", this); but = new TButton("Pretty", txt, 0.01, 0.95, 0.15, 0.99); but->Draw(); sprintf(txt, "((MCamDisplay*)0x%lx)->SetPalette(51,0);", this); but = new TButton("Deap Sea", txt, 0.16, 0.95, 0.30, 0.99); but->Draw(); sprintf(txt, "((MCamDisplay*)0x%lx)->SetPalette(52,0);", this); but = new TButton("Blue Inv", txt, 0.31, 0.95, 0.45, 0.99); but->Draw(); */ // // Draw all pixels of the camera // (means apend all pixelobjects to the current pad) // for (UInt_t i=0; i ROOT_VERSION(3,01,06) (*this)[i].SetBit(/*kNoContextMenu|*/kCannotPick); #endif (*this)[i].SetFillColor(22); (*this)[i].Draw(); } fArrowX->Draw(); fArrowY->Draw(); fLegRadius->Draw(); fLegDegree->Draw(); // // initialize and draw legend // const Float_t H = 0.9*fRange; const Float_t h = 2./kItemsLegend; const Float_t w = fRange/sqrt(fNumPixels); for (Int_t i=0; iSetX1(fRange); box->SetX2(fRange+w); box->SetY1(H*( i *h - 1.)); box->SetY2(H*((i+1)*h - 1.)); box->SetFillColor(22); #if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06) box->SetBit(/*kNoContextMenu|*/kCannotPick); #endif box->Draw(); TText *txt = GetText(i); txt->SetX(fRange+1.5*w); txt->SetY(H*((i+0.5)*h - 1.)); #if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06) txt->SetBit(/*kNoContextMenu|*/kCannotPick); #endif txt->Draw(); } // // Append this object, so that the aspect ratio is maintained // (Paint-function is called) // Add it here so that root will have it first in the internal list: // This means, that root 'sees' the whole camera instead of all the // single hexagons. // AppendPad(option); //fDrawingPad->SetEditable(kFALSE); } void MCamDisplay::DrawPixelNumbers() { if (!fDrawingPad) Draw(); fDrawingPad->cd(); TText txt; txt.SetTextFont(122); txt.SetTextAlign(22); // centered/centered for (UInt_t i=0; iSetTextSize(0.3*h.GetD()/fGeomCam->GetMaxRadius()); } } // ------------------------------------------------------------------------ // // Call this function to draw the number of photo electron into the // camera. // void MCamDisplay::DrawPhotNum(const MCerPhotEvt *event) { if (!event) return; Draw(); fDrawingPad->cd(); for (int i=0; iSetFillColor(fColors[i]); // // Reset pixel colors to default value // Reset(); // // if the autoscale is true, set the values for the range for // each event // Float_t min = 0; Float_t max = 50; if (fAutoScale) { min = event->GetNumPhotonsMin(fGeomCam); max = event->GetNumPhotonsMax(fGeomCam); if (max < 20.) max = 20.; UpdateLegend(min, max); } // // update the colors in the picture // const Int_t entries = event->GetNumPixels(); for (Int_t i=0; iModified(); fDrawingPad->Update(); } // ------------------------------------------------------------------------ // // Call this function to draw the number of photo electron into the // camera. // void MCamDisplay::DrawPedestals(const MPedestalCam *event) { if (!event) return; Draw(); fDrawingPad->cd(); for (int i=0; iSetFillColor(fColors[i]); // // Reset pixel colors to default value // Reset(); // // if the autoscale is true, set the values for the range for // each event // Float_t min = 0; Float_t max = 50; if (fAutoScale) { min = event->GetMeanMin(fGeomCam); max = event->GetMeanMax(fGeomCam); if (max < 20.) max = 20.; UpdateLegend(min, max); } // // update the colors in the picture // const Int_t entries = event->GetSize(); for (Int_t i=0; iModified(); fDrawingPad->Update(); } // ------------------------------------------------------------------------ // // Call this function to draw the error of number of photo electron // into the camera. // void MCamDisplay::DrawErrorPhot(const MCerPhotEvt *event) { if (!event) return; if (!fDrawingPad) Draw(); fDrawingPad->cd(); for (int i=0; iSetFillColor(fColors[i]); // // Reset pixel colors to default value // Reset(); // // if the autoscale is true, set the values for the range for // each event // Float_t min = 0; Float_t max = 50; if (fAutoScale) { min = event->GetErrorPhotMin(fGeomCam); max = event->GetErrorPhotMax(fGeomCam); if (max < 20.) max = 20.; UpdateLegend(min, max); } // // update the colors in the picture // const Int_t entries = event->GetNumPixels(); for (Int_t i=0; iModified(); fDrawingPad->Update(); } // ------------------------------------------------------------------------ // // Call this function to draw the ratio of the number of photons // divided by its error // void MCamDisplay::DrawRatio(const MCerPhotEvt *event) { if (!event) return; if (!fDrawingPad) Draw(); fDrawingPad->cd(); for (int i=0; iSetFillColor(fColors[i]); // // Reset pixel colors to default value // Reset(); // // if the autoscale is true, set the values for the range for // each event // Float_t min = 0; Float_t max = 20; if (fAutoScale) { min = event->GetRatioMin(); max = event->GetRatioMax(); UpdateLegend(min, max); } // // update the colors in the picture // const Int_t entries = event->GetNumPixels(); for (Int_t i=0; iModified(); fDrawingPad->Update(); } // ------------------------------------------------------------------------ // // Draw the colors in respect to the cleaning levels // void MCamDisplay::DrawLevels(const MCerPhotEvt *event, Float_t lvl1, Float_t lvl2) { if (!event) return; if (!fDrawingPad) Draw(); fDrawingPad->cd(); for (int i=0; iSetFillColor(fColors[i]); // // Reset pixel colors to default value // Reset(); // // update the colors in the picture // const Int_t entries = event->GetNumPixels(); for (Int_t i=0; iModified(); fDrawingPad->Update(); } // ------------------------------------------------------------------------ // // Draw the colors in respect to the cleaning levels // void MCamDisplay::DrawLevels(const MCerPhotEvt *event, const MImgCleanStd &clean) { DrawLevels(event, clean.GetCleanLvl1(), clean.GetCleanLvl2()); } // ------------------------------------------------------------------------ // // reset the all pixel colors to a default value // void MCamDisplay::Reset() { for (UInt_t i=0; iSetPalette(1,0) // for the display. So we have to convert the value "wert" into // a color index that fits the color palette. // The range of the color palette is defined by the values fMinPhe // and fMaxRange. Between this values we have 50 color index, starting // with 0 up to 49. // Int_t MCamDisplay::GetColor(Float_t val, Float_t min, Float_t max) { // // first treat the over- and under-flows // const Int_t maxcolidx = kItemsLegend-1; if (val >= max) return fColors[maxcolidx]; if (val <= min) return fColors[0]; // // calculate the color index // const Float_t ratio = (val-min) / (max-min); const Int_t colidx = (Int_t)(ratio*maxcolidx + .5); return fColors[colidx]; } // ------------------------------------------------------------------------ // // change the text on the legend according to the range of the // Display // void MCamDisplay::UpdateLegend(Float_t minphe, Float_t maxphe) { char text[10]; for (Int_t i=0; iClassSaved(TCanvas::Class())) fDrawingPad->SavePrimitive(out, opt); out << " " << fDrawingPad->GetName() << "->SetWindowSize("; out << fDrawingPad->GetWw() << "," << fDrawingPad->GetWh() << ");" << endl; } // ------------------------------------------------------------------------ // // compute the distance of a point (px,py) to the Camera // this functions needed for graphical primitives, that // means without this function you are not able to interact // with the graphical primitive with the mouse!!! // // All calcutations are running in pixel coordinates // Int_t MCamDisplay::DistancetoPrimitive(Int_t px, Int_t py) { Int_t dist = 999999; for (UInt_t i=0; iDistancetoPrimitive(px, py); if (d