Protection to skip PYTHIA events with large jet energy compared to pTHard
[u/mrichter/AliRoot.git] / PWG4 / PartCorrBase / AliMCAnalysisUtils.cxx
CommitLineData
abde65b8 1/**************************************************************************\r
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *\r
3 * *\r
4 * Author: The ALICE Off-line Project. *\r
5 * Contributors are mentioned in the code where appropriate. *\r
6 * *\r
7 * Permission to use, copy, modify and distribute this software and its *\r
8 * documentation strictly for non-commercial purposes is hereby granted *\r
9 * without fee, provided that the above copyright notice appears in all *\r
10 * copies and that both the copyright notice and this permission notice *\r
11 * appear in the supporting documentation. The authors make no claims *\r
12 * about the suitability of this software for any purpose. It is *\r
13 * provided "as is" without express or implied warranty. *\r
14 **************************************************************************/\r
15/* $Id: AliMCAnalysisUtils.cxx 21839 2007-10-29 13:49:42Z gustavo $ */\r
16\r
17//_________________________________________________________________________\r
18// Class for analysis utils for MC data\r
19// stored in stack or event header.\r
20// Contains:\r
21// - method to check the origin of a given track/cluster\r
22// - method to obtain the generated jets\r
23// \r
24//*-- Author: Gustavo Conesa (LNF-INFN) \r
25//////////////////////////////////////////////////////////////////////////////\r
26 \r
27\r
28// --- ROOT system ---\r
29#include <TMath.h>\r
30#include <TList.h>\r
31\r
32//---- ANALYSIS system ----\r
33#include "AliMCAnalysisUtils.h"\r
34#include "AliStack.h"\r
35#include "TParticle.h"\r
36#include "AliGenPythiaEventHeader.h"\r
37\r
38 ClassImp(AliMCAnalysisUtils)\r
39\r
40 //________________________________________________\r
41 AliMCAnalysisUtils::AliMCAnalysisUtils() : \r
42 TObject(), fCurrentEvent(-1), fDebug(-1), \r
29b2ceec 43 fJetsList(new TList), fMCGenerator("PYTHIA"), fpTHardpTJetFactor(7)\r
abde65b8 44{\r
45 //Ctor\r
46}\r
47\r
48//____________________________________________________________________________\r
49AliMCAnalysisUtils::AliMCAnalysisUtils(const AliMCAnalysisUtils & mcutils) : \r
50 TObject(mcutils), fCurrentEvent(mcutils.fCurrentEvent), fDebug(mcutils.fDebug),\r
29b2ceec 51 fJetsList(mcutils.fJetsList), fMCGenerator(mcutils.fMCGenerator), fpTHardpTJetFactor(mcutils.fpTHardpTJetFactor)\r
abde65b8 52{\r
53 // cpy ctor\r
54 \r
55}\r
56\r
57//_________________________________________________________________________\r
58AliMCAnalysisUtils & AliMCAnalysisUtils::operator = (const AliMCAnalysisUtils & mcutils)\r
59{\r
60 // assignment operator\r
61 \r
62 if(&mcutils == this) return *this;\r
63 fCurrentEvent = mcutils.fCurrentEvent ;\r
64 fDebug = mcutils.fDebug;\r
65 fJetsList = mcutils.fJetsList;\r
66 fMCGenerator = mcutils.fMCGenerator;\r
29b2ceec 67 fpTHardpTJetFactor = mcutils.fpTHardpTJetFactor;\r
abde65b8 68 \r
69 return *this; \r
70}\r
71\r
72//____________________________________________________________________________\r
73AliMCAnalysisUtils::~AliMCAnalysisUtils() \r
74{\r
75 // Remove all pointers.\r
76 \r
77 if (fJetsList) {\r
78 fJetsList->Clear();\r
79 delete fJetsList ;\r
80 } \r
81}\r
82\r
83//_________________________________________________________________________\r
84Int_t AliMCAnalysisUtils::CheckOrigin(const Int_t label, AliStack * stack) const {\r
85 //Play with the MC stack if available\r
86 //Check origin of the candidates, good for PYTHIA\r
87 \r
88 if(!stack) {\r
89 printf("AliMCAnalysisUtils::CheckOrigin() - Stack is not available, check analysis settings in configuration file, STOP!!\n");\r
90 abort();\r
91 }\r
92 // printf("label %d, ntrack %d, nprim %d\n",label, stack->GetNtrack(), stack->GetNprimary());\r
93 // for(Int_t i = 0; i< stack->GetNprimary(); i++){\r
94 // TParticle *particle = stack->Particle(i);\r
95 // //particle->Print();\r
96 // }\r
97 if(label >= 0 && label < stack->GetNtrack()){\r
98 //Mother\r
99 TParticle * mom = stack->Particle(label);\r
100 Int_t mPdg = TMath::Abs(mom->GetPdgCode());\r
101 Int_t mStatus = mom->GetStatusCode() ;\r
102 Int_t iParent = mom->GetFirstMother() ;\r
103 if(fDebug > 0 && label < 8 ) printf("AliMCAnalysisUtils::CheckOrigin: Mother is parton %d\n",iParent);\r
104 \r
105 //GrandParent\r
106 TParticle * parent = new TParticle ;\r
107 Int_t pPdg = -1;\r
108 Int_t pStatus =-1;\r
109 if(iParent > 0){\r
110 parent = stack->Particle(iParent);\r
111 pPdg = TMath::Abs(parent->GetPdgCode());\r
112 pStatus = parent->GetStatusCode(); \r
113 }\r
114 else if(fDebug > 0 ) printf("AliMCAnalysisUtils::CheckOrigin: Parent with label %d\n",iParent);\r
115 \r
116 //return tag\r
117 if(mPdg == 22){ //photon\r
118 if(mStatus == 1){ //undecayed particle\r
119 if(fMCGenerator == "PYTHIA"){\r
120 if(iParent < 8 && iParent > 5) {//outgoing partons\r
121 if(pPdg == 22) return kMCPrompt;\r
122 else return kMCFragmentation;\r
123 }//Outgoing partons\r
124 else if(pStatus == 11){//Decay\r
125 if(pPdg == 111) return kMCPi0Decay ;\r
126 else if (pPdg == 221) return kMCEtaDecay ;\r
127 else return kMCOtherDecay ;\r
128 }//Decay\r
129 else return kMCISR; //Initial state radiation\r
130 }//PYTHIA\r
131\r
132 else if(fMCGenerator == "HERWIG"){ \r
133 if(pStatus < 197){//Not decay\r
134 while(1){\r
135 if(parent->GetFirstMother()<=5) break;\r
136 iParent = parent->GetFirstMother();\r
137 parent=stack->Particle(iParent);\r
138 pStatus= parent->GetStatusCode();\r
139 pPdg = parent->GetPdgCode();\r
140 }//Look for the parton\r
141 \r
142 if(iParent < 8 && iParent > 5) {\r
143 if(pPdg == 22) return kMCPrompt;\r
144 else return kMCFragmentation;\r
145 }\r
146 return kMCISR;//Initial state radiation\r
147 }//Not decay\r
148 else{//Decay\r
149 if(pPdg == 111) return kMCPi0Decay ;\r
150 else if (pPdg == 221) return kMCEtaDecay ;\r
151 else return kMCOtherDecay ;\r
152 }//Decay\r
153 }//HERWIG\r
154 else return kMCUnknown;\r
155 }//Status 1 : Pythia generated\r
156 else if(mStatus == 0){\r
157 if(pPdg ==22 || pPdg ==11|| pPdg == 2112 || pPdg == 211 || \r
158 pPdg == 321 || pPdg == 2212 || pPdg == 130 || pPdg == 13 ) \r
159 return kMCConversion ;\r
160 if(pPdg == 111) return kMCPi0Decay ;\r
161 else if (pPdg == 221) return kMCEtaDecay ;\r
162 else return kMCOtherDecay ;\r
163 }//status 0 : geant generated\r
164 }//Mother Photon\r
165 else if(mPdg == 111) return kMCPi0 ;\r
166 else if(mPdg == 221) return kMCEta ;\r
167\r
168 //cluster's mother is an electron. Where did that electron come from?\r
169 else if(mPdg == 11){ //electron\r
170\r
171 if(fDebug > 0) printf("AliMCAnalysisUtils::CheckOrigin: Checking ancestors of electrons");\r
172\r
173 //check first for B and C ancestry, then other possibilities.\r
174 //An electron from a photon parent could have other particles in\r
175 //its history and we would want to know that, right?\r
176\r
177 if(mStatus == 1) { //electron from event generator\r
178 if (pPdg == -1) return kMCElectron; //no parent\r
179 else if (pPdg == 23) return kMCZDecay; //parent is Z-boson\r
180 else if (pPdg == 24) return kMCWDecay; //parent is W-boson\r
181 else { //check the electron's ancestors for B/C contribution\r
29b2ceec 182 Bool_t bAncestor = kFALSE;\r
183 Bool_t cAncestor = kFALSE;\r
abde65b8 184 TParticle * ancestors = stack->Particle(label);\r
185 Int_t aPdg = TMath::Abs(ancestors->GetPdgCode());\r
186 //Int_t aStatus = ancestors->GetStatusCode();\r
187 Int_t iAncestors = ancestors->GetFirstMother();\r
188 if(fDebug > 0) printf("AliMCAnalysisUtils::CheckOrigin: Scaning the decay chain for bottom/charm generated electron");\r
189 while(ancestors->IsPrimary()){//searching for ancestors \r
29b2ceec 190 if((499 < aPdg && aPdg < 600)||(4999 < aPdg && aPdg < 6000)) bAncestor = kTRUE;\r
191 if((399 < aPdg && aPdg < 500)||(3999 < aPdg && aPdg < 5000)) cAncestor = kTRUE;\r
192 if(bAncestor && cAncestor) break;\r
abde65b8 193 iAncestors = ancestors->GetFirstMother();\r
194 ancestors = stack->Particle(iAncestors);\r
195 aPdg = ancestors->GetPdgCode();\r
196 }//searching for ancestors\r
29b2ceec 197 if(bAncestor && cAncestor) return kMCEFromCFromB;//Decay chain has both B and C\r
198 else if(bAncestor && !cAncestor) return kMCEFromB;//Decay chain has only B\r
199 else if(!bAncestor && cAncestor) return kMCEFromC;//Decay chain has only C \r
abde65b8 200 }\r
201 //if it is not from W,Z or B/C ancestor, where is it from?\r
202 if (pPdg == 111) return kMCPi0Decay;//Pi0 Dalitz decay\r
203 else if(pPdg == 221) return kMCEtaDecay;//Eta Dalitz decay\r
204 else return kMCOtherDecay;\r
205\r
206 } else if (mStatus == 0) { //electron from GEANT\r
207\r
208 //Rewind ancestry and check for electron with status == 1\r
209 //if we find one, we'll assume that this object is from an\r
210 //electron but that it may have gone through some showering in\r
211 //material before the detector\r
212\r
213 //Not a double-counting problem because we are only accessing\r
214 //these histories for MC labels connected to a reco object.\r
215 //If you wanted to use this to sort through the kine stack\r
216 //directly, might it be a problem?\r
29b2ceec 217 Bool_t eleFromEvGen = kFALSE;\r
218 Bool_t bAncestor = kFALSE;\r
219 Bool_t cAncestor = kFALSE;\r
abde65b8 220\r
221 TParticle * ancestors = stack->Particle(label);\r
29b2ceec 222 Int_t aPdg = TMath::Abs(ancestors->GetPdgCode());\r
223 Int_t aStatus = ancestors->GetStatusCode();\r
224 Int_t iAncestors = ancestors->GetFirstMother();\r
225 if(fDebug > 0) printf("AliMCAnalysisUtils::CheckOrigin: Scaning the decay chain for bottom/charm electrons");\r
abde65b8 226 while(ancestors->IsPrimary()){//searching for ancestors\r
29b2ceec 227 if(aStatus == 1 && aPdg == 11) eleFromEvGen = kTRUE;\r
228 if(eleFromEvGen && aPdg == 23) return kMCZDecay;\r
229 if(eleFromEvGen && aPdg == 24) return kMCWDecay;\r
230 if(eleFromEvGen && ((499 < aPdg && aPdg < 600)||(4999 < aPdg && aPdg < 6000))) bAncestor = kTRUE;\r
231 if(eleFromEvGen && ((399 < aPdg && aPdg < 500)||(3999 < aPdg && aPdg < 5000))) cAncestor = kTRUE;\r
232 if(bAncestor && cAncestor) break;\r
abde65b8 233 iAncestors = ancestors->GetFirstMother();\r
234 ancestors = stack->Particle(iAncestors);\r
235 aPdg = ancestors->GetPdgCode();\r
236 }//searching for ancestors\r
29b2ceec 237 if(bAncestor && cAncestor) return kMCEFromCFromB;//Decay chain has both B and C\r
238 else if(bAncestor && !cAncestor) return kMCEFromB;//Decay chain has only B\r
239 else if(!bAncestor && cAncestor) return kMCEFromC;//Decay chain has only C\r
abde65b8 240 if(pPdg ==22 || pPdg ==11|| pPdg == 2112 || pPdg == 211 || \r
241 pPdg == 321 || pPdg == 2212 || pPdg == 130 || pPdg == 13 ) \r
242 return kMCConversion ;\r
243 if(pPdg == 111) return kMCPi0Decay ;\r
244 else if (pPdg == 221) return kMCEtaDecay ;\r
245 else return kMCOtherDecay ;\r
246 } //GEANT check\r
247 }//electron check\r
248 else return kMCUnknown;\r
249 }//Good label value\r
250 else{\r
251 if(label < 0 ) printf("AliMCAnalysisUtils::CheckOrigin: *** bad label or no stack ***: label %d \n", label);\r
252 if(label >= stack->GetNtrack()) printf("AliMCAnalysisUtils::CheckOrigin: *** large label ***: label %d, n tracks %d \n", label, stack->GetNtrack());\r
253 return kMCUnknown;\r
254 }//Bad label\r
255 \r
256 return kMCUnknown;\r
257 \r
258}\r
259\r
260//_________________________________________________________________________\r
29b2ceec 261TList * AliMCAnalysisUtils::GetJets(const Int_t iEvent, AliStack * stack, const AliGenEventHeader * geh) {\r
abde65b8 262 //Return list of jets (TParticles) and index of most likely parton that originated it.\r
263 \r
264 if(fCurrentEvent!=iEvent){\r
265 fCurrentEvent = iEvent;\r
266 fJetsList = new TList;\r
267 Int_t nTriggerJets = 0;\r
268 Float_t tmpjet[]={0,0,0,0};\r
269 \r
270 //printf("Event %d %d\n",fCurrentEvent,iEvent);\r
271 //Get outgoing partons\r
272 if(stack->GetNtrack() < 8) return fJetsList;\r
273 TParticle * parton1 = stack->Particle(6);\r
274 TParticle * parton2 = stack->Particle(7);\r
275 if(fDebug > 2){\r
276 printf("AliMCAnalysisUtils::GetJets() - parton 6 : %s, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",\r
277 parton1->GetName(),parton1->Pt(),parton1->Energy(),parton1->Phi()*TMath::RadToDeg(),parton1->Eta());\r
278 printf("AliMCAnalysisUtils::GetJets() - parton 7 : %s, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",\r
279 parton2->GetName(),parton2->Pt(),parton2->Energy(),parton2->Phi()*TMath::RadToDeg(),parton2->Eta());\r
280 }\r
281// //Trace the jet from the mother parton\r
282// Float_t pt = 0;\r
283// Float_t pt1 = 0;\r
284// Float_t pt2 = 0;\r
285// Float_t e = 0;\r
286// Float_t e1 = 0;\r
287// Float_t e2 = 0;\r
288// TParticle * tmptmp = new TParticle;\r
289// for(Int_t i = 0; i< stack->GetNprimary(); i++){\r
290// tmptmp = stack->Particle(i);\r
291 \r
292// if(tmptmp->GetStatusCode() == 1){\r
293// pt = tmptmp->Pt();\r
294// e = tmptmp->Energy(); \r
295// Int_t imom = tmptmp->GetFirstMother();\r
296// Int_t imom1 = 0;\r
297// //printf("1st imom %d\n",imom);\r
298// while(imom > 5){\r
299// imom1=imom;\r
300// tmptmp = stack->Particle(imom);\r
301// imom = tmptmp->GetFirstMother();\r
302// //printf("imom %d \n",imom);\r
303// }\r
304// //printf("Last imom %d %d\n",imom1, imom);\r
305// if(imom1 == 6) {\r
306// pt1+=pt;\r
307// e1+=e; \r
308// }\r
309// else if (imom1 == 7){\r
310// pt2+=pt;\r
311// e2+=e; }\r
312// }// status 1\r
313 \r
314// }// for\r
315 \r
316// printf("JET 1, pt %2.2f, e %2.2f; JET 2, pt %2.2f, e %2.2f \n",pt1,e1,pt2,e2);\r
317 \r
318 //Get the jet, different way for different generator\r
319 //PYTHIA\r
320 if(fMCGenerator == "PYTHIA"){\r
321 TParticle * jet = new TParticle;\r
322 AliGenPythiaEventHeader* pygeh= (AliGenPythiaEventHeader*) geh;\r
323 nTriggerJets = pygeh->NTriggerJets();\r
324 if(fDebug > 1)\r
325 printf("AliMCAnalysisUtils::GetJets() - PythiaEventHeader: Njets: %d\n",nTriggerJets);\r
326 \r
327 Int_t iparton = -1;\r
328 for(Int_t i = 0; i< nTriggerJets; i++){\r
329 iparton=-1;\r
330 pygeh->TriggerJet(i, tmpjet);\r
331 jet = new TParticle(94, 21, -1, -1, -1, -1, tmpjet[0],tmpjet[1],tmpjet[2],tmpjet[3], 0,0,0,0);\r
332 //Assign an outgoing parton as mother\r
333 Float_t phidiff1 = TMath::Abs(jet->Phi()-parton1->Phi()); \r
334 Float_t phidiff2 = TMath::Abs(jet->Phi()-parton2->Phi());\r
335 if(phidiff1 > phidiff2) jet->SetFirstMother(7);\r
336 else jet->SetFirstMother(6);\r
337 //jet->Print();\r
338 if(fDebug > 1)\r
339 printf("AliMCAnalysisUtils::GetJets() - PYTHIA Jet %d: mother %d, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",\r
340 i, jet->GetFirstMother(),jet->Pt(),jet->Energy(),jet->Phi()*TMath::RadToDeg(),jet->Eta());\r
341 fJetsList->Add(jet); \r
342 }\r
343 }//Pythia triggered jets\r
344 //HERWIG\r
345 else if (fMCGenerator=="HERWIG"){\r
346 Int_t pdg = -1; \r
347 //Check parton 1\r
348 TParticle * tmp = parton1;\r
349 if(parton1->GetPdgCode()!=22){\r
350 while(pdg != 94){\r
351 if(tmp->GetFirstDaughter()==-1) return fJetsList;\r
352 tmp = stack->Particle(tmp->GetFirstDaughter());\r
353 pdg = tmp->GetPdgCode();\r
354 }//while\r
355 \r
356 //Add found jet to list\r
357 TParticle *jet1 = new TParticle(*tmp);\r
358 jet1->SetFirstMother(6);\r
359 fJetsList->Add(jet1);\r
360 //printf("jet 1: first daughter %d, last daughter %d\n", tmp->GetFirstDaughter(), tmp->GetLastDaughter());\r
361 //tmp = stack->Particle(tmp->GetFirstDaughter());\r
362 //tmp->Print();\r
363 //jet1->Print();\r
364 if(fDebug > 1) \r
365 printf("AliMCAnalysisUtils::GetJets() - HERWIG Jet 1: mother %d, status %d, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",\r
366 jet1->GetFirstMother(),jet1->GetStatusCode(),jet1->Pt(),jet1->Energy(),jet1->Phi()*TMath::RadToDeg(),jet1->Eta());\r
367 }//not photon\r
368 \r
369 //Check parton 2\r
370 pdg = -1;\r
371 tmp = parton2;\r
372 Int_t i = -1;\r
373 if(parton2->GetPdgCode()!=22){\r
374 while(pdg != 94){\r
375 if(tmp->GetFirstDaughter()==-1) return fJetsList;\r
376 i = tmp->GetFirstDaughter();\r
377 tmp = stack->Particle(tmp->GetFirstDaughter());\r
378 pdg = tmp->GetPdgCode();\r
379 }//while\r
380 //Add found jet to list\r
381 TParticle *jet2 = new TParticle(*tmp);\r
382 jet2->SetFirstMother(7);\r
383 fJetsList->Add(jet2);\r
384 //jet2->Print();\r
385 if(fDebug > 1)\r
386 printf("AliMCAnalysisUtils::GetJets() - HERWIG Jet 2: mother %d, status %d, pt %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",\r
387 jet2->GetFirstMother(),jet2->GetStatusCode(),jet2->Pt(),jet2->Energy(),jet2->Phi()*TMath::RadToDeg(),jet2->Eta());\r
388 //Int_t first = tmp->GetFirstDaughter();\r
389 //Int_t last = tmp->GetLastDaughter();\r
390 //printf("jet 2: first daughter %d, last daughter %d, pdg %d\n",first, last, tmp->GetPdgCode());\r
391 // for(Int_t d = first ; d < last+1; d++){\r
392// tmp = stack->Particle(d);\r
393// if(i == tmp->GetFirstMother())\r
394// printf("Daughter n %d, Mother %d, name %s, status %d, pT %2.2f,E %2.2f, phi %2.2f, eta %2.2f \n",\r
395// d,tmp->GetFirstMother(), tmp->GetName(), tmp->GetStatusCode(),tmp->Pt(),tmp->Energy(),tmp->Phi()*TMath::RadToDeg(),tmp->Eta()); \r
396// }\r
397 //tmp->Print();\r
398 }//not photon\r
399 }//Herwig generated jets\r
400 }\r
401 \r
402 return fJetsList;\r
403}\r
404\r
29b2ceec 405\r
406//_________________________________________________________________________\r
407Bool_t AliMCAnalysisUtils::ComparePtHardAndJetPt(const AliGenEventHeader * geh){\r
408 // Check the event, if the requested ptHard is much larger than the jet pT, then there is a problem.\r
409 // Only for PYTHIA.\r
410 \r
411 if(fMCGenerator == "PYTHIA"){\r
412 TParticle * jet = new TParticle;\r
413 AliGenPythiaEventHeader* pygeh= (AliGenPythiaEventHeader*) geh;\r
414 Int_t nTriggerJets = pygeh->NTriggerJets();\r
415 Float_t ptHard = pygeh->GetPtHard();\r
416\r
417 //if(fDebug > 1) printf("AliMCAnalysisUtils::PythiaEventHeader: Njets: %d, pT Hard %f\n",nTriggerJets, ptHard);\r
418 Float_t tmpjet[]={0,0,0,0};\r
419 for(Int_t ijet = 0; ijet< nTriggerJets; ijet++){\r
420 pygeh->TriggerJet(ijet, tmpjet);\r
421 jet = new TParticle(94, 21, -1, -1, -1, -1, tmpjet[0],tmpjet[1],tmpjet[2],tmpjet[3], 0,0,0,0);\r
422 //Compare jet pT and pt Hard\r
423 //if(fDebug > 1) printf("AliMCAnalysisUtils:: %d pycell jet pT %f\n",ijet, jet->Pt());\r
424 if(jet->Pt() > fpTHardpTJetFactor * ptHard) {\r
425 printf("AliMCAnalysisUtils::PythiaEventHeader: Njets: %d, pT Hard %2.2f, pycell jet pT %2.2f, rejection factor %1.1f\n",\r
426 nTriggerJets, ptHard, jet->Pt(), fpTHardpTJetFactor);\r
427 return kFALSE;\r
428 }\r
429 }\r
430 } \r
431 \r
432 return kTRUE ;\r
433\r
434}\r
435\r
abde65b8 436//________________________________________________________________\r
437void AliMCAnalysisUtils::Print(const Option_t * opt) const\r
438{\r
439 //Print some relevant parameters set for the analysis\r
440 \r
441 if(! opt)\r
442 return;\r
443 \r
444 printf("***** Print: %s %s ******\n", GetName(), GetTitle() ) ;\r
445 \r
446 printf("Debug level = %d\n",fDebug);\r
447 printf("MC Generator = %s\n",fMCGenerator.Data());\r
29b2ceec 448 printf("fpTHardpTJetFactor = %2.2f",fpTHardpTJetFactor);\r
abde65b8 449 printf(" \n");\r
450 \r
451} \r
452\r
453\r