New version including TOF
[u/mrichter/AliRoot.git] / ANALYSIS / AliReaderESD.cxx
CommitLineData
a5556ea5 1#include "AliReaderESD.h"
2//____________________________________________________________________
3//////////////////////////////////////////////////////////////////////
4// //
5// class AliReaderESD //
6// //
7// reader for ALICE Event Summary Data (ESD). //
8// //
9// Piotr.Skowronski@cern.ch //
10// //
11//////////////////////////////////////////////////////////////////////
12
13#include <TPDGCode.h>
14#include <TString.h>
15#include <TObjString.h>
16#include <TTree.h>
17#include <TFile.h>
18#include <TKey.h>
19#include <TParticle.h>
20#include <TH1.h>
21
22#include <AliRun.h>
23#include <AliRunLoader.h>
24#include <AliStack.h>
25#include <AliESDtrack.h>
26#include <AliESD.h>
27
28#include "AliAnalysis.h"
29#include "AliAODRun.h"
30#include "AliAOD.h"
31#include "AliAODStdParticle.h"
32#include "AliAODParticleCut.h"
33#include "AliTrackPoints.h"
34#include "AliClusterMap.h"
35
36ClassImp(AliReaderESD)
37
38AliReaderESD::AliReaderESD(const Char_t* esdfilename, const Char_t* galfilename):
39 fESDFileName(esdfilename),
40 fGAlFileName(galfilename),
41 fFile(0x0),
42 fRunLoader(0x0),
43 fKeyIterator(0x0),
44 fReadSim(kFALSE),
45 fCheckParticlePID(kFALSE),
46 fReadMostProbableOnly(kFALSE),
47 fNTrackPoints(0),
48 fdR(0.0),
49 fClusterMap(kFALSE),
50 fNTPCClustMin(0),
51 fNTPCClustMax(150),
52 fTPCChi2PerClustMin(0.0),
53 fTPCChi2PerClustMax(10e5),
54 fChi2Min(0.0),
55 fChi2Max(10e5),
56 fC00Min(0.0),
57 fC00Max(10e5),
58 fC11Min(0.0),
59 fC11Max(10e5),
60 fC22Min(0.0),
61 fC22Max(10e5),
62 fC33Min(0.0),
63 fC33Max(10e5),
64 fC44Min(0.0),
65 fC44Max(10e5),
66 fTPCC00Min(0.0),
67 fTPCC00Max(10e5),
68 fTPCC11Min(0.0),
69 fTPCC11Max(10e5),
70 fTPCC22Min(0.0),
71 fTPCC22Max(10e5),
72 fTPCC33Min(0.0),
73 fTPCC33Max(10e5),
74 fTPCC44Min(0.0),
75 fTPCC44Max(10e5)
76
77{
78 //cosntructor
79 if ( ((Int_t)kNSpecies) != ((Int_t)AliESDtrack::kSPECIES))
80 Fatal("AliReaderESD","ESD defintions probobly changed. Ask Youra.");
81}
82/********************************************************************/
83
84AliReaderESD::AliReaderESD(TObjArray* dirs,const Char_t* esdfilename, const Char_t* galfilename):
85 AliReader(dirs),
86 fESDFileName(esdfilename),
87 fGAlFileName(galfilename),
88 fFile(0x0),
89 fRunLoader(0x0),
90 fKeyIterator(0x0),
91 fReadSim(kFALSE),
92 fCheckParticlePID(kFALSE),
93 fReadMostProbableOnly(kFALSE),
94 fNTrackPoints(0),
95 fdR(0.0),
96 fClusterMap(kFALSE),
97 fNTPCClustMin(0),
98 fNTPCClustMax(150),
99 fTPCChi2PerClustMin(0.0),
100 fTPCChi2PerClustMax(10e5),
101 fChi2Min(0.0),
102 fChi2Max(10e5),
103 fC00Min(0.0),
104 fC00Max(10e5),
105 fC11Min(0.0),
106 fC11Max(10e5),
107 fC22Min(0.0),
108 fC22Max(10e5),
109 fC33Min(0.0),
110 fC33Max(10e5),
111 fC44Min(0.0),
112 fC44Max(10e5),
113 fTPCC00Min(0.0),
114 fTPCC00Max(10e5),
115 fTPCC11Min(0.0),
116 fTPCC11Max(10e5),
117 fTPCC22Min(0.0),
118 fTPCC22Max(10e5),
119 fTPCC33Min(0.0),
120 fTPCC33Max(10e5),
121 fTPCC44Min(0.0),
122 fTPCC44Max(10e5)
123{
124 //cosntructor
125 if ( ((Int_t)kNSpecies) != ((Int_t)AliESDtrack::kSPECIES))
126 Fatal("AliReaderESD","ESD defintions probobly changed. Ask Youra.");
127}
128/********************************************************************/
129
130AliReaderESD::~AliReaderESD()
131{
132 //desctructor
133 delete fRunLoader;
134 delete fKeyIterator;
135 delete fFile;
136}
137/**********************************************************/
138Int_t AliReaderESD::ReadNext()
139{
140//reads next event from fFile
141 //fRunLoader is for reading Kine
142
143 if (AliAODParticle::GetDebug())
144 Info("ReadNext","Entered");
145
146 if (fEventSim == 0x0) fEventSim = new AliAOD();
147 if (fEventRec == 0x0) fEventRec = new AliAOD();
148
149 fEventSim->Reset();
150 fEventRec->Reset();
151
152 do //do{}while; is OK even if 0 dirs specified. In that case we try to read from "./"
153 {
154 if (fFile == 0x0)
155 {
156 fFile = OpenFile(fCurrentDir);//rl is opened here
157 if (fFile == 0x0)
158 {
159 Error("ReadNext","Cannot get fFile for dir no. %d",fCurrentDir);
160 fCurrentDir++;
161 continue;
162 }
163 fCurrentEvent = 0;
164 fKeyIterator = new TIter(fFile->GetListOfKeys());
165// fFile->Dump();
166// fFile->GetListOfKeys()->Print();
167 }
168 TKey* key = (TKey*)fKeyIterator->Next();
169 if (key == 0x0)
170 {
171 if (AliAODParticle::GetDebug() > 2 )
172 {
173 Info("ReadNext","No more keys.");
174 }
175 fCurrentDir++;
176 delete fKeyIterator;
177 fKeyIterator = 0x0;
178 delete fFile;//we have to assume there is no more ESD objects in the fFile
179 fFile = 0x0;
180 delete fRunLoader;
181 fRunLoader = 0x0;
182 continue;
183 }
184 //try to read
185
186
187// TObject* esdobj = key->ReadObj();
188// if (esdobj == 0x0)
189// {
190// if (AliAODParticle::GetDebug() > 2 )
191// {
192// Info("ReadNext","Key read NULL. Key Name is %s",key->GetName());
193// key->Dump();
194// }
195// continue;
196// }
197// esdobj->Dump();
198// AliESD* esd = dynamic_cast<AliESD*>(esdobj);
199
200 TString esdname = "ESD";
201 esdname+=fCurrentEvent;
202 AliESD* esd = dynamic_cast<AliESD*>(fFile->Get(esdname));
203 if (esd == 0x0)
204 {
205// if (AliAODParticle::GetDebug() > 2 )
206// {
207// Info("ReadNext","This key is not an AliESD object %s",key->GetName());
208// }
209 if (AliAODParticle::GetDebug() > 2 )
210 {
211 Info("ReadNext","Can not find AliESD object named %s",esdname.Data());
212 }
213 fCurrentDir++;
214 delete fKeyIterator;
215 fKeyIterator = 0x0;
216 delete fFile;//we have to assume there is no more ESD objects in the fFile
217 fFile = 0x0;
218 delete fRunLoader;
219 fRunLoader = 0x0;
220 continue;
221 }
222
223 ReadESD(esd);
224
225 fCurrentEvent++;
226 fNEventsRead++;
227 delete esd;
228 return 0;//success -> read one event
229 }while(fCurrentDir < GetNumberOfDirs());//end of loop over directories specified in fDirs Obj Array
230
231 return 1; //no more directories to read
232}
233/**********************************************************/
234
235Int_t AliReaderESD::ReadESD(AliESD* esd)
236{
237 //****** Tentative particle type "concentrations"
238 static const Double_t concentr[5]={0.05, 0., 0.85, 0.10, 0.05};
239
240 Double_t pidtable[kNSpecies];//array used for reading pid probabilities from ESD track
241 Double_t w[kNSpecies];
242 Double_t mom[3];//momentum
243 Double_t pos[3];//position
244 Double_t vertexpos[3];//vertex position
245 //Reads one ESD
246 if (esd == 0x0)
247 {
248 Error("ReadESD","ESD is NULL");
249 return 1;
250 }
251
252 TDatabasePDG* pdgdb = TDatabasePDG::Instance();
253 if (pdgdb == 0x0)
254 {
255 Error("ReadESD","Can not get PDG Database Instance.");
256 return 1;
257 }
258
259 Float_t mf = esd->GetMagneticField();
260
261 if ( (mf == 0.0) && (fNTrackPoints > 0) )
262 {
263 Error("ReadESD","Magnetic Field is 0 and Track Points Demended. Skipping to next event.");
264 return 1;
265 }
266
267 AliStack* stack = 0x0;
268 if (fReadSim && fRunLoader)
269 {
270 fRunLoader->GetEvent(fCurrentEvent);
271 stack = fRunLoader->Stack();
272 }
273
274 const AliESDVertex* vertex = esd->GetVertex();
275 if (vertex == 0x0)
276 {
277 Info("ReadESD","ESD returned NULL pointer to vertex - assuming (0.0,0.0,0.0)");
278 vertexpos[0] = 0.0;
279 vertexpos[1] = 0.0;
280 vertexpos[2] = 0.0;
281 }
282 else
283 {
284 vertex->GetXYZ(vertexpos);
285 }
286
287 if (AliAODParticle::GetDebug() > 0)
288 {
289 Info("ReadESD","Primary Vertex is (%f,%f,%f)",vertexpos[0],vertexpos[1],vertexpos[2]);
290 }
291
292 Info("ReadESD","Reading Event %d",fCurrentEvent);
293
294 Int_t ntr = esd->GetNumberOfTracks();
295 Info("ReadESD","Found %d tracks.",ntr);
296 for (Int_t i = 0;i<ntr; i++)
297 {
298 AliESDtrack *esdtrack = esd->GetTrack(i);
299 if (esdtrack == 0x0)
300 {
301 Error("Next","Can not get track %d", i);
302 continue;
303 }
304
305 //if (esdtrack->HasVertexParameters() == kFALSE)
306 if ((esdtrack->GetStatus() & AliESDtrack::kITSrefit) == kFALSE)
307 {
308 if (AliAODParticle::GetDebug() > 2)
309 Info("ReadNext","Particle skipped: Data at vertex not available.");
310 continue;
311 }
312
313 if ((esdtrack->GetStatus() & AliESDtrack::kESDpid) == kFALSE)
314 {
315 if (AliAODParticle::GetDebug() > 2)
316 Info("ReadNext","Particle skipped: PID BIT is not set.");
317 continue;
318 }
319
320
321 Double_t extx;
322 Double_t extp[5];
323 esdtrack->GetConstrainedExternalParameters(extx,extp);
324 if (extp[4] == 0.0)
325 {
326 if (AliAODParticle::GetDebug() > 2)
327 Info("ReadNext","Track has 0 contrianed curvature -> Probobly parameters never updated. Skipping.");
328 continue;
329 }
330 esdtrack->GetESDpid(pidtable);
331 esdtrack->GetConstrainedPxPyPz(mom);
332 esdtrack->GetConstrainedXYZ(pos);
333 pos[0] -= vertexpos[0];//we are interested only in relative position to Primary vertex at this point
334 pos[1] -= vertexpos[1];
335 pos[2] -= vertexpos[2];
336
337 Int_t charge = (extp[4] > 0)?1:-1;//if curvature=charg/Pt is positive charge is positive
338
339 //Particle from kinematics
340 AliAODStdParticle* particle = 0;
341 Bool_t keeppart = kFALSE;
342 if ( fReadSim && stack )
343 {
344 if (esdtrack->GetLabel() < 0) continue;//this is fake - we are not able to match any track
345 TParticle *p = stack->Particle(esdtrack->GetLabel());
346 if (p==0x0)
347 {
348 Error("ReadNext","Can not find track with such label.");
349 continue;
350 }
351 if(Pass(p->GetPdgCode()))
352 {
353 if ( AliAODParticle::GetDebug() > 5 )
354 Info("ReadNext","Simulated Particle PID (%d) did not pass the cut.",p->GetPdgCode());
355 continue; //check if we are intersted with particles of this type
356 }
357// if(p->GetPdgCode()<0) charge = -1;
358 particle = new AliAODStdParticle(*p,i);
359
360 }
361
362 if(CheckTrack(esdtrack)) continue;
363
364 //Here we apply Bayes' formula
365 Double_t rc=0.;
366 for (Int_t s=0; s<AliESDtrack::kSPECIES; s++) rc+=concentr[s]*pidtable[s];
367 if (rc==0.0)
368 {
369 if (AliAODParticle::GetDebug() > 2)
370 Info("ReadNext","Particle rejected since total bayessian PID probab. is zero.");
371 continue;
372 }
373
374 for (Int_t s=0; s<AliESDtrack::kSPECIES; s++) w[s]=concentr[s]*pidtable[s]/rc;
375
376 if (AliAODParticle::GetDebug() > 4)
377 {
378 Info("ReadNext","###########################################################################");
379 Info("ReadNext","Momentum: %f %f %f",mom[0],mom[1],mom[2]);
380 Info("ReadNext","Position: %f %f %f",pos[0],pos[1],pos[2]);
381 TString msg("Pid list got from track:");
382 for (Int_t s = 0;s<kNSpecies;s++)
383 {
384 msg+="\n ";
385 msg+=s;
386 msg+="(";
387 msg+=charge*GetSpeciesPdgCode((ESpecies)s);
388 msg+="): ";
389 msg+=w[s];
390 msg+=" (";
391 msg+=pidtable[s];
392 msg+=")";
393 }
394 Info("ReadNext","%s",msg.Data());
395 }//if (AliAODParticle::GetDebug()>4)
396
397 AliTrackPoints* tpts = 0x0;
398 if (fNTrackPoints > 0)
399 {
400 tpts = new AliTrackPoints(fNTrackPoints,esdtrack,mf,fdR);
401 }
402
403 AliClusterMap* cmap = 0x0;
404 if ( fClusterMap )
405 {
406 cmap = new AliClusterMap(esdtrack);
407 }
408
409 //If this flag fReadMostProbableOnly is false the
410 //loop over species (see "LOOPPIDS") is over all possible PIDs
411 //in other case the most probablle PID is searched
412 //and the loop is limited to that PID only
413
414 Int_t firstspecie = 0;
415 Int_t lastspecie = kNSpecies;
416
417 if (fReadMostProbableOnly)
418 {
419 //find the most probable PID
420 Int_t spec = 0;
421 Float_t maxprob = w[0];
422 for (Int_t s=1; s<AliESDtrack::kSPECIES; s++)
423 {
424 if (w[s]>maxprob)
425 {
426 maxprob = w[s];
427 spec = s;
428 }
429 }
430 firstspecie = spec;
431 lastspecie = spec + 1;
432 }
433
434 for (Int_t s = firstspecie; s<lastspecie; s++)//LOOPPIDS
435 {
436 Int_t pdgcode = charge*GetSpeciesPdgCode((ESpecies)s);
437 Float_t pp = w[s];
438 if (pp == 0.0)
439 {
440 if ( AliAODParticle::GetDebug() > 5 )
441 Info("ReadNext","Probability of being PID %d is zero. Continuing.",pdgcode);
442 continue;
443 }
444
445 if(Pass(pdgcode))
446 {
447 if ( AliAODParticle::GetDebug() > 5 )
448 Info("ReadNext","PID (%d) did not pass the cut.",pdgcode);
449 continue; //check if we are intersted with particles of this type
450 }
451
452 Double_t mass = pdgdb->GetParticle(pdgcode)->Mass();
453 Double_t tEtot = TMath::Sqrt( mom[0]*mom[0] + mom[1]*mom[1] + mom[2]*mom[2] + mass*mass);//total energy of the track
454
455 AliAODStdParticle* track = new AliAODStdParticle(pdgcode, w[s],i,
456 mom[0], mom[1], mom[2], tEtot,
457 pos[0], pos[1], pos[2], 0.);
458 //copy probabilitis of other species (if not zero)
459 for (Int_t k = 0; k<kNSpecies; k++)
460 {
461 if (k == s) continue;
462 if (w[k] == 0.0) continue;
463 track->SetPIDprobability(charge*GetSpeciesPdgCode( (ESpecies)k ),w[k]);
464 }
465
466 if(Pass(track))//check if meets all criteria of any of our cuts
467 //if it does not delete it and take next good track
468 {
469 if ( AliAODParticle::GetDebug() > 4 )
470 Info("ReadNext","Track did not pass the cut");
471 delete track;
472 continue;
473 }
474
475 //Single Particle cuts on cluster map and track points rather do not have sense
476 if (tpts)
477 {
478 track->SetTrackPoints(tpts);
479 }
480
481 if (cmap)
482 {
483 track->SetClusterMap(cmap);
484 }
485
486 fEventRec->AddParticle(track);
487 if (particle) fEventSim->AddParticle(particle);
488 keeppart = kTRUE;
489
490 if (AliAODParticle::GetDebug() > 4 )
491 {
492 Info("ReadNext","\n\nAdding Particle with incarnation %d",pdgcode);
493 track->Print();
494 if (particle) particle->Print();
495 Info("ReadNext","\n----------------------------------------------\n");
496 }
497 }//for (Int_t s = 0; s<kNSpecies; s++)
498
499 if (keeppart == kFALSE)
500 {
501 delete particle;//particle was not stored in event
502 delete tpts;
503 delete cmap;
504 }
505
506 }//for (Int_t i = 0;i<ntr; i++) -- loop over tracks
507
508 Info("ReadNext","Read %d tracks and %d particles from event %d (event %d in dir %d).",
509 fEventRec->GetNumberOfParticles(), fEventSim->GetNumberOfParticles(),
510 fNEventsRead,fCurrentEvent,fCurrentDir);
511 fTrackCounter->Fill(fEventRec->GetNumberOfParticles());
512 return 0;
513}
514
515/**********************************************************/
516
517void AliReaderESD::Rewind()
518{
519 //rewinds reading
520 delete fKeyIterator;
521 delete fFile;
522 fFile = 0x0;
523 fKeyIterator = 0x0;
524 delete fRunLoader;
525 fRunLoader = 0x0;
526 fCurrentDir = 0;
527 fNEventsRead = 0;
528 if (fTrackCounter) fTrackCounter->Reset();
529}
530/**********************************************************/
531
532TFile* AliReaderESD::OpenFile(Int_t n)
533{
534//opens fFile with kine tree
535
536 const TString& dirname = GetDirName(n);
537 if (dirname == "")
538 {
539 Error("OpenFiles","Can not get directory name");
540 return 0x0;
541 }
542 TString filename = dirname +"/"+ fESDFileName;
543 TFile *ret = TFile::Open(filename.Data());
544
545 if ( ret == 0x0)
546 {
547 Error("OpenFiles","Can't open fFile %s",filename.Data());
548 return 0x0;
549 }
550 if (!ret->IsOpen())
551 {
552 Error("OpenFiles","Can't open fFile %s",filename.Data());
553 return 0x0;
554 }
555
556 if (fReadSim )
557 {
558 fRunLoader = AliRunLoader::Open(dirname +"/"+ fGAlFileName);
559 if (fRunLoader == 0x0)
560 {
561 Error("OpenFiles","Can't get RunLoader for directory %s",dirname.Data());
562 delete ret;
563 return 0x0;
564 }
565
566 fRunLoader->LoadHeader();
567 if (fRunLoader->LoadKinematics())
568 {
569 Error("Next","Error occured while loading kinematics.");
570 delete fRunLoader;
571 delete ret;
572 return 0x0;
573 }
574 }
575
576 return ret;
577}
578/**********************************************************/
579
580Int_t AliReaderESD::GetSpeciesPdgCode(ESpecies spec)//skowron
581{
582 //returns pdg code from the PID index
583 //ask jura about charge
584 switch (spec)
585 {
586 case kESDElectron:
587 return kPositron;
588 break;
589 case kESDMuon:
590 return kMuonPlus;
591 break;
592 case kESDPion:
593 return kPiPlus;
594 break;
595 case kESDKaon:
596 return kKPlus;
597 break;
598 case kESDProton:
599 return kProton;
600 break;
601 default:
602 ::Warning("GetSpeciesPdgCode","Specie with number %d is not defined.",(Int_t)spec);
603 break;
604 }
605 return 0;
606}
607/********************************************************************/
608Bool_t AliReaderESD::CheckTrack(AliESDtrack* t) const
609{
610 //Performs check of the track
611
612 if ( (t->GetConstrainedChi2() < fChi2Min) || (t->GetConstrainedChi2() > fChi2Max) ) return kTRUE;
613
614 if ( (t->GetTPCclusters(0x0) < fNTPCClustMin) || (t->GetTPCclusters(0x0) > fNTPCClustMax) ) return kTRUE;
615
616 if (t->GetTPCclusters(0x0) > 0)
617 {
618 Float_t chisqpercl = t->GetTPCchi2()/((Double_t)t->GetTPCclusters(0x0));
619 if ( (chisqpercl < fTPCChi2PerClustMin) || (chisqpercl > fTPCChi2PerClustMax) ) return kTRUE;
620 }
621
622 Double_t cc[15];
623 t->GetConstrainedExternalCovariance(cc);
624
625 if ( (cc[0] < fC00Min) || (cc[0] > fC00Max) ) return kTRUE;
626 if ( (cc[2] < fC11Min) || (cc[2] > fC11Max) ) return kTRUE;
627 if ( (cc[5] < fC22Min) || (cc[5] > fC22Max) ) return kTRUE;
628 if ( (cc[9] < fC33Min) || (cc[9] > fC33Max) ) return kTRUE;
629 if ( (cc[14] < fC44Min) || (cc[14] > fC44Max) ) return kTRUE;
630
631
632 t->GetInnerExternalCovariance(cc);
633
634 if ( (cc[0] < fTPCC00Min) || (cc[0] > fTPCC00Max) ) return kTRUE;
635 if ( (cc[2] < fTPCC11Min) || (cc[2] > fTPCC11Max) ) return kTRUE;
636 if ( (cc[5] < fTPCC22Min) || (cc[5] > fTPCC22Max) ) return kTRUE;
637 if ( (cc[9] < fTPCC33Min) || (cc[9] > fTPCC33Max) ) return kTRUE;
638 if ( (cc[14] < fTPCC44Min) || (cc[14] > fTPCC44Max) ) return kTRUE;
639
640 return kFALSE;
641
642}
643/********************************************************************/
644
645void AliReaderESD::SetChi2Range(Float_t min, Float_t max)
646{
647 //sets range of Chi2 per Cluster
648 fChi2Min = min;
649 fChi2Max = max;
650}
651/********************************************************************/
652
653void AliReaderESD::SetTPCNClustersRange(Int_t min,Int_t max)
654{
655 //sets range of Number Of Clusters that tracks have to have
656 fNTPCClustMin = min;
657 fNTPCClustMax = max;
658}
659/********************************************************************/
660
661void AliReaderESD::SetTPCChi2PerCluserRange(Float_t min, Float_t max)
662{
663 //sets range of Chi2 per Cluster
664 fTPCChi2PerClustMin = min;
665 fTPCChi2PerClustMax = max;
666}
667/********************************************************************/
668
669void AliReaderESD::SetC00Range(Float_t min, Float_t max)
670{
671 //Sets range of C00 parameter of covariance matrix of the track
672 //it defines uncertainty of the momentum
673 fC00Min = min;
674 fC00Max = max;
675}
676/********************************************************************/
677
678void AliReaderESD::SetC11Range(Float_t min, Float_t max)
679{
680 //Sets range of C11 parameter of covariance matrix of the track
681 //it defines uncertainty of the momentum
682 fC11Min = min;
683 fC11Max = max;
684}
685/********************************************************************/
686
687void AliReaderESD::SetC22Range(Float_t min, Float_t max)
688{
689 //Sets range of C22 parameter of covariance matrix of the track
690 //it defines uncertainty of the momentum
691 fC22Min = min;
692 fC22Max = max;
693}
694/********************************************************************/
695
696void AliReaderESD::SetC33Range(Float_t min, Float_t max)
697{
698 //Sets range of C33 parameter of covariance matrix of the track
699 //it defines uncertainty of the momentum
700 fC33Min = min;
701 fC33Max = max;
702}
703/********************************************************************/
704
705void AliReaderESD::SetC44Range(Float_t min, Float_t max)
706{
707 //Sets range of C44 parameter of covariance matrix of the track
708 //it defines uncertainty of the momentum
709 fC44Min = min;
710 fC44Max = max;
711}