]>
Commit | Line | Data |
---|---|---|
d810d0de | 1 | // $Id$ |
2 | // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007 | |
3b868b75 | 3 | |
d810d0de | 4 | /************************************************************************** |
5 | * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. * | |
6 | * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for * | |
51346b82 | 7 | * full copyright notice. * |
d810d0de | 8 | **************************************************************************/ |
9 | ||
10 | #include "AliEveITSScaledModule.h" | |
3b868b75 | 11 | |
0879c50b | 12 | #include <AliITSsegmentationSPD.h> |
13 | #include <AliITSsegmentationSDD.h> | |
14 | #include <AliITSsegmentationSSD.h> | |
15 | ||
3b868b75 | 16 | #include <AliITSdigitSPD.h> |
17 | #include <AliITSdigitSDD.h> | |
18 | #include <AliITSdigitSSD.h> | |
d810d0de | 19 | |
0879c50b | 20 | #include <TMath.h> |
a15e6d7d | 21 | #include <TClonesArray.h> |
3b868b75 | 22 | |
a15e6d7d | 23 | //============================================================================== |
24 | //============================================================================== | |
d810d0de | 25 | // AliEveDigitScaleInfo |
a15e6d7d | 26 | //============================================================================== |
27 | ||
28 | //______________________________________________________________________________ | |
3b868b75 | 29 | // |
a15e6d7d | 30 | // Encapsulates current state of scaling and agglomeration. |
698e2c9b | 31 | |
d810d0de | 32 | ClassImp(AliEveDigitScaleInfo) |
3b868b75 | 33 | |
d810d0de | 34 | AliEveDigitScaleInfo::AliEveDigitScaleInfo(): |
3b868b75 | 35 | fScale(1), |
a15e6d7d | 36 | fStatType (kSTAverage), |
32e219c2 | 37 | fSyncPalette(kFALSE) |
3b868b75 | 38 | { |
39 | } | |
40 | ||
d810d0de | 41 | void AliEveDigitScaleInfo::ScaleChanged(Int_t s) |
3b868b75 | 42 | { |
32e219c2 | 43 | fScale = s; |
51346b82 | 44 | |
d810d0de | 45 | AliEveITSScaledModule* sm; |
22828c05 | 46 | #if ROOT_VERSION_CODE >= 334599 |
47 | RefMap_i i = fBackRefs.begin(); | |
48 | #else | |
84aff7a4 | 49 | std::list<TEveElement*>::iterator i = fBackRefs.begin(); |
22828c05 | 50 | #endif |
32e219c2 | 51 | while (i != fBackRefs.end()) |
52 | { | |
22828c05 | 53 | #if ROOT_VERSION_CODE >= 334599 |
54 | sm = dynamic_cast<AliEveITSScaledModule*>((*i).first); | |
55 | #else | |
d810d0de | 56 | sm = dynamic_cast<AliEveITSScaledModule*>(*i); |
22828c05 | 57 | #endif |
32e219c2 | 58 | if(sm) sm->LoadQuads(); |
59 | ++i; | |
60 | } | |
3b868b75 | 61 | } |
62 | ||
d810d0de | 63 | void AliEveDigitScaleInfo::StatTypeChanged(Int_t t) |
3b868b75 | 64 | { |
32e219c2 | 65 | fStatType = t; |
66 | fSyncPalette = kTRUE; | |
51346b82 | 67 | |
d810d0de | 68 | AliEveITSScaledModule* sm; |
22828c05 | 69 | #if ROOT_VERSION_CODE >= 334599 |
70 | RefMap_i i = fBackRefs.begin(); | |
71 | #else | |
84aff7a4 | 72 | std::list<TEveElement*>::iterator i = fBackRefs.begin(); |
22828c05 | 73 | #endif |
32e219c2 | 74 | while (i != fBackRefs.end()) |
75 | { | |
22828c05 | 76 | #if ROOT_VERSION_CODE >= 334599 |
77 | sm = dynamic_cast<AliEveITSScaledModule*>((*i).first); | |
78 | #else | |
d810d0de | 79 | sm = dynamic_cast<AliEveITSScaledModule*>(*i); |
22828c05 | 80 | #endif |
a15e6d7d | 81 | if (sm) sm->SetQuadValues(); |
32e219c2 | 82 | ++i; |
83 | } | |
3b868b75 | 84 | } |
85 | ||
57ffa5fb | 86 | //______________________________________________________________________________ |
a15e6d7d | 87 | // ScaledDigit_t |
3b868b75 | 88 | // |
c76ea574 | 89 | |
a15e6d7d | 90 | AliEveITSScaledModule::ScaledDigit_t::ScaledDigit_t() : |
3b868b75 | 91 | TObject(), |
a15e6d7d | 92 | fN(0), |
93 | fSum(0), fSqrSum(0), | |
94 | fMinI(-1), fMinJ(-1), fMaxI(-1), fMaxJ(-1) | |
3b868b75 | 95 | { |
96 | } | |
97 | ||
a15e6d7d | 98 | AliEveITSScaledModule::ScaledDigit_t::ScaledDigit_t(Int_t di, Int_t dj) : |
3b868b75 | 99 | TObject(), |
a15e6d7d | 100 | fN(0), |
101 | fSum(0), fSqrSum(0), | |
102 | fMinI(di), fMinJ(dj), fMaxI(di), fMaxJ(dj) | |
3b868b75 | 103 | { |
104 | } | |
105 | ||
a15e6d7d | 106 | void AliEveITSScaledModule::ScaledDigit_t::Dump() const |
3b868b75 | 107 | { |
a15e6d7d | 108 | printf("N %d, sum %f, sqr_sum %f", fN, fSum, fSqrSum); |
3b868b75 | 109 | } |
110 | ||
698e2c9b | 111 | |
a15e6d7d | 112 | //============================================================================== |
113 | //============================================================================== | |
d810d0de | 114 | // AliEveITSScaledModule |
a15e6d7d | 115 | //============================================================================== |
698e2c9b | 116 | |
117 | //______________________________________________________________________________ | |
3b868b75 | 118 | // |
698e2c9b | 119 | // Visualization of an ITS module with digits aggregated |
120 | // on a grid of pre-defined size. | |
3b868b75 | 121 | |
d810d0de | 122 | ClassImp(AliEveITSScaledModule) |
3b868b75 | 123 | |
d810d0de | 124 | AliEveITSScaledModule::AliEveITSScaledModule(Int_t gid, AliEveITSDigitsInfo* info, AliEveDigitScaleInfo* si): |
125 | AliEveITSModule("AliEveITSScaledModule", "AliEveITSScaledModule"), | |
3b868b75 | 126 | fNx(-1), |
127 | fNz(-1), | |
128 | fNCx(-1), | |
03dfc4a7 | 129 | fNCz(-1), |
9af86b69 | 130 | fScaleInfo(si), |
131 | fDigitsMap() | |
3b868b75 | 132 | { |
3b868b75 | 133 | SetOwnIds(kTRUE); |
134 | ||
135 | SetDigitsInfo(info); | |
51346b82 | 136 | SetID(gid); |
32e219c2 | 137 | fScaleInfo->IncRefCount(this); |
3b868b75 | 138 | } |
139 | ||
d810d0de | 140 | AliEveITSScaledModule::~AliEveITSScaledModule() |
3b868b75 | 141 | { |
32e219c2 | 142 | fScaleInfo->DecRefCount(this); |
3b868b75 | 143 | } |
144 | ||
57ffa5fb | 145 | /******************************************************************************/ |
3b868b75 | 146 | |
d810d0de | 147 | void AliEveITSScaledModule::LoadQuads() |
3b868b75 | 148 | { |
149 | // Here we still use 'z' for the name of axial coordinates. | |
150 | // The transforamtion matrix aplied rotates y -> z. | |
84aff7a4 | 151 | // We need this as TEveQuadSet offers optimized treatment for |
3b868b75 | 152 | // quads in the x-y plane. |
153 | ||
a4135a45 | 154 | TClonesArray *digits = fInfo->GetDigits(fID, fDetID); |
155 | if (!digits) return; | |
156 | ||
157 | Int_t ndigits = digits->GetEntriesFast(); | |
158 | ||
3b868b75 | 159 | Float_t x, z, zo, dpx, dpz; // orig cells size, pos |
a4135a45 | 160 | Int_t i, j; // orig cells idx |
161 | Int_t c1, c2; // original coordinates | |
3b868b75 | 162 | |
163 | Int_t id; | |
fd31e9de | 164 | std::map<Int_t, Int_t> dmap; |
165 | std::map<Int_t, Int_t>::iterator miter; | |
3b868b75 | 166 | |
03dfc4a7 | 167 | Int_t scale = fScaleInfo->GetScale() -1; |
3b868b75 | 168 | switch(fDetID) |
169 | { | |
51346b82 | 170 | case 0: |
171 | { | |
3b868b75 | 172 | // SPD |
84aff7a4 | 173 | Reset(kQT_RectangleXZFixedY, kFALSE, 32); |
3b868b75 | 174 | |
175 | fNCz = fInfo->fSPDScaleZ[scale]; | |
176 | fNCx = fInfo->fSPDScaleX[scale]; | |
177 | fNz = Int_t(fInfo->fSegSPD->Npz()/fNCz); | |
178 | fNx = Int_t(fInfo->fSegSPD->Npx()/fNCx); | |
51346b82 | 179 | dpz = 2*fDz/fNz; |
3b868b75 | 180 | dpx = 2*fDx/fNx; |
181 | //printf("SPD orig cells (%d, %d) (%d, %d)\n", fInfo->fSegSPD->Npx(), fInfo->fSegSPD->Npz(), Nx, Nz); | |
182 | ||
183 | AliITSdigitSPD *od ; | |
184 | for (Int_t k=0; k<ndigits; ++k) | |
185 | { | |
186 | od = (AliITSdigitSPD*) digits->UncheckedAt(k); | |
187 | ||
188 | fInfo->GetSPDLocalZ(od->GetCoord1(),zo); | |
189 | c1 = od->GetCoord1(); c2 = od->GetCoord2(); | |
9af86b69 | 190 | i = Int_t((zo+fDz)/dpz); |
191 | j = Int_t((od->GetCoord2()*fNx)/fInfo->fSegSPD->Npx()); | |
3b868b75 | 192 | id = j*fNx + i; |
51346b82 | 193 | |
9af86b69 | 194 | ScaledDigit_t* sd = 0; |
3b868b75 | 195 | miter = dmap.find(id); |
196 | if(miter == dmap.end()) | |
51346b82 | 197 | { |
3b868b75 | 198 | dmap[id] = fPlex.Size(); |
199 | z = dpz*(i) - fDz; | |
200 | x = dpx*(j) - fDx; | |
201 | AddQuad(x, z, dpx, dpz); | |
a15e6d7d | 202 | sd = new ScaledDigit_t(c1, c2); |
3b868b75 | 203 | QuadId(sd); |
204 | } | |
51346b82 | 205 | else |
3b868b75 | 206 | { |
a15e6d7d | 207 | sd = dynamic_cast<ScaledDigit_t*>(GetId(miter->second)); |
208 | if(c1 < sd->fMinI) | |
209 | sd->fMinI = c1; | |
210 | else if( c1 > sd->fMaxI) | |
211 | sd->fMaxI = c1; | |
212 | ||
213 | if(c2 < sd->fMinJ) | |
214 | sd->fMinJ = c2; | |
215 | else if( c2 > sd->fMaxJ) | |
216 | sd->fMaxJ = c2; | |
3b868b75 | 217 | } |
51346b82 | 218 | |
a15e6d7d | 219 | sd->fN++; |
220 | sd->fSum += od->GetSignal(); | |
221 | sd->fSqrSum += od->GetSignal()*od->GetSignal(); | |
3b868b75 | 222 | } |
223 | break; | |
224 | } | |
51346b82 | 225 | case 1: |
226 | { | |
3b868b75 | 227 | // SDD |
84aff7a4 | 228 | Reset(kQT_RectangleXZFixedY, kFALSE, 32); |
3b868b75 | 229 | |
230 | fNCz = fInfo->fSDDScaleZ[scale]; | |
51346b82 | 231 | fNCx = fInfo->fSDDScaleX[scale]; |
3b868b75 | 232 | fNz = Int_t(fInfo->fSegSDD->Npz()/fNCz); |
233 | fNx = Int_t(fInfo->fSegSDD->Npx()/fNCx); | |
9af86b69 | 234 | dpz = 2*fDz/fNz; |
235 | dpx = 2*fDx/fNx; | |
3b868b75 | 236 | |
9af86b69 | 237 | AliITSdigitSDD *od = 0; |
238 | for (Int_t k = 0; k < ndigits; ++k) | |
239 | { | |
240 | od = (AliITSdigitSDD*)digits->UncheckedAt(k); | |
3b868b75 | 241 | fInfo->fSegSDD->DetToLocal(od->GetCoord2(), od->GetCoord1(),x,z); |
9af86b69 | 242 | z += fDz; |
243 | x += fDx; | |
244 | i = Int_t(z/dpz); | |
245 | j = Int_t(x/dpx); | |
3b868b75 | 246 | //printf("Mod %d coord %d,%d out of %d,%d :: ORIG coord %d,%d out of %d,%d \n",fID, |
247 | // i,j,Nz,Nx,od->GetCoord1(),od->GetCoord2(),fInfo->fSegSDD->Npz(),fInfo->fSegSDD->Npx()); | |
248 | ||
249 | id = j*fNx + i; | |
250 | c1 = od->GetCoord1(); c2 = od->GetCoord2(); | |
51346b82 | 251 | |
9af86b69 | 252 | ScaledDigit_t* sd = 0; |
3b868b75 | 253 | miter = dmap.find(id); |
254 | if(miter == dmap.end()) | |
51346b82 | 255 | { |
3b868b75 | 256 | dmap[id] = fPlex.Size(); |
257 | z = dpz*(i) - fDz; | |
258 | x = dpx*(j) - fDx; | |
259 | AddQuad(x, z, dpx, dpz); | |
a15e6d7d | 260 | sd = new ScaledDigit_t(od->GetCoord1(),od->GetCoord2()); |
3b868b75 | 261 | QuadId(sd); |
262 | } | |
51346b82 | 263 | else |
3b868b75 | 264 | { |
a15e6d7d | 265 | sd = dynamic_cast<ScaledDigit_t*>(GetId(miter->second)); |
266 | if(c1 < sd->fMinI) | |
267 | sd->fMinI = c1; | |
268 | else if( c1 > sd->fMaxI) | |
269 | sd->fMaxI = c1; | |
270 | ||
271 | if(c2 < sd->fMinJ) | |
272 | sd->fMinJ = c2; | |
273 | else if( c2 > sd->fMaxJ) | |
274 | sd->fMaxJ = c2; | |
3b868b75 | 275 | } |
a15e6d7d | 276 | sd->fN++; |
277 | sd->fSum += od->GetSignal(); | |
278 | sd->fSqrSum += od->GetSignal()*od->GetSignal(); | |
3b868b75 | 279 | } |
280 | break; | |
51346b82 | 281 | } |
282 | case 2: | |
283 | { | |
284 | // SSD | |
84aff7a4 | 285 | Reset(kQT_LineXZFixedY, kFALSE, 32); |
3b868b75 | 286 | |
51346b82 | 287 | AliITSsegmentationSSD* seg = fInfo->fSegSSD; |
3b868b75 | 288 | Float_t ap, an; // positive/negative angles -> offsets |
289 | seg->Angles(ap, an); | |
290 | ap = TMath::Tan(ap) * fDz; | |
291 | an = - TMath::Tan(an) * fDz; | |
292 | ||
51346b82 | 293 | fNCx = fInfo->fSSDScale[scale]; |
3b868b75 | 294 | fNz = 1; |
295 | fNx = Int_t(fInfo->fSegSSD->Npx()/fNCx); | |
296 | dpz = 2*fDz/fNz; | |
297 | dpx = 2*fDx/fNx; | |
298 | ||
9af86b69 | 299 | AliITSdigitSSD *od = 0; |
3b868b75 | 300 | for (Int_t k=0; k<ndigits; k++) { |
301 | od=(AliITSdigitSSD*)digits->UncheckedAt(k); | |
51346b82 | 302 | if(od->GetCoord1() == 1) |
3b868b75 | 303 | i = 1; // p side |
51346b82 | 304 | else |
3b868b75 | 305 | i= -1; // n side |
306 | j = Int_t(od->GetCoord2()/fNCx); | |
307 | c1 = od->GetCoord1(); c2 = od->GetCoord2(); | |
51346b82 | 308 | id = j*i; |
3b868b75 | 309 | |
9af86b69 | 310 | ScaledDigit_t* sd = 0; |
3b868b75 | 311 | miter = dmap.find(id); |
3b868b75 | 312 | if(miter == dmap.end()) |
51346b82 | 313 | { |
3b868b75 | 314 | // printf("orig digit %d,%d scaled %d,%d \n",od->GetCoord1(),od->GetCoord2(),i,j); |
315 | dmap[id] = fPlex.Size(); | |
316 | z = dpz*(i) - fDz; | |
317 | x = dpx*(j) - fDx; | |
318 | Float_t a = ( od->GetCoord1() == 1) ? ap : an; | |
319 | AddLine(x-a, -fDz, 2*a, 2*fDz); | |
320 | ||
a15e6d7d | 321 | sd = new ScaledDigit_t(c1, c2); |
3b868b75 | 322 | QuadId(sd); |
323 | } | |
51346b82 | 324 | else |
3b868b75 | 325 | { |
a15e6d7d | 326 | sd = dynamic_cast<ScaledDigit_t*>(GetId(miter->second)); |
327 | if(c1 < sd->fMinI) | |
328 | sd->fMinI = c1; | |
329 | else if( c1 > sd->fMaxI) | |
330 | sd->fMaxI = c1; | |
331 | ||
332 | if(c2 < sd->fMinJ) | |
333 | sd->fMinJ = c2; | |
334 | else if( c2 > sd->fMaxJ) | |
335 | sd->fMaxJ = c2; | |
3b868b75 | 336 | } |
a15e6d7d | 337 | sd->fN++; |
338 | sd->fSum += od->GetSignal(); | |
339 | sd->fSqrSum += od->GetSignal()*od->GetSignal(); | |
3b868b75 | 340 | } // for digits |
341 | break; | |
342 | } // end case 2 | |
343 | } // end switch | |
344 | ||
345 | SetQuadValues(); | |
346 | RefitPlex(); | |
347 | } | |
348 | ||
57ffa5fb | 349 | /******************************************************************************/ |
3b868b75 | 350 | |
d810d0de | 351 | void AliEveITSScaledModule::SetQuadValues() |
3b868b75 | 352 | { |
32e219c2 | 353 | if(fScaleInfo->GetSyncPalette()) SyncPalette(); |
354 | ||
a15e6d7d | 355 | Int_t num = fPlex.Size(); |
356 | for (Int_t i = 0 ; i < num; i++) | |
3b868b75 | 357 | { |
a15e6d7d | 358 | ScaledDigit_t* sd = dynamic_cast<ScaledDigit_t*>(GetId(i)); |
3b868b75 | 359 | Int_t v = 0; |
32e219c2 | 360 | switch(fScaleInfo->GetStatType()) |
361 | { | |
362 | using namespace TMath; | |
363 | ||
a15e6d7d | 364 | case AliEveDigitScaleInfo::kSTOccup: |
365 | v = Nint((100.0*sd->fN) / (fNCx*fNCz)); | |
32e219c2 | 366 | break; |
a15e6d7d | 367 | case AliEveDigitScaleInfo::kSTAverage: |
368 | v = Nint((Double_t) sd->fSum / sd->fN); | |
32e219c2 | 369 | break; |
a15e6d7d | 370 | case AliEveDigitScaleInfo::kSTRms: |
371 | v = Nint(Sqrt(sd->fSqrSum) / sd->fN); | |
32e219c2 | 372 | break; |
3b868b75 | 373 | } |
84aff7a4 | 374 | DigitBase_t* qb = GetDigit(i); |
3b868b75 | 375 | qb->fValue = v; |
376 | } | |
377 | } | |
378 | ||
57ffa5fb | 379 | /******************************************************************************/ |
3b868b75 | 380 | |
d810d0de | 381 | void AliEveITSScaledModule::SyncPalette() |
51346b82 | 382 | { |
d810d0de | 383 | // printf("AliEveITSScaledModule::SyncPalette()\n"); |
a15e6d7d | 384 | if(fScaleInfo->GetStatType() == AliEveDigitScaleInfo::kSTOccup) |
32e219c2 | 385 | { |
386 | // SPD | |
d810d0de | 387 | AliEveITSModule::fgSPDPalette->SetLimits(0, 100); |
388 | AliEveITSModule::fgSPDPalette->SetMinMax(0, 100); | |
51346b82 | 389 | |
32e219c2 | 390 | // SDD |
d810d0de | 391 | AliEveITSModule::fgSDDPalette->SetLimits(0, 100); |
392 | AliEveITSModule::fgSDDPalette->SetMinMax(0, 100); | |
32e219c2 | 393 | |
394 | // SSD | |
d810d0de | 395 | AliEveITSModule::fgSSDPalette->SetLimits(0, 100); |
396 | AliEveITSModule::fgSDDPalette->SetMinMax(0, 100); | |
32e219c2 | 397 | } |
398 | else | |
399 | { | |
a15e6d7d | 400 | AliEveITSDigitsInfo& di = *fInfo; |
32e219c2 | 401 | // SPD |
a15e6d7d | 402 | AliEveITSModule::fgSPDPalette->SetLimits(0, di.fSPDHighLim); |
403 | AliEveITSModule::fgSPDPalette->SetMinMax(di.fSPDMinVal, di.fSPDMaxVal); | |
51346b82 | 404 | |
32e219c2 | 405 | // SDD |
a15e6d7d | 406 | AliEveITSModule::fgSDDPalette->SetLimits(0, di.fSDDHighLim); |
407 | AliEveITSModule::fgSDDPalette->SetMinMax(di.fSDDMinVal, di.fSDDMaxVal); | |
32e219c2 | 408 | |
409 | // SSD | |
a15e6d7d | 410 | AliEveITSModule::fgSSDPalette->SetLimits(0, di.fSSDHighLim); |
411 | AliEveITSModule::fgSSDPalette->SetMinMax(di.fSSDMinVal, di.fSSDMaxVal); | |
32e219c2 | 412 | } |
413 | ||
414 | fScaleInfo->SetSyncPalette(kFALSE); | |
415 | } | |
416 | ||
57ffa5fb | 417 | /******************************************************************************/ |
32e219c2 | 418 | |
a15e6d7d | 419 | void AliEveITSScaledModule::GetScaleData(Int_t& cnx, Int_t& cnz, Int_t& total) const |
32e219c2 | 420 | { |
a15e6d7d | 421 | cnx = fNx; |
422 | cnz = fNz; | |
32e219c2 | 423 | total = cnx*cnz; |
424 | } | |
425 | ||
57ffa5fb | 426 | /******************************************************************************/ |
32e219c2 | 427 | |
d810d0de | 428 | void AliEveITSScaledModule::DigitSelected(Int_t idx) |
3b868b75 | 429 | { |
84aff7a4 | 430 | // Override control-click from TEveQuadSet |
d810d0de | 431 | printf("AliEveITSScaledModule::DigitSelected "); Print(); |
3b868b75 | 432 | |
d794819f | 433 | // DigitBase_t *qb = GetDigit(idx); |
434 | TObject *obj = GetId(idx); | |
435 | ScaledDigit_t *sd = dynamic_cast<ScaledDigit_t*>(obj); | |
3b868b75 | 436 | TClonesArray *digits = fInfo->GetDigits(fID, fDetID); |
437 | Int_t ndigits = digits->GetEntriesFast(); | |
438 | ||
a15e6d7d | 439 | printf("%d digits in cell scaleX = %d, scaleZ = %d \n", sd->fN, fNCx, fNCz); |
3b868b75 | 440 | |
441 | Int_t il = 0; | |
51346b82 | 442 | for(Int_t k=0; k<ndigits; k++) |
3b868b75 | 443 | { |
444 | AliITSdigit *d = (AliITSdigit*) digits->UncheckedAt(k); | |
445 | ||
a15e6d7d | 446 | if(d->GetCoord1()>=sd->fMinI && d->GetCoord1()<=sd->fMaxI && |
447 | d->GetCoord2()>=sd->fMinJ && d->GetCoord2()<=sd->fMaxJ) | |
3b868b75 | 448 | { |
449 | printf("%3d, %3d: %3d", d->GetCoord1(), d->GetCoord2(), d->GetSignal()); | |
450 | printf(" | "); | |
451 | il++; | |
452 | if(il>5) { | |
453 | printf("\n"); | |
454 | il = 0; | |
455 | } | |
456 | } | |
457 | } | |
458 | if(il) printf("\n"); | |
459 | } |