// $Id$ //----------------------------------------------------------------------- // The GSI Online Offline Object Oriented (Go4) Project // Experiment Data Processing at EE department, GSI //----------------------------------------------------------------------- // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH // Planckstr. 1, 64291 Darmstadt, Germany // Contact: http://go4.gsi.de //----------------------------------------------------------------------- // This software can be used under the license agreements as stated // in Go4License.txt file which is part of the distribution. //----------------------------------------------------------------------- #include "TGo4PolyCond.h" #include "RVersion.h" #include "TMath.h" #include "TROOT.h" #include "TH2.h" #include "TList.h" #include "TCutG.h" #include "TGo4PolyCondPainter.h" #include "TGo4Log.h" /** JAM2016: this define switches between cloning when updating condition * and simple copy of TCutG points*/ //#define POLYCOND_UPDATE_WITHCLONE 1 TString TGo4PolyCond::fgxURL_NPOINTS="npolygon"; TString TGo4PolyCond::fgxURL_XPRE="x"; TString TGo4PolyCond::fgxURL_YPRE="y"; TString TGo4PolyCond::NextAvailableName() { TString res; Int_t cnt = 0; do { res.Form("CutG_%d",cnt++); } while (gROOT->GetListOfSpecials()->FindObject(res)!=0); return res; } // ---------------------------------------------------------- TGo4PolyCond::TGo4PolyCond() : TGo4Condition(), fxCut(0), fxCutHis(0) { SetDimension(2); //SetBit(kCanDelete, kFALSE); //std::cout <<"TGo4PolyCond default ctor, this="<<(long) this <<", threadid="<< (long) pthread_self()<GetCut(false); // get fxCut pointer //std::cout <<"TGo4PolyCond "<<(long) this <<" CloneCut "<< (long) tempcut<<"from polycond "<< (long) source << std::endl; if(tempcut) { CleanupSpecials(); // JAM2016: Clone might delete cut of same name from list of specials, remove it first TCutG* ret= (TCutG *)tempcut->Clone(GetName()); CleanupSpecials(); return ret; } return 0; } // ---------------------------------------------------------- void TGo4PolyCond::SetValues(TCutG * newcut) { if(newcut==0) return; #ifdef POLYCOND_UPDATE_WITHCLONE if(fxCut!=0) delete fxCut; CleanupSpecials(); // JAM2016: Clone might delete cut of same name from list of specials, remove it first //fxCut = (TCutG*) newcut->Clone(NextAvailableName()); fxCut = (TCutG*) newcut->Clone(GetName()); fxCut->SetBit(kCanDelete,kFALSE); CleanupSpecials(); #else Int_t pn = newcut->GetN(); if(fxCut==0) { fxCut = new TCutG(GetName(),pn); fxCut->SetBit(kMustCleanup); TGo4PolyCond::CleanupSpecials(); // JAM2016 } else { fxCut->Set(pn); } Double_t xp=0; Double_t yp=0; for(Int_t i=0; iGetPoint(i,xp,yp); fxCut->SetPoint(i,xp,yp); } #endif // when updated from view, we store graphical attributes: SetLineColor(newcut->GetLineColor()); SetLineWidth(newcut->GetLineWidth()); SetLineStyle(newcut->GetLineStyle()); SetFillColor(newcut->GetFillColor()); SetFillStyle(newcut->GetFillStyle()); ClearCutHis(); // fxCut changed, so discard previous fxCut histogram } // ---------------------------------------------------------- void TGo4PolyCond::SetValuesDirect(TCutG * newcut) { if(newcut==0) return; if(fxCut!=0 && fxCut!=newcut) delete fxCut; fxCut = newcut; //fxCut->SetName(NextAvailableName()); // JAM2016 fxCut->SetName(GetName()); // when updated from view, we store graphical attributes: SetLineColor(newcut->GetLineColor()); SetLineWidth(newcut->GetLineWidth()); SetLineStyle(newcut->GetLineStyle()); SetFillColor(newcut->GetFillColor()); SetFillStyle(newcut->GetFillStyle()); ClearCutHis(); // fxCut changed, so discard previous fxCut histogram } // ---------------------------------------------------------- void TGo4PolyCond::SetValues(Double_t * x, Double_t * y, Int_t len) { if(fxCut != 0) delete fxCut; TGo4PolyCond::CleanupSpecials(); // JAM2016 //fxCut = new TCutG(NextAvailableName(), len, x, y); fxCut = new TCutG(GetName(), len, x, y); fxCut->SetBit(kMustCleanup); //fxCut->SetBit(kCanDelete,kFALSE); TGo4PolyCond::CleanupSpecials(); // JAM2016 ClearCutHis(); // discard previous fxCut histogram } // ---------------------------------------------------------- Bool_t TGo4PolyCond::Test(Double_t x, Double_t y) { IncCounts(); if((!IsEnabled()) || (fxCut == 0)){ if(FixedResult()) IncTrueCounts(); return FixedResult(); } Bool_t outside = (fxCut->IsInside(x,y) == 0); if(outside) return IsFalse(); IncTrueCounts(); return IsTrue(); } // ---------------------------------------------------------- void TGo4PolyCond::PrintCondition(Bool_t points) { TGo4Condition::PrintCondition(); if(points) { if(fxCut == 0) std::cout << "No polygon specified!" << std::endl; else fxCut->Print(0); } } // ----------------------------------------------- // PrintBar switch is handled in condition baseclass now. //void TGo4PolyCond::Print(Option_t* opt) const{ //// this trick is needed since root defines Print as const function... // TGo4PolyCond* const localthis= const_cast(this); // localthis->PrintBar(); //} // ---------------------------------------------------------- Bool_t TGo4PolyCond::UpdateFrom(TGo4Condition * cond, Bool_t counts) { if(!TGo4Condition::UpdateFrom(cond,counts)) return kFALSE; if(cond->InheritsFrom(TGo4PolyCond::Class())) { #ifdef POLYCOND_UPDATE_WITHCLONE TCutG * temp = CloneCut((TGo4PolyCond*)cond); // get clone from source, still valid there! CleanupSpecials(); // remove all references to cloned TCutG from list of specials //std::cout << "Update " << GetName() << " from " << temp << std::endl; if(temp != 0) { TCutG* old=fxCut; // JAM2016 change cut before deleting the old one! fxCut=temp; if(old != 0) delete old; ClearCutHis(); return kTRUE; } else { return kFALSE; } #else /* JAM2016: try to avoid streaming the cut multiple times when updating condition:*/ TGo4PolyCond* source=(TGo4PolyCond*)cond; TCutG * srccut = source->GetCut(false); //std::cout << "TGo4PolyCond::UpdateFrom without Clone of" << GetName() << ", srccut="<<(long )srccut<<", fxCut="<< (long)fxCut << std::endl; if(srccut==0) return kFALSE; CleanupSpecials(); // redundant? do it to get rid of entries from streamer!? Int_t pn = srccut->GetN(); fxCut->Set(pn); Double_t xp=0; Double_t yp=0; for(Int_t i=0; iGetPoint(i,xp,yp); fxCut->SetPoint(i,xp,yp); } // still need this to reassign the bins of statistics histogram: ClearCutHis(); return kTRUE; #endif } else { std::cout << "Cannot update " << GetName() << " from " << cond->ClassName() << std::endl; return kFALSE; } } Bool_t TGo4PolyCond::UpdateFromUrl(const char* rest_url_opt) { if(!TGo4Condition::UpdateFromUrl(rest_url_opt)) return kFALSE; TString message; message.Form("TGo4PolyCond::UpdateFromUrl - condition %s: with url:%s", GetName(), rest_url_opt); TGo4Log::Message(1,message.Data()); // evaluate options that change array of points if (UrlOptionHasKey(TGo4PolyCond::fgxURL_NPOINTS)) { Int_t npoints = GetUrlOptionAsInt(TGo4PolyCond::fgxURL_NPOINTS, -1); if(npoints>=0) { TString xname,yname; Double_t* X = new Double_t[npoints]; Double_t* Y = new Double_t[npoints]; for(Int_t i=0; i= ROOT_VERSION(5,25,1) return (fxCut->IntegralHist(dynamic_cast(histo),opt)); #else return (fxCut->Integral(dynamic_cast(histo),opt)); #endif return 0; } Double_t TGo4PolyCond::GetMean(TH1* histo, Int_t axis) { if (IsCutHis(histo)) return fxCutHis->GetMean(axis); return -1; } Double_t TGo4PolyCond::GetRMS(TH1* histo, Int_t axis) { if (IsCutHis(histo)) return fxCutHis->GetRMS(axis); return -1; } Double_t TGo4PolyCond::GetSkewness(TH1* histo, Int_t axis) { if (IsCutHis(histo)) return fxCutHis->GetSkewness(axis); return -1; } Double_t TGo4PolyCond::GetCurtosis(TH1* histo, Int_t axis) { if (IsCutHis(histo)) return fxCutHis->GetKurtosis(axis); return -1; } Double_t TGo4PolyCond::GetXMax(TH1* histo) { if (IsCutHis(histo)) { TAxis *xax = fxCutHis->GetXaxis(); Int_t maxbin = fxCutHis->GetMaximumBin(); Int_t xmaxbin = maxbin % (fxCutHis->GetNbinsX() + 2); return xax->GetBinCenter(xmaxbin); } return -1; } Double_t TGo4PolyCond::GetYMax(TH1* histo) { if (IsCutHis(histo)) { TAxis *yax = fxCutHis->GetYaxis(); Int_t maxbin = fxCutHis->GetMaximumBin(); Int_t maxybin = maxbin / (fxCutHis->GetNbinsX() + 2); return yax->GetBinCenter(maxybin); } return -1; } Double_t TGo4PolyCond::GetCMax(TH1* histo) { if (IsCutHis(histo)) return fxCutHis->GetMaximum(); return -1; } void TGo4PolyCond::SetPainter(TGo4ConditionPainter* painter) { if (painter == 0) return; if (painter->InheritsFrom(TGo4PolyCondPainter::Class())) { if (fxPainter) delete fxPainter; fxPainter = painter; fxPainter->SetCondition(this); } else { TGo4Log::Warn("Could not set painter of class %s for TGo4PolyCond %s", painter->ClassName(), GetName()); } } TGo4ConditionPainter* TGo4PolyCond::CreatePainter() { TGo4ConditionPainter* painter=new TGo4PolyCondPainter(GetName()); painter->SetCondition(this); //std::cout<<"TGo4PolyCond::CreatePainter() creates new painter"<< (long) painter<< std::endl; return painter; } Bool_t TGo4PolyCond::IsCutHis(TH1* source) { if (fxCutHis) return kTRUE; TH2 *his = dynamic_cast(source); if (!his) return kFALSE; fxCutHis = (TH2 *) his->Clone(); Int_t nx = fxCutHis->GetNbinsX(); Int_t ny = fxCutHis->GetNbinsY(); TAxis *xaxis = fxCutHis->GetXaxis(); TAxis *yaxis = fxCutHis->GetYaxis(); xaxis->SetRange(0, 0); // expand work histogram to full range yaxis->SetRange(0, 0); // set all bins outside fxCut to zero: for (Int_t i = 0; i < nx; ++i) { Double_t x = xaxis->GetBinCenter(i); for (Int_t j = 0; j < ny; ++j) { Double_t y = yaxis->GetBinCenter(j); if (fxCut && !(fxCut->IsInside(x, y))) fxCutHis->SetBinContent(i, j, 0); } } // prepare statistics: Stat_t s[11] = {0}; // dimension is kNstat of TH1.cxx fxCutHis->PutStats(s); // reset previous stats fxCutHis->GetStats(s); // recalculate fxCutHis->PutStats(s); // put back fxCutHis->SetDirectory(0); // important for first draw from marker setup file! return kTRUE; } // ---------------------------------------------------------- void TGo4PolyCond::CleanupSpecials() { //std::cout<<"TGo4PolyCond::CleanupSpecials()..."<< std::endl; TSeqCollection* specials=gROOT->GetListOfSpecials(); TIter iter(specials); TObject* ob=0; while((ob = iter())!=0) { if(ob->InheritsFrom(TCutG::Class())) { specials->Remove(ob); //std::cout <<">>>>>>>>>> removed fxCut" << (long) ob<<" :" << ob->GetName() <<" from list of specials "<< std::endl; } }//while } Int_t TGo4PolyCond::GetMemorySize() { Int_t size = sizeof(*this); if (GetName()!=0) size+=strlen(GetName()); if (GetTitle()!=0) size+=strlen(GetTitle()); if (fxCut!=0) { size += sizeof(*fxCut); #if ROOT_VERSION_CODE > ROOT_VERSION(4,0,8) size += fxCut->GetMaxSize()*2*sizeof(Double_t); #else size += fxCut->GetN()*2*sizeof(Double_t); #endif } return size; } void TGo4PolyCond::SavePrimitive(std::ostream& out, Option_t* opt) { static int cnt = 0; TString line, varname = MakeScript(out, Form("polycond%d", cnt++), opt); if ((fxCut==0) || (fxCut->GetN()==0)) line.Form(" %s->SetValues(0, 0, 0);", varname.Data()); else { TString xname = varname; xname.ReplaceAll("->At(","_sub"); xname.ReplaceAll(")",""); TString yname = xname + "_y"; xname = xname + "_x"; line.Form(" Double_t %s[%d], %s[%d];", xname.Data(), fxCut->GetN(), yname.Data(), fxCut->GetN()); out << line << std::endl; for (Int_t n=0;nGetN();n++) { Double_t x,y; fxCut->GetPoint(n, x, y); line.Form(" %s[%d] = %f; %s[%d] = %f;", xname.Data(), n, x, yname.Data(), n, y); out << line << std::endl; } line.Form(" %s->SetValues(%s, %s, %d);", varname.Data(), xname.Data(), yname.Data(), fxCut->GetN()); } out << line << std::endl; }