//________________________________________________________________ void KVZALineFinder::FindZLine(Int_t zz) { fLinearHisto->SetAxisRange(zz-0.5,zz+0.5,"Y"); KVIDLine* line = (KVIDLine*)fGrid->GetIdentifier(zz,2*zz+1); // A=2*zz+1 : dummy, A is ignored in this case if(!line) { int i=1; while(!(line = (KVIDLine*)fGrid->GetIdentifier(zz+i,2*zz+1))) i++; } if(!line) return; Double_t lX, lY; line->GetStartPoint(lX,lY); Int_t xbmin = 1; line->GetEndPoint(lX,lY); Int_t xbmax = fLinearHisto->GetXaxis()->FindBin(lX); Int_t width = (Int_t)((xbmax-xbmin)*1.0/100.); Int_t widthmax = (Int_t)((xbmax-xbmin)*1.0/30.); KVIDZALine* TheLine = 0; TheLine = (KVIDZALine*)((KVIDZAGrid*)fGeneratedGrid)->NewLine("ID"); TheLine->SetZ(zz); TheLine->SetA(fAList.at(zz-1)); TH1* projey = 0; Int_t i=0; Double_t lasty = zz; for(int xx=xbmin; xx<xbmax; xx+=width) { projey = fLinearHisto->ProjectionY("ProjectionAfterLin",TMath::Max(xx-width/2,xbmin),xx+width/2); Double_t xline = fLinearHisto->GetBinCenter(xx); Double_t yline = projey->GetMean(); if((yline>zz-0.5)&&(yline<zz+0.5)) { if(i==0) lasty = yline; if(TMath::Abs(yline-lasty)<0.2) { TheLine->SetPoint(i, xline, yline); lasty = yline; i++; if(width<widthmax) width*=1.2; } } delete projey; } if(TheLine->GetN()>5) fGeneratedGrid->Add("ID",TheLine); }
//_____________________________________________________________________________________________________// KVIDGrid* KVIDTelescope::CalculateDeltaE_EGrid(TH2* haa_zz, Bool_t Zonly, Int_t npoints) { //Genere une grille dE-E (perte d'energie - energie residuelle) //Le calcul est fait pour chaque couple comptant de charge (Z) et masse (A) //au moins un coup dans l'histogramme haa_zz definit : // Axe X -> Z // Axe Y -> A // //- Si Zonly=kTRUE (kFALSE par defaut), pour un Z donne, le A choisi est la valeur entiere la //plus proche de la valeur moyenne <A> //- Si Zonly=kFALSE et que pour un Z donne il n'y a qu'un seul A associe, les lignes correspondants //a A-1 et A+1 sont ajoutes //- Si a un Z donne, il n'y a aucun A, pas de ligne tracee //un noyau de A et Z donne n'est considere que s'il retourne KVNucleus::IsKnown() = kTRUE // // Warning : the grid is not added to the list of the telescope and MUST BE DELETED by the user ! if (GetSize() <= 1) return 0; TClass* cl = new TClass(GetDefaultIDGridClass()); KVIDGrid* idgrid = (KVIDGrid*)cl->New(); delete cl; idgrid->AddIDTelescope(this); idgrid->SetOnlyZId(Zonly); KVDetector* det_de = GetDetector(1); if (!det_de) return 0; KVDetector* det_eres = GetDetector(2); if (!det_eres) return 0; KVNucleus part; Info("CalculateDeltaE_EGrid", "Calculating dE-E grid: dE detector = %s, E detector = %s", det_de->GetName(), det_eres->GetName()); KVIDCutLine* B_line = (KVIDCutLine*)idgrid->Add("OK", "KVIDCutLine"); Int_t npoi_bragg = 0; B_line->SetName("Bragg_line"); B_line->SetAcceptedDirection("right"); Double_t SeuilE = 0.1; for (Int_t nx = 1; nx <= haa_zz->GetNbinsX(); nx += 1) { Int_t zz = TMath::Nint(haa_zz->GetXaxis()->GetBinCenter(nx)); KVNumberList nlA; Double_t sumA = 0, sum = 0; for (Int_t ny = 1; ny <= haa_zz->GetNbinsY(); ny += 1) { Double_t stat = haa_zz->GetBinContent(nx, ny); if (stat > 0) { Double_t val = haa_zz->GetYaxis()->GetBinCenter(ny); nlA.Add(TMath::Nint(val)); sumA += val * stat; sum += stat; } } sumA /= sum; Int_t nA = nlA.GetNValues(); if (nA == 0) { Warning("CalculateDeltaE_EGrid", "no count for Z=%d", zz); } else { if (Zonly) { nlA.Clear(); nlA.Add(TMath::Nint(sumA)); } else { if (nA == 1) { Int_t aref = nlA.Last(); nlA.Add(aref - 1); nlA.Add(aref + 1); } } part.SetZ(zz); // printf("zz=%d\n",zz); nlA.Begin(); while (!nlA.End()) { Int_t aa = nlA.Next(); part.SetA(aa); // printf("+ aa=%d known=%d\n",aa,part.IsKnown()); if (part.IsKnown()) { //loop over energy //first find : // ****E1 = energy at which particle passes 1st detector and starts to enter in the 2nd one**** // E2 = energy at which particle passes the 2nd detector //then perform npoints calculations between these two energies and use these //to construct a KVIDZALine Double_t E1, E2; //find E1 //go from SeuilE MeV to det_de->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA())) Double_t E1min = SeuilE, E1max = det_de->GetEIncOfMaxDeltaE(zz, aa); E1 = (E1min + E1max) / 2.; while ((E1max - E1min) > SeuilE) { part.SetEnergy(E1); det_de->Clear(); det_eres->Clear(); det_de->DetectParticle(&part); det_eres->DetectParticle(&part); if (det_eres->GetEnergy() > SeuilE) { //particle got through - decrease energy E1max = E1; E1 = (E1max + E1min) / 2.; } else { //particle stopped - increase energy E1min = E1; E1 = (E1max + E1min) / 2.; } } //add point to Bragg line Double_t dE_B = det_de->GetMaxDeltaE(zz, aa); Double_t E_B = det_de->GetEIncOfMaxDeltaE(zz, aa); Double_t Eres_B = det_de->GetERes(zz, aa, E_B); B_line->SetPoint(npoi_bragg++, Eres_B, dE_B); //find E2 //go from E1 MeV to maximum value where the energy loss formula is valid Double_t E2min = E1, E2max = det_eres->GetEmaxValid(part.GetZ(), part.GetA()); E2 = (E2min + E2max) / 2.; while ((E2max - E2min > SeuilE)) { part.SetEnergy(E2); det_de->Clear(); det_eres->Clear(); det_de->DetectParticle(&part); det_eres->DetectParticle(&part); if (part.GetEnergy() > SeuilE) { //particle got through - decrease energy E2max = E2; E2 = (E2max + E2min) / 2.; } else { //particle stopped - increase energy E2min = E2; E2 = (E2max + E2min) / 2.; } } // printf("z=%d a=%d E1=%lf E2=%lf\n",zz,aa,E1,E2); KVIDZALine* line = (KVIDZALine*)idgrid->Add("ID", "KVIDZALine"); if (TMath::Even(zz)) line->SetLineColor(4); line->SetAandZ(aa, zz); Double_t logE1 = TMath::Log(E1); Double_t logE2 = TMath::Log(E2); Double_t dLog = (logE2 - logE1) / (npoints - 1.); for (Int_t i = 0; i < npoints; i++) { Double_t E = TMath::Exp(logE1 + i * dLog); Double_t Eres = 0.; Int_t niter = 0; while (Eres < SeuilE && niter <= 20) { det_de->Clear(); det_eres->Clear(); part.SetEnergy(E); det_de->DetectParticle(&part); det_eres->DetectParticle(&part); Eres = det_eres->GetEnergy(); E += SeuilE; niter += 1; } if (!(niter > 20)) { Double_t dE = det_de->GetEnergy(); Double_t gEres, gdE; line->GetPoint(i - 1, gEres, gdE); line->SetPoint(i, Eres, dE); } } } } } } return idgrid; }
//_____________________________________________________________________________________________________// KVIDGrid* KVIDTelescope::CalculateDeltaE_EGrid(const Char_t* Zrange, Int_t deltaA, Int_t npoints, Double_t lifetime, UChar_t massformula, Double_t xfactor) { //Genere une grille dE-E (perte d'energie - energie residuelle) pour une gamme en Z donnee // - Zrange definit l'ensemble des charges pour lequel les lignes vont etre calculees // - deltaA permet de definir si a chaque Z n'est associee qu'un seul A (deltaA=0) ou plusieurs //Exemple : // deltaA=1 -> Aref-1, Aref et Aref+1 seront les masses associees a chaque Z et // donc trois lignes de A par Z. le Aref pour chaque Z est determine par // la formule de masse par defaut (Aref = KVNucleus::GetA() voir le .kvrootrc) // deltaA=0 -> pour chaque ligne de Z le A associe sera celui de KVNucleus::GetA() // - est le nombre de points par ligne // //un noyau de A et Z donne n'est considere que s'il retourne KVNucleus::IsKnown() = kTRUE // if (GetSize() <= 1) return 0; KVNumberList nlz(Zrange); TClass* cl = TClass::GetClass(GetDefaultIDGridClass()); if (!cl || !cl->InheritsFrom("KVIDZAGrid")) cl = TClass::GetClass("KVIDZAGrid"); KVIDGrid* idgrid = (KVIDGrid*)cl->New(); idgrid->AddIDTelescope(this); idgrid->SetOnlyZId((deltaA == 0)); KVDetector* det_de = GetDetector(1); if (!det_de) return 0; KVDetector* det_eres = GetDetector(2); if (!det_eres) return 0; KVNucleus part; Info("CalculateDeltaE_EGrid", "Calculating dE-E grid: dE detector = %s, E detector = %s", det_de->GetName(), det_eres->GetName()); KVIDCutLine* B_line = (KVIDCutLine*)idgrid->Add("OK", "KVIDCutLine"); Int_t npoi_bragg = 0; B_line->SetName("Bragg_line"); B_line->SetAcceptedDirection("right"); Double_t SeuilE = 0.1; nlz.Begin(); while (!nlz.End()) { Int_t zz = nlz.Next(); part.SetZ(zz, massformula); Int_t aref = part.GetA(); // printf("%d\n",zz); for (Int_t aa = aref - deltaA; aa <= aref + deltaA; aa += 1) { part.SetA(aa); // printf("+ %d %d %d\n",aa,aref,part.IsKnown()); if (part.IsKnown() && (part.GetLifeTime() > lifetime)) { //loop over energy //first find : // ****E1 = energy at which particle passes 1st detector and starts to enter in the 2nd one**** // E2 = energy at which particle passes the 2nd detector //then perform npoints calculations between these two energies and use these //to construct a KVIDZALine Double_t E1, E2; //find E1 //go from SeuilE MeV to det_de->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA())) Double_t E1min = SeuilE, E1max = det_de->GetEIncOfMaxDeltaE(zz, aa); E1 = (E1min + E1max) / 2.; while ((E1max - E1min) > SeuilE) { part.SetEnergy(E1); det_de->Clear(); det_eres->Clear(); det_de->DetectParticle(&part); det_eres->DetectParticle(&part); if (det_eres->GetEnergy() > SeuilE) { //particle got through - decrease energy E1max = E1; E1 = (E1max + E1min) / 2.; } else { //particle stopped - increase energy E1min = E1; E1 = (E1max + E1min) / 2.; } } //add point to Bragg line Double_t dE_B = det_de->GetMaxDeltaE(zz, aa); Double_t E_B = det_de->GetEIncOfMaxDeltaE(zz, aa); Double_t Eres_B = det_de->GetERes(zz, aa, E_B); B_line->SetPoint(npoi_bragg++, Eres_B, dE_B); //find E2 //go from E1 MeV to maximum value where the energy loss formula is valid Double_t E2min = E1, E2max = det_eres->GetEmaxValid(part.GetZ(), part.GetA()); E2 = (E2min + E2max) / 2.; while ((E2max - E2min > SeuilE)) { part.SetEnergy(E2); det_de->Clear(); det_eres->Clear(); det_de->DetectParticle(&part); det_eres->DetectParticle(&part); if (part.GetEnergy() > SeuilE) { //particle got through - decrease energy E2max = E2; E2 = (E2max + E2min) / 2.; } else { //particle stopped - increase energy E2min = E2; E2 = (E2max + E2min) / 2.; } } E2 *= xfactor; if ((!strcmp(det_eres->GetType(), "CSI")) && (E2 > 5000)) E2 = 5000; // printf("z=%d a=%d E1=%lf E2=%lf\n",zz,aa,E1,E2); KVIDZALine* line = (KVIDZALine*)idgrid->Add("ID", "KVIDZALine"); if (TMath::Even(zz)) line->SetLineColor(4); line->SetZ(zz); line->SetA(aa); Double_t logE1 = TMath::Log(E1); Double_t logE2 = TMath::Log(E2); Double_t dLog = (logE2 - logE1) / (npoints - 1.); for (Int_t i = 0; i < npoints; i++) { // Double_t E = E1 + i*(E2-E1)/(npoints-1.); Double_t E = TMath::Exp(logE1 + i * dLog); Double_t Eres = 0.; Int_t niter = 0; while (Eres < SeuilE && niter <= 20) { det_de->Clear(); det_eres->Clear(); part.SetEnergy(E); det_de->DetectParticle(&part); det_eres->DetectParticle(&part); Eres = det_eres->GetEnergy(); E += SeuilE; niter += 1; } if (!(niter > 20)) { Double_t dE = det_de->GetEnergy(); Double_t gEres, gdE; line->GetPoint(i - 1, gEres, gdE); line->SetPoint(i, Eres, dE); } } //printf("sort de boucle points"); } } } return idgrid; }
void KVSpIdGUI::SpiderIdentification() { if ((!fHisto) || (!fGrid)) return; TVirtualPad* pad = fGrid->GetPad(); fGrid->UnDraw(); fZp = fZpEntry->GetIntNumber(); if (!fUserParameter) fSpFactor = GetFactor(); else fSpFactor = fSpiderFactorEntry->GetNumber(); fAnglesUp = fAngleUpEntry->GetIntNumber(); fAnglesDown = fAngleDownEntry->GetIntNumber(); fAlpha = fApertureUpEntry->GetNumber(); fPiedType = fPiedChoice->GetSelected(); fMatrixType = fTypeChoice->GetSelected(); Int_t type = fMatrixType; TH2* tmpHisto = fHisto; TList* tmpCut = 0; if (fUseCut) { tmpHisto = (TH2*)fHisto->Clone(Form("%s_cut", fHisto->GetName())); tmpHisto->Reset(); for (int i = 1; i <= fHisto->GetNbinsX(); i++) { for (int j = 1; j <= fHisto->GetNbinsY(); j++) { Stat_t ww = fHisto->GetBinContent(i, j); Axis_t x0 = fHisto->GetXaxis()->GetBinCenter(i); Axis_t y0 = fHisto->GetYaxis()->GetBinCenter(j); if (fGrid->IsIdentifiable(x0, y0)) tmpHisto->Fill(x0, y0, ww); } } tmpCut = (TList*)fGrid->GetCuts()->Clone("tmpCuts"); } fGrid->Clear(); if (fScaledHisto) delete fScaledHisto; KVHistoManipulator hm; TF1 RtLt("RtLt", Form("x*%lf", fSfx), 0, tmpHisto->GetXaxis()->GetXmax()); TF1 RtLty("RtLty", Form("x*%lf", fSfy), 0, tmpHisto->GetXaxis()->GetXmax()); fScaledHisto = (TH2F*)hm.ScaleHisto(tmpHisto, &RtLt, &RtLty); if (fIdentificator) delete fIdentificator; fIdentificator = new KVSpiderIdentificator(fScaledHisto, fXm * fSfx, fYm * fSfy); switch (fPiedType) { case kUser: fIdentificator->SetX0(fPdx * fSfx); fIdentificator->SetY0(fPdy * fSfy); break; case kAuto: break; case kNone: fIdentificator->SetX0(0.); fIdentificator->SetY0(0.); } fIdentificator->SetParameters(fSpFactor); fIdentificator->SetNangles(fAnglesUp, fAnglesDown); fIdentificator->SetAlpha(fAlpha); fProgressBar->SetRange(0, fAnglesUp + fAnglesDown + 1); fProgressBar->Reset(); fIdentificator->Connect("Increment(Float_t)", "TGHProgressBar", fProgressBar, "SetPosition(Float_t)"); fTestButton->SetEnabled(kFALSE); fCloseButton->SetEnabled(kFALSE); fIdentificator->ProcessIdentification(); fTestButton->SetEnabled(kTRUE); fCloseButton->SetEnabled(kTRUE); fIdentificator->Disconnect("Increment(Float_t)", fProgressBar, "SetPosition(Float_t)"); fProgressBar->Reset(); if (fDebug) fIdentificator->Draw(fOption.Data()); TList* ll = (TList*)fIdentificator->GetListOfLines(); KVIDZALine* TheLine = 0; int zmax = 0; KVSpiderLine* spline = 0; TIter next_line(ll); while ((spline = (KVSpiderLine*)next_line())) { if ((spline->GetN() > 10)) { //&&(spline->GetX(0)<=fIdentificator->GetX0()+200.)) TF1* ff1 = 0; if (type == kSiCsI) ff1 = spline->GetFunction(fPdx * fSfx, TMath::Max(fScaledHisto->GetXaxis()->GetXmax() * 0.9, spline->GetX(spline->GetN() - 1))); else if (type == kSiSi) ff1 = spline->GetFunction(fPdx * fSfx, TMath::Min(fScaledHisto->GetXaxis()->GetXmax() * 0.9, spline->GetX(spline->GetN() - 1) * 1.5)); else if (type == kChIoSi) ff1 = spline->GetFunction(fPdx * fSfx, TMath::Min(fScaledHisto->GetXaxis()->GetXmax() * 0.9, spline->GetX(spline->GetN() - 1) * 1.5)); else ff1 = spline->GetFunction(); if ((type == kSiCsI) && (ff1->GetParameter(1) >= 3000. || (ff1->GetParameter(2) <= 0.35) || (ff1->GetParameter(2) >= 1.))) { Info("SpiderIdentification", "Z = %d has been rejected (fit parameters)", spline->GetZ()); continue; } TheLine = (KVIDZALine*)((KVIDZAGrid*)fGrid)->NewLine("ID"); TheLine->SetZ(spline->GetZ()); double min, max; ff1->GetRange(min, max); double step = TMath::Min((max - min) * 0.05, 20.); //20.; double stepmax = (max - min) * 0.2; //800.; double x = 0.; for (x = min + 1; x < max + step; x += step) { if (step <= stepmax) step *= 1.3; if (ff1->Eval(x) < 4000) TheLine->SetPoint(TheLine->GetN(), x, ff1->Eval(x)); } if (max > x) TheLine->SetPoint(TheLine->GetN(), max, ff1->Eval(max)); fGrid->Add("ID", TheLine); if (spline->GetZ() >= zmax) zmax = spline->GetZ(); } else { Info("SpiderIdentification", "Z = %d has been rejected (too few points)", spline->GetZ()); } } TF1 fx("fx12", Form("x/%lf", fSfx), 0., fScaledHisto->GetNbinsX() * 1.); TF1 fy("fy12", Form("x/%lf", fSfy), 0., fScaledHisto->GetNbinsY() * 1.); fGrid->Scale(&fx, &fy); if (fUseCut) delete tmpHisto; if (tmpCut) fGrid->GetCuts()->AddAll(tmpCut); pad->cd(); fGrid->Draw(); pad->Modified(); pad->Update(); DoClose(); }
void KVZALineFinder::MakeGrid() { fGeneratedGrid = new KVIDZAGrid; fGeneratedGrid->SetName(Form("%s_Up",fGrid->GetName())); fGeneratedGrid->SetVarX(fGrid->GetVarX()); fGeneratedGrid->SetVarY(fGrid->GetVarY()); fGeneratedGrid->AddIDTelescopes(fGrid->GetIDTelescopes()); KVIDZALine* TheLine = 0; KVIDZALine* TheZLine = 0; KVSpiderLine* spline = 0; TIter next_line(fLines); while((spline = (KVSpiderLine*)next_line())) // generate KVLines from KVSpiderLines { spline->Sort(); if((spline->GetN()>5)) { TheLine = (KVIDZALine*)((KVIDZAGrid*)fGeneratedGrid)->NewLine("ID"); TheLine->SetZ(spline->GetZ()); TheLine->SetA(spline->GetA()); for(int i=0; i<spline->GetN(); i++) { Int_t ibin = fConvertHisto->FindBin(spline->GetX(i),spline->GetY(i)); Double_t y = fConvertHisto->GetBinContent(ibin); Int_t di = 1; while(!y) { y = fConvertHisto->GetBinContent(ibin+di); di++; } if((i>spline->GetN()-3)&&(abs(y-TheLine->GetY()[TheLine->GetN()-1])>20)) continue; TheLine->SetPoint(i, spline->GetX(i), y);//spline->GetY(i)); } TheZLine = (KVIDZALine*)fGrid->GetIdentifier(TheLine->GetZ(),200); if(!TheZLine) continue; Double_t x0 = TheLine->GetX()[0]; Double_t x0ref = TheZLine->GetX()[0]; Double_t x1ref = TheZLine->GetX()[TheZLine->GetN()-1]; if((x0>2.*x0ref)&&(x0<0.15*x1ref)) { Double_t dy = (TheLine->GetY()[0]) - (TheZLine->Eval(x0)); for(int i=0; i<=TheZLine->GetN();i++) { Double_t x = TheZLine->GetX()[i]; Double_t y = dy + TheZLine->GetY()[i]; if(x>=x0) break; TheLine->SetPoint(TheLine->GetN(),x,y); } TheLine->Sort(&TGraph::CompareX, kTRUE); } Double_t x1 = TheLine->GetX()[TheLine->GetN()-1]; if((x1<x1ref)) { Double_t dy = (TheLine->GetY()[TheLine->GetN()-1]) - (TheZLine->Eval(x1)); for(int i=TheZLine->GetN()-1; i>0;i--) { Double_t x = TheZLine->GetX()[i]; Double_t y = dy + TheZLine->GetY()[i]; if(x<=x1) break; TheLine->SetPoint(TheLine->GetN(),x,y); } TheLine->Sort(&TGraph::CompareX, kTRUE); } fGeneratedGrid->Add("ID",TheLine); fLines->Remove(spline); } } // return; // TheLine = 0; // spline = 0; // TIter next(fLines); // while((spline = (KVSpiderLine*)next())) // scan rejected lines // { // Int_t zl = spline->GetZ(); // if(zl<4) continue; // Int_t aMostProb = 0; // if(zl<=fAList.size()) aMostProb = fAList.at(zl-1); // else aMostProb = 2*zl+1; // int index = 0; // KVIDZALine* oldLine = 0; // oldLine=(fGeneratedGrid->GetZALine(spline->GetZ(),aMostProb,index)); // if(!oldLine) // { // continue; // } // TheLine = (KVIDZALine*)((KVIDZAGrid*)fGeneratedGrid)->NewLine("ID"); // TheLine->SetZ(spline->GetZ()); // TheLine->SetA(spline->GetA()); // Int_t ibin = fConvertHisto->FindBin(spline->GetX(),spline->GetY()); // Double_t y = fConvertHisto->GetBinContent(ibin); // Int_t di = 1; // while(!y) // { // y = fConvertHisto->GetBinContent(ibin+di); // di++; // } // Double_t dy = y - oldLine->Eval(spline->GetX()); // for(int i=0; i<oldLine->GetN(); i++) // { // TheLine->SetPoint(i, (oldLine->GetX()[i]), (oldLine->GetY()[i])+dy); //// TheLine->SetPoint(i, spline->GetX(i), fConvertHisto->Interpolate(spline->GetX(i),spline->GetY(i))); // } //// fGeneratedGrid->Add("ID",TheLine); // } }