/* ======================================================================== *\ ! ! * ! * 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, 10/2001 ! ! Copyright: MAGIC Software Development, 2000-2003 ! ! \* ======================================================================== */ #include "MEventDisplay.h" // // C-lib // #include // atoi // // root // #include // TFile #include // TTree #include // TList::Add #include // gStyle->SetOptStat #include // TCanvas::cd #include // TSystem::BaseName // // root GUI // #include // TGLabel #include // TGPictureButton #include // TGHorizontal3DLine #include // TGTextEntry #include // TGVButtonGroup #include // TRootEmbeddedCanvas // // General // #include "MGList.h" // MGList #include "MLog.h" #include "MLogManip.h" #include "MParList.h" // MParList::AddToList #include "MEvtLoop.h" // MEvtLoop::GetParList #include "MTaskList.h" // MTaskList::AddToList // // Tasks // #include "MReadMarsFile.h" // MReadMarsFile #include "MGeomApply.h" // MGeomApply #include "MFDataMember.h" // MFDataMember #include "MMcPedestalCopy.h" // MMcPedestalCopy #include "MMcPedestalNSBAdd.h" // MMcPedestalNSBAdd #include "MCerPhotAnal2.h" // MCerPhotAnal2 #include "MImgCleanStd.h" // MImgCleanStd #include "MHillasCalc.h" // MHillasCalc //#include "MHillasSrcCalc.h" // MHillasSrcCalc //#include "MBlindPixelCalc.h" // MBlindPixelCalc #include "MArrivalTimeCalc.h" // MArrivalTimeCalc #include "MFillH.h" // MFillH #include "MExtractSignal.h" // MExtractsignal #include "MMcCalibrationUpdate.h" // MMcCalibrationUpdate #include "MCalibrate.h" // MCalibrate #include "MMcTriggerLvl2Calc.h" // MMcTriggerLvl2Calc // // Container // #include "MHillas.h" // MHillas::Print(const MGeomCam&) #include "MHillasExt.h" // MHillasExt::Print(const MGeomCam&) #include "MHillasSrc.h" // MHillasSrc::Print(const MGeomCam&) #include "MImagePar.h" // MImagePar::Print(const MGeomCam&) #include "MNewImagePar.h" // MNewImagePar::Print(const MGeomCam&) #include "MHEvent.h" // MHEvent #include "MHCamera.h" // MHCamera #include "MRawEvtData.h" // MRawEvtData #include "MArrivalTimeCam.h" // MArrivalTimeCam #include "MBadPixelsCam.h" // MBadPixelsCam #include "MPedPhotCam.h" // MPedPhotCam #include "MCalibrationChargeCam.h" // MCalibrationChargeCam #include "MMcTriggerLvl2.h" // MMcTriggerLvl2 using namespace std; ClassImp(MEventDisplay); // -------------------------------------------------------------------------- // // Constructor. // MEventDisplay::MEventDisplay(const char *fname, const char *pname, const char *cname) : MStatusDisplay(), fEvtLoop(0) { // // Setup Task list for hillas calculation // SetupTaskList("Events", fname, pname, cname); // // Add MEventDisplay GUI elements to the display // AddUserFrame(fname); // // Show new part of the window, resize to correct aspect ratio // // FIXME: This should be done by MStatusDisplay automatically Resize(GetWidth(), GetHeight() + fUserFrame->GetDefaultHeight()); SetWindowName("Event Display"); MapSubwindows(); // // Readin first event and display it // if (fEvtLoop) ReadFirstEvent(); SetNoContextMenu(kFALSE); } // -------------------------------------------------------------------------- // // Destructor: PostProcess eventloop, delete eventloop with all containers // MEventDisplay::~MEventDisplay() { if (fEvtLoop) { fEvtLoop->PostProcess(); delete fEvtLoop; } } Int_t MEventDisplay::GetFileType(const char *tree, const char *fname) const { TFile f(fname, "READ"); TTree *t = (TTree*)f.Get(tree); if (!t) return -1; if (t->FindBranch("MCerPhotEvt.")) return 1; if (t->FindBranch("MRawEvtData.")) return 2; return -2; } // -------------------------------------------------------------------------- // // Setup Task and parameter list for hillas calculation, // preprocess tasks and read in first event (process) // void MEventDisplay::SetupTaskList(const char *tname, const char *fname, const char *pname, const char *cname) { MCalibrationChargeCam *ccam=0; MPedPhotCam *pcam=0; MBadPixelsCam *badpix = new MBadPixelsCam; const Int_t type = GetFileType(tname, fname); switch (type) { case 1: gLog << all << "Calibrated Data File detected..." << endl; break; case 2: gLog << all << "Raw Data File detected..." << endl; break; case -2: gLog << err << "File type unknown... abort." << endl; return; case -1: gLog << err << "Tree " << tname << " not found... abort." << endl; return; } if (type==2) { TFile file(pname, "READ"); if (!file.IsZombie()) pcam = new MPedPhotCam; if (pcam) { if (pcam->Read()<=0) { delete pcam; pcam = NULL; } if (file.FindKey("MBadPixelsCam")) { MBadPixelsCam bad; if (bad.Read()>0) badpix->Merge(bad); } } file.Close(); file.Open(cname, "READ"); if (!file.IsZombie()) ccam = new MCalibrationChargeCam; if (ccam) { if (ccam->Read()<=0) { delete ccam; ccam = NULL; } if (file.FindKey("MBadPixelsCam")) { MBadPixelsCam bad; if (bad.Read()>0) badpix->Merge(bad); } } file.Close(); } // // Setup an empty job, with a reader task only. // All tasks and parameter containers are deleted automatically // (via SetOwner()) // MTaskList *tlist = new MTaskList; tlist->SetOwner(); MReadMarsFile *read = new MReadMarsFile(tname, fname); read->DisableAutoScheme(); tlist->AddToList(read); MGeomApply *apl = new MGeomApply; tlist->AddToList(apl); MParList *plist = new MParList; plist->SetOwner(); plist->AddToList(tlist); plist->AddToList(badpix); if (pcam) plist->AddToList(pcam); if (ccam) plist->AddToList(ccam); //MArrivalTime *atime = new MArrivalTime; //plist->AddToList(atime); MHEvent *evt01 = new MHEvent(MHEvent::kEvtSignalRaw); MHEvent *evt02 = new MHEvent(MHEvent::kEvtSignalRaw); MHEvent *evt03 = new MHEvent(MHEvent::kEvtPedestal); MHEvent *evt04 = new MHEvent(MHEvent::kEvtPedestalRMS); MHEvent *evt06a= new MHEvent(MHEvent::kEvtCleaningData); MHEvent *evt06b= new MHEvent(MHEvent::kEvtCleaningLevels); MHEvent *evt07 = new MHEvent(MHEvent::kEvtIdxMax); MHEvent *evt08 = new MHEvent(MHEvent::kEvtArrTime); MHEvent *evt09 = new MHEvent(MHEvent::kEvtTrigPix); MHEvent *evt10 = new MHEvent(MHEvent::kEvtIslandIndex); evt01->SetName("Signal"); evt02->SetName("Cleaned"); evt03->SetName("Pedestal"); evt04->SetName("PedRMS"); evt06a->SetName("CleanData"); evt06b->SetName("CleanLevels"); evt07->SetName("Max Slice Idx"); evt08->SetName("Arrival Time"); evt09->SetName("Trigger"); evt10->SetName("Islands"); // This makes sure, that the containers are deleted... plist->AddToList(evt01); plist->AddToList(evt02); plist->AddToList(evt03); plist->AddToList(evt04); plist->AddToList(evt06a); plist->AddToList(evt06b); plist->AddToList(evt07); plist->AddToList(evt08); plist->AddToList(evt09); plist->AddToList(evt10); MCerPhotAnal2 *nanal = new MCerPhotAnal2; MFillH *fill01 = new MFillH(evt01, "MCerPhotEvt", "MFillH01"); MImgCleanStd *clean = new MImgCleanStd; MFillH *fill02 = new MFillH(evt02, "MCerPhotEvt", "MFillH02"); MFillH *fill03 = new MFillH(evt03, "MPedPhotCam", "MFillH03"); MFillH *fill04 = new MFillH(evt04, "MPedPhotCam", "MFillH04"); MFillH *fill06a= new MFillH(evt06a, "MCameraData", "MFillH06a"); MFillH *fill06b= new MFillH(evt06b, "MCameraData", "MFillH06b"); //MBlindPixelCalc *blind = new MBlindPixelCalc; MHillasCalc *hcalc = new MHillasCalc; MMcTriggerLvl2Calc *trcal = new MMcTriggerLvl2Calc; MFillH *fill09 = new MFillH(evt09, "MMcTriggerLvl2", "MFillH09"); MFillH *fill10 = new MFillH(evt10, "MCerPhotEvt", "MFillH10"); // If no pedestal or no calibration file is availble if (type==2) { if (!pcam || !ccam) { MFilter *f1=new MFDataMember("MRawRunHeader.fRunType", '>', 255.5); MFilter *f2=new MFDataMember("MRawRunHeader.fRunType", '<', 255.5); f1->SetName("MFMonteCarlo"); f2->SetName("MFRealData"); MMcPedestalCopy *pcopy = new MMcPedestalCopy; MMcPedestalNSBAdd *pdnsb = new MMcPedestalNSBAdd; MExtractSignal* extra = new MExtractSignal(); extra->SetRange(0, 14, 0, 14); extra->SetSaturationLimit(240); MMcCalibrationUpdate* mcupd = new MMcCalibrationUpdate; mcupd->SetOuterPixelsGainScaling(kFALSE); MCalibrate* mccal = new MCalibrate; mccal->SetCalibrationMode(MCalibrate::kFfactor); // MC extra->SetFilter(f1); mcupd->SetFilter(f1); mccal->SetFilter(f1); trcal->SetFilter(f1); //fill09->SetFilter(f1); // Data nanal->SetFilter(f2); // TaskList tlist->AddToList(f1); tlist->AddToList(f2); tlist->AddToList(pcopy); tlist->AddToList(pdnsb); tlist->AddToList(extra); tlist->AddToList(mcupd); tlist->AddToList(mccal); tlist->AddToList(nanal); } else { MCalibrate* calib = new MCalibrate; tlist->AddToList(calib); } } tlist->AddToList(fill01); tlist->AddToList(clean); tlist->AddToList(fill02); tlist->AddToList(fill03); tlist->AddToList(fill04); tlist->AddToList(fill06a); tlist->AddToList(fill06b); //tlist->AddToList(blind); tlist->AddToList(fill10); tlist->AddToList(hcalc); if ((!pcam || !ccam) && type==2) { MArrivalTimeCalc *tcalc = new MArrivalTimeCalc; MFillH *fill07 = new MFillH(evt07, "MRawEvtData", "MFillH7"); MFillH *fill08 = new MFillH(evt08, "MArrivalTimeCam", "MFillH8"); tlist->AddToList(tcalc); tlist->AddToList(fill07); tlist->AddToList(fill08); tlist->AddToList(trcal); tlist->AddToList(fill09); } if (type==1) { MFillH *fill08 = new MFillH(evt08, "MArrivalTime", "MFillH8"); tlist->AddToList(fill08); } // // Now distribute Display to all tasks // fEvtLoop = new MEvtLoop(Form("Mars %s", gSystem->BaseName(fname))); fEvtLoop->SetOwner(); fEvtLoop->SetParList(plist); fEvtLoop->SetDisplay(this); fEvtLoop->ReadEnv("mars.rc"); } // -------------------------------------------------------------------------- // // Add the top part of the frame: This is filename and treename display // void MEventDisplay::AddTopFramePart1(TGCompositeFrame *frame, const char *filename, const char *treename) { // // --- the top1 part of the window --- // TGHorizontalFrame *top1 = new TGHorizontalFrame(frame, 1, 1); fList->Add(top1); // // create gui elements // TGLabel *file = new TGLabel(top1, new TGString(Form("%s#%s", filename, treename))); fList->Add(file); // // layout and add gui elements in/to frame // TGLayoutHints *laystd = new TGLayoutHints(kLHintsCenterX, 5, 5); fList->Add(laystd); top1->AddFrame(file, laystd); // // --- the top1 part of the window --- // TGHorizontalFrame *top2 = new TGHorizontalFrame(frame, 1, 1); fList->Add(top2); // // layout and add frames // TGLayoutHints *laytop1 = new TGLayoutHints(kLHintsCenterX, 5, 5, 5); fList->Add(laytop1); frame->AddFrame(top1, laytop1); frame->AddFrame(top2, laytop1); } // -------------------------------------------------------------------------- // // Add the second part of the top frame: This are the event number controls // void MEventDisplay::AddTopFramePart2(TGCompositeFrame *frame) { // // --- the top2 part of the window --- // TGHorizontalFrame *top2 = new TGHorizontalFrame(frame, 1, 1); fList->Add(top2); // // Create the gui elements // TGTextButton *prevevt = new TGTextButton(top2, " << ", kEvtPrev); prevevt->Associate(this); TGLabel *evtnr = new TGLabel(top2, new TGString("Event:")); TGTextEntry *entry=new TGTextEntry(top2, new TGTextBuffer(100), kEvtNumber); entry->Resize(60, entry->GetDefaultHeight()); entry->Associate(this); fNumOfEvts = new TGLabel(top2, "of ."); TGTextButton *nextevt = new TGTextButton (top2, " >> ", kEvtNext); nextevt->Associate(this); // // Add gui elements to 'atotodel' // fList->Add(prevevt); fList->Add(evtnr); fList->Add(entry); fList->Add(fNumOfEvts); fList->Add(nextevt); // // add the gui elements to the frame // TGLayoutHints *laystd = new TGLayoutHints(kLHintsLeft|kLHintsCenterY, 5, 5); fList->Add(laystd); top2->AddFrame(prevevt, laystd); top2->AddFrame(evtnr, laystd); top2->AddFrame(entry, laystd); top2->AddFrame(fNumOfEvts, laystd); top2->AddFrame(nextevt, laystd); TGLayoutHints *laystd2 = new TGLayoutHints(kLHintsCenterX, 5, 5, 5, 5); fList->Add(laystd2); frame->AddFrame(top2, laystd2); // // Add trailing line... // TGHorizontal3DLine *line = new TGHorizontal3DLine(frame); TGLayoutHints *layline = new TGLayoutHints(kLHintsExpandX); fList->Add(line); fList->Add(layline); frame->AddFrame(line, layline); } // -------------------------------------------------------------------------- // // Add the user frame part of the display // void MEventDisplay::AddUserFrame(const char* filename) { fUserFrame->ChangeOptions(kHorizontalFrame); TGCompositeFrame *vf1 = new TGVerticalFrame(fUserFrame, 1, 1); TGCompositeFrame *vf2 = new TGVerticalFrame(fUserFrame, 1, 1); AddTopFramePart1(vf1, filename, "Events"); AddTopFramePart2(vf1); // create root embedded canvas and add it to the tab TRootEmbeddedCanvas *ec = new TRootEmbeddedCanvas("Slices", vf2, vf1->GetDefaultHeight()*3/2, vf1->GetDefaultHeight(), 0); vf2->AddFrame(ec); fList->Add(ec); // set background and border mode of the canvas fCanvas = ec->GetCanvas(); fCanvas->SetBorderMode(0); gROOT->GetListOfCanvases()->Add(fCanvas); //fCanvas->SetBorderSize(1); //fCanvas->SetBit(kNoContextMenu); //fCanvas->SetFillColor(16); TGLayoutHints *lay = new TGLayoutHints(kLHintsExpandX); fUserFrame->AddFrame(vf1, lay); fUserFrame->AddFrame(vf2); } // -------------------------------------------------------------------------- // // Checks if the event number is valid, and if so reads the new event // and updates the display // void MEventDisplay::ReadinEvent(Int_t dir) { MParList *plist = (MParList*) fEvtLoop->GetParList(); MTaskList *tlist = (MTaskList*) fEvtLoop->GetTaskList(); MGeomCam *geom = (MGeomCam*) plist->FindObject("MGeomCam"); MRawEvtData *raw = (MRawEvtData*)plist->FindObject("MRawEvtData"); // // Read first event. // MReadTree *reader = (MReadTree*)fEvtLoop->FindTask("MRead"); const Int_t num = reader->GetNumEntry(); do { if (dir<0 && !reader->DecEventNum()) { reader->SetEventNum(num); return; } if (dir>0 && !reader->IncEventNum()) { reader->SetEventNum(num); return; } if (!tlist->Process()) return; reader->DecEventNum(); } while (raw && raw->GetNumPixels()<1 && dir!=0); // // Cleare the 'FADC canvas' // fCanvas->Clear(); fCanvas->Modified(); fCanvas->Update(); // // Print parameters // ((MHillas*) plist->FindObject("MHillas"))->Print(*geom); ((MHillasExt*) plist->FindObject("MHillasExt"))->Print(*geom); ((MHillasSrc*) plist->FindObject("MHillasSrc"))->Print(*geom); plist->FindObject("MImagePar")->Print(); ((MNewImagePar*)plist->FindObject("MNewImagePar"))->Print(*geom); // // UpdateDisplay // gStyle->SetOptStat(1101); Update(); TGTextEntry *entry = (TGTextEntry*)fList->FindWidget(kEvtNumber); entry->SetText(Form("%d", reader->GetNumEntry()+1)); } // -------------------------------------------------------------------------- // // Read first event to get display booted // void MEventDisplay::ReadFirstEvent() { if (!fEvtLoop->PreProcess()) return; UnLock(); // // Get parlist // MParList *plist = (MParList*)fEvtLoop->GetParList(); // // Add Geometry tab // AddGeometryTabs(); // // Now read event... // ReadinEvent(); MReadTree *reader = (MReadTree*)fEvtLoop->FindTask("MRead"); TGString *txt = new TGString(Form("of %d", reader->GetEntries())); fNumOfEvts->SetText(txt); // // Draw ellipse on top of all pads // TObject *hillas1 = plist->FindObject("MHillas"); TObject *hillas2 = plist->FindObject("MHillasSrc"); for (int i=1; i<7;i++) { TCanvas *c = GetCanvas(i); c->GetPad(1)->cd(1); hillas1->Draw(); hillas2->Draw(); } } // -------------------------------------------------------------------------- // // Adds the geometry tab // void MEventDisplay::AddGeometryTabs() { MGeomCam *geom = (MGeomCam*)fEvtLoop->GetParList()->FindObject("MGeomCam"); if (!geom) return; TCanvas &c1=AddTab("Geometry"); MHCamera *cam = new MHCamera(*geom); cam->SetBit(TH1::kNoStats|MHCamera::kNoLegend|kCanDelete); cam->Draw("pixelindex"); c1.Modified(); c1.Update(); TCanvas &c2=AddTab("Sectors"); cam = new MHCamera(*geom); cam->SetBit(TH1::kNoStats|MHCamera::kNoLegend|kCanDelete); cam->Draw("sectorindex"); c2.Modified(); c2.Update(); } // -------------------------------------------------------------------------- // // ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2) // // Processes information from all GUI items. // Selecting an item usually generates an event with 4 parameters. // The first two are packed into msg (first and second bytes). // The other two are parm1 and parm2. // Bool_t MEventDisplay::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2) { switch (GET_MSG(msg)) { case kC_TEXTENTRY: switch(GET_SUBMSG(msg)) { case kTE_ENTER: switch(GET_SUBMSG(msg)) { case kTE_ENTER: { TGTextEntry *entry = (TGTextEntry*)fList->FindWidget(kEvtNumber); MReadTree *reader = (MReadTree*)fEvtLoop->FindTask("MRead"); if (reader->SetEventNum(atoi(entry->GetText())-1)) ReadinEvent(); } return kTRUE; } return kTRUE; } break; case kC_COMMAND: switch (GET_SUBMSG(msg)) { case kCM_TAB: { // // Set name for 'FADC canvas'. The name is the anchor for MHCamera. // and clear the canvas TCanvas *c = GetCanvas(mp1); if (!c) break; MHEvent *o = (MHEvent*)fEvtLoop->GetParList()->FindObject(c->GetName()); if (!o) break; fCanvas->SetName(Form("%p;%p;PixelContent", o->GetHist(), c->GetPad(1)->GetPad(1))); } break; case kCM_BUTTON: switch (mp1) { case kEvtPrev: ReadinEvent(-1); return kTRUE; case kEvtNext: ReadinEvent(+1); return kTRUE; } return kTRUE; } break; } return MStatusDisplay::ProcessMessage(msg, mp1, mp2); }