]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGHF/correlationHF/AliDxHFECorrelation.cxx
cleanup
[u/mrichter/AliRoot.git] / PWGHF / correlationHF / AliDxHFECorrelation.cxx
CommitLineData
f8554911 1// $Id$
2
3//**************************************************************************
4//* This file is property of and copyright by the ALICE Project *
5//* ALICE Experiment at CERN, All rights reserved. *
6//* *
7//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8//* Sedat Altinpinar <Sedat.Altinpinar@cern.ch> *
9//* Hege Erdal <hege.erdal@gmail.com> *
10//* *
11//* Permission to use, copy, modify and distribute this software and its *
12//* documentation strictly for non-commercial purposes is hereby granted *
13//* without fee, provided that the above copyright notice appears in all *
14//* copies and that both the copyright notice and this permission notice *
15//* appear in the supporting documentation. The authors make no claims *
16//* about the suitability of this software for any purpose. It is *
17//* provided "as is" without express or implied warranty. *
18//**************************************************************************
19
20/// @file AliDxHFECorrelation.cxx
21/// @author Sedat Altinpinar, Hege Erdal, Matthias Richter
22/// @date 2012-04-25
23/// @brief Worker class for D0-HF electron correlation
24///
25
26#include "AliDxHFECorrelation.h"
27#include "AliVParticle.h"
28#include "AliLog.h"
29//#include "AliAnalysisCuts.h" // required dependency libANALYSISalice.so
30//#include "AliFlowTrackSimple.h" // required dependency libPWGflowBase.so
31//#include "AliFlowCandidateTrack.h" // required dependency libPWGflowTasks.so
32//#include "AliCFContainer.h" // required dependency libCORRFW.so
33#include "TObjArray.h"
34#include "AliHFCorrelator.h"
35#include "AliAODEvent.h"
36#include "AliAODVertex.h"
37#include "TH1D.h"
38#include "TH2D.h"
39#include "TH3D.h"
40#include "THnSparse.h"
41#include "TMath.h"
42#include "TFile.h"
43#include "TCanvas.h"
44#include "TDatabasePDG.h"
45#include "TLorentzVector.h"
46#include "AliReducedParticle.h"
47#include "AliDxHFEParticleSelection.h"
48#include <iostream>
49#include <cerrno>
50#include <memory>
51
52using namespace std;
53
54ClassImp(AliDxHFECorrelation)
55
56AliDxHFECorrelation::AliDxHFECorrelation(const char* name)
57 : TNamed(name?name:"AliDxHFECorrelation", "")
58 , fHistograms(NULL)
59 , fControlObjects(NULL)
60 , fCorrProperties(NULL)
61 , fhEventControlCorr(NULL)
62 , fCuts(NULL)
63 , fUseMC(kFALSE)
64 , fCorrelator(NULL)
65 , fUseEventMixing(kFALSE)
66 , fSystem(0)
67 , fMinPhi(-TMath::Pi()/2)
68 , fMaxPhi(3*TMath::Pi()/2)
69 , fDeltaPhi(0)
70 , fDeltaEta(0)
71 , fDimThn(0)
72 , fCorrArray(NULL)
73 , fEventType(0)
74{
75 // default constructor
76 //
77 //
78
79}
80
81const char* AliDxHFECorrelation::fgkEventControlBinNames[]={
82 "nEventsAll",
83 "nEventsSelected",
84 "nEventsD0",
85 "nEventsD0e"
86};
87
88AliDxHFECorrelation::~AliDxHFECorrelation()
89{
90 // destructor
91 //
92 //
93 if (fHistograms) delete fHistograms;
94 fHistograms=NULL;
95
96 // NOTE: fControlObjects owns the object, and they are deleted in the
97 // destructor of TList
98 if (fControlObjects) delete fControlObjects;
99 fControlObjects=NULL;
100 fCorrProperties=NULL;
101 fhEventControlCorr=NULL;
102 if(fCorrelator) delete fCorrelator;
103 fCorrelator=NULL;
104 if(fCorrArray) delete fCorrArray;
105 fCorrArray=NULL;
106
107 // NOTE: the external object is deleted elsewhere
108 fCuts=NULL;
109}
110
111int AliDxHFECorrelation::Init(const char* arguments)
112{
113 //
114 // Will initialize thnsparse, histogram and AliHFCorrelator
115 //
116 AliInfo("Initializing correlation objects");
117 ParseArguments(arguments);
118
119 //----------------------------------------------
120 // Setting up THnSparse
121 fCorrProperties=DefineTHnSparse();
122 AddControlObject(fCorrProperties);
123
124 //----------------------------------------------
125 // Histogram for storing event information
126
127 std::auto_ptr<TH1D> hEventControl(new TH1D("hEventControlCorr", "hEventControlCorr", 10, 0, 10));
128 if (!hEventControl.get()) {
129 return -ENOMEM;
130 }
131 int iLabel=0;
132 for (iLabel=0; iLabel<kNEventControlLabels; iLabel++)
133 hEventControl->GetXaxis()->SetBinLabel(iLabel+1, fgkEventControlBinNames[iLabel]);
134
135 fhEventControlCorr=hEventControl.release();
136 AddControlObject(fhEventControlCorr);
137
138 //----------------------------------------------
139 // AliHFCorrelator for Event Mixing and correlation
140 //
141 // fCuts is the hadron cut object, fSystem to switch between pp or PbPb
142 AliHFAssociatedTrackCuts* cuts=dynamic_cast<AliHFAssociatedTrackCuts*>(fCuts);
143 if (!cuts) {
144 if (fCuts)
145 AliError(Form("cuts object of wrong type %s, required AliHFAssociatedTrackCuts", fCuts->ClassName()));
146 else
147 AliError("mandatory cuts object missing");
148 return -EINVAL;
149 }
150 if (cuts->GetNCentPoolBins()==0 || cuts->GetCentPoolBins()==NULL ||
151 cuts->GetNZvtxPoolBins()==0 || cuts->GetZvtxPoolBins()==NULL) {
152 // the bin information is used further downstream so it
153 // needs to be available in order to continue
154 AliError(Form("inavlid object %s: bin configuration is mandatory", cuts->GetName()));
155 cuts->Dump();
156 return -EINVAL;
157 }
158 cuts->Print("");
159 fCorrelator = new AliHFCorrelator("Correlator", cuts, fSystem);
160 fCorrelator->SetDeltaPhiInterval(fMinPhi,fMaxPhi); //Correct Phi Interval
161 fCorrelator->SetEventMixing(fUseEventMixing); // mixing Off/On
162 fCorrelator->SetAssociatedParticleType(AliHFCorrelator::kElectron);
163 // 0: don't calculate d0; 1: return d0; 2: return d0/d0err
164 fCorrelator->SetApplyDisplacementCut(kFALSE);
165 fCorrelator->SetUseMC(fUseMC);
166 fCorrelator->SetUseReco(kTRUE); // Reco/MCTruth
167 Bool_t pooldef = fCorrelator->DefineEventPool();
168
169 if(!pooldef) AliInfo("Warning:: Event pool not defined properly");
170
171
172 // ============================= EVENT MIXING CHECKS ======================================
173 // TODO: Not sure if all 4 histos are needed. Keep for now..
174 Int_t MaxNofEvents = cuts->GetMaxNEventsInPool();
175 Int_t MinNofTracks = cuts->GetMinNTracksInPool();
176 Int_t NofCentBins = cuts->GetNCentPoolBins();
177 const Double_t * CentBins = cuts->GetCentPoolBins();
178 const Double_t defaultCentBins[] = {0,100};
179 if (NofCentBins==0 || CentBins==NULL) {
180 NofCentBins=1; // note: array dimension minus one, because of bin is bound by upper and lower
181 CentBins=defaultCentBins;
182 }
183 Int_t NofZVrtxBins = cuts->GetNZvtxPoolBins();
184 const Double_t *ZVrtxBins = cuts->GetZvtxPoolBins();
185 const Double_t defaultZVrtxBins[] = {-10,10};
186 if (NofZVrtxBins==0 || ZVrtxBins==NULL) {
187 NofZVrtxBins=1; // note: array dimension minus one, because of bin is bound by upper and lower
188 ZVrtxBins=defaultZVrtxBins;
189 }
190
191 Int_t nofEventPropBins =0;
192
193 if(fSystem) nofEventPropBins = 100; // PbPb centrality
194 if(!fSystem) nofEventPropBins = NofCentBins; // pp multiplicity
195
196 Double_t minvalue = CentBins[0];
197 Double_t maxvalue = CentBins[NofCentBins];
198 Double_t Zminvalue = ZVrtxBins[0];
199 Double_t Zmaxvalue = ZVrtxBins[NofCentBins];
200
201 const Double_t Nevents[]={0,2*MaxNofEvents/10,4*MaxNofEvents/10,6*MaxNofEvents/10,8*MaxNofEvents/10,MaxNofEvents};
202 const Double_t * events = Nevents;
203
204 TH3D * EventsPerPoolBin = new TH3D("EventsPerPoolBin","Number of events in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins,5,events);
205 EventsPerPoolBin->GetXaxis()->SetTitle("Centrality/multiplicity ");
206 EventsPerPoolBin->GetYaxis()->SetTitle("Z vertex [cm]");
207 EventsPerPoolBin->GetZaxis()->SetTitle("Number of events in pool bin");
208 if(fUseEventMixing) AddControlObject(EventsPerPoolBin);
209
210 Int_t MaxNofTracks = (MaxNofEvents+1)*MinNofTracks;
211 Int_t Diff = MaxNofTracks-MinNofTracks;
212
213 Double_t Ntracks[]={MinNofTracks,MinNofTracks+Diff/5,MinNofTracks+2*Diff/5,MinNofTracks+3*Diff/5,MinNofTracks+4*Diff/5,MaxNofTracks};
214 Double_t * trackN = Ntracks;
215
216 TH3D * NofTracksPerPoolBin = new TH3D("NofTracksPerPoolBin","Number of tracks in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins,5,trackN);
217 NofTracksPerPoolBin->GetXaxis()->SetTitle("Centrality/multiplicity ");
218 NofTracksPerPoolBin->GetYaxis()->SetTitle("Z vertex [cm]");
219 NofTracksPerPoolBin->GetZaxis()->SetTitle("Number of tracks per bin");
220
221 if(fUseEventMixing) AddControlObject(NofTracksPerPoolBin);
222
223 TH2D * NofPoolBinCalls = new TH2D("NofPoolBinCalls","Number of tracks in bin pool",NofCentBins,CentBins,NofZVrtxBins,ZVrtxBins);
224 NofPoolBinCalls->GetXaxis()->SetTitle("Centrality/multiplicity ");
225 NofPoolBinCalls->GetYaxis()->SetTitle("Z vertex [cm]");
226 if(fUseEventMixing) AddControlObject(NofPoolBinCalls);
227
228 TH2D * EventProps = new TH2D("EventProps","Number of tracks in bin pool",nofEventPropBins,minvalue,maxvalue,100,Zminvalue,Zmaxvalue);
229 EventProps->GetXaxis()->SetTitle("Centrality/multiplicity ");
230 EventProps->GetYaxis()->SetTitle("Z vertex [cm]");
231 if(fUseEventMixing) AddControlObject(EventProps);
232
233 return 0;
234}
235
236int AliDxHFECorrelation::ParseArguments(const char* arguments)
237{
238 // parse arguments and set internal flags
239 TString strArguments(arguments);
240 auto_ptr<TObjArray> tokens(strArguments.Tokenize(" "));
241 if (!tokens.get()) return -ENOMEM;
242
243 TIter next(tokens.get());
244 TObject* token;
245 while ((token=next())) {
246 TString argument=token->GetName();
247
248 if (argument.BeginsWith("event-mixing")) {
249 fUseEventMixing=true;
250 continue;
251 }
252
253 if (argument.BeginsWith("use-mc")) {
254 fUseMC=true;
255 continue;
256 }
257 if (argument.BeginsWith("system=")) {
258 argument.ReplaceAll("system=", "");
259 if (argument.CompareTo("pp")==0) fSystem=0;
260 else if (argument.CompareTo("Pb-Pb")==0) fSystem=1;
261 else {
262 AliWarning(Form("can not set collision system, unknown parameter '%s'", argument.Data()));
263 // TODO: check what makes sense
264 fSystem=0;
265 }
266 continue;
267 }
268 AliWarning(Form("unknown argument '%s'", argument.Data()));
269
270 }
271
272 return 0;
273}
274
275THnSparse* AliDxHFECorrelation::DefineTHnSparse()
276{
277 //
278 //Defines the THnSparse. For now, only calls CreateControlTHnSparse
279
280 // here is the only place to change the dimension
281 static const int sizeEventdphi = 7;
282 InitTHnSparseArray(sizeEventdphi);
283 const double pi=TMath::Pi();
284
285 //TODO: add phi for electron??
286 // 0 1 2 3 4 5 6
287 // D0invmass PtD0 PhiD0 PtbinD0 Pte dphi deta
288 int binsEventdphi[sizeEventdphi] = { 200, 1000, 100, 21, 1000, 100, 100};
289 double minEventdphi [sizeEventdphi] = { 1.5648, 0, 0, 0, 0, fMinPhi, -2};
290 double maxEventdphi [sizeEventdphi] = { 2.1648, 100, 2*pi, 20, 100, fMaxPhi, 2};
291 const char* nameEventdphi[sizeEventdphi] = {
292 "D0InvMass",
293 "PtD0",
294 "PhiD0",
295 "PtBinD0",
296 "PtEl",
297 "#Delta#Phi",
298 "#Delta#eta"
299 };
300
301 TString name;
302 name.Form("%s info", GetName());
303
304
305 return CreateControlTHnSparse(name,sizeEventdphi,binsEventdphi,minEventdphi,maxEventdphi,nameEventdphi);
306
307}
308
309THnSparse* AliDxHFECorrelation::CreateControlTHnSparse(const char* name,
310 int thnSize,
311 int* thnBins,
312 double* thnMin,
313 double* thnMax,
314 const char** binLabels) const
315{
316 //
317 // Creates THnSparse.
318 //
319
320 AliInfo("Setting up THnSparse");
321
322 std::auto_ptr<THnSparseD> th(new THnSparseD(name, name, thnSize, thnBins, thnMin, thnMax));
323 if (th.get()==NULL) {
324 return NULL;
325 }
326 for (int iLabel=0; iLabel<thnSize; iLabel++) {
327 th->GetAxis(iLabel)->SetTitle(binLabels[iLabel]);
328
329 }
330 return th.release();
331
332}
333
334int AliDxHFECorrelation::AddControlObject(TObject* pObj)
335{
336 AliInfo("Adding object");
337 /// add control object to list, the base class becomes owner of the object
338 if (!pObj) return -EINVAL;
339 if (!fControlObjects) {
340 fControlObjects=new TList;
341 if (!fControlObjects) return -ENOMEM;
342 fControlObjects->SetOwner();
343 }
344 if (fControlObjects->FindObject(pObj->GetName())) {
345 AliError(Form("ignoring duplicate object '%s' of type %s", pObj->GetName(), pObj->ClassName()));
346 return -EEXIST;
347 }
348 fControlObjects->Add(pObj);
349 return 0;
350}
351
352int AliDxHFECorrelation::HistogramEventProperties(int bin)
353{
354 /// histogram event properties
355 if (!fhEventControlCorr) return 0;
356 fhEventControlCorr->Fill(bin);
357
358 return 0;
359}
360
361int AliDxHFECorrelation::Fill(const TObjArray* triggerCandidates, const TObjArray* associatedTracks, const AliVEvent* pEvent)
362{
363 //
364 // will use AliHFCorrelator to process D0-electron pair and then fill THnSparse.
365 //
366 if (!triggerCandidates || !associatedTracks) return -EINVAL;
367 if (!fControlObjects) {
368 Init();
369 }
370 if (!fControlObjects) {
371 AliError("Initialisation failed, can not fill THnSparse");
372 return -ENODEV;
373 }
374 // set the event to be processed
375 // TODO: change the correlator class to take the const pointer
376 if (!fCorrelator) {
377 AliError("working class instance fCorrelator missing");
378 return -ENODEV;
379 }
380 fCorrelator->SetAODEvent(dynamic_cast<AliAODEvent*>(const_cast<AliVEvent*>(pEvent)));
381
382 Bool_t correlatorON = fCorrelator->Initialize(); //define the pool for mixing
383 if(!correlatorON) {
384 AliError("AliHFCorrelator didn't initialize the pool correctly or processed a bad event");
385 return 1;
386 }
387
388 TIter itrigger(triggerCandidates);
389 TObject* otrigger=NULL;
390 int ctrigger=-1;
391
392 // For the moment this is very specific to D0-electron correlation. Should be
393 // changed to be less specific.
394 while ((otrigger=itrigger())!=NULL) {
395 // loop over trigger D0 particle
396 ctrigger++;
397 AliReducedParticle* ptrigger=dynamic_cast<AliReducedParticle*>(otrigger);
398 if (!ptrigger) continue;
399
400 Double_t phiTrigger = ptrigger->Phi();
401 Double_t ptTrigger = ptrigger->Pt();
402 Double_t etaTrigger = ptrigger->Eta();
403
404 // set the phi of the D meson in the correct range
405 // TODO: Is this correct to do this??
406 phiTrigger = fCorrelator->SetCorrectPhiRange(phiTrigger);
407 // pass to the object the necessary trigger part parameters
408 fCorrelator->SetTriggerParticleProperties(ptTrigger,phiTrigger,etaTrigger);
409
410 Bool_t execPool = fCorrelator->ProcessEventPool();
411 if(fUseEventMixing && !execPool) {
412 AliInfo("Mixed event analysis: pool is not ready");
413 continue;
414 }
415 Int_t NofEventsinPool = 1;
416 if(fUseEventMixing) NofEventsinPool = fCorrelator->GetNofEventsInPool();
417
418 // loop on events in the pool; if it is SE analysis, stops at one
419 for (Int_t jMix =0; jMix < NofEventsinPool; jMix++){
420 Bool_t analyzetracks = fCorrelator->ProcessAssociatedTracks(jMix, associatedTracks);
421
422 if(!analyzetracks) {
423 AliError("AliHFCorrelator::Cannot process the track array");
424 continue;
425 }
426
427 Int_t NofTracks = fCorrelator->GetNofTracks();
428
429 // looping on track candidates
430 for(Int_t iTrack = 0; iTrack<NofTracks; iTrack++){
431 Bool_t runcorrelation = fCorrelator->Correlate(iTrack);
432 if(!runcorrelation) continue;
433
434 fDeltaPhi = fCorrelator->GetDeltaPhi();
435 fDeltaEta = fCorrelator->GetDeltaEta();
436
437 AliReducedParticle *assoc = fCorrelator->GetAssociatedParticle();
438
439 FillParticleProperties(ptrigger,assoc,ParticleProperties(),GetDimTHnSparse());
440 fCorrProperties->Fill(ParticleProperties());
441
442 } // loop over electron tracks in event
443 } // loop over events in pool
444 } // loop over trigger particle
445
446 Bool_t updated = fCorrelator->PoolUpdate(associatedTracks);
447 if(fUseEventMixing){
448 if(!updated) AliInfo("Pool was not updated");
449 else {
450 EventMixingChecks(pEvent);
451 AliInfo("Pool was updated");
452 }
453 }
454 return 0;
455}
456
457
458
459int AliDxHFECorrelation::FillParticleProperties(AliVParticle* tr, AliVParticle *as, Double_t* data, int dimension) const
460{
461 // fill the data array from the particle data
462 if (!data) return -EINVAL;
463 AliReducedParticle *ptrigger=(AliReducedParticle*)tr;
464 AliReducedParticle *assoc=(AliReducedParticle*)as;
465 if (!ptrigger || !assoc) return -ENODATA;
466 int i=0;
467 if (dimension!=GetDimTHnSparse()) {
468 // TODO: think about filling only the available data and throwing a warning
469 return -ENOSPC;
470 }
471 data[i++]=ptrigger->GetInvMass();
472 data[i++]=ptrigger->Pt();
473 data[i++]=ptrigger->Phi();
474 data[i++]=ptrigger->GetPtBin();
475 data[i++]=assoc->Pt();
476 data[i++]=GetDeltaPhi();
477 data[i++]=GetDeltaEta();
478
479 return i;
480}
481
482void AliDxHFECorrelation::Clear(Option_t * /*option*/)
483{
484 /// overloaded from TObject: cleanup
485
486 // nothing to be done so far
487 return TObject::Clear();
488}
489
490void AliDxHFECorrelation::Print(Option_t */*option*/) const
491{
492 /// overloaded from TObject: print info
493 cout << "====================================================================" << endl;
494 TObject::Print();
495 if (fHistograms) {
496 fHistograms->Print();
497 }
498}
499
500void AliDxHFECorrelation::Draw(Option_t */*option*/)
501{
502 /// overloaded from TObject: draw histograms
503}
504
505TObject* AliDxHFECorrelation::FindObject(const char *name) const
506{
507 /// overloaded from TObject: find object by name
508 if (fControlObjects) {
509 return fControlObjects->FindObject(name);
510 }
511 return NULL;
512}
513
514TObject* AliDxHFECorrelation::FindObject(const TObject *obj) const
515{
516 /// overloaded from TObject: find object by pointer
517 if (fControlObjects) {
518 return fControlObjects->FindObject(obj);
519 }
520 return NULL;
521}
522
523void AliDxHFECorrelation::SaveAs(const char *filename, Option_t */*option*/) const
524{
525 /// overloaded from TObject: save to file
526 std::auto_ptr<TFile> output(TFile::Open(filename, "RECREATE"));
527 if (!output.get() || output->IsZombie()) {
528 AliError(Form("can not open file %s from writing", filename));
529 return;
530 }
531 output->cd();
532 if (fControlObjects) fControlObjects->Write();
533 output->Close();
534}
535
536AliDxHFECorrelation& AliDxHFECorrelation::operator+=(const AliDxHFECorrelation& other)
537{
538 /// add histograms from another instance
539 // TODO - need to change this to ThnSparse?
540 if (!fHistograms || !other.fHistograms) return *this;
541
542 for (int i=0; i<kNofHistograms; i++) {
543 if (fHistograms->At(i)==NULL || other.fHistograms->At(i)==NULL) continue;
544 TH1* target=reinterpret_cast<TH1*>(fHistograms->At(i));
545 TH1* source=reinterpret_cast<TH1*>(other.fHistograms->At(i));
546 if (!target || !source) continue;
547 TString name(fHistograms->At(i)->GetName());
548 if (name.CompareTo(target->GetName())!=0) {
549 AliWarning(Form("skipping incompatible objects at position %d: %s vs %s", i, source->GetName(), target->GetName()));
550 continue;
551 }
552 if (source->IsA()!=target->IsA()) {
553 AliWarning(Form("skipping incompatible classes at position %d: %s vs %s", i, source->ClassName(), target->ClassName()));
554 continue;
555 }
556 target->Add(source);
557 }
558 return *this;
559}
560
561
562//____________________________ Run checks on event mixing ___________________________________________________
563void AliDxHFECorrelation::EventMixingChecks(const AliVEvent* pEvent){
564
565 AliAODEvent *AOD= (AliAODEvent*)(pEvent);
566 AliCentrality *centralityObj = 0;
567 Int_t multiplicity = -1;
568 Double_t MultipOrCent = -1;
569
570 // get the pool for event mixing
571 if(!fSystem){ // pp
572 multiplicity = AOD->GetNTracks();
573 MultipOrCent = multiplicity; // convert from Int_t to Double_t
574 }
575 if(fSystem){ // PbPb
576 centralityObj = AOD->GetHeader()->GetCentralityP();
577 MultipOrCent = centralityObj->GetCentralityPercentileUnchecked("V0M");
578 AliInfo(Form("Centrality is %f", MultipOrCent));
579 }
580
581 AliAODVertex *vtx = AOD->GetPrimaryVertex();
582 Double_t zvertex = vtx->GetZ(); // zvertex
583
584 AliEventPool *pool = fCorrelator->GetPool();
585
586 ((TH2D*)fControlObjects->FindObject("NofPoolBinCalls"))->Fill(MultipOrCent,zvertex); // number of calls of pool
587 ((TH2D*)fControlObjects->FindObject("EventProps"))->Fill(MultipOrCent,zvertex); // event properties
588 ((TH3D*)fControlObjects->FindObject("EventsPerPoolBin"))->Fill(MultipOrCent,zvertex,pool->NTracksInPool()); // number of events in the pool
589 ((TH3D*)fControlObjects->FindObject("NofTracksPerPoolBin"))->Fill(MultipOrCent,zvertex,pool->GetCurrentNEvents()); // number of calls of pool
590}
591