Line data Source code
1 : #include "AliTPCExB.h"
2 : #include "TMath.h"
3 : //#include "TTreeStream.h"
4 : #include "AliMagF.h"
5 : #include "TLinearFitter.h"
6 : #include "AliTPCcalibDB.h"
7 :
8 :
9 : /// \class AliTPCExB
10 : /// \brief Abstract class for ExB effect parameterization
11 : ///
12 : /// The ExB correction map is stored in the calib DB
13 : /// The lookup can be dumped to the tree:
14 : ///
15 : /// ~~~{.cxx}
16 : /// char *storage = "local://OCDBres"
17 : /// Int_t RunNumber=0;
18 : /// AliCDBManager::Instance()->SetDefaultStorage(storage);
19 : /// AliCDBManager::Instance()->SetRun(RunNumber)
20 : /// AliTPCExBFirst * exb = AliTPCcalibDB::Instance()->GetExB();
21 : ///
22 : /// // See example macro $ALICE_ROOT/TPC/macros/AliTPCExBdraw.C
23 : ///
24 : /// .L $ALICE_ROOT/TPC/macros/AliTPCExBdraw.C
25 : /// Draw(0)
26 : /// ~~~
27 :
28 : AliTPCExB* AliTPCExB::fgInstance = 0;
29 :
30 24 : TObjArray AliTPCExB::fgArray;
31 :
32 :
33 :
34 : /// \cond CLASSIMP
35 24 : ClassImp(AliTPCExB)
36 : /// \endcond
37 :
38 : AliTPCExB::AliTPCExB():
39 3 : TObject(),
40 3 : fMatBrBz(0), //param matrix Br/Bz
41 3 : fMatBrfiBz(0), //param matrix Br/Bz
42 3 : fMatBrBzI0(0), //param matrix Br/Bz integral z>0
43 3 : fMatBrBzI1(0), //param matrix Br/Bz integral z<0
44 3 : fMatBrfiBzI0(0), //param matrix Br/Bz integral z>0
45 3 : fMatBrfiBzI1(0) //param matrix Br/Bz integral z<0
46 9 : {
47 : //
48 : // default constructor
49 : //
50 3 : }
51 :
52 : AliTPCExB::AliTPCExB(const AliTPCExB& exb):
53 0 : TObject(exb),
54 0 : fMatBrBz(new TVectorD(*(exb.fMatBrBz))), //param matrix Br/Bz
55 0 : fMatBrfiBz(new TVectorD(*(exb.fMatBrfiBz))), //param matrix Br/Bz
56 0 : fMatBrBzI0(new TVectorD(*(exb.fMatBrBzI0))), //param matrix Br/Bz integral z>0
57 0 : fMatBrBzI1(new TVectorD(*(exb.fMatBrBzI1))), //param matrix Br/Bz integral z<0
58 0 : fMatBrfiBzI0(new TVectorD(*(exb.fMatBrfiBzI0))), //param matrix Br/Bz integral z>0
59 0 : fMatBrfiBzI1(new TVectorD(*(exb.fMatBrfiBzI1))) //param matrix Br/Bz integral z<0
60 0 : {
61 : /// copy constructor
62 :
63 0 : }
64 :
65 : AliTPCExB& AliTPCExB::operator=(const AliTPCExB &/*exb*/)
66 : {
67 : /// Dummy assignment
68 :
69 0 : return *this;
70 : }
71 :
72 :
73 :
74 :
75 : void AliTPCExB::TestExB(const char* fileName) {
76 : /// Test ExB -
77 : /// Dump the filed and corrections to the tree in file fileName
78 :
79 0 : TTreeSRedirector ts(fileName);
80 0 : Double_t x[3];
81 0 : for (x[0]=-250.;x[0]<=250.;x[0]+=10.)
82 0 : for (x[1]=-250.;x[1]<=250.;x[1]+=10.)
83 0 : for (x[2]=-250.;x[2]<=250.;x[2]+=20.) {
84 0 : Double_t r=TMath::Sqrt(x[0]*x[0]+x[1]*x[1]);
85 0 : if (r<20) continue;
86 0 : if (r>260) continue;
87 0 : Double_t z = x[2];
88 0 : Double_t d[3];
89 0 : Correct(x,d);
90 0 : Double_t rd=TMath::Sqrt(d[0]*d[0]+d[1]*d[1]);
91 0 : Double_t dr=r-rd;
92 0 : Double_t phi=TMath::ATan2(x[1],x[0]);
93 0 : Double_t phid=TMath::ATan2(d[1],d[0]);
94 0 : Double_t dphi=phi-phid;
95 0 : if (dphi<0.) dphi+=TMath::TwoPi();
96 0 : if (dphi>TMath::Pi()) dphi=TMath::TwoPi()-dphi;
97 0 : Double_t drphi=r*dphi;
98 0 : Double_t dx=x[0]-d[0];
99 0 : Double_t dy=x[1]-d[1];
100 0 : Double_t dz=x[2]-d[2];
101 : //
102 0 : Double_t bx = GetBx(r,phi,z,0);
103 0 : Double_t by = GetBy(r,phi,z,0);
104 0 : Double_t bz = GetBz(r,phi,z,0);
105 0 : Double_t br = GetBr(r,phi,z,0);
106 0 : Double_t brfi = GetBrfi(r,phi,z,0);
107 : //
108 0 : Double_t bxi = GetBxI(r,phi,z,0);
109 0 : Double_t byi = GetByI(r,phi,z,0);
110 0 : Double_t bzi = GetBzI(r,phi,z,0);
111 0 : Double_t bri = GetBrI(r,phi,z,0);
112 0 : Double_t brfii = GetBrfiI(r,phi,z,0);
113 :
114 0 : ts<<"positions"<<
115 0 : "x0="<<x[0]<<
116 0 : "x1="<<x[1]<<
117 0 : "x2="<<x[2]<<
118 0 : "dx="<<dx<<
119 0 : "dy="<<dy<<
120 0 : "dz="<<dz<<
121 0 : "r="<<r<<
122 0 : "phi="<<phi<<
123 0 : "dr="<<dr<<
124 0 : "drphi="<<drphi<<
125 : //
126 : // B-Field
127 : //
128 0 : "bx="<<bx<<
129 0 : "by="<<by<<
130 0 : "bz="<<bz<<
131 0 : "br="<< br<<
132 0 : "brfi="<<brfi<<
133 : // B-field integ
134 0 : "bxi="<<bxi<<
135 0 : "byi="<<byi<<
136 0 : "bzi="<<bzi<<
137 0 : "bri="<< bri<<
138 0 : "brfii="<<brfii<<
139 : "\n";
140 0 : }
141 0 : }
142 :
143 :
144 :
145 : Double_t AliTPCExB::GetDr(Double_t r, Double_t phi, Double_t z, Double_t bz){
146 : /// Static function
147 : /// Posibble to us it for visualization
148 :
149 0 : AliTPCExB *exb = Instance();
150 0 : if (!exb) exb = AliTPCcalibDB::GetExB(bz,kFALSE);
151 0 : if (!exb) return 0;
152 0 : Double_t pos0[3] = {r*TMath::Cos(phi), r*TMath::Sin(phi),z};
153 0 : Double_t pos1[3];
154 0 : exb->Correct(pos0,pos1);
155 0 : Double_t dx=pos1[0]-pos0[0];
156 0 : Double_t dy=pos1[1]-pos0[1];
157 : // Double_t dz=pos1[2]-pos0[2];
158 : // return TMath::Sqrt(dx*dx+dy*dy);
159 0 : Float_t dr = (dx*pos0[0]+dy*pos0[1])/r;
160 0 : return dr;
161 0 : }
162 :
163 :
164 : Double_t AliTPCExB::GetDrphi(Double_t r, Double_t phi, Double_t z, Double_t bz){
165 : ///
166 :
167 0 : AliTPCExB *exb = Instance();
168 0 : if (!exb) exb = AliTPCcalibDB::GetExB(bz,kFALSE);
169 0 : if (!exb) return 0;
170 0 : Double_t pos0[3] = {r*TMath::Cos(phi), r*TMath::Sin(phi),z};
171 0 : Double_t pos1[3];
172 0 : exb->Correct(pos0,pos1);
173 0 : Double_t dphi=TMath::ATan2(pos1[1],pos1[0])-TMath::ATan2(pos0[1],pos0[0]);
174 0 : if (dphi>TMath::Pi()) dphi-=TMath::TwoPi();
175 0 : if (dphi<-TMath::Pi()) dphi+=TMath::TwoPi();
176 0 : return r*dphi;
177 :
178 0 : }
179 :
180 :
181 : Double_t AliTPCExB::GetDphi(Double_t r, Double_t phi, Double_t z, Double_t bz){
182 : ///
183 :
184 0 : AliTPCExB *exb = Instance();
185 0 : if (!exb) exb = AliTPCcalibDB::GetExB(bz,kFALSE);
186 0 : if (!exb) return 0;
187 0 : Double_t pos0[3] = {r*TMath::Cos(phi), r*TMath::Sin(phi),z};
188 0 : Double_t pos1[3];
189 0 : exb->Correct(pos0,pos1);
190 0 : Double_t dphi=TMath::ATan2(pos1[1],pos1[0])-TMath::ATan2(pos0[1],pos0[0]);
191 : return dphi;
192 :
193 0 : }
194 :
195 : Double_t AliTPCExB::GetDz(Double_t r, Double_t phi, Double_t z, Double_t bz){
196 : ///
197 :
198 0 : AliTPCExB *exb = Instance();
199 0 : if (!exb) exb = AliTPCcalibDB::GetExB(bz,kFALSE);
200 0 : if (!exb) return 0;
201 0 : Double_t pos0[3] = {r*TMath::Cos(phi), r*TMath::Sin(phi),z};
202 0 : Double_t pos1[3];
203 0 : exb->Correct(pos0,pos1);
204 0 : Double_t dz=pos1[2]-pos0[2];
205 : return dz;
206 0 : }
207 :
208 : //
209 : // Magnetic field
210 : //
211 :
212 :
213 :
214 :
215 : void AliTPCExB::RegisterField(Int_t index, AliMagF * magf){
216 : /// add the filed to the list
217 :
218 0 : fgArray.AddAt(magf,index);
219 0 : }
220 :
221 :
222 :
223 : Double_t AliTPCExB::GetBx(Double_t r, Double_t phi, Double_t z,Int_t index){
224 : ///
225 :
226 0 : AliMagF *mag = (AliMagF*)fgArray.At(index);
227 0 : if (!mag) return 0;
228 0 : Double_t xyz[3]={r*TMath::Cos(phi),r*TMath::Sin(phi),z};
229 : // xyz[1]+=30;
230 0 : Double_t bxyz[3];
231 0 : mag->Field(xyz,bxyz);
232 0 : return bxyz[0];
233 0 : }
234 :
235 : Double_t AliTPCExB::GetBy(Double_t r, Double_t phi, Double_t z,Int_t index){
236 : ///
237 :
238 0 : AliMagF *mag = (AliMagF*)fgArray.At(index);
239 0 : if (!mag) return 0;
240 0 : Double_t xyz[3]={r*TMath::Cos(phi),r*TMath::Sin(phi),z};
241 : // xyz[1]+=30;
242 0 : Double_t bxyz[3];
243 0 : mag->Field(xyz,bxyz);
244 0 : return bxyz[1];
245 0 : }
246 :
247 : Double_t AliTPCExB::GetBz(Double_t r, Double_t phi, Double_t z,Int_t index){
248 : ///
249 :
250 0 : AliMagF *mag = (AliMagF*)fgArray.At(index);
251 0 : if (!mag) return 0;
252 0 : Double_t xyz[3]={r*TMath::Cos(phi),r*TMath::Sin(phi),z};
253 : // xyz[1]+=30;
254 0 : Double_t bxyz[3];
255 0 : mag->Field(xyz,bxyz);
256 0 : return bxyz[2];
257 0 : }
258 :
259 :
260 :
261 : Double_t AliTPCExB::GetBr(Double_t r, Double_t phi, Double_t z,Int_t index){
262 : ///
263 :
264 0 : AliMagF *mag = (AliMagF*)fgArray.At(index);
265 0 : if (!mag) return 0;
266 0 : Double_t xyz[3]={r*TMath::Cos(phi),r*TMath::Sin(phi),z};
267 : //xyz[1]+=30;
268 0 : Double_t bxyz[3];
269 0 : mag->Field(xyz,bxyz);
270 0 : if (r==0) return 0;
271 0 : Double_t br = (bxyz[0]*xyz[0]+bxyz[1]*xyz[1])/r;
272 : return br;
273 0 : }
274 :
275 : Double_t AliTPCExB::GetBrfi(Double_t r, Double_t phi, Double_t z,Int_t index){
276 : ///
277 :
278 0 : AliMagF *mag = (AliMagF*)fgArray.At(index);
279 0 : if (!mag) return 0;
280 0 : Double_t xyz[3]={r*TMath::Cos(phi),r*TMath::Sin(phi),z};
281 : //xyz[1]+=30;
282 0 : Double_t bxyz[3];
283 0 : mag->Field(xyz,bxyz);
284 0 : if (r==0) return 0;
285 0 : Double_t br = (-bxyz[0]*xyz[1]+bxyz[1]*xyz[0])/r;
286 : return br;
287 0 : }
288 :
289 :
290 :
291 :
292 : Double_t AliTPCExB::GetBxI(Double_t r, Double_t phi, Double_t z,Int_t index)
293 : {
294 : Double_t sumf =0;
295 0 : if (z>0 &&z<250){
296 0 : for (Float_t zi=z;zi<250;zi+=5){
297 0 : sumf+=GetBx(r,phi,zi,index)/GetBz(r,phi,zi,index);
298 : }
299 0 : }
300 0 : if (z<0 &&z>-250){
301 0 : for (Float_t zi=z;zi>-250;zi-=5){
302 0 : sumf+=GetBx(r,phi,zi,index)/GetBz(r,phi,zi,index);
303 : }
304 0 : }
305 0 : return sumf*5;
306 : }
307 :
308 : Double_t AliTPCExB::GetByI(Double_t r, Double_t phi, Double_t z,Int_t index)
309 : {
310 : Double_t sumf =0;
311 0 : if (z>0 &&z<250){
312 0 : for (Float_t zi=z;zi<250;zi+=5){
313 0 : sumf+=GetBy(r,phi,zi,index)/GetBz(r,phi,zi,index);
314 : }
315 0 : }
316 0 : if (z<0 &&z>-250){
317 0 : for (Float_t zi=z;zi>-250;zi-=5){
318 0 : sumf+=GetBy(r,phi,zi,index)/GetBz(r,phi,zi,index);
319 : }
320 0 : }
321 0 : return sumf*5;
322 : }
323 :
324 : Double_t AliTPCExB::GetBzI(Double_t r, Double_t phi, Double_t z,Int_t index)
325 : {
326 : Double_t sumf =0;
327 0 : if (z>0 &&z<250){
328 0 : for (Float_t zi=z;zi<250;zi+=5){
329 0 : sumf+=GetBz(r,phi,zi,index);
330 : }
331 0 : }
332 0 : if (z<0 &&z>-250){
333 0 : for (Float_t zi=z;zi>-250;zi-=5){
334 0 : sumf+=GetBz(r,phi,zi,index);
335 : }
336 0 : }
337 0 : return sumf*5;
338 : }
339 :
340 :
341 : Double_t AliTPCExB::GetBrI(Double_t r, Double_t phi, Double_t z,Int_t index)
342 : {
343 : Double_t sumf =0;
344 0 : if (z>0 &&z<250){
345 0 : for (Float_t zi=z;zi<250;zi+=5){
346 0 : sumf+=GetBr(r,phi,zi,index)/GetBz(r,phi,zi,index);
347 : }
348 0 : }
349 0 : if (z<0 &&z>-250){
350 0 : for (Float_t zi=z;zi>-250;zi-=5){
351 0 : sumf+=GetBr(r,phi,zi,index)/GetBz(r,phi,zi,index);
352 : }
353 0 : }
354 0 : return sumf*5;
355 : }
356 :
357 : Double_t AliTPCExB::GetBrfiI(Double_t r, Double_t phi, Double_t z,Int_t index)
358 : {
359 : Double_t sumf =0;
360 0 : if (z>0 &&z<250){
361 0 : for (Float_t zi=z;zi<250;zi+=5.){
362 0 : sumf+=GetBrfi(r,phi,zi,index)/GetBz(r,phi,zi,index);
363 : }
364 0 : }
365 0 : if (z<0 &&z>-250){
366 0 : for (Float_t zi=z;zi>-250;zi-=5){
367 0 : sumf+=GetBrfi(r,phi,zi,index)/GetBz(r,phi,zi,index);
368 : }
369 0 : }
370 0 : return sumf*5;
371 : }
372 :
373 :
374 : Double_t AliTPCExB::Eval(Int_t type, Double_t r, Double_t phi, Double_t z){
375 : /// Evaluate parameterization
376 : ///
377 : /// br integral param
378 :
379 0 : if (type==0) {
380 0 : if (z>0 && fMatBrBzI0) return EvalMat(*fMatBrBzI0,r,phi,z);
381 0 : if (z<0 && fMatBrBzI1) return EvalMat(*fMatBrBzI1,r,phi,z);
382 : }
383 : // brfi integral param
384 0 : if (type==1) {
385 0 : if (z>0 && fMatBrfiBzI0) return EvalMat(*fMatBrfiBzI0,r,phi,z);
386 0 : if (z<0 && fMatBrfiBzI1) return EvalMat(*fMatBrfiBzI1,r,phi,z);
387 : }
388 : // brbz param
389 0 : if (type==2 && fMatBrBz) return EvalMat(*fMatBrBz,r,phi,z);
390 : // brfibz param
391 0 : if (type==3 && fMatBrfiBz) return EvalMat(*fMatBrfiBz,r,phi,z);
392 0 : return 0;
393 0 : }
394 :
395 :
396 : Double_t AliTPCExB::EvalMat(const TVectorD &vec, Double_t r, Double_t phi, Double_t z){
397 : /// Evaluate taylor expansion in r,phi,z
398 : ///
399 : /// Variables:
400 : /// ~~~
401 : /// tree->SetAlias("sa","sin(phi+0.0)");
402 : /// tree->SetAlias("ca","cos(phi+0.0)");
403 : /// tree->SetAlias("sa2","sin(phi*2+0.0)");
404 : /// tree->SetAlias("ca2","cos(phi*2+0.0)");
405 : /// tree->SetAlias("zn","(x2/250.)");
406 : /// tree->SetAlias("rn","(r/250.)")
407 : /// TString fstringSym="";
408 : ///
409 : /// fstringSym+="zn++";
410 : /// fstringSym+="rn++";
411 : /// fstringSym+="zn*rn++";
412 : /// fstringSym+="zn*zn++";
413 : /// fstringSym+="zn*zn*rn++";
414 : /// fstringSym+="zn*rn*rn++";
415 : ///
416 : /// fstringSym+="sa++";
417 : /// fstringSym+="ca++";
418 : /// fstringSym+="ca2++";
419 : /// fstringSym+="sa2++";
420 : /// fstringSym+="ca*zn++";
421 : /// fstringSym+="sa*zn++";
422 : /// fstringSym+="ca2*zn++";
423 : /// fstringSym+="sa2*zn++";
424 : /// fstringSym+="ca*zn*zn++";
425 : /// fstringSym+="sa*zn*zn++";
426 : /// fstringSym+="ca*zn*rn++";
427 : /// fstringSym+="sa*zn*rn++";
428 : /// ~~~
429 :
430 0 : Double_t sa = TMath::Sin(phi);
431 0 : Double_t ca = TMath::Cos(phi);
432 0 : Double_t sa2 = TMath::Sin(phi*2);
433 0 : Double_t ca2 = TMath::Cos(phi*2);
434 0 : Double_t zn = z/250.;
435 0 : Double_t rn = r/250.;
436 : Int_t ipoint=0;
437 0 : Double_t res = vec[ipoint++];
438 0 : res+=vec[ipoint++]*zn;
439 0 : res+=vec[ipoint++]*rn;
440 0 : res+=vec[ipoint++]*zn*rn;
441 0 : res+=vec[ipoint++]*zn*zn;
442 0 : res+=vec[ipoint++]*zn*zn*rn;
443 0 : res+=vec[ipoint++]*zn*rn*rn;
444 : //
445 0 : res+=vec[ipoint++]*sa;
446 0 : res+=vec[ipoint++]*ca;
447 0 : res+=vec[ipoint++]*ca2;
448 0 : res+=vec[ipoint++]*sa2;
449 0 : res+=vec[ipoint++]*ca*zn;
450 0 : res+=vec[ipoint++]*sa*zn;
451 0 : res+=vec[ipoint++]*ca2*zn;
452 0 : res+=vec[ipoint++]*sa2*zn;
453 0 : res+=vec[ipoint++]*ca*zn*zn;
454 0 : res+=vec[ipoint++]*sa*zn*zn;
455 0 : res+=vec[ipoint++]*ca*zn*rn;
456 0 : res+=vec[ipoint++]*sa*zn*rn;
457 0 : return res;
458 : }
459 :
460 :
461 :
462 :
463 :
464 :
465 :
466 :
467 :
468 :
469 :
470 :
471 :
472 :
473 : /*
474 :
475 : AliTPCExB draw;
476 : draw.RegisterField(0,new AliMagWrapCheb("Maps","Maps", 2, 1., 10., AliMagWrapCheb::k5kG));
477 : draw.RegisterField(1,new AliMagFMaps("Maps","Maps", 2, 1., 10., 2));
478 :
479 : TF2 fbz_rz_0pi("fbz_rz_0pi","AliTPCExB::GetBz(x,0*pi,y)",0,250,-250,250);
480 : fbz_rz_0pi->Draw("surf2");
481 :
482 : TF1 fbz_z_90_00pi("fbz_z_90_00pi","AliTPCExB::GetBz(90,0*pi,x)",-250,250);
483 : TF1 fbz_z_90_05pi("fbz_z_90_05pi","AliTPCExB::GetBz(90,0.5*pi,x)",-250,250);
484 : TF1 fbz_z_90_10pi("fbz_z_90_10pi","AliTPCExB::GetBz(90,1.0*pi,x)",-250,250);
485 : TF1 fbz_z_90_15pi("fbz_z_90_15pi","AliTPCExB::GetBz(90,1.5*pi,x)",-250,250);
486 : fbz_z_90_00pi->SetLineColor(2);
487 : fbz_z_90_05pi->SetLineColor(3);
488 : fbz_z_90_10pi->SetLineColor(4);
489 : fbz_z_90_15pi->SetLineColor(5);
490 : fbz_z_90_00pi->Draw()
491 : fbz_z_90_05pi->Draw("same")
492 : fbz_z_90_15pi->Draw("same")
493 : fbz_z_90_10pi->Draw("same")
494 :
495 :
496 : TF1 fbr_z_90_00pi("fbz_z_90_00pi","AliTPCExB::GetBr(90,0*pi,x)",-250,250);
497 : TF1 fbr_z_90_05pi("fbz_z_90_05pi","AliTPCExB::GetBr(90,0.5*pi,x)",-250,250);
498 : TF1 fbr_z_90_10pi("fbz_z_90_10pi","AliTPCExB::GetBr(90,1.0*pi,x)",-250,250);
499 : TF1 fbr_z_90_15pi("fbz_z_90_15pi","AliTPCExB::GetBr(90,1.5*pi,x)",-250,250);
500 : fbr_z_90_00pi->SetLineColor(2);
501 : fbr_z_90_05pi->SetLineColor(3);
502 : fbr_z_90_10pi->SetLineColor(4);
503 : fbr_z_90_15pi->SetLineColor(5);
504 : fbr_z_90_00pi->Draw()
505 : fbr_z_90_05pi->Draw("same")
506 : fbr_z_90_15pi->Draw("same")
507 : fbr_z_90_10pi->Draw("same")
508 :
509 : //
510 : TF2 fbz_xy_0z("fbz_xy_0z","AliTPCExB::GetBz(sqrt(x^2+y^2),atan2(y,x),0)",-250,250,-250,250);
511 : fbz_xy_0z.SetNpy(100);
512 : fbz_xy_0z.SetNpx(100);
513 : fbz_xy_0z->Draw("colz");
514 : //
515 : TF2 fbz_xy_250z("fbz_xy_250z","AliTPCExB::GetBz(sqrt(x^2+y^2),atan2(y,x),250)",-250,250,-250,250);
516 : fbz_xy_250z.SetNpy(100);
517 : fbz_xy_250z.SetNpx(100)
518 : fbz_xy_250z->Draw("colz");
519 : //
520 : TF2 fbz_xy_m250z("fbz_xy_m250z","AliTPCExB::GetBz(sqrt(x^2+y^2),atan2(y,x),-250)",-250,250,-250,250);
521 : fbz_xy_m250z.SetNpy(100);
522 : fbz_xy_m250z.SetNpx(100)
523 : fbz_xy_m250z->Draw("colz");
524 : //
525 :
526 :
527 :
528 :
529 :
530 : */
531 :
532 :
|